State machine
Every WU inside an initiative is in exactly one orchestration state at any time. The state is reconciled from durable evidence on every status call — not from what an agent remembers or what a prompt implies.
States
Section titled “States”| State | When it fires | Next safe action |
|---|---|---|
planned | WU exists in the initiative but has no handoff evidence. | Wait for dependencies, then eligible. |
eligible | All dependencies complete, no launch recorded yet. | launch_wu (emit handoff + receipt). |
handoff_emitted | launch.json records a receipt for this WU but no worktree / pickup evidence yet. | wait until pickup or relaunch if it stalls. |
claimed | Claim recorded (delegation pickup or YAML claim) but no execution evidence yet. | wait for execution signal. |
active | Worktree present, YAML is in_progress, or delegation registered a pickup. | wait — work is in flight. |
worker_returned | A subagent-stop checkpoint or delegation-completed event fired but the WU is not done yet. | wait and inspect before advancing. |
ready_for_finish | worker_returned and the worktree is still present. | finish_wu (run wu:prep + wu:done). |
awaiting_merge | Branch-PR mode: worker returned, no worktree, no stamp, PR outstanding. | wait for PR merge + wu:cleanup. |
blocked | YAML status is blocked or a blocker signal was received. | wait for blocker resolution. |
contaminated | Delegated WU’s code_paths overlap with uncommitted changes in the main checkout. | recover_wu before advancing anything else in the wave. |
stalled | Worktree is present but there has been no checkpoint / signal / claim activity for longer than the configured stall threshold (default 4 h). | recover_wu — investigate before relaunching. |
needs_relaunch | Worker returned but the worktree is gone and restore is not applicable or not possible. | relaunch_wu. |
stale-but-reconciled | Delegation row looks stale, but WU YAML, done stamp, execution evidence, or signals show the WU is settled. | Terminal for that stale row; no relaunch. |
conflicting-evidence | Delegation, WU, worktree, branch, stamp, or signal evidence disagree in a way that cannot be auto-classified. | recover_wu — inspect evidence before advancing. |
done | Stamp file exists or YAML status is done. | Terminal. |
Priorities
Section titled “Priorities”When multiple WUs have open actions, reconciliation orders them so integrity is surfaced first:
recover_wu— contamination, stall, restorable missing worktrees, or conflicting evidence.finish_wu— ready work that can complete immediately.relaunch_wu— dead worktrees that cannot be restored and need a new agent.launch_wu— fresh eligible work.wait— everything else.
Humans and agents read this ordering the same way. There is no hidden prompt telling Claude “fix integrity first” — the reconciler makes that the first action in the list.
Phase exit states
Section titled “Phase exit states”A phase is a scheduling boundary, and it has its own small state vocabulary,
reconciled from the same evidence. A phase exit is satisfied only when every
exit criterion is proved; the other three values explain why it is not.
| Phase exit state | When it fires | Effect on later phases |
|---|---|---|
pending | Exit criteria unproved and no phase WU is active or blocked. | Later-phase WUs stay out of launch. |
active | Exit criteria unproved and at least one phase WU is in flight. | Later-phase WUs stay out of launch. |
blocked | Exit criteria unproved and at least one phase WU is blocked. | Later-phase WUs stay out of launch. |
satisfied | Every exit criterion is proved by canonical evidence. | The next phase’s WUs become launchable. |
A phase MAY declare exit_criteria, each with a stable id, a description, and
one of three evidence kinds:
| Criterion kind | Proved by |
|---|---|
phase_wus_done | Every WU of this phase is done. Membership is the union of each WU’s initiative_phase and the phase record’s own wus list. |
wus_done | Each WU id named in evidence is done. |
artifact_present | Each repository-relative path named in evidence exists. |
The field is optional. A phase that omits it is derived as a single implicit
phase_wus_done criterion, so initiatives written before this contract behave
exactly as they always did.
“Done” here is resolved through the canonical terminal WU statuses, not the
single literal done. Every terminal status is classified, because one that is
neither proving nor withdrawing would freeze its phase forever:
| Terminal status | Phase-exit treatment |
|---|---|
done | Proves the criterion. |
completed | Proves the criterion (documented legacy spelling of done). |
cancelled | Withdrawn — leaves the phase’s denominator. |
superseded | Withdrawn — another WU carries the outcome. |
abandoned | Withdrawn — the work was given up, not deferred. |
deferred | Withdrawn — explicitly moved out of this phase’s scope. |
closed | Withdrawn — closed without the outcome being delivered. |
failed | Blocks the exit. |
Work that will never happen cannot be waited on, so it leaves the denominator.
failed blocks because it is the only terminal status recording an outcome
that was attempted and did not happen; re-open, replace, or explicitly withdraw
the failed WU before the phase can exit.
Evaluation fails closed. A criterion kind this build cannot resolve, and a
criterion that names no evidence reference, are both unproved rather than
vacuously satisfied. Reading is separate from evaluating: a consumer parsing a
status.json written by a newer build does not throw away the document over a
criterion kind it has never heard of — that one row is reported as
unrecognized and unsatisfied, carrying the raw kind, and the rest of the
projection is preserved. artifact_present evidence must be repository-relative:
absolute paths and .. traversal are refused by the schema, by the record
validator, and again by the runtime probe, so an initiative cannot prove its own
exit against a file the workspace does not own.
A phase that nothing is assigned to, and that declares no criteria, has nothing
left to prove: it is satisfied and gates no later work. A phase boundary may
only withhold work on evidence, and there is no evidence in an empty set.
Three rules make the boundary load-bearing rather than decorative:
- A declared phase status is a claim, not evidence. Where the status
written in the initiative record disagrees with the derived exit state, the
derived state wins and the disagreement is reported as an explicit override
with its reason. Marking a phase
donecannot release later work while its WUs are incomplete. - An unproved phase withholds later work. A WU in phase N is excluded from
next_safe_actionsuntil every phase before N issatisfied, and thewaitaction names the exact unsatisfied criterion, the blocker, and the supporting evidence reference. - Every surface resolves WU state the same way. One
resolvePhaseExitWuStatesanswers “what state is this WU actually in” fororchestrate:initiative,orchestrate:init-status,initiative:status, andstatus.json, so a dependency-blocked WU cannot readreadyon one surface andblockedon the next. A wave in which nothing may launch still writes its bundle, so the projection and the reasons are durable exactly when they matter most.
Progress is reported the same way: current phase, WU state counts, exit-criteria satisfaction, the blocking reason, and the last evidence-backed progress delta. Raw done ÷ total is still available, but only as an explicitly labelled secondary metric, printed below the phase-exit block rather than as the headline.
Where the record’s declared phase status and the derived state disagree, the projection distinguishes the two directions. An over-claim — the record says the phase exited but the evidence does not — is the governance failure an operator must act on. An under-claim — the evidence has moved ahead of a record nobody updated — is benign bookkeeping and withholds nothing. Both are reported, never in the same words.
initiative:status --format json carries the projection under the camelCase key
phaseExit, matching the rest of that command’s JSON; the durable artifact
carries the same value as snake_case phase_exit. They are one value in two
spellings, converted by toOrchestrationPhaseExitProjection.
Legacy value mapping
Section titled “Legacy value mapping”Earlier versions of LumenFlow used ready where the orchestration model now says
eligible. The control-plane SDK parser normalizes 'ready' to
'eligible' on read so older status.json files do not fail validation,
but every new emitter uses the eligible spelling.
Related
Section titled “Related”- Lifecycle — which phase each state surfaces in.
- Capacity + integrity — what makes contamination and stall fire in practice.
- Control-plane SDK —
OrchestrationStatusValueas the canonical type. - Artifact bundle — the
phase_exitprojectionstatus.jsoncarries.