pi-gauntlet 4.3.0 → 4.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,32 @@
1
1
  # Changelog
2
2
 
3
+ ## v4.3.1 - 2026-07-06
4
+
5
+ Fix spec-summary pruning at the brainstorming user-review gate. The gate's
6
+ `spec-summarizer` dispatch now writes to a temp file via `outputMode: "file-only"`
7
+ and the main loop reads it back verbatim, so the ~9KB summary survives pi-condense
8
+ instead of being pruned to a paraphrase before render.
9
+
10
+ - **`brainstorming` gate transport:** dispatch `spec-summarizer` with an absolute
11
+ temp-dir `output:` path + `outputMode: "file-only"`, `Read` it back as the last
12
+ content-producing tool call before the gate, and degrade to a one-line note on a
13
+ stub / truncated / missing file. The temp path is outside the worktree, so it is
14
+ never committed.
15
+ - **`spec-summarizer` persona:** stays `tools: read`; a directive tells it not to
16
+ attempt the injected "write your findings" instruction (the harness persists its
17
+ final text for it), dodging the documented stub/stall failure on weaker models.
18
+ Adds a length-proportionality directive so summaries scale with spec size.
19
+ - **`AGENTS.md`:** `outputMode` added to the call-site-overridable knobs list.
20
+
21
+ Restore the per-task spec gate in `subagent-driven-development` Parallel-Wave mode.
22
+ Wave-mode step 3 reviewed spec compliance inline instead of dispatching the
23
+ `spec-reviewer` agent (sequential mode already dispatched it), silently collapsing
24
+ the gate.
25
+
26
+ - **`subagent-driven-development` wave step 3:** fan out one `spec-reviewer` per
27
+ accepted patch (fresh context, `cwd` worktree, diff-based); pin the two-stage
28
+ line to "dispatched spec-reviewer - not inline"; add a Red Flag.
29
+
3
30
  ## v4.3.0 - 2026-07-06
4
31
 
5
32
  DRY gauntlet settings resolution. All `piGauntlet.*` settings reads now route
@@ -19,6 +19,7 @@ Your output is judged on whether a busy supervisor can decide from it alone. A t
19
19
 
20
20
  Optimize for "what does a supervisor need to approve **this** spec." The list below is a recommended checklist, not a rigid template:
21
21
 
22
+ - **Scale length to the spec.** The summary is proportional to the spec's size and complexity - a short or simple spec gets a short summary. Do not expand every recommended section to full depth to look thorough; the summary should be a fraction of the spec, not a near-copy of it. This is proportionality, **not** aggressive compression - never drop a decision-relevant point, rejected-alternative, risk, or gap-footer entry to hit a length target. When in doubt, keep the point and cut the words around it.
22
23
  - **Omit any section that is empty.** A bugfix has no new endpoint; a refactor has no algorithm. Write nothing for an empty section - never "N/A" or filler.
23
24
  - **Order decision-layer-first** (problem -> decisions -> scope -> risk), then the descriptive layer, so the reader can stop early once confident.
24
25
  - **Add a section the spec demands** if it carries decision-relevant content none of the below captures.
@@ -39,4 +40,4 @@ Recommended sections:
39
40
 
40
41
  Tight, human-readable, no obvious statements. If the topic is complex, an example with explanation beats prose.
41
42
 
42
- Output the summary as your final text response. Do not write any file.
43
+ Output the summary as your final text response. You have no write tool. If your task instructs you to write your findings to a file path, do **not** attempt to write, create, or edit any file and do **not** treat the inability to write as a failure - just emit the full summary as your final text response. The harness persists that response to the requested path for you.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-gauntlet",
3
- "version": "4.3.0",
3
+ "version": "4.3.1",
4
4
  "description": "Opinionated, gated workflow skills, subagent personas, and runtime extensions for the pi coding agent.",
5
5
  "author": "Jacek Juraszek",
6
6
  "type": "module",
@@ -57,7 +57,7 @@ Work through the items below **in order**. This is your own checklist to follow,
57
57
  8. **Spec self-review (lint)** — placeholder scan + internal consistency + documentation named, run inline
