pi-gauntlet 4.4.1 → 4.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -0
- package/README.md +2 -2
- package/package.json +1 -1
- package/skills/finishing-a-development-branch/SKILL.md +67 -22
- package/skills/subagent-driven-development/SKILL.md +3 -3
- package/skills/verification-before-completion/SKILL.md +1 -1
- package/skills/verification-before-completion/reference/conformance-check.md +249 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v4.4.2 - 2026-07-15
|
|
4
|
+
|
|
5
|
+
Condense the finish-time conformance disposition gate to a dense, human-readable
|
|
6
|
+
decision list - the corrective second pass over v4.4.1's disposition work, which
|
|
7
|
+
delivered the right behavior but bloated the render and the freshness protocol.
|
|
8
|
+
|
|
9
|
+
- **Finish gate (`finishing-a-development-branch`):** carried-open conformance
|
|
10
|
+
findings now render as a dense one-line-per-decision list - each line carries a
|
|
11
|
+
plain-language title, the unresolved point, its question, and an inline recommended
|
|
12
|
+
choice - with a two-option reply (`1` = every recommendation; `2:` =
|
|
13
|
+
recommended-except comma-separated `<handle>=<choice>` overrides). Replaces the
|
|
14
|
+
terse `Gn` tokens and the flat D1-D5 per-gap menu. Single-concern gaps show no
|
|
15
|
+
`/Cn` symbol; `UNAUTHORIZED` items note availability deviations inline; the
|
|
16
|
+
zero-gap path still goes straight to branch options with no sign-off.
|
|
17
|
+
- **Freshness (`verification-before-completion/reference/conformance-check.md`,
|
|
18
|
+
`finishing-a-development-branch`, `subagent-driven-development`):** the four-field
|
|
19
|
+
audit-identity/hash protocol (duplicated across three files) collapses to a
|
|
20
|
+
`status`/`audited-base` sentinel plus a two-command working-tree drift check;
|
|
21
|
+
any change or doubt re-audits. The durable `## Closure / conformance` handoff
|
|
22
|
+
header drops `audited-spec-path`/`audited-diff-hash`/`audited-spec-hash`.
|
|
23
|
+
- **De-duplication:** the disposition-availability table, the `UNAUTHORIZED`
|
|
24
|
+
question, the `recommended: none` preflight, and the fix loop now live only in
|
|
25
|
+
`conformance-check.md`; the finish gate and SDD consume them by link.
|
|
26
|
+
|
|
3
27
|
## v4.4.1 - 2026-07-13
|
|
4
28
|
|
|
5
29
|
Gates ratify, not ceremony: two gauntlet gates now auto-apply mechanical/drafting
|
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. Compatible executable recommendations auto-run through an isolated fix-and-re-audit loop with no prompt; anything still open surfaces as a dense list - one line per decision, plain-language, with its recommended choice inline. Reply `1` to take every recommendation, or `2:` with per-item overrides; a current `CONFORMS` / no-concerns result goes straight to the branch options with no extra conformance sign-off.
|
|
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?
|
|
77
|
+
| Conformance gate | The closing check: does the delivered code + docs match your *original prompt*, not the derived plan? Compatible executable recommendations auto-fix first; anything still open renders as a dense one-line-per-decision list with each recommended choice inline. Reply `1` to accept all recommendations or `2:` with per-item overrides; a current `CONFORMS` / no-concerns handoff goes straight to branch options with no extra sign-off. |
|
|
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
|
|
package/package.json
CHANGED
|
@@ -72,46 +72,91 @@ Or ask: "This branch split from main - is that correct?"
|
|
|
72
72
|
|
|
73
73
|
### Step 3.5: Closure / Conformance Disposition Gate
|
|
74
74
|
|
|
75
|
-
This is an **enforced
|
|
75
|
+
This is an **enforced disposition gate**, not a surface-only notice. The user is about to choose how to ship; every carried-open decision 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
|
-
**
|
|
77
|
+
`verification-before-completion/reference/conformance-check.md` is **canonical** for the durable handoff schema, concern-decomposition rules, the single disposition-availability table, the `UNAUTHORIZED` question text, the `recommended: none` preflight, the freshness rule, and the concern-scoped fix projection. This step owns only **render, response, and execute-order** and consumes the rest by link - it does not restate the availability table, the `UNAUTHORIZED` question, or the preflight prose.
|
|
78
78
|
|
|
79
|
-
**If
|
|
79
|
+
**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 that reference - it owns the audit-time input rule (stage/commit untracked deliverables before auditing). Closing the loop is cheap relative to shipping unverified intent. Route the raw reviewer verdict through the reference's canonical pipeline (gap/concern partition, auto-fix where eligible, concern decomposition, emission of a durable `## Closure / conformance` block), then consume that block through the branching below exactly as a carried handoff.
|
|
80
80
|
|
|
81
|
-
**
|
|
81
|
+
**Freshness precondition - before any verdict branch, including `CONFORMS`.** The durable block opens with a two-line sentinel: `status: CONFORMS (0 open)` or `status: GAPS (N open)`, then `audited-base: <full HEAD SHA at audit time>`. Read the sentinel, then apply the reference's freshness rule (its `## Closure / conformance` block is the single source): compare `audited-base` to the current working tree; any change, doubt, missing/mismatched sentinel, legacy terse row, or malformed structured reviewer block triggers a fresh audit and replacement of the closure block. Never infer `CONFORMS` from the absence of bullets. Only a clean, valid `status: CONFORMS (0 open)` handoff enters the zero-gap fast path.
|
|
82
82
|
|
|
83
|
+
**Zero-gap fast path:** print exactly
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
Closure / conformance: CONFORMS
|
|
83
87
|
```
|
|
84
|
-
G<n>: <verdict> — recommended: <fix|accept|rescope> — touched-files: <paths>
|
|
85
|
-
round history: R1 ..., R2 ...
|
|
86
88
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
then continue directly to Step 4. No approval prompt, no menu, no shared options line, no sign-off. If the run auto-applied fixes, surface the flat `auto-applied fix commits: <Gn: SHA>, ...` index from the durable block as **one informational, non-blocking line** with a one-line revert offer (see "Revert semantics") - a gap that auto-converged mid-verify has no bullet, so this index is the only place its fix commit stays revertable. Do not wait for acknowledgment.
|
|
90
|
+
|
|
91
|
+
**Carried-open render (dense).** Read the `## Closure / conformance` block. Render a header with the decision count, one bullet per decision unit (a gap by default; a `Gn/Cn` concern only where the reference split it), then the shared options line, then the recommended-set reply. Never show durable-card internals (ownership, evidence tokens, identity, hashes) in the render.
|
|
92
|
+
|
|
93
|
+
Each bullet:
|
|
92
94
|
|
|
93
|
-
|
|
95
|
+
`* <handle> - <plain title>: <what's unresolved, one clause>. <short question> Recommended: <choice> (<one-clause why>).`
|
|
96
|
+
|
|
97
|
+
- `<handle>` leads the bullet and is a short unique human word derived from the title (`Cache coverage` -> `cache`); on collision append a digit. It is the token option 2 targets. When a gap split and no clean word fits, use the bare `Gn/Cn`; a single-concern gap uses its gap ID `Gn`.
|
|
98
|
+
- The shared options line sits below the bullets: `Other options per item: fix-now / accept / rescope / follow-up / custom`, listing the options **generally available across items**. When a specific item's availability deviates - an option unavailable for it, or an `UNAUTHORIZED` item whose `rescope` is unavailable and whose `fix-now` means removal - note that deviation as a short parenthetical on **that item's bullet** (one clause, not a block), e.g. `(rescope N/A: scope creep)`. The shared line appears **only in the carried-open render**, never in the zero-gap path. Full per-option effects only on request, or when option 2 targets an unclear choice.
|
|
99
|
+
- Group items under one recommended line only when they share a disposition and rationale; each grouped handle repeats its title.
|
|
100
|
+
- Availability per concern comes from the reference's single availability table - apply it against current context (worktree state, `maxFixRounds`, ownership, resource accessibility), do not restate it. `UNAUTHORIZED` bullets ask the reference's question verbatim (`Should this unrequested behavior become part of the current workflow?`); `rescope-into-spec` is shown **unavailable** (not dropped) and `fix-now` means **removal** of the unrequested code.
|
|
101
|
+
- `revert conformance fix Gn`, when the gap has an auto-applied fix, renders on the shared options line as a **separate one-off action** - never inside a bullet's recommendation and never in the option-2 list. Name the parent gap and warn that revert undoes the entire gap-level commit (see "Revert semantics").
|
|
102
|
+
|
|
103
|
+
Representative carried-open render (multi-concern gap split to `e2e`; single-concern gap `cache`; `UNAUTHORIZED` gap `auth`):
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
Conformance: 3 decisions needed before shipping.
|
|
107
|
+
|
|
108
|
+
* e2e - Source-image E2E validation: not run; blocked (HYDRA1.png, HTTP 401).
|
|
109
|
+
Still in scope for this branch? Recommended: rescope (defer until image available) (fix-now N/A: needs HYDRA1.png).
|
|
110
|
+
* cache - Cache coverage: implemented but the spec is silent on it.
|
|
111
|
+
In scope? Recommended: accept into spec (behavior is intentional).
|
|
112
|
+
* auth - Unrequested admin bypass: adds an unlisted route. Should this unrequested behavior become part of the current workflow? Recommended: fix-now = remove it (rescope N/A: scope creep).
|
|
113
|
+
|
|
114
|
+
Other options per item: fix-now / accept / rescope / follow-up / custom.
|
|
115
|
+
|
|
116
|
+
1. Go with recommended
|
|
117
|
+
2. Recommended except <handle>=<choice> e.g. "2: cache=follow-up"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
A single-concern render is identical minus the split: one bullet whose handle is the gap ID or word, no sibling.
|
|
121
|
+
|
|
122
|
+
#### Response grammar
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
1 -> apply every recommendation
|
|
126
|
+
2: cache=follow-up
|
|
127
|
+
2: e2e=custom(open ticket after image lands), cache=follow-up
|
|
94
128
|
```
|
|
95
129
|
|
|
96
|
-
|
|
130
|
+
- `1` (or `apply recommended`) applies all recommendations.
|
|
131
|
+
- `2:` takes a comma-separated override list, each `<handle>=<choice>`; omitted items keep their recommendation. A handle may appear at most once (repeat = invalid).
|
|
132
|
+
- `custom(<concrete effect>)` supplies an inline effect. Manual fix-in-place is expressed only as `custom(...)` where isolated `fix-now` is unavailable.
|
|
133
|
+
- `recommended: none` items follow the reference's preflight (linked, not restated): the item needs a `<handle>=custom(...)` decision, and option 1 is withheld until every open item has an executable recommendation; after the custom decision the menu re-renders for the remainder.
|
|
134
|
+
- `revert conformance fix Gn` is a valid standalone reply, mutually exclusive with `1` and `2:`; it never appears inside a `2:` override list.
|
|
135
|
+
- Invalid handle or choice -> focused reprompt naming only that item, retaining every valid pick and never reopening the gate. Unknown token: list the valid titled handles. Known item, bad choice: repeat its title + its available choices.
|
|
97
136
|
|
|
98
|
-
|
|
137
|
+
#### Execute order
|
|
99
138
|
|
|
100
|
-
|
|
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.
|
|
139
|
+
Take **no** disposition action before the reply. Then, once, in order:
|
|
104
140
|
|
|
105
|
-
**
|
|
141
|
+
1. **Normalize** every `custom(...)` into explicit operations; classify state-changing (edits code or spec) vs not. Clarify only an ambiguous or unexecutable effect.
|
|
142
|
+
2. **Commit spec edits** (`accept-into-spec`, `rescope-into-spec`, state-changing spec `custom`) - the main session edits the spec directly, before any fix dispatch (a dirty tree rejects `worktree: true`, and the re-audit must read the amended spec).
|
|
143
|
+
3. **Re-audit if step 2 changed the spec**; regenerate the inventory and re-render if it changed. Project `fix-now` only from the refreshed inventory.
|
|
144
|
+
4. **fix-now + code-changing custom:** project the selected concerns per gap into the reference's concern-scoped fix contract (excluding accepted/rescoped/followed-up siblings); run the reference "Fix loop" (unchanged - do not re-describe it). A code-changing `custom` runs the project's tests + `code-reviewer` on its delta before proceeding. Re-run Step 1's canonical tests.
|
|
145
|
+
5. **Re-audit after all state-changing work;** obtain fresh decisions **only if** the refreshed inventory differs from the approved one, else proceed.
|
|
146
|
+
6. **follow-up** from the current inventory: create the item via the project's issue-tracker convention (`.pi/gauntlet-overrides.md`), record the ticket ID/URL; on failure keep the concern open.
|
|
147
|
+
7. **Non-state-changing custom:** execute and record the result.
|
|
148
|
+
8. **revert** (`revert conformance fix Gn`): light-revert the indexed commit, re-run Step 1's canonical tests; on failure stop; on pass re-audit and regenerate.
|
|
149
|
+
9. Re-enter Step 3.5 with the re-audited block if any concern remains open.
|
|
106
150
|
|
|
107
|
-
|
|
151
|
+
Record every final disposition with its **stable ID** as `Gn/Cn - <title>: <disposition>` (or `Gn - <title>: <disposition>` for a single-concern gap) - ticket ID/URL for `follow-up`, result for `custom`; never relabel a `custom` result as a recommendation. This durable record is the machine/audit surface; the interactive render stays handle-based. Then continue to Step 4:
|
|
108
152
|
|
|
109
153
|
```
|
|
110
154
|
Closure / conformance: CONFORMS
|
|
111
|
-
(or: GAPS
|
|
155
|
+
(or: GAPS resolved - G1/C1 - Source-image E2E validation: rescope-into-spec;
|
|
156
|
+
G2 - Cache coverage: follow-up (PROJ-123); ...)
|
|
112
157
|
```
|
|
113
158
|
|
|
114
|
-
|
|
159
|
+
No auto-proceed: every carried-open decision needs an explicit disposition before Step 4 renders.
|
|
115
160
|
|
|
116
161
|
### Revert semantics
|
|
117
162
|
|
|
@@ -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.
|
|
194
|
-
3. Summarize what was implemented (tasks completed, files changed, test counts, code-review verdict). Emit the `## Closure / conformance` block
|
|
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
|
|
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. Follow that reference for the partition rule, concern decomposition, and fix-loop mechanics; do not reimplement them here. The fix loop may drive `plan_tracker` to surface fix-wave progress (task name = `Gn: <short desc>`, lifecycle `pending → in_progress → complete` per gap); it never calls `phase_tracker`. Call `phase_tracker({ action: "complete", phase: "verify" })` only when the reference says the handoff is durably complete: either a current `CONFORMS` result, or a current `## Closure / conformance` inventory whose carried-open concerns all come from valid deferred gaps, including `recommended: fix` gaps carried open because a declared precondition made the fix loop unavailable (`maxFixRounds: 0`, or no eligible named-branch worktree). A started positive-cap fix loop that blocks, fails, or exhausts its rounds with an open `fix` gap is escalation, not completion; on escalation, do not complete verify, stop and report.
|
|
194
|
+
3. Summarize what was implemented (tasks completed, files changed, test counts, code-review verdict). Emit the `## Closure / conformance` block exactly as defined in `verification-before-completion/reference/conformance-check.md`: it must open with the two-line sentinel (`status: CONFORMS (0 open)` or `status: GAPS (N open)`, then `audited-base: <full HEAD SHA>`), then carry the exact durable concern schema by reference with no renamed or reformatted fields. `finishing-a-development-branch` Step 3.5 consumes that block verbatim.
|
|
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 concerns are resolved there per concern via the `## Closure / conformance` block from step 3. 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
|
|
|
@@ -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; verify completes
|
|
60
|
+
| Intent delivered (loop closed) | Fresh reviewer audits code+doc vs origin spec + prompt; verify completes only on a current `CONFORMS` result or a current durable carried-open closure inventory permitted by `reference/conformance-check.md` (including declared-precondition-unavailable `recommended: fix` gaps). A started positive-cap fix loop that blocks, fails, or exhausts rounds with an open `fix` gap is escalation, not completion. | Plan-vs-code review, tests passing |
|
|
61
61
|
|
|
62
62
|
## Rationalization Prevention
|
|
63
63
|
|
|
@@ -101,17 +101,18 @@ No prompt, no menu: this partition is deterministic and exhaustive.
|
|
|
101
101
|
regardless of its `recommended` value. Never auto-remove or auto-accept
|
|
102
102
|
unrequested code here.
|
|
103
103
|
3. **Every remaining `PARTIAL`/`MISSING`/`DRIFTED` gap**:
|
|
104
|
-
- `recommended: fix` → auto-run the fix loop below — **unless
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
- `recommended: fix` → auto-run the fix loop below — **unless a declared
|
|
105
|
+
fix-loop precondition is unavailable** (`maxFixRounds: 0`, or no eligible
|
|
106
|
+
named-branch worktree), in which case carry the gap **OPEN** (see the fix
|
|
107
|
+
loop's precondition and `maxFixRounds: 0` notes).
|
|
107
108
|
- `recommended: accept` or `recommended: rescope` → carry the gap **OPEN**,
|
|
108
109
|
deferred to the finish gate. Do not apply a spec edit here — the finish
|
|
109
110
|
gate owns disposition of deferred gaps.
|
|
110
111
|
|
|
111
|
-
So the fast path (all gaps `recommended: fix`, none `UNAUTHORIZED`, cap > 0
|
|
112
|
-
therefore auto-runs the fix loop with no menu,
|
|
113
|
-
|
|
114
|
-
run. Record every gap's outcome (`CONFORMS`-closed or carried OPEN) in the
|
|
112
|
+
So the fast path (all gaps `recommended: fix`, none `UNAUTHORIZED`, cap > 0,
|
|
113
|
+
eligible named-branch worktree) therefore auto-runs the fix loop with no menu,
|
|
114
|
+
stop, or confirmation; any other mix carries the
|
|
115
|
+
`accept`/`rescope`/`UNAUTHORIZED` gaps OPEN while the `fix` gaps run. Record every gap's outcome (`CONFORMS`-closed or carried OPEN) in the
|
|
115
116
|
`## Closure / conformance` block (schema below).
|
|
116
117
|
|
|
117
118
|
**Re-partition after every re-audit.** A re-audit can introduce `Gn+1` or flip a
|
|
@@ -130,8 +131,10 @@ Only the fan-out/integrate/review shape and `plan_tracker` are reused.
|
|
|
130
131
|
**Precondition — worktree required.** The loop needs a worktree HEAD to branch
|
|
131
132
|
fixes from. On the ad-hoc `finishing-a-development-branch` paths that run in a
|
|
132
133
|
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
|
|
134
|
-
|
|
134
|
+
skip this loop, carry every `fix` gap OPEN, and resolve it at finish via the
|
|
135
|
+
canonical Disposition catalog and availability table below. `fix-now` is
|
|
136
|
+
unavailable there; any other disposition is offered only when its table
|
|
137
|
+
prerequisites hold.
|
|
135
138
|
|
|
136
139
|
Per round:
|
|
137
140
|
|
|
@@ -203,31 +206,262 @@ per-gap dispatch against the **gap block**, not a plan task:
|
|
|
203
206
|
|
|
204
207
|
This is a task-framing contract in the dispatch, not a new persona.
|
|
205
208
|
|
|
209
|
+
## Concern decomposition
|
|
210
|
+
|
|
211
|
+
The main verification orchestrator — **not** `conformance-reviewer` — decomposes
|
|
212
|
+
each carried-open gap into concerns when it writes the completion summary. A
|
|
213
|
+
**gap** is the reviewer's overall finding; a **concern** (`Gn/Cn`) is one
|
|
214
|
+
consequence within it that could reasonably receive a *different* disposition.
|
|
215
|
+
Observations that necessarily move together stay one concern.
|
|
216
|
+
|
|
217
|
+
The orchestrator reasons from:
|
|
218
|
+
|
|
219
|
+
- The final reviewer coverage row and structured gap block.
|
|
220
|
+
- The origin spec and original prompt already supplied to verification.
|
|
221
|
+
- Session-observed blockers, prerequisite checks, and fix-loop outcomes.
|
|
222
|
+
- The round history and current touched-file/resource ownership.
|
|
223
|
+
|
|
224
|
+
Per gap, apply these rules **in order**:
|
|
225
|
+
|
|
226
|
+
1. Extract atomic unmet clauses and remediation actions from `origin`,
|
|
227
|
+
`evidence`, and `remediation`. Add a session-observed blocker **only** when a
|
|
228
|
+
tool result or fix-loop outcome established it.
|
|
229
|
+
2. **Split** two points when either could be fixed, accepted, rescoped, or
|
|
230
|
+
followed up without imposing the same disposition on the other.
|
|
231
|
+
3. **Keep together** when one action is meaningful only with the other, or no
|
|
232
|
+
different disposition could be executed independently.
|
|
233
|
+
4. Map **every** unmet clause, remediation action, and established blocker to at
|
|
234
|
+
least one concern. Do **not** add a requirement absent from the origin or
|
|
235
|
+
prompt — invent nothing.
|
|
236
|
+
5. Order concerns by first appearance in the origin/remediation and assign
|
|
237
|
+
`C1`, `C2`, and so on (source order).
|
|
238
|
+
|
|
239
|
+
A valid decomposition has no omitted source point, no invented requirement or
|
|
240
|
+
evidence, and a concern-scoped remediation plus ownership estimate for every
|
|
241
|
+
`fix-now` candidate. Shared evidence may appear in multiple concerns. When the
|
|
242
|
+
source cannot support a safe split, the fallback is **one indivisible `Gn/C1`**
|
|
243
|
+
concern carrying the complete gap and the known blocker; decomposition never
|
|
244
|
+
blocks on obtaining richer prose from the unchanged reviewer.
|
|
245
|
+
|
|
246
|
+
Field derivation is explicit: `title` and `unresolved` summarize the unmet
|
|
247
|
+
clause; `origin` narrows the gap `origin` to this concern's specific clause
|
|
248
|
+
without inventing a new requirement; `remediation` states the concern-scoped
|
|
249
|
+
remediation action drawn from the gap `remediation`; `impact` states the
|
|
250
|
+
consequence already implied by the origin requirement; `evidence` copies
|
|
251
|
+
reviewer evidence plus verified session observations;
|
|
252
|
+
`touched-files`/`touched-resources` narrow the gap ownership where supported,
|
|
253
|
+
otherwise `unknown`/`none`. For an `UNAUTHORIZED` concern there is no origin
|
|
254
|
+
requirement to narrow: keep `origin: none (scope creep)` verbatim — never invent
|
|
255
|
+
an origin clause; derive `unresolved` from the reviewer's `evidence`/`remediation`
|
|
256
|
+
as a plain description of the unrequested behavior; and derive `impact` from the
|
|
257
|
+
consequence of retaining, removing, or ratifying that behavior, not from an origin
|
|
258
|
+
requirement. These per-concern fields persist the exact contract
|
|
259
|
+
the concern-scoped fix projection consumes after pruning. **`evidence: absent`
|
|
260
|
+
is an unmet-delivery fact, not
|
|
261
|
+
an external blocker** — never relabel missing implementation evidence as a
|
|
262
|
+
blocker. A malformed structured reviewer gap block — missing its stable `Gn`
|
|
263
|
+
label or any required field (`verdict`, `origin`, `evidence`, `remediation`,
|
|
264
|
+
`touched-files`, `touched-resources`, `recommended`) — triggers a **fresh
|
|
265
|
+
audit**; a complete structured reviewer gap block does not — the orchestrator
|
|
266
|
+
decomposes it or emits the indivisible fallback.
|
|
267
|
+
|
|
268
|
+
## Disposition catalog and availability
|
|
269
|
+
|
|
270
|
+
Each concern lists **every** supported disposition, its concrete effect, and
|
|
271
|
+
current availability. This table is the single availability contract, referenced
|
|
272
|
+
by both this verify gate and `finishing-a-development-branch`:
|
|
273
|
+
|
|
274
|
+
|Disposition|Ordinary gap effect|`UNAUTHORIZED` effect|Available when|
|
|
275
|
+
|---|---|---|---|
|
|
276
|
+
|`fix-now`|Complete missing implementation or validation.|Remove the unrequested code or behavior.|Named-branch worktree; `maxFixRounds > 0`; concern ownership is known; every required local/external resource is accessible.|
|
|
277
|
+
|`accept-into-spec`|Ratify intentional implemented behavior when the written contract is stale.|Ratify the unrequested behavior as approved scope.|A writable spec exists and there is concrete behavior to ratify.|
|
|
278
|
+
|`rescope-into-spec`|Explicitly remove or defer the origin requirement from this workflow.|Unavailable: scope creep has no origin requirement to defer.|The verdict is not `UNAUTHORIZED` and a writable spec exists.|
|
|
279
|
+
|`follow-up`|Keep the concern valid but transfer it to separately owned work.|Transfer a separately valid decision or removal task.|The concern can stand alone and the project defines an executable issue-tracker convention. Without one, mark unavailable and direct the user to `custom` to name another durable owner.|
|
|
280
|
+
|`custom`|Execute another user-defined disposition after its effect is clarified.|Same.|Always visible; executable only after the user supplies a concrete effect. It is never an automatic recommendation.|
|
|
281
|
+
|
|
282
|
+
A failed condition leaves the disposition visible and names the exact missing
|
|
283
|
+
prerequisite. `touched-files: unknown` makes `fix-now` unavailable until
|
|
284
|
+
ownership is established. A normal checkout (`GIT_DIR == GIT_COMMON`) or detached
|
|
285
|
+
HEAD cannot dispatch the isolated fix loop at all - it has no named-branch
|
|
286
|
+
worktree to branch fixes from - so `fix-now` stays unavailable there regardless
|
|
287
|
+
of ownership; resolve those concerns manually at finish. `maxFixRounds: 0`
|
|
288
|
+
(audit-only) likewise leaves `fix-now` visible but unavailable — the user
|
|
289
|
+
configured no auto-fix loop, and finish-time selection never bypasses or resets
|
|
290
|
+
that cap; a concrete `custom`/manual-fix disposition remains possible. `UNAUTHORIZED` cards
|
|
291
|
+
replace the primary question with
|
|
292
|
+
`Should this unrequested behavior become part of the current workflow?`, so
|
|
293
|
+
removal and ratification are not presented as missing-feature choices.
|
|
294
|
+
|
|
295
|
+
Reviewer tokens map to executable concern recommendations:
|
|
296
|
+
|
|
297
|
+
- `fix` maps to `fix-now`; for `UNAUTHORIZED`, that means removal.
|
|
298
|
+
- `accept` maps to `accept-into-spec`; for `UNAUTHORIZED`, that means ratification.
|
|
299
|
+
- `rescope` maps to `rescope-into-spec` and is invalid for `UNAUTHORIZED`.
|
|
300
|
+
- `follow-up` may replace an unavailable `fix-now`/`rescope-into-spec` **only**
|
|
301
|
+
when the concern remains valid, has separate ownership, and the issue-tracker
|
|
302
|
+
action is executable.
|
|
303
|
+
|
|
304
|
+
The orchestrator may choose another named disposition only when current evidence
|
|
305
|
+
supports its stated effect. If no named executable disposition is available, the
|
|
306
|
+
concern serializes `recommended: none` - the durable state for "no named
|
|
307
|
+
executable choice exists" - and its `rationale` must name the exact missing
|
|
308
|
+
prerequisites plus the concrete custom effect still required. `custom` is never
|
|
309
|
+
auto-recommended, so `none` never silently resolves to `custom`.
|
|
310
|
+
|
|
311
|
+
A concern with `recommended: none` is excluded from the recommended set. Before
|
|
312
|
+
any exhaustive `Apply recommended set`, the finish gate asks for a targeted
|
|
313
|
+
custom approval that supplies a concrete effect for that one concern (finishing
|
|
314
|
+
owns the exact reply syntax - a per-item `custom(...)` decision - not an `apply
|
|
315
|
+
recommended` variant). That reply approves only that concrete custom effect for
|
|
316
|
+
that concern. Validate and normalize it immediately: if the effect is ambiguous or
|
|
317
|
+
unexecutable, clarify and keep the concern open; if executable, record it as a
|
|
318
|
+
**pending approved custom decision** and remove that concern from the still-open
|
|
319
|
+
inventory used to build the recommended set. If other open concerns remain,
|
|
320
|
+
render the exhaustive recommended set for them and visibly carry the pending
|
|
321
|
+
approved custom decision through the existing action-order and freshness
|
|
322
|
+
barriers; `apply recommended` approves only the remaining recommendations. If no
|
|
323
|
+
other concerns remain, execute the approved custom directly through the existing
|
|
324
|
+
mechanics. The final disposition record keeps this concern as a `custom` result;
|
|
325
|
+
never relabel it as a model recommendation.
|
|
326
|
+
|
|
327
|
+
**Never recommend an unavailable disposition or an unexecutable `custom`
|
|
328
|
+
placeholder.**
|
|
329
|
+
|
|
330
|
+
`revert` is a separate action, not a generic concern disposition. The commit
|
|
331
|
+
index stays gap-granular (`conformance fix Gn`). A listed gap-level commit makes
|
|
332
|
+
revert visible on every concern card under that gap, with an explicit warning
|
|
333
|
+
that the **entire gap commit** is reverted. Existing light-revert semantics
|
|
334
|
+
remain: revert the indexed commit, re-audit, and return to the decision gate
|
|
335
|
+
only if a concern remains open.
|
|
336
|
+
|
|
206
337
|
## Closure / conformance
|
|
207
338
|
|
|
208
339
|
Emit this block in the verify completion summary. It is the durable handoff
|
|
209
340
|
`finishing-a-development-branch` Step 3.5 consumes — parseable even if session
|
|
210
341
|
context was pruned. Verify completes when every gap is either fixed
|
|
211
|
-
(`CONFORMS`) or carried OPEN as a deferred `accept`/`rescope`/`UNAUTHORIZED
|
|
212
|
-
|
|
213
|
-
|
|
342
|
+
(`CONFORMS`) or carried OPEN as a deferred gap - `accept`/`rescope`/`UNAUTHORIZED`,
|
|
343
|
+
or a `recommended: fix` gap carried open because a declared fix-loop precondition
|
|
344
|
+
was unavailable so the loop never started (`maxFixRounds: 0`, or no eligible
|
|
345
|
+
named-branch worktree - normal checkout / detached HEAD). Escalation - a started
|
|
346
|
+
positive-cap loop that exhausted its rounds or blocked/failed with an open `fix`
|
|
347
|
+
gap - is the one non-completing terminal state; the precondition-unavailable
|
|
348
|
+
carried-open `fix` state is valid closure inventory, not escalation.
|
|
349
|
+
|
|
350
|
+
### Handoff sentinel and freshness anchor - every handoff
|
|
351
|
+
|
|
352
|
+
Every `## Closure / conformance` block - a `CONFORMS` no-card handoff and a
|
|
353
|
+
carried-open GAPS handoff alike - **opens with a two-line sentinel** that lets
|
|
354
|
+
the finish gate re-verify freshness after context pruning, with no session
|
|
355
|
+
history:
|
|
356
|
+
|
|
357
|
+
```text
|
|
358
|
+
status: CONFORMS (0 open) # or: status: GAPS (N open)
|
|
359
|
+
audited-base: <full HEAD SHA at audit time>
|
|
360
|
+
```
|
|
214
361
|
|
|
215
|
-
|
|
362
|
+
`N` = count of open concerns (decision units), matching the number of emitted
|
|
363
|
+
concern cards. Record `audited-base` as the full 40-char HEAD SHA at audit time;
|
|
364
|
+
never abbreviate. This block is the **single source** for the freshness rule;
|
|
365
|
+
`finishing-a-development-branch` links here rather than restating it.
|
|
216
366
|
|
|
367
|
+
**Freshness rule.** The audit-input rule requires deliverables committed before
|
|
368
|
+
auditing, so `audited-base` captures the audited state; freshness compares that
|
|
369
|
+
commit to the **current working tree**, not to HEAD (a commit-to-commit diff
|
|
370
|
+
misses staged/unstaged edits when HEAD has not moved). Run two cheap commands:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
ROOT=$(git rev-parse --show-toplevel)
|
|
374
|
+
git -C "$ROOT" diff --stat <audited-base> -- . # tracked changes since the audited commit (staged + unstaged)
|
|
375
|
+
git -C "$ROOT" status --porcelain --untracked-files=all # new/untracked deliverables
|
|
217
376
|
```
|
|
218
|
-
|
|
377
|
+
|
|
378
|
+
Any output from either command, any doubt, a missing/mismatched sentinel, or any
|
|
379
|
+
closure block not opening with the two-line sentinel above (e.g. a legacy
|
|
380
|
+
`Gn: PARTIAL - recommended: ...` row) triggers a fresh audit - never infer
|
|
381
|
+
`CONFORMS` from the absence of cards. This is a lightweight freshness check (two
|
|
382
|
+
git commands, no hashing or identity fields).
|
|
383
|
+
|
|
384
|
+
**Sentinel validation.** `status: CONFORMS` requires `N = 0` and **no** emitted
|
|
385
|
+
concern cards; `status: GAPS` requires `N > 0` exactly matching the emitted card
|
|
386
|
+
count (`Gn/Cn` blocks), not merely gap headers. A mismatch is stale -> re-audit.
|
|
387
|
+
|
|
388
|
+
**Audit-time input rule.** Stage or commit untracked deliverables before
|
|
389
|
+
auditing, since `git diff <base> -- .` omits untracked files from the reviewer
|
|
390
|
+
payload.
|
|
391
|
+
|
|
392
|
+
For each carried-open gap, emit a durable gap header plus one card per concern
|
|
393
|
+
(decomposition and derivation rules above). In rendered cards, recommendation
|
|
394
|
+
lists, clarification lists, and final disposition records, every user-facing
|
|
395
|
+
identifier carries both its ID **and** title; bare `Gn`/`Cn` or grouped
|
|
396
|
+
identifier lists without titles are prohibited. The only exceptions are the
|
|
397
|
+
machine/interaction tokens the grammar requires: bare `Gn/Cn` inside typed
|
|
398
|
+
response tokens, the literal `conformance fix Gn` commit/action identifiers, and
|
|
399
|
+
the flat `auto-applied fix commits` index below. The surrounding prompt or list
|
|
400
|
+
must map each token to its titled concern or gap before asking for input.
|
|
401
|
+
|
|
402
|
+
```text
|
|
403
|
+
G1 - Source-image validation is incomplete
|
|
404
|
+
verdict: PARTIAL
|
|
405
|
+
origin: <requirement source and clause>
|
|
406
|
+
evidence: <current file:line or observed state>
|
|
407
|
+
blocker: <specific blocker, or none>
|
|
408
|
+
touched-files: <paths or unknown>
|
|
409
|
+
touched-resources: <resources or none>
|
|
219
410
|
round history: R1 <verdict/action>, R2 <verdict/action>, ...
|
|
411
|
+
|
|
412
|
+
G1/C1 - End-to-end OCR output has not been validated
|
|
413
|
+
unresolved: <plain statement of the concern>
|
|
414
|
+
impact: <why it matters to the current workflow>
|
|
415
|
+
origin: <requirement source and clause, narrowed from the gap origin; or none (scope creep) for UNAUTHORIZED>
|
|
416
|
+
remediation: <concern-scoped remediation action>
|
|
417
|
+
evidence: <concern-specific evidence or blocker>
|
|
418
|
+
touched-files: <concern-scoped paths, narrowed from the gap; or unknown>
|
|
419
|
+
touched-resources: <concern-scoped resources, narrowed from the gap; or none>
|
|
420
|
+
available dispositions:
|
|
421
|
+
fix-now: <effect and availability>
|
|
422
|
+
accept-into-spec: <effect and availability>
|
|
423
|
+
rescope-into-spec: <effect and availability>
|
|
424
|
+
follow-up: <effect and availability>
|
|
425
|
+
custom: <effect and availability>
|
|
426
|
+
recommended: <available named disposition, or none>
|
|
427
|
+
rationale: <why this is the best current choice; for none, the missing prerequisites and the concrete custom effect required>
|
|
220
428
|
```
|
|
221
429
|
|
|
430
|
+
All concerns in a gap must be represented.
|
|
431
|
+
|
|
222
432
|
Then a single flat revert index of **every** `conformance fix Gn` commit the fix
|
|
223
433
|
loop produced this run — including gaps that later converged to `CONFORMS`
|
|
224
|
-
(a closed gap has no
|
|
434
|
+
(a closed gap has no card above, so its commit lives only here) — since the
|
|
225
435
|
finish gate's revert option needs them all:
|
|
226
436
|
|
|
227
437
|
```
|
|
228
438
|
auto-applied fix commits: <Gn: SHA>, <Gm: SHA>, ... (revertable)
|
|
229
439
|
```
|
|
230
440
|
|
|
441
|
+
## Concern-scoped fix projection
|
|
442
|
+
|
|
443
|
+
When the finish gate selects `fix-now` on some concerns of a gap, the fix loop
|
|
444
|
+
above runs against a **projected** contract, not the original whole-gap block.
|
|
445
|
+
For each parent gap with selected `fix-now` concerns, project only those
|
|
446
|
+
concerns into one gap-scoped fix contract:
|
|
447
|
+
|
|
448
|
+
- The parent gap ID.
|
|
449
|
+
- The selected concern IDs and titles.
|
|
450
|
+
- Their origin clauses, concern remediations, and evidence.
|
|
451
|
+
- The **union** of the selected concerns' touched files/resources (ownership
|
|
452
|
+
boundary).
|
|
453
|
+
|
|
454
|
+
Rescoped, accepted, and followed-up sibling concerns are **excluded** from the
|
|
455
|
+
projection. The `implementer` and the pre-integration `spec-reviewer` receive
|
|
456
|
+
this projected contract in place of the original whole-gap block.
|
|
457
|
+
|
|
458
|
+
The projected task runs the existing full loop above: it retains the gap-level
|
|
459
|
+
`conformance fix Gn` commit name, reruns the project's tests, runs
|
|
460
|
+
`code-reviewer`, re-audits against the amended spec, and reenters the gate only
|
|
461
|
+
if concerns remain. Gap-level revert stays available through the flat commit
|
|
462
|
+
index. The gate records the final result by concern ID and title before showing
|
|
463
|
+
branch integration options.
|
|
464
|
+
|
|
231
465
|
## Checklist
|
|
232
466
|
|
|
233
467
|
- [ ] Located canonical requirements (spec → prompt → ticket fallback)
|