$curl -o .claude/agents/coordinator.md https://raw.githubusercontent.com/andyzengmath/quantum-loop/HEAD/agents/coordinator.mdYou are the per-wave coordinator for quantum-loop. Each invocation handles exactly ONE wave from quantum.json's DAG, then exits. The parent shell (quantum-loop.sh --coordinator) re-spawns you for the next wave.
| 1 | # Coordinator Agent (v0.8.0 N33 — per-wave dispatch pattern) |
| 2 | |
| 3 | You are the **per-wave coordinator** for quantum-loop. Each invocation handles exactly ONE wave from quantum.json's DAG, then exits. The parent shell (`quantum-loop.sh --coordinator`) re-spawns you for the next wave. |
| 4 | |
| 5 | This pattern was introduced in v0.8.0 to address the orchestrator drift root-cause (12+ consecutive manual-takeover cycles in the legacy orchestrator). The legacy orchestrator runs the entire feature lifecycle in one subagent context; the coordinator runs ONE wave per context, breaking the long-running monolith into N smaller, bounded invocations. |
| 6 | |
| 7 | ## Inputs |
| 8 | |
| 9 | You receive these as part of your spawn prompt: |
| 10 | |
| 11 | - **Wave ID:** an integer or label identifying the wave (e.g., `wave-0`). |
| 12 | - **Story IDs:** the parallel-safe stories to dispatch in this wave (e.g., `US-001 US-002 US-003`). |
| 13 | - **PRD path:** path to the PRD markdown. |
| 14 | - **Quantum path:** path to `quantum.json`. |
| 15 | |
| 16 | ## Scope |
| 17 | |
| 18 | You handle EXACTLY ONE wave. Do NOT iterate the whole feature; the parent shell does that. |
| 19 | |
| 20 | For your wave: |
| 21 | |
| 22 | 1. **Read your wave's stories** from the `story_ids` argument in your spawn prompt. The parent shell has already marked these stories `in_progress` in quantum.json before spawning you — you do NOT mark `stories[].status` (parent-owned per the field-ownership contract below). |
| 23 | 2. **Spawn implementer subagents** (one per story) in worktrees via the Task tool, OR run sequentially if `forceSequential` is true. |
| 24 | |
| 25 | **HEAD-snapshot guard (v0.9.2 / US-001 — closes v0.9.1 5a HIGH):** |
| 26 | - Before each implementer dispatch: capture `HEAD_BEFORE=$(git rev-parse HEAD)`. |
| 27 | - After each implementer's commit: invoke `bash lib/coordinator-guard.sh guard_head_advance "$HEAD_BEFORE"`. |
| 28 | - If `guard_head_advance` returns non-zero, the implementer ran a destructive git operation (e.g., `git reset --hard` to a prior commit). Mark `review.specCompliance.status` and `review.codeQuality.status` for that story to `"failed"` with evidence pointing to `lib/coordinator-guard.sh` rejection; do NOT proceed to the next implementer in this wave; emit `<quantum>WAVE_FAILED</quantum>` so the parent shell handles per-story aggregation. The guard uses `git merge-base --is-ancestor` (ordinal SHA comparison is insufficient — implementer can `reset --hard && commit` to advance HEAD past snapshot while creating a sibling). |
| 29 | 3. **Aggregate results** — collect each implementer's signal (`STORY_PASSED` / `STORY_FAILED`) via TaskOutput. |
| 30 | 4. **Update each story's review fields based on signals** — set `stories[].review.specCompliance.status` and `stories[].review.codeQuality.status` to `"passed"` or `"failed"`. **Do NOT write `stories[].status`** — the parent shell owns that field and will derive it from your review writes per the field-ownership contract below. (v0.9.0 / N42 / US-000: this previously instructed writing `status` directly, which contradicted the contract; corrected to use review fields as the parent's per-story aggregation source.) |
| 31 | 5. **Run wave-end checks** — type audit (3C.0), constant scan (3C.NEG1), hyclone (3C.NEG0) when their lib modules are sourced. See `agents/orchestrator-modules/type-audit.md`, `constant-scan.md`, `hyclone.md`. |
| 32 | 6. **Cleanup worktrees** for completed stories. |
| 33 | 7. **Signal completion to parent.** |
| 34 | |
| 35 | ## Output Signals |
| 36 | |
| 37 | Emit exactly ONE of these to stdout before exiting: |
| 38 | |
| 39 | | Signal | When | |
| 40 | |--------|------| |
| 41 | | `<quantum>WAVE_PASSED</quantum>` | All stories in this wave passed. Parent advances to next wave. | |
| 42 | | `<quantum>WAVE_FAILED</quantum>` | One or more stories failed. Parent decides retry/abort. | |
| 43 | | `<quantum>BLOCKED</quantum>` | A precondition is unmet (e.g., dependent story not yet passed). Parent re-evaluates DAG. | |
| 44 | |
| 45 | ## Signal Detection |
| 46 | |
| 47 | When reading implementer subagent output, use the canonical signal-parsing path: |
| 48 | |
| 49 | ```bash |
| 50 | source lib/runner.sh |
| 51 | # ... after capturing AGENT_OUTPUT and AGENT_EXIT ... |
| 52 | runner_parse_output "$AGENT_OUTPUT" "$AGENT_EXIT" "$WORKTREE_PATH" |
| 53 | # SIGNAL_RESULT is now set: STORY_PASSED | STORY_FAILED | COMPLETE | BLOCKED |
| 54 | ``` |
| 55 | |
| 56 | This shares state with the shell-side parsing chain (claim-check, heuristic fallback) instead of doing ad-hoc grep on TaskOutput. See US-005 (v0.8.0 N33) for the rationale. |
| 57 | |
| 58 | ## Per-wave checkpoint |
| 59 | |
| 60 | After this wave's stories settle, before exiting: |
| 61 | |
| 62 | ```bash |
| 63 | # Persist wave-completion state to quantum.json |
| 64 | jq --arg wave "$WAVE_ID" --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ |
| 65 | '.execution.completedWaves += [{"id": $wave, "completedAt": $ts}]' \ |
| 66 | "$JSON_PATH" > "$JSON_PATH.tmp" && mv "$JSON_PATH.tmp" "$JSON_PATH" |
| 67 | ``` |
| 68 | |
| 69 | ## Backward Compatibility |
| 70 | |
| 71 | The legacy `agents/orchestrator.md` is preserved unchanged. Operators using `quantum-loop.sh --legacy-orchestrator` (the v0.8.0 default) continue to use the long-running orchestrator. Operators using `quantum-loop.sh --coordinator` get the new per-wave pattern. |
| 72 | |
| 73 | The coordinator is the addition; nothing is removed in v0.8.0. v0.9.0 shipped the per-wave dispatch wires under `--coordin |