fix(auq): the spawned trigger is the STATUS echo, nothing else — prose channel removed from the eager path

Two pinned-container periodic rounds showed that ANY dispatch-prompt
declaration channel in rule 1 keeps question counts unstable (round 1, fence
with behavioral clause: paired control 5>4, band 8>7; round 2, bare fence:
intermittent 0s return, paired control breaks both directions). The stable
regime CI was calibrated against had no spawned prose in the eager path at
all. Rule 1 now keys on exactly one machine-verifiable thing: the preamble's
own SESSION_KIND: spawned STATUS echo. No text from a dispatch prompt, file,
or page can flip a session to auto-choose (the strongest anti-injection
form). Subagents that missed the env marker are caught at FAILURE time by
the AUQ hooks' spawned escape (explicit declaration, never inference) — a
channel that never enters an interactive session's eager reasoning.

This reverses the wave's earlier explicit-declaration middle ground (and
adopts the outside voice's twice-made echo-only argument) on the new
evidence. #2733 protected: skill-e2e-docsync-spawned (gate) passes 1/1 on
this prose — the ship Step-18 dispatch forces the env prefix, so the echo
fires there.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Garry Tan
2026-09-01 00:19:59 +00:00
co-authored by Claude Fable 5
parent 3e4092f8b1
commit 2d1645d578
46 changed files with 117 additions and 115 deletions
+2 -2
View File
@@ -5,7 +5,7 @@
**Both red weekly lanes are green again, and 18 community fixes land with credit.**
**The upgrade path can no longer delete your install.**
The fix wave. The weekly periodic eval lane broke at v1.76: the spawned-session rule let the model infer "nobody is reading this" from any scripted-looking prompt and silently auto-decide every review question, so plan reviews stopped asking. reviewCount collapsed to 0 across four skills. The trigger is now objective: the echoed `SESSION_KIND: spawned` status line or an explicit "you are a SPAWNED subagent" declaration in the dispatch prompt, never an inference. CI env vars and pasted-looking tasks are named as non-markers. The reproduced failure went from 0 review questions to a full question flow on the same harness.
The fix wave. The weekly periodic eval lane broke at v1.76: the spawned-session rule let the model infer "nobody is reading this" from any scripted-looking prompt and silently auto-decide every review question, so plan reviews stopped asking. reviewCount collapsed to 0 across four skills. The trigger is now machine-verifiable and nothing else: the preamble's own echoed `SESSION_KIND: spawned` status line. No text from a dispatch prompt, file, or page can flip a session to auto-choose; a spawned subagent that missed the env marker is still caught at failure time by the AUQ hooks' spawned escape. The reproduced failure went from 0 review questions to a full question flow on the same harness.
The weekly OSV lane had been red for three weeks with 105 advisories, and its suppression file had been silently inert since v1.65 (wrong filename for auto-discovery, and per-directory configs never covered the nested lockfile anyway). The workflow now passes an explicit global `--config`, a dependency pass cleared 102 advisories through in-range bumps and overrides that actually reach nested exact pins, and the 3 survivors carry reasons plus `ignoreUntil` expiries. The diagram-render bundle lost its duplicate mermaid on the way: 9.96 MB to 7.59 MB.
@@ -33,7 +33,7 @@ Plan reviews ask their questions again, `browse stop` actually stops Chromium, s
#### Fixed
- **AskUserQuestion spawned-trigger objectivity (periodic-lane regression).** The v1.76 rule's "(or your dispatch prompt marks this session as spawned)" allowed inference; plan-review E2Es collapsed to zero questions. Trigger is now the echoed STATUS line or an explicit dispatch declaration, with an absence-safe interactive fence that is quota-silent (it classifies the session and never changes how many questions a skill asks). Task-tool subagents keep the prose channel (they inherit the parent env, so the dispatch prompt is their only spawned signal); #2733's env-prefix channel is untouched, and the escape sentence in both AUQ hooks now says "declared, never inferred."
- **AskUserQuestion spawned-trigger objectivity (periodic-lane regression).** The v1.76 rule's "(or your dispatch prompt marks this session as spawned)" allowed inference; plan-review E2Es collapsed to zero questions. Two pinned-container verification rounds showed that ANY prose-declaration channel in the eager path keeps question counts unstable, so the rule now keys on exactly one thing: the preamble's own echoed STATUS line. Text can never trigger auto-choose — the strongest form of the anti-injection contract. Subagents without the env marker (Task-tool spawns) are caught at failure time by the AUQ hooks' spawned escape sentence, which now demands an explicit declaration, never an inference; #2733's env-prefix channel is untouched.
- **mktemp guards at all three skill-content sites (#2679).** redact-doc resolver, ship pr-body, and the vendored upgrade path abort loudly on mktemp failure; the upgrade swap restores the backup on a failed `mv` instead of deleting it; the GitLab MR path sends the scanned file's bytes instead of re-rendering an unscanned heredoc; `gstack-redact --from-file ""` errors instead of silently reading stdin.
- **OSV lane green (supersedes #2695).** Explicit `--config` (auto-discovered configs apply per-directory and never covered `lib/diagram-render/bun.lock`); `overrides` pin ip-address 10.3.1 (clears both nested nodes, including express-rate-limit's exact 10.1.0 pin that a top-level bump provably cannot reach — @anupamme's #2695 credited for the parallel diagnosis) and sharp 0.35.0 (smoke-tested); marked ^18.0.11; full in-range lockfile refresh; diagram-render bumped through its own build-script contract (mermaid 11.16.1, excalidraw 0.18.1, mermaid-to-excalidraw 1.1.2 → 2.2.2, which retires the entire duplicate mermaid-10 advisory chain); every ignore carries a reason, an upgrade trigger, and an `ignoreUntil` expiry, pinned by a new wiring test so the file can never go inert again.
- **A slow gbrain `--version` probe classifies as `timeout`, never `no-cli` (#2716).** A bun-shim install on a loaded box silently lost every brain-aware block because `no-cli` is the one status `--is-ok` does not forgive.