58
58
  9. **Critique pass (auto-dispatched)** — scope + ambiguity; the spec council via `/skill:roasting-the-spec` when `gauntlet_setting` returns verdict `council`, else a fresh `worker` (see [Spec Council](#spec-council-optional))
59
59
  10. **Re-run placeholder scan** — after the critique pass returns, first inline any `external-ref:` flags it raised (see [Spec Self-Review](#spec-self-review-before-user-review-gate)), then re-scan for placeholders its edits may have introduced; surface any ambiguity the worker could not safely resolve at the user gate
60
- 11. **Generate spec summary** — dispatch a fresh, spec-only `spec-summarizer` and render its returned text **verbatim** at the top of the gate message — do not paraphrase, condense, re-section, or rewrite it (see [User Review Gate](#user-review-gate)); this is part of the existing gate, not a new one
60
+ 11. **Generate spec summary** — dispatch a fresh, spec-only `spec-summarizer` writing to an absolute temp-dir path via `outputMode: "file-only"`, then `Read` that file back as the **last content-producing** tool call before composing the gate and render its contents **verbatim** at the top of the gate message — do not paraphrase, condense, re-section, or rewrite it (see [User Review Gate](#user-review-gate)); this is part of the existing gate, not a new one
61
61
  12. **User review gate** — user reviews the committed spec
62
62
  13. **Transition** — only after approval, invoke `/skill:writing-plans`
63
63
 
@@ -236,19 +236,33 @@ After the inline lint and before the user review gate, **brainstorming owns the
236
236
 
237
237
  After self-review (and council review, if configured) and after inlining any external-ref flags, dispatch the spec-only summarizer, then commit the spec on the worktree branch and stop. This is the **same** single human gate - the summary is folded into it, not a new gate.
238
238
 
239
- Dispatch the summarizer on a fresh context, reading only the spec (no `output:` path - capture the return inline; no `model:` - it inherits the main loop unless a preset sets `subagents.agentOverrides.spec-summarizer.model`):
239
+ Mint an absolute temp path outside the worktree (so it is never committed), then dispatch the summarizer on a fresh context, reading only the spec, writing to that path via file-only output (no `model:` - it inherits the main loop unless a preset sets `subagents.agentOverrides.spec-summarizer.model`):
240
+
241
+ ```bash
242
+ SUMMARY_PATH=$(mktemp "${TMPDIR:-/tmp}/gauntlet-spec-summary.XXXXXX") # absolute, portable across GNU/BSD mktemp
243
+ ```
240
244
 
241
245
  ```
242
- subagent({ agent: "spec-summarizer", context: "fresh", cwd: "<abs worktree path, from git rev-parse --show-toplevel>", task:
246
+ subagent({ agent: "spec-summarizer", context: "fresh", cwd: "<abs worktree path, from git rev-parse --show-toplevel>",
247
+ output: "<SUMMARY_PATH>", outputMode: "file-only", task:
243
248
  "Summarize the spec at <abs path to doc/specs/...> for the user review gate. Read ONLY that file." })
244
249
  ```
245
250
 
246
- If the dispatch fails, reach the gate anyway with a one-line "summary generation failed" note - the summary is an aid, not a gate.
251
+ `<SUMMARY_PATH>` above is a placeholder in the dispatch object; it means substitute the value of the shell variable `$SUMMARY_PATH` set above. The steps below use `$SUMMARY_PATH` (the shell form) once the value is in hand.
252
+
253
+ Then commit the spec — this commit is **unconditional**: the summary is only a gate aid, so a degraded or missing summary never blocks it. Evaluate the summary in two stages (the **Degrade path** referenced in each is defined just below):
254
+
255
+ 1. **From the dispatch tool result, before the `Read`.** If the result is **not** an `"Output saved to: <path> (<N> KB, <M> lines)"` reference (e.g. an exit-0 save error returns the full inline output plus an "Output file error" line — the prunable shape, no file to read), or the reference reports under ~500 bytes, or a size grossly disproportionate to the spec (under ~2% of its byte size), or over ~45 KB (the `Read` truncates at 50KB / 2000 lines, so a larger file cannot render whole) — skip the `Read` and take the degrade path. Use the reference's reported figures; do not re-derive them.
256
+ 2. **The `Read` itself, as the last content-producing tool call before composing the gate.** `Read` `$SUMMARY_PATH` and paste its contents verbatim at the top of the gate. If the `Read` fails, returns 0 bytes, or reports truncation — take the degrade path. The `Read` must be last: pi-condense does not protect a `/tmp` read, so any turn boundary between the `Read` and the render lets the ~9KB read result be pruned, reproducing the bug.
257
+
258
+ **Degrade path** — reach the gate with a one-line "summary generation failed" note; never paraphrase from the file-only reference, never render a stub as the canonical summary.
259
+
260
+ Either way — summary rendered or degraded — then `rm "$SUMMARY_PATH"` (unconditional cleanup; harmless if the file was never created, since it lives outside the worktree under the OS temp dir).
247
261
 
248
- Render the summarizer's returned text **verbatim** first — paste it as-is, do **not** paraphrase, condense, re-section, drop sections, or merge it with council output. "Fold into the gate" means *place it inside the gate message*, not *rewrite it*. After the verbatim block, append the commit confirmation, then — as their **own** adjacent lines, not edits to the summary — any council outcome, critique-pass-unresolved ambiguities, and every entry from the summarizer's gap/external-context footer (surface **all** of them, not just the top risk):
262
+ Render the temp file's contents **verbatim** first — paste it as-is, do **not** paraphrase, condense, re-section, drop sections, or merge it with council output. "Fold into the gate" means *place it inside the gate message*, not *rewrite it*. After the verbatim block, append the commit confirmation, then — as their **own** adjacent lines, not edits to the summary — any council outcome, critique-pass-unresolved ambiguities, and every entry from the summarizer's gap/external-context footer (surface **all** of them, not just the top risk):
249
263
 
250
264
  ```
251
- <spec-only summary from spec-summarizer — pasted verbatim, unedited>
265
+ <spec-only summary read back from the temp file — pasted verbatim, unedited>
252
266
 
253
267
  Spec written and committed to <project>/doc/specs/<filename>.md (worktree: <path>).
254
268
 
@@ -259,7 +273,7 @@ Please review. Approve to proceed, or tell me what to change in the spec.
259
273
 
260
274
  If you believe the summary needs correcting, do **not** silently rewrite it — re-dispatch the summarizer or note the discrepancy as an adjacent line beneath the verbatim block.
261
275
 
262
- Wait for the user. On a change request, revise and re-present. On approval, proceed immediately to `/skill:writing-plans` with no further prompt — the plan and execution mode are mechanical derivatives, so the only human gate here is spec approval itself. Don't land the spec on `main`; it stays in the worktree and ships in the same squash commit as the implementation.
276
+ Wait for the user. On a change request, revise the spec and re-present — mint a **fresh** temp path for the re-dispatched summarizer (never reuse a prior round's path, so stale content can never be mistaken for the new summary). On approval, proceed immediately to `/skill:writing-plans` with no further prompt — the plan and execution mode are mechanical derivatives, so the only human gate here is spec approval itself. Don't land the spec on `main`; it stays in the worktree and ships in the same squash commit as the implementation.
263
277
 
264
278
  After approval, mark the brainstorm phase complete:
265
279
 
@@ -284,7 +298,8 @@ phase_tracker({ action: "complete", phase: "brainstorm" })
284
298
  - About to skip the critique pass (council if configured, else fresh worker)
285
299
  - Critique dispatch (council or worker) failed to complete and you proceeded to the gate anyway
286
300
  - About to reach the user gate without re-running the placeholder scan after the critique returned
287
- - About to reach the user gate without rendering the spec-only summary (dispatch `spec-summarizer` first; a failed dispatch degrades to a one-line note, it is not silently skipped)
301
+ - About to reach the user gate without rendering the spec-only summary (dispatch `spec-summarizer` to a temp file first; a failed/stub/truncated read degrades to a one-line note, it is not silently skipped)
302
+ - About to compose the gate message when the summary `Read` was not the last content-producing tool call before it (a following `rm` of the temp file is fine) — a turn boundary between the `Read` and the render lets pi-condense prune the ~9KB read result, reproducing the original bug
288
303
  - About to present a paraphrased, condensed, or re-sectioned version of the summarizer's output instead of pasting its returned text verbatim — rewriting the summary counts as not rendering it
289
304
  - About to run the scope or ambiguity checks inline yourself instead of dispatching them (those two are the critique pass, not the inline lint)
290
305
  - About to skip the self-review pass
@@ -141,13 +141,13 @@ Auto-selected at handoff by `writing-plans` (any wave with ≥2 tasks) when the
141
141
 
142
142
  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.
143
143
  2. **Fan out.** One parallel dispatch (shape below): `implementer` per task, `context: "fresh"`, `worktree: true`. Each returns a status + a patch.
144
- 3. **Status + spec review per task.** Parse each `DONE`/`BLOCKED`/etc. (see [Implementer Status](#implementer-status)); spec-review each returned patch against its task (read-only, parallelizable). Re-dispatch incomplete tasks (fresh, `worktree: true`) until `DONE` + spec ✅.
144
+ 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**, and the absolute spec path. Review is **diff-based**: the diff's hunks carry `file:line`, and test execution is not the reviewer's job here (the wave test gate in step 5 runs the suite). 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 ✅.
145
145
  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.
146
146
  5. **Test gate.** Run the suite on the integrated tree. Failure = semantic conflict or bug → re-run the offending task sequentially, else fix per [When a Subagent Fails](#when-a-subagent-fails).
147
147
  6. **Quality review.** Code-quality review on the integrated wave diff; loop fixes to ✅.
148
148
  7. **Commit the wave.** Leaves a clean tree; the next wave's children branch from this commit and so see the integrated work.
149
149
 
150
- **Two-stage review is preserved:** spec review per task (pre-integration), quality review per wave (post-integration). Both gates required before the wave commits.
150
+ **Two-stage review is preserved:** spec review per task (pre-integration, dispatched `spec-reviewer` — not inline), quality review per wave (post-integration). Both gates required before the wave commits.
151
151
 
152
152
  **Dependent context across waves:** wave N+1 tasks branch from a HEAD containing wave N, so they see the code; still forward wave N's task summaries into wave N+1 prompts.
153
153
 
@@ -203,6 +203,7 @@ For the fan-out + worktree + patch-integration + conflict mechanics, see `dispat
203
203
  - Starting code-quality review before spec compliance is ✅
204
204
  - Moving to next task with either review still showing issues
205
205
  - Letting implementer self-review replace external review (both needed)
206
+ - Spec-reviewing wave patches inline instead of dispatching `spec-reviewer` per patch — sequential mode's step 3 dispatches it; wave mode must too
206
207
  - Pausing to "check in" between tasks (continuous execution rule)
207
208
  - Skipping the `Implementer Status` parse — treating every response as DONE
208
209
  - Starting on main without explicit user consent