Skip to content

fix-wave 4: native outside voice without TaskOutput (#3182), CEO plan finder (#3159) - #3206

Closed
garrytan wants to merge 5 commits into
capy/fixwave-3from
capy/fixwave-4
Closed

garrytan wants to merge 5 commits into
capy/fixwave-3from
capy/fixwave-4

Conversation

@garrytan

Copy link
Copy Markdown
Owner

Fix wave 2026-10-15 stack (review per layer; merge only the wave PR capy/fixwave-release → main, which carries the single v1.91.104.0 stamp, the combined CHANGELOG, and runs the paid gate once). Order: capy/fix-wave-2026-10-15 (= main 47d639a) ← 1a ← 1b ← 2 ← 3 ← 4 ← release. This PR: 4. Layer PRs target the layer below, so no paid evals run on them; they get closed with a pointer once the wave PR merges.

Fix wave 2026-10-15, layer 4: native outside voice without TaskOutput (#3182) and the CEO plan finder (#3159, #280)

This layer stacks on capy/fixwave-3 (Lane D). It has no VERSION or CHANGELOG stamp; the release layer adds those.

Item 17 (#3182): bound the native outside voice without TaskOutput

On Claude Code 2.1.277 and later, plan reviews lost their native second opinion when Codex was missing or failed, because the fallback depended on TaskOutput. A free spike against the Claude Code docs and the published 2.1.300 binary showed a deadline can still be enforced:

  • Interactive sessions always run agents in the background, so a foreground Plan agent isn't available there.
  • A finished background agent sends a <task-notification> (task-id, status, summary, result). Its summary marks interim results ("is waiting on its own background work") and partial ones (turn limit).
  • TaskStop accepts background agent and shell IDs.
  • The 2.1.300 sleep block applies only to foreground commands, so a background sleep 300 (run_in_background: true, timeout: 300000) works as a host timer.
  • Six captured native reviewer runs took 50.6 to 103.7 s.

The fallback now starts the background timer, dispatches the Plan agent in the background, waits for notifications, and stops whichever task loses with TaskStop. Only a matching completed notification that beats the timer counts. Late, partial, interim and foreground results get no credit.

If the bounded fallback can't run (for example CLAUDE_CODE_DISABLE_BACKGROUND_TASKS=1 or bare mode), the review prints Outside voice unavailable: <cause>. Fix: <fix>. … (OUTSIDE_VOICE_UNAVAILABLE). That's a new result code with a docs/troubleshooting.md entry (#outside-voice-unavailable). Review-log rows for unavailable outcomes carry unavailable_reason. bin/gstack-doctor-components.sh is regenerated.

The prose was tightened so the change shrinks the plan-eng-review union by 17 bytes and adds 4 to plan-ceo-review, which keeps both under their caps.

Tests:

  • test/outside-voice-native-deadline.test.ts is new. It fails 4/4 on the base and passes on this branch.
  • test/run-in-background-guidance.test.ts pins now check the timer, notification and TaskStop contract instead of TaskOutput's output format.
  • test/helpers/auq-sdk-capture.ts detectSectionReads fix (separate commit): two chunks that touch exactly and share an edge byte by chance lost a real byte when overlap was trimmed. A new case in test/section-capture-native-tools.test.ts fails without the fix.

Item 14 (#3159, #280): /plan-eng-review reads the branch's CEO plan

The two commits from #3159 are cherry-picked with their original authorship (thanks @szsunyuan):

  • bin/gstack-ceo-plan-find locates the CEO plan for a branch.
  • The plan-eng-review Design Doc Check reads it.

Follow-up changes on top:

  • The finder's stdout stays a bare path, or empty when there's no plan.
  • A plan borrowed from another branch prints one stderr line: CEO plan found (from branch <b>, not <current>): <path>. Control characters are stripped, and the branch reads unknown when the plan has no Branch line.
  • Interactive reviewers ask before using such a plan. Spawned sessions use it and quote the line.
  • test/ceo-plan-find-cross-branch.test.ts is new. It fails 5 of 7 on the fix(plan-eng-review): read the CEO plan in the Design Doc Check (#280) #3159 head; all 7 pass here.
  • plan-eng-review's size cap goes from 1.2170 to 1.2196, an approved raise. The measured size is 151,945 / 124,597 = 1.2195.

Behavior changes

  • Plan reviews on Claude Code 2.1.277+ get the native second opinion back when Codex is missing or fails: a Plan subagent runs in the background with a five-minute host timer, and only a complete report that arrives before the timer counts.
  • When background tasks are disabled, the review reports OUTSIDE_VOICE_UNAVAILABLE with the cause and the fix.
  • /plan-eng-review reads the branch's CEO plan. If the plan comes from another branch, it says so, and interactive sessions ask first.

Validation

Focused tests and ratchets pass on this branch: typecheck, typecheck:test (no new diagnostics), the spawnSync tripwire, module size, parity, context budget, gen-skill-docs freshness, and the item tests above. The paid gate runs once on the wave PR.

Not verified

  • No live Claude Code run of the new fallback, because that's paid. The format of a background agent's <task-notification> comes from the binary's prompt text, not from a captured notification.
  • When TaskStop ends the timer, the host may still deliver its notification. The prompt treats that as noise, but I haven't seen it happen.

Open in Capy

garrytan and others added 5 commits October 16, 2026 00:31
…3182)

Claude Code 2.1.277 removed TaskOutput, so the plan-review native fallback's
preflight always failed and users without the Codex CLI never got a second
voice. The fallback now uses primitives the host still enforces: a background
`sleep 300` Bash timer (its exit re-invokes the parent; the 2.1.300 sleep block
applies only to foreground commands), a background Plan dispatch whose
completion arrives as a <task-notification>, and TaskStop for whichever task
loses. Only a matching completed notification that beats the timer counts;
interim ("is waiting on its own background work"), turn-limit, foreground and
late results get no credit. The "[Subagent hand-back]" header (2.1.277) is
treated as framing.

The unavailable line now names its cause and fix, ends with
OUTSIDE_VOICE_UNAVAILABLE (new result code + troubleshooting entry), and the
review-log row carries unavailable_reason. The bounded-wait prose was
tightened so plan-ceo-review and plan-eng-review stay under their existing
size ceilings (no ratchet raise for this item).

Intentional pin change: test/run-in-background-guidance.test.ts
hasBoundedOutsideVoiceWait and the dispatch-contract cases now pin the
timer/notification/TaskStop contract instead of TaskOutput's envelope.
bin/gstack-doctor-components.sh is regenerated from lib/result-codes.ts.

Reported by HuellintonMota in #3182.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
/plan-ceo-review saves its scope decisions under the state root's
ceo-plans/, but no plan review can find them: only /design-html reads
that directory, newest file first. This helper is the CEO-plan sibling of
gstack-design-doc-find, so /plan-eng-review can call one command instead
of a glob in prose.

It prints the newest top-level plan whose "Branch:" header names the
branch, compared the way gstack-slug writes BRANCH (feat/x matches
feat-x), else the newest plan, else nothing. Subdirectories are not
read. A usage error exits 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/plan-eng-review never looked in ceo-plans/, so an eng review after
/plan-ceo-review ran without the scope that review accepted, deferred or
skipped. capy-ai closed #414 asking for this focused fix, and TODOS.md
scopes it as a gstack-ceo-plan-find sibling of gstack-design-doc-find.

The Design Doc Check now prints "CEO plan found: <path>" or "No CEO plan
found" after the design doc line, and the prose says what to read the
plan for. The data-not-instructions rule names the CEO plan too, since
another agent may have written it. Only plan-eng-review changes: the
shared {{DESIGN_DOC_DISCOVERY}} block and the branch-scoped review log
are untouched. Reported by @chancheuklap in #280.

main left plan-eng-review 4 bytes under its parity cap, so the +325
bytes raise maxSizeRatio to the measured 1.2196, noted the way earlier
growth was.

Fixes #280

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#280)

Review changes on top of #3159 (szsunyuan / y$un_):
- gstack-ceo-plan-find keeps stdout a bare path or empty; when it falls back
  to another branch's plan it prints one stderr line,
  "CEO plan found (from branch <b>, not <current>): <path>", with control
  characters stripped from the plan header ("unknown" when it has none).
- The Design Doc Check tells an interactive reviewer to ask before using such
  a plan, and a spawned session to use it and quote the disclosure.
- The Design Doc Check prose is tightened so plan-eng-review fits the
  owner-approved 1.2196 ceiling (measured 151,950 / 124,597 = 1.2195).

Reviewer tests: test/ceo-plan-find-cross-branch.test.ts (5 of 7 fail on the

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
#3159 head). The design-doc finder's matching disclosure stays deferred.
)

detectSectionReads trims the longest suffix/prefix overlap between
consecutive Bash outputs. Two chunks that abut exactly (tail -c +N after a
chunk ending at N-1) can share an edge byte by chance; the trim then drops a
real byte and a fully printed section reads as incomplete. #3182's
review-sections edit moved plan-ceo-review's 66,999-byte boundary onto
"cur|rent", which turned the existing byte-range test red. The detector now
also checks the plain concatenation; a gap still refuses.

Detector/fixture defect, not a product change. New regression case in
test/section-capture-native-tools.test.ts fails without the fix.

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
@capy-ai

capy-ai Bot commented Oct 16, 2026

Copy link
Copy Markdown
Contributor

Merged to main through the wave PR #3209 (squash 3e8b34d, v1.91.106.0), which carried this layer unchanged. Closing the layer PR.

@capy-ai capy-ai Bot closed this Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants