pub fn transition_resets_consecutive_failures(from: Stage, to: Stage) -> boolExpand description
Whether transition() should zero
crate::state::State::consecutive_failures when moving from from to
to.
consecutive_failures is meant to count repeated Code↔Validate CYCLES —
each cycle is a full loop through Code, then Validate, then (on failure)
back to Code again. But the Code→Validate hop is crossed on every
single cycle, including the ones that are about to fail. Resetting the
counter on that specific hop means it can never accumulate past 1, so
MAX_CONSECUTIVE_FAILURES — the ceiling that exists specifically to
bound this loop — is unreachable (18d). Every other transition is
genuine forward progress out of the Code↔Validate loop (or the initial
Define→Plan→Code entry into it) and correctly clears the counter.
This rule deliberately does NOT apply to
crate::state::State::infra_failures, whose unconditional reset in
transition() is correct for its own semantics: infra faults accumulate
within a single stage’s repeated failures and are routed through
handle_infra_outcome → gate_or_abort_infra → handle_stage_failure,
whose retry arms call launch_stage directly and never cross
transition() at all. Widening this predicate’s shape onto
infra_failures would silently convert MAX_INFRA_FAILURES from a
stuck-loop bound into a phase-lifetime bound — the exact regression
17-06 was written to prevent.