fix-paste-events

Fix: paste events leak to PTY child when new-chat dialog is open (fix-new-chat-2 covered keystrokes only)

Metadata

Statusdone
Assignedagent-1257
Agent identityf51439356729d112a6c404803d88015d5b44832c6c584c62b96732b63c2b0c7e
Created2026-04-30T14:08:18.218683243+00:00
Started2026-04-30T14:08:48.011832397+00:00
Completed2026-04-30T14:21:02.050311925+00:00
Tagspriority-high,bug,tui,ux,input,dialog, eval-scheduled
Eval score0.93
└ blocking impact0.90
└ completeness0.98
└ coordination overhead0.88
└ correctness0.95
└ downstream usability0.85
└ efficiency0.90
└ intent fidelity0.89
└ style adherence0.95

Description

Description

fix-new-chat-2 (commit f6d2c62ce) gated vendor_pty_active on InputMode::Normal for keystroke routing — keys typed into the new-chat dialog no longer leak to the underlying chat's PTY. But the user reports that PASTING (Cmd-V / Ctrl-Shift-V / middle-click) into the dialog STILL leaks the pasted content into the underlying chat tab.

User repro 2026-04-30 on fresh post-fix binary: pasted https://lambda01.tail334fe6.ts.net:30000 into the new-chat dialog → URL appeared in the active background chat tab.

Likely cause

Paste events are a separate crossterm event class. When the terminal sends bracketed paste \x1b[200~<content>\x1b[201~, crossterm parses it as Event::Paste(String) rather than a sequence of Event::Key events. fix-new-chat-2's input_mode guard was on the key-event branch of the dispatch; the paste-event branch likely has its own direct-to-PTY forwarding that doesn't consult input_mode.

The fix is the symmetric guard on the paste path: when input_mode is NOT Normal (i.e., the launcher overlay is open), paste events go to the focused dialog widget, NOT to the underlying PTY child stdin.

Confirmed scope (from user testing)

  • Keystroke leak: FIXED by fix-new-chat-2
  • Paste leak: STILL BROKEN
  • Switching focus between chat tabs (no dialog open): works correctly — chat-vs-chat input routing is fine
  • Bug is specific to: new-chat overlay open + paste event

Investigation

  1. Find the paste-event handling in src/tui/ — search for Event::Paste or MouseEventKind::Paste (different terminals may emit differently)
  2. Check whether it routes through a unified input dispatch (which fix-new-chat-2 should have covered) OR through a separate paste-only branch (which it didn't)
  3. If the latter: apply the same input_mode guard on the paste branch

Validation

  • Failing test written first: simulate Event::Paste while launcher overlay is open, assert child_input_bytes_written stays at 0
  • Live smoke: open new-chat dialog, paste a URL into a text field, confirm: - URL appears in the dialog field (not the background chat) - Background chat's PTY child stdin receives 0 bytes during the paste
  • Same for keystroke path (no regression of fix-new-chat-2)
  • No regression on chat-vs-chat input routing (typing into a focused chat works as before)
  • cargo build + cargo test pass
  • Permanent smoke scenario: programmatic Event::Paste injection while launcher is open, byte-level assertion on background pane's child stdin
  • cargo install --path . was run before claiming done

Process note

This is the THIRD iteration of the new-chat input-leak bug class (fix-new-chat → fix-new-chat-2 → this). Pattern: each iteration covers ONE event class (chat tab focus, keystrokes, paste). Future input-routing changes should test ALL crossterm event kinds (Key, Mouse, Paste, Resize, FocusGained, FocusLost) to avoid another sequel. Worth a smoke scenario template that exercises every event kind under each input_mode combination so this regression class is fully gated going forward.

Depends on

Required by

Log