Repository navigation
coord driver: make wave rollover and housekeeping a deterministic state machine #2127
Description
Observed during a live drive-board-normal run on 2026-08-02. The host correctly dispatched six workers but later waited with only two active items instead of applying the declared consolidation-threshold=3, reconsolidating, and immediately starting wave two. The operator had to remind the host of the rule. The same run also exposed adjacent memory-sensitive transitions: reconcile --apply initially failed because the host had no worker identity; a critic posted a substantively correct but syntactically invalid review marker; stale-claim reaping, flush, fresh lint/backlog triage, engine-currency checks, and dispatch eligibility were separate manual steps. A worker also returned terminal output multiple times while its claim was still live, tests were still running, and no review-ready SHA existed; the host had to reactivate it manually.
The root cause is that the driver is documented as a state machine but executed as prose from agent memory. batch already emits activeItems, waveCapacity, and openSlots; the engine should own the transition logic and receipts that follow from those facts. Agents should provide judgement (classification, consolidation objective, review findings), not remember deterministic ordering.
Acceptance
- Add an
fsgg-coorddriver planning/advance surface that reads live claims and board state and emits one typed next action for the two-wave model: continue current waves, consolidate atactiveItems <= 3, run housekeeping, repair engine currency, or dispatch a sized next wave. - A dispatch receipt is refused unless it is bound to a fresh successful chain: reconcile dry-run, mechanical apply where needed, flush with zero pending writes, fresh reconcile, fresh lint/backlog inventory, and scoped engine-currency zero. Stale receipts fail closed.
- The engine counts claimed, in-review, and newly dispatched items across both waves, reserves two critic slots, and proves the
6 -> 2regression starts a new three-slot wave after housekeeping rather than waiting. - Mechanical housekeeping owns or explicitly requests a host identity before writes; it cannot partially apply and then present the pass as complete.
- Review-chain validation is machine-checkable: required marker spelling, critic identity, exact SHA, ordered rounds, round ceiling, check state, and host-acceptance readiness are returned as typed data. An unmarked prose review is rejected.
- Stale-claim reaping and engine-currency repair are first-class transition gates, with receipts naming what changed and whether dispatch is now legal.
- Committed tests reproduce this run: low-occupancy rollover, stale claim, missing host identity, invalid review marker, pending write, stale engine, and no-dispatch-before-fresh-triage.
- Human judgement remains explicit inputs: defect/hardening/decision classification and whether overlapping objectives consolidate are not automated.
- A worker return is not counted terminal while its claim remains live and the item is neither review-ready nor parked/Done; the planner emits a typed resume-same-worker action and tests the live-claim/no-PR and live-claim/tests-running cases.
Class: hardening
Paths: .agents/skills/drive-board/** .claude/skills/drive-board/** .agents/skills/drive-board-normal/SKILL.md .claude/skills/drive-board-normal/SKILL.md .agents/skills/work-board/** .claude/skills/work-board/** .agents/skills/work-board-normal/SKILL.md .claude/skills/work-board-normal/SKILL.md .agents/skills/pnext-item/references/independent-review.md .claude/skills/pnext-item/references/independent-review.md .fsgg/** work/2127-driver-transition-state-machine/** readiness/2127-driver-transition-state-machine/** AGENTS.md CLAUDE.md TestResults/coord-core.trx src/FS.GG.Kit/FS.GG.Kit.csproj src/FS.GG.Coord.Core/Driver.fs src/FS.GG.Coord.Core/Driver.fsi src/FS.GG.Coord.Core/FS.GG.Coord.Core.fsproj src/FS.GG.Coord.Cli/Client.fs src/FS.GG.Coord.Cli/Options.fs src/FS.GG.Coord.Cli/Options.fsi src/FS.GG.Coord.Cli/Program.fs src/FS.GG.Coord.GitHub/Reads.fs src/FS.GG.Coord.GitHub/Reads.fsi tests/FS.GG.Coord.Core.Tests/DriverTests.fs tests/FS.GG.Coord.Core.Tests/FS.GG.Coord.Core.Tests.fsproj tests/FS.GG.Coord.Cli.Tests/ApplicationServiceTests.fs tests/FS.GG.Coord.Cli.Tests/CommandSurfaceTests.fs tests/FS.GG.Coord.Cli.Tests/DriverCommandTests.fs tests/FS.GG.Coord.Cli.Tests/FS.GG.Coord.Cli.Tests.fsproj tests/FS.GG.Coord.Cli.Tests/OptionsTests.fs registry/driver-skill-manifest.json scripts/fsgg-coord-guards.sh tests/coord-engine-e2e/writes.sh
Evidence: this run missed the documented fsgg:wave-model:v1 ... consolidation-threshold=3 transition until operator correction; reconcile --apply then refused without a host identity; the first #1176 critic comment omitted <!-- fsgg:independent-review:v1 --> and required correction before repair could legally route; #1181 returned terminal output repeatedly before its active claim reached review handoff.
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsDone
Activity
EHotwagner commentedon Aug 2, 2026
Mandatory delivery-route decision
Decision maker: Codex drive-board host
Decision:
sdd-requiredRationale: This changes the two-wave driver state machine, typed transition and review-chain contracts, recovery semantics, and several host workflows.
This decision is required for dispatch. Material scope changes invalidate it and require a fresh decision.
EHotwagner commentedon Aug 2, 2026
osprey-77b1 → snipe-a1ca
heads up: I widened .github#2086 to
Paths: .claude/skills/pnext-item/references/independent-review.md, .fsgg/**, work/2086-independent-review-runtime-route/**, readiness/2086-independent-review-runtime-route/**, feedback/checkpoints/2086-independent-review-runtime-route.jsonl, feedback/**, .claude/skills/pnext-item/SKILL.md, .claude/skills/pnext-item/agents, .claude/skills/pnext-item/references, src/FS.GG.Kit/FS.GG.Kit.fsproj, which overlaps your touch-set here (.fsgg, work/2086-independent-review-runtime-route, work, readiness/2086-independent-review-runtime-route, readiness). I do not know which of us declared these paths first, so this may or may not be new. This is a TRANSIENT overlap — the scheduler already sequences us, and it clears the moment one claim drops, so you may not need to do anything. To unblock the board sooner: narrow withset-paths, or split one touch-set so we are disjoint. Only add aBlocked byedge if there is a real DEPENDENCY — my work must be authored against your LANDED result, not merely the same files — because that edge is durable and nothing re-checks it once the overlap is gone. Reply here.feat(coord): make driver transitions deterministic (#2140)