pi-gauntlet 7.3.0 → 7.3.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,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v7.3.2 - 2026-10-06
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- **Telemetry docs and test tightened.** `doc/configuration.md` states that council dispositions are read from any `git ... commit` command's audit lines during brainstorm (not only the heredoc shape), and the non-git telemetry test now uses a multi-line `cat` heredoc so it fails if the `git ... commit` guard is removed.
|
|
8
|
+
|
|
9
|
+
## v7.3.1 - 2026-10-06
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **Spec gate shows council counts, not the audit.** The brainstorming user review gate renders one `Council: <A> applied, <D> deferred, <R> rejected` line (with `; coverage <N> of <M>` on partial coverage) under the briefing and a third menu row, `3 - show council dispositions`, that prints the audit verbatim from the spec commit body and re-presents the gate without approving. The spec commit is made through a quoted heredoc (`git add -- <spec> && git commit -q -F - <<'EOF'`) so the audit lines are in the command; the `telemetry` extension records council dispositions from that command during brainstorm, with assistant text as the fallback. New `eval/spec-gate/` target (five samples, first run recorded) measures the gate render; `scripts/ci.mjs` runs its driver test.
|
|
14
|
+
|
|
3
15
|
## v7.3.0 - 2026-10-05
|
|
4
16
|
|
|
5
17
|
- eval/brainstorming/replay: the live-tool replay harness code and verdict tables are committed; private inputs and transcripts are documented as non-committable.
|
|
@@ -626,6 +626,67 @@
|
|
|
626
626
|
assert.deepEqual(h.readRecord().derived.council, EXPECTED_COUNCIL);
|
|
627
627
|
});
|
|
628
628
|
|
|
629
|
+
const HEREDOC_COMMIT = (body: string) => `git -C /w commit -q -F - -- doc/specs/a.md <<'EOF'\nspec: a\n\n${body}\nEOF`;
|
|
630
|
+
const ALL_NONE = "Applied: none\nDeferred: none\nRejected: none";
|
|
631
|
+
const EMPTY_CHAIR = "consensus: sound\nclusters:\nresolved:\n";
|
|
632
|
+
test("council records the audit from the spec commit heredoc without a chat render", async () => {
|
|
633
|
+
const h = await boundInBrainstorm();
|
|
634
|
+
await h.emit("tool_result", memberBatch());
|
|
635
|
+
await h.emit("tool_result", chairResult());
|
|
636
|
+
await h.bash("c1", HEREDOC_COMMIT(AUDIT_TEXT));
|
|
637
|
+
assert.deepEqual(h.readRecord().derived.council, EXPECTED_COUNCIL);
|
|
638
|
+
});
|
|
639
|
+
test("council ignores a chat audit after the commit already recorded it", async () => {
|
|
640
|
+
const h = await boundInBrainstorm();
|
|
641
|
+
await h.emit("tool_result", memberBatch());
|
|
642
|
+
await h.emit("tool_result", chairResult());
|
|
643
|
+
await h.bash("c1", HEREDOC_COMMIT(AUDIT_TEXT));
|
|
644
|
+
const before = h.readRecord().derived.council;
|
|
645
|
+
assert.deepEqual(before, EXPECTED_COUNCIL);
|
|
646
|
+
await h.emit("message_end", assistant(AUDIT_TEXT));
|
|
647
|
+
assert.deepEqual(h.readRecord().derived.council, before);
|
|
648
|
+
});
|
|
649
|
+
test("council ignores a commit outside brainstorm or before a chair result", async () => {
|
|
650
|
+
const planned = await boundInPlan();
|
|
651
|
+
await planned.emit("tool_result", memberBatch());
|
|
652
|
+
await planned.emit("tool_result", chairResult());
|
|
653
|
+
await planned.bash("c1", HEREDOC_COMMIT(AUDIT_TEXT));
|
|
654
|
+
assert.equal(planned.readRecord().derived.council, undefined);
|
|
655
|
+
const early = await boundInBrainstorm();
|
|
656
|
+
await early.emit("tool_result", memberBatch());
|
|
657
|
+
await early.bash("c1", HEREDOC_COMMIT(AUDIT_TEXT));
|
|
658
|
+
assert.equal(early.readRecord().derived.council, undefined);
|
|
659
|
+
});
|
|
660
|
+
test("council keeps pending across the grant amend and records a later chat audit", async () => {
|
|
661
|
+
const h = await boundInBrainstorm();
|
|
662
|
+
await h.emit("tool_result", memberBatch());
|
|
663
|
+
await h.emit("tool_result", chairResult());
|
|
664
|
+
await h.bash("c1", "git -C /w commit --amend --no-edit -q");
|
|
665
|
+
assert.equal(h.readRecord().derived.council, undefined);
|
|
666
|
+
await h.emit("message_end", assistant(AUDIT_TEXT));
|
|
667
|
+
assert.deepEqual(h.readRecord().derived.council, EXPECTED_COUNCIL);
|
|
668
|
+
});
|
|
669
|
+
test("council records an all-none audit from the commit against an empty chair", async () => {
|
|
670
|
+
const h = await boundInBrainstorm();
|
|
671
|
+
await h.emit("tool_result", memberBatch());
|
|
672
|
+
await h.emit("tool_result", chairResult(EMPTY_CHAIR));
|
|
673
|
+
await h.bash("c1", HEREDOC_COMMIT(ALL_NONE));
|
|
674
|
+
const zeroed = { total: counts(), unique: counts(), applied: counts(), unique_applied: counts(), deferred: counts(), rejected: counts() };
|
|
675
|
+
assert.deepEqual(h.readRecord().derived.council, {
|
|
676
|
+
chair: { model: "p/chair:medium", dispatches: 1, clusters: 0, members_reported: 0 },
|
|
677
|
+
members: { "p/alpha:xhigh": { dispatches: 1, ...zeroed }, "p/beta:high": { dispatches: 2, ...zeroed } },
|
|
678
|
+
});
|
|
679
|
+
});
|
|
680
|
+
test("council ignores a non-git bash command carrying audit text", async () => {
|
|
681
|
+
const h = await boundInBrainstorm();
|
|
682
|
+
await h.emit("tool_result", memberBatch());
|
|
683
|
+
await h.emit("tool_result", chairResult());
|
|
684
|
+
await h.bash("c1", `cat <<'EOF'\n${AUDIT_TEXT}\nEOF`);
|
|
685
|
+
assert.equal(h.readRecord().derived.council, undefined);
|
|
686
|
+
await h.emit("message_end", assistant(AUDIT_TEXT));
|
|
687
|
+
assert.deepEqual(h.readRecord().derived.council, EXPECTED_COUNCIL);
|
|
688
|
+
});
|
|
689
|
+
|
|
629
690
|
test("subagent results: dispatch events, persona tokens, spec_rounds, reviews, conformance_loops; async results: [] contribute nothing", async () => {
|
|
630
691
|
const h = await boundInPlan();
|
|
631
692
|
await h.emit("tool_result", subagentResult([
|
package/extensions/telemetry.ts
CHANGED
|
@@ -656,11 +656,11 @@
|
|
|
656
656
|
}
|
|
657
657
|
};
|
|
658
658
|
|
|
659
|
-
const onCouncilAudit = (
|
|
659
|
+
const onCouncilAudit = (text: string) => {
|
|
660
660
|
const pending = councilPending;
|
|
661
661
|
const clusters = pending?.chair?.clusters;
|
|
662
662
|
if (!record || !pending?.chair || !clusters) return;
|
|
663
|
-
const audit = parseAudit(
|
|
663
|
+
const audit = parseAudit(text);
|
|
664
664
|
if (!audit) return;
|
|
665
665
|
const members = resolveMembers(pending.memberResults);
|
|
666
666
|
const block = members && buildCouncil({ chair: { ...pending.chair, clusters }, members, audit });
|
|
@@ -758,6 +758,7 @@
|
|
|
758
758
|
}
|
|
759
759
|
if (event.toolName === "bash") {
|
|
760
760
|
const command = String((event.input as { command?: unknown }).command ?? "");
|
|
761
|
+
if (phaseNow() === "brainstorm" && /\bgit\b[^\n]*\bcommit\b/.test(command)) onCouncilAudit(command);
|
|
761
762
|
if (record && (phases.verify.status === "in_progress" || phases.ship.status === "in_progress")) {
|
|
762
763
|
const statement = matchTestStatement(command, snap.testCommands ?? DEFAULT_TEST_COMMANDS);
|
|
763
764
|
if (statement) pendingTest.set(event.toolCallId, statement);
|
|
@@ -771,7 +772,7 @@
|
|
|
771
772
|
const msg = event.message as { role?: string; usage?: unknown; content?: unknown };
|
|
772
773
|
if (msg.role !== "assistant") return;
|
|
773
774
|
addPhaseTokens(usageToTokens(msg.usage));
|
|
774
|
-
if (phaseNow() === "brainstorm") onCouncilAudit(msg.content);
|
|
775
|
+
if (phaseNow() === "brainstorm") onCouncilAudit(textOf(msg.content));
|
|
775
776
|
});
|
|
776
777
|
|
|
777
778
|
pi.on("turn_end", async (_event, ctx) => {
|
package/package.json
CHANGED
|
@@ -88,7 +88,19 @@ subagent({ agent: "spec-summarizer", context: "fresh", async: false, cwd: "<abs
|
|
|
88
88
|
|
|
89
89
|
`<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.
|
|
90
90
|
|
|
91
|
-
Then commit the spec - staging any predecessor spec edited per [Marking superseded specs](superseding.md) alongside it; a change request at the gate that renames, materially revises, or drops the spec also reconciles the predecessor's banner before recommitting. This commit is **unconditional**: the summary is only a gate aid, so a degraded or missing summary never blocks it.
|
|
91
|
+
Then commit the spec - staging any predecessor spec edited per [Marking superseded specs](superseding.md) alongside it; a change request at the gate that renames, materially revises, or drops the spec also reconciles the predecessor's banner before recommitting. This commit is **unconditional**: the summary is only a gate aid, so a degraded or missing summary never blocks it. Commit with the message on stdin through a quoted heredoc - the only permitted form, so audit lines carrying backticks or `$` land unchanged and each starts a line (telemetry reads them from this command):
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
git -C <abs worktree path> add -- <spec path> [<predecessor path>] && git -C <abs worktree path> commit -q -F - -- <spec path> [<predecessor path>] <<'EOF'
|
|
95
|
+
<subject>
|
|
96
|
+
|
|
97
|
+
<audit lines, verbatim>
|
|
98
|
+
EOF
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
If the council path ran, the body is its audit (`Coverage:` when present, then `Applied:` / `Deferred:` / `Rejected:`, verbatim from `/skill:roasting-the-spec`'s return) - the durable, non-contractual record a finish-time revert and row 3 below read back; the audit is never a committed spec section. On the worker path the body is empty. `-m`, `-F <file>`, `printf | ... -F -`, and `$'...'` strings are not used for this commit. The `add` on the same line is required because the spec is untracked at its first commit and `commit -- <path>` rejects an untracked path.
|
|
102
|
+
|
|
103
|
+
Evaluate the summary in two stages (the **Degrade path** referenced in each is defined just below):
|
|
92
104
|
|
|
93
105
|
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 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.
|
|
94
106
|
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 read result be pruned, reproducing the bug.
|
|
@@ -97,24 +109,22 @@ Then commit the spec - staging any predecessor spec edited per [Marking supersed
|
|
|
97
109
|
|
|
98
110
|
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).
|
|
99
111
|
|
|
100
|
-
Paste the summary verbatim, unedited in the template below; use adjacent lines for the
|
|
112
|
+
Paste the summary verbatim, unedited in the template below; use adjacent lines for the `Council:` counts, unresolved ambiguities, and every `Missing from the spec` entry; the audit itself is shown only on row 3:
|
|
101
113
|
|
|
102
114
|
```
|
|
103
115
|
<spec-only summary read back from the temp file - pasted verbatim, unedited>
|
|
104
116
|
|
|
105
117
|
Spec written and committed to <project>/doc/specs/<filename>.md (worktree: <path>).
|
|
106
118
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
Deferred: [<severity>] <cluster> - raised-by: [<slugs>] -> <where it belongs>
|
|
110
|
-
Rejected: [<severity>] <cluster> - raised-by: [<slugs>] -> <one-line reason>
|
|
111
|
-
(one line per item, exactly as returned by roasting-the-spec - `Applied: none` / `Deferred: none` / `Rejected: none` when a list is empty; omit the audit lines when the worker path ran, not the council)
|
|
119
|
+
Council: <A> applied, <D> deferred, <R> rejected
|
|
120
|
+
(council path only: A, D, R count the non-`none` lines under each label of the returned audit; append `; coverage <N> of <M>` only when the return carried a `Coverage:` line, e.g. `Council: 11 applied, 0 deferred, 0 rejected; coverage 2 of 3`; omit the whole line and row 3 on the worker path or when the council aborted before an audit existed)
|
|
112
121
|
|
|
113
122
|
<unresolved ambiguities; every `Missing from the spec` entry from the summary>
|
|
114
123
|
New predecessor candidates at spec-writing: <path> (<title>), ... - index rows are a hint; code is the source and an absent row proves nothing.
|
|
115
124
|
|
|
116
125
|
1 - approve: proceed to planning under the existing amendment review; a fresh reviewer applies evidence-backed factual corrections on its own, and every other spec amendment (scope, acceptance-criteria, or contract edits, and redraws) stops for your review.
|
|
117
126
|
2 - approve, auto-apply amends: every later spec amendment in this flow (corrected facts, paths, verification lines, and scope, acceptance-criteria, or public-contract edits alike) applies without asking; only a redraw (changed problem statement, component added, removed, or re-bounded) still stops for you, and the grant never stands in for a spec approval.
|
|
127
|
+
3 - show council dispositions: prints the council audit verbatim, then re-presents this gate. Not an approval.
|
|
118
128
|
|
|
119
129
|
Or tell me what to change in the spec, or say "revert applied council edit <X>" to undo a specific applied edit.
|
|
120
130
|
```
|
|
@@ -123,7 +133,7 @@ If you believe the summary needs correcting, do **not** silently rewrite it - re
|
|
|
123
133
|
|
|
124
134
|
**Revert valve.** "Revert applied council edit X" is a normal change request: revise the spec to undo edit X, re-dispatch the summarizer with a **fresh** temp path (per the re-dispatch rule below), and re-present the gate. This is cheap here - the spec is not yet plan- or code-bearing.
|
|
125
135
|
|
|
126
|
-
Wait for the user. On a change request (including a revert), revise the spec and re-present - mint a **fresh** temp path for the re-dispatched summarizer (never reuse a prior round's path, so stale content can never be mistaken for the new summary). On approval - `1`, `approve`, or equivalent prose approves without a grant; `2`, `approve, auto-apply amends`, or equivalent prose approves and grants - proceed immediately to `/skill:writing-plans` with no further prompt; first read [Standing grants](amendment-surface.md#standing-grants) (stop if unreadable). On a grant (`2`, `approve, auto-apply amends`, or equivalent prose), `edit` the spec's `**Amend-grant:**` value to the granting sentence (the digit `2` becomes the grant description after `2 - approve, auto-apply amends:` above), then `git -C <abs worktree path> add -- <spec path>` and `git -C <abs worktree path> commit --amend --no-edit -q`, so the spec commit carries the line and keeps its council-audit body; then confirm `git -C <abs worktree path> show HEAD:<spec path>` reads "grant active" through the predicate. On a plain approval (`1`, `approve`) the value stays `none` and the commit is untouched. A reply that mixes approval with a change request ("2 but rename the section") is a change request: revise, re-present, and read the grant only from the reply to the re-presented gate. If the amend or the HEAD check fails, stop and report; never proceed as granted. 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.
|
|
136
|
+
Wait for the user. On a change request (including a revert), revise the spec and re-present - mint a **fresh** temp path for the re-dispatched summarizer (never reuse a prior round's path, so stale content can never be mistaken for the new summary). On `3` or its label alone: print the audit verbatim from `git -C <abs worktree path> show -s --format=%b HEAD` (never from a held tool result; the body survives the grant's `--amend --no-edit`), then re-present the same gate - the briefing text of the gate message just rendered, reused verbatim (no summarizer re-dispatch, no read of the removed `$SUMMARY_PATH`; if that text is no longer in context, the one-line degrade note takes its place), the `Council:` line, the adjacent lines, the three rows; nothing in the spec or the commit changes. `3` plus a change request is a change request. `3` plus `1`/`2` prints and re-presents, and the approval is read only from a clean `1`/`2` on the re-presented gate - a reply carrying `3` never grants. A gate-round recommit (change request or revert) re-runs the same heredoc commit with the audit as its body, so HEAD always carries it; on a revert of edit X, move X's `Applied:` line to `Rejected:` with `-> reverted at gate` and recompute the `Council:` counts from the revised audit. On approval - `1`, `approve`, or equivalent prose approves without a grant; `2`, `approve, auto-apply amends`, or equivalent prose approves and grants - proceed immediately to `/skill:writing-plans` with no further prompt; first read [Standing grants](amendment-surface.md#standing-grants) (stop if unreadable). On a grant (`2`, `approve, auto-apply amends`, or equivalent prose), `edit` the spec's `**Amend-grant:**` value to the granting sentence (the digit `2` becomes the grant description after `2 - approve, auto-apply amends:` above), then `git -C <abs worktree path> add -- <spec path>` and `git -C <abs worktree path> commit --amend --no-edit -q`, so the spec commit carries the line and keeps its council-audit body; then confirm `git -C <abs worktree path> show HEAD:<spec path>` reads "grant active" through the predicate. On a plain approval (`1`, `approve`) the value stays `none` and the commit is untouched. A reply that mixes approval with a change request ("2 but rename the section") is a change request: revise, re-present, and read the grant only from the reply to the re-presented gate. If the amend or the HEAD check fails, stop and report; never proceed as granted. 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.
|
|
127
137
|
|
|
128
138
|
Post-approval changes follow [Amending an approved spec](../SKILL.md#amending-an-approved-spec).
|
|
129
139
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: roasting-the-spec
|
|
3
|
-
description: Use after writing a spec, when a spec council is configured (the resolved piGauntlet.specCouncil council, via the gauntlet_setting tool, repo settings over the preset). Auto-dispatched by /skill:brainstorming as the critique pass when members is non-empty (no longer offered). N members on different models critique in parallel, a neutral chair consolidates and adjudicates, the parent applies its own dispositions and returns an audit
|
|
3
|
+
description: Use after writing a spec, when a spec council is configured (the resolved piGauntlet.specCouncil council, via the gauntlet_setting tool, repo settings over the preset). Auto-dispatched by /skill:brainstorming as the critique pass when members is non-empty (no longer offered). N members on different models critique in parallel, a neutral chair consolidates and adjudicates, the parent applies its own dispositions and returns an audit that brainstorming commits with the spec, counts at its gate, and prints on request.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Roasting the Spec (Spec Council)
|
|
@@ -126,20 +126,20 @@ For each cluster in the chair's report, decide one of:
|
|
|
126
126
|
|
|
127
127
|
Also inline any `external-ref:` cluster you have context for (e.g. a ticket fetched during brainstorming) as part of the apply-set — this is your call, same as any other cluster.
|
|
128
128
|
|
|
129
|
-
An `over-spec:` cluster decided **apply** is executed as deletion or shrink of the quoted clause **and** any acceptance-criteria or testing-approach line that exists only for it. Its audit line reads `Applied: [<severity>] over-spec: <clause> — raised-by: [<slugs>] -> cut (was adds: M files / N tests / K ACs)` or `Applied: [<severity>] over-spec: <clause> — raised-by: [<slugs>] -> shrunk to <replacement> (was adds: ...)`, so
|
|
129
|
+
An `over-spec:` cluster decided **apply** is executed as deletion or shrink of the quoted clause **and** any acceptance-criteria or testing-approach line that exists only for it. Its audit line reads `Applied: [<severity>] over-spec: <clause> — raised-by: [<slugs>] -> cut (was adds: M files / N tests / K ACs)` or `Applied: [<severity>] over-spec: <clause> — raised-by: [<slugs>] -> shrunk to <replacement> (was adds: ...)`, so row 3 at brainstorming's gate shows what was removed. `defer`/`reject` are unchanged.
|
|
130
130
|
|
|
131
131
|
You are the advocate — decide on scope grounds — and, unlike a dispatched subagent, also the executor: you hold `edit`/`write` tools directly, so apply the edit yourself instead of proposing it for someone else to make. Do this **before** returning to brainstorming.
|
|
132
132
|
|
|
133
133
|
### 4 — Emit the audit
|
|
134
134
|
|
|
135
|
-
Return a structured audit,
|
|
135
|
+
Return a structured audit, for the commit body and row 3 only (not a committed spec section) — a coverage line plus three labelled lists:
|
|
136
136
|
|
|
137
137
|
- `Coverage:` — `N of M members reported; <slug>: <reason>` — present only when member coverage was partial; omitted at full coverage.
|
|
138
138
|
- `Applied:` — one line per applied cluster: `Applied: [<severity>] <cluster> — raised-by: [<slugs>] -> <edit> (grounded: <member probe>)`, `... -> <edit> (probed: <check> - <result>)` for a confirmed hypothesis, or `... -> open question (<not found | inconclusive: <check> | contradicted: <result>>)`. Copy `[<severity>]` and `raised-by: [...]` verbatim from the cluster line - telemetry joins on them. No applied cluster -> the single line `Applied: none`. The probe rides on the audit line because member files are removed in section 5.
|
|
139
139
|
- `Deferred:` — one line per deferred cluster, same `[<severity>] <cluster> — raised-by: [<slugs>]` prefix, then `-> <where it belongs>`. None -> `Deferred: none`.
|
|
140
140
|
- `Rejected:` — one line per rejected cluster, same prefix, then `-> <one-line reason>`. None -> `Rejected: none`.
|
|
141
141
|
|
|
142
|
-
Hand this audit to brainstorming along with the now-final spec. brainstorming writes it into the **spec commit message body** (git-native, readable pre-squash) so it survives for finish-time revert visibility,
|
|
142
|
+
Hand this audit to brainstorming along with the now-final spec. brainstorming writes it into the **spec commit message body** (git-native, readable pre-squash) so it survives for finish-time revert visibility, shows a `Council:` counts line at its one review gate, and prints the audit verbatim when the user picks row 3. The user can revert any applied edit there - that gate, not this skill, is where ratification happens.
|
|
143
143
|
|
|
144
144
|
### 5 — Clean up
|
|
145
145
|
|
|
@@ -152,7 +152,7 @@ Single pass — no automatic re-roast loop. The user can invoke this skill again
|
|
|
152
152
|
- Running the council when `piGauntlet.specCouncil.members` is absent or empty (brainstorming owns the gate and should have used the worker fallback).
|
|
153
153
|
- Reading member critique files' findings content yourself instead of routing them through the chair (the mechanical structural probe - existence plus header regex - is the named exception).
|
|
154
154
|
- Writing member files to a relative path (they land in the worktree).
|
|
155
|
-
- Applying edits without
|
|
155
|
+
- Applying edits without the `Council:` counts and the row-3 audit at brainstorming's gate - apply-before-the-gate is correct; apply-without-the-gate is not.
|
|
156
156
|
- Suppressing a finding instead of routing it to applied, deferred, or rejected in the audit.
|
|
157
157
|
- Surfacing member-vs-member disagreements to the user instead of letting the chair adjudicate.
|
|
158
158
|
- Editing anything other than the spec under `doc/specs/`.
|