pi-gauntlet 4.4.0 → 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 +29 -0
- package/README.md +2 -2
- package/agents/conformance-reviewer.md +4 -4
- package/extensions/phase-tracker.ts +6 -6
- package/extensions/plan-tracker.ts +1 -1
- package/package.json +1 -1
- package/skills/brainstorming/SKILL.md +25 -17
- 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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v4.4.1 - 2026-07-13
|
|
4
|
+
|
|
5
|
+
Gates ratify, not ceremony: two gauntlet gates now auto-apply mechanical/drafting
|
|
6
|
+
changes and stop the human only for a load-bearing decision, not ritual confirmation.
|
|
7
|
+
|
|
8
|
+
- **Conformance gate (`verification-before-completion/reference/conformance-check.md`,
|
|
9
|
+
`subagent-driven-development`, `verification-before-completion`):** GAPS handling is
|
|
10
|
+
a deterministic verdict-then-`recommended` partition, no menu. `fix` gaps auto-close
|
|
11
|
+
through an isolated SDD-mirror fix loop (per-gap `implementer` + `spec-reviewer` on a
|
|
12
|
+
gap-block contract, `plan_tracker` fix-wave progress, per-round `code-reviewer`, delta
|
|
13
|
+
re-audit with regression guard, `maxFixRounds` cap -> escalate). `accept`/`rescope`/
|
|
14
|
+
`UNAUTHORIZED` gaps carry OPEN to the finishing gate. New `## Closure / conformance`
|
|
15
|
+
handoff schema + `conformance fix Gn` commit convention.
|
|
16
|
+
- **Spec council (`roasting-the-spec`, `brainstorming`):** the main-loop model applies
|
|
17
|
+
the chair's apply-set before the single brainstorming review gate; a gate-only
|
|
18
|
+
Applied/Deferred/Rejected audit is recorded in the spec commit body. The verbatim
|
|
19
|
+
summary now reflects the final post-apply spec on both worker and council paths;
|
|
20
|
+
checklist item 10 reduced to a re-scan; revert valve at the gate.
|
|
21
|
+
- **`finishing-a-development-branch` Step 3.5:** enforced per-gap disposition gate
|
|
22
|
+
(accept-into-spec / rescope-into-spec / fix-now / custom disposition / revert) with
|
|
23
|
+
three-tier revert semantics.
|
|
24
|
+
- **`agents/conformance-reviewer.md`:** deterministic `UNAUTHORIZED` recommendation
|
|
25
|
+
(harmless -> accept, else fix).
|
|
26
|
+
- **Extensions (`phase-tracker.ts`, `plan-tracker.ts`):** `SHIP_ADVISORY` and the
|
|
27
|
+
`plan_tracker` tool description reworded to allow carried-open deferred gaps and
|
|
28
|
+
verify-phase fix waves (description strings only, no logic change).
|
|
29
|
+
- **`README.md`:** conformance gate auto-fixes requirement-restoring gaps, defers
|
|
30
|
+
spec-rewriting decisions to the finishing gate.
|
|
31
|
+
|
|
3
32
|
## v4.4.0 - 2026-07-12
|
|
4
33
|
|
|
5
34
|
Add an unconditional parallel context-gather step to `/skill:brainstorming`. Step 3's
|
package/README.md
CHANGED
|
@@ -38,7 +38,7 @@ Concretely, one change through the gauntlet:
|
|
|
38
38
|
1. You describe the change. **`brainstorming`** sets up an isolated worktree, explores the codebase, and turns your description into a written spec. A multi-model critique runs on it automatically. **You read and approve the spec - human gate 1.** No implementation code exists yet.
|
|
39
39
|
2. **`writing-plans`** decomposes the approved spec into atomic, independently-verifiable tasks, grouped into parallel waves where they don't touch the same files.
|
|
40
40
|
3. **`subagent-driven-development`** executes the plan one task at a time, each in a fresh subagent, behind spec-compliance review then code-quality review. TDD-locked: red, green, refactor.
|
|
41
|
-
4. **verify**: a whole-diff code review, then the **conformance gate** - a subagent reads the finished code and docs against your *original words* from step 1, not the plan, and reports per-requirement: delivered, partial, missing, drifted, or unauthorized. This gate is machine-blocked from being skipped.
|
|
41
|
+
4. **verify**: a whole-diff code review, then the **conformance gate** - a subagent reads the finished code and docs against your *original words* from step 1, not the plan, and reports per-requirement: delivered, partial, missing, drifted, or unauthorized. This gate is machine-blocked from being skipped. Requirement-restoring gaps (code drifted from the approved spec) auto-close through an isolated fix-and-re-audit loop with no prompt; only decisions that would *rewrite* your approved spec - accept, rescope, or removing unrequested code - are deferred to the finishing gate for your call.
|
|
42
42
|
5. **`finishing-a-development-branch`**: squash, PR, keep, or discard. **Human gate 2** - the only other decision you make.
|
|
43
43
|
|
|
44
44
|
```mermaid
|
|
@@ -74,7 +74,7 @@ pi-gauntlet is **opinionated**: every non-trivial change rides this one pipeline
|
|
|
74
74
|
| --- | --- |
|
|
75
75
|
| Gate | A machine-enforced checkpoint between phases (e.g. `complete verify` is blocked until conformance review has run). Not a suggestion. |
|
|
76
76
|
| Spec council | Multi-model critique of the spec before you see it (`roasting-the-spec`); falls back to a single-model critique if no council is configured. |
|
|
77
|
-
| Conformance gate | The closing check: does the delivered code + docs match your *original prompt*, not the derived plan? Per-requirement verdict,
|
|
77
|
+
| Conformance gate | The closing check: does the delivered code + docs match your *original prompt*, not the derived plan? Per-requirement verdict; auto-fixes requirement-restoring gaps, defers spec-rewriting decisions (accept/rescope/unauthorized) to the finishing gate. |
|
|
78
78
|
| Wave | A batch of plan tasks that don't touch the same files, dispatched to implementers in parallel. |
|
|
79
79
|
| Overrides file | `.pi/gauntlet-overrides.md` - where you put project-specific detail the generic skills don't know (CI command, worktree wrapper, routing rules). |
|
|
80
80
|
|
|
@@ -64,7 +64,7 @@ DELIVERED rows keep an `Rn` id; every non-DELIVERED row gets a durable `Gn` id r
|
|
|
64
64
|
## Structured gap blocks
|
|
65
65
|
|
|
66
66
|
After the coverage table, emit one fenced block per non-DELIVERED row so the
|
|
67
|
-
orchestrator can
|
|
67
|
+
orchestrator can partition and dispose of them mechanically. In a re-audit round
|
|
68
68
|
(see conformance-check.md "When the check finds gaps"), also emit a `DELIVERED`
|
|
69
69
|
block for any gap that closed, reusing its original `Gn` id.
|
|
70
70
|
|
|
@@ -122,15 +122,15 @@ disjointness rule does. When you cannot confidently certify a pair disjoint, mar
|
|
|
122
122
|
`recommended` is a proposal; you never decide, edit, dispatch, or re-audit.
|
|
123
123
|
|
|
124
124
|
- Default `fix` for every `PARTIAL` / `MISSING` / `DRIFTED` row.
|
|
125
|
-
-
|
|
126
|
-
|
|
125
|
+
- For every `UNAUTHORIZED` row: harmless → `accept` with a one-line rationale in
|
|
126
|
+
`remediation`; otherwise → `fix` (= remove the unrequested code).
|
|
127
127
|
- `rescope` only when the `origin` requirement is impractical to satisfy in this branch
|
|
128
128
|
(`rescope` is inapplicable to `UNAUTHORIZED` — there is no requirement to defer).
|
|
129
129
|
|
|
130
130
|
## Rules
|
|
131
131
|
|
|
132
132
|
- **Read-only. Never edit.** You audit; you do not fix.
|
|
133
|
-
- **Propose, do not dispose.** For each gap you may suggest a one-line remediation *direction*, but you do **not** decide
|
|
133
|
+
- **Propose, do not dispose.** For each gap you may suggest a one-line remediation *direction*, but you do **not** decide the disposition - the orchestrator auto-applies `fix` gaps and defers `accept`/`rescope`/`UNAUTHORIZED` to the user at the finish gate. Never present a fix as a decision you made.
|
|
134
134
|
- **Evidence or it didn't happen.** Cite a real `file:line` for every DELIVERED/PARTIAL. If you cannot, downgrade the row to MISSING.
|
|
135
135
|
- **Spec is canonical; the prompt catches what the spec dropped; the ticket is fallback only** when no spec exists.
|
|
136
136
|
- **Do not absorb origin drift silently** — flag every spec↔prompt/ticket disagreement.
|
|
@@ -71,12 +71,12 @@ const CLOSURE_GATE_ERROR =
|
|
|
71
71
|
' phase_tracker({ action: "skip", phase: "verify", reason: "<user waiver>" })';
|
|
72
72
|
|
|
73
73
|
const SHIP_ADVISORY =
|
|
74
|
-
"Verify is complete and ship is pending.
|
|
75
|
-
"
|
|
76
|
-
"/skill:finishing-a-development-branch
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
74
|
+
"Verify is complete and ship is pending. Verify may complete when the conformance\n" +
|
|
75
|
+
"verdict is CONFORMS, or every gap is either fixed or carried open as a deferred\n" +
|
|
76
|
+
"accept/rescope/unauthorized decision. Invoke /skill:finishing-a-development-branch\n" +
|
|
77
|
+
"now - do not add a 'ready to finish?' prompt; its disposition + squash/PR/keep/discard\n" +
|
|
78
|
+
"menu is the human gate that resolves any carried-open decision. Only reopen verify if\n" +
|
|
79
|
+
"a `fix` gap was left unresolved (neither fixed nor deferred).";
|
|
80
80
|
|
|
81
81
|
// --- Flow guards (spec 2026-06-17-gauntlet-flow-guards) ---
|
|
82
82
|
|
|
@@ -129,7 +129,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
129
129
|
name: "plan_tracker",
|
|
130
130
|
label: "Plan Tracker",
|
|
131
131
|
description:
|
|
132
|
-
"Track progress while EXECUTING an implementation plan
|
|
132
|
+
"Track progress while EXECUTING an implementation plan (the implement phase) or a verify-phase conformance fix wave. Actions: init (set task list), update (change task status), status (show current state), clear (remove plan). Do NOT use for brainstorming, research, or planning checklists: those phases are open-ended and a bounded task list misrepresents them as a fixed N-step process.",
|
|
133
133
|
parameters: PlanTrackerParams,
|
|
134
134
|
|
|
135
135
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
package/package.json
CHANGED
|
@@ -59,10 +59,10 @@ Work through the items below **in order**. This is your own checklist to follow,
|
|
|
59
59
|
6. **Present the design** — in sections, get approval after each
|
|
60
60
|
7. **Write the spec** — to `doc/specs/` (see [Filename Convention](#filename-convention))
|
|
61
61
|
8. **Spec self-review (lint)** — placeholder scan + internal consistency + documentation named, run inline
|
|
62
|
-
9. **Critique pass (auto-dispatched)** — scope + ambiguity; the spec council via `/skill:roasting-the-spec` when `gauntlet_setting` returns verdict `council
|
|
63
|
-
10. **Re-run placeholder scan** — after the critique pass returns,
|
|
64
|
-
11. **Generate spec summary** — dispatch a fresh, spec-only `spec-summarizer` writing to an absolute temp-dir path via `outputMode: "file-only"`, then `Read` that file back as the **last content-producing** tool call before composing the gate and render its contents **verbatim** at the top of the gate message — do not paraphrase, condense, re-section, or rewrite it (see [User Review Gate](#user-review-gate)); this is part of the existing gate, not a new one
|
|
65
|
-
12. **User review gate** — user reviews the
|
|
62
|
+
9. **Critique pass (auto-dispatched)** — scope + ambiguity; the spec council via `/skill:roasting-the-spec` when `gauntlet_setting` returns verdict `council` (it applies its apply-set, including any external-ref inlining, to the spec before returning — see [Spec Council](#spec-council-optional)), else a fresh `worker` that applies its own fixes in place
|
|
63
|
+
10. **Re-run placeholder scan** — after the critique pass returns, re-scan the **applied** spec for placeholders its edits may have introduced; surface any ambiguity the critique could not safely resolve at the user gate
|
|
64
|
+
11. **Generate spec summary** — dispatch a fresh, spec-only `spec-summarizer` over the **final (post-apply)** spec, writing to an absolute temp-dir path via `outputMode: "file-only"`, then `Read` that file back as the **last content-producing** tool call before composing the gate and render its contents **verbatim** at the top of the gate message — do not paraphrase, condense, re-section, or rewrite it (see [User Review Gate](#user-review-gate)); this is part of the existing gate, not a new one
|
|
65
|
+
12. **User review gate** — user reviews the applied spec's verbatim summary plus the council audit (Applied/Deferred/Rejected), with a revert valve for any applied council edit
|
|
66
66
|
13. **Transition** — only after approval, invoke `/skill:writing-plans`
|
|
67
67
|
|
|
68
68
|
## Project Routing
|
|
@@ -244,7 +244,7 @@ After writing the spec to `<project>/doc/specs/<filename>.md` (per [Filename Con
|
|
|
244
244
|
|
|
245
245
|
The first three checks — **placeholder scan**, **internal consistency**, and **documentation named** — are the inline **lint**: run them here at the main loop and fix what they surface. The last two — **scope** and **ambiguity** — are **not** run inline; they are the **critique pass**, auto-dispatched (per [Spec Council](#spec-council-optional)):
|
|
246
246
|
|
|
247
|
-
- **Council** (`gauntlet_setting({ key: "specCouncil" })` returns verdict `council`) → invoke `/skill:roasting-the-spec`; it runs the critique and
|
|
247
|
+
- **Council** (`gauntlet_setting({ key: "specCouncil" })` returns verdict `council`) → invoke `/skill:roasting-the-spec`; it runs the critique, derives dispositions, and **applies the apply-set to the spec** (including inlining any `external-ref:` cluster it has context for) **before returning** — see that skill for apply mechanics. It returns a structured audit: `Applied:` / `Deferred:` / `Rejected:`.
|
|
248
248
|
- **Otherwise** → dispatch one fresh `worker` that applies the scope + ambiguity checks and fixes them in place:
|
|
249
249
|
|
|
250
250
|
```
|
|
@@ -253,23 +253,24 @@ The first three checks — **placeholder scan**, **internal consistency**, and *
|
|
|
253
253
|
"Read the spec at <abs path to doc/specs/...>. Edit ONLY that file. Apply two checks and\n" +
|
|
254
254
|
"fix what you find in place: (1) Scope — does every paragraph serve the goal? Cut filler;\n" +
|
|
255
255
|
"state out-of-scope explicitly. (2) Ambiguity — is every 'we should' a concrete decision?\n" +
|
|
256
|
-
"Replace 'we could probably' with 'we will'/'we won't'. Also
|
|
257
|
-
"
|
|
258
|
-
"
|
|
259
|
-
"ambiguity you could NOT
|
|
256
|
+
"Replace 'we could probably' with 'we will'/'we won't'. Also inline any load-bearing\n" +
|
|
257
|
+
"external reference (ticket AC, commit SHA, doc) already given to you in the problem\n" +
|
|
258
|
+
"statement above; if the spec relies on one not provided here, flag it (do NOT fetch) in\n" +
|
|
259
|
+
"your summary. Return a summary of what you changed, and flag any ambiguity you could NOT\n" +
|
|
260
|
+
"safely resolve." })
|
|
260
261
|
```
|
|
261
262
|
|
|
262
263
|
`worker`'s model resolves from `subagents.agentOverrides.worker.model` in `settings.json` (unset → inherits the main loop); the dispatch passes no `model:`.
|
|
263
264
|
|
|
264
|
-
|
|
265
|
+
Both paths apply their fixes **before returning** — the council auto-applies inside `/skill:roasting-the-spec`, the worker edits the spec file directly. After the critique pass returns, re-run the placeholder scan over the **applied** spec to catch anything the edits introduced. If the worker flagged ambiguities it could not safely resolve, surface them in the [User Review Gate](#user-review-gate) message so the user decides - the worker auto-applies fixes but never silently swallows an open question.
|
|
265
266
|
|
|
266
267
|
## Spec Council (Optional)
|
|
267
268
|
|
|
268
|
-
After the inline lint and before the user review gate, **brainstorming owns the critique-pass gate
|
|
269
|
+
After the inline lint and before the user review gate, **brainstorming owns the critique-pass gate**; council **apply mechanics** live in `/skill:roasting-the-spec` (single source of truth - link, don't restate). Resolve the council with `gauntlet_setting({ key: "specCouncil" })` - the tool returns the merged (repo-over-preset) value as `{ verdict, members, chair, malformed, warning, errors }`. **Do not** hand-roll a settings read. When `verdict` is `"council"`, the council *is* the critique pass - invoke `/skill:roasting-the-spec` automatically (no offer, no prompt), passing `members`/`chair`; it applies its apply-set and returns the audit (Applied/Deferred/Rejected). When `verdict` is `"worker"`, run the fresh-`worker` critique instead (see [Spec Self-Review](#spec-self-review-before-user-review-gate)). If `malformed` is true or `errors` is non-empty, emit the `warning`/error as one line, then branch strictly on `verdict` - `malformed` can accompany *either* verdict (e.g. a bad `chair` with valid `members` still returns `council`), so never infer the worker path from `malformed` alone. If `gauntlet_setting` is unavailable, stop and report - never fall back to a manual bash/JSON settings merge. The already-applied council edits (or the worker's in-place fixes) ride in the same worktree commit. The conceptual precedence rule lives in `verification-before-completion/reference/settings-precedence.md`.
|
|
269
270
|
|
|
270
271
|
## User Review Gate
|
|
271
272
|
|
|
272
|
-
After self-review
|
|
273
|
+
After self-review and the critique pass (council or worker, both already applied to the spec - see [Spec Council](#spec-council-optional)), dispatch the spec-only summarizer over the **applied** spec, then commit the spec on the worktree branch and stop. This is the **same** single human gate - the summary is folded into it, not a new gate.
|
|
273
274
|
|
|
274
275
|
Mint an absolute temp path outside the worktree (so it is never committed), then dispatch the summarizer on a fresh context, reading only the spec, writing to that path via file-only output (no `model:` - it inherits the main loop unless a preset sets `subagents.agentOverrides.spec-summarizer.model`):
|
|
275
276
|
|
|
@@ -285,7 +286,7 @@ subagent({ agent: "spec-summarizer", context: "fresh", cwd: "<abs worktree path,
|
|
|
285
286
|
|
|
286
287
|
`<SUMMARY_PATH>` above is a placeholder in the dispatch object; it means substitute the value of the shell variable `$SUMMARY_PATH` set above. The steps below use `$SUMMARY_PATH` (the shell form) once the value is in hand.
|
|
287
288
|
|
|
288
|
-
Then commit the spec — this commit is **unconditional**: the summary is only a gate aid, so a degraded or missing summary never blocks it. Evaluate the summary in two stages (the **Degrade path** referenced in each is defined just below):
|
|
289
|
+
Then commit the spec — this commit is **unconditional**: the summary is only a gate aid, so a degraded or missing summary never blocks it. If the council path ran, include its audit (`Applied:` / `Deferred:` / `Rejected:`, verbatim from `/skill:roasting-the-spec`'s return) in the **commit message body** - this is the durable, non-contractual record a finish-time revert reads back; the audit is never a committed spec section. Evaluate the summary in two stages (the **Degrade path** referenced in each is defined just below):
|
|
289
290
|
|
|
290
291
|
1. **From the dispatch tool result, before the `Read`.** If the result is **not** an `"Output saved to: <path> (<N> KB, <M> lines)"` reference (e.g. an exit-0 save error returns the full inline output plus an "Output file error" line — the prunable shape, no file to read), or the reference reports under ~500 bytes, or a size grossly disproportionate to the spec (under ~2% of its byte size), or over ~45 KB (the `Read` truncates at 50KB / 2000 lines, so a larger file cannot render whole) — skip the `Read` and take the degrade path. Use the reference's reported figures; do not re-derive them.
|
|
291
292
|
2. **The `Read` itself, as the last content-producing tool call before composing the gate.** `Read` `$SUMMARY_PATH` and paste its contents verbatim at the top of the gate. If the `Read` fails, returns 0 bytes, or reports truncation — take the degrade path. The `Read` must be last: pi-condense does not protect a `/tmp` read, so any turn boundary between the `Read` and the render lets the ~9KB read result be pruned, reproducing the bug.
|
|
@@ -294,21 +295,28 @@ Then commit the spec — this commit is **unconditional**: the summary is only a
|
|
|
294
295
|
|
|
295
296
|
Either way — summary rendered or degraded — then `rm "$SUMMARY_PATH"` (unconditional cleanup; harmless if the file was never created, since it lives outside the worktree under the OS temp dir).
|
|
296
297
|
|
|
297
|
-
Render the temp file's contents **verbatim** first — paste it as-is, do **not** paraphrase, condense, re-section, drop sections, or merge it with council
|
|
298
|
+
Render the temp file's contents **verbatim** first — paste it as-is, do **not** paraphrase, condense, re-section, drop sections, or merge it with the council audit. "Fold into the gate" means *place it inside the gate message*, not *rewrite it*. This summary is of the **final (post-apply)** spec, since both critique paths already applied before this dispatch. After the verbatim block, append the commit confirmation, then — as their **own** adjacent lines, not edits to the summary — the council audit (if the council path ran: `Applied:` / `Deferred:` / `Rejected:`, one line each), critique-pass-unresolved ambiguities, and every entry from the summarizer's gap/external-context footer (surface **all** of them, not just the top risk):
|
|
298
299
|
|
|
299
300
|
```
|
|
300
301
|
<spec-only summary read back from the temp file — pasted verbatim, unedited>
|
|
301
302
|
|
|
302
303
|
Spec written and committed to <project>/doc/specs/<filename>.md (worktree: <path>).
|
|
303
304
|
|
|
304
|
-
<
|
|
305
|
+
Applied: <cluster -> edit>, ...
|
|
306
|
+
Deferred: <cluster -> where it belongs>, ...
|
|
307
|
+
Rejected: <cluster -> one-line reason>, ...
|
|
308
|
+
(omit the three lines above when the worker path ran, not the council)
|
|
305
309
|
|
|
306
|
-
|
|
310
|
+
<unresolved ambiguities; every gap-footer entry from the summary>
|
|
311
|
+
|
|
312
|
+
Please review. Approve to proceed, tell me what to change in the spec, or say "revert applied council edit <X>" to undo a specific applied edit.
|
|
307
313
|
```
|
|
308
314
|
|
|
309
315
|
If you believe the summary needs correcting, do **not** silently rewrite it — re-dispatch the summarizer or note the discrepancy as an adjacent line beneath the verbatim block.
|
|
310
316
|
|
|
311
|
-
|
|
317
|
+
**Revert valve.** "Revert applied council edit X" is a normal change request: revise the spec to undo edit X, re-dispatch the summarizer with a **fresh** temp path (per the re-dispatch rule below), and re-present the gate. This is cheap here - the spec is not yet plan- or code-bearing.
|
|
318
|
+
|
|
319
|
+
Wait for the user. On a change request (including a revert), revise the spec and re-present — mint a **fresh** temp path for the re-dispatched summarizer (never reuse a prior round's path, so stale content can never be mistaken for the new summary). On approval, proceed immediately to `/skill:writing-plans` with no further prompt — the plan and execution mode are mechanical derivatives, so the only human gate here is spec approval itself. Don't land the spec on `main`; it stays in the worktree and ships in the same squash commit as the implementation.
|
|
312
320
|
|
|
313
321
|
After approval, mark the brainstorm phase complete:
|
|
314
322
|
|
|
@@ -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)
|