pi-gauntlet 4.3.1 → 4.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/README.md +71 -211
- package/agents/conformance-reviewer.md +4 -4
- package/extensions/lib/phase-tracker-helpers.test.ts +120 -0
- package/extensions/lib/phase-tracker-helpers.ts +97 -0
- package/extensions/phase-tracker.ts +103 -16
- package/extensions/plan-tracker.ts +1 -1
- package/package.json +1 -1
- package/skills/brainstorming/SKILL.md +72 -25
- package/skills/brainstorming/gatherer.md +117 -0
- package/skills/finishing-a-development-branch/SKILL.md +46 -9
- package/skills/roasting-the-spec/SKILL.md +25 -16
- package/skills/subagent-driven-development/SKILL.md +4 -4
- package/skills/verification-before-completion/SKILL.md +1 -1
- package/skills/verification-before-completion/reference/conformance-check.md +131 -118
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Context Gather (brainstorming supplementary)
|
|
2
|
+
|
|
3
|
+
Consumed only by `SKILL.md` in this directory. Runs unconditionally between worktree
|
|
4
|
+
setup and the questionary. **Foreground, no user interaction** — the first thing the
|
|
5
|
+
operator sees after gather is questionary question one. Do not announce, do not ask.
|
|
6
|
+
|
|
7
|
+
## Dispatch
|
|
8
|
+
|
|
9
|
+
Mint a temp dir outside the worktree (never committed):
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
GATHER_DIR=$(mktemp -d)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Set the substep, then dispatch one parallel-tasks `subagent` call (foreground — no
|
|
16
|
+
`async:`; no `model:` — pi-cohort `agentOverrides` owns builder models):
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
phase_tracker({ action: "substep", phase: "brainstorm", substep: "gather" })
|
|
20
|
+
subagent({
|
|
21
|
+
tasks: [
|
|
22
|
+
{ agent: "scout", cwd: "<abs worktree path>", phase: "context-gather",
|
|
23
|
+
output: "<GATHER_DIR>/scout.md",
|
|
24
|
+
task: "<scout task, template below>" },
|
|
25
|
+
// include ONLY when the trigger rule below fires:
|
|
26
|
+
{ agent: "context-builder", cwd: "<abs worktree path>", phase: "context-gather",
|
|
27
|
+
output: "<GATHER_DIR>/external.md",
|
|
28
|
+
task: "<context-builder task, template below>" }
|
|
29
|
+
]
|
|
30
|
+
})
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Absolute `output:` paths are mandatory: relative paths in parallel mode resolve
|
|
34
|
+
against the worktree and would get committed.
|
|
35
|
+
|
|
36
|
+
## Task templates
|
|
37
|
+
|
|
38
|
+
Scout (always dispatched):
|
|
39
|
+
|
|
40
|
+
> Recon for an upcoming design discussion. The request: `<initial prompt verbatim>`.
|
|
41
|
+
> Map the territory this change touches: relevant files with line ranges, existing
|
|
42
|
+
> patterns and conventions the change must match, test conventions, integration
|
|
43
|
+
> points, and whether the codebase or ecosystem already solves any of this. Cite
|
|
44
|
+
> exact paths and line ranges. End with an "Open questions that matter for the spec"
|
|
45
|
+
> section. Compact handoff, not a dump.
|
|
46
|
+
|
|
47
|
+
Context-builder (conditional):
|
|
48
|
+
|
|
49
|
+
> Extract external context for an upcoming design discussion. The request:
|
|
50
|
+
> `<initial prompt verbatim>`. Fetch and distill these references:
|
|
51
|
+
> `<detected refs, one per line>`. For each: acceptance criteria, hard constraints,
|
|
52
|
+
> linked discussion that changes scope, and contradictions with the request as
|
|
53
|
+
> stated. Write ONLY the context handoff to your output path; do NOT produce a
|
|
54
|
+
> meta-prompt file. End with an "Open questions that matter for the spec" section.
|
|
55
|
+
> If a ref is unreadable, say so explicitly and continue.
|
|
56
|
+
|
|
57
|
+
(The meta-prompt exclusion matters: in chain mode context-builder emits two files —
|
|
58
|
+
`context.md` + `meta-prompt.md`; this flow consumes only the context handoff.)
|
|
59
|
+
|
|
60
|
+
## Context-builder trigger rule
|
|
61
|
+
|
|
62
|
+
Dispatch context-builder when the initial prompt (or a file it explicitly references)
|
|
63
|
+
contains any of:
|
|
64
|
+
|
|
65
|
+
- an `http(s)://` URL;
|
|
66
|
+
- a tracker-style ID matching `[A-Z][A-Z0-9]+-\d+` (Linear/Jira form) **when a fetch
|
|
67
|
+
path exists** (a tracker tool/MCP, or a URL pattern in `.pi/gauntlet-overrides.md`);
|
|
68
|
+
- a GitHub-style ref `owner/repo#N`, or a bare `#N` when the repo's tracker is
|
|
69
|
+
GitHub Issues.
|
|
70
|
+
|
|
71
|
+
Examples: "implement ABC-123" with a Linear tool available → trigger; "add rate
|
|
72
|
+
limiting like https://example.com/rfc" → trigger; "rename the settings resolver" →
|
|
73
|
+
scout only. An opaque ID with **no** fetch path → do not dispatch; list it in the
|
|
74
|
+
draft's `## External context` as an unfetched ref instead of guessing.
|
|
75
|
+
|
|
76
|
+
## Failure and degradation
|
|
77
|
+
|
|
78
|
+
A builder **failed** when its task errored **or** its output file is missing or
|
|
79
|
+
empty (0 bytes). Degradation never blocks and never surfaces to the user at gather
|
|
80
|
+
time:
|
|
81
|
+
|
|
82
|
+
- scout failed → `## Codebase recon` reads: `Scout recon failed (<one-line reason>).
|
|
83
|
+
Draft is thin; exploration falls to the questionary.` followed by the initial prompt.
|
|
84
|
+
- context-builder failed → `## External context` reads: `External refs not fetched
|
|
85
|
+
(<one-line reason>):` followed by the ref list — the critique pass later surfaces
|
|
86
|
+
them as external-ref candidates.
|
|
87
|
+
|
|
88
|
+
## Draft assembly
|
|
89
|
+
|
|
90
|
+
Read the temp files and write the draft **to the spec path** (normal filename
|
|
91
|
+
convention; slug minted from the initial prompt):
|
|
92
|
+
|
|
93
|
+
```markdown
|
|
94
|
+
# CONTEXT DRAFT - NOT A SPEC - fully replaced at spec-writing
|
|
95
|
+
|
|
96
|
+
## Codebase recon
|
|
97
|
+
<scout output, or the degraded text>
|
|
98
|
+
|
|
99
|
+
## External context
|
|
100
|
+
<context-builder output, degraded text, or unfetched-ref list; omit this section
|
|
101
|
+
only when the trigger rule never fired>
|
|
102
|
+
|
|
103
|
+
## Appended during questionary
|
|
104
|
+
<starts empty>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
The marker line is **line 1, verbatim**. Then clean up and clear the substep:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
rm -rf "$GATHER_DIR"
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
phase_tracker({ action: "substep", phase: "brainstorm", substep: null })
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The questionary runs under plain `brainstorm`.
|
|
@@ -70,24 +70,61 @@ git merge-base HEAD main 2>/dev/null || git merge-base HEAD master 2>/dev/null
|
|
|
70
70
|
|
|
71
71
|
Or ask: "This branch split from main - is that correct?"
|
|
72
72
|
|
|
73
|
-
### Step 3.5:
|
|
73
|
+
### Step 3.5: Closure / Conformance Disposition Gate
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
This is an **enforced per-gap disposition gate**, not a surface-only notice. The user is about to choose how to ship; every carried-open gap must get an explicit disposition here, before Step 4's menu. Tests prove the code runs; conformance proves it does what was requested — different gates.
|
|
76
76
|
|
|
77
|
-
|
|
78
|
-
- **If no conformance check has run in this flow** (e.g., ad-hoc work that landed without an execution skill), say so plainly and offer to run it now — dispatch a fresh-context `conformance-reviewer` against the origin (spec + verbatim prompt + full diff vs base) per `verification-before-completion/reference/conformance-check.md`. Closing the loop is cheap relative to shipping unverified intent.
|
|
79
|
-
- **Unreconciled gaps are a blocker, not a footnote.** Do not bury them inside the options menu. If any gap is still open, resolve it (or get explicit user acceptance recorded in the spec) before offering Option 1 (squash-merge) or Option 2 (PR).
|
|
77
|
+
**If no conformance check has run in this flow** (e.g., ad-hoc work that landed without an execution skill): say so, then dispatch a fresh-context `conformance-reviewer` against the origin (spec + verbatim prompt + full diff vs base) per `verification-before-completion/reference/conformance-check.md`. Closing the loop is cheap relative to shipping unverified intent. Then proceed below with its verdict.
|
|
80
78
|
|
|
81
|
-
|
|
79
|
+
**If verdict is `CONFORMS`** (no carried-open gaps): report `Closure / conformance: CONFORMS`. If the run auto-applied any fixes, also surface the flat `auto-applied fix commits: <Gn: SHA>, ...` index from the `## Closure / conformance` block with a one-line revert offer (see "Revert semantics") — a gap that auto-converged to `CONFORMS` mid-verify has no per-gap line above, so this index is the only place its fix commit stays revertable. No per-gap menu. Continue to Step 4.
|
|
80
|
+
|
|
81
|
+
**If gaps were carried open:** read the `## Closure / conformance` block from the verify completion summary (schema and field names defined once in `verification-before-completion/reference/conformance-check.md` — do not re-derive them here). For each `Gn` line, render it verbatim and offer this ordered menu — the human must pick one entry per gap before Step 4:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
G<n>: <verdict> — recommended: <fix|accept|rescope> — touched-files: <paths>
|
|
85
|
+
round history: R1 ..., R2 ...
|
|
86
|
+
|
|
87
|
+
D1. Apply now: accept-into-spec — fold a dated decision into the spec now (main session edits the spec directly, never a subagent)
|
|
88
|
+
D2. Apply now: rescope-into-spec — same, recorded as reduced/changed scope
|
|
89
|
+
D3. Apply now: fix-now — run the fix loop now (worktree finish paths only, see below)
|
|
90
|
+
D4. Custom disposition — e.g. capture as a follow-up ticket per this project's issue-tracker convention (see `.pi/gauntlet-overrides.md`)
|
|
91
|
+
D5. Revert an auto-applied change for this gap (see "Revert semantics" below)
|
|
92
|
+
|
|
93
|
+
Which option for G<n>?
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Also surface the flat `auto-applied fix commits: <Gn: SHA>, ...` index from the same block — this is the revert candidate list for D5, covering every `conformance fix Gn` commit this run (open and already-closed gaps alike).
|
|
97
|
+
|
|
98
|
+
**`fix-now` loop scope (worktree finish paths only):**
|
|
99
|
+
|
|
100
|
+
1. Commit any `accept-into-spec` / `rescope-into-spec` edits picked in this gate **before** dispatching — a dirty tree rejects `worktree: true`, and the re-audit must read the amended spec.
|
|
101
|
+
2. Run the **full** loop from `verification-before-completion/reference/conformance-check.md` "Fix loop" (implementer → integrate → test → `code-reviewer` → re-audit). Do not re-describe the loop steps here — that file is the single source.
|
|
102
|
+
3. Re-run Step 1's test verification on the result.
|
|
103
|
+
4. Re-enter this step (3.5) with the re-audited `## Closure / conformance` block before re-presenting ship options.
|
|
104
|
+
|
|
105
|
+
**Non-worktree precondition (unchanged):** on a normal-repo finish (`GIT_DIR == GIT_COMMON`) or detached HEAD there is no worktree to dispatch fix waves into — the menu above offers D1, D2, D4, and D5 (manual fix-in-place substitutes for D3) but never dispatches `fix-now`.
|
|
106
|
+
|
|
107
|
+
No auto-proceed: every carried-open gap needs an explicit answer from the list above before Step 4 renders. Once all gaps are dispositioned, report the final state as a distinct line:
|
|
82
108
|
|
|
83
109
|
```
|
|
84
110
|
Closure / conformance: CONFORMS
|
|
85
|
-
(or: GAPS — <n>
|
|
86
|
-
- <gap> → proposed remediation: <one line> [if any open]
|
|
111
|
+
(or: GAPS — <n> dispositioned: G1 accept-into-spec, G2 fix-now → CONFORMS, ...)
|
|
87
112
|
```
|
|
88
113
|
|
|
89
114
|
Then continue to Step 4.
|
|
90
115
|
|
|
116
|
+
### Revert semantics
|
|
117
|
+
|
|
118
|
+
Three tiers, increasing cost — name the tier when a revert is requested:
|
|
119
|
+
|
|
120
|
+
| Tier | What's reverted | Cost | Mechanics |
|
|
121
|
+
|---|---|---|---|
|
|
122
|
+
| Cheap | Council edit, reverted at the `brainstorming` gate | Spec isn't yet plan- or code-bearing | Revise spec, re-present |
|
|
123
|
+
| Light | Conformance fix, reverted at finish | Gap re-opens for a fresh disposition | Revert the `conformance fix Gn` commit(s), re-audit |
|
|
124
|
+
| Heavy | Council edit, reverted at finish | Rewrites the already-ratified contract that drove the plan and code | Amend spec → re-approve → regenerate affected plan/code → re-run verify before ship |
|
|
125
|
+
|
|
126
|
+
A **heavy** revert is not a menu toggle — say so explicitly to the user before proceeding, and do not present it as equivalent-effort to the light tier. The council audit that lets the human identify revert candidates lives in the `brainstorming` spec commit message body (not a committed spec section).
|
|
127
|
+
|
|
91
128
|
### Step 4: Present Options
|
|
92
129
|
|
|
93
130
|
**Normal repo and named-branch worktree — present exactly these 4 options:**
|
|
@@ -300,7 +337,7 @@ phase_tracker({ action: "complete", phase: "ship" })
|
|
|
300
337
|
- Remove a worktree before confirming merge success
|
|
301
338
|
- Clean up worktrees you didn't create (provenance check)
|
|
302
339
|
- Run `git worktree remove` from inside the worktree
|
|
303
|
-
-
|
|
340
|
+
- Auto-proceed past an undispositioned carried-open gap
|
|
304
341
|
- Skip the guarded plan-doc removal before push on Option 2 when a plan doc was committed
|
|
305
342
|
|
|
306
343
|
**Always:**
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: roasting-the-spec
|
|
3
|
-
description: Use after writing a spec, when a spec council is configured (the resolved piGauntlet.specCouncil council, via the gauntlet_setting tool, repo settings over the preset). Auto-dispatched by /skill:brainstorming as the critique pass when members is non-empty (no longer offered). N members on different models critique in parallel, a neutral chair consolidates and adjudicates, the parent
|
|
3
|
+
description: Use after writing a spec, when a spec council is configured (the resolved piGauntlet.specCouncil council, via the gauntlet_setting tool, repo settings over the preset). Auto-dispatched by /skill:brainstorming as the critique pass when members is non-empty (no longer offered). N members on different models critique in parallel, a neutral chair consolidates and adjudicates, the parent applies its own dispositions and returns an audit for the user to ratify at brainstorming's gate.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Roasting the Spec (Spec Council)
|
|
7
7
|
|
|
8
8
|
## Overview
|
|
9
9
|
|
|
10
|
-
A multi-model critique pass for a freshly written spec. Each council **member** runs on a different model and critiques the spec independently — different models surface different angles. A neutral **chair** consolidates the critiques and adjudicates disagreements. The parent
|
|
10
|
+
A multi-model critique pass for a freshly written spec. Each council **member** runs on a different model and critiques the spec independently — different models surface different angles. A neutral **chair** consolidates the critiques and adjudicates disagreements. The parent decides what to apply and applies it before returning; the **user** ratifies (or reverts) the result at brainstorming's single gate. The council never decides on its own what changes land.
|
|
11
11
|
|
|
12
12
|
Auto-dispatched from `/skill:brainstorming` as the critique pass, after the inline lint and before the user review gate, **only when a council is configured** (`members` non-empty). brainstorming owns that gate; when no council is configured it runs a single fresh-`worker` critique instead and does not invoke this skill.
|
|
13
13
|
|
|
@@ -19,8 +19,8 @@ This skill may read anything and edit **only** the spec under `doc/specs/`. It d
|
|
|
19
19
|
|
|
20
20
|
- **Members** — independent witnesses. One per configured model, fresh context, read-only.
|
|
21
21
|
- **Chair** — judge of the testimony. Fresh context (never saw the spec authored); consolidates and resolves member-vs-member conflicts. Final say on conflicts; no say on what gets applied.
|
|
22
|
-
- **Parent (you)** — advocate.
|
|
23
|
-
- **User** — jury.
|
|
22
|
+
- **Parent (you)** — advocate, and now also executor. You decide apply / defer / reject per finding on scope grounds, then apply the apply-set yourself (you hold the `edit`/`write` tools; this was always the main-loop model's job, just moved earlier). Cannot suppress findings — every finding lands in the audit as applied, deferred, or rejected.
|
|
23
|
+
- **User** — sole jury. Ratifies (or reverts) the finished spec at brainstorming's one gate — after the apply, not before.
|
|
24
24
|
|
|
25
25
|
## Configuration and gating
|
|
26
26
|
|
|
@@ -100,32 +100,41 @@ List the exact member paths in the task text. The `reads:` array injects their c
|
|
|
100
100
|
|
|
101
101
|
If the configured `chair` model is unreachable, retry once with the inherited model.
|
|
102
102
|
|
|
103
|
-
### 3 —
|
|
103
|
+
### 3 — Decide and apply
|
|
104
104
|
|
|
105
|
-
For each cluster in the chair's report, decide
|
|
105
|
+
For each cluster in the chair's report, decide one of:
|
|
106
106
|
|
|
107
|
-
- **apply** —
|
|
108
|
-
- **defer** — out of scope for this spec; name where it belongs.
|
|
109
|
-
- **reject** —
|
|
107
|
+
- **apply** — make the concrete edit to the spec under `doc/specs/` now.
|
|
108
|
+
- **defer** — out of scope for this spec; name where it belongs. Do not edit the spec.
|
|
109
|
+
- **reject** — one-line reason. Do not edit the spec.
|
|
110
110
|
|
|
111
|
-
|
|
111
|
+
Also inline any `external-ref:` cluster you have context for (e.g. a ticket fetched during brainstorming) as part of the apply-set — this is your call, same as any other cluster.
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
You are the advocate — decide on scope grounds — and, unlike a dispatched subagent, also the executor: you hold `edit`/`write` tools directly, so apply the edit yourself instead of proposing it for someone else to make. Do this **before** returning to brainstorming.
|
|
114
114
|
|
|
115
|
-
|
|
115
|
+
### 4 — Emit the audit
|
|
116
116
|
|
|
117
|
-
|
|
117
|
+
Return a structured audit, gate-only (not a committed spec section) — three labelled lists:
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
- `Applied:` — cluster -> the concrete edit made.
|
|
120
|
+
- `Deferred:` — cluster -> where it belongs.
|
|
121
|
+
- `Rejected:` — cluster -> one-line reason.
|
|
120
122
|
|
|
121
|
-
|
|
123
|
+
Hand this audit to brainstorming along with the now-final spec. brainstorming writes it into the **spec commit message body** (git-native, readable pre-squash) so it survives for finish-time revert visibility, then shows it to the user alongside the final spec at its one review gate. The user can revert any applied edit there — that gate, not this skill, is where ratification happens.
|
|
124
|
+
|
|
125
|
+
### 5 — Clean up
|
|
126
|
+
|
|
127
|
+
Re-run brainstorming's placeholder scan over the applied result. Remove the temp dir (`rm -rf` the `mktemp -d` path). Nothing council-related (member files) is ever staged.
|
|
128
|
+
|
|
129
|
+
Single pass — no automatic re-roast loop. The user can invoke this skill again after the gate for another round.
|
|
122
130
|
|
|
123
131
|
## Red flags — STOP
|
|
124
132
|
|
|
125
133
|
- Running the council when `piGauntlet.specCouncil.members` is absent or empty (brainstorming owns the gate and should have used the worker fallback).
|
|
126
134
|
- Reading member critique files yourself instead of routing them through the chair.
|
|
127
135
|
- Writing member files to a relative path (they land in the worktree).
|
|
128
|
-
-
|
|
136
|
+
- Applying edits without surfacing the audit at brainstorming's gate — apply-before-the-gate is correct; apply-without-the-gate is not.
|
|
137
|
+
- Suppressing a finding instead of routing it to applied, deferred, or rejected in the audit.
|
|
129
138
|
- Surfacing member-vs-member disagreements to the user instead of letting the chair adjudicate.
|
|
130
139
|
- Editing anything other than the spec under `doc/specs/`.
|
|
131
140
|
|
|
@@ -190,9 +190,9 @@ For the fan-out + worktree + patch-integration + conflict mechanics, see `dispat
|
|
|
190
190
|
|
|
191
191
|
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.)
|
|
192
192
|
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 `.pi/gauntlet-overrides.md`, or run `/self-audit` manually.)
|
|
193
|
-
2. **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. On `GAPS`,
|
|
194
|
-
3. Summarize what was implemented (tasks completed, files changed, test counts, code-review verdict).
|
|
195
|
-
4. **Proceed to finishing — no confirmation prompt.**
|
|
193
|
+
2. **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. On `GAPS`, this skill does not choose a disposition or stop for one: `conformance-check.md` "When the check finds gaps" auto-runs the fix loop for every `recommended: fix` gap (no menu, no stop) and carries any `accept`/`rescope`/`UNAUTHORIZED` gap OPEN to the finish gate — follow that file for the partition rule and the fix-loop mechanics; do not reimplement them here. The fix loop may drive `plan_tracker` to surface fix-wave progress (task name = `Gn: <short desc>`, lifecycle `pending → in_progress → complete` per gap); it never calls `phase_tracker`. Call `phase_tracker({ action: "complete", phase: "verify" })` once every gap is either fixed (`CONFORMS`) or carried OPEN as a deferred `accept`/`rescope`/`UNAUTHORIZED` gap — escalation (fix-round cap reached with an open `fix` gap) is the sole non-completing terminal state; on escalation, do not complete verify, stop and report.
|
|
194
|
+
3. Summarize what was implemented (tasks completed, files changed, test counts, code-review verdict). Emit the `## Closure / conformance` block verbatim per the schema defined in `verification-before-completion/reference/conformance-check.md` (do not rename or reformat its fields); `finishing-a-development-branch` Step 3.5 consumes it by those exact field names.
|
|
195
|
+
4. **Proceed to finishing — no confirmation prompt.** Once verify is complete per step 2's criterion, invoke `/skill:finishing-a-development-branch` immediately. Its Step 4 menu (squash / PR / keep / discard) is the human gate; a separate "ready to finish?" prompt only stacks a second stop in front of it. Carried-open gaps are resolved at Step 3.5 of that skill via the `## Closure / conformance` block from step 3 — nothing is left to decide here. Manual testing is a follow-up after the finishing choice (on `<base-branch>` after a squash-merge, or on the PR branch), never a reason to hold this gate.
|
|
196
196
|
|
|
197
197
|
## Red Flags — STOP
|
|
198
198
|
|
|
@@ -215,7 +215,7 @@ For the fan-out + worktree + patch-integration + conflict mechanics, see `dispat
|
|
|
215
215
|
- `/skill:using-git-worktrees` — set up isolation first (small changes can branch in place with user approval)
|
|
216
216
|
- `/skill:writing-plans` — creates the plan this skill executes
|
|
217
217
|
- `/skill:requesting-code-review` — review template for reviewer subagents
|
|
218
|
-
- `/skill:finishing-a-development-branch` — invoked automatically once
|
|
218
|
+
- `/skill:finishing-a-development-branch` — invoked automatically once every gap is fixed (`CONFORMS`) or carried open
|
|
219
219
|
|
|
220
220
|
**Subagents follow by default:**
|
|
221
221
|
|
|
@@ -57,7 +57,7 @@ Skip any step = lying, not verifying
|
|
|
57
57
|
| Regression test works | Red-green cycle verified | Test passes once |
|
|
58
58
|
| Agent completed | VCS diff shows changes | Agent reports "success" |
|
|
59
59
|
| Requirements met | Line-by-line checklist | Tests passing |
|
|
60
|
-
| Intent delivered (loop closed) | Fresh reviewer audits code+doc vs origin spec + prompt (`reference/conformance-check.md`
|
|
60
|
+
| Intent delivered (loop closed) | Fresh reviewer audits code+doc vs origin spec + prompt; verify completes when every gap is `CONFORMS` or carried-open as a deferred `accept`/`rescope`/`UNAUTHORIZED` gap - the sole non-completing terminal state is escalation (cap reached with an unresolved `fix` gap). Partition, fix loop, and `## Closure / conformance` schema: `reference/conformance-check.md` | Plan-vs-code review, tests passing |
|
|
61
61
|
|
|
62
62
|
## Rationalization Prevention
|
|
63
63
|
|
|
@@ -89,132 +89,145 @@ The reviewer **proposes, it does not dispose.** It emits structured gap blocks
|
|
|
89
89
|
the verify gate) drives disposition, fixes, and re-audit. The reviewer never edits,
|
|
90
90
|
dispatches, or re-audits itself.
|
|
91
91
|
|
|
92
|
-
###
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
92
|
+
### Disposition — verdict-then-`recommended` partition, no menu
|
|
93
|
+
|
|
94
|
+
Render the enumerated gap list — each as `Gn [VERDICT] origin — remediation
|
|
95
|
+
(recommended: fix|accept|rescope)` — then partition and act, in this exact order.
|
|
96
|
+
No prompt, no menu: this partition is deterministic and exhaustive.
|
|
97
|
+
|
|
98
|
+
1. **Verdict `CONFORMS`** (no gaps) → record the verdict in the completion
|
|
99
|
+
summary's closure section and proceed. No loop.
|
|
100
|
+
2. **Any gap is `UNAUTHORIZED`** → that gap **always** defers to the finish gate,
|
|
101
|
+
regardless of its `recommended` value. Never auto-remove or auto-accept
|
|
102
|
+
unrequested code here.
|
|
103
|
+
3. **Every remaining `PARTIAL`/`MISSING`/`DRIFTED` gap**:
|
|
104
|
+
- `recommended: fix` → auto-run the fix loop below — **unless `maxFixRounds:
|
|
105
|
+
0`**, in which case carry the gap **OPEN** (see the fix loop's
|
|
106
|
+
`maxFixRounds: 0` note).
|
|
107
|
+
- `recommended: accept` or `recommended: rescope` → carry the gap **OPEN**,
|
|
108
|
+
deferred to the finish gate. Do not apply a spec edit here — the finish
|
|
109
|
+
gate owns disposition of deferred gaps.
|
|
110
|
+
|
|
111
|
+
So the fast path (all gaps `recommended: fix`, none `UNAUTHORIZED`, cap > 0)
|
|
112
|
+
therefore auto-runs the fix loop with no menu, stop, or confirmation; any other
|
|
113
|
+
mix carries the `accept`/`rescope`/`UNAUTHORIZED` gaps OPEN while the `fix` gaps
|
|
114
|
+
run. Record every gap's outcome (`CONFORMS`-closed or carried OPEN) in the
|
|
115
|
+
`## Closure / conformance` block (schema below).
|
|
116
|
+
|
|
117
|
+
**Re-partition after every re-audit.** A re-audit can introduce `Gn+1` or flip a
|
|
118
|
+
carried gap's `recommended`. Re-run steps 1-3 above over the **full current
|
|
119
|
+
open-gap set** each time the reviewer returns a report — never reuse a stale
|
|
120
|
+
partition from an earlier round.
|
|
121
|
+
|
|
122
|
+
### Fix loop — SDD Parallel-Wave mirror, per round
|
|
123
|
+
|
|
124
|
+
Mirrors `subagent-driven-development` Parallel-Wave Mode and reuses its
|
|
125
|
+
`plan_tracker` progress surface. Runs entirely inside the gate — it invokes
|
|
126
|
+
**no** `phase_tracker` calls (`phase_tracker({ phase: "implement" })` errors
|
|
127
|
+
while verify is `in_progress`) and does **not** enter SDD's phase machinery.
|
|
128
|
+
Only the fan-out/integrate/review shape and `plan_tracker` are reused.
|
|
129
|
+
|
|
130
|
+
**Precondition — worktree required.** The loop needs a worktree HEAD to branch
|
|
131
|
+
fixes from. On the ad-hoc `finishing-a-development-branch` paths that run in a
|
|
132
|
+
normal repo (`GIT_DIR == GIT_COMMON`) or detached HEAD, there is no such HEAD:
|
|
133
|
+
skip this loop, carry every `fix` gap OPEN, and resolve manually at finish
|
|
134
|
+
(`accept`/`rescope`/manual fix-in-place only).
|
|
135
|
+
|
|
136
|
+
Per round:
|
|
137
|
+
|
|
138
|
+
1. **`plan_tracker` init** with the round's gaps as tasks. Wave-prefix tasks
|
|
139
|
+
when the reviewer's `Parallel-safe:` line marks a `conflicts` pair (file OR
|
|
140
|
+
`touched-resources` overlap) — that pair runs in separate serial waves;
|
|
141
|
+
`disjoint` gaps share one wave. Lifecycle per gap: `pending` →
|
|
142
|
+
`in_progress` → `complete`. This re-init **replaces** the implement phase's
|
|
143
|
+
completed task list in the singleton widget — state-safe, since
|
|
144
|
+
`phase-tracker.ts` `applyPlanActivity` only auto-completes `implement`
|
|
145
|
+
while it is `in_progress`; the widget now shows fix-wave progress during
|
|
146
|
+
verify.
|
|
147
|
+
2. **Per gap** (task → `in_progress`): dispatch `implementer` (fresh context,
|
|
148
|
+
`worktree: true`, `cwd` = the conformance worktree, `touched-files` from the
|
|
149
|
+
gap block as an explicit ownership boundary) → dispatch `spec-reviewer` on
|
|
150
|
+
the gap-block reference contract below → task → `complete`.
|
|
151
|
+
3. **Integrate** serially via `git apply` onto the worktree HEAD, one gap's
|
|
152
|
+
patch at a time. Failure handling is inherited verbatim from
|
|
153
|
+
`dispatching-parallel-agents` "Review and Integrate": textual conflict →
|
|
154
|
+
re-run one agent sequentially with the other's integrated changes as
|
|
155
|
+
context; semantic conflict (applies clean, suite fails) → re-run the
|
|
156
|
+
offending task sequentially on integrated HEAD; a failed agent → integrate
|
|
157
|
+
the successes, then retry the failure with fresh context including the
|
|
158
|
+
integrated changes. A `BLOCKED`/`NEEDS_CONTEXT` return surfaces to the user.
|
|
159
|
+
4. **Test gate** on the integrated tree, using the project's canonical test
|
|
160
|
+
command. A failure re-enters the failure-handling rules above.
|
|
161
|
+
5. **`code-reviewer` once** on the round's cumulative fix delta (not per gap).
|
|
162
|
+
6. **Re-audit**: re-dispatch `conformance-reviewer` over the fixes **plus** the
|
|
163
|
+
regression guard (any prior-`DELIVERED` requirement whose `evidence` file
|
|
164
|
+
the fix diff touched). Pass the full prior conformance report (every row,
|
|
165
|
+
including DELIVERED rows and their `evidence` `file:line`) and the round's
|
|
166
|
+
fix diff. Inject `model:` call-site per `gauntlet_setting({ key:
|
|
167
|
+
"closureReview" }).model` — same mechanism as the initial audit; omit
|
|
168
|
+
`model:` when it is `undefined` to inherit the parent's model. The
|
|
169
|
+
phase-tracker closure guard blocks a dispatch that omits `model:` when
|
|
170
|
+
`closureReview.model` is set, and warns (non-blocking) on one whose model
|
|
171
|
+
differs.
|
|
172
|
+
7. **Converge or continue**: verdict `CONFORMS` → record it, done. Open gaps
|
|
173
|
+
within the cap → re-partition (per the rule above) and start the next
|
|
174
|
+
round. Cap (`gauntlet_setting({ key: "closureReview" }).maxFixRounds`,
|
|
175
|
+
default `2`, floors negatives at `0`, coerces non-integers to `2`) reached
|
|
176
|
+
with an open `fix` gap → **escalate to the human** with the per-gap
|
|
177
|
+
round-by-round verdict trail. Escalation is the sole non-completing
|
|
178
|
+
terminal state — no silent re-loop, no auto-ship.
|
|
179
|
+
|
|
180
|
+
Commit each per-gap fix with the message **`conformance fix Gn`** (durable,
|
|
181
|
+
`git log`-readable pre-squash) so the finish gate and any revert can identify
|
|
182
|
+
auto-applied fixes.
|
|
183
|
+
|
|
184
|
+
**`maxFixRounds: 0`**: skip this loop entirely. Every `recommended: fix` gap
|
|
185
|
+
becomes carried OPEN to the finish gate instead of auto-running — the user
|
|
186
|
+
opted out of auto-fix, so treat `fix` gaps like any other deferred gap. This
|
|
187
|
+
differs from a cap > 0 that is *exhausted*: that case escalates mid-verify
|
|
188
|
+
because the loop tried and could not converge.
|
|
189
|
+
|
|
190
|
+
### `spec-reviewer` gap-block reference contract
|
|
191
|
+
|
|
192
|
+
Per-gap `spec-reviewer` in step 2 above is a **pre-integration mechanical
|
|
193
|
+
check**, distinct from the round-level re-audit in step 6 (which still
|
|
194
|
+
references the *origin* — spec + original prompt — unchanged). Frame the
|
|
195
|
+
per-gap dispatch against the **gap block**, not a plan task:
|
|
196
|
+
|
|
197
|
+
- **Requirement** = the gap's `origin` + `remediation` (what must be true
|
|
198
|
+
after the fix).
|
|
199
|
+
- **Closure proof** = the patch satisfies that requirement within the gap's
|
|
200
|
+
`touched-files` — nothing missing, nothing extra.
|
|
201
|
+
- **Output** = `spec-reviewer`'s normal MATCH/DRIFT verdict, referenced to the
|
|
202
|
+
gap block instead of a plan task.
|
|
203
|
+
|
|
204
|
+
This is a task-framing contract in the dispatch, not a new persona.
|
|
205
|
+
|
|
206
|
+
## Closure / conformance
|
|
207
|
+
|
|
208
|
+
Emit this block in the verify completion summary. It is the durable handoff
|
|
209
|
+
`finishing-a-development-branch` Step 3.5 consumes — parseable even if session
|
|
210
|
+
context was pruned. Verify completes when every gap is either fixed
|
|
211
|
+
(`CONFORMS`) or carried OPEN as a deferred `accept`/`rescope`/`UNAUTHORIZED`
|
|
212
|
+
gap; escalation (cap reached with an open `fix` gap) is the one
|
|
213
|
+
non-completing terminal state.
|
|
214
|
+
|
|
215
|
+
For each carried-open gap:
|
|
101
216
|
|
|
102
217
|
```
|
|
103
|
-
|
|
104
|
-
|
|
218
|
+
Gn: <verdict> — recommended: <fix|accept|rescope> — touched-files: <paths>
|
|
219
|
+
round history: R1 <verdict/action>, R2 <verdict/action>, ...
|
|
105
220
|
```
|
|
106
221
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
Disposition semantics:
|
|
113
|
-
|
|
114
|
-
- `fix` — dispatch a remediation unit (below), then re-audit. For an `UNAUTHORIZED`
|
|
115
|
-
gap, "fix" = **remove** the unrequested code.
|
|
116
|
-
- `accept` — the **main session** (not a subagent) folds the deviation into the spec as
|
|
117
|
-
a dated decision (template below). For `UNAUTHORIZED`, accept = keep the behavior,
|
|
118
|
-
document it as intended.
|
|
119
|
-
- `rescope` — the main session records the requirement in the spec as an explicit
|
|
120
|
-
out-of-scope / deferred item, dated.
|
|
222
|
+
Then a single flat revert index of **every** `conformance fix Gn` commit the fix
|
|
223
|
+
loop produced this run — including gaps that later converged to `CONFORMS`
|
|
224
|
+
(a closed gap has no block above, so its commit lives only here) — since the
|
|
225
|
+
finish gate's revert option needs them all:
|
|
121
226
|
|
|
122
|
-
Dated-decision template (append to the spec's decisions/deviations section):
|
|
123
|
-
|
|
124
|
-
```
|
|
125
|
-
- YYYY-MM-DD accept|rescope Gn: <requirement/behavior> — <one-line rationale> (conformance gate)
|
|
126
227
|
```
|
|
127
|
-
|
|
128
|
-
**Commit accept/rescope spec edits BEFORE any fix wave dispatches:** pi-cohort
|
|
129
|
-
rejects a dirty tree on a `worktree: true` dispatch, and the re-audit must read the
|
|
130
|
-
amended spec. If a round has only accept/rescope and no `fix`, the edits land, the
|
|
131
|
-
verdict is recorded, and no re-audit runs.
|
|
132
|
-
|
|
133
|
-
### Fix dispatch — reuse dispatching-parallel-agents mechanics
|
|
134
|
-
|
|
135
|
-
Fixes reuse the `dispatching-parallel-agents` fan-out primitive. Invoke **no**
|
|
136
|
-
`phase_tracker` / `plan_tracker` calls and do **not** enter `subagent-driven-development`
|
|
137
|
-
Parallel-Wave Mode (that mode opens with `phase_tracker({ phase: "implement" })`, which
|
|
138
|
-
errors while the verify phase is `in_progress`, and needs a plan the fix loop lacks).
|
|
139
|
-
|
|
140
|
-
**Precondition — worktree required.** Fix-via-dispatch needs a worktree HEAD to branch
|
|
141
|
-
from. On the ad-hoc `finishing-a-development-branch` paths that run in a normal repo
|
|
142
|
-
(`GIT_DIR == GIT_COMMON`) or detached HEAD, there is no such HEAD: the menu offers
|
|
143
|
-
`accept` / `rescope` and **manual fix-in-place** only; unresolved gaps route to escalation.
|
|
144
|
-
The loop below applies only when the gate already runs inside a worktree.
|
|
145
|
-
|
|
146
|
-
**Wave grouping** comes from the reviewer's `Parallel-safe:` line: `disjoint` gaps form
|
|
147
|
-
one parallel wave; any `conflicts` pair splits into separate serial waves. A pair conflicts
|
|
148
|
-
on **file OR runtime-resource** overlap - two gaps whose fixes touch disjoint files but whose
|
|
149
|
-
verification shares a `touched-resources` entry (DB/schema, port, fixture, external service,
|
|
150
|
-
shared temp path) are **not** parallel-safe and run in separate serial waves, identical to
|
|
151
|
-
planned-execution wave grouping. This is why the reviewer certifies both axes.
|
|
152
|
-
|
|
153
|
-
**Dispatch shape** (mirrors `dispatching-parallel-agents`):
|
|
154
|
-
|
|
155
|
-
```ts
|
|
156
|
-
subagent({
|
|
157
|
-
context: "fresh",
|
|
158
|
-
worktree: true,
|
|
159
|
-
cwd: "<abs worktree path, from git rev-parse --show-toplevel>",
|
|
160
|
-
tasks: [
|
|
161
|
-
{ agent: "implementer",
|
|
162
|
-
task: "Close conformance gap G1. Origin requirement: <origin>. What's missing: " +
|
|
163
|
-
"<remediation>. Satisfy the requirement; do not expand scope. " +
|
|
164
|
-
"Ownership boundary — modify only: <touched-files>." },
|
|
165
|
-
// one task per disjoint gap in this wave
|
|
166
|
-
],
|
|
167
|
-
})
|
|
228
|
+
auto-applied fix commits: <Gn: SHA>, <Gm: SHA>, ... (revertable)
|
|
168
229
|
```
|
|
169
230
|
|
|
170
|
-
- Unit = `implementer`, fresh context, `worktree: true`, `cwd` = the conformance
|
|
171
|
-
worktree. Pass `touched-files` as an explicit ownership boundary.
|
|
172
|
-
- **Integrate** serially via `git apply` back onto the worktree HEAD — the fix ships in
|
|
173
|
-
the same worktree and rides `finishing-a-development-branch`'s squash. No new merge machinery.
|
|
174
|
-
- **Failure handling is inherited verbatim** from `dispatching-parallel-agents`
|
|
175
|
-
"Review and Integrate": textual conflict → re-run one agent sequentially with the
|
|
176
|
-
other's integrated changes as context; semantic conflict (applies clean, suite fails)
|
|
177
|
-
→ re-run the offending task sequentially on integrated HEAD; a failed agent → integrate
|
|
178
|
-
the successes, then retry the failure with fresh context including the integrated changes.
|
|
179
|
-
A `BLOCKED` / `NEEDS_CONTEXT` return surfaces to the user.
|
|
180
|
-
- **`code-reviewer` over the integrated fix delta, once per round** (not per gap) — gap
|
|
181
|
-
fixes land after the branch's final code review, so review the round's cumulative diff.
|
|
182
|
-
- **`spec-reviewer` is excluded** — plan-vs-code is the wrong reference point; the re-audit
|
|
183
|
-
checks fixes against the origin.
|
|
184
|
-
- **Test gate** on the integrated tree after the round's waves apply, using the project's
|
|
185
|
-
canonical test command. A failure re-enters the failure-handling rules above.
|
|
186
|
-
|
|
187
|
-
One round = dispatch waves → serial integrate → `code-reviewer` on round delta → test
|
|
188
|
-
gate → re-audit.
|
|
189
|
-
|
|
190
|
-
### Delta re-audit + cap
|
|
191
|
-
|
|
192
|
-
Re-dispatch `conformance-reviewer` for a delta-scoped re-audit. Pass:
|
|
193
|
-
|
|
194
|
-
- the **full prior conformance report** — every row including DELIVERED rows and their
|
|
195
|
-
`evidence` `file:line` (needed for the regression guard), not just gap IDs;
|
|
196
|
-
- the **fix diff** for the round.
|
|
197
|
-
|
|
198
|
-
The reviewer (not the orchestrator) computes the regression intersection: it re-verifies
|
|
199
|
-
the gaps marked `fix` this round **plus** any previously-DELIVERED requirement whose
|
|
200
|
-
`evidence` file appears in the fix diff. It reuses `G1..Gn`, marking each `DELIVERED`,
|
|
201
|
-
still-open with its prior verdict, or introducing `Gn+1`.
|
|
202
|
-
|
|
203
|
-
- The re-audit dispatch carries the **same call-site `model:` injection** as the initial
|
|
204
|
-
audit (when `piGauntlet.closureReview.model` is set, the phase-tracker closure guard
|
|
205
|
-
blocks a `conformance-reviewer` dispatch that omits `model:`, and warns — non-blocking —
|
|
206
|
-
on one whose model differs from the configured value).
|
|
207
|
-
- New or still-open gaps within the cap re-enter the menu above.
|
|
208
|
-
- **Cap: `gauntlet_setting({ key: "closureReview" }).maxFixRounds`** (the tool applies the
|
|
209
|
-
default `2`, floors negatives at `0`, and coerces non-integers to `2`). `0` = audit-only:
|
|
210
|
-
`GAPS` renders an accept/rescope-only menu and any unresolved gap escalates instead of
|
|
211
|
-
dispatching a fix.
|
|
212
|
-
- **On non-convergence** (cap reached with open gaps): **escalate to human** with the
|
|
213
|
-
per-gap round-by-round verdict trail. No silent re-loop, no auto-ship.
|
|
214
|
-
|
|
215
|
-
No completion claim stands over a gap that is neither fixed, accepted, nor rescoped.
|
|
216
|
-
"Surface, don't auto-fix": the orchestrator presents options, the user decides.
|
|
217
|
-
|
|
218
231
|
## Checklist
|
|
219
232
|
|
|
220
233
|
- [ ] Located canonical requirements (spec → prompt → ticket fallback)
|