pi-gauntlet 4.13.0 → 4.13.2

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,11 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## v4.13.2 - 2026-08-21
4
+
5
+ - Review scoping and wave density (execution-latency pass): `spec-reviewer` never executes tests/linters/type-checkers and excludes code-quality opinions (CR's gate); `implementer`/`code-reviewer` run only dispatch-supplied `SCOPED_TEST_COMMANDS` (threaded through every SDD dispatch point, prompt templates, `requesting-code-review`, and the conformance fix loop; TDD skill gates tasks on scoped commands, full suite at verify); `writing-plans` defaults to dense waves - single-task waves require a named-blocker `Solo:` line; SDD binds exactly one initial code review per code-touching wave; `conformance-reviewer` gaps require an origin locator + verbatim quote (quotable notes only, malformed origin triggers a fresh audit; `UNAUTHORIZED` unchanged).
6
+
7
+ ## v4.13.1 - 2026-08-20
8
+
9
+ - `gatekeep-pr`: dense output protocol - stable append-only finding IDs (`P#` blocking fixes, `L#` requirement/doc drift, `C#` verdict-neutral thread replies, `F#` owned follow-ups), bare-verb action vocabulary with selection grammar (`all`, ranges, exclusions), normative per-cell course table (one `[recommended]`, custom last, push and merge never bundled), fix-wave execution (file-disjoint batches, parallel edit-only implementers, one gate/re-review/push per wave), output done-check for external payloads with a `## comms style` overrides hook.
10
+
3
11
  ## v4.13.0 - 2026-08-20
4
12
 
5
13
  - Claude Code plugin marketplace (gh-11): new `.claude-plugin/marketplace.json` exposes exactly three tracker-facing skills (`shape-ticket`, `gatekeep-pr`, `check-delivery`) to Claude Code in place - plugin `gauntlet`, marketplace `pi-gauntlet`, consumer setting `"enabledPlugins": {"gauntlet@pi-gauntlet": true}`. Exclusivity rests on `source: "./"` + `strict: false` + specific subdir paths; `"agents": []` suppresses the default `agents/` scan so pi personas never register as CC agents. Zero skill-body edits; the directory is excluded from the npm tarball and never read by pi.
6
14
  - `scripts/ci.mjs`: new marketplace guard - identity pins (`gauntlet`@`pi-gauntlet`), source/strict/agents assertions, scan-leak entry ban, allowlist path + frontmatter existence checks, bundle-local `.md` reference integrity for allowlisted skills, and a negative npm-pack assertion for `.claude-plugin/`.
7
15
  - README: new "Use from Claude Code" section - consumer settings snippet, register/install/enable distinction, `CLAUDE.md` symlink advice, folder-trust gotcha, and an 11-step smoke-test cookbook.
8
-
9
16
  ## v4.12.2 - 2026-08-19
10
17
 
11
18
  - New `skills/shape-ticket/reference/split-axes.md`: the shared split test for tickets and specs - identity test (same precipitating failure / mooted outcome = one concern), user-observable outcome test, closed axis list with pass/fail examples, Never-axis list (fix location, service/repo/layer/team, "keep tickets small"), discovery-conversion exemption, fail-closed release-timing precondition gated on a documented `## Deployment` overrides section.
package/README.md CHANGED
@@ -69,7 +69,7 @@ Everything between gate 1 and gate 2 - task breakdown, implementation, both revi
69
69
 
70
70
  pi-gauntlet ships three kinds of pieces, layered on top of pi-cohort's dispatch:
71
71
 
72
- - **16 skills** - the workflow logic. Thirteen activate automatically when pi sees the matching kind of task, and each one gates the next: `brainstorming`, `writing-plans`, `roasting-the-spec`, `test-driven-development`, `subagent-driven-development`, `dispatching-parallel-agents`, `verification-before-completion`, `systematic-debugging`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `writing-skills`. Three more are explicit-invocation-only (`disable-model-invocation: true`): `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 - run it with `/skill:shape-ticket`. `gatekeep-pr` is consent-gated pre-merge verification of a PR against its issue - read-only gathering, running the project's verification command, a rubric-based review, then a deterministic authorship-aware menu; nothing mutates (fixes, pushes, reviews, merges) until you pick a row - run it with `/skill:gatekeep-pr <pr>`. `check-delivery` 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>`.
72
+ - **16 skills** - the workflow logic. Thirteen activate automatically when pi sees the matching kind of task, and each one gates the next: `brainstorming`, `writing-plans`, `roasting-the-spec`, `test-driven-development`, `subagent-driven-development`, `dispatching-parallel-agents`, `verification-before-completion`, `systematic-debugging`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `writing-skills`. Three more are explicit-invocation-only (`disable-model-invocation: true`): `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 - run it with `/skill:shape-ticket`. `gatekeep-pr` is consent-gated pre-merge verification of a PR against its issue - read-only gathering, running the project's verification command, a rubric-based review, then a deterministic authorship-aware menu with stable finding IDs (P#/L#/C#/F#) and numbered pre-composed courses (fixes execute as a single parallel-safe wave: one gate run, one re-review, one push); nothing mutates (fixes, pushes, reviews, merges) until you pick a row - run it with `/skill:gatekeep-pr <pr>`. `check-delivery` 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>`.
73
73
  - **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.
74
74
  - **3 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. See [doc/configuration.md](./doc/configuration.md) for the settings each one reads.
75
75
 
@@ -362,7 +362,9 @@ customization lives in two places, never in the wrapper itself:
362
362
 
363
363
  An existing `## verification-before-completion` overrides section is an accepted
364
364
  equivalent source for the verification command only; all other PR-gate keys
365
- still live under `## PR gate`.
365
+ still live under `## PR gate`. A `## comms style` section in the same overrides
366
+ file extends gatekeep-pr's output done-check (rules applied to review bodies,
367
+ replies, tracker comments, and commit subjects before posting).
366
368
 
367
369
  Anything a wrapper skill contains beyond trigger phrases is misplaced - move it to
368
370
  `REVIEW.md` or the overrides file instead.
@@ -383,6 +385,10 @@ Nothing committed beyond what's shipped. Changes land via [CHANGELOG.md](./CHANG
383
385
 
384
386
  pi-gauntlet's skill methodology was inspired by [obra/superpowers](https://github.com/obra/superpowers) (MIT, Copyright (c) 2025 Jesse Vincent), by way of [coctostan/pi-superpowers-plus](https://github.com/coctostan/pi-superpowers-plus). The pi runtime integration, enforced phase gates, multi-model spec council, conformance-review gate, and parallel execution waves are pi-gauntlet's own. Thanks to the upstream authors; their copyright is preserved in [`LICENSE`](./LICENSE).
385
387
 
388
+ ## Contributing
389
+
390
+ See [CONTRIBUTING.md](CONTRIBUTING.md) - issues follow a Context / Problem / Idea / Acceptance Criteria template; PRs run the [pi-gauntlet](https://github.com/jjuraszek/pi-gauntlet) workflow (one-liners exempt from ceremony, never from keeping docs truthful).
391
+
386
392
  ## Support
387
393
 
388
394
  [Buy me a coffee](https://buymeacoffee.com/jjurasszek) if this saves you time.
@@ -9,7 +9,7 @@ systemPromptMode: replace
9
9
  completionGuard: false
10
10
  ---
11
11
 
12
- You are a code reviewer. You find issues before they ship. You **do not edit code**. You may run read-only verification commands (tests, type-checks, linters) and quote their actual output.
12
+ You are a code reviewer. You find issues before they ship. You **do not edit code**. You may run the verification commands your dispatch supplies (`SCOPED_TEST_COMMANDS`, read-only) and quote their actual output. Run ONLY those. Never run a repo-wide suite, linter, or type-checker on your own initiative. Dispatch carries no commands: say so in your report; run nothing.
13
13
 
14
14
  ## Review priorities, in order
15
15
 
@@ -30,7 +30,7 @@ Work flows `origin (prompt + spec) → plan → code/doc`. Every hop is lossy: a
30
30
 
31
31
  ## Process
32
32
 
33
- 1. **Reconstruct the origin.** Read the spec and the verbatim original prompt. Extract a flat list of every requirement: explicit acceptance criteria / spec clauses **+** implicit notes (ticket body, comments) **+** any requirement stated inline in the prompt but never written into the spec.
33
+ 1. **Reconstruct the origin.** Read the spec and the verbatim original prompt. Extract a flat list of every requirement: explicit acceptance criteria / spec clauses **+** quotable notes - written sentences you can quote verbatim (ticket body, comments); never derived inferences **+** any requirement stated inline in the prompt but never written into the spec.
34
34
  2. **Check origin drift.** If the spec and the prompt/ticket disagree, do **not** absorb it silently. A deviation recorded in the spec → spec wins (it was review-gated). An *unrecorded* divergence → the spec silently dropped or altered a requirement = a conformance failure to report.
35
35
  3. **Map each requirement to the deliverable.** Read the diff (code **and** docs) yourself — do not trust any summary. For each requirement, find where it is satisfied and cite real `file:line` evidence. Run read-only checks (tests, grep) when they confirm a behavior; quote actual output.
36
36
  4. **Flag the unrequested.** Anything shipped that no requirement in the origin asked for = `UNAUTHORIZED` (scope creep), even if it looks useful. Do not negotiate scope with yourself.
@@ -43,10 +43,10 @@ Conformance verdict: CONFORMS | GAPS
43
43
  Confidence: low | medium | high (based on how much you could verify from the diff + checks)
44
44
 
45
45
  Requirement coverage:
46
- - [DELIVERED] R1: <requirement> — origin: <spec §/prompt line> — evidence: file.ts:42
47
- - [PARTIAL] G1: <requirement> — origin: <…> — evidence: file.ts:80 — missing: <what's absent>
48
- - [MISSING] G2: <requirement> — origin: <…> — searched: <where you looked>
49
- - [DRIFTED] G3: delivered <X>, origin asked <Y> — origin: <…> — evidence: file.ts:120
46
+ - [DELIVERED] R1: <requirement> — origin: spec "Section 3" - "<quoted clause>" — evidence: file.ts:42
47
+ - [PARTIAL] G1: <requirement> — origin: spec "Section 3" - "<quoted clause>" — evidence: file.ts:80 — missing: <what's absent>
48
+ - [MISSING] G2: <requirement> — origin: spec "Section 3" - "<quoted clause>" — searched: <where you looked>
49
+ - [DRIFTED] G3: delivered <X>, origin asked <Y> — origin: spec "Section 3" - "<quoted clause>" — evidence: file.ts:120
50
50
  - [UNAUTHORIZED] G4: <behavior with no origin requirement> — origin: none (scope creep) — evidence: file.ts:200
51
51
 
52
52
  Origin drift (spec vs prompt/ticket):
@@ -71,7 +71,7 @@ block for any gap that closed, reusing its original `Gn` id.
71
71
  ```
72
72
  G1:
73
73
  verdict: MISSING
74
- origin: spec "Section 3 / Fix dispatch"
74
+ origin: spec "Section 3 / Fix dispatch" - "implementer task not dispatched for gaps marked fix"
75
75
  evidence: absent
76
76
  remediation: implementer task not dispatched for gaps marked fix
77
77
  touched-files: skills/verification-before-completion/reference/conformance-check.md
@@ -132,6 +132,7 @@ serial waves — identical to planned-execution wave grouping. Runtime-resource
132
132
  - **Read-only. Never edit.** You audit; you do not fix.
133
133
  - **Propose, do not dispose.** For each gap you may suggest a one-line remediation *direction*, but you do **not** decide the disposition - the orchestrator auto-applies `fix` gaps and defers `accept`/`rescope`/`UNAUTHORIZED` to the user at the finish gate. Never present a fix as a decision you made.
134
134
  - **Evidence or it didn't happen.** Cite a real `file:line` for every DELIVERED/PARTIAL. If you cannot, downgrade the row to MISSING.
135
+ - **Origin quote or it isn't a gap.** Every non-UNAUTHORIZED gap's `origin` carries a locator AND a verbatim quote: `origin: <file/section, 'prompt', or 'ticket'> - "<quoted clause>"` (truncate long clauses with `[...]` as long as the fragment uniquely identifies the clause). No quotable origin clause = no gap. Do not derive implicit requirements. Do not flag wording preferences. A deviation recorded in the spec wins over an older origin value (Process step 2); report it only if unrecorded.
135
136
  - **Spec is canonical; the prompt catches what the spec dropped; the ticket is fallback only** when no spec exists.
136
137
  - **Do not absorb origin drift silently** — flag every spec↔prompt/ticket disagreement.
137
138
  - **Quote real command output** if you ran checks. Do not paraphrase from memory.
@@ -16,17 +16,18 @@ You are an implementation specialist. You execute an approved plan using strict
16
16
 
17
17
  1. **RED** — Write or identify a failing test that pins down the desired behavior. Run it. Confirm it fails for the right reason (not a typo, not an import error).
18
18
  2. **GREEN** — Write the minimum code that makes the test pass. Run it.
19
- 3. **REFACTOR** — Clean up without changing behavior. Run the tests the task declares (its `Test:` files and stated commands).
19
+ 3. **REFACTOR** — Clean up without changing behavior. Run the tests the task declares the dispatch-supplied `SCOPED_TEST_COMMANDS`.
20
20
 
21
21
  ## Three-scenario TDD
22
22
 
23
23
  - **New feature** → full RED → GREEN → REFACTOR.
24
24
  - **Modifying tested code** → run the existing tests first, modify, re-run; add new tests only for new behavior.
25
- - **Trivial change** (typo, comment, formatting) → use judgment; if any test touches the surface, run it.
25
+ - **Trivial change** (typo, comment, formatting) → use judgment; if a dispatch-supplied test command touches the surface, run it.
26
26
 
27
27
  ## Hard rules
28
28
 
29
- - Never claim a task is done without running tests and observing them pass. Quote the actual command and the actual output.
29
+ - Run ONLY the test commands your dispatch hands you (`SCOPED_TEST_COMMANDS`). Never run a repo-wide suite, linter, or type-checker on your own initiative. Dispatch carries no test commands: say so in your report; run nothing.
30
+ - Never claim a task is done without running the dispatch-supplied scoped commands and observing them pass. Quote the actual command and the actual output. If none were supplied, say so in your report - that is sufficient for DONE.
30
31
  - Never invent or paraphrase test output. If you skipped tests, say so and why.
31
32
  - If the plan does not cover a design decision, **stop and report**, do not guess. Escalate via the return value rather than improvising.
32
33
  - Stay inside the scope the parent assigned. If you notice unrelated issues, list them in your report instead of fixing them.
@@ -9,14 +9,14 @@ systemPromptMode: replace
9
9
  completionGuard: false
10
10
  ---
11
11
 
12
- You are a spec compliance reviewer. Your job is to verify that an implementation **actually does what its spec or plan says**, and nothing else. You are **skeptical of the implementer's self-report** — verify everything by reading code and running checks yourself.
12
+ You are a spec compliance reviewer. Your job is to verify that an implementation **actually does what its spec or plan says**, and nothing else. You are **skeptical of the implementer's self-report** — verify everything by reading code yourself.
13
13
 
14
14
  ## Process
15
15
 
16
16
  1. Read the spec/plan thoroughly. Extract a flat list of every requirement, acceptance criterion, and explicit non-goal.
17
17
  2. Read the implementation (diff or relevant files). Do not trust summaries.
18
18
  3. For each requirement, determine status by reading the code, not by reading the implementer's prose.
19
- 4. Run tests that exercise the spec'd behavior when available. Quote actual command and output.
19
+ 4. Never run tests, linters, or type-checkers. Your evidence is the diff and the files you read. Test execution belongs to the implementer, the code-reviewer's scoped run, and the orchestrator's gates (task/wave gate; verify phase).
20
20
  5. Flag any behavior present in the implementation that the spec did not ask for (scope creep / undocumented changes).
21
21
  6. Flag any requirement from the spec that is missing from the implementation.
22
22
 
@@ -81,5 +81,6 @@ certify a pair disjoint, mark them `conflicts` (conservative default = serial).
81
81
 
82
82
  - You are **read-only**. Never edit files.
83
83
  - Cite a real file:line for every MET/PARTIAL claim. If you cannot, downgrade to MISSING.
84
- - Quote real test output if you ran tests. Do not paraphrase.
85
84
  - Do not negotiate scope with yourself. If the spec didn't ask for it, it's scope creep, even if it looks useful.
85
+ - Never run tests, linters, or type-checkers. Read; do not execute checks.
86
+ - Do not report code-quality opinions - naming, design, complexity, test aesthetics, style. Those belong to code-reviewer. Report only spec-vs-implementation deltas.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-gauntlet",
3
- "version": "4.13.0",
3
+ "version": "4.13.2",
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",
@@ -165,10 +165,18 @@ verification command may write to the tree while the Reviewer reads it):
165
165
  claim is a blocking finding. An `unverifiable-pre-merge` claim used as merge proof
166
166
  (appears in the PR body's evidence/result/test-plan content) is blocking; stated as
167
167
  an explicit post-merge observation instead, it is a non-blocking follow-up.
168
- - **Required CI checks:** a failing or pending **required** status
169
- check withholds merge from every pre-composed course until the user explicitly
170
- dispositions it - flaky (proceed via the custom row) or real (it blocks). Non-required
171
- checks are informational, listed in Evidence only.
168
+ - **Required CI checks:** a failing **required** status check withholds merge from
169
+ every pre-composed course until the user explicitly dispositions it - flaky
170
+ (proceed via the custom row) or real (it blocks); it mints a `P#`. A **pending**
171
+ required check (still running - the normal case, not a defect) is **wait-until-
172
+ green, not dispositionable**: it mints no `P#`, is never flaky/real-dispositioned,
173
+ and the withhold auto-lifts the moment it turns green - or, if it instead fails,
174
+ converts into an undispositioned failing check with its own `P#` at that point.
175
+ While pending, the report notes it under Evidence and every merge course simply
176
+ does not render (a pending-only PR is not a blocking verdict - findings groups can
177
+ all read "None" - the recommended course falls to `stop` or `review-comment`,
178
+ never a merge course, until it resolves). Non-required checks are informational,
179
+ listed in Evidence only.
172
180
  - **Doc drift:** when the review finds committed doc drift as a **blocking** finding,
173
181
  the orchestrator applies the doc fixes itself, in the provisioned worktree (created
174
182
  or reused), as part of assessment - real edits, uncommitted, worktree-local. The
@@ -208,8 +216,8 @@ issue is linked, committed doc drift, anything the merged rubric maps to blockin
208
216
 
209
217
  **Merge preconditions** (all must hold): gate green with every blocking finding fixed,
210
218
  not deferred; `mergeable == MERGEABLE` (`UNKNOWN` after the one post-provision
211
- re-poll withholds merge, same as `CONFLICTING`); no undispositioned failing required
212
- check; evidence pasted with clean provenance; worktree clean and synced with the remote
219
+ re-poll withholds merge, same as `CONFLICTING`); no undispositioned failing or
220
+ pending required check; evidence pasted with clean provenance; worktree clean and synced with the remote
213
221
  head (fixes pushed first); explicit selection with a head compare-and-swap that
214
222
  passes. A merge selection while any precondition fails is refused, naming the failing
215
223
  precondition, and the menu re-renders - never a dead end, never a silent merge. Merge
@@ -229,14 +237,17 @@ are never bundled into one selection.
229
237
  | any | draft PR | assessment rows only; merge and approve rows absent until ready-for-review |
230
238
  | any | merged / closed | report-only; no mutation rows |
231
239
 
232
- Plus always: a final **custom row** composing the full action vocabulary (apply code
233
- fixes / push doc fixes / post review / reply to thread / merge / tracker comment when
234
- a tracker tool resolved). Rows GitHub would refuse (branch protection, missing
235
- permissions, `viewerPermission` too low) are listed as unavailable with the reason.
236
- Approving your own PR is not offered. Nothing executes until explicit selection.
240
+ The consent table above remains the single oracle for what may be offered; the
241
+ Decision rendering section defines how its rows render as actions and numbered
242
+ courses. Rows GitHub would refuse (branch protection, missing permissions,
243
+ `viewerPermission` too low) are listed as unavailable with the reason. Approving
244
+ your own PR is not offered. Nothing executes until explicit selection.
237
245
 
238
246
  ## Output
239
247
 
248
+ The rendered report is terse by design: deciding factor, evidence lines, ID'd
249
+ findings, menu. No restating diffs, no narration, no recap prose.
250
+
240
251
  ```markdown
241
252
  ## Outcome
242
253
  <one line + the deciding factor>
@@ -245,21 +256,171 @@ Approving your own PR is not offered. Nothing executes until explicit selection.
245
256
  <verbatim command + raw_tail per run; claims checked; CI rollup with required-check disposition>
246
257
 
247
258
  ## Findings (blocking)
248
- <file:line, defect, fix>
259
+ Blocking findings (P#):
260
+ P1. **<source_ref>** - <defect>. Fix: <concrete change> | Action: <disposition/what unblocks>. [code | test | spec | security | performance | quality]
261
+ Requirement/doc drift (linked issue, committed doc drift, or spec conflict):
262
+ L1. <doc-drift | spec-conflict | outdated-AC | missing-behavior> -> <action>
263
+
264
+ ## Comment-thread replies (existing discussion - verdict-neutral)
265
+ C1. <thread ref> -> <drafted reply> (already-addressed | reasonable | judgment-call)
249
266
 
250
267
  ## Non-blocking follow-ups
251
- <list, or "None">
268
+ F1. **<source_ref>** - <action>. Owner: <pr-author | tracker | human>
252
269
 
253
270
  ## Decision
254
- <the menu>
271
+ <action vocabulary + numbered courses - see Decision rendering>
255
272
 
256
273
  ## Drafted fixes / review
257
- <the exact payload to be applied or posted>
274
+ <payloads, each keyed by its finding ID>
275
+ ```
276
+
277
+ **ID rules:**
278
+
279
+ - `<source_ref>` is a `file:line` where one exists, else the disputed thing (a
280
+ quoted PR-body claim, a failing gate command, a required check name).
281
+ - **Precedence:** Phase 4 and the merged rubric decide blocking vs. follow-up (the
282
+ severity translation, AC coverage, claims, and required-check rules above); this
283
+ section only chooses **which namespace** (`P#` / `L#` / `F#`) renders that
284
+ decision. Category tags and the triage bar below never override an upstream
285
+ blocking classification - a Phase-4 Moderate is always blocking (`P#` or `L#`
286
+ per Total mapping), never demoted to `F#` by tag or by judgment call.
287
+ - **Total mapping:** every blocking element of the Verdict maps to a `P#` or `L#` -
288
+ a blocking verdict with "None" in both groups is a rendering bug. Concretely:
289
+ failed gate -> `P#` `[test]` referencing the gate command; contradicted or
290
+ merge-proof-unverifiable material claim -> `P#` `[spec]` referencing the claim;
291
+ scope creep with a linked issue -> `L#` `spec-conflict`; committed doc drift ->
292
+ `L#` `doc-drift`; `partial` AC coverage -> `L#` `outdated-AC`; `missing` AC
293
+ coverage -> `L#` `missing-behavior`. `L#` covers exactly the drift the Verdict
294
+ already blocks on (committed doc drift, AC coverage, spec conflict); it widens
295
+ nothing. Code-level spec bugs (the diff contradicts the spec) are `P#` `[spec]`;
296
+ requirement/doc mismatches (the spec or docs are stale relative to intent) are
297
+ `L#`.
298
+ - **Required checks close by disposition, not by fix:** an undispositioned failing
299
+ required check is `P#` `[test]` referencing the check name; it is never a target
300
+ of a worktree `fix`. The user's Phase-4 disposition annotates the same ID rather
301
+ than closing it outright: dispositioned **flaky** -> annotate
302
+ `(dispositioned: flaky)`; this annotation excepts the `P#` from the unfixed-blocker
303
+ set - it no longer counts against "every `P#` blocks" or the merge precondition
304
+ "every blocking finding fixed", and the merge path is Phase 4's explicit flaky
305
+ disposition via the custom row. Dispositioned **real** -> annotate
306
+ `(dispositioned: real)` and the `P#` keeps blocking until the check is green.
307
+ - **Severity is decided at triage, not by the category tag:** a finding lands in
308
+ `P#` only when it must be fixed before merge (correctness, security, material
309
+ performance trap, a convention the repo enforces); improvements that don't
310
+ change merge correctness are `F#`, whatever their category. `[quality]` on a
311
+ `P#` is a category, never a downgrade - every `P#` blocks. This triage bar governs
312
+ findings the orchestrator originates itself; it never re-triages a classification
313
+ Phase 4 already made (see Precedence above).
314
+ - `C#` replies are verdict-neutral drafts: they never block and never gate merge;
315
+ nothing posts until selected.
316
+ - `F#` items carry an owner so follow-ups don't evaporate; when no tracker tool
317
+ resolved, the report itself is their durable home.
318
+ - **IDs are append-only for the run's lifetime:** minted at first assessment,
319
+ never renumbered, never reused. A resolved finding keeps its ID annotated
320
+ `(fixed in <sha>)`; later rounds continue each namespace's sequence.
321
+ - Empty groups say "None".
322
+
323
+ "Drafted fixes / review" holds, per finding ID, the concrete edit (for `fix`), the
324
+ reviewed doc-drift edit (for `push-docs`, keyed to its `L#`), or the reply text
325
+ (for `reply`) - each keyed to its finding ID, one selection mapping 1:1 to its
326
+ payload. A posted review body is not itself a finding: it is composed at post time
327
+ from the ID'd `P#`/`L#` findings being addressed - one summary sentence, then the
328
+ numbered findings, ending on the fix or asked action - and occupies its own
329
+ non-finding slot of this section.
330
+
331
+ ## Decision rendering
332
+
333
+ `## Decision` has two parts: the action vocabulary, then the numbered courses.
334
+
335
+ **Action vocabulary** (bare verbs; availability constraints inline):
336
+
337
+ ```markdown
338
+ Actions (compose freely in the custom row):
339
+ fix <P#s|all> apply blocking fixes in worktree, re-run gate, push (in-repo PRs only)
340
+ push-docs push already-applied doc-drift edits (only when uncommitted
341
+ reviewed doc edits exist
342
+ in the worktree)
343
+ merge-squash | merge-commit (preconditions per Verdict;
344
+ never bundled with a push)
345
+ request-changes | review-comment | approve (approve: never own PR)
346
+ reply <C#s> post drafted thread replies
347
+ tracker <act> tracker action (only when a tracker tool resolved)
348
+ stop leave the PR as-is / report-only exit
258
349
  ```
259
350
 
260
- Empty lists say "None". For code fixes, "Drafted fixes / review" holds the concrete
261
- edit per finding; for reviews, the full body - one summary sentence, then numbered
262
- file:line findings, ending on the fix.
351
+ A `+ tracker <act>` suffix is available on any mutation course when a tracker tool
352
+ resolved.
353
+
354
+ **Selection grammar:** ID sets accept `all`, ranges (`P1-P4`), comma lists
355
+ (`P1,P3`), and exclusions (`all but P2`).
356
+
357
+ **Numbered courses** - a normative rendering of the consent table (never a second
358
+ offer source): per author x state cell, exactly one `[recommended]` course first,
359
+ the custom row always last. Courses are **atomic across pushes**: no course,
360
+ pre-composed or custom, bundles a push-producing action (`fix`, `push-docs`) with
361
+ `merge-*`; after a fix wave the menu re-renders with merge as row 1.
362
+
363
+ | Author | State | Courses (first = `[recommended]`) |
364
+ |---|---|---|
365
+ | you | clean / follow-ups only | 1. merge-squash; 2. merge-commit; 3. stop; 4. review-comment (post no-blockers note) |
366
+ | you | blocking | 1. fix (worktree-fixable P#s only - `all` covers only those) [+ push-docs when uncommitted doc edits exist]; 2. push-docs (alone, when doc edits exist); 3. stop; 4. review-comment (post findings). When no P# is worktree-fixable (blocking is required-check-only or L#-only), course 1 (fix) is not rendered: push-docs becomes first when doc edits exist, else stop is first |
367
+ | you | blocking, post-fix re-render (gate green, preconditions hold) | 1. merge-squash; 2. merge-commit; 3. stop; 4. review-comment |
368
+ | someone else | clean / follow-ups only | 1. approve; 2. merge-squash (offered-unrecommended); 3. review-comment (no-blockers note) |
369
+ | someone else | blocking | 1. request-changes; 2. fix all (courtesy, their branch - omitted when nothing is worktree-fixable); 3. reply <C#s> (omitted when the `C#` group is None); 4. review-comment |
370
+ | bot author | any | someone-else's rows for the same state; review actions recommended |
371
+ | any | draft | 1. request-changes / review-comment / reply <C#s> (omit the reply course when the `C#` group is None) / stop - `[recommended]` follows the same authorship rule as the non-draft cells, **except** on your own draft PR `request-changes` is never recommended (you cannot request changes on your own PR any more than you can approve it); the fallback recommendation there is `review-comment` when findings exist, else `stop`. Custom present but cannot compose `merge-*`/`approve`/`fix`/`push-docs` until ready-for-review |
372
+ | any | merged / closed | 1. stop; report-only, no other mutation courses at all; Custom present but cannot compose `merge-*`/`approve`/`fix`/`push-docs`/`request-changes`/`review-comment`/`reply`/`tracker` - nothing remains actionable |
373
+
374
+ **Fork overlay:** the consent-table fork row renders as an overlay on the authorship
375
+ cells (push/merge/fix absent; approve also dropped when the viewer authored the PR) -
376
+ it is not a distinct authorship cell. It overlays whichever authorship row above
377
+ applies (you vs. someone else), removing `fix`, `push-docs`, and `merge-*` (never
378
+ available on a fork). When you authored the fork PR, `approve` is
379
+ also dropped (never offered on your own PR) - fork|you|clean renders
380
+ `review-comment`/`stop` only; fork|you|blocking renders
381
+ `request-changes`/`review-comment`/`stop` (the someone-else courtesy fix-on-their-
382
+ branch course is also absent, since it is your own PR). A fork PR authored by someone
383
+ else uses the someone-else cells above with `fix`/`push-docs`/`merge-*` removed.
384
+
385
+ **Required-check gate on merge courses:** an undispositioned failing **or pending**
386
+ required check withholds every pre-composed course containing `merge-*` (per the
387
+ Verdict merge preconditions) - none render, whatever the author/state cell says. A
388
+ pending check mints no `P#` and is wait-until-green, not dispositionable (see Phase
389
+ 4); a failing one mints a `P#` and takes a disposition. A **flaky** disposition does
390
+ not restore merge to a pre-composed course; merge proceeds only via the custom row
391
+ naming the disposition explicitly. A **real** disposition, or an unresolved pending
392
+ check, keeps every merge course withheld until the check is green - a pending-only
393
+ render is not itself a blocking verdict (findings groups may all read "None"); the
394
+ recommended course falls to `stop` or `review-comment` in the meantime. This never
395
+ falls through to the clean cell's recommended `merge-squash` - a required-check
396
+ failure or pend means the PR is not in the clean state to begin with.
397
+
398
+ Rows a cell offers but GitHub would refuse (branch protection, missing permission)
399
+ render listed-but-unavailable with the reason. Zero mutation courses is a legal
400
+ render (merged/closed) - the menu still appears, carrying findings and `stop`.
401
+
402
+ Example render (golden fixture 1 - own PR, blocking findings including committed doc
403
+ drift, so uncommitted reviewed doc edits exist):
404
+
405
+ ```markdown
406
+ Pick one:
407
+ 1. fix all (P1-P10) + push-docs [recommended]
408
+ 2. push-docs (docs only, hold code fixes)
409
+ 3. stop (leave as-is)
410
+ 4. review-comment (post findings, act later)
411
+ 5. Custom - compose: e.g. "fix P1-P8,P10 + push-docs" or "reply C1 + tracker comment"
412
+ ```
413
+
414
+ Golden fixture 2 - the post-fix re-render after course 1's gate re-run passes:
415
+
416
+ ```markdown
417
+ Pick one:
418
+ 1. merge-squash [recommended]
419
+ 2. merge-commit
420
+ 3. stop (leave as-is)
421
+ 4. review-comment
422
+ 5. Custom
423
+ ```
263
424
 
264
425
  ## Post-selection loop
265
426
 
@@ -267,22 +428,83 @@ The menu is a state machine, not a one-shot report:
267
428
 
268
429
  1. **Compare-and-swap before every external write:** re-fetch `headRefOid`, `state`,
269
430
  `mergeable`. Any change since assessment invalidates the current state - re-sync
270
- the worktree, re-run Phase 3, re-render the menu.
271
- 2. Execute only the selected row: code fixes -> commit on the PR branch (subject
272
- names the fix), re-run the gate, push. Doc fixes -> stage + commit (subject names
273
- what is documented), re-run the gate, push. Reviews and comments -> `gh pr review`
274
- / `gh api`, non-interactive, with the drafted body.
275
- 3. After any mutation that can change readiness (fix pushed, docs pushed, PR head
276
- moved), re-run Verify + Review on the synced worktree and re-render `## Outcome`,
277
- `## Evidence`, `## Findings`, and the menu.
431
+ the worktree, re-run Phase 3, re-render the menu. **Exception:** a course's own
432
+ push updates the assessed head to the pushed SHA as part of that course's
433
+ execution - this self-inflicted head move does not invalidate the course; the
434
+ next CAS check runs against the new head on the next external write.
435
+ 2. Execute only the selected course. **Fix wave** (`fix <set>`): first filter the
436
+ selected set to worktree-fixable `P#`s - drop any `P#` closed by disposition
437
+ (an undispositioned required-check failure is never a `fix` target; a **flaky**
438
+ disposition already excepts it) - and route file-less `P#`s (a claim or a gate
439
+ command as `source_ref`, no draft touching a file) to run inline/sequentially,
440
+ never as part of a parallel file-batch.
441
+
442
+ For the remaining worktree-fixable set, batch by the **union of files each
443
+ finding's drafted edit in `## Drafted fixes / review` touches** (fallback to
444
+ the `source_ref` file only when a finding has no draft) - findings whose
445
+ drafts share a file share a batch.
446
+
447
+ **Child contract (same for 1 batch or many):** children are `implementer`
448
+ dispatches - `subagent({ agent: "implementer", context: "fresh", cwd: <PR
449
+ worktree> })`, matching Inline-first execution's persona-naming style; this is
450
+ the pi-cohort optimization path, inline is always valid per that section. The
451
+ orchestrator owns commit, gate, and push - never a child. Every dispatched
452
+ child gets `cwd` = the PR worktree, **`worktree: true` forbidden** (a separate
453
+ isolated worktree breaks the shared-tree contract - see Inline-first
454
+ execution); is **edit-only, no git commands, no verification runs**; and its
455
+ task is that batch's `P#` lines **plus the drafted edit already keyed to each
456
+ ID** in `## Drafted fixes / review` - the child applies the consented payload,
457
+ it does not re-solve the finding. Below the cutoff (<= 2 worktree-fixable findings), the orchestrator
458
+ applies inline instead of dispatching - the no-cohort path stays available at
459
+ any batch count per Inline-first execution. Above the cutoff, when more than
460
+ one batch results, dispatch the batches' children **in parallel**, all under
461
+ the same contract.
462
+
463
+ Once every dispatched/inline batch returns, the orchestrator commits the golden
464
+ course as one local commit set - the code fixes plus any already-applied
465
+ reviewed doc edits selected alongside them (one commit, or one per batch
466
+ sequentially; subjects name the fixes) - then re-runs the gate **once**. **On
467
+ green**, push **once**; gate and push are per-wave invariants, never per-fix or
468
+ per-batch. **On red**, do not push: leave the commit(s) local, re-render with
469
+ the unresolved `P#`s still open, and warn that unpushed fix commits sit in the
470
+ worktree exactly like unpushed doc edits (see Teardown). Doc fixes (`push-docs`
471
+ alone) follow the same green-gate-then-push rule: stage + commit (subject names
472
+ what is documented), re-run the gate, push only on green. Reviews, replies, and
473
+ tracker actions -> `gh pr review` / `gh api` / the tracker tool, non-interactive,
474
+ with the drafted payload for the selected IDs.
475
+ 3. After any mutation that can change readiness (fix wave pushed, docs pushed, PR
476
+ head moved), re-run the claim-check and Review on the synced worktree: claims
477
+ are re-checked against the new head and findings are re-rendered, but the
478
+ verification command itself is **not** re-executed here - step 2's gate run
479
+ already was the wave's one and only execution of it. Re-render the report:
480
+ each selected `P#`/`L#` confirmed resolved is annotated `(fixed in <sha>)`
481
+ under its original ID; unresolved ones stay open unchanged; new findings
482
+ continue the sequence. Merge, if now available, renders as row 1.
278
483
  4. Loop until the user selects merge or an explicit stop/no-action row.
279
484
 
280
485
  **Teardown:** merge success -> tear down the worktree, whether it was reused or
281
486
  created (the sync precondition guarantees no local-only work is stranded, and the
282
487
  branch is gone remotely). A non-merge stop: offer teardown of a **created** worktree
283
488
  (never autonomous; warn if unpushed doc edits would be discarded); a **reused**
284
- worktree is left as found - if unpushed doc edits remain in it, say so explicitly and
285
- let the user choose leave-or-discard.
489
+ worktree is left as found - if unpushed doc edits **or unpushed fix commits from a
490
+ red-gate hold** remain in it, say so explicitly and let the user choose
491
+ leave-or-discard.
492
+
493
+ ## Output done-check
494
+
495
+ Before posting or committing any externally persisted payload - review bodies,
496
+ thread replies, commit subjects, tracker comments - re-read it against:
497
+
498
+ - ASCII only: `-`, `...`, straight quotes.
499
+ - No headings or template scaffolding on payloads under ~150 words - bullets and
500
+ prose carry short content.
501
+ - Review findings are file:line-specific where one exists, else keyed to the
502
+ finding's `source_ref`, and end on the fix or asked action, not a recap.
503
+ - Empty sections say "None"; never invent content to fill a section.
504
+
505
+ The check governs external payloads only - the skill's own rendered report keeps
506
+ its fixed headings regardless of length. Project rules extend this list via the
507
+ overrides file - see Project overrides.
286
508
 
287
509
  ## Red flags - STOP
288
510
 
@@ -293,7 +515,27 @@ let the user choose leave-or-discard.
293
515
  - Merging around an undispositioned blocking finding or required-check failure
294
516
  - Reading configuration (rubric, verification command, or ladder sources) from the
295
517
  PR's head instead of the base branch's merge-base
518
+ - Renumbering or reusing a finding ID between menu rounds
519
+ - Presenting findings without IDs, a blocking verdict with no `P#`/`L#`, or a
520
+ `## Decision` rendered without its action vocabulary
521
+ - Treating `[quality]` or `[performance]` as a downgrade signal on a `P#` - only
522
+ an explicit Phase-4 flaky disposition excepts a required-check `P#` from the
523
+ unfixed-blocker set, never a category tag
524
+ - A course (pre-composed or custom) bundling a push-producing action with
525
+ `merge-*`
526
+ - A pre-composed course, or a custom row, composing an action the overlay or the
527
+ cell lists as unavailable
528
+ - Batching a file-less `P#` (a claim or a gate command as `source_ref`, no draft touching a file)
529
+ into a parallel dispatch - a claim `P#` with a drafted file edit is
530
+ worktree-fixable and may batch - dispatching parallel implementers over
531
+ batches that share a file, or letting a fix-wave child run git commands or a
532
+ verification pass in the shared worktree, or dispatching a fix-wave child with
533
+ `worktree: true`
534
+ - A second execution of the verification command, a second push, or pushing fix
535
+ commits after a red gate, within one fix wave - re-running Verify/Review to
536
+ re-confirm claims and annotate IDs (step 3) is not a second gate execution
537
+ - Posting or committing an external payload without the output done-check
296
538
 
297
539
  ## Project overrides
298
540
 
299
- If a gauntlet overrides file exists - checked in order: `.pi/gauntlet-overrides.md`, `<repo root>/gauntlet-overrides.md`, `<repo root>/doc/gauntlet-overrides.md`; first found wins - read it. Any sections relevant to this skill - by name match, by topic (routing, verification, worktrees, etc.), or by workflow convention - override or extend the instructions above. Project-local `AGENTS.md` is already in context - check it for project-specific routing tables, service paths, and verification commands.
541
+ If a gauntlet overrides file exists - checked in order: `.pi/gauntlet-overrides.md`, `<repo root>/gauntlet-overrides.md`, `<repo root>/doc/gauntlet-overrides.md`; first found wins - read it. Any sections relevant to this skill - by name match, by topic (routing, verification, worktrees, etc.), or by workflow convention - override or extend the instructions above. Project-local `AGENTS.md` is already in context - check it for project-specific routing tables, service paths, and verification commands. A `## comms style` section in the overrides file extends the output done-check with project rules.
@@ -49,6 +49,7 @@ subagent({ agent: "code-reviewer", task: "... filled template ..." })
49
49
  - `{BASE_SHA}` - Starting commit
50
50
  - `{HEAD_SHA}` - Ending commit
51
51
  - `{DESCRIPTION}` - Brief summary
52
+ - `{SCOPED_TEST_COMMANDS}` - the scoped verification commands the reviewer may run, or `none`
52
53
 
53
54
  **3. Act on feedback:**
54
55
  - Fix Critical issues immediately
@@ -73,6 +74,7 @@ HEAD_SHA=$(git rev-parse HEAD)
73
74
  PLAN_OR_REQUIREMENTS: Task 2 from doc/plans/deployment-plan.md
74
75
  BASE_SHA: a7981ec
75
76
  HEAD_SHA: 3df7661
77
+ SCOPED_TEST_COMMANDS: none (whole-branch review; orchestrator gate owns execution)
76
78
  DESCRIPTION: Added verifyIndex() and repairIndex() with 4 issue types
77
79
 
78
80
  [Subagent returns]:
@@ -4,7 +4,8 @@ You are reviewing code changes for production readiness.
4
4
 
5
5
  ## Boundaries
6
6
 
7
- - **Read code, run tests, run git commands: yes**
7
+ - **Read code, run git commands: yes**
8
+ - **Run tests: ONLY the commands listed under SCOPED_TEST_COMMANDS below; if `none`, run nothing**
8
9
  - **Edit, create, or delete any source files: NO**
9
10
  - **Apply fixes or refactors: NO**
10
11
  - You are a reviewer. Your output is a written report. You never touch the code.
@@ -17,6 +18,8 @@ You are reviewing code changes for production readiness.
17
18
  5. Flag plan deviations explicitly
18
19
  6. Assess production readiness
19
20
 
21
+ SCOPED_TEST_COMMANDS: {SCOPED_TEST_COMMANDS}
22
+
20
23
  ## Calibration
21
24
 
22
25
  Before writing the report:
@@ -63,7 +66,7 @@ git diff {BASE_SHA}..{HEAD_SHA}
63
66
  - Tests actually test logic (not mocks)?
64
67
  - Edge cases covered?
65
68
  - Integration tests where needed?
66
- - All tests passing?
69
+ - Scoped test commands passing (quote actual output; if `none` supplied, note the orchestrator gate owns execution)?
67
70
 
68
71
  **Requirements:**
69
72
  - All plan requirements met?
@@ -53,11 +53,11 @@ Before the first task, enter the implement phase: `phase_tracker({ action: "star
53
53
 
54
54
  For each task in `plan_tracker`:
55
55
 
56
- 1. **Dispatch implementer.** Pass the full task text + scene-setting context. Don't make the subagent re-read the plan.
56
+ 1. **Dispatch implementer.** Pass the full task text + scene-setting context + the task's plan-declared test commands as `SCOPED_TEST_COMMANDS` (or `none`). Don't make the subagent re-read the plan.
57
57
  2. **Handle implementer status** (see below).
58
58
  3. **Dispatch spec reviewer.** Verify the diff matches the spec — nothing missing, nothing extra.
59
59
  4. If spec reviewer finds gaps → re-dispatch implementer to fix → re-review. Loop until ✅, within [Fix-Loop Rounds](#fix-loop-rounds).
60
- 5. **Dispatch code-quality reviewer.** Only after spec is ✅. Skip for doc-only tasks (every file in the task's `Files:` block documentation-only) — SR-only, same exemption as doc-only waves.
60
+ 5. **Dispatch code-quality reviewer.** Only after spec is ✅. Skip for doc-only tasks (every file in the task's `Files:` block documentation-only) — SR-only, same exemption as doc-only waves. Pass `SCOPED_TEST_COMMANDS` = the task's plan-declared commands.
61
61
  6. If quality reviewer finds issues → re-dispatch implementer → re-review. Loop until ✅, within [Fix-Loop Rounds](#fix-loop-rounds).
62
62
  7. Mark task complete in `plan_tracker`.
63
63
 
@@ -71,6 +71,8 @@ One rule governs both review loops - spec-compliance and code-quality - in seque
71
71
 
72
72
  **Fix fan-out.** When the triggering review's `Parallel-safe:` line certifies a `disjoint` group of ≥ 2 findings, dispatch that fix round 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 plan-declared commands, and one re-review of the integrated delta follows.
73
73
 
74
+ Every fix re-dispatch (implementer) and code-review re-review carries the consuming task/wave's `SCOPED_TEST_COMMANDS`; spec-reviewer re-reviews carry none - SR never executes.
75
+
74
76
  **The sequence.** Each review that finds issues is a decision point: read the `TRAJECTORY:` line before dispatching anything (review 1 has no line - on issues, dispatch fix 1). Any clean review ends the loop.
75
77
 
76
78
  1. **Review 1** (first review - no sentinel). Issues -> dispatch fix 1.
@@ -128,13 +130,13 @@ When in doubt, default. Don't downgrade reviewers — false negatives are expens
128
130
 
129
131
  ```ts
130
132
  // implementer
131
- subagent({ agent: "implementer", task: "<task text + context + status protocol>" })
133
+ subagent({ agent: "implementer", task: "<task text + context + SCOPED_TEST_COMMANDS + status protocol>" })
132
134
 
133
135
  // spec compliance
134
136
  subagent({ agent: "spec-reviewer", task: "<diff range + spec excerpt + ask: does this match?>" })
135
137
 
136
138
  // code quality
137
- subagent({ agent: "code-reviewer", task: "<diff range + ask: production-ready?>" })
139
+ subagent({ agent: "code-reviewer", task: "<diff range + SCOPED_TEST_COMMANDS (task commands; wave: union; whole-diff: none) + ask: production-ready?>" })
138
140
 
139
141
  // closing-loop conformance (origin vs deliverable) — its OWN dispatch, never fused with code quality
140
142
  // model: call gauntlet_setting({ key: "closureReview" }) first; use the returned model (omit model: if undefined to inherit) and maxFixRounds
@@ -167,10 +169,10 @@ Auto-selected at handoff by `writing-plans` (any wave with ≥2 tasks) when the
167
169
 
168
170
  1. **Independence check.** Parse the wave's tasks' `Files:` blocks; assert pairwise-disjoint (mechanical). 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
171
  2. **Fan out.** One parallel 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**, and the absolute spec path. Review is **diff-based**: the diff's hunks carry `file:line`, and test execution is not the reviewer's job here (the wave test gate in step 5 runs the wave's declared 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.
172
+ 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**, and the absolute spec path. Review is **diff-based**: the diff's hunks carry `file:line`, 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 declared 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
173
  4. **Integrate.** `git 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.
172
174
  5. **Test gate.** Run the union of the wave's tasks' declared test commands on the integrated tree — 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.** Code-quality review on the integrated wave diff; loop fixes to ✅ within [Fix-Loop Rounds](#fix-loop-rounds), same as sequential. Skip for doc-only waves (SR-only per the commit precondition below).
175
+ 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 `SCOPED_TEST_COMMANDS` = the union of the wave's tasks' declared commands. Code-quality review on the integrated wave diff; loop fixes to ✅ within [Fix-Loop Rounds](#fix-loop-rounds), same as sequential. Skip for doc-only waves (SR-only per the commit precondition below).
174
176
  7. **Commit the wave.** Leaves a clean tree; the next wave's children branch from this commit and so see the integrated work.
175
177
 
176
178
  **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.
@@ -189,8 +191,8 @@ subagent({
189
191
  concurrency: 4, // default; cap = wave size
190
192
  tasks: [
191
193
  // do NOT set per-task cwd under worktree:true — it must equal the top-level cwd or the run errors
192
- { agent: "implementer", task: "<task text + owned files + status protocol>", output: "wave1-task1.md" },
193
- { agent: "implementer", task: "<task text + owned files + status protocol>", output: "wave1-task2.md" },
194
+ { agent: "implementer", task: "<task text + owned files + SCOPED_TEST_COMMANDS + status protocol>", output: "wave1-task1.md" },
195
+ { agent: "implementer", task: "<task text + owned files + SCOPED_TEST_COMMANDS + status protocol>", output: "wave1-task2.md" },
194
196
  ],
195
197
  })
196
198
  ```
@@ -215,7 +217,7 @@ For the fan-out + worktree + patch-integration + conflict mechanics, see `dispat
215
217
  ## After All Tasks Complete
216
218
 
217
219
  0. Call `phase_tracker({ action: "start", phase: "verify" })`. (The `implement` phase was started at execution start and auto-completes from `plan_tracker` once all tasks are done; this flow runs its own verify gate instead of `/skill:verification-before-completion`, so it must mark verify itself.)
218
- 1. **Run the whole-diff code review.** Dispatch `/skill:requesting-code-review` against the worktree's full diff vs `main` (already covered in [The Process](#the-process) step "After all tasks"). Address Critical and Moderate findings before handoff. (Consumers wanting an in-flow project-specific audit re-add it as an explicit step in the gauntlet overrides file (see Project overrides), or run `/self-audit` manually.)
220
+ 1. **Run the whole-diff code review.** Dispatch `/skill:requesting-code-review` against the worktree's full diff vs `main` (already covered in [The Process](#the-process) step "After all tasks"). Address Critical and Moderate findings before handoff. (Consumers wanting an in-flow project-specific audit re-add it as an explicit step in the gauntlet overrides file (see Project overrides), or run `/self-audit` manually.) Pass `SCOPED_TEST_COMMANDS: none` - the verify phase's full run (step 2) is the orchestrator's.
219
221
  2. **Run the full verification set — once.** Read the plan header's `**Verification:**` line and run it: tests + style + format (a single bundling entrypoint, or the listed individual commands). Green output is the fresh evidence verify requires; this is the only full run before conformance — task and wave gates ran scoped commands only. After conformance fix rounds land, re-run the set before re-dispatching the gate.
220
222
  3. **Close the loop — conformance check.** The review in step 1 is plan-vs-code (single-step); it inherits any requirement the plan already dropped. Before marking verify complete, dispatch a fresh-context **`conformance-reviewer`** — its **own** dispatch, never fused into the step-1 review — to confront the deliverable (code **and** docs) against the *origin* — the spec **and** the original prompt — per `verification-before-completion/reference/conformance-check.md`. Pass the spec path, the verbatim original prompt, and the full diff. Follow that reference for the partition rule, concern decomposition, and fix-loop mechanics; do not reimplement them here. The fix loop may drive `plan_tracker` to surface fix-wave progress (task naming and lifecycle per conformance-check.md's fix loop / the Fix fan-out Progress rule); it never calls `phase_tracker`. Call `phase_tracker({ action: "complete", phase: "verify" })` only when the reference says the handoff is durably complete: either a current `CONFORMS` result, or a current `## Closure / conformance` inventory whose carried-open concerns all come from valid deferred gaps, including `recommended: fix` gaps carried open because a declared precondition made the fix loop unavailable (`maxFixRounds: 0`, or no eligible named-branch worktree). A started positive-cap fix loop that blocks, fails, or exhausts its rounds with an open `fix` gap is escalation, not completion; on escalation, do not complete verify, stop and report.
221
223
  4. Summarize what was implemented (tasks completed, files changed, test counts, code-review verdict). Emit the `## Closure / conformance` block exactly as defined in `verification-before-completion/reference/conformance-check.md`: it must open with the two-line sentinel (`status: CONFORMS (0 open)` or `status: GAPS (N open)`, then `audited-base: <full HEAD SHA>`), then carry the exact durable concern schema by reference with no renamed or reformatted fields. `finishing-a-development-branch` Step 3.5 consumes that block verbatim.
@@ -238,6 +240,8 @@ For the fan-out + worktree + patch-integration + conflict mechanics, see `dispat
238
240
  - Starting on main without explicit user consent
239
241
  - Dispatching `code-reviewer` before every one of the wave's spec-review verdicts has landed (including fusing SR+CR into one parallel call)
240
242
  - Dispatching fixes sequentially on a clean HEAD despite a ≥ 2-ID `disjoint` group in the review's `Parallel-safe:` line
243
+ - Dispatching `code-reviewer` per task inside a wave (CR binds to the integrated wave diff)
244
+ - Dispatching an implementer or code-reviewer without a `SCOPED_TEST_COMMANDS` value (commands or `none`)
241
245
  - About to run the full verification entrypoint during the implement phase — task and wave gates run scoped, plan-declared commands only; the full set belongs to verify
242
246
 
243
247
  ## Integration
@@ -14,6 +14,7 @@ Dispatch a subagent with the code-reviewer template:
14
14
  PLAN_OR_REQUIREMENTS: Task N from [plan-file]
15
15
  BASE_SHA: [commit before task]
16
16
  HEAD_SHA: [current commit]
17
+ SCOPED_TEST_COMMANDS: [the consuming task's plan-declared commands; wave reviews: the union of the wave's tasks' declared commands; `none` for the whole-diff verify-phase review]
17
18
  ```
18
19
 
19
20
  **In addition to standard code quality concerns, the reviewer should check:**
@@ -31,13 +31,19 @@ Dispatch a subagent with this prompt:
31
31
  Once you're clear on requirements:
32
32
  1. Implement exactly what the task specifies
33
33
  2. Write tests (following TDD — failing test first for production code)
34
- 3. Verify implementation works
34
+ 3. Verify with the commands under SCOPED_TEST_COMMANDS (if `none`, state that)
35
35
  4. Commit your work
36
36
  5. Self-review (see below)
37
37
  6. Report back
38
38
 
39
39
  Work from: [directory]
40
40
 
41
+ SCOPED_TEST_COMMANDS: [the task's plan-declared test commands, verbatim | none]
42
+
43
+ Run ONLY these commands for verification. Never run a repo-wide suite,
44
+ linter, or type-checker. If the value is `none`, run nothing and say so
45
+ in your report.
46
+
41
47
  **While you work:** If you encounter something unexpected or unclear, **ask questions**.
42
48
  It's always OK to pause and clarify. Don't guess or make assumptions.
43
49
 
@@ -38,6 +38,8 @@ Dispatch a subagent with this prompt:
38
38
 
39
39
  - **Read code and compare to spec: yes**
40
40
  - **Edit, create, or delete any files: NO**
41
+ - **Run tests, linters, or type-checkers: NO.** Never run tests, linters, or type-checkers. Your evidence is the diff and the files you read.
42
+ - **Code-quality opinions (naming, design, complexity, test aesthetics, style): NO.** Those belong to code-reviewer. Report only spec-vs-implementation deltas.
41
43
  - You are a reviewer. Your output is a written report listing what matches and what doesn't.
42
44
  - If you find issues, describe them — do NOT fix them.
43
45
 
@@ -117,11 +117,11 @@ Don't add features, refactor other code, or "improve" beyond what the test requi
117
117
 
118
118
  Run the test. Confirm:
119
119
  - New test passes
120
- - All other tests still pass
120
+ - The task's scoped commands pass (full-suite verification belongs to the verify phase)
121
121
  - Output is pristine (no errors, no warnings)
122
122
 
123
123
  **Test fails?** Fix code, not test.
124
- **Other tests fail?** Fix now — don't move on with broken tests.
124
+ **Scoped commands fail?** Fix now — don't move on with broken tests.
125
125
 
126
126
  ### REFACTOR — Clean Up
127
127
 
@@ -176,7 +176,7 @@ Before marking work complete:
176
176
  - [ ] Watched each test fail before implementing
177
177
  - [ ] Each test failed for expected reason (feature missing, not typo)
178
178
  - [ ] Wrote minimal code to pass each test
179
- - [ ] All tests pass
179
+ - [ ] The task's scoped commands pass (full suite belongs to the verify phase)
180
180
  - [ ] Output pristine (no errors, warnings)
181
181
  - [ ] Tests use real code (mocks only if unavoidable)
182
182
  - [ ] Edge cases and errors covered
@@ -76,8 +76,9 @@ Default: **1 requirement source = 1 spec = code covering every requirement.**
76
76
  The requirement source is whatever sits at the top of the priority table — a
77
77
  ticket if there is one, otherwise the spec + original prompt. No ticket is fine;
78
78
  spec + prompt is a first-class source, not a degraded one. "Every requirement" =
79
- explicit acceptance criteria / spec clauses **+** implicit notes (ticket body,
80
- comments, or inline in the prompt). Source and solution must end in sync.
79
+ explicit acceptance criteria / spec clauses **+** quotable notes (written
80
+ sentences in the ticket body, comments, or inline in the prompt - quotable
81
+ verbatim, never derived inferences). Source and solution must end in sync.
81
82
 
82
83
  Multi-spec effort → allowed **only if the spec explicitly says** it covers a
83
84
  defined subset and names the deferred requirements. Silent partial coverage = failure.
@@ -152,7 +153,9 @@ Per round:
152
153
  group of ≥ 2 gaps (per the report's `Parallel-safe:` line) fixes in one parallel
153
154
  dispatch — one `implementer` per gap (fresh context, `worktree: true`, `cwd` =
154
155
  the conformance worktree, task = the gap block verbatim with `touched-files` as
155
- the ownership boundary); `conflicts` pairs serialize. Gaps outside any ≥ 2-ID
156
+ the ownership boundary). The dispatch adds `SCOPED_TEST_COMMANDS` to the gap
157
+ block: the gap-relevant plan-declared commands, or `none` (the round's test
158
+ gate owns execution). `conflicts` pairs serialize. Gaps outside any ≥ 2-ID
156
159
  `disjoint` group run sequentially as before. Then dispatch `spec-reviewer` per
157
160
  gap on the gap-block reference contract below. Task lifecycle: mark `in_progress` at
158
161
  dispatch; `complete` is deferred until the gap's patch is successfully
@@ -167,7 +170,7 @@ Per round:
167
170
  integrated changes. A `BLOCKED`/`NEEDS_CONTEXT` return surfaces to the user.
168
171
  4. **Test gate** on the integrated tree, using the project's canonical test
169
172
  command. A failure re-enters the failure-handling rules above.
170
- 5. **`code-reviewer` once** on the round's cumulative fix delta (not per gap).
173
+ 5. **`code-reviewer` once** on the round's cumulative fix delta (not per gap), with `SCOPED_TEST_COMMANDS` = the round's gap-relevant commands, or `none` (the round's test gate owns execution).
171
174
  6. **Re-audit**: re-dispatch `conformance-reviewer` over the fixes **plus** the
172
175
  regression guard (any prior-`DELIVERED` requirement whose `evidence` file
173
176
  the fix diff touched). Pass the full prior conformance report (every row,
@@ -269,7 +272,9 @@ is an unmet-delivery fact, not
269
272
  an external blocker** — never relabel missing implementation evidence as a
270
273
  blocker. A malformed structured reviewer gap block — missing its stable `Gn`
271
274
  label or any required field (`verdict`, `origin`, `evidence`, `remediation`,
272
- `touched-files`, `touched-resources`, `recommended`) — triggers a **fresh
275
+ `touched-files`, `touched-resources`, `recommended`) — or, for any non-`UNAUTHORIZED`
276
+ gap (including re-audit blocks), an `origin` lacking a locator or a nonempty
277
+ quoted fragment — triggers a **fresh
273
278
  audit**; a complete structured reviewer gap block does not — the orchestrator
274
279
  decomposes it or emits the indivisible fallback.
275
280
 
@@ -411,7 +416,7 @@ must map each token to its titled concern or gap before asking for input.
411
416
  ```text
412
417
  G1 - Source-image validation is incomplete
413
418
  verdict: PARTIAL
414
- origin: <requirement source and clause>
419
+ origin: <requirement source and clause> - "<quoted clause>"
415
420
  evidence: <current file:line or observed state>
416
421
  blocker: <specific blocker, or none>
417
422
  touched-files: <paths or unknown>
@@ -421,7 +426,7 @@ G1 - Source-image validation is incomplete
421
426
  G1/C1 - End-to-end OCR output has not been validated
422
427
  unresolved: <plain statement of the concern>
423
428
  impact: <why it matters to the current workflow>
424
- origin: <requirement source and clause, narrowed from the gap origin; or none (scope creep) for UNAUTHORIZED>
429
+ origin: <requirement source and clause, narrowed from the gap origin> - "<quoted clause>"; or none (scope creep) for UNAUTHORIZED
425
430
  remediation: <concern-scoped remediation action>
426
431
  evidence: <concern-specific evidence or blocker>
427
432
  touched-files: <concern-scoped paths, narrowed from the gap; or unknown>
@@ -474,7 +479,8 @@ branch integration options.
474
479
  ## Checklist
475
480
 
476
481
  - [ ] Located canonical requirements (spec → prompt → ticket fallback)
477
- - [ ] Enumerated every requirement: explicit ACs / spec clauses + implicit notes + inline prompt reqs
482
+ - [ ] Enumerated every requirement: explicit ACs / spec clauses + quotable notes + inline prompt reqs (verbatim-quotable only)
483
+ - [ ] Every non-UNAUTHORIZED gap's origin carries locator + verbatim quote
478
484
  - [ ] Checked spec ↔ prompt/ticket drift; reconciled any divergence
479
485
  - [ ] Each requirement mapped to where it's satisfied (code/doc) + evidence
480
486
  - [ ] Multi-spec? Subset declared in spec; deferred ACs noted as out of scope
@@ -128,7 +128,8 @@ If you can't list the files, the spec isn't ready. Send it back to `/skill:brain
128
128
  Group tasks into **waves** so the executor can parallelize independent work (see `subagent-driven-development` Parallel-Wave Mode). A wave is a maximal set of tasks that (a) have no ordering dependency on each other, (b) own **pairwise-disjoint files**, and (c) contend on **no shared mutable runtime resource** (same DB/schema, port, fixture file, external service, shared temp path).
129
129
 
130
130
  - Tasks nest under `## Wave N — <label>` headers; `### Task N` headers sit inside a wave.
131
- - A wave with one task is legal (runs sequentially). A pure dependency chain yields one task per waveno parallelism, which is correct.
131
+ - Group independent tasks into the same wave by default. A wave with one task is legal **only with a named-blocker justification**: a body line directly under the `## Wave N <label>` header, `Solo: <reason>`, where the reason names the blocking task/wave, the contended runtime resource, or `lone remaining task` (reserved for the genuinely final unmatched task; doc-only trailing waves qualify). Category-only justifications ("dependency" with no named task) do not satisfy the rule.
132
+ - A pure dependency chain yields one task per wave — no parallelism, which is correct; each such wave carries its `Solo:` line naming the prior-wave dependency.
132
133
  - Each wave after the first states its dependency on prior waves.
133
134
 
134
135
  **File-ownership contract.** The per-task `**Files:**` block *is* the ownership declaration — no new syntax. Rule: **within a wave, the union of every task's declared paths must be pairwise disjoint.** Globs are allowed for `Modify` when exact paths are unknown, but must not overlap another same-wave task's paths. A task that must touch another's file belongs in a later wave.
@@ -152,6 +153,8 @@ Parallel-safe: Tasks 1–3 own disjoint files (see each task's Files block).
152
153
 
153
154
  ## Wave 2 — Wire-up
154
155
 
156
+ Solo: Task 4 depends on Wave 1 Task 1's API (named-blocker justification).
157
+
155
158
  Depends on Wave 1: Task 4 consumes the API introduced by Task 1.
156
159
 
157
160
  ### Task 4: ...
@@ -269,6 +272,7 @@ After drafting the plan and before announcing it complete, run three checks your
269
272
  - **Placeholder scan.** Grep the doc for `TODO`, `TBD`, `xxx`, `[fill in]`, `<example>`, `etc.`, "probably", "something like". Resolve or convert each into an explicit Open Question.
270
273
  - **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.
271
274
  - **Wave disjointness.** For every multi-task wave, confirm the tasks' `Files:` sets are pairwise disjoint **and** that no two tasks contend on a shared mutable runtime resource (DB/schema, port, fixture, external service, shared temp path). Either kind of overlap = mis-grouped wave; split or re-order before handoff.
275
+ - **Solo-wave justification.** Every single-task wave carries a `Solo:` line naming its specific blocker. A solo wave without one is mis-grouped or under-justified — merge it or justify it before handoff.
272
276
  - **Scoped-test coverage.** Every code-touching wave declares at least one scoped test command; only doc-only waves may have none.
273
277
  - **Header-only entrypoint.** The full verification entrypoint appears only in the plan header's `**Verification:**` line. Grep the task body for the header's command string — expect zero hits.
274
278