You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
release: v3.2.0 — the triage gate is on by default, and the claim that kept it off was wrong
The Stop triage gate shipped OFF, justified in our own audit table with: "turning
it on blocks turn-end in every session of every install, including sessions that
never touched Compound V." A live probe disproved both halves.
no .claude/compound-v.json -> silent (most installs)
config present, no uncovered change -> silent
docs/superpowers/**, hook's store -> exempt
uncovered code changes -> fires ONCE per session, marker before block
any timeout/unreadable/git error -> fails open, whole rule bounded at ~800 ms
The real population is a repository that deliberately initialised Compound V, once
per session, with code changes no triage record covers — exactly the failure this
plugin exists to catch. The complaint that started the 3.0 line was an agent
skipping the pipeline; leaving the one mechanism that catches it switched off was
not caution, it was mechanism-with-no-caller wearing a config key.
That is the SECOND published limitation in two releases that did not survive being
checked (3.1.2 was the clamp). Both were written from reading one function instead
of the path around it, and both were corrected only because something made me look.
The flip then introduced a bug of its own. jq's `//` is the ALTERNATIVE operator:
it yields the RHS for null AND for false, so `.enforcement.triage_gate // true`
turns an explicit `false` back into `true` and the opt-out documented in the gate's
own block message would silently not work. Caught by its own test on the first run
— the opt-out test was written before the flip was believed. Now an explicit
`== false` comparison, boolean or string.
Consequence pinned rather than discovered: the triage rule runs first, so a project
with pipeline_bypass:true and no triage_gate key now sees the triage wording instead
of the bypass wording. Deliberate — /v:triage IS the first step of the correction
the bypass rule asks for — and `"triage_gate": false` restores the old message.
Opt out with {"enforcement": {"triage_gate": false}}. Documented in README, /v:init
and the block message. pipeline_bypass unchanged and still off.
tests/test-epic-goal-stop.sh: 88 -> 98 checks. Eleven of twelve unused-native rows
now close fully; agentType remains at its designed end state, and triage keeps a
small honest ⚠ — UserPromptSubmit still carries a reminder and enforcement lands one
turn later at Stop. The gate makes skipping expensive, not impossible.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+38Lines changed: 38 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,6 +4,44 @@ All notable changes to **superpowers-v (Compound V)** are documented here.
4
4
5
5
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project uses semantic versioning.
6
6
7
+
## [3.2.0] - 2026-09-02
8
+
9
+
### Changed — the triage gate is ON by default, and the claim that kept it off was wrong
10
+
11
+
This is a behaviour change, and it exists because a limitation this project published about itself did not survive being checked. **Twice in two releases now.**
12
+
13
+
The `Stop` triage gate shipped off under `enforcement.triage_gate`, and the audit table justified that with: *"turning it on by default blocks turn-end in every session of every install, including for sessions that never touched Compound V."* A live probe on 2026-09-02 disproved both halves:
14
+
15
+
| State | Behaviour |
16
+
|---|---|
17
+
| no `.claude/compound-v.json`|**silent** — a project that never ran `/v:init` is untouched, which is most installs |
18
+
| config present, no uncovered change | silent |
19
+
|`docs/superpowers/**`, the hook's own store | exempt |
20
+
| uncovered code changes | fires **once per session**, marker written *before* the block, so it cannot loop |
21
+
| any timeout / unreadable record / git error |**fails open**, whole rule bounded at ~800 ms |
22
+
23
+
The real population is *a repository that deliberately initialised Compound V, once per session, with code changes no triage record covers*. That is exactly the failure this plugin exists to catch — the complaint that started the 3.0 line was an agent skipping the pipeline — and leaving the one mechanism that catches it switched off was not caution. It was the mechanism-with-no-caller defect wearing a config key.
24
+
25
+
**Opt out with `"enforcement": {"triage_gate": false}`** in `.claude/compound-v.json`. Documented in the README, in `/v:init`, and in the block message itself. `pipeline_bypass` is unchanged and still off.
26
+
27
+
### Fixed — the flip introduced a bug that would have made the opt-out a lie
28
+
29
+
`jq`'s `//` is the **alternative** operator: it yields the right-hand side when the left is `null`**or `false`**. So the obvious `.enforcement.triage_gate // true` turns an explicit `"triage_gate": false` back into `true`, and the opt-out documented in the gate's own block message would silently not work.
30
+
31
+
Caught by its own test on the first run of the flip — the opt-out test was written before the flip was believed. The value is now read with an explicit `== false` comparison, and both the boolean and the string form turn it off.
32
+
33
+
### Changed — the triage gate now shadows the bypass rule, deliberately
34
+
35
+
Both rules say *"you changed code without X"*, and only one response per `Stop` event is permitted. The more specific diagnosis goes first: `/v:triage`**is** the first step of the correction the bypass rule asks for. So a project with `pipeline_bypass: true` and no `triage_gate` key now sees the triage wording instead of the bypass wording. Setting `"triage_gate": false` restores the old message. Pinned by three tests so it can never become an accident.
36
+
37
+
`tests/test-epic-goal-stop.sh`: 88 → **98 checks**, including the opt-out, the shadowing, and the four live-probed states.
38
+
39
+
### Where the native-mechanism audit stands now
40
+
41
+
Eleven of the twelve "native mechanism exists, we were not using it" rows close fully. The remaining one is `agentType`, at its designed end state and explained in the table.
42
+
43
+
Triage-at-prompt-arrival keeps a small, honest ⚠: `UserPromptSubmit` still carries a *reminder*, and the enforcement lands one turn later at `Stop`. Between those two points nothing stops work beginning without triage. The gate makes that expensive, not impossible — and no wording here should be read as saying otherwise.
44
+
7
45
## [3.1.2] - 2026-09-02
8
46
9
47
### Fixed — a caveat this project published about itself was wrong
Copy file name to clipboardExpand all lines: README.md
+7Lines changed: 7 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -128,6 +128,13 @@ That's it.
128
128
-**Epic mode is bounded by default** — it stops after each feature for a human checkpoint. It is *not* a fire-and-forget overnight build unless you raise the budget.
129
129
-**Marathon mode (opt-in) is still not fire-and-forget-overnight.** It removes the per-feature checkpoint and adds an arbiter panel + blocker ledger + global breakers so it can run further unattended in one sitting — but on its own it does not self-revive after a hard death. If the session dies, you re-run `/v:epic <epic-id>` yourself; it resumes from the last committed state.
130
130
-**Auto-Resurrection (opt-in, v2.11) is a bounded catch-up, not an always-on service.** With `epic.autonomy.watch` on, a scheduler wakes roughly every 30 minutes and resumes a genuinely-dead marathon epic for you, up to a resume cap. It pauses or misses fires while the session is busy/unavailable, only catches up once per app open/wake on the on-disk tier, and needs both a quota reset and a still-authenticated session to survive quota exhaustion. A machine that is truly off is not covered; that needs remote infrastructure, which this does not ship.
131
+
-**The triage gate is ON by default (3.2.0), and here is how to turn it off.** Once per session, in a repo that has a `.claude/compound-v.json`, if the working tree carries code changes that no triage record covers, the `Stop` hook holds the turn open and asks for `/v:triage`. It is exempt on `docs/superpowers/**`, it fires at most once per session, it is bounded at ~800 ms and fails open on any timeout or error, and a project that never ran `/v:init` never sees it. To opt out:
132
+
133
+
```json
134
+
{ "enforcement": { "triage_gate": false } }
135
+
```
136
+
137
+
in `.claude/compound-v.json`. An explicit `false` is the only value that turns it off. It is **advisory** — the runtime discards a `Stop` block when a turn ends via a tool result or a loop tick, and `CLAUDE_CODE_STOP_HOOK_BLOCK_CAP` (default 8) lets the harness override it outright. It raises the cost of skipping the pipeline; it cannot make skipping impossible.
131
138
- No daemon, no server, no MCP service, no made-up cost numbers. Everything is small, readable scripts.
0 commit comments