pi-gauntlet 5.0.1 → 5.0.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
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v5.0.2 - 2026-08-24
|
|
4
|
+
|
|
5
|
+
- Plan fidelity (gh-13): `writing-plans` task template gains a required spec-anchor line (`**Spec:** <path> § "<heading>" L<start>-L<end>`), a verbatim-quote rule for exact-string requirements, an extraction-first `## Spec coverage` table, and four mechanical self-review checks (quote integrity spec->task, anchor resolution, three-leg table closure, paths exist). `subagent-driven-development` spec-reviewer contract becomes spec+task: dispatches pass the spec path + the task's anchors in both modes and the Dispatch sketch, the spec wins every dispute, task-vs-spec divergence is unconditionally flagged with the spec literal, and `spec-reviewer-prompt.md` gains a `## Spec Authority` section plus `plan transcription gap` / `out-of-anchor-slice` finding labels. Spec: `doc/specs/2026-08-23-gh-13-plan-fidelity-anchors.md` (partially supersedes `doc/specs/2026-07-06-parallel-wave-spec-reviewer-dispatch.md`, SR contract scope only).
|
|
6
|
+
|
|
3
7
|
## v5.0.1 - 2026-08-23
|
|
4
8
|
|
|
5
9
|
- Council roast hardening: verification scope moves from the `spec-council-member` persona to dispatch task text (ticket roasts are content-only; spec roasts verify bounded - `rg`, explicit paths, `timeout`); persona gains a read-only invariant; explicit silence-kill control blocks (shape-ticket 5 min, spec-roast members 10 min, chair 15 min); shape-ticket mandates two-call dispatch (member fanout, then chair over usable files); mechanical usable-critique probe (`verdict:`/`addresses-problem:` headers, `consensus:` for the chair); targeted single retry of failed members only; quorum salvage (>= 1 usable critique -> chair runs with a `Coverage:` note, rendered to the user at brainstorming's gate and at shape-ticket's confirmation gate when coverage was partial). Spec: `doc/specs/2026-08-23-council-roast-hardening.md`.
|
package/package.json
CHANGED
|
@@ -55,12 +55,14 @@ For each task in `plan_tracker`:
|
|
|
55
55
|
|
|
56
56
|
1. **Dispatch implementer.** Pass the full task text + scene-setting context + the task's plan-declared test commands as `SCOPED_TEST_COMMANDS` (or `none`). Don't make the subagent re-read the plan.
|
|
57
57
|
2. **Handle implementer status** (see below).
|
|
58
|
-
3. **Dispatch spec reviewer.** Verify the diff matches the spec — nothing missing, nothing extra.
|
|
58
|
+
3. **Dispatch spec reviewer.** Pass the task text, the patch diff, the absolute spec path, and the task's `**Spec:**` anchors — SR reads the anchored ranges from the spec file itself; never inline spec excerpts. The spec wins every dispute; the authority hierarchy and finding labels live in `./spec-reviewer-prompt.md`. Anchor-less tasks (no `**Spec:**` line): task text alone is the contract. Verify the diff matches the anchored spec — nothing missing, nothing extra.
|
|
59
59
|
4. If spec reviewer finds gaps → re-dispatch implementer to fix → re-review. Loop until ✅, within [Fix-Loop Rounds](#fix-loop-rounds).
|
|
60
60
|
5. **Dispatch code-quality reviewer.** Only after spec is ✅. Skip for doc-only tasks (every file in the task's `Files:` block documentation-only) — SR-only, same exemption as doc-only waves. Pass `SCOPED_TEST_COMMANDS` = the task's plan-declared commands.
|
|
61
61
|
6. If quality reviewer finds issues → re-dispatch implementer → re-review. Loop until ✅, within [Fix-Loop Rounds](#fix-loop-rounds).
|
|
62
62
|
7. Mark task complete in `plan_tracker`.
|
|
63
63
|
|
|
64
|
+
The spec is frozen at plan time and the orchestrator is its only writer during execution; if you do edit it mid-run, re-run writing-plans' anchor-resolution check before the next wave. An SR unable to read the spec at a cited anchor (missing file, unresolvable heading/range) returns a blocking finding — the contract is spec+task or stop, never a silent fallback to task-only review.
|
|
65
|
+
|
|
64
66
|
After all tasks: run the whole-diff code review (`requesting-code-review`). Then [After All Tasks](#after-all-tasks-complete).
|
|
65
67
|
|
|
66
68
|
## Fix-Loop Rounds
|
|
@@ -133,7 +135,7 @@ When in doubt, default. Don't downgrade reviewers — false negatives are expens
|
|
|
133
135
|
subagent({ agent: "implementer", task: "<task text + context + SCOPED_TEST_COMMANDS + status protocol>" })
|
|
134
136
|
|
|
135
137
|
// spec compliance
|
|
136
|
-
subagent({ agent: "spec-reviewer", task: "<
|
|
138
|
+
subagent({ agent: "spec-reviewer", task: "<task text + patch diff + absolute spec path + task's Spec: anchors>" })
|
|
137
139
|
|
|
138
140
|
// code quality
|
|
139
141
|
subagent({ agent: "code-reviewer", task: "<diff range + SCOPED_TEST_COMMANDS (task commands; wave: union; whole-diff: none) + ask: production-ready?>" })
|
|
@@ -169,7 +171,7 @@ Auto-selected at handoff by `writing-plans` (any wave with ≥2 tasks) when the
|
|
|
169
171
|
|
|
170
172
|
1. **Independence check.** Parse the wave's tasks' `Files:` blocks; assert pairwise-disjoint (mechanical). Runtime-resource disjointness (DB/schema, port, fixture, external service, shared temp path) is not machine-checkable here — trust the plan's wave grouping, which `writing-plans`' D5 contract guarantees. Either kind of overlap → the wave is mis-grouped; run those tasks as sequential single-task waves and note it.
|
|
171
173
|
2. **Fan out.** One parallel dispatch (shape below): `implementer` per task, `context: "fresh"`, `worktree: true`. Each returns a status + a patch.
|
|
172
|
-
3. **Status + spec review per task.** Parse each `DONE`/`BLOCKED`/etc. (see [Implementer Status](#implementer-status)) **first**. Then **dispatch a `spec-reviewer` per accepted patch** (`DONE`, or a `DONE_WITH_CONCERNS` you proceeded with) in one parallel fan-out — `context: "fresh"`, `cwd: <this worktree>`, **no `worktree` flag** (read-only) — each passed its task text, the returned **patch diff**,
|
|
174
|
+
3. **Status + spec review per task.** Parse each `DONE`/`BLOCKED`/etc. (see [Implementer Status](#implementer-status)) **first**. Then **dispatch a `spec-reviewer` per accepted patch** (`DONE`, or a `DONE_WITH_CONCERNS` you proceeded with) in one parallel fan-out — `context: "fresh"`, `cwd: <this worktree>`, **no `worktree` flag** (read-only) — each passed its task text, the returned **patch diff**, the absolute spec path, and the task's `**Spec:**` anchors — SR reads the anchored ranges itself (never inline excerpts; authority hierarchy in `./spec-reviewer-prompt.md`; anchor-less tasks are task-text-only). Review is **diff-based**: the diff's hunks carry `file:line`, and test execution is never the reviewer's job - in either mode (persona rule; the wave test gate in step 5 runs the wave's declared test commands). Inline verdicts are fine at normal wave sizes; large waves use `output:` + `outputMode: "file-only"` to keep verdicts out of your context. **Re-dispatch by cause:** `BLOCKED`/`NEEDS_CONTEXT` per the [Implementer Status](#implementer-status) matrix; a **spec gap** re-dispatches the implementer (fresh, `worktree: true`) carrying the prior patch + the reviewer's findings, the new patch superseding the old at step 4. Loop until accepted + spec ✅, within [Fix-Loop Rounds](#fix-loop-rounds), same as sequential.
|
|
173
175
|
4. **Integrate.** `git apply` each task's patch sequentially onto HEAD. Apply fails = textual conflict → drop that task, finish the rest, re-run the dropped task sequentially on the updated HEAD.
|
|
174
176
|
5. **Test gate.** Run the union of the wave's tasks' declared test commands on the integrated tree — the full verification set is the verify phase's job, run once. Failure = semantic conflict or bug → re-run the offending task sequentially, else fix per [When a Subagent Fails](#when-a-subagent-fails).
|
|
175
177
|
6. **Quality review.** CR binds to the wave: exactly one **initial** code-review dispatch per code-touching wave, over the integrated wave diff - never per task within a wave, never batched across waves. Subsequent dispatches within the wave are re-reviews triggered only by findings, per Fix-Loop Rounds. Pass `SCOPED_TEST_COMMANDS` = the union of the wave's tasks' declared commands. Code-quality review on the integrated wave diff; loop fixes to ✅ within [Fix-Loop Rounds](#fix-loop-rounds), same as sequential. Skip for doc-only waves (SR-only per the commit precondition below).
|
|
@@ -14,10 +14,26 @@ Dispatch a subagent with this prompt:
|
|
|
14
14
|
|
|
15
15
|
[FULL TEXT of task requirements]
|
|
16
16
|
|
|
17
|
+
(The task text is a derivative of the spec — a lossy projection into an executable unit. See ## Spec Authority below.)
|
|
18
|
+
|
|
17
19
|
## What Implementer Claims They Built
|
|
18
20
|
|
|
19
21
|
[From implementer's report]
|
|
20
22
|
|
|
23
|
+
## Spec Authority
|
|
24
|
+
|
|
25
|
+
Spec: [absolute spec path]
|
|
26
|
+
Anchors: [the task's **Spec:** anchor list, e.g. § "Design" L34-L37 — or "omitted: anchor-less mechanical task"]
|
|
27
|
+
|
|
28
|
+
The spec is the sole authority — human-approved; the task never wins a dispute. Read the anchored ranges from the spec file yourself. Requirements in scope are ONLY the cited anchor ranges; do not extract, review, or flag the rest of the spec file.
|
|
29
|
+
|
|
30
|
+
- **Correctness / wording / completeness:** judged against the anchored spec lines. The spec wins every dispute.
|
|
31
|
+
- **Scope ("nothing more"):** the boundary is the anchor set — the slice of spec this task owns. Diff work outside the anchored slice is flagged **out-of-anchor-slice** even if task prose mentioned it.
|
|
32
|
+
- **Plan transcription gap:** spec-required work inside the anchored slice that is missing from the diff because the task prose omitted it — the requirement still binds; flag it. Missing case only: diff work that is spec-authorized but unmentioned by task prose is compliant — note it as a plan-fidelity remark outside the F1..Fn finding stream, never as a finding.
|
|
33
|
+
- **Task-vs-spec divergence** (task says X, anchored spec says Y): unconditional flag; quote the spec literal with spec file:line so the fix re-dispatch carries authoritative wording. Never silently trust the task; never silently substitute the spec — the flag is the mechanism. Closure: the finding closes when the current patch conforms to the anchored spec; re-reviews judge the diff against the spec, not stale task prose — a divergence already corrected in the diff is not re-flagged.
|
|
34
|
+
- **Anchor-less task** (Anchors: omitted): the task text alone is your contract; no out-of-anchor-slice or transcription-gap flagging — only nothing-extra-vs-the-chore review.
|
|
35
|
+
- **Finding grammar:** divergence findings use the existing F1..Fn finding grammar - a finding kind by prose label, not a new schema; the `Parallel-safe:` and `TRAJECTORY:` grammars are untouched.
|
|
36
|
+
|
|
21
37
|
## CRITICAL: Do Not Trust the Report
|
|
22
38
|
|
|
23
39
|
The implementer finished suspiciously quickly. Their report may be incomplete,
|
|
@@ -51,11 +67,13 @@ Dispatch a subagent with this prompt:
|
|
|
51
67
|
- Did they implement everything that was requested?
|
|
52
68
|
- Are there requirements they skipped or missed?
|
|
53
69
|
- Did they claim something works but didn't actually implement it?
|
|
70
|
+
- Anchored spec work absent from the diff because task prose omitted it? Label it "plan transcription gap".
|
|
54
71
|
|
|
55
72
|
**Extra/unneeded work:**
|
|
56
73
|
- Did they build things that weren't requested?
|
|
57
74
|
- Did they over-engineer or add unnecessary features?
|
|
58
75
|
- Did they add "nice to haves" that weren't in spec?
|
|
76
|
+
- Diff work outside the task's anchor slice? Label it "out-of-anchor-slice" (distinct from a spec-declared non-goal).
|
|
59
77
|
|
|
60
78
|
**Misunderstandings:**
|
|
61
79
|
- Did they interpret requirements differently than intended?
|
|
@@ -204,6 +204,8 @@ Each task uses `- [ ]` checkbox steps so execution tools (and humans) can track
|
|
|
204
204
|
|
|
205
205
|
**TDD scenario:** [New feature — full TDD cycle | Modifying tested code — run existing tests first | Trivial change — use judgment]
|
|
206
206
|
|
|
207
|
+
**Spec:** doc/specs/<file>.md § "<heading>" L<start>-L<end>
|
|
208
|
+
|
|
207
209
|
**Files:**
|
|
208
210
|
- Create: `exact/path/to/file.py`
|
|
209
211
|
- Modify: `exact/path/to/existing.py:123-145`
|
|
@@ -249,6 +251,27 @@ Each task uses `- [ ]` checkbox steps so execution tools (and humans) can track
|
|
|
249
251
|
|
|
250
252
|
Every code task carries this step (red -> green -> fmt/lint -> commit). Doc-only tasks omit it unless the project formats Markdown.
|
|
251
253
|
|
|
254
|
+
**Anchor rules.** The task's `**Spec:**` line cites the plan header's spec path; multiple anchors sit comma-separated on one line (`§ "A" L10-L18, § "C" L40-L44`). Checks key on the `§` marker, so the header's path-only `**Spec:**` line is never matched. Anchors are captured once against the gated spec at plan-writing time — the spec is frozen once planning starts. A task with no anchorable requirement (pure-mechanics chore) omits the `**Spec:**` line entirely (never `**Spec:** none`) and carries a mechanical-task row in `## Spec coverage` — silence is never valid.
|
|
255
|
+
|
|
256
|
+
## Spec Coverage Table
|
|
257
|
+
|
|
258
|
+
Every plan ends with a `## Spec coverage` section — authored last, placed after all Task sections (owner IDs do not exist earlier). Build it extraction-first: walk the spec top to bottom and write one row per normative requirement **before** assigning owners — every Design imperative (Add/Remove/Keep/Replace-style directives, not any fixed lexical form), every Edge-cases rule, every Acceptance criterion, every Out-of-scope entry, and every non-none Documentation-impact entry. Then assign owners. Two row kinds:
|
|
259
|
+
|
|
260
|
+
```markdown
|
|
261
|
+
## Spec coverage
|
|
262
|
+
|
|
263
|
+
| anchor | requirement (short) | owner |
|
|
264
|
+
|---|---|---|
|
|
265
|
+
| § "Design" L34-L37 | anchor line in task template | Task 2 |
|
|
266
|
+
| § "Edge cases" L120 | stale anchor = blocking SR finding | Task 4, Task 5 |
|
|
267
|
+
| § "Out of scope" L131 | fix-round anchoring | waived: out of scope per spec |
|
|
268
|
+
| - | mechanical: release commit | Task 7 |
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
- **Requirement rows:** anchor + short requirement + owner = task-ID list, or `waived: <reason>` **only when the spec itself marks the item out of scope**. A waiver on an in-scope normative requirement is a Self-Review failure — there is no human plan-review gate to catch it downstream.
|
|
272
|
+
- **Mechanical-task rows:** anchor `-`, requirement `mechanical: <short>`, owner = the task ID. One such row per anchor-less task.
|
|
273
|
+
- The table is plan-authoring-time only — never passed to implementer or reviewer dispatches.
|
|
274
|
+
|
|
252
275
|
## No Placeholders
|
|
253
276
|
|
|
254
277
|
Every plan failure mode:
|
|
@@ -257,6 +280,7 @@ Every plan failure mode:
|
|
|
257
280
|
- ❌ `# Implement the rest of the function` — incomplete code is invalid code.
|
|
258
281
|
- ❌ "Add tests for edge cases" — name the edge cases.
|
|
259
282
|
- ❌ "Wire it up to the existing system" — give file paths and call sites.
|
|
283
|
+
- ❌ "timeout/gtimeout ladder" when the spec fixes the literal `timeout 30` — never paraphrase an exact-string requirement (setting keys, error messages, banner/format strings, command names and invocations, API shapes); transcribe it as a backtick-quoted spec literal: `timeout 30`. Spec-side backtick spans containing `<placeholder>` segments are templates the plan instantiates, not exact-string requirements — exempt from quote integrity.
|
|
260
284
|
- ❌ "Similar to Task N" — repeat the code. Implementers (and subagents with fresh context) may read tasks out of order; pointing at a sibling task is not a substitute for showing the code.
|
|
261
285
|
- ❌ References to types, functions, methods, or fields not defined in any task in this plan. If it shows up in Task 5, it must be introduced by Task 1–4 or already exist in the codebase (with a file:line citation).
|
|
262
286
|
- ❌ `[fill in]`, `<example>`, `xxx` markers anywhere in the doc.
|
|
@@ -266,9 +290,12 @@ If a decision is genuinely open, put it in an explicit **Open Questions** sectio
|
|
|
266
290
|
|
|
267
291
|
## Self-Review (Before Handoff)
|
|
268
292
|
|
|
269
|
-
After drafting the plan and before announcing it complete, run
|
|
293
|
+
After drafting the plan and before announcing it complete, run these checks yourself. This is a checklist you run yourself — not a subagent dispatch.
|
|
270
294
|
|
|
271
|
-
- **Spec coverage
|
|
295
|
+
- **Table closure (three legs).** Every `## Spec coverage` row's owner is a task-ID list, a spec-authorized `waived: <reason>`, or a mechanical-task row; every `### Task N` heading appears in >=1 row; every requirement row's anchor is contained in the anchor set of each listed owner task's `**Spec:**` line. Zero orphans, zero waived in-scope normative rows, zero row-vs-owner anchor mismatches. Each Documentation impact entry maps to a plan task (or explicit "none").
|
|
296
|
+
- **Quote integrity (spec -> task).** For every non-waived requirement row, extract each backtick-quoted literal inside the row's anchored spec lines (strip the backticks; skip `<placeholder>` template spans) and `grep -F` it against the owning task's body — zero misses. Planner-authored backticks elsewhere in tasks are never scanned; the input set is spec-side literals only.
|
|
297
|
+
- **Anchor resolution.** For every task-level anchor (a `**Spec:**` line carrying `§`; the plan header's path line is exempt), the quoted heading text matches an ATX heading in the spec file and `L<start>-L<end>` is in-bounds, non-empty, and lies within that heading's section — zero unresolved anchors. Verify with `grep -n '^#'` plus a scoped `sed -n`. Ignore `#`-lines inside fenced code blocks when locating headings and section boundaries - a fenced markdown example is not a heading.
|
|
298
|
+
- **Paths exist.** Every `Modify:` path in `Files:` blocks passes `test -f` after stripping any trailing `:line[-line]` suffix; a `Modify:` glob must expand to >=1 match; `Create:` and `Test:` paths are exempt unless the `Test:` path is also listed under `Modify:`. Zero missing.
|
|
272
299
|
- **Placeholder scan.** Grep the doc for `TODO`, `TBD`, `xxx`, `[fill in]`, `<example>`, `etc.`, "probably", "something like". Resolve or convert each into an explicit Open Question.
|
|
273
300
|
- **Type / API consistency.** Function signatures and field names that appear in multiple tasks must match exactly. The plan is its own contract — internal contradictions surface as bugs during execution.
|
|
274
301
|
- **Wave disjointness.** For every multi-task wave, confirm the tasks' `Files:` sets are pairwise disjoint **and** that no two tasks contend on a shared mutable runtime resource (DB/schema, port, fixture, external service, shared temp path). Either kind of overlap = mis-grouped wave; split or re-order before handoff.
|