Problem
executeTuiRun (server/lib/tuiPromptRunner.js) still gates its paste on the old idle heuristic — "saw output, then went quiet for READY_IDLE_THRESHOLD_MS", with a blind sendPrompt('fallback') at PASTE_DEADLINE_MS. It has no equivalent of the CoS agent path's positive input-ready gate or its startup-dialog dismissals.
That means any first-run/opt-in modal the provider CLI paints will be treated as "the banner finished repainting", and the prompt gets pasted into the dialog, which ignores it. The run then burns its full timeout and finalizes on whatever the screen happened to say.
The agent path (server/services/agentTuiSpawning.js) has already had to learn this lesson twice:
- Claude Code's folder-trust gate (
TUI_TRUST_PROMPT_PATTERN)
- Claude Code v2.1.233's auto-mode offer (
TUI_AUTO_MODE_PROMPT_PATTERN) — four agents died paste-not-rendered on 2026-08-14 before it was handled
tuiPromptRunner handles neither, so a one-shot TUI run in a folder claude has not seen, or on a CLI version showing a new opt-in, fails the same way with no dismissal.
Why it was left out of the fix
The auto-mode fix scoped itself to the CoS agent spawner, which is where the incident happened and the only consumer of createInputReadyTracker. Extending tuiPromptRunner is a real behavior change to a separate execution path (it would newly suppress the blind-paste fallback), so it wants its own change and its own test pass rather than riding along.
Proposed work
- Build the shared tracker in
tuiPromptRunner too: createInputReadyTracker(...) from server/lib/tuiHandshake.js, fed from the existing onData handler with both the raw and ANSI-stripped chunk.
- Add the two dismissal branches to the
readyTimer interval, mirroring agentTuiSpawning.js — needsTrust → \r (accept "Yes, I trust"); needsAutoModeChoice → \x1b[B\r (decline, then ackAutoModeChoice()), each behind a one-shot latch.
- Decide the fallback posture explicitly. The agent path refuses to blind-paste and fails
tui-not-ready at the deadline. tuiPromptRunner currently always blind-pastes. Recommendation: keep the blind-paste fallback for non-claude providers, but suppress it while needsTrust/needsAutoModeChoice is armed — pasting into a known-live modal is never right, and the hard timeout is still the backstop.
- Tests in
server/lib/tuiPromptRunner.test.js: a run that paints the trust gate and one that paints the auto-mode offer both dismiss it and then paste. Verify each test bites by reverting the branch.
Acceptance
- A one-shot TUI run started in an untrusted folder dismisses the trust gate and submits its prompt.
- A run that hits the auto-mode offer declines it (option 2 — never rewrite the user's global permission default) and submits its prompt.
- No blind paste is sent while a known dialog is on screen.
Refs #4181 (the CoS-agent-side fix for the same class).
Problem
executeTuiRun(server/lib/tuiPromptRunner.js) still gates its paste on the old idle heuristic — "saw output, then went quiet forREADY_IDLE_THRESHOLD_MS", with a blindsendPrompt('fallback')atPASTE_DEADLINE_MS. It has no equivalent of the CoS agent path's positive input-ready gate or its startup-dialog dismissals.That means any first-run/opt-in modal the provider CLI paints will be treated as "the banner finished repainting", and the prompt gets pasted into the dialog, which ignores it. The run then burns its full timeout and finalizes on whatever the screen happened to say.
The agent path (
server/services/agentTuiSpawning.js) has already had to learn this lesson twice:TUI_TRUST_PROMPT_PATTERN)TUI_AUTO_MODE_PROMPT_PATTERN) — four agents diedpaste-not-renderedon 2026-08-14 before it was handledtuiPromptRunnerhandles neither, so a one-shot TUI run in a folder claude has not seen, or on a CLI version showing a new opt-in, fails the same way with no dismissal.Why it was left out of the fix
The auto-mode fix scoped itself to the CoS agent spawner, which is where the incident happened and the only consumer of
createInputReadyTracker. ExtendingtuiPromptRunneris a real behavior change to a separate execution path (it would newly suppress the blind-paste fallback), so it wants its own change and its own test pass rather than riding along.Proposed work
tuiPromptRunnertoo:createInputReadyTracker(...)fromserver/lib/tuiHandshake.js, fed from the existingonDatahandler with both the raw and ANSI-stripped chunk.readyTimerinterval, mirroringagentTuiSpawning.js—needsTrust→\r(accept "Yes, I trust");needsAutoModeChoice→\x1b[B\r(decline, thenackAutoModeChoice()), each behind a one-shot latch.tui-not-readyat the deadline.tuiPromptRunnercurrently always blind-pastes. Recommendation: keep the blind-paste fallback for non-claude providers, but suppress it whileneedsTrust/needsAutoModeChoiceis armed — pasting into a known-live modal is never right, and the hard timeout is still the backstop.server/lib/tuiPromptRunner.test.js: a run that paints the trust gate and one that paints the auto-mode offer both dismiss it and then paste. Verify each test bites by reverting the branch.Acceptance
Refs #4181 (the CoS-agent-side fix for the same class).