pi-gauntlet 7.16.0 → 7.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## v7.17.1 - 2026-10-18
4
+
5
+ ### Fixed
6
+
7
+ - **Wave reviews inspect the implemented files.** Pre-integration spec reviews read a temporary checkout with the task's patch applied, including new and deleted files. Integrated code reviews compare staged and unstaged deliverables against the recorded wave base instead of an unchanged commit range; in-place repairs preserve that base and supply only their fix delta. Real Git fixtures cover both review sources and malformed patches. Paired with pi-cohort's binary-safe patch capture fix.
8
+
9
+ ## v7.17.0 - 2026-10-18
10
+
11
+ ### Changed
12
+
13
+ - **`writing-plans` authors the plan through a fresh `plan-writer` child.** The main loop dispatches one `plan-writer` (`context: "fresh"`, spec, plan, and worktree paths in the task), runs `plan_check` once for the stamp, re-dispatches once with the verbatim findings when its check fails after a `PLAN WRITTEN` reply, and reads the finished plan once before `plan_tracker` init; the scout recon dispatch, the context-draft marker, and the parent's write-and-fix loop are gone. The amendment aftermath's plan edit goes through the same dispatch. New persona `agents/plan-writer.md` (model-free; `subagents.agentOverrides.plan-writer.model` overrides). (#69)
14
+
3
15
  ## v7.16.0 - 2026-10-18
4
16
 
5
17
  ### Added
package/README.md CHANGED
@@ -78,7 +78,7 @@ The run's grants, target/scope baseline, repair usage, and poll deadline live in
78
78
  pi-gauntlet ships three kinds of pieces, layered on top of pi-cohort's dispatch:
79
79
 
80
80
  - **20 skills** - the workflow logic. Fifteen activate automatically when pi sees the matching kind of task, and the workflow skills chain through their gates: `shape-ticket` (creates or repairs one tracker issue per run against a Context/Problem/Idea/Acceptance-Criteria template, gated by an AC integrity check, a cheap council roast, and a single human-confirmed write; model-invocable so other skills and commands can route "file a ticket" to it, the gate still needs your yes), `gatekeep-pr` (model-invocable on an explicit ask that names the PR and the verb; the gates still need your selection - is consent-gated pre-merge verification of a PR against the scope contract at its head - the approved spec's acceptance-criteria dispositions and Design when the PR carries one, else the PR's stated intent; the ticket is cross-checked, never judged here (`check-delivery` owns it) - read-only gathering, verification evidence resolved CI-first (green checks on the exact assessed head count as evidence; a pending commit status that GitHub does not report as blocking the gating actor (`mergeStateStatus` not `BLOCKED`) is not waited for - external-CI commit statuses included - while a running Actions check, an unknown merge state, and every other merge precondition still withhold; the project's verification command runs only as fallback), a rubric-based review, a compact bottom-up report (what the PR delivers, including rows deferred or deviating per spec, PR comments, nits, blockers, then a `mergeable` / `fixable` verdict) and a verb menu whose rows derive from the actor's permissions on the PR; nothing mutates (fixes, pushes, reviews, merges, tracker comments) until you pick a row, except the opt-in `--rebase [base]` sync that rebases, reviews, and lease-pushes the head before verification, or holds the rebased head locally when a conflict stop's scoped tests fail, so the normal `fix` row resolves it before the lease push; after your own merge two opt-in rows post the `AC coverage` block to the ticket or the PR; every terminal menu offers a recommended `cleanup` row that tears down the gate's worktree and branch and runs the overrides file's `## cleanup` steps - run it with `/skill:gatekeep-pr <pr> [--rebase [base]]`), `check-delivery` (model-invocable on an explicit ask that names the ticket and the verb; the gates still need your selection - is a post-merge detective control: proves an issue actually shipped (default-branch landing, delivery target, per-AC evidence) before its tracker status advances; it never writes a terminal status - run it with `/skill:check-delivery <ref>`), `writing-plans`, `roasting-the-spec`, `test-driven-development`, `subagent-driven-development`, `dispatching-parallel-agents`, `verification-before-completion`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `forge-skill`, `linear` (reads/searches/comments on/manages Linear tickets via the `linearis` CLI; owns all linearis mechanics and the `## Issue tracker` overrides schema; tracker-facing skills route to it). Five more require explicit entry (`disable-model-invocation: true`): `brainstorming` starts the gated workflow on explicit consent - use `/skill:brainstorming` for reliable discovery, or opt in through reachable explicit prose or a human-selected handoff; after spec approval, downstream planning and implementation still chain automatically. `chase-bug` is human-only bug triage: read-only root-cause discovery to an evidenced verdict menu (real bug -> ticket/brainstorm/hotfix/respond; five negative verdicts), then a gated response to the reporter for addressable origins (GitHub issue / tracker ticket) and a rendered verdict summary otherwise - it never fixes during triage; the hotfix row hands off to `skills/chase-bug/hotfix.md` after the menu - run it with `/skill:chase-bug`. `gauntlet-performance` reads the committed run telemetry (current repo by default, `--dir <path>` adds others) through the parse-only `gauntlet-performance` CLI and answers with one example-led recommendation, 3-5 cornerstone numbers, a council assessment when available, and a menu of at most three actions (render a report file, open the recommendation as a ticket via `shape-ticket`, drill into one run); it writes nothing unless you pick render - run it with `/skill:gauntlet-performance [--dir <path>]... [--since <version>]`. `gauntlet-handoff` ends a session whose flow a fresh session will continue: it invokes pi-cohort's `handoff` skill (`--out <path>` or `--key <name>`, default key = the run worktree's branch with `/` flattened to `-`, default file `<tmpdir>/pi-handoff/<key>.md`), then appends the gauntlet process-state section (phase/plan tracker status) per the shared contract `skills/gauntlet-resume/reference/brief-contract.md` - run it with `/skill:gauntlet-handoff [--out <path> | --key <name>]`. `gauntlet-resume` is the only way back into an interrupted flow from a fresh session: it takes a `gauntlet-handoff` brief (a file path, pasted text, or - with no arguments - a pick from the briefs under `<tmpdir>/pi-handoff/`), a bare worktree that already holds a spec, or a spec tracked on main under a configured spec dir (a spec seed: it creates or reuses the worktree through `using-git-worktrees` and pins the spec), restores phase/plan tracker state through the legal arming sequence (`start brainstorm`, `skip` with `resume:` reasons, `plan_check` before implement-or-later), and never infers approval from artifacts - run it with `/skill:gauntlet-resume [<brief-file> | <spec>.md | <worktree-name-or-path>]`.
81
- - **7 subagent personas** - the specialized child agents the skills dispatch via pi-cohort: `implementer`, `code-reviewer`, `spec-reviewer`, `conformance-reviewer`, `spec-summarizer`, `spec-council-member`, `spec-council-synthesizer`. See [doc/personas.md](./doc/personas.md) for what each one does and why its permissions are scoped the way they are.
81
+ - **8 subagent personas** - the specialized child agents the skills dispatch via pi-cohort: `implementer`, `code-reviewer`, `spec-reviewer`, `conformance-reviewer`, `spec-summarizer`, `plan-writer`, `spec-council-member`, `spec-council-synthesizer`. See [doc/personas.md](./doc/personas.md) for what each one does and why its permissions are scoped the way they are.
82
82
  - **4 runtime extensions** - the enforcement layer. `plan-tracker` and `phase-tracker` are tools skills call to track progress (with a TUI widget); `verify-before-ship` is a hook that warns if you push or open a PR without a passing test run since your last edit; a phase-tracker flow guard reminds on implement-phase commits missing spec/code review. In a brainstorming-entered flow, phase-tracker rejects `implement` or `verify` completion while tracker tasks remain pending or in progress; see [its configuration reference](./doc/configuration.md#phase-tracker). phase-tracker also registers `plan_check`, which verifies a plan against its spec and against the grammar in [skills/writing-plans/reference/plan-contract.md](./skills/writing-plans/reference/plan-contract.md), including that each task's `Tests:` commands are selective and never the full suite; a pass stamps the plan for implementation. `telemetry` records one YAML record per gauntlet run (phase timing, models, personas, gate/fix rounds, diff at ship) that ships in the squash beside the spec - it is written only inside a brainstorming-entered flow, kept out of history until `finishing-a-development-branch` seals it once with `gauntlet-telemetry-seal` (a `telemetry:` commit under git; the working-copy snapshot in a plain jj workspace) - and blocks a brainstorm `write` into an already-shipped spec; see [its configuration reference](./doc/configuration.md#telemetry). See [doc/configuration.md](./doc/configuration.md) for the settings each one reads.
83
83
 
84
84
  pi-gauntlet is **opinionated**: it recommends this pipeline for non-trivial changes, but starts `brainstorming` only after explicit user consent. Enforcement is opt-in by entry, not ambient: once brainstorming starts a flow, the phase-tracker extension mechanically blocks a phase from closing before its gate runs, and warns once if the main loop writes code during implement (subagents own implement-phase edits). A change made *without* entering the flow (a typo, a formatting run, a dependency bump - see "When to use / when NOT to use") is not gated; the discipline of routing real work through the pipeline is a convention the tooling supports, not a trap it springs on every edit.
@@ -122,7 +122,7 @@ Run by a human against pi-cohort >= 7.1.0, before a pi-gauntlet release claims t
122
122
  ## Requirements
123
123
 
124
124
  - [pi-coding-agent](https://github.com/earendil-works/pi) ≥ 0.85.1 - tested minimum for sequential `phase_tracker` tool execution, which persists a tracker update before a later tool call in the same model message.
125
- - [pi-cohort](https://github.com/jjuraszek/pi-cohort) ≥ 1.4.5 - required peer package. Skills that dispatch agents (`requesting-code-review`, `subagent-driven-development`, `dispatching-parallel-agents`, `writing-plans`, `forge-skill`, `shape-ticket`, `roasting-the-spec`) call `subagent({})`, which pi-cohort provides. pi-gauntlet does not vendor the dispatch tool; without pi-cohort those skills have nothing to call. Gauntlet execution dispatches explicitly use `async: false`; do not enable pi-cohort's incompatible `forceTopLevelAsync` setting. See pi-cohort's [dispatch configuration](https://github.com/jjuraszek/pi-cohort/blob/main/doc/configuration.md) for that setting's owner and semantics.
125
+ - [pi-cohort](https://github.com/jjuraszek/pi-cohort) >= 7.3.1 - required peer package, including binary-safe worktree patches. Skills that dispatch agents (`requesting-code-review`, `subagent-driven-development`, `dispatching-parallel-agents`, `writing-plans`, `forge-skill`, `shape-ticket`, `roasting-the-spec`) call `subagent({})`, which pi-cohort provides. pi-gauntlet does not vendor the dispatch tool; without pi-cohort those skills have nothing to call. Gauntlet execution dispatches explicitly use `async: false`; do not enable pi-cohort's incompatible `forceTopLevelAsync` setting. See pi-cohort's [dispatch configuration](https://github.com/jjuraszek/pi-cohort/blob/main/doc/configuration.md) for that setting's owner and semantics.
126
126
 
127
127
  Both packages must be listed in your `.pi/settings.json#packages` array (pi adds them automatically when you `pi install`). pi-gauntlet and pi-cohort are versioned independently but release together whenever dispatch semantics change - pin compatible versions of both.
128
128
 
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: plan-writer
3
+ description: Writes, checks, and repairs the gauntlet implementation plan for one approved spec in a fresh context; the plan file is its only output. Dispatched only by the writing-plans skill; not for direct dispatch.
4
+ tools: read, grep, find, ls, write, plan_check
5
+ inheritProjectContext: false
6
+ inheritSkills: false
7
+ completionGuard: true
8
+ systemPromptMode: replace
9
+ ---
10
+
11
+ You are the plan writer for a gauntlet flow. You exist so the orchestrating session never carries the drafting and repair of an implementation plan: you do the recon, write the plan, check it, and fix it, and the orchestrator gets back one line and a file.
12
+
13
+ ## Output contract
14
+
15
+ The plan file at the plan path is your only output. Your final reply is exactly one line, nothing before or after it:
16
+
17
+ - `PLAN WRITTEN <abs plan path>` when the plan passed its last check and carries no open questions.
18
+ - `OPEN QUESTIONS <abs plan path>` when the plan carries an `## Open Questions` section.
19
+
20
+ No plan content, no summary, no commentary.
21
+
22
+ ## Inputs
23
+
24
+ The task names five absolute paths: the worktree, the approved spec, the plan path, the plan skill file, and the plan contract file. It may also carry one block after them:
25
+
26
+ - `Findings:` - the verbatim output of the orchestrator's own `plan_check` on the plan at the plan path, or a human's answers to the plan's open questions. Read the existing plan first and keep everything the block does not touch. Treat each answer as the resolution of the matching open question; remove the `## Open Questions` section when every question is answered.
27
+ - `Amend:` - the amended spec sections and the rule for the edit. Read the existing plan first; preserve every task title and wave position the amendment does not touch; edit only the affected anchors and tasks.
28
+
29
+ ## Procedure
30
+
31
+ 1. Read the repo's `AGENTS.md` at the worktree root and the gauntlet overrides file - the first that exists of `.pi/gauntlet-overrides.md`, `gauntlet-overrides.md`, `doc/gauntlet-overrides.md` under the worktree - for conventions, verification commands, and a `## Happy path` table.
32
+ 2. Read the plan skill file (`SKILL.md`) from its `## File Structure` heading through the end of its `## Self-Review` section, and the whole plan contract file (`plan-contract.md`). That text is the plan contract; follow it as written.
33
+ 3. Read the spec in full. Recon the code the spec touches by reading it directly: exact paths to create, modify, or delete; call sites and tests with line ranges; the scoped command that runs one test file; scoped and repo-wide lint and format commands; the full-suite verification entrypoint and whether it bundles style checks. Dispatch nothing.
34
+ 4. Write the plan at the plan path with `write` as a full replacement. The plan path is the only file you write; never create or edit any other file.
35
+ 5. Run `plan_check({ planPath })` on the plan path. A result whose first line starts with `PASS` is a pass; `PASS (no flow to stamp)` is the expected text here. On `FAIL`, fix every finding in the plan and run it again.
36
+ 6. Apply the judgment checks the skill's `## Self-Review` section lists: code-vs-anchor sanity, type and API consistency, test contract, runtime-resource disjointness, solo-reason validity, waiver authorization, verification-ownership authorization, documentation-impact mapping. Any edit returns you to step 5.
37
+ 7. Stop when `plan_check` passes and the judgment checks caused no edit. When the same finding has survived 3 fix rounds, write it under an `## Open Questions` section at the top of the plan and stop; rows in a `Findings:` block continue that finding's count, so one 3-round budget per finding covers every dispatch. Then reply per the output contract.
38
+
39
+ ## Rules
40
+
41
+ - Never leave a placeholder in the plan; a decision you cannot make is a named open question.
42
+ - Never call `plan_tracker`, `phase_tracker`, or `subagent`; the orchestrator owns them.
43
+ - Never reply with more than the one line.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-gauntlet",
3
- "version": "7.16.0",
3
+ "version": "7.17.1",
4
4
  "description": "Opinionated, gated workflow skills, subagent personas, and runtime extensions for the pi coding agent.",
5
5
  "author": "Jacek Juraszek",
6
6
  "type": "module",
@@ -24,7 +24,7 @@ A grant is the spec's `**Amend-grant:**` line read through the shared predicate;
24
24
  | Event | Edit |
25
25
  |---|---|
26
26
  | Grant given at a tier-2 footer | `edit` the value to the sentence |
27
- | Line absent (legacy spec) | insert the line at the writer placement above; when a plan exists, the insertion shifts every heading by one line, so run the section 5 aftermath's anchor repair (`plan_check` until PASS) and commit spec and plan together |
27
+ | Line absent (legacy spec) | insert the line at the writer placement above; when a plan exists, the insertion shifts every heading by one line, so run the section 5 aftermath's anchor repair (the `plan-writer` amend dispatch, then the parent `plan_check`) and commit spec and plan together |
28
28
  | Revocation (`revoke auto-apply amends`, `stop auto-applying amends`, or the same intent in other words) | `edit` the value to `none` |
29
29
  | Hand-edited line | not an event; the next batch boundary re-reads it and the value found is the current consent |
30
30
 
@@ -140,7 +140,7 @@ Before the aftermath, `read` this section again; never run it from memory.
140
140
 
141
141
  Apply accepted items only: reviewer clears, `accept`, `alt-n`, and state-changing `custom`. Print one line per applied item: `amended the spec: <title> - <what>`.
142
142
 
143
- Aftermath, once per batch, only when at least one item applied (nothing applied -> skip to the commit below). No plan yet -> commit the spec; continue. Plan exists -> update affected anchors and tasks: `plan_tracker` `add` for new tasks; anchor-changed completed tasks are reopened as `in_progress` and re-run the task loop (`update` never sets `pending`). A removed task is deleted from the plan; then re-`init` the tracker with `{ name, status }` elements: preserved tasks keep their order and statuses, reopened tasks are `in_progress` in place, every still-`pending` task (including newly added ones, whatever wave label they carry) trails the non-pending ones, removed tasks are the only deletions (the only permitted `init` after handoff; never `clear`). Re-run `plan_check` until it passes, commit spec + plan together; continue. A task reopened while `verify` or `ship` is in progress stays in that phase - no `phase_tracker` call. Repair it through the current phase's fix loop and `plan_tracker({ action: "update", index: N, status: "complete" })` it once that repair's review or re-audit accepts; open tasks block `complete verify`, and in `ship` nothing checks them, so close them explicitly.
143
+ Aftermath, once per batch, only when at least one item applied (nothing applied -> skip to the commit below). No plan yet -> commit the spec; continue. Plan exists -> dispatch `plan-writer` per `writing-plans` `## Author the plan` step 3 with an `Amend:` block naming the amended spec sections and the rule "preserve every task title and wave position the amendment does not touch; edit only affected anchors and tasks", then run that section's steps 5-6 (the parent `plan_check` and its branches), then read the amended plan once (step 7's read, without its phase completion or `plan_tracker` init) - the main loop never edits the plan text; then update the tracker: `plan_tracker` `add` for new tasks; anchor-changed completed tasks are reopened as `in_progress` and re-run the task loop (`update` never sets `pending`). A removed task is deleted from the plan; then re-`init` the tracker with `{ name, status }` elements: preserved tasks keep their order and statuses, reopened tasks are `in_progress` in place, every still-`pending` task (including newly added ones, whatever wave label they carry) trails the non-pending ones, removed tasks are the only deletions (the only permitted `init` after handoff; never `clear`). Commit spec + plan together; continue. A task reopened while `verify` or `ship` is in progress stays in that phase - no `phase_tracker` call. Repair it through the current phase's fix loop and `plan_tracker({ action: "update", index: N, status: "complete" })` it once that repair's review or re-audit accepts; open tasks block `complete verify`, and in `ship` nothing checks them, so close them explicitly.
144
144
 
145
145
  One commit per batch:
146
146
 
@@ -25,7 +25,7 @@ Dispatch a subagent with the code-reviewer prompt template to catch issues befor
25
25
 
26
26
  ## How to Request
27
27
 
28
- **1. Get git SHAs:**
28
+ **1. Select the review source.** For an integrated uncommitted wave, use its recorded base as `BASE_SHA` and the literal `WORKTREE` as `HEAD_SHA`; stage new deliverables before dispatch, per `code-reviewer.md`. For committed changes, get git SHAs:
29
29
  ```bash
30
30
  BASE_SHA=$(git rev-parse HEAD~1) # or origin/main
31
31
  HEAD_SHA=$(git rev-parse HEAD)
@@ -47,7 +47,7 @@ subagent({ agent: "code-reviewer", async: false, task: "... filled template ..."
47
47
  - `{WHAT_WAS_IMPLEMENTED}` - What you just built
48
48
  - `{PLAN_OR_REQUIREMENTS}` - What it should do
49
49
  - `{BASE_SHA}` - Starting commit
50
- - `{HEAD_SHA}` - Ending commit
50
+ - `{HEAD_SHA}` - Ending commit, or `WORKTREE` for an integrated uncommitted wave
51
51
  - `{DESCRIPTION}` - Brief summary
52
52
  - `{SCOPED_TEST_COMMANDS}` - the scoped verification commands the reviewer may run, or `none`
53
53
 
@@ -40,9 +40,16 @@ Before writing the report:
40
40
  **Base:** {BASE_SHA}
41
41
  **Head:** {HEAD_SHA}
42
42
 
43
+ Use a commit SHA for committed changes, or the literal `WORKTREE` for an integrated uncommitted wave. For `WORKTREE`, the caller stages every new deliverable before dispatch; read the current checkout, including staged and unstaged changes, against Base. Use the same source on re-review.
44
+
43
45
  ```bash
44
- git diff --stat {BASE_SHA}..{HEAD_SHA}
45
- git diff {BASE_SHA}..{HEAD_SHA}
46
+ if [ "{HEAD_SHA}" = WORKTREE ]; then
47
+ git diff --stat {BASE_SHA} -- .
48
+ git diff --binary {BASE_SHA} -- .
49
+ else
50
+ git diff --stat {BASE_SHA}..{HEAD_SHA}
51
+ git diff {BASE_SHA}..{HEAD_SHA}
52
+ fi
46
53
  ```
47
54
 
48
55
  ## Review Checklist
@@ -39,7 +39,7 @@ Periodic "should I continue?" prompts add latency without adding safety. The pla
39
39
 
40
40
  ## Prerequisites
41
41
 
42
- - The worktree path is known - from the `using-git-worktrees` Step 4 report in this session or the handoff brief's `worktree:` row - and is passed as the top-level dispatch `cwd`. If no worktree path exists, stop and invoke `/skill:using-git-worktrees` first - implementation never lands directly on `main`. The process cwd is the primary checkout; nothing here changes it.
42
+ - The worktree path is known - from the `using-git-worktrees` Step 4 report in this session or the handoff brief's `worktree:` row - and is passed as the top-level dispatch `cwd`, except per-patch spec reviews use [Spec-review snapshots](#spec-review-snapshots). If no worktree path exists, stop and invoke `/skill:using-git-worktrees` first - implementation never lands directly on `main`. The process cwd is the primary checkout; nothing here changes it.
43
43
  - Approved plan or clear task scope
44
44
  - `plan_tracker` list initialized at writing-plans handoff with the full wave-ordered task list. Consume and preserve it on continuation; only direct recovery with no tracker initializes the full plan list once, before dispatch, and never over an existing list.
45
45
 
@@ -73,11 +73,11 @@ After all tasks: proceed to [After All Tasks](#after-all-tasks-complete) - it ow
73
73
 
74
74
  One rule governs both review loops - spec-compliance and code-quality - in sequential and parallel-wave modes alike.
75
75
 
76
- **Re-review dispatch rule:** every re-review task includes the complete prior review report verbatim under the marker `## Previous review report (re-review trigger)`, plus the trajectory block from the reviewer's prompt template. The marker's presence is what obligates the reviewer to emit the `TRAJECTORY:` line. You never select, summarize, or diff findings yourself - pattern-match the sentinel line only. Code re-reviews also carry a `## Fix delta` block holding the fix round just integrated: sequential mode, the output of `git diff <HEAD the prior review was dispatched against> HEAD`; wave mode (HEAD unmoved until step 7), the applied fix patch(es) verbatim, never a SHA range. Whole-diff re-reviews never carry the block. Omit it otherwise only when the input is unavailable (a fresh-session resume); the reviewer then treats the task's whole diff as the delta.
76
+ **Re-review dispatch rule:** every re-review task includes the complete prior review report verbatim under the marker `## Previous review report (re-review trigger)`, plus the trajectory block from the reviewer's prompt template. The marker's presence is what obligates the reviewer to emit the `TRAJECTORY:` line. You never select, summarize, or diff findings yourself - pattern-match the sentinel line only. Code re-reviews also carry a `## Fix delta` block holding the fix round just integrated: sequential mode, the output of `git diff <HEAD the prior review was dispatched against> HEAD`; wave mode (HEAD unmoved until step 7), the applied fix patch(es) verbatim, or the in-place fix delta captured in wave step 6, never a SHA range. Whole-diff re-reviews never carry the block. Omit it otherwise only when the input is unavailable (a fresh-session resume); the reviewer then treats the task's whole diff as the delta.
77
77
 
78
78
  **Fix fan-out.** When a fix round is fanned out per `/skill:requesting-code-review` Fix rounds, dispatch per `dispatching-parallel-agents` "Fix fan-out"; the fan-out counts as **one** fix against this budget, its scoped test gate is the consuming task/wave's `SCOPED_TEST_COMMANDS`, and one re-review of the integrated delta follows.
79
79
 
80
- **Behaviour-change reroute.** When the triggering CR report carries `Behaviour-change: yes`, the fix round's re-review is SR first, then CR. The SR dispatch reviews the fix diff against the task's spec anchors as a first review (no `## Previous review report` marker, so no `TRAJECTORY:` line; SR carries no test commands but does carry the task's `**Tests:**` block and `- Test:` paths), but its ordinal continues the task's SR-loop count - a task whose SR loop ended at review 2 gets review 3 here, and an issue-bearing rerouted SR after review 4 escalates. Issues follow the normal sequence: fix, then SR re-review pasting this SR's report. CR round numbering is unchanged. `Behaviour-change: no` re-reviews with CR only. A missing or malformed `Behaviour-change:` line is re-asked once like `Parallel-safe:` (see `dispatching-parallel-agents` "Structural probe"); still missing -> route through SR, never default to `no`. In wave mode the SR re-review targets the task(s) whose files the fix touched.
80
+ **Behaviour-change reroute.** When the triggering CR report carries `Behaviour-change: yes`, the fix round's re-review is SR first, then CR. The SR dispatch reviews the fix diff against the task's spec anchors as a first review (no `## Previous review report` marker, so no `TRAJECTORY:` line; SR carries no test commands but does carry the task's `**Tests:**` block and `- Test:` paths), but its ordinal continues the task's SR-loop count - a task whose SR loop ended at review 2 gets review 3 here, and an issue-bearing rerouted SR after review 4 escalates. Issues follow the normal sequence: fix, then SR re-review pasting this SR's report. CR round numbering is unchanged. `Behaviour-change: no` re-reviews with CR only. A missing or malformed `Behaviour-change:` line is re-asked once like `Parallel-safe:` (see `dispatching-parallel-agents` "Structural probe"); still missing -> route through SR, never default to `no`. In wave mode the SR re-review targets the task(s) whose files the fix touched; after integration, dispatch it against the current implementation worktree, not a pre-integration snapshot.
81
81
 
82
82
  Every fix re-dispatch (implementer) and code-review re-review carries the consuming task/wave's `SCOPED_TEST_COMMANDS`; spec-reviewer re-reviews carry the `**Tests:**` block and `- Test:` paths, no commands - SR never executes.
83
83
 
@@ -104,7 +104,7 @@ Every implementer dispatch returns one of:
104
104
 
105
105
  | Status | Meaning | Orchestrator action |
106
106
  |---|---|---|
107
- | `DONE` | Implemented + tests pass + self-reviewed + committed | Proceed to spec review |
107
+ | `DONE` | Implemented + tests pass + self-reviewed + committed (in-place wave repairs leave the commit to wave step 7) | Proceed to spec review |
108
108
  | `DONE_WITH_CONCERNS` | Implemented + tests pass, but flagged a deviation or risk | Read concerns. If acceptable, proceed. If not, dispatch fix subagent. |
109
109
  | `NEEDS_CONTEXT` | Implementer needs information you have | Answer the questions, re-dispatch with answers in the task text |
110
110
  | `BLOCKED` | Cannot proceed (missing dependency, spec contradicts code, environment broken) | Stop. Diagnose. Either fix orchestration-level issue and re-dispatch, or escalate to user. |
@@ -121,7 +121,7 @@ Implementer prompt templates must instruct subagents to return one of these stat
121
121
 
122
122
  ## Dispatch
123
123
 
124
- Every dispatch carries the worktree as top-level `cwd` - sequential mode included.
124
+ Pass the implementation worktree as top-level `cwd` - sequential mode included. For per-patch spec reviews, use [Spec-review snapshots](#spec-review-snapshots) instead.
125
125
 
126
126
  ```ts
127
127
  // implementer
@@ -130,8 +130,8 @@ subagent({ agent: "implementer", async: false, cwd: "<abs worktree path>", task:
130
130
  // escalated fix round (Fix-Loop Rounds): same fix payload, model from gauntlet_setting({ key: "escalationLoop" }).implModel
131
131
  subagent({ agent: "implementer", model: "<implModel>", context: "fresh", async: false, cwd: "<abs worktree path>", task: "<the just-dispatched fix payload + prior review report verbatim>" })
132
132
 
133
- // spec compliance
134
- subagent({ agent: "spec-reviewer", async: false, cwd: "<abs worktree path>", task: "<task text + patch diff + absolute spec path + task's Spec: anchors + Tests: block + Test: paths>" })
133
+ // spec compliance: per-patch reviews use the materialized snapshot cwd
134
+ subagent({ agent: "spec-reviewer", async: false, cwd: "<abs review checkout path>", task: "<task text + patch diff + absolute spec path + task's Spec: anchors + Tests: block + Test: paths>" })
135
135
 
136
136
  // code quality
137
137
  subagent({ agent: "code-reviewer", async: false, cwd: "<abs worktree path>", task: "<diff range + SCOPED_TEST_COMMANDS (task commands; wave: union; whole-diff: none) + ask: production-ready?>" })
@@ -166,11 +166,11 @@ Auto-selected at handoff by `writing-plans` (any wave with ≥2 tasks) when the
166
166
  **Per-wave loop:**
167
167
 
168
168
  1. **Independence check.** Parse the wave's tasks' `Files:` blocks; assert pairwise-disjoint (mechanical, mirroring `wave-file-disjointness`: `Test`/`Test` on one path is not overlap, `Test` vs another task's `Create`/`Modify` is, `Modify`/`Modify` is). Runtime-resource disjointness (DB/schema, port, fixture, external service, shared temp path) is not machine-checkable here — trust the plan's wave grouping, which `writing-plans`' D5 contract guarantees. Either kind of overlap → the wave is mis-grouped; run those tasks as sequential single-task waves and note it.
169
- 2. **Start, then fan out.** Mark every wave index `in_progress` before one parallel foreground dispatch (shape below): `implementer` per task, `context: "fresh"`, `worktree: true`. Each returns a status + a patch.
170
- 3. **Status + spec review per task.** Parse each `DONE`/`BLOCKED`/etc. (see [Implementer Status](#implementer-status)) **first**. Then **dispatch a `spec-reviewer` per accepted patch** (`DONE`, or a `DONE_WITH_CONCERNS` you proceeded with) in one parallel fan-out — `context: "fresh"`, `cwd: <this worktree>`, **no `worktree` flag** (read-only) — each passed its task text, the returned **patch diff**, the absolute spec path, and the task's `**Spec:**` anchors, plus its `**Tests:**` block and `- Test:` paths as contract — SR reads the anchored ranges itself (never inline excerpts; authority hierarchy in `./spec-reviewer-prompt.md`; anchor-less tasks are task-text-only). Review starts from the diff (its hunks carry `file:line`) and reads each touched file in full, and test execution is never the reviewer's job - in either mode (persona rule; the wave test gate in step 5 runs the wave's `SCOPED_TEST_COMMANDS`). Inline verdicts are fine at normal wave sizes; large waves use `output:` + `outputMode: "file-only"` to keep verdicts out of your context. **Re-dispatch by cause:** `BLOCKED`/`NEEDS_CONTEXT` per the [Implementer Status](#implementer-status) matrix; a **spec gap** re-dispatches the implementer (fresh, `worktree: true`) carrying the prior patch + the reviewer's findings, the new patch superseding the old at step 4. Loop until accepted + spec ✅, within [Fix-Loop Rounds](#fix-loop-rounds), same as sequential.
171
- 4. **Integrate.** `git -C <worktree> apply` each task's patch sequentially onto HEAD. Apply fails = textual conflict → drop that task, finish the rest, re-run the dropped task sequentially on the updated HEAD.
169
+ 2. **Start, then fan out.** Record `WAVE_BASE_SHA` with `git -C <worktree> rev-parse HEAD` before dispatch; keep it fixed through the wave's commit. Mark every wave index `in_progress` before one parallel foreground dispatch (shape below): `implementer` per task, `context: "fresh"`, `worktree: true`. Each returns a status + a patch.
170
+ 3. **Status + spec review per task.** Parse each `DONE`/`BLOCKED`/etc. (see [Implementer Status](#implementer-status)) **first**. Then **dispatch a `spec-reviewer` per accepted patch** (`DONE`, or a `DONE_WITH_CONCERNS` you proceeded with) in one parallel fan-out - `context: "fresh"`, each task's `cwd` = its [Spec-review snapshot](#spec-review-snapshots), **no `worktree` flag** (read-only) - each passed its task text, the returned **patch diff**, the absolute spec path, and the task's `**Spec:**` anchors, plus its `**Tests:**` block and `- Test:` paths as contract — SR reads the anchored ranges itself (never inline excerpts; authority hierarchy in `./spec-reviewer-prompt.md`; anchor-less tasks are task-text-only). Review starts from the diff (its hunks carry `file:line`) and reads each touched file in full, and test execution is never the reviewer's job - in either mode (persona rule; the wave test gate in step 5 runs the wave's `SCOPED_TEST_COMMANDS`). Inline verdicts are fine at normal wave sizes; large waves use `output:` + `outputMode: "file-only"` to keep verdicts out of your context. **Re-dispatch by cause:** `BLOCKED`/`NEEDS_CONTEXT` per the [Implementer Status](#implementer-status) matrix; a **spec gap** re-dispatches the implementer (fresh, `worktree: true`) carrying the prior patch + the reviewer's findings, the new patch superseding the old at step 4. Loop until accepted + spec ✅, within [Fix-Loop Rounds](#fix-loop-rounds), same as sequential.
171
+ 4. **Integrate.** Run `git -C <worktree> apply --index <patch-path>` for each accepted task's patch sequentially. This stages additions as well as tracked changes for review. Apply fails = textual conflict → drop that task, finish the rest, re-run the dropped task sequentially on the updated HEAD.
172
172
  5. **Test gate.** Run the wave's `SCOPED_TEST_COMMANDS` (union of its tasks' `Tests:` commands) on the integrated tree as `(cd "<worktree>" && <command>)` for each command — the full verification set is the verify phase's job, run once. Failure = semantic conflict or bug → re-run the offending task sequentially, else fix per [When a Subagent Fails](#when-a-subagent-fails).
173
- 6. **Quality review.** CR binds to the wave: exactly one **initial** code-review dispatch per code-touching wave, over the integrated wave diff - never per task within a wave, never batched across waves. Subsequent dispatches within the wave are re-reviews triggered only by findings, per Fix-Loop Rounds. Pass the wave's `SCOPED_TEST_COMMANDS`. Code-quality review on the integrated wave diff; when issue-bearing, re-dispatch the implementer per `/skill:requesting-code-review` Fix rounds and re-review, to ✅ within [Fix-Loop Rounds](#fix-loop-rounds), same as sequential. Skip for doc-only waves (SR-only per the commit precondition below).
173
+ 6. **Quality review.** CR binds to the wave: exactly one **initial** code-review dispatch per code-touching wave, over the integrated wave diff - never per task within a wave, never batched across waves. Subsequent dispatches within the wave are re-reviews triggered only by findings, per Fix-Loop Rounds. Pass the wave's `SCOPED_TEST_COMMANDS`, `BASE_SHA: <WAVE_BASE_SHA>`, and `HEAD_SHA: WORKTREE` per `code-quality-reviewer-prompt.md`; the review reads the staged and unstaged integrated diff, not a commit range. On findings, fix and re-review per `/skill:requesting-code-review` and [Fix-Loop Rounds](#fix-loop-rounds). For in-place repairs, stage the reviewed deliverables before dispatch and override the implementer commit step: leave the fix uncommitted and unstaged. After it returns, run `git -C <worktree> add -N -- <new-fix-paths>` for new deliverables, capture `git -C <worktree> diff --binary` as `## Fix delta`, then stage the fix's deliverable paths before SR/CR re-review. Preserve `WAVE_BASE_SHA` and `HEAD_SHA: WORKTREE` through every re-review and escalated in-place repair. Skip CR for doc-only waves (SR-only per the commit precondition below).
174
174
  7. **Commit and complete the wave.** After the gate passes, commit with `git -C <worktree> add ... && git -C <worktree> commit ...`, then mark all of its existing indices `complete`. Leaves a clean tree; the next wave's children branch from this commit and so see the integrated work.
175
175
 
176
176
  **Two-stage review is preserved:** spec review per task (pre-integration, dispatched `spec-reviewer` — not inline), quality review per wave (post-integration). A wave commit requires one spec-review verdict per accepted task, plus one code-review verdict on the integrated diff for waves that touch code. A doc-only wave (every task's `Files:` block documentation-only, per `writing-plans`' Wave Grouping) is SR-only — the CR gate does not apply.
@@ -179,7 +179,7 @@ Auto-selected at handoff by `writing-plans` (any wave with ≥2 tasks) when the
179
179
 
180
180
  **Caveat:** each task must be independently runnable and verifiable in a fresh worktree — no reliance on uncommitted local state. `pi-cohort` symlinks `node_modules`; repos needing other per-worktree setup must account for it.
181
181
 
182
- Pass the worktree's absolute path as the top-level `cwd` on every dispatch; rule and rationale: `dispatching-parallel-agents` "pi-cohort Integration".
182
+ Pass the implementation worktree's absolute path as top-level `cwd`; override each per-patch SR task's `cwd` with its snapshot path, without `worktree: true`. Rule and rationale for editing dispatches: `dispatching-parallel-agents` "pi-cohort Integration".
183
183
 
184
184
  ```bash
185
185
  REPORT_DIR=$(mktemp -d)
@@ -202,6 +202,26 @@ subagent({
202
202
 
203
203
  For the fan-out + worktree + patch-integration + conflict mechanics, see `dispatching-parallel-agents`.
204
204
 
205
+ ## Spec-review snapshots
206
+
207
+ Materialize each accepted patch before its pre-integration spec review, including replacement patches on re-review. Keep the implementation worktree unchanged; pi-cohort removes its worker checkouts before returning patches.
208
+
209
+ Substitute shell-quoted literals for the implementation worktree, the recorded `WAVE_BASE_SHA`, and the absolute patch path. Run this block once per patch:
210
+
211
+ <!-- spec-review-snapshot-shell -->
212
+ ```bash
213
+ SR_ROOT={{WORKTREE}}
214
+ SR_BASE={{BASE_SHA}}
215
+ SR_PATCH={{PATCH_PATH}}
216
+ SR_DIR=$(mktemp -d) || exit 1
217
+ SR_TREE="$SR_DIR/tree"
218
+ git -C "$SR_ROOT" worktree add --detach "$SR_TREE" "$SR_BASE" || exit 1
219
+ git -C "$SR_TREE" apply --index "$SR_PATCH" || exit 1
220
+ printf 'snapshot: %s\n' "$SR_TREE"
221
+ ```
222
+
223
+ Use the printed snapshot path as that spec-review task's `cwd` and whole-file read root. Keep the authoritative spec's absolute path in the implementation worktree. Pass the patch diff as before; the snapshot contains this task's changed and added files, with deleted files absent. Read deleted files from `WAVE_BASE_SHA` when the review needs their prior contents. Dispatch read-only, with no `worktree` flag. A failed command or missing snapshot path stops dispatch; retain the failed snapshot for diagnosis. After a terminal review report is saved, remove its snapshot with `git -C <implementation-worktree> worktree remove --force <snapshot-path>`. Recreate from the replacement patch for each pre-integration re-review. Post-integration SR reviews the implementation worktree directly.
224
+
205
225
  ## When a Subagent Fails
206
226
 
207
227
  **You are the orchestrator. You do NOT write code.**
@@ -12,8 +12,8 @@ Dispatch a subagent with the code-reviewer template:
12
12
 
13
13
  DESCRIPTION: [task summary, from implementer's report]
14
14
  PLAN_OR_REQUIREMENTS: Task N from [plan-file]
15
- BASE_SHA: [commit before task]
16
- HEAD_SHA: [current commit]
15
+ BASE_SHA: [commit before task; wave: WAVE_BASE_SHA recorded before worker dispatch]
16
+ HEAD_SHA: [current commit; integrated uncommitted wave: the literal WORKTREE, including re-reviews]
17
17
  SCOPED_TEST_COMMANDS: [the consuming task's Tests: commands; wave reviews: the union of the wave's tasks' Tests: commands; `none` for the whole-diff verify-phase review]
18
18
  ```
19
19
 
@@ -33,7 +33,7 @@ If no spec exists, recommend `/skill:brainstorming` and await the user's explici
33
33
  ## Boundaries
34
34
 
35
35
  - Read code and docs: yes
36
- - Write the plan to the sibling `plans/` dir of the spec: yes
36
+ - Dispatch `plan-writer` to write the plan to the sibling `plans/` dir of the spec: yes; the main loop never writes it
37
37
  - Edit or create any other files: no
38
38
  - Write implementation code: never inside this skill. After Self-Review + `phase_tracker` complete, auto-invoke `/skill:subagent-driven-development` to execute.
39
39
  - Land the plan on `main`: no — the plan commit goes on the worktree branch (same branch as the spec)
@@ -50,25 +50,36 @@ If yes, decompose into separate plans, executed in order, and state the split an
50
50
 
51
51
  Otherwise one plan. Service, contract, or schema count is not a split signal - one concern routinely spans several. The concern test itself lives in `../shape-ticket/reference/split-axes.md` (resolve the path against this skill's own directory) and was applied upstream at spec time; plans do not re-litigate it. A single plan should land in one PR worth of work.
52
52
 
53
- ## Recon (mandatory)
53
+ ## Author the plan
54
54
 
55
- Before mapping files, dispatch a scout to build the implementation map. Foreground, no announcement, no user interaction. The task template below is fixed — fill exactly **one** variable, the absolute spec path; compose nothing else:
55
+ The main loop never writes the plan. One fresh `plan-writer` child does the recon, writes the plan at the plan path, runs `plan_check` itself, and repairs its own findings; the parent dispatches it, runs the stamping `plan_check`, and reads the finished plan once. Foreground, no announcement, no user interaction.
56
56
 
57
- ```
58
- subagent({ agent: "scout", context: "fresh", async: false, cwd: "<abs worktree path>",
59
- phase: "plan-recon", output: "<abs plan path — same filename as the spec, per the table above>",
60
- task: <the fixed template below, with the spec path filled> })
61
- ```
57
+ 1. The Overview already ran `phase_tracker({ action: "start", phase: "plan" })`, or skipped it because `plan` was `in_progress`. Set the substep: `phase_tracker({ action: "substep", phase: "plan", substep: "plan-write" })`.
58
+ 2. Resolve five absolute paths: the worktree (the `using-git-worktrees` Step 4 value), the spec, the plan (table above), this `SKILL.md`, and `reference/plan-contract.md` beside it - the last two from the loaded skill's path in the command's skill envelope or the absolute path used to read it.
59
+ 3. Entry branch. A plan file already at the plan path in a flow restored by `/skill:gauntlet-resume` is checked before anything overwrites it: skip to step 5. Otherwise dispatch:
60
+
61
+ ```
62
+ subagent({ agent: "plan-writer", context: "fresh", async: false, cwd: "<abs worktree path>",
63
+ phase: "plan-write",
64
+ acceptance: { level: "none", reason: "the parent plan_check owns acceptance" },
65
+ task: <the fixed template below, with the five paths filled> })
66
+ ```
67
+
68
+ > Write the implementation plan for the approved spec. Worktree: `<abs worktree path>`. Spec: `<abs spec path>`. Plan path: `<abs plan path>`. Plan skill: `<abs path to this SKILL.md>`. Plan contract: `<abs path to reference/plan-contract.md>`.
62
69
 
63
- > Recon for implementation planning. Read the approved spec at `<abs spec path>` - it is the single source of truth for what is being built. Also read the repo's `AGENTS.md` and, if present, the gauntlet overrides file (checked in order: `.pi/gauntlet-overrides.md`, `gauntlet-overrides.md`, `doc/gauntlet-overrides.md` at the repo root) for conventions. Build an implementation map for the spec: exact file paths to create/modify/delete; existing call sites and tests with line ranges; conventions and patterns the plan must match; the project's test runner and the exact scoped-invocation form for running individual test files (derived from the repo's Makefile/bin/config and the overrides file); the style/lint and auto-format commands in both scoped per-file form and repo-wide form (same sources); separately, the full-suite verification entrypoint and whether it bundles style/format checks. When the overrides file has a `## Happy path` section, copy its table verbatim into your report under a `## Happy path` heading. Flag any spec claim that contradicts the code. Read-only recon: do not edit any file except writing your report to your output path. Start your report with the line `# CONTEXT DRAFT - NOT A PLAN - fully replaced at plan-writing` verbatim. End with an "Open questions that matter for the plan" section. Compact handoff, not a dump.
70
+ No `output:`, no `model:` (`subagents.agentOverrides.plan-writer.model` applies when set, else the child inherits the main loop). The `acceptance` line is required: without it pi-cohort appends a structured-report contract that the child's one-line reply would fail. Fill the five paths and, when step 6 or an amendment supplies one, append a `Findings:` or `Amend:` block after the template; compose nothing else.
71
+ 4. The dispatch errored, returned an async handle, or left the plan path missing or empty: stop and report. There is no parent-authored fallback.
72
+ 5. `plan_check({ planPath: "<abs plan path>" })` in the parent. This is the stamping call; run it whichever line the child replied with.
73
+ 6. Branch on the pair (child reply, parent check):
74
+ - `PLAN WRITTEN` + `PASS` -> step 7.
75
+ - `OPEN QUESTIONS` + any result -> present the plan's `## Open Questions` section to the user and wait (the Open-Questions halt; no `plan_tracker` init before the answers). After the answers, re-dispatch per step 3 with the answers as the `Findings:` block, then step 5.
76
+ - `PLAN WRITTEN` + `FAIL` -> re-dispatch per step 3 with the verbatim `FAIL (...)` output as the `Findings:` block, then step 5. Once per verbatim FAIL output: the same FAIL a second time goes to the user as an open question (the FAIL lines, verbatim), as an exhausted finding does.
77
+ - No child reply (the step 3 entry branch on a restored plan) -> read the result as if the reply were `OPEN QUESTIONS` when the plan carries an `## Open Questions` section, else `PLAN WRITTEN`, and take that reply's branch above; a `FAIL` re-dispatch overwrites the restored plan with a repaired one.
78
+ 7. Clear the substep (`phase_tracker({ action: "substep", phase: "plan", substep: null })`). Read the plan once, then `## Execution Handoff` as written below: `phase_tracker({ action: "complete", phase: "plan" })`, `plan_tracker({ action: "init", ... })` from the `W<k>: <title>` list, mode selection from the wave structure, `/skill:subagent-driven-development`.
64
79
 
65
- Consumption:
80
+ The parent holds no run id and never calls `resume` or `status`; every dispatch here is `async: false`. Re-entering this section without a restored plan overwrites whatever the plan path holds - a committed prior plan (recoverable from git history) or an uncommitted one (destroyed); re-planning is a deliberate overwrite. An amendment of the approved spec after the plan exists re-enters at step 3 with an `Amend:` block (brainstorming's `reference/amendment-surface.md` section 5 owns that call).
66
81
 
67
- - `Read` the draft at the plan path before mapping files — the on-disk copy is canonical (prune-proof, restart-proof).
68
- - The draft is a helper, not a fence: verify load-bearing claims against real code before planning against them.
69
- - Plan-writing is a **full-replacement `write`** at the same path. Re-read the draft in the same turn immediately before the overwrite. After the write, confirm line 1 is no longer the draft marker before self-review and handoff.
70
- - **Degradation:** the scout failed when its task errored or the output file is missing or empty. Proceed from your own reads with a one-line note; never block. If the file is absent, no marker check applies at the overwrite.
71
- - **Re-entry:** re-dispatching recon overwrites whatever the plan path holds — including a committed prior plan (recoverable from git history) or an uncommitted one (destroyed). Re-planning is a deliberate overwrite.
82
+ The sections from `## File Structure` through `## Self-Review` are the plan contract: `plan-writer` reads and executes them; the main loop never does.
72
83
 
73
84
  ## File Structure
74
85
 
@@ -76,7 +87,7 @@ Consumption:
76
87
 
77
88
  List the files this implementation will create, modify, or delete. Group by component. This forces the design decisions out of the task list and into a single review surface.
78
89
 
79
- **Happy-path row selection.** When the recon report carries a `## Happy path` table, match the union of every task's `Files:` paths against the table's `Paths` prefixes (a path is inside a row when it starts with one of the row's prefixes). Two or more non-`cross-cutting` rows matched, or a path inside the `cross-cutting` row's own `Paths` and inside no other row's -> the `cross-cutting` row (no such row -> no line); this takes precedence. Otherwise exactly one non-`cross-cutting` row matched -> that row. No row matched, or no table -> no line. The selected row becomes the header's `**Happy path:**` line (below); the parent re-derives the row from the real diff at verify time, so this is the plan-time default and the `plan_check` anchor.
90
+ **Happy-path row selection.** When the overrides file carries a `## Happy path` table, match the union of every task's `Files:` paths against the table's `Paths` prefixes (a path is inside a row when it starts with one of the row's prefixes). Two or more non-`cross-cutting` rows matched, or a path inside the `cross-cutting` row's own `Paths` and inside no other row's -> the `cross-cutting` row (no such row -> no line); this takes precedence. Otherwise exactly one non-`cross-cutting` row matched -> that row. No row matched, or no table -> no line. The selected row becomes the header's `**Happy path:**` line (below); the parent re-derives the row from the real diff at verify time, so this is the plan-time default and the `plan_check` anchor.
80
91
 
81
92
  ```markdown
82
93
  ## Files
@@ -157,7 +168,7 @@ Each step is **one action, 2-5 minutes**:
157
168
 
158
169
  **Spec:** `<project>/doc/specs/<same-filename-as-this-plan>.md`
159
170
 
160
- **Verification:** `<full verification command set — tests + style + format; a single bundling entrypoint, or the listed individual commands; from the recon report / project overrides>` - in a repo with per-service verification commands, list the command of every service the change affects (its own files or code it depends on; a repo-wide shared path such as root config, a lockfile, or a shared library affects every dependent service), taking the per-service commands from the overrides file or AGENTS.md when recon reports a single entrypoint
171
+ **Verification:** `<full verification command set - tests + style + format; a single bundling entrypoint, or the listed individual commands; from your recon / the overrides file>` - in a repo with per-service verification commands, list the command of every service the change affects (its own files or code it depends on; a repo-wide shared path such as root config, a lockfile, or a shared library affects every dependent service), taking the per-service commands from the overrides file or AGENTS.md when recon reports a single entrypoint
161
172
  **Happy path:** <row label> - `<command from the selected row>` (~<Timeout from the row>)
162
173
 
163
174
  **Ticket:** `<ticket-id>` (omit if none)
@@ -259,9 +270,9 @@ If a decision is genuinely open, put it in an explicit **Open Questions** sectio
259
270
 
260
271
  ## Self-Review (Before Handoff)
261
272
 
262
- After drafting the plan and before announcing it complete, run the deterministic checker, then the judgment checks yourself — not a subagent dispatch.
273
+ The plan-writer runs these before replying: the deterministic checker, then the judgment checks.
263
274
 
264
- - **Deterministic checker.** Run `plan_check({ planPath: "<abs plan path>" })` on the saved plan. Assess and fix every finding yourself (no human involvement), then re-run until it passes — a pass writes the execution stamp that implement-start verifies mechanically. If the same finding survives 3 fix rounds, convert it to an explicit Open Question and stop (the pre-existing Open-Questions halt, resolved by the human in-session — not a new gate). Findings are defined in [reference/plan-contract.md](reference/plan-contract.md).
275
+ - **Deterministic checker.** Run `plan_check({ planPath: "<abs plan path>" })` on the saved plan. Assess and fix every finding yourself (no human involvement), then re-run until it passes - a pass in the child validates the plan; the parent's own `plan_check` writes the execution stamp that implement-start verifies mechanically. If the same finding survives 3 fix rounds, convert it to an explicit Open Question and stop (the pre-existing Open-Questions halt, resolved by the human in-session - not a new gate). Findings are defined in [reference/plan-contract.md](reference/plan-contract.md).
265
276
  - **Code-vs-anchor sanity.** For each task-owned requirement row, re-read the anchored spec lines and confirm the owner tasks' bodies do what they say - mechanism present, not just the quoted literal. For each `Verification` row, confirm the header command exercises the anchored requirement. Fix the task, don't annotate.
266
277
  - **Type / API consistency.** Function signatures and field names that appear in multiple tasks must match exactly. The plan is its own contract — internal contradictions surface as bugs during execution.
267
278
  - **Test contract.** Every code task's `Tests:` commands are anchored to its `Test:` path(s); `none:` only where no tests apply; a spec-named seam appears as `via:`, a spec-named fixture path as `Create:`. Prefer the existing test file for the behavior as `Test:`; a new test file is declared as both `Create:` and `Test:`.
@@ -286,7 +297,7 @@ Fix what this review finds before handoff.
286
297
 
287
298
  ## Execution Handoff
288
299
 
289
- After saving the plan, mark the planning phase complete, then initialize `plan_tracker` once with every plan task in wave order. Name each entry `W<k>: <title>` using its containing wave and task title. This is the execution list: do not initialize it again on continuation.
300
+ After the parent `plan_check` passes and the plan has been read once (`## Author the plan` step 7), mark the planning phase complete, then initialize `plan_tracker` once with every plan task in wave order. Name each entry `W<k>: <title>` using its containing wave and task title. This is the execution list: do not initialize it again on continuation.
290
301
 
291
302
  ```
292
303
  phase_tracker({ action: "complete", phase: "plan" })
@@ -309,6 +320,7 @@ Auto-invoke `/skill:subagent-driven-development` in this session. Do not wait fo
309
320
  - Two tasks reference the same function with different signatures
310
321
  - Self-review skipped
311
322
  - About to start executing the plan yourself
323
+ - A `scout` recon dispatch, or a parent `write`/`edit` on the plan path
312
324
 
313
325
  ## Project overrides
314
326