Phase 1 Data Model: Advancing next — task-board authority unification

No persisted schema changes. The "entities" here are the in-memory decision structures and the board-state read that flows through them. Documented so the contract and tests have named referents.

Board step (value)

The step name the board authority derives from the finalized task board + coord-aware status surface.

ValueMeaningAdvancing decision
implement≥1 WP in a pre-review lane (planned/claimed/in_progress)kind=step action=implement wp_id=<claimable>
review≥1 WP in for_reviewkind=step action=review wp_id=<for_review>
acceptall WPs at an acceptable ending, not all doneadvance-past-step (handled by the leave-step path)
doneall WPs doneterminal
blocked:review_in_progressonly in_review WPs (claimed by another reviewer)kind=blocked + recovery
blocked:no_actionable_wpnothing claimable/actionable (e.g. dependency wall)kind=blocked + recovery

Derived by _finalized_task_board_override_step(task_board_dir, progress, status_dir=<coord-aware>). Invariant: advancing mode and query mode derive this value from the identical inputs (same task_board_dir, same coord-aware status_dir), so they never disagree.

Advancing decision envelope (existing DecisionEnvelope)

Fields relevant to this fix:

FieldPre-fix bug value (#4980)Pre-fix bug value (#4975)Post-fix required
kindstepblockedstep (re-dispatch) or blocked (floor)
actionreviewNoneimplement (re-dispatch) / board step
wp_idnullnullWP01 (the actionable WP)
mission_statereviewimplementboard step
prompt_filecomposed placeholder—real action prompt, or blocked reason
exit code010 (step) / 1 (blocked)

Invariant (FR-005): no live advancing result has kind=step with wp_id=null for a WP-iteration step. A WP-less WP-iteration state is either a real re-dispatch (wp_id set) or kind=blocked.

Issued step marker (persisted, unchanged)

The run's issued_step_id (e.g. review). Invariant (NFR-001): unchanged by the re-dispatch; the advancing action is recomputed from the board each call. The whole persisted run/engine snapshot is byte-identical before and after the re-dispatch call.

Coord status surface (read, fail-closed)

The coord-aware status_dir resolved via the placement seam (mission_context_for(repo_root, mission_slug).artifact(STATUS_STATE).read_dir). Invariant (NFR-003): on an unmaterialized/deleted coordination surface the read raises the typed fail-closed error (ADR 2026-09-24-2); it is never substituted with an empty primary read that fabricates "no WP".

State transitions (advancing loop, post-fix)

issued=review, WP01 for_review        --review success-->  reviewer verdict
  ├─ approve → WP01 approved  → board=accept  → advance → accept → terminal
  └─ reject  → WP01 planned   → board=implement → RE-DISPATCH implement WP01   (was: spin on placeholder ∞)
issued=implement (coord), WP01 planned → board=implement (coord-aware) → DISPATCH implement WP01  (was: blocked "No action mapped")
board=blocked:*                        → kind=blocked + named recovery command  (never composed placeholder)
coord surface unmaterialized           → typed fail-closed error (named), NOT generic no-actionable-WP