pub fn decompose_ci(
caixa: &Caixa,
ci: &CiRun,
) -> Result<CanteiroDag, CiDecomposeFailure>Expand description
Predicate: decompose a borrowed canteiro_types::CiRun into its
typed canteiro_types::CanteiroDag via
canteiro_types::decompose, wrapping any
canteiro_types::DecomposeError in a typed CiDecomposeFailure
view (carrying Caixa::nome) on rejection. The canonical
entry-point every per-Acao consumer wraps in its own
thiserror Error variant via #[from] — the call site becomes
a single let cd = caixa_core::decompose_ci(caixa, ci)?; in place
of the prior inline
let cd = canteiro_types::decompose(ci).map_err(|source| CiDecomposeFailure { nome: caixa.nome().to_string(), source })?;
block.
Takes the borrowed canteiro_types::CiRun as a separate argument
(rather than re-borrowing it through require_ci internally) so
the axis stays single-purpose — the sibling require_ci presence
gate returns the borrowed slot, this predicate consumes it, and the
two together form the substrate-canonical two-line per-Acao prelude
let ci = caixa_core::require_ci(caixa)?; let cd = caixa_core::decompose_ci(caixa, ci)?;
every present + roadmapped per-Acao consumer runs at its
entry-point (matching how the sibling per-Servico entry-gate axes
keep require_kind and require_single_servico as separate
primitives, then compose them into the V0-shape
require_v0_servico_shape helper — the compound require + decompose
helper is a peer-lift for a later commit when a second per-Acao
consumer arrives). The caixa: &Caixa argument is what makes the
diagnostic name the offending caixa.lisp — the borrowed
Caixa::nome accessor projects through the typed-view
constructor unchanged, matching the peer require_ci /
require_kind / require_single_servico typed-view constructors.
Lifted to a single helper so the canteiro_types::decompose
axis — the same axis every per-Acao consumer runs on its declared
:ci slot — lives in exactly one place across every future
per-Acao consumer: a future sui-supercacheci::canteiro::emit_gha
workflow renderer (the deferred caixa-actions next step named in
its own crate docs), a future per-Acao CR materializer’s admission
webhook, a future feira lint sub-diagnostic that offers a
:deps-repair suggestion on the [canteiro_types::DecomposeError::MissingDependency]
arm but not the canteiro_types::DecomposeError::Cycle arm — every
consumer reaches for the same one-liner + #[from] and gets the
diagnostic-naming-the-offending-caixa contract for free.
Same trajectory as require_kind / KindMismatch on the peer
per-renderer kind-gate axis, require_single_servico /
ServicoCountMismatch on the peer per-Servico V0-count-gate
axis, and require_ci / MissingCiSlot on the peer per-Acao
presence-gate axis: one caixa_core::require_*/decompose_ci
helper per typed axis, so the diagnostic shape (named caixa, named
field) is uniform across the substrate, and every consumer’s
Error::From<*> #[from] arm gets the diagnostic-naming-the-
offending-caixa contract for free.
§Errors
Returns CiDecomposeFailure when canteiro_types::decompose
refuses the borrowed :ci run — every failure mode the sibling
canteiro_types::DecomposeError enumerates (a duplicate node
name, a dependency on an undeclared node, a dependency cycle) lands
on this arm. The error carries the caixa’s :nome + the underlying
canteiro_types::DecomposeError verbatim so the diagnostic names
the offending caixa.lisp and a consumer that fans on the specific
arm reaches for err.source directly rather than re-parsing the
Display bytes — same shape every consumer’s
Error::From<CiDecomposeFailure> converts into the consumer’s local
error type.