# Proof audit pass 1 — issue 23918

Read-only proof-scope audit, 2026-10-24. Workspace: /home/ubuntu/wt/issue-23918, branch fix/issue-23918. Compared local base revision 6e79211743 to local head revision 2995473fb0. No implementation review, edits to the worktree, tests, server, browser, forge operations, push, or merge performed. This document is outside the worktree.

## Complete diff and visual matrix

The entire diff contains only apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts and its .test.ts: 79 insertions, 1 deletion. Production changes extract whole-tool allow rules, retain granted tool names in the live Claude query context, consult that set in the tool permission callback, populate it after permission decisions, and initialize it for a newly opened query.

**Visual fixture matrix: empty (0 rows).** No render component, client caller, client data schema, navigation, layout, or interaction control changed. The existing approval surface receives fewer redundant requests; this is verified by event/runtime evidence. No screenshots, before/after pair, or interaction recordings are required for this server-only change. Existing before screenshots are optional context, not a substitute for runtime proof.

Changed callers/data scope: Claude SDK canUseTool -> canUseToolEffect; approval decision -> permissionResultFromDecision -> updatedPermissions -> wholeToolAllowRules -> live query set; query open/reuse/reset lifecycle. The resume dialog also calls canUseToolEffect with AskUserQuestion, which returns through its earlier dedicated path. ExitPlanMode, no-active-turn, approvals-disabled Plan, and no-approval-required paths remain earlier returns. No separate web/desktop/mobile, remote/tunnel, Settings, palette, keybinding, scheduler, or other-provider matrix is needed: all clients reach the same Claude server adapter and none of those paths changed. Other tools, including ordinary built-ins and MCP names, share this callback; fixture scope therefore cannot stop at one MCP name.

## Minimum real after-fix runtime proof

One real Claude run on the fixed revision, using the reproduced selection (Opus 5.5, Full access + Plan), in isolated development state. The executor must record the exact tested revision, CLI/SDK version, model, runtime and interaction modes, thread/provider-session identifiers, and process identity/lifetime. A stable native session ID alone does not establish that the CLI process was not restarted.

Use a benign synthetic target thread with at least two activity items and an item long enough to truncate at maxCharsPerItem=300. Request sequential t3_thread_read calls with view=activity, limit=1, maxCharsPerItem=300. First call must produce an approval request; respond acceptForSession once. Then make at least one actual afterPosition=nextPosition call and one actual itemId/textOffset=nextTextOffset call with distinct tool-use IDs. Both must execute successfully and return tool results without another approval request. Keep all calls in the same live CLI process. Complete the controlled sequence normally and capture all runtime-request events from before the first call through completion, so absence of repeat prompts has a bounded, auditable observation window.

Capture a timestamped transcript correlating each tool-use ID, arguments, successful tool result, first approval request ID and acceptForSession decision, and the full runtime-request event list for that window. Include process-open/close evidence or process identity with start time at both ends; do not infer process continuity solely from a provider session ID. Do not accept an assistant statement that no prompt occurred, a screenshot of an empty pending queue, or a mocked callback as real runtime proof. If the CLI itself now suppresses all later callbacks, record that fact: the runtime run proves the user outcome, while the adapter regression test proves the fallback branch.

A different benign tool must remain outside the grant. This can be demonstrated in the focused adapter fixture below; the live run need not execute a shell write or request additional permissions. Ordinary bugfix/MCP approval authorization is already explicit; no new permission checkpoint is required for this proof plan.

## Minimal behavioral fixture matrix (not visual)

Use focused adapter callback tests, not a product-wide Cartesian matrix. Multiple cases can share a harness. Inspect actual callback decisions and emitted request events, including unchanged input/tool-use ID on automatic allow.

| Row | Fixture | Required observation | Existing evidence / gap |
| --- | --- | --- | --- |
| B1 | Full access + Plan, no suggestions, first whole-tool MCP acceptForSession; then pagination and text continuation with changed inputs | First request asks; both later same-tool calls allow without new request; unrelated Bash still asks | Added regression covers this callback sequence; real after runtime still required |
| B2 | One-shot accept, decline, and cancel, followed by same-tool callback | None creates a standing grant; subsequent callback asks (cancel may end the active turn, so use valid next active turn in same process); denial/interrupt semantics preserved | Existing decision tests do not alone demonstrate cache non-population |
| B3 | Suggested permission updates: unrestricted addRules/allow (including another exact tool name); restricted ruleContent (including empty string); deny/ask and non-addRules updates | Only unrestricted addRules/allow tool names become automatic grants; each listed exact name works; restricted/unrelated names still ask | Existing helper tests cover conversion, not the new cache extraction/use |
| B4 | Grant already present, later callback has suppressAlwaysAllowRule=true or matchedAskRule present; also first response under either flag | Both flags prevent cache bypass and prevent recording a new standing grant from that callback; later ordinary callback has only previously valid grants | Existing presentation tests do not exercise the new callback guards |
| B5 | Grant then next active turn reusing the same query; then close/reopen query for the same native thread | Grant survives live-query reuse; adapter set is fresh on new process/query. Force a callback in the harness because native CLI resume rules may independently allow it | New lifecycle state needs focused query reuse/reopen proof |
| B6 | Ordinary approval-capable non-Plan callback (auto/default; and full-access provider-check callback if it reaches this branch) | Whole-tool cache behavior and exception guards are consistent outside Plan, since the new branch has no Plan-only condition | Focused harness coverage sufficient; no second live provider run required |
| B7 | Plan approvalPolicy=never, AskUserQuestion/resume dialog, ExitPlanMode, no-active-turn and no-approval-required paths | Earlier policy/special-tool behavior still wins over a seeded grant where reachable; never grants do not bypass Plan denial | Reuse existing focused tests; only extend where they do not establish ordering against a grant |

B1 is the issue acceptance fixture. B2–B7 are narrowly scoped proof obligations from the changed cache producer, consumer, guard, and lifetime, not additional implementation review findings. Cases impossible through the public callback contract can be documented as unreachable rather than fabricated. No destructive command, user data mutation, or full-suite rerun is needed.

## Evidence assessed and remaining requirements

The supplied runtime_requests_full.jsonl contains three resolved acceptForSession requests followed by a fourth pending request, all under one provider session/turn. The supplied native JSONL identifies Plan, claude-opus-5-5, CLI 2.1.303, and repeated t3_thread_read calls with text continuation offsets. This supports the before symptom; the same-process claim is supplied by the parent and should have process-lifetime evidence in the final paired runtime proof.

Parent reports the red regression at local revision 46b788d5c1 fails on main and fixed head passes 209 tests. This audit did not rerun or independently certify those results. Retain the actual red assertion/output and green command/output with tested revisions; do not replace them with the pass count. The added test covers B1, not all cache-boundary cases in B2–B7. Existing broad green tests can be reused where they prove the exact required observations; the number 209 alone does not establish them.

Proof acceptance: red output + fixed green output + bounded real after transcript for B1 + targeted evidence for applicable B2–B7. No visual artifacts required.

## FRICTION

- No after-fix runtime transcript was supplied or generated in this read-only pass. Runtime proof remains outstanding.
- Red/green test outcomes were supplied as claims; raw logs were not present in the listed evidence directory.
- The existing short runtime_requests.txt is truncated and ends earlier than runtime_requests_full.jsonl. Use the full JSONL for audit correlation.
- The supplied native transcript includes prompt/context payloads. Do not upload it wholesale without redaction; publish only synthetic or sanitized evidence with the correlation fields above. This audit uploads only this scope document.
- No browser/server/forge access is needed for this audit. No PR exists yet; no PR linking or publication action was attempted.
