Repository navigation
fix(claude): resolve the trust dialog from the observed highlight - #707
Conversation
Claude Code 2.1.251 flipped the trust dialog's default highlight to 'No, exit'; every accept path we own writes a bare Enter that now confirms the exit option and kills the session. The plan replaces the static keystroke contract with an observe-verify driver. Refs #705 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E9UW81kpTBiDPhZFpcpjf6
Claude Code 2.1.251 pre-highlights 'No, exit' in the folder-trust dialog, so the bare Enter this modal dispatched for accept confirmed the exit option and terminated the CLI — and because trust never persisted, the dialog returned on every start. Accept now leaves the renderer as the claude.trust-dialog.accept custom action, resolved headless-side by the new highlight-aware driver (claude-code-headless#51): it walks the pointer onto 'Yes, I trust this folder' with per-press verification and refuses to write when the screen cannot prove the layout. Decline becomes Esc, whose meaning does not depend on the highlight. Fixes #705 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E9UW81kpTBiDPhZFpcpjf6
|
Pre-merge review: 2-agent adversarial orchestrated panel (run Verified: full accept chain traced (modal → outlet custom dispatch → Recorded non-blocking follow-ups: desktop discards the |
Problem
Claude Code 2.1.251 re-ordered the folder-trust dialog and pre-highlights "No, exit". Our entire accept contract was a bare
'\r'written on the old "Yes is pre-selected" assumption — so clicking the app's own trust this folder button confirmed No, exit, terminated the CLI ~300ms later, never persisted trust, and brought the dialog back on every start. Every later send into the pane then failed withCannot deliver prompt: <id> is not a live agent session. Recorded end to end in debug bundle2026-08-30T23-51-06-471-9bd68e14(three identical kill loops across sessions1cc95cb1/4ac948fd/9bd68e14).Fixes #705.
Implemented behavior
Accept stops being a keystroke and becomes intent, resolved against the live screen:
TrustDialogParsernow extracts the real on-screen option order and which row carries the❯pointer; the newdriveTrustDialogAcceptdriver walks the highlight onto "Yes, I trust this folder" with per-press verification before pressing Enter, and fails closed (writes nothing) when the screen cannot prove where the pointer is. Theclaude.trust-dialogcondition's accept action is now{ kind: 'custom', name: 'claude.trust-dialog.accept' }; decline is Esc (replacing the numbered-list'2\r'). Handles both the 2.1.251 layout and the legacy numbered layout.onAccept/onDecline); the view dispatches the condition actions through the existing outlet →session:resolveCondition→ headless resolver path (the same plumbing AskUserQuestion uses). No raw bytes originate in the renderer anymore.ClaudeTrustDialogState.optionsgains the optionalhighlightedfield the parser now reports.Design decisions
'\r'pty accept; dispatching the pinned custom action is deterministic, and an old headless answers it with a structuredno-resolverfailure instead of a fatal byte.Tests
trustDialogView.renderer.test.tsxpins that accept dispatches the custom action and that no pty payload containing'\r'leaves the view, and that cancel dispatches Esc. Conditions-adjacent renderer suites green (28 tests).tscnode + web clean; targeted suites green underNODE_ENV=development.Known limitations / follow-ups
package-lock.jsondeliberately untouched: the package's ownpackage.jsondid not change.🤖 Generated with Claude Code
https://claude.ai/code/session_01E9UW81kpTBiDPhZFpcpjf6