pi-gauntlet 4.8.2 → 4.9.0
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 +9 -0
- package/agents/code-reviewer.md +29 -3
- package/agents/conformance-reviewer.md +3 -3
- package/agents/spec-reviewer.md +42 -4
- package/extensions/plan-tracker.test.ts +66 -0
- package/extensions/plan-tracker.ts +35 -5
- package/extensions/test-support/pi-stubs.mjs +2 -0
- package/package.json +1 -1
- package/skills/dispatching-parallel-agents/SKILL.md +14 -0
- package/skills/requesting-code-review/SKILL.md +5 -3
- package/skills/requesting-code-review/code-reviewer.md +39 -7
- package/skills/subagent-driven-development/SKILL.md +4 -1
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +4 -1
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +29 -1
- package/skills/verification-before-completion/reference/conformance-check.md +14 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v4.9.0 - 2026-08-14
|
|
4
|
+
|
|
5
|
+
Review fix rounds parallelize when the reviewer certifies disjoint findings.
|
|
6
|
+
|
|
7
|
+
- `plan_tracker`: new `add` action - appends tasks as `pending`, preserving existing statuses; fix sub-waves extend the tracker instead of re-initializing it (conformance fix rounds no longer wipe the implement phase's completed task list).
|
|
8
|
+
- `dispatching-parallel-agents`: new "Fix fan-out" section - reviewer-certified `disjoint` finding groups fix in one parallel wave (one implementer per finding, verbatim finding blocks, serial integration, one re-review); silent sequential degradation when no certificate is present.
|
|
9
|
+
- Reviewer contracts (`spec-reviewer-prompt`, `code-reviewer` template + persona, `conformance-reviewer`): global finding IDs (`F<n>`/`G<n>`), per-finding `touched-files`/`touched-resources`, and a shared `Parallel-safe:` partition grammar (drift-guarded copies across templates and personas).
|
|
10
|
+
- `subagent-driven-development`, `requesting-code-review`, `verification-before-completion/conformance-check`: fix loops reference the shared fan-out rule; `requesting-code-review` gains a minimal fix loop (2 rounds, then escalate); severity vocabulary unified on Critical/Moderate/Minor.
|
|
11
|
+
|
|
3
12
|
## v4.8.2 - 2026-08-14
|
|
4
13
|
|
|
5
14
|
Tracker-neutral skill wording - Linear is an example, not the canonical vocabulary.
|
package/agents/code-reviewer.md
CHANGED
|
@@ -32,12 +32,15 @@ Verdict: SHIP | FIX_FIRST | REJECT
|
|
|
32
32
|
Confidence: low | medium | high (based on how much you could verify locally)
|
|
33
33
|
|
|
34
34
|
Findings:
|
|
35
|
-
- [Critical] path/to/file.ts:42 — one-sentence problem
|
|
35
|
+
- [Critical] F1: path/to/file.ts:42 — one-sentence problem
|
|
36
36
|
Fix: one or two sentences.
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
touched-files: path/to/file.ts
|
|
38
|
+
touched-resources: none
|
|
39
|
+
- [Moderate] F2: ...
|
|
40
|
+
- [Minor] F3: [shrink] path/to/file.ts:30 — manual loop builds dict; `dict(zip(keys, values))`, 1 line.
|
|
39
41
|
|
|
40
42
|
Complexity: net -<N> lines (omit if nothing to cut)
|
|
43
|
+
Parallel-safe: F1,F3 disjoint; F2 conflicts F1 (both touch auth.ts)
|
|
41
44
|
```
|
|
42
45
|
|
|
43
46
|
Severity:
|
|
@@ -46,4 +49,27 @@ Severity:
|
|
|
46
49
|
- **Moderate** — should fix; open for discussion (significant but not strictly blocking).
|
|
47
50
|
- **Minor** — nit, style, preference, suggestion.
|
|
48
51
|
|
|
52
|
+
Label every finding with a globally unique `F1..Fn` ID (no restart per severity),
|
|
53
|
+
and a `touched-files:`/`touched-resources:` pair (files/resources a fix would
|
|
54
|
+
touch, or the literal `none`). On any issue-bearing review end the findings
|
|
55
|
+
with one partition line over the `Fn` IDs assigned above; when a task requires
|
|
56
|
+
a trailing `TRAJECTORY:` verdict (re-review), that verdict follows it as the
|
|
57
|
+
true final line:
|
|
58
|
+
|
|
59
|
+
<!-- grammar identical to skills/requesting-code-review/code-reviewer.md — change them together or not at all; writing-plans' plan-time Parallel-safe: line is a deliberately different free-text form, do NOT unify -->
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
Parallel-safe: <group>[; <group>]*
|
|
63
|
+
<group> = <comma-separated finding-id list> " disjoint"
|
|
64
|
+
| <finding-id> " conflicts " <finding-id> " (" <reason> ")"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Example: `Parallel-safe: F1,F3 disjoint; F2 conflicts F1 (both touch auth.ts)`
|
|
68
|
+
|
|
69
|
+
IDs inside a `disjoint` list are mutually parallel-safe (their fixes can run
|
|
70
|
+
concurrently). Any file OR runtime-resource overlap between two findings' fixes
|
|
71
|
+
forces `conflicts`. Runtime-resource disjointness is estimated over: DB/schema,
|
|
72
|
+
port, fixture, external service, shared temp path. When you cannot confidently
|
|
73
|
+
certify a pair disjoint, mark them `conflicts` (conservative default = serial).
|
|
74
|
+
|
|
49
75
|
If you ran verification commands, quote them and their output verbatim under a `Verification:` section. If you did not, say so.
|
|
@@ -99,6 +99,8 @@ Empty values use the literal tokens `absent` / `none` / `unknown` — never a bl
|
|
|
99
99
|
After the gap blocks, emit one `Parallel-safe:` line so the orchestrator does not
|
|
100
100
|
re-derive fix concurrency:
|
|
101
101
|
|
|
102
|
+
<!-- grammar identical to skills/subagent-driven-development/spec-reviewer-prompt.md and skills/requesting-code-review/code-reviewer.md (modulo G vs F id prefix) — change them together or not at all; writing-plans' plan-time Parallel-safe: line is a deliberately different free-text form, do NOT unify -->
|
|
103
|
+
|
|
102
104
|
```
|
|
103
105
|
Parallel-safe: <group>[; <group>]*
|
|
104
106
|
<group> = <comma-separated gap-id list> " disjoint"
|
|
@@ -112,9 +114,7 @@ Parallel-safe: G1,G3 disjoint; G2 conflicts G1 (both touch auth.ts); G4 conflict
|
|
|
112
114
|
```
|
|
113
115
|
|
|
114
116
|
Any **file OR runtime-resource** overlap forces the conflicting gaps into separate
|
|
115
|
-
serial waves — identical to planned-execution wave grouping. Runtime-resource
|
|
116
|
-
disjointness is not machine-checkable; estimate it as `writing-plans`' Runtime-resource
|
|
117
|
-
disjointness rule does. When you cannot confidently certify a pair disjoint, mark them
|
|
117
|
+
serial waves — identical to planned-execution wave grouping. Runtime-resource disjointness is not machine-checkable; estimate it over: DB/schema, port, fixture, external service, shared temp path. When you cannot confidently certify a pair disjoint, mark them
|
|
118
118
|
`conflicts` (conservative default = serial).
|
|
119
119
|
|
|
120
120
|
### `recommended` selection policy
|
package/agents/spec-reviewer.md
CHANGED
|
@@ -25,20 +25,58 @@ You are a spec compliance reviewer. Your job is to verify that an implementation
|
|
|
25
25
|
```
|
|
26
26
|
Per-requirement status:
|
|
27
27
|
- [MET] REQ-1: short requirement text — evidence: file.ts:42
|
|
28
|
-
- [PARTIAL] REQ-2: ... — evidence: file.ts:80; missing: ...
|
|
29
|
-
|
|
28
|
+
- [PARTIAL] F1: REQ-2: ... — evidence: file.ts:80; missing: ...
|
|
29
|
+
touched-files: file.ts
|
|
30
|
+
touched-resources: none
|
|
31
|
+
- [MISSING] F2: REQ-3: ... — searched: <where>
|
|
32
|
+
touched-files: file.ts, other.ts
|
|
33
|
+
touched-resources: none
|
|
30
34
|
- [OUT_OF_SCOPE] REQ-4: ... — flagged as non-goal in spec
|
|
31
35
|
|
|
32
36
|
Scope creep (not in spec, but present):
|
|
33
|
-
-
|
|
37
|
+
- F3: widget.ts:120 — short description
|
|
38
|
+
touched-files: widget.ts
|
|
39
|
+
touched-resources: none
|
|
34
40
|
|
|
35
41
|
Missing from implementation:
|
|
36
|
-
- REQ-3 — short description
|
|
42
|
+
- F2: REQ-3 — short description
|
|
37
43
|
|
|
38
44
|
Verdict: COMPLIANT | NEEDS_REWORK | OUT_OF_SCOPE_CHANGES
|
|
39
45
|
Confidence: low | medium | high
|
|
46
|
+
|
|
47
|
+
Parallel-safe: F1,F3 disjoint; F2 conflicts F1 (both touch file.ts)
|
|
40
48
|
```
|
|
41
49
|
|
|
50
|
+
## Finding IDs and fix-concurrency certification
|
|
51
|
+
|
|
52
|
+
Label every finding (each `PARTIAL`/`MISSING` requirement, each scope-creep
|
|
53
|
+
item) with a globally unique ID `F1..Fn`, numbered across the whole report
|
|
54
|
+
(no restart per section). Each finding carries:
|
|
55
|
+
|
|
56
|
+
- `touched-files:` — files a fix would edit (not just the evidence location), comma-separated, or the literal `none`
|
|
57
|
+
- `touched-resources:` — shared runtime resources a fix or its verification touches (DB/schema, port, fixture, external service, shared temp path), or the literal `none`
|
|
58
|
+
|
|
59
|
+
On any issue-bearing review (any `PARTIAL`, `MISSING`, or scope-creep finding),
|
|
60
|
+
end the findings with one partition line over the `Fn` IDs assigned above; when
|
|
61
|
+
a task requires a trailing `TRAJECTORY:` verdict (re-review), that verdict
|
|
62
|
+
follows it as the true final line:
|
|
63
|
+
|
|
64
|
+
<!-- grammar identical to skills/subagent-driven-development/spec-reviewer-prompt.md — change them together or not at all; writing-plans' plan-time Parallel-safe: line is a deliberately different free-text form, do NOT unify -->
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
Parallel-safe: <group>[; <group>]*
|
|
68
|
+
<group> = <comma-separated finding-id list> " disjoint"
|
|
69
|
+
| <finding-id> " conflicts " <finding-id> " (" <reason> ")"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Example: `Parallel-safe: F1,F3 disjoint; F2 conflicts F1 (both touch auth.ts)`
|
|
73
|
+
|
|
74
|
+
IDs inside a `disjoint` list are mutually parallel-safe (their fixes can run
|
|
75
|
+
concurrently). Any file OR runtime-resource overlap between two findings' fixes
|
|
76
|
+
forces `conflicts`. Runtime-resource disjointness is estimated over: DB/schema,
|
|
77
|
+
port, fixture, external service, shared temp path. When you cannot confidently
|
|
78
|
+
certify a pair disjoint, mark them `conflicts` (conservative default = serial).
|
|
79
|
+
|
|
42
80
|
## Rules
|
|
43
81
|
|
|
44
82
|
- You are **read-only**. Never edit files.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { test } from "node:test";
|
|
3
|
+
import registerPlanTracker from "./plan-tracker.ts";
|
|
4
|
+
|
|
5
|
+
type ToolResult = {
|
|
6
|
+
content: { type: string; text: string }[];
|
|
7
|
+
details: { action: string; tasks: { name: string; status: string }[]; error?: string };
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function harness(branch: unknown[] = []) {
|
|
11
|
+
const tools: { name: string; execute: (...args: any[]) => unknown }[] = [];
|
|
12
|
+
const pi = {
|
|
13
|
+
on(_event: string, _handler: unknown) {},
|
|
14
|
+
registerTool(tool: { name: string; execute: (...args: any[]) => unknown }) {
|
|
15
|
+
tools.push(tool);
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
registerPlanTracker(pi as any);
|
|
19
|
+
const ctx = { hasUI: false, sessionManager: { getBranch: () => branch } };
|
|
20
|
+
const call = async (params: Record<string, unknown>): Promise<ToolResult> =>
|
|
21
|
+
(await tools[0].execute("id", params, undefined, undefined, ctx)) as ToolResult;
|
|
22
|
+
return { call };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
test("add appends pending tasks and preserves existing statuses", async () => {
|
|
26
|
+
const { call } = harness();
|
|
27
|
+
await call({ action: "init", tasks: ["a", "b", "c"] });
|
|
28
|
+
await call({ action: "update", index: 0, status: "complete" });
|
|
29
|
+
const res = await call({ action: "add", tasks: ["d", "e"] });
|
|
30
|
+
assert.equal(res.details.error, undefined);
|
|
31
|
+
assert.equal(res.details.action, "add");
|
|
32
|
+
assert.deepEqual(
|
|
33
|
+
res.details.tasks.map((t) => [t.name, t.status]),
|
|
34
|
+
[["a", "complete"], ["b", "pending"], ["c", "pending"], ["d", "pending"], ["e", "pending"]],
|
|
35
|
+
);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("add with no active plan creates one", async () => {
|
|
39
|
+
const { call } = harness();
|
|
40
|
+
const res = await call({ action: "add", tasks: ["g1"] });
|
|
41
|
+
assert.equal(res.details.error, undefined);
|
|
42
|
+
assert.deepEqual(res.details.tasks, [{ name: "g1", status: "pending" }]);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("add result carries the FULL merged list (reconstruction invariant)", async () => {
|
|
46
|
+
const { call } = harness();
|
|
47
|
+
await call({ action: "init", tasks: ["a"] });
|
|
48
|
+
await call({ action: "update", index: 0, status: "in_progress" });
|
|
49
|
+
const res = await call({ action: "add", tasks: ["b"] });
|
|
50
|
+
// reconstructState rebuilds wholesale from the latest details.tasks:
|
|
51
|
+
// the add result alone must reproduce the whole plan.
|
|
52
|
+
assert.deepEqual(res.details.tasks, [
|
|
53
|
+
{ name: "a", status: "in_progress" },
|
|
54
|
+
{ name: "b", status: "pending" },
|
|
55
|
+
]);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("add with empty/missing tasks errors and preserves state", async () => {
|
|
59
|
+
const { call } = harness();
|
|
60
|
+
await call({ action: "init", tasks: ["a"] });
|
|
61
|
+
const res = await call({ action: "add", tasks: [] });
|
|
62
|
+
assert.equal(res.details.error, "tasks required");
|
|
63
|
+
assert.deepEqual(res.details.tasks, [{ name: "a", status: "pending" }]);
|
|
64
|
+
const res2 = await call({ action: "add" });
|
|
65
|
+
assert.equal(res2.details.error, "tasks required");
|
|
66
|
+
});
|
|
@@ -19,18 +19,18 @@ interface Task {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
interface PlanTrackerDetails {
|
|
22
|
-
action: "init" | "update" | "status" | "clear";
|
|
22
|
+
action: "init" | "add" | "update" | "status" | "clear";
|
|
23
23
|
tasks: Task[];
|
|
24
24
|
error?: string;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
const PlanTrackerParams = Type.Object({
|
|
28
|
-
action: StringEnum(["init", "update", "status", "clear"] as const, {
|
|
28
|
+
action: StringEnum(["init", "add", "update", "status", "clear"] as const, {
|
|
29
29
|
description: "Action to perform",
|
|
30
30
|
}),
|
|
31
31
|
tasks: Type.Optional(
|
|
32
32
|
Type.Array(Type.String(), {
|
|
33
|
-
description: "Task names (for init)",
|
|
33
|
+
description: "Task names (for init and add)",
|
|
34
34
|
}),
|
|
35
35
|
),
|
|
36
36
|
index: Type.Optional(
|
|
@@ -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 (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.",
|
|
132
|
+
"Track progress while EXECUTING an implementation plan (the implement phase) or a verify-phase conformance fix wave. Actions: init (set task list), add (append tasks as pending; existing statuses preserved), 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) {
|
|
@@ -158,6 +158,30 @@ export default function (pi: ExtensionAPI) {
|
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
+
case "add": {
|
|
162
|
+
if (!params.tasks || params.tasks.length === 0) {
|
|
163
|
+
return {
|
|
164
|
+
content: [{ type: "text", text: "Error: tasks array required for add" }],
|
|
165
|
+
details: {
|
|
166
|
+
action: "add",
|
|
167
|
+
tasks: tasks.map((t) => ({ ...t })),
|
|
168
|
+
error: "tasks required",
|
|
169
|
+
} as PlanTrackerDetails,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
tasks.push(...params.tasks.map((name) => ({ name, status: "pending" as TaskStatus })));
|
|
173
|
+
updateWidget(ctx);
|
|
174
|
+
return {
|
|
175
|
+
content: [
|
|
176
|
+
{
|
|
177
|
+
type: "text",
|
|
178
|
+
text: `Added ${params.tasks.length} tasks (${tasks.length} total).\n${formatStatus(tasks)}`,
|
|
179
|
+
},
|
|
180
|
+
],
|
|
181
|
+
details: { action: "add", tasks: tasks.map((t) => ({ ...t })) } as PlanTrackerDetails,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
161
185
|
case "update": {
|
|
162
186
|
if (params.index === undefined || !params.status) {
|
|
163
187
|
return {
|
|
@@ -248,7 +272,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
248
272
|
text += ` ${theme.fg("accent", `[${args.index}]`)}`;
|
|
249
273
|
if (args.status) text += ` → ${theme.fg("dim", args.status)}`;
|
|
250
274
|
}
|
|
251
|
-
if (args.action === "init" && args.tasks) {
|
|
275
|
+
if ((args.action === "init" || args.action === "add") && args.tasks) {
|
|
252
276
|
text += ` ${theme.fg("dim", `(${args.tasks.length} tasks)`)}`;
|
|
253
277
|
}
|
|
254
278
|
return new Text(text, 0, 0);
|
|
@@ -273,6 +297,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
273
297
|
0,
|
|
274
298
|
0,
|
|
275
299
|
);
|
|
300
|
+
case "add":
|
|
301
|
+
return new Text(
|
|
302
|
+
theme.fg("success", "✓ ") + theme.fg("muted", `Added tasks (${taskList.length} total)`),
|
|
303
|
+
0,
|
|
304
|
+
0,
|
|
305
|
+
);
|
|
276
306
|
case "update": {
|
|
277
307
|
const complete = taskList.filter((t) => t.status === "complete").length;
|
|
278
308
|
return new Text(
|
package/package.json
CHANGED
|
@@ -104,6 +104,20 @@ When agents return:
|
|
|
104
104
|
|
|
105
105
|
**If some agents failed:** Integrate successful agents first (commit their work). Then retry the failed agent with fresh context that includes the integrated changes.
|
|
106
106
|
|
|
107
|
+
## Fix fan-out
|
|
108
|
+
|
|
109
|
+
Fix rounds in review loops reuse the fan-out mechanics above, keyed off the reviewer's partition certificate — the orchestrator never partitions findings itself.
|
|
110
|
+
|
|
111
|
+
Reviewers certify fix concurrency with a `Parallel-safe:` line (see the reviewer's report contract). The fan-out trigger is a `disjoint` group naming **≥ 2 finding IDs**: that group IS the parallel wave — dispatch **one `implementer` per finding ID in the group** (`context: "fresh"`, `worktree: true`, `cwd` = the current worktree; task = that finding's block **verbatim**, including its `touched-files` line as the ownership boundary). A finding named in any `conflicts` pair runs sequentially after every finding it names has integrated (chained `conflicts` define a partial order; remaining serial findings run in the line's order). Findings outside any ≥ 2-ID `disjoint` group run sequentially. Fan out per review line only — never merge or co-schedule groups from different `Parallel-safe:` lines; run those fan-outs serially.
|
|
112
|
+
|
|
113
|
+
**Precondition:** a clean committed HEAD containing the code under review. When the reviewed change is an unintegrated patch (a wave-mode per-patch spec review), each fix task branches from the wave's base HEAD and carries the prior patch verbatim in its task text — the consuming loop's existing re-dispatch protocol. When the tree is dirty (e.g. post-integration, before the wave commit), the fan-out is unavailable: fix sequentially in place.
|
|
114
|
+
|
|
115
|
+
**Degradation:** missing, malformed, or ID-less `Parallel-safe:` line, or no `disjoint` group with ≥ 2 IDs → fully sequential fixes. Degradation is silent — it costs parallelism, never correctness.
|
|
116
|
+
|
|
117
|
+
**After the fix wave:** integrate patches serially per "Review and Integrate" above (mis-partition is self-healing: integrate the successes, re-run the conflicting finding sequentially on integrated HEAD); run the consuming loop's scoped test gate on the integrated tree; then one re-review of the integrated fix delta, per the consuming loop's own rules. The fan-out counts as one fix round against the consuming loop's budget — it grants no extra rounds.
|
|
118
|
+
|
|
119
|
+
**Progress:** `plan_tracker({ action: "add" })` one task per fixed finding, named mechanically — `"<prefix>fix F<n>: <finding's first line verbatim>"`, where `<prefix>` is `"W<k>-"` inside an execution wave and empty elsewhere. Fix tasks always extend the tracker, never re-init. Mark `in_progress` at dispatch, `complete` at integration.
|
|
120
|
+
|
|
107
121
|
## Agent Prompt Structure
|
|
108
122
|
|
|
109
123
|
Good agent prompts are:
|
|
@@ -52,10 +52,12 @@ subagent({ agent: "code-reviewer", task: "... filled template ..." })
|
|
|
52
52
|
|
|
53
53
|
**3. Act on feedback:**
|
|
54
54
|
- Fix Critical issues immediately
|
|
55
|
-
- Fix
|
|
55
|
+
- Fix Moderate issues before proceeding
|
|
56
56
|
- Note Minor issues for later
|
|
57
57
|
- Push back if reviewer is wrong (with reasoning)
|
|
58
58
|
|
|
59
|
+
**Fix rounds.** Critical and Moderate findings trigger a fix round; when dispatched from an orchestrating skill, fixes go to `implementer` subagents (per the orchestrator's no-self-coding rule), fanned out per `dispatching-parallel-agents` "Fix fan-out" when the review's `Parallel-safe:` line certifies a `disjoint` group of ≥ 2 findings. After integration and the project's test command, re-dispatch the reviewer once on the integrated delta. If Critical or Moderate findings remain, run one more fix round and one more re-review; still failing → escalate to the user. Minor findings never trigger the fan-out.
|
|
60
|
+
|
|
59
61
|
## Example
|
|
60
62
|
|
|
61
63
|
```
|
|
@@ -76,7 +78,7 @@ HEAD_SHA=$(git rev-parse HEAD)
|
|
|
76
78
|
[Subagent returns]:
|
|
77
79
|
Strengths: Clean architecture, real tests
|
|
78
80
|
Issues:
|
|
79
|
-
|
|
81
|
+
Moderate: Missing progress indicators
|
|
80
82
|
Minor: Magic number (100) for reporting interval
|
|
81
83
|
Assessment: Ready to proceed
|
|
82
84
|
|
|
@@ -100,7 +102,7 @@ You: [Fix progress indicators]
|
|
|
100
102
|
**Never:**
|
|
101
103
|
- Skip review because "it's simple"
|
|
102
104
|
- Ignore Critical issues
|
|
103
|
-
- Proceed with unfixed
|
|
105
|
+
- Proceed with unfixed Moderate issues
|
|
104
106
|
- Argue with valid technical feedback
|
|
105
107
|
|
|
106
108
|
**If reviewer wrong:**
|
|
@@ -21,7 +21,7 @@ You are reviewing code changes for production readiness.
|
|
|
21
21
|
|
|
22
22
|
Before writing the report:
|
|
23
23
|
|
|
24
|
-
- **Not everything is Critical.** Reserve Critical for bugs, data loss, security, broken functionality. A missing helper method is
|
|
24
|
+
- **Not everything is Critical.** Reserve Critical for bugs, data loss, security, broken functionality. A missing helper method is Moderate. A naming preference is Minor.
|
|
25
25
|
- **Lead with strengths.** Accurate praise earns the implementer's trust on the critique that follows. Generic praise ("good code") undermines it.
|
|
26
26
|
- **If you wouldn't block a PR over it, it's not Critical.** Be honest with yourself about severity before assigning it.
|
|
27
27
|
- **Plan deviations get their own treatment.** If the implementation diverged from the spec/plan — added scope, removed scope, changed an interface — call it out under a dedicated "Plan Deviations" heading, not buried in Critical or Minor.
|
|
@@ -90,17 +90,20 @@ git diff {BASE_SHA}..{HEAD_SHA}
|
|
|
90
90
|
#### Critical (Must Fix)
|
|
91
91
|
[Bugs, security issues, data loss risks, broken functionality]
|
|
92
92
|
|
|
93
|
-
####
|
|
93
|
+
#### Moderate (Should Fix)
|
|
94
94
|
[Architecture problems, missing features, poor error handling, test gaps]
|
|
95
95
|
|
|
96
96
|
#### Minor (Nice to Have)
|
|
97
97
|
[Code style, optimization opportunities, documentation improvements]
|
|
98
98
|
|
|
99
99
|
**For each issue:**
|
|
100
|
+
- `Fn` label - globally unique, numbered across the whole report (no restart per severity section)
|
|
100
101
|
- File:line reference
|
|
101
102
|
- What's wrong
|
|
102
103
|
- Why it matters
|
|
103
104
|
- How to fix (if not obvious)
|
|
105
|
+
- `touched-files:` - files a fix would edit (not just the evidence location), comma-separated, or the literal `none`
|
|
106
|
+
- `touched-resources:` - shared runtime resources a fix or its verification touches (DB/schema, port, fixture, external service, shared temp path), or the literal `none`
|
|
104
107
|
|
|
105
108
|
### Recommendations
|
|
106
109
|
[Improvements for code quality, architecture, or process]
|
|
@@ -111,6 +114,27 @@ git diff {BASE_SHA}..{HEAD_SHA}
|
|
|
111
114
|
|
|
112
115
|
**Reasoning:** [Technical assessment in 1-2 sentences]
|
|
113
116
|
|
|
117
|
+
### Fix-concurrency certification
|
|
118
|
+
|
|
119
|
+
On any issue-bearing review, end the report with one partition line over the
|
|
120
|
+
`Fn` IDs assigned above:
|
|
121
|
+
|
|
122
|
+
<!-- grammar identical to agents/conformance-reviewer.md (modulo G vs F id prefix) — change them together or not at all; writing-plans' plan-time Parallel-safe: line is a deliberately different free-text form, do NOT unify -->
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Parallel-safe: <group>[; <group>]*
|
|
126
|
+
<group> = <comma-separated finding-id list> " disjoint"
|
|
127
|
+
| <finding-id> " conflicts " <finding-id> " (" <reason> ")"
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Example: `Parallel-safe: F1,F3 disjoint; F2 conflicts F1 (both touch auth.ts)`
|
|
131
|
+
|
|
132
|
+
IDs inside a `disjoint` list are mutually parallel-safe (their fixes can run
|
|
133
|
+
concurrently). Any file OR runtime-resource overlap between two findings' fixes
|
|
134
|
+
forces `conflicts`. Runtime-resource disjointness is estimated over: DB/schema,
|
|
135
|
+
port, fixture, external service, shared temp path. When you cannot confidently
|
|
136
|
+
certify a pair disjoint, mark them `conflicts` (conservative default = serial).
|
|
137
|
+
|
|
114
138
|
## Critical Rules
|
|
115
139
|
|
|
116
140
|
**DO:**
|
|
@@ -137,22 +161,28 @@ git diff {BASE_SHA}..{HEAD_SHA}
|
|
|
137
161
|
|
|
138
162
|
### Issues
|
|
139
163
|
|
|
140
|
-
####
|
|
141
|
-
|
|
164
|
+
#### Moderate
|
|
165
|
+
F1. **Missing help text in CLI wrapper**
|
|
142
166
|
- File: index-conversations:1-31
|
|
143
167
|
- Issue: No --help flag, users won't discover --concurrency
|
|
144
168
|
- Fix: Add --help case with usage examples
|
|
169
|
+
- touched-files: index-conversations.ts
|
|
170
|
+
- touched-resources: none
|
|
145
171
|
|
|
146
|
-
|
|
172
|
+
F2. **Date validation missing**
|
|
147
173
|
- File: search.ts:25-27
|
|
148
174
|
- Issue: Invalid dates silently return no results
|
|
149
175
|
- Fix: Validate ISO format, throw error with example
|
|
176
|
+
- touched-files: search.ts
|
|
177
|
+
- touched-resources: none
|
|
150
178
|
|
|
151
179
|
#### Minor
|
|
152
|
-
|
|
180
|
+
F3. **Progress indicators**
|
|
153
181
|
- File: indexer.ts:130
|
|
154
182
|
- Issue: No "X of Y" counter for long operations
|
|
155
183
|
- Impact: Users don't know how long to wait
|
|
184
|
+
- touched-files: indexer.ts
|
|
185
|
+
- touched-resources: none
|
|
156
186
|
|
|
157
187
|
### Recommendations
|
|
158
188
|
- Add progress reporting for user experience
|
|
@@ -162,5 +192,7 @@ git diff {BASE_SHA}..{HEAD_SHA}
|
|
|
162
192
|
|
|
163
193
|
**Ready to merge: With fixes**
|
|
164
194
|
|
|
165
|
-
**Reasoning:** Core implementation is solid with good architecture and tests.
|
|
195
|
+
**Reasoning:** Core implementation is solid with good architecture and tests. Moderate issues (help text, date validation) are easily fixed and don't affect core functionality.
|
|
196
|
+
|
|
197
|
+
Parallel-safe: F1,F2,F3 disjoint
|
|
166
198
|
```
|
|
@@ -69,6 +69,8 @@ One rule governs both review loops - spec-compliance and code-quality - in seque
|
|
|
69
69
|
|
|
70
70
|
**Re-review dispatch rule:** every re-review task includes the complete prior review report verbatim under the marker `## Previous review report (re-review trigger)`, plus the trajectory block from the reviewer's prompt template. The marker's presence is what obligates the reviewer to emit the `TRAJECTORY:` line. You never select, summarize, or diff findings yourself - pattern-match the sentinel line only.
|
|
71
71
|
|
|
72
|
+
**Fix fan-out.** When the triggering review's `Parallel-safe:` line certifies a `disjoint` group of ≥ 2 findings, dispatch that fix round per `dispatching-parallel-agents` "Fix fan-out"; the fan-out counts as **one** fix against this budget, its scoped test gate is the consuming task/wave's plan-declared commands, and one re-review of the integrated delta follows.
|
|
73
|
+
|
|
72
74
|
**The sequence.** Each review that finds issues is a decision point: read the `TRAJECTORY:` line before dispatching anything (review 1 has no line - on issues, dispatch fix 1). Any clean review ends the loop.
|
|
73
75
|
|
|
74
76
|
1. **Review 1** (first review - no sentinel). Issues -> dispatch fix 1.
|
|
@@ -215,7 +217,7 @@ For the fan-out + worktree + patch-integration + conflict mechanics, see `dispat
|
|
|
215
217
|
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.)
|
|
216
218
|
1. **Run the whole-diff code review.** Dispatch `/skill:requesting-code-review` against the worktree's full diff vs `main` (already covered in [The Process](#the-process) step "After all tasks"). Address Critical and Moderate findings before handoff. (Consumers wanting an in-flow project-specific audit re-add it as an explicit step in `.pi/gauntlet-overrides.md`, or run `/self-audit` manually.)
|
|
217
219
|
2. **Run the full verification set — once.** Read the plan header's `**Verification:**` line and run it: tests + style + format (a single bundling entrypoint, or the listed individual commands). Green output is the fresh evidence verify requires; this is the only full run before conformance — task and wave gates ran scoped commands only. After conformance fix rounds land, re-run the set before re-dispatching the gate.
|
|
218
|
-
3. **Close the loop — conformance check.** The review in step 1 is plan-vs-code (single-step); it inherits any requirement the plan already dropped. Before marking verify complete, dispatch a fresh-context **`conformance-reviewer`** — its **own** dispatch, never fused into the step-1 review — to confront the deliverable (code **and** docs) against the *origin* — the spec **and** the original prompt — per `verification-before-completion/reference/conformance-check.md`. Pass the spec path, the verbatim original prompt, and the full diff. Follow that reference for the partition rule, concern decomposition, and fix-loop mechanics; do not reimplement them here. The fix loop may drive `plan_tracker` to surface fix-wave progress (task
|
|
220
|
+
3. **Close the loop — conformance check.** The review in step 1 is plan-vs-code (single-step); it inherits any requirement the plan already dropped. Before marking verify complete, dispatch a fresh-context **`conformance-reviewer`** — its **own** dispatch, never fused into the step-1 review — to confront the deliverable (code **and** docs) against the *origin* — the spec **and** the original prompt — per `verification-before-completion/reference/conformance-check.md`. Pass the spec path, the verbatim original prompt, and the full diff. Follow that reference for the partition rule, concern decomposition, and fix-loop mechanics; do not reimplement them here. The fix loop may drive `plan_tracker` to surface fix-wave progress (task naming and lifecycle per conformance-check.md's fix loop / the Fix fan-out Progress rule); it never calls `phase_tracker`. Call `phase_tracker({ action: "complete", phase: "verify" })` only when the reference says the handoff is durably complete: either a current `CONFORMS` result, or a current `## Closure / conformance` inventory whose carried-open concerns all come from valid deferred gaps, including `recommended: fix` gaps carried open because a declared precondition made the fix loop unavailable (`maxFixRounds: 0`, or no eligible named-branch worktree). A started positive-cap fix loop that blocks, fails, or exhausts its rounds with an open `fix` gap is escalation, not completion; on escalation, do not complete verify, stop and report.
|
|
219
221
|
4. Summarize what was implemented (tasks completed, files changed, test counts, code-review verdict). Emit the `## Closure / conformance` block exactly as defined in `verification-before-completion/reference/conformance-check.md`: it must open with the two-line sentinel (`status: CONFORMS (0 open)` or `status: GAPS (N open)`, then `audited-base: <full HEAD SHA>`), then carry the exact durable concern schema by reference with no renamed or reformatted fields. `finishing-a-development-branch` Step 3.5 consumes that block verbatim.
|
|
220
222
|
5. **Proceed to finishing — no confirmation prompt.** Once verify is complete per step 3'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 4. 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.
|
|
221
223
|
|
|
@@ -235,6 +237,7 @@ For the fan-out + worktree + patch-integration + conflict mechanics, see `dispat
|
|
|
235
237
|
- Skipping the `Implementer Status` parse — treating every response as DONE
|
|
236
238
|
- Starting on main without explicit user consent
|
|
237
239
|
- Dispatching `code-reviewer` before every one of the wave's spec-review verdicts has landed (including fusing SR+CR into one parallel call)
|
|
240
|
+
- Dispatching fixes sequentially on a clean HEAD despite a ≥ 2-ID `disjoint` group in the review's `Parallel-safe:` line
|
|
238
241
|
- About to run the full verification entrypoint during the implement phase — task and wave gates run scoped, plan-declared commands only; the full set belongs to verify
|
|
239
242
|
|
|
240
243
|
## Integration
|
|
@@ -24,6 +24,8 @@ Dispatch a subagent with the code-reviewer template:
|
|
|
24
24
|
|
|
25
25
|
**Code reviewer returns:** Strengths, Issues (Critical/Moderate/Minor), Assessment
|
|
26
26
|
|
|
27
|
+
Emit finding IDs and the `Parallel-safe:` line per that contract.
|
|
28
|
+
|
|
27
29
|
## Re-review: trajectory verdict
|
|
28
30
|
|
|
29
31
|
Include the following in the reviewer's task text on every re-review, after
|
|
@@ -31,7 +33,8 @@ the prior review report pasted verbatim under a
|
|
|
31
33
|
`## Previous review report (re-review trigger)` heading:
|
|
32
34
|
|
|
33
35
|
If your task contains a "Previous review report (re-review trigger)" section
|
|
34
|
-
and you found issues,
|
|
36
|
+
and you found issues, append exactly one more line after `Parallel-safe:` — this
|
|
37
|
+
line, not `Parallel-safe:`, is the true final line of the report:
|
|
35
38
|
|
|
36
39
|
TRAJECTORY: CONVERGING (<n_prev> -> <n_now>, max severity <X>)
|
|
37
40
|
TRAJECTORY: DIVERGING
|
|
@@ -62,10 +62,38 @@ Dispatch a subagent with this prompt:
|
|
|
62
62
|
|
|
63
63
|
**Verify by reading code, not by trusting report.**
|
|
64
64
|
|
|
65
|
+
### Finding IDs and fix-concurrency certification
|
|
66
|
+
|
|
67
|
+
Label every finding with a globally unique ID `F1..Fn`, numbered across the whole
|
|
68
|
+
report (no restart per severity section). Each finding carries:
|
|
69
|
+
|
|
70
|
+
- `touched-files:` — files a fix would edit (not just the evidence location), comma-separated, or the literal `none`
|
|
71
|
+
- `touched-resources:` — shared runtime resources a fix or its verification touches (DB/schema, port, fixture, external service, shared temp path), or the literal `none`
|
|
72
|
+
|
|
73
|
+
On any issue-bearing review, end the findings with one partition line (this is the
|
|
74
|
+
final line of the report unless a re-review trajectory verdict is also required — see below):
|
|
75
|
+
|
|
76
|
+
<!-- grammar identical to agents/conformance-reviewer.md (modulo G vs F id prefix) — change them together or not at all; writing-plans' plan-time Parallel-safe: line is a deliberately different free-text form, do NOT unify -->
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
Parallel-safe: <group>[; <group>]*
|
|
80
|
+
<group> = <comma-separated finding-id list> " disjoint"
|
|
81
|
+
| <finding-id> " conflicts " <finding-id> " (" <reason> ")"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Example: `Parallel-safe: F1,F3 disjoint; F2 conflicts F1 (both touch auth.ts)`
|
|
85
|
+
|
|
86
|
+
IDs inside a `disjoint` list are mutually parallel-safe (their fixes can run
|
|
87
|
+
concurrently). Any file OR runtime-resource overlap between two findings' fixes
|
|
88
|
+
forces `conflicts`. Runtime-resource disjointness is estimated over: DB/schema,
|
|
89
|
+
port, fixture, external service, shared temp path. When you cannot confidently
|
|
90
|
+
certify a pair disjoint, mark them `conflicts` (conservative default = serial).
|
|
91
|
+
|
|
65
92
|
## Re-review: trajectory verdict
|
|
66
93
|
|
|
67
94
|
If your task contains a "Previous review report (re-review trigger)" section
|
|
68
|
-
and you found issues,
|
|
95
|
+
and you found issues, append exactly one more line after `Parallel-safe:` — this
|
|
96
|
+
line, not `Parallel-safe:`, is the true final line of the report:
|
|
69
97
|
|
|
70
98
|
TRAJECTORY: CONVERGING (<n_prev> -> <n_now>)
|
|
71
99
|
TRAJECTORY: DIVERGING
|
|
@@ -142,19 +142,21 @@ prerequisites hold.
|
|
|
142
142
|
|
|
143
143
|
Per round:
|
|
144
144
|
|
|
145
|
-
1. **`plan_tracker`
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
`in_progress` → `complete`.
|
|
150
|
-
completed task list in the singleton widget — state-safe, since
|
|
151
|
-
`phase-tracker.ts` `applyPlanActivity` only auto-completes `implement`
|
|
152
|
-
while it is `in_progress`; the widget now shows fix-wave progress during
|
|
145
|
+
1. **`plan_tracker` add** — append the round's gaps as tasks (`Gn: <gap origin
|
|
146
|
+
clause verbatim, truncated>`; carry the gap's requirement text mechanically,
|
|
147
|
+
no orchestrator-authored summaries); never `init`, which would wipe the
|
|
148
|
+
implement phase's completed task list. Lifecycle per gap: `pending` →
|
|
149
|
+
`in_progress` → `complete`. The widget now shows fix-wave progress during
|
|
153
150
|
verify.
|
|
154
|
-
2. **
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
the
|
|
151
|
+
2. **Fix dispatch** — per `dispatching-parallel-agents` "Fix fan-out": a `disjoint`
|
|
152
|
+
group of ≥ 2 gaps (per the report's `Parallel-safe:` line) fixes in one parallel
|
|
153
|
+
dispatch — one `implementer` per gap (fresh context, `worktree: true`, `cwd` =
|
|
154
|
+
the conformance worktree, task = the gap block verbatim with `touched-files` as
|
|
155
|
+
the ownership boundary); `conflicts` pairs serialize. Gaps outside any ≥ 2-ID
|
|
156
|
+
`disjoint` group run sequentially as before. Then dispatch `spec-reviewer` per
|
|
157
|
+
gap on the gap-block reference contract below. Task lifecycle: mark `in_progress` at
|
|
158
|
+
dispatch; `complete` is deferred until the gap's patch is successfully
|
|
159
|
+
integrated in step 3 below.
|
|
158
160
|
3. **Integrate** serially via `git apply` onto the worktree HEAD, one gap's
|
|
159
161
|
patch at a time. Failure handling is inherited verbatim from
|
|
160
162
|
`dispatching-parallel-agents` "Review and Integrate": textual conflict →
|