pi-gauntlet 5.0.2 → 5.0.4
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 +11 -0
- package/README.md +5 -3
- package/agents/spec-reviewer.md +16 -13
- package/package.json +1 -1
- package/skills/gatekeep-pr/SKILL.md +63 -44
- package/skills/gatekeep-pr/verification-brief.md +73 -21
- package/skills/subagent-driven-development/SKILL.md +2 -2
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +6 -0
- package/skills/writing-plans/SKILL.md +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v5.0.4 - 2026-08-26
|
|
4
|
+
|
|
5
|
+
- `spec-reviewer` (persona + dispatch template, lockstep): decomposes its anchored spec lines into atomic clauses with one verdict row per clause (`Per-clause status:`, `C-n`); plan/task code snippets declared non-authoritative for review (a diff matching a snippet never proves compliance); reads every diff-touched file in full, not just hunks, reporting any file it could not exhaust.
|
|
6
|
+
- `subagent-driven-development`: reviewer framing reworded to match (change-satisfies-spec, whole-file reads); dispatch shape unchanged.
|
|
7
|
+
- `writing-plans`: extraction re-walk ("every normative clause has a row"), a code-vs-anchor sanity Self-Review bullet, and a one-line declaration of plan code's review-time standing.
|
|
8
|
+
- README: reworked "The problem" section.
|
|
9
|
+
|
|
10
|
+
## v5.0.3 - 2026-08-25
|
|
11
|
+
|
|
12
|
+
- gatekeep-pr defaults to green exact-head CI evidence (gh-14): normative six-path "Evidence resolution" table at the top of verification-brief.md Section B (opt-out / failed-CI / CI-sufficient / pending / fallback / stale-head, top-down); the local verification command runs only on fallback/opt-out rows; source-discriminated Verifier output (`source: ci|local`) with the exact CI claim form `verified by CI: <check name(s)> succeeded on <sha> (run <url>)`; any blocking conclusion in the resolved set mints a `P#` with a third disposition `CI-infrastructure-broken` that triggers the fallback run; two new `## PR gate` keys `local verification: always` and `ci checks:`. Spec: `doc/specs/2026-09-06-gh-14-gatekeep-ci-evidence-default.md` (partially supersedes `doc/specs/2026-08-18-gh-9-gatekeep-pr-skill.md`, verification-evidence scope only).
|
|
13
|
+
|
|
3
14
|
## v5.0.2 - 2026-08-24
|
|
4
15
|
|
|
5
16
|
- Plan fidelity (gh-13): `writing-plans` task template gains a required spec-anchor line (`**Spec:** <path> § "<heading>" L<start>-L<end>`), a verbatim-quote rule for exact-string requirements, an extraction-first `## Spec coverage` table, and four mechanical self-review checks (quote integrity spec->task, anchor resolution, three-leg table closure, paths exist). `subagent-driven-development` spec-reviewer contract becomes spec+task: dispatches pass the spec path + the task's anchors in both modes and the Dispatch sketch, the spec wins every dispute, task-vs-spec divergence is unconditionally flagged with the spec literal, and `spec-reviewer-prompt.md` gains a `## Spec Authority` section plus `plan transcription gap` / `out-of-anchor-slice` finding labels. Spec: `doc/specs/2026-08-23-gh-13-plan-fidelity-anchors.md` (partially supersedes `doc/specs/2026-07-06-parallel-wave-spec-reviewer-dispatch.md`, SR contract scope only).
|
package/README.md
CHANGED
|
@@ -10,9 +10,9 @@ The gated workflow for the [pi coding agent](https://github.com/earendil-works/p
|
|
|
10
10
|
|
|
11
11
|
## The problem
|
|
12
12
|
|
|
13
|
-
Point an agent at a task and let it loop until done - that's the easy 5%.
|
|
13
|
+
Point an agent at a task and let it loop until done - that's the easy 5%. LLMs are more a compressed library with a sampler on top than an independent mind: they produce fluent analysis faster than humans can audit it, and humans can't efficiently unravel that flood of output from the authenticity of a sound idea. So the agent quietly drifts from what you asked, and by the time you look, the diff is too big to honestly review.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
It *is* a model problem - one-shotting an idea makes a great demo, not a product. But no better model fixes it on its own: Cursor, Claude Code, and Codex all drift the same way on long tasks, because nothing in a bare loop confronts output against *original* intent, and a model cannot audit itself - the same blind spot that wrote the bug will happily approve it. A weak generator needs a strong harness - because fluency is not correctness.
|
|
16
16
|
|
|
17
17
|
## Why pi-gauntlet exists
|
|
18
18
|
|
|
@@ -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. Twelve 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`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `writing-skills`. Four 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,
|
|
72
|
+
- **16 skills** - the workflow logic. Twelve 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`, `requesting-code-review`, `receiving-code-review`, `using-git-worktrees`, `finishing-a-development-branch`, `writing-skills`. Four 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, verification evidence resolved CI-first (green checks on the exact assessed head count as evidence; the project's verification command runs only as fallback), 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>`. `chase-bug` is human-only bug triage: read-only root-cause discovery to an evidenced verdict menu (real bug -> ticket/brainstorm/respond; five negative verdicts), then a gated response to the reporter - it never fixes during triage - run it with `/skill:chase-bug`.
|
|
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
|
|
|
@@ -355,6 +355,8 @@ customization lives in two places, never in the wrapper itself:
|
|
|
355
355
|
- verification command: <command> # required unless documented elsewhere
|
|
356
356
|
- timeout minutes: 15 # optional; default 15
|
|
357
357
|
- requires credentials: false # optional; true => skill reports "not run" as missing evidence
|
|
358
|
+
- local verification: always # optional; default (absent) = CI-first; "always" forces the local run even when exact-head CI is green
|
|
359
|
+
- ci checks: <comma-separated check names> # optional; narrows which checks count as evidence; absent = all checks on the assessed head
|
|
358
360
|
- worktree wrapper: <command> # optional
|
|
359
361
|
- issue fetch: <command with <ref> placeholder> # optional, replaces gh issue view
|
|
360
362
|
- merge policy: squash | merge-commit # optional
|
package/agents/spec-reviewer.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-reviewer
|
|
3
|
-
description: Independently verifies an implementation against its spec
|
|
3
|
+
description: Independently verifies an implementation against its spec, clause by clause. Trusts the spec and the code, not the implementer's self-report.
|
|
4
4
|
tools: read, grep, find, ls, bash
|
|
5
5
|
defaultContext: fresh
|
|
6
6
|
inheritProjectContext: true
|
|
@@ -9,29 +9,31 @@ 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
|
|
12
|
+
You are a spec compliance reviewer. Your job is to verify that an implementation **actually does what its spec 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
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
<!-- clause decomposition / snippet non-authority / whole-file reads: keep in lockstep with skills/subagent-driven-development/spec-reviewer-prompt.md — change them together or not at all -->
|
|
17
|
+
|
|
18
|
+
1. Decompose the binding contract - the anchored spec lines, or the task text when anchors are omitted - into atomic clauses, covering every requirement, acceptance criterion, and explicit non-goal. Each independently checkable statement is one clause; a sentence listing three requirements yields three clauses. Every clause gets a verdict row.
|
|
19
|
+
2. Read the implementation. Do not trust summaries. Read every diff-touched file in full, not just the hunks - continue in chunks until the file is exhausted; if you cannot exhaust it, say so in the report instead of treating the file as covered. A statement elsewhere in a touched file that the change now contradicts is in scope.
|
|
20
|
+
3. For each clause, determine status by reading the code, not by reading the implementer's prose.
|
|
19
21
|
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
22
|
5. Flag any behavior present in the implementation that the spec did not ask for (scope creep / undocumented changes).
|
|
21
|
-
6. Flag any
|
|
23
|
+
6. Flag any clause from the spec that is missing from the implementation.
|
|
22
24
|
|
|
23
25
|
## Output format
|
|
24
26
|
|
|
25
27
|
```
|
|
26
|
-
Per-
|
|
27
|
-
- [MET]
|
|
28
|
-
- [PARTIAL] F1:
|
|
28
|
+
Per-clause status:
|
|
29
|
+
- [MET] C-1: short clause text — evidence: file.ts:42
|
|
30
|
+
- [PARTIAL] F1: C-2: ... — evidence: file.ts:80; missing: ...
|
|
29
31
|
touched-files: file.ts
|
|
30
32
|
touched-resources: none
|
|
31
|
-
- [MISSING] F2:
|
|
33
|
+
- [MISSING] F2: C-3: ... — searched: <where>
|
|
32
34
|
touched-files: file.ts, other.ts
|
|
33
35
|
touched-resources: none
|
|
34
|
-
- [OUT_OF_SCOPE]
|
|
36
|
+
- [OUT_OF_SCOPE] C-4: ... — flagged as non-goal in spec
|
|
35
37
|
|
|
36
38
|
Scope creep (not in spec, but present):
|
|
37
39
|
- F3: widget.ts:120 — short description
|
|
@@ -39,7 +41,7 @@ Scope creep (not in spec, but present):
|
|
|
39
41
|
touched-resources: none
|
|
40
42
|
|
|
41
43
|
Missing from implementation:
|
|
42
|
-
- F2:
|
|
44
|
+
- F2: C-3 — short description
|
|
43
45
|
|
|
44
46
|
Verdict: COMPLIANT | NEEDS_REWORK | OUT_OF_SCOPE_CHANGES
|
|
45
47
|
Confidence: low | medium | high
|
|
@@ -49,7 +51,7 @@ Parallel-safe: F1,F3 disjoint; F2 conflicts F1 (both touch file.ts)
|
|
|
49
51
|
|
|
50
52
|
## Finding IDs and fix-concurrency certification
|
|
51
53
|
|
|
52
|
-
Label every finding (each `PARTIAL`/`MISSING`
|
|
54
|
+
Label every finding (each `PARTIAL`/`MISSING` clause, each scope-creep
|
|
53
55
|
item) with a globally unique ID `F1..Fn`, numbered across the whole report
|
|
54
56
|
(no restart per section). Each finding carries:
|
|
55
57
|
|
|
@@ -82,5 +84,6 @@ certify a pair disjoint, mark them `conflicts` (conservative default = serial).
|
|
|
82
84
|
- You are **read-only**. Never edit files.
|
|
83
85
|
- Cite a real file:line for every MET/PARTIAL claim. If you cannot, downgrade to MISSING.
|
|
84
86
|
- Do not negotiate scope with yourself. If the spec didn't ask for it, it's scope creep, even if it looks useful.
|
|
87
|
+
- Plan/task code snippets are implementation guidance, not review authority; a diff matching a snippet never proves compliance. For anchor-less tasks the task text's prose requirements remain your contract.
|
|
85
88
|
- Never run tests, linters, or type-checkers. Read; do not execute checks.
|
|
86
89
|
- 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
|
@@ -9,8 +9,9 @@ argument-hint: "<pr> [issue-ref] (e.g. 123, or 123 gh-45)"
|
|
|
9
9
|
|
|
10
10
|
Verify, don't trust. A PR description is a claim, not proof: over-claimed coverage,
|
|
11
11
|
hallucinated references, and "tests pass" that were never rerun are the normal case,
|
|
12
|
-
not the exception - especially on generated code. This skill gathers evidence,
|
|
13
|
-
the project's own verification command
|
|
12
|
+
not the exception - especially on generated code. This skill gathers evidence, accepts green CI on the exact assessed head as
|
|
13
|
+
verification evidence (running the project's own verification command only as
|
|
14
|
+
the fallback), reviews the diff against a rubric, and
|
|
14
15
|
presents a deterministic, authorship-aware menu. Authorship sets which row carries
|
|
15
16
|
`[recommended]`; it never changes which rows are offered.
|
|
16
17
|
|
|
@@ -40,7 +41,7 @@ a wrapper skill:
|
|
|
40
41
|
baseline and reviewer-persona defaults on any conflict.
|
|
41
42
|
2. **Gauntlet overrides file** (3-location discovery, first found wins): the
|
|
42
43
|
`## PR gate` section (verification command, `timeout minutes`, `requires credentials`, issue
|
|
43
|
-
fetch, worktree wrapper, merge policy). An existing `## verification-before-completion`
|
|
44
|
+
fetch, worktree wrapper, merge policy, `local verification`, `ci checks`). An existing `## verification-before-completion`
|
|
44
45
|
section is an accepted equivalent source for the verification command.
|
|
45
46
|
3. **Repo documentation** - an explicitly documented command or tool (e.g. `AGENTS.md`'s
|
|
46
47
|
canonical test entrypoint, a documented worktree wrapper, a documented tracker CLI,
|
|
@@ -56,6 +57,8 @@ which is required unless documented elsewhere):
|
|
|
56
57
|
- verification command: <command> # required unless documented elsewhere
|
|
57
58
|
- timeout minutes: 15 # optional; default 15
|
|
58
59
|
- requires credentials: false # optional; true => skill reports "not run" as missing evidence
|
|
60
|
+
- local verification: always # optional; default (absent) = CI-first; "always" forces the local run even when exact-head CI is green
|
|
61
|
+
- ci checks: <comma-separated check names> # optional; narrows which checks count as evidence; absent = all checks on the assessed head
|
|
59
62
|
- worktree wrapper: <command> # optional
|
|
60
63
|
- issue fetch: <command with <ref> placeholder> # optional, replaces gh issue view
|
|
61
64
|
- merge policy: squash | merge-commit # optional
|
|
@@ -81,7 +84,7 @@ configuration.
|
|
|
81
84
|
## Progress tracking
|
|
82
85
|
|
|
83
86
|
Use `plan_tracker`, never `phase_tracker`. Init with the stage names: `gather`,
|
|
84
|
-
`provision worktree`, `
|
|
87
|
+
`provision worktree`, `resolve evidence`, `claim-check`, `review`, `consent menu`.
|
|
85
88
|
Append one task per material claim as the Verifier enumerates them. A passing stage or
|
|
86
89
|
a matched claim -> `complete`. A failed stage or a contradicted claim -> `failed`
|
|
87
90
|
(shown crossed, error color) and stays failed while the skill stops at the menu -
|
|
@@ -124,14 +127,15 @@ merge-ready and surfaced (see the merge preconditions below).
|
|
|
124
127
|
**Phase 3 - Verify, then Review** (sequential, same worktree - deliberate: the
|
|
125
128
|
verification command may write to the tree while the Reviewer reads it):
|
|
126
129
|
|
|
127
|
-
- Run verification-brief.md Section B: the
|
|
128
|
-
|
|
130
|
+
- Run verification-brief.md Section B: resolve the verification evidence per its
|
|
131
|
+
Evidence resolution table (green exact-head CI is the default evidence); run
|
|
132
|
+
the resolved verification command only when the table selects a fallback or
|
|
133
|
+
opt-out row, under its safety contract - self-contained and non-interactive (no prompts; run under a
|
|
129
134
|
non-interactive environment), bounded by a timeout (default 15 minutes, `timeout
|
|
130
135
|
minutes` override) via the first available mechanism: the harness's own bash
|
|
131
136
|
timeout parameter, else the `timeout`/`gtimeout` CLI when installed, else a
|
|
132
137
|
background-and-kill fallback - then material-claim checking against the PR body.
|
|
133
|
-
After
|
|
134
|
-
the orchestrator asserts tracked-only cleanliness (`git status --porcelain
|
|
138
|
+
After a local run, the orchestrator asserts tracked-only cleanliness (`git status --porcelain
|
|
135
139
|
--untracked-files=no` empty, equivalently `git diff --quiet && git diff --cached
|
|
136
140
|
--quiet`; HEAD unmoved) - untracked gate artifacts, including the Verifier's
|
|
137
141
|
`log_path`, are expected and do not fail this check as long as `log_path` sits
|
|
@@ -147,11 +151,16 @@ verification command may write to the tree while the Reviewer reads it):
|
|
|
147
151
|
- **Provenance:** `worktree_root` matches the provisioned path, every `run_cwd` is
|
|
148
152
|
inside it, `head_sha` matches the digest's `headRefOid`. On mismatch, re-fetch the
|
|
149
153
|
PR head once and re-sync + re-run Phase 3 if it advanced; a second mismatch, or any
|
|
150
|
-
path mismatch, is treated as missing evidence - not merge-ready. The claim stated in
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
154
|
+
path mismatch, is treated as missing evidence - not merge-ready. The claim stated in output names its source. Local path: precisely "reproduced
|
|
155
|
+
locally under the project's documented verification command" - nothing
|
|
156
|
+
stronger; never worded to imply a deployed, staging, or CI environment.
|
|
157
|
+
CI path (`source: ci`): precisely
|
|
158
|
+
`verified by CI: <check name(s)> succeeded on <sha> (run <url>)`
|
|
159
|
+
- never phrased as local reproduction, never implying the local command ran;
|
|
160
|
+
`<sha>` is the assessed `headRefOid`, `<url>` degrades to `unavailable` when
|
|
161
|
+
absent. Provenance checks on `worktree_root`/`run_cwd` bind only to the local
|
|
162
|
+
path.
|
|
163
|
+
- **Evidence:** On the CI path, list each satisfying check's name, conclusion, assessed SHA, and run URL - there is no command or raw_tail to paste. On the local path, paste each run's `command` and `raw_tail` verbatim, fenced - never
|
|
155
164
|
paraphrased. Any authored summary is labeled as a summary and never substitutes for
|
|
156
165
|
`raw_tail`.
|
|
157
166
|
- **Severity translation:** Critical -> blocking, Moderate -> blocking, Minor ->
|
|
@@ -165,18 +174,25 @@ verification command may write to the tree while the Reviewer reads it):
|
|
|
165
174
|
claim is a blocking finding. An `unverifiable-pre-merge` claim used as merge proof
|
|
166
175
|
(appears in the PR body's evidence/result/test-plan content) is blocking; stated as
|
|
167
176
|
an explicit post-merge observation instead, it is a non-blocking follow-up.
|
|
168
|
-
- **
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
green,
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
+
- **CI checks:** any blocking conclusion in the resolved check set (required or
|
|
178
|
+
not - see the brief's Evidence resolution table) withholds merge from every
|
|
179
|
+
pre-composed course until the user explicitly dispositions it, and mints a
|
|
180
|
+
`P#`. Three dispositions: **flaky** (proceed via the custom row), **real** (it
|
|
181
|
+
blocks until green), **CI-infrastructure-broken** (the checks themselves are
|
|
182
|
+
untrustworthy: triggers the fallback local run, and merge stays withheld until
|
|
183
|
+
that fallback produces green evidence). A **pending** required check (still
|
|
184
|
+
running - the normal case, not a defect) is **wait-until-green, not
|
|
185
|
+
dispositionable**: it mints no `P#`, is never dispositioned, and the withhold
|
|
186
|
+
auto-lifts the moment it turns green - or, if it instead fails, converts into
|
|
187
|
+
an undispositioned failing check with its own `P#` at that point. While
|
|
188
|
+
pending, the report notes it under Evidence and every merge course simply does
|
|
189
|
+
not render (a pending-only PR is not a blocking verdict - findings groups can
|
|
177
190
|
all read "None" - the recommended course falls to `stop` or `review-comment`,
|
|
178
|
-
never a merge course, until it resolves).
|
|
179
|
-
|
|
191
|
+
never a merge course, until it resolves). The evidence decision is
|
|
192
|
+
independent: a green check elsewhere in the resolved set still satisfies
|
|
193
|
+
verification evidence while a pending required check withholds merge. The
|
|
194
|
+
CI-sufficient path changes no consent surface: still read-only, no auto-merge,
|
|
195
|
+
no posting, no menu change beyond the third disposition.
|
|
180
196
|
- **Doc drift:** when the review finds committed doc drift as a **blocking** finding,
|
|
181
197
|
the orchestrator applies the doc fixes itself, in the provisioned worktree (created
|
|
182
198
|
or reused), as part of assessment - real edits, uncommitted, worktree-local. The
|
|
@@ -215,9 +231,9 @@ issue is linked, committed doc drift, anything the merged rubric maps to blockin
|
|
|
215
231
|
**follow-ups only** (never gate merge), or **clean**.
|
|
216
232
|
|
|
217
233
|
**Merge preconditions** (all must hold): gate green with every blocking finding fixed,
|
|
218
|
-
not deferred; `mergeable == MERGEABLE` (`UNKNOWN` after the one post-provision
|
|
219
|
-
re-poll withholds merge, same as `CONFLICTING`); no undispositioned failing
|
|
220
|
-
pending required check; evidence pasted with clean provenance; worktree clean and synced with the remote
|
|
234
|
+
not deferred; verification evidence present per the brief's Evidence resolution table (a CI claim or a green local run - a table-sanctioned CI skip is evidence, not missing "not run" evidence; result: not run blocks only when the table required a fallback run that didn't happen); `mergeable == MERGEABLE` (`UNKNOWN` after the one post-provision
|
|
235
|
+
re-poll withholds merge, same as `CONFLICTING`); no undispositioned failing check in
|
|
236
|
+
the resolved set, no pending required check; evidence pasted with clean provenance; worktree clean and synced with the remote
|
|
221
237
|
head (fixes pushed first); explicit selection with a head compare-and-swap that
|
|
222
238
|
passes. A merge selection while any precondition fails is refused, naming the failing
|
|
223
239
|
precondition, and the menu re-renders - never a dead end, never a silent merge. Merge
|
|
@@ -253,7 +269,7 @@ findings, menu. No restating diffs, no narration, no recap prose.
|
|
|
253
269
|
<one line + the deciding factor>
|
|
254
270
|
|
|
255
271
|
## Evidence
|
|
256
|
-
<verbatim command + raw_tail per run; claims checked;
|
|
272
|
+
<CI path: satisfying check name(s)/conclusion/sha/url; local path: verbatim command + raw_tail per run; claims checked; resolved-set check dispositions>
|
|
257
273
|
|
|
258
274
|
## Findings (blocking)
|
|
259
275
|
Blocking findings (P#):
|
|
@@ -295,8 +311,8 @@ Requirement/doc drift (linked issue, committed doc drift, or spec conflict):
|
|
|
295
311
|
nothing. Code-level spec bugs (the diff contradicts the spec) are `P#` `[spec]`;
|
|
296
312
|
requirement/doc mismatches (the spec or docs are stale relative to intent) are
|
|
297
313
|
`L#`.
|
|
298
|
-
- **
|
|
299
|
-
|
|
314
|
+
- **Failing checks close by disposition, not by fix:** an undispositioned failing check in the resolved set
|
|
315
|
+
is `P#` `[test]` referencing the check name; it is never a target
|
|
300
316
|
of a worktree `fix`. The user's Phase-4 disposition annotates the same ID rather
|
|
301
317
|
than closing it outright: dispositioned **flaky** -> annotate
|
|
302
318
|
`(dispositioned: flaky)`; this annotation excepts the `P#` from the unfixed-blocker
|
|
@@ -304,6 +320,9 @@ Requirement/doc drift (linked issue, committed doc drift, or spec conflict):
|
|
|
304
320
|
"every blocking finding fixed", and the merge path is Phase 4's explicit flaky
|
|
305
321
|
disposition via the custom row. Dispositioned **real** -> annotate
|
|
306
322
|
`(dispositioned: real)` and the `P#` keeps blocking until the check is green.
|
|
323
|
+
Dispositioned **CI-infrastructure-broken** -> annotate
|
|
324
|
+
`(dispositioned: ci-infrastructure-broken)`; the fallback local run executes,
|
|
325
|
+
and the `P#` keeps blocking until that fallback is green.
|
|
307
326
|
- **Severity is decided at triage, not by the category tag:** a finding lands in
|
|
308
327
|
`P#` only when it must be fixed before merge (correctness, security, material
|
|
309
328
|
performance trap, a convention the repo enforces); improvements that don't
|
|
@@ -363,7 +382,7 @@ pre-composed or custom, bundles a push-producing action (`fix`, `push-docs`) wit
|
|
|
363
382
|
| Author | State | Courses (first = `[recommended]`) |
|
|
364
383
|
|---|---|---|
|
|
365
384
|
| 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
|
|
385
|
+
| 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 failing-check-only or L#-only), course 1 (fix) is not rendered: push-docs becomes first when doc edits exist, else stop is first |
|
|
367
386
|
| you | blocking, post-fix re-render (gate green, preconditions hold) | 1. merge-squash; 2. merge-commit; 3. stop; 4. review-comment |
|
|
368
387
|
| someone else | clean / follow-ups only | 1. approve; 2. merge-squash (offered-unrecommended); 3. review-comment (no-blockers note) |
|
|
369
388
|
| 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 |
|
|
@@ -382,18 +401,18 @@ also dropped (never offered on your own PR) - fork|you|clean renders
|
|
|
382
401
|
branch course is also absent, since it is your own PR). A fork PR authored by someone
|
|
383
402
|
else uses the someone-else cells above with `fix`/`push-docs`/`merge-*` removed.
|
|
384
403
|
|
|
385
|
-
**
|
|
386
|
-
required check withholds every pre-composed course containing `merge-*` (per the
|
|
404
|
+
**CI-check gate on merge courses:** an undispositioned failing check in the resolved
|
|
405
|
+
set, or a pending **required** check, withholds every pre-composed course containing `merge-*` (per the
|
|
387
406
|
Verdict merge preconditions) - none render, whatever the author/state cell says. A
|
|
388
407
|
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
|
|
408
|
+
4); a failing one mints a `P#` and takes a disposition (flaky / real / CI-infrastructure-broken). A **flaky** disposition does
|
|
390
409
|
not restore merge to a pre-composed course; merge proceeds only via the custom row
|
|
391
410
|
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
|
|
411
|
+
check, keeps every merge course withheld until the check is green; a **CI-infrastructure-broken** disposition keeps them withheld until the triggered fallback run is green - a pending-only
|
|
393
412
|
render is not itself a blocking verdict (findings groups may all read "None"); the
|
|
394
413
|
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
|
|
396
|
-
|
|
414
|
+
falls through to the clean cell's recommended `merge-squash` - a failing resolved-set
|
|
415
|
+
check or a pending required check means the PR is not in the clean state to begin with.
|
|
397
416
|
|
|
398
417
|
Rows a cell offers but GitHub would refuse (branch protection, missing permission)
|
|
399
418
|
render listed-but-unavailable with the reason. Zero mutation courses is a legal
|
|
@@ -434,7 +453,7 @@ The menu is a state machine, not a one-shot report:
|
|
|
434
453
|
next CAS check runs against the new head on the next external write.
|
|
435
454
|
2. Execute only the selected course. **Fix wave** (`fix <set>`): first filter the
|
|
436
455
|
selected set to worktree-fixable `P#`s - drop any `P#` closed by disposition
|
|
437
|
-
(an undispositioned
|
|
456
|
+
(an undispositioned failing-check `P#` is never a `fix` target; a **flaky**
|
|
438
457
|
disposition already excepts it) - and route file-less `P#`s (a claim or a gate
|
|
439
458
|
command as `source_ref`, no draft touching a file) to run inline/sequentially,
|
|
440
459
|
never as part of a parallel file-batch.
|
|
@@ -463,7 +482,7 @@ The menu is a state machine, not a one-shot report:
|
|
|
463
482
|
Once every dispatched/inline batch returns, the orchestrator commits the golden
|
|
464
483
|
course as one local commit set - the code fixes plus any already-applied
|
|
465
484
|
reviewed doc edits selected alongside them (one commit, or one per batch
|
|
466
|
-
sequentially; subjects name the fixes) - then re-
|
|
485
|
+
sequentially; subjects name the fixes) - then re-resolves the evidence for the new head **once** (the brief's stale-head row: prior evidence is stale; the local command executes only on a fallback/opt-out resolution). **On
|
|
467
486
|
green**, push **once**; gate and push are per-wave invariants, never per-fix or
|
|
468
487
|
per-batch. **On red**, do not push: leave the commit(s) local, re-render with
|
|
469
488
|
the unresolved `P#`s still open, and warn that unpushed fix commits sit in the
|
|
@@ -474,9 +493,9 @@ The menu is a state machine, not a one-shot report:
|
|
|
474
493
|
with the drafted payload for the selected IDs.
|
|
475
494
|
3. After any mutation that can change readiness (fix wave pushed, docs pushed, PR
|
|
476
495
|
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
|
|
478
|
-
verification command itself is **not** re-executed here - step 2's
|
|
479
|
-
already was the wave's one and only
|
|
496
|
+
are re-checked against the new head and findings are re-rendered, but
|
|
497
|
+
the verification command itself is **not** re-executed here - step 2's evidence re-resolution
|
|
498
|
+
already was the wave's one and only gate pass. Re-render the report:
|
|
480
499
|
each selected `P#`/`L#` confirmed resolved is annotated `(fixed in <sha>)`
|
|
481
500
|
under its original ID; unresolved ones stay open unchanged; new findings
|
|
482
501
|
continue the sequence. Merge, if now available, renders as row 1.
|
|
@@ -512,14 +531,14 @@ overrides file - see Project overrides.
|
|
|
512
531
|
- Any mutation (fix, push, review, merge) without an explicit menu selection
|
|
513
532
|
- Pasting paraphrased evidence instead of verbatim `raw_tail`
|
|
514
533
|
- A provenance mismatch (worktree, `run_cwd`, or `head_sha`) noticed and ignored
|
|
515
|
-
- Merging around an undispositioned blocking finding or
|
|
534
|
+
- Merging around an undispositioned blocking finding or failing-check `P#`
|
|
516
535
|
- Reading configuration (rubric, verification command, or ladder sources) from the
|
|
517
536
|
PR's head instead of the base branch's merge-base
|
|
518
537
|
- Renumbering or reusing a finding ID between menu rounds
|
|
519
538
|
- Presenting findings without IDs, a blocking verdict with no `P#`/`L#`, or a
|
|
520
539
|
`## Decision` rendered without its action vocabulary
|
|
521
540
|
- Treating `[quality]` or `[performance]` as a downgrade signal on a `P#` - only
|
|
522
|
-
an explicit Phase-4 flaky disposition excepts a
|
|
541
|
+
an explicit Phase-4 flaky disposition excepts a failing-check `P#` from the
|
|
523
542
|
unfixed-blocker set, never a category tag
|
|
524
543
|
- A course (pre-composed or custom) bundling a push-producing action with
|
|
525
544
|
`merge-*`
|
|
@@ -57,7 +57,7 @@ invent ACs.
|
|
|
57
57
|
provisioning, so it never re-polls; the orchestrator re-polls once after
|
|
58
58
|
provisioning the worktree (see SKILL.md Phase 2) and treats a still-`UNKNOWN`
|
|
59
59
|
result as not merge-ready. Bot author noted
|
|
60
|
-
(`author_is_bot`). Capture each status check's `isRequired` where exposed.
|
|
60
|
+
(`author_is_bot`). Capture each status check's `isRequired` where exposed (digest field: `required`).
|
|
61
61
|
|
|
62
62
|
**Gather digest output schema (normative):**
|
|
63
63
|
|
|
@@ -65,7 +65,7 @@ result as not merge-ready. Bot author noted
|
|
|
65
65
|
- pr: { number, title, body, author, author_is_bot, state, isDraft, headRefName, baseRefName,
|
|
66
66
|
isCrossRepository, mergeable, headRefOid, files, additions, deletions, reviewDecision }
|
|
67
67
|
- viewer: { login, is_author, permission }
|
|
68
|
-
- status_checks: [ { name, status, conclusion, required } ] #
|
|
68
|
+
- status_checks: [ { name, status, conclusion, required, url } ] # evidence semantics: Section B Evidence resolution
|
|
69
69
|
- comments: { inline[], top_level[], review_threads[]? }
|
|
70
70
|
- issue: { ref, title, body, acceptance_criteria[], comments[] } | null
|
|
71
71
|
- worktree_discovery: { expected_path, exists, branch, dirty, ahead, behind }
|
|
@@ -73,18 +73,57 @@ result as not merge-ready. Bot author noted
|
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
`viewer_is_author` lives at `viewer.is_author` in the digest, computed as
|
|
76
|
-
`viewer.login == pr.author.login`. `status_checks`
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
76
|
+
`viewer.login == pr.author.login`. Each `status_checks` entry's `url` is the CheckRun `detailsUrl` / StatusContext
|
|
77
|
+
`targetUrl` already present in the fetched payload; when the payload omits it,
|
|
78
|
+
downstream CI claims record `url: unavailable` - absence never disqualifies the
|
|
79
|
+
check. GraphQL enums are case-folded; a StatusContext's `state` is its
|
|
80
|
+
conclusion, with `ERROR` blocking and `PENDING` pending. Missing `required` is
|
|
81
|
+
treated as non-required. `ci checks:` matches check name, workflow name, or
|
|
82
|
+
status context, trimmed, case-insensitive. What checks mean for verification evidence is owned by
|
|
83
|
+
Section B's Evidence resolution table; what they mean for merge is owned by the
|
|
84
|
+
orchestrator's required-check rule (SKILL.md Phase 4) - two independent
|
|
85
|
+
consumers of the same data.
|
|
80
86
|
|
|
81
87
|
## Section B - Verifier
|
|
82
88
|
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
Resolves the verification evidence per the table below - green exact-head CI is
|
|
90
|
+
the default evidence; the resolved verification command runs inside the
|
|
91
|
+
provisioned worktree only when the table selects a fallback or opt-out row -
|
|
92
|
+
then claim-checks the PR body. Report only - do not
|
|
85
93
|
edit, fix, or commit anything; you are running a gate and claim-checking,
|
|
86
94
|
not implementing.
|
|
87
95
|
|
|
96
|
+
**Evidence resolution (normative).** The single rule for whether the local
|
|
97
|
+
command runs. Inputs come from Section A's existing `gh pr view` call - no
|
|
98
|
+
second fetch.
|
|
99
|
+
|
|
100
|
+
- **Resolved check set** = checks named by `ci checks:` if configured, else all
|
|
101
|
+
checks on the assessed `headRefOid`.
|
|
102
|
+
- **Conclusion semantics**: `success` satisfies; `failure`/`timed_out`/
|
|
103
|
+
`action_required`/`error` block; `neutral`/`skipped`/`cancelled`/`stale`/
|
|
104
|
+
`startup_failure` are inert; a check with `status != completed` is pending; a
|
|
105
|
+
completed check with a missing/unreadable conclusion cannot satisfy
|
|
106
|
+
(fail-safe).
|
|
107
|
+
|
|
108
|
+
Row precedence is top-down: the first matching row wins.
|
|
109
|
+
|
|
110
|
+
| Path | Trigger | Action | Evidence recorded |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| Opt-out | `local verification: always` in `## PR gate` | Run local command unconditionally; a Failed-CI block below still applies independently | Local, as today |
|
|
113
|
+
| Failed CI | Any blocking conclusion in resolved set | Blocks: mints a `P#` (any resolved-set failure, required or not). A green local run never overrides it. Only an explicit human CI-infrastructure-broken disposition triggers the fallback run; merge stays withheld until the fallback produces green evidence | The disposition; plus the fallback run's result only when CI-infrastructure-broken triggered one |
|
|
114
|
+
| CI-sufficient | >=1 `success` in resolved set | Skip local run | CI claim: check name(s), conclusion, assessed SHA, run URL |
|
|
115
|
+
| Pending | Zero `success` and >=1 pending check in resolved set | Evidence decision waits until the set reaches a completed conclusion - never a fallback trigger, never an evidence-less merge; merge is withheld as missing evidence until the table re-resolves | n/a (waiting) |
|
|
116
|
+
| Fallback | No checks on assessed head, or zero `success` with none pending (all inert / fail-safe) | Run local command (protocol below, unchanged) | Local command + raw tail, existing provenance rules |
|
|
117
|
+
| Stale head | Head advances since evidence was resolved (e.g. a fix-wave push); fires across runs - a single gather is same-head by construction | All prior evidence (CI or local) is stale; re-resolve this table for the new head before merge is offered | Fresh evidence for the new head |
|
|
118
|
+
|
|
119
|
+
CI-sufficient predicate, stated once (the rows implement exactly this): **>=1
|
|
120
|
+
completed `success`, zero blocking conclusions, no opt-out.** Pending checks are
|
|
121
|
+
excluded from the predicate - they neither satisfy nor veto it. The evidence
|
|
122
|
+
decision ("run local?") and the merge decision ("can this merge?") are separate
|
|
123
|
+
consumers of the same `status_checks` data: a green non-required check satisfies
|
|
124
|
+
evidence even while a pending required check blocks merge under the existing
|
|
125
|
+
wait rule. The only evidence-path wait is the Pending row's zero-success case.
|
|
126
|
+
|
|
88
127
|
**Safety contract:**
|
|
89
128
|
|
|
90
129
|
- Timeout default 15 minutes, overridable by the resolved `timeout minutes`
|
|
@@ -95,7 +134,9 @@ not implementing.
|
|
|
95
134
|
non-interactive.
|
|
96
135
|
- If the resolved config states `requires credentials: true`, do not run
|
|
97
136
|
the command; report "verification requires credentials, not run" as
|
|
98
|
-
missing evidence instead of prompting for secrets
|
|
137
|
+
missing evidence instead of prompting for secrets; this arises only when
|
|
138
|
+
the table selected a fallback or opt-out row - a CI-sufficient resolution
|
|
139
|
+
needs no credentials.
|
|
99
140
|
- Capture full output to a `log_path` inside the (disposable) worktree, under a
|
|
100
141
|
gitignored path (e.g. `.worktrees/pr-<N>/.gatekeep-logs/`) so it never counts as a
|
|
101
142
|
tracked change; keep only the last ~100 lines verbatim in the digest as `raw_tail`.
|
|
@@ -103,19 +144,27 @@ not implementing.
|
|
|
103
144
|
**Verifier output schema (normative):**
|
|
104
145
|
|
|
105
146
|
```text
|
|
106
|
-
-
|
|
107
|
-
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
-
|
|
147
|
+
- source: ci | local
|
|
148
|
+
- source: ci ->
|
|
149
|
+
head_sha: <the assessed headRefOid>
|
|
150
|
+
checks: [ { name, conclusion, url } ] # url: unavailable when the payload omits it
|
|
151
|
+
(no command, no raw_tail - nothing ran locally)
|
|
152
|
+
- source: local ->
|
|
153
|
+
worktree_root: <absolute path>
|
|
154
|
+
head_sha: <git rev-parse HEAD at run time>
|
|
155
|
+
runs: [ { run_cwd, command (verbatim), exit_code, result: pass|fail|not run,
|
|
156
|
+
raw_tail: <last ~100 lines of combined stdout+stderr, verbatim, fenced>,
|
|
157
|
+
log_path: <file inside the worktree holding the full captured output> } ]
|
|
158
|
+
- claims: [ { claim, disposition: matched|contradicted|unverifiable-pre-merge, evidence } ] # both sources
|
|
112
159
|
```
|
|
113
160
|
|
|
114
|
-
`raw_tail` is captured output, not authored prose; anything written in your
|
|
161
|
+
Local provenance and raw-tail rules bind only to source: local. `raw_tail` is captured output, not authored prose; anything written in your
|
|
115
162
|
own words is labeled `summary` and must never be pasted in place of
|
|
116
163
|
`raw_tail`.
|
|
117
164
|
|
|
118
|
-
**Material-claim check.**
|
|
165
|
+
**Material-claim check.** Always runs, on both sources - on the CI path,
|
|
166
|
+
dispositions are judged against the recorded CI evidence and the diff; on the
|
|
167
|
+
local path, against the run and the diff. Claim-check the PR body -
|
|
119
168
|
**material claims only** (test/verification/behavior assertions: "added
|
|
120
169
|
X", "tests cover Y", "fixed Z"), not qualitative prose. Disposition each
|
|
121
170
|
claim as one of:
|
|
@@ -130,7 +179,7 @@ proof* (it appears in the PR body's evidence/result/test-plan content) is
|
|
|
130
179
|
blocking; the same claim stated as an explicit post-merge observation is
|
|
131
180
|
non-blocking follow-up only.
|
|
132
181
|
|
|
133
|
-
After
|
|
182
|
+
After a local run (`source: local` only), the orchestrator asserts tracked-only cleanliness
|
|
134
183
|
(`git status --porcelain --untracked-files=no` empty, equivalently
|
|
135
184
|
`git diff --quiet && git diff --cached --quiet`; HEAD unmoved); untracked gate
|
|
136
185
|
artifacts - including `log_path` itself, provided it sits under a gitignored path
|
|
@@ -171,9 +220,12 @@ blocking/follow-up happens later, at integration.
|
|
|
171
220
|
judges against stated intent only, never inventing ACs; scope-creep findings
|
|
172
221
|
do not apply.
|
|
173
222
|
- No resolvable verification command (ladder exhausted, user asked, user
|
|
174
|
-
declines)
|
|
175
|
-
|
|
176
|
-
|
|
223
|
+
declines) **when the Evidence resolution table selected a fallback or opt-out
|
|
224
|
+
row**: the gate runs without local verification evidence; record
|
|
225
|
+
`result: not run` in the Verifier output. Missing evidence blocks merge the
|
|
226
|
+
same as a failed gate - the PR is not merge-ready. A table-sanctioned CI skip
|
|
227
|
+
(`source: ci`) is evidence, never missing evidence, and needs no command at
|
|
228
|
+
all.
|
|
177
229
|
- Linked-issue fetch fails (tracker unreachable, bad ref): proceed judging
|
|
178
230
|
against the PR's stated intent, mark `issue: null` in the digest plus a
|
|
179
231
|
truncation/availability note explaining why, and never invent ACs; AC
|
|
@@ -55,7 +55,7 @@ For each task in `plan_tracker`:
|
|
|
55
55
|
|
|
56
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
|
-
3. **Dispatch spec reviewer.** Pass the task text, the patch diff, the absolute spec path, and the task's `**Spec:**` anchors — SR reads the anchored ranges from the spec file itself; never inline spec excerpts. The spec wins every dispute; the authority hierarchy and finding labels live in `./spec-reviewer-prompt.md`. Anchor-less tasks (no `**Spec:**` line): task text alone is the contract. Verify the
|
|
58
|
+
3. **Dispatch spec reviewer.** Pass the task text, the patch diff, the absolute spec path, and the task's `**Spec:**` anchors — SR reads the anchored ranges from the spec file itself; never inline spec excerpts. The spec wins every dispute; the authority hierarchy and finding labels live in `./spec-reviewer-prompt.md`. Anchor-less tasks (no `**Spec:**` line): task text alone is the contract. Verify the change satisfies the anchored 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
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).
|
|
@@ -171,7 +171,7 @@ Auto-selected at handoff by `writing-plans` (any wave with ≥2 tasks) when the
|
|
|
171
171
|
|
|
172
172
|
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.
|
|
173
173
|
2. **Fan out.** One parallel dispatch (shape below): `implementer` per task, `context: "fresh"`, `worktree: true`. Each returns a status + a patch.
|
|
174
|
-
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 — SR reads the anchored ranges itself (never inline excerpts; authority hierarchy in `./spec-reviewer-prompt.md`; anchor-less tasks are task-text-only). Review
|
|
174
|
+
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 — 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 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.
|
|
175
175
|
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.
|
|
176
176
|
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).
|
|
177
177
|
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).
|
|
@@ -33,6 +33,7 @@ Dispatch a subagent with this prompt:
|
|
|
33
33
|
- **Task-vs-spec divergence** (task says X, anchored spec says Y): unconditional flag; quote the spec literal with spec file:line so the fix re-dispatch carries authoritative wording. Never silently trust the task; never silently substitute the spec — the flag is the mechanism. Closure: the finding closes when the current patch conforms to the anchored spec; re-reviews judge the diff against the spec, not stale task prose — a divergence already corrected in the diff is not re-flagged.
|
|
34
34
|
- **Anchor-less task** (Anchors: omitted): the task text alone is your contract; no out-of-anchor-slice or transcription-gap flagging — only nothing-extra-vs-the-chore review.
|
|
35
35
|
- **Finding grammar:** divergence findings use the existing F1..Fn finding grammar - a finding kind by prose label, not a new schema; the `Parallel-safe:` and `TRAJECTORY:` grammars are untouched.
|
|
36
|
+
- **Plan/task code snippets:** implementation guidance, not review authority; a diff matching a snippet never proves compliance. For anchor-less tasks the task text's prose requirements remain your contract.
|
|
36
37
|
|
|
37
38
|
## CRITICAL: Do Not Trust the Report
|
|
38
39
|
|
|
@@ -46,6 +47,7 @@ Dispatch a subagent with this prompt:
|
|
|
46
47
|
|
|
47
48
|
**DO:**
|
|
48
49
|
- Read the actual code they wrote
|
|
50
|
+
- Read each touched file in full, not just the diff hunks, continuing in chunks; note in the report any touched file not read to the end
|
|
49
51
|
- Compare actual implementation to requirements line by line
|
|
50
52
|
- Check for missing pieces they claimed to implement
|
|
51
53
|
- Look for extra features they didn't mention
|
|
@@ -61,6 +63,10 @@ Dispatch a subagent with this prompt:
|
|
|
61
63
|
|
|
62
64
|
## Your Job
|
|
63
65
|
|
|
66
|
+
<!-- clause decomposition / snippet non-authority / whole-file reads: keep in lockstep with agents/spec-reviewer.md — change them together or not at all -->
|
|
67
|
+
|
|
68
|
+
Decompose the binding contract - the anchored spec lines, or the task text when anchors are omitted - into atomic clauses, covering every requirement, acceptance criterion, and explicit non-goal. Each independently checkable statement is one clause; a sentence listing three requirements yields three clauses.
|
|
69
|
+
|
|
64
70
|
Read the implementation code and verify:
|
|
65
71
|
|
|
66
72
|
**Missing requirements:**
|
|
@@ -255,7 +255,7 @@ Every code task carries this step (red -> green -> fmt/lint -> commit). Doc-only
|
|
|
255
255
|
|
|
256
256
|
## Spec Coverage Table
|
|
257
257
|
|
|
258
|
-
Every plan ends with a `## Spec coverage` section — authored last, placed after all Task sections (owner IDs do not exist earlier). Build it extraction-first: walk the spec top to bottom and write one row per normative requirement **before** assigning owners — every Design imperative (Add/Remove/Keep/Replace-style directives, not any fixed lexical form), every Edge-cases rule, every Acceptance criterion, every Out-of-scope entry, and every non-none Documentation-impact entry. Then assign owners. Two row kinds:
|
|
258
|
+
Every plan ends with a `## Spec coverage` section — authored last, placed after all Task sections (owner IDs do not exist earlier). Build it extraction-first: walk the spec top to bottom and write one row per normative requirement **before** assigning owners — every Design imperative (Add/Remove/Keep/Replace-style directives, not any fixed lexical form), every Edge-cases rule, every Acceptance criterion, every Out-of-scope entry, and every non-none Documentation-impact entry. Then assign owners, then re-walk the spec once: every normative clause has a row. Two row kinds:
|
|
259
259
|
|
|
260
260
|
```markdown
|
|
261
261
|
## Spec coverage
|
|
@@ -293,6 +293,7 @@ If a decision is genuinely open, put it in an explicit **Open Questions** sectio
|
|
|
293
293
|
After drafting the plan and before announcing it complete, run these checks yourself. This is a checklist you run yourself — not a subagent dispatch.
|
|
294
294
|
|
|
295
295
|
- **Table closure (three legs).** Every `## Spec coverage` row's owner is a task-ID list, a spec-authorized `waived: <reason>`, or a mechanical-task row; every `### Task N` heading appears in >=1 row; every requirement row's anchor is contained in the anchor set of each listed owner task's `**Spec:**` line. Zero orphans, zero waived in-scope normative rows, zero row-vs-owner anchor mismatches. Each Documentation impact entry maps to a plan task (or explicit "none").
|
|
296
|
+
- **Code-vs-anchor sanity.** For each non-waived 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. Fix the task, don't annotate.
|
|
296
297
|
- **Quote integrity (spec -> task).** For every non-waived requirement row, extract each backtick-quoted literal inside the row's anchored spec lines (strip the backticks; skip `<placeholder>` template spans) and `grep -F` it against the owning task's body — zero misses. Planner-authored backticks elsewhere in tasks are never scanned; the input set is spec-side literals only.
|
|
297
298
|
- **Anchor resolution.** For every task-level anchor (a `**Spec:**` line carrying `§`; the plan header's path line is exempt), the quoted heading text matches an ATX heading in the spec file and `L<start>-L<end>` is in-bounds, non-empty, and lies within that heading's section — zero unresolved anchors. Verify with `grep -n '^#'` plus a scoped `sed -n`. Ignore `#`-lines inside fenced code blocks when locating headings and section boundaries - a fenced markdown example is not a heading.
|
|
298
299
|
- **Paths exist.** Every `Modify:` path in `Files:` blocks passes `test -f` after stripping any trailing `:line[-line]` suffix; a `Modify:` glob must expand to >=1 match; `Create:` and `Test:` paths are exempt unless the `Test:` path is also listed under `Modify:`. Zero missing.
|
|
@@ -309,6 +310,7 @@ Fix what this review finds before handoff.
|
|
|
309
310
|
|
|
310
311
|
- Exact file paths always
|
|
311
312
|
- Complete code in plan (not "add validation")
|
|
313
|
+
- Plan code is guidance for the implementer, not review authority - reviewers judge the diff against the spec, never against plan snippets
|
|
312
314
|
- Exact commands with expected output
|
|
313
315
|
- Reference relevant skills
|
|
314
316
|
- DRY, YAGNI, TDD, frequent commits
|