Skip to content

Lifecycle state machine

Source: packages/core/src/lifecycle/machine.ts · Spec: §4, §5.1

reported → reproducing → diagnosing → fixing → verifying → resolved
└────────── any open state → wontfix | duplicate | cannot-reproduce (reason required)

Gates to enter a state (strict mode, the default):

Into Requires
reproducing report.symptoms
diagnosing reproduction.reliability (+ reproduction.reason when not-reproduced)
fixing diagnosis.rootCause + ≥1 diagnosis.filesImplicated
verifying fix.summary + fix.approach
resolved verification.testsAdded non-empty or verification.noTestReason (logged)
other terminal a stated reason (recorded in resolution + the status event)
  • Backward moves between open states are legal and logged as events.
  • transition() accepts a target ahead of the current state and chains through intermediates when their gates are satisfied, logging every step.
  • allUnmetGates() powers file-complete’s single atomic pass — agents get every unmet gate in one error instead of discovering them serially.
  • checklist() returns the next status’s unmet gates plus recommended high-value fields (category, surface, rootCause, filesImplicated).
  • strictness: "loose" skips content gates but never the terminal-reason rule.
  • file-complete is strict-always (spec §5.1: it validates every gate and “strictness must not soften”) — strictness: "loose" does not apply to the one-shot path. Gate-relevant text must be non-empty after trimming (H-08): empty/whitespace strings and [""] entries satisfy no gate, enforced both in the schema (nonEmptyString) and defensively in the gate checks.