Metadata
| Status | done |
|---|---|
| Assigned | agent-2467 |
| Agent identity | 02e879681e52e0a384106169be043416c4d946e850ab26b2269c57681b52a6e7 |
| Model | codex:gpt-5.5 |
| Created | 2026-05-04T21:38:44.996177450+00:00 |
| Started | 2026-05-04T21:40:57.715650160+00:00 |
| Completed | 2026-05-04T21:58:56.051282193+00:00 |
| Tags | fix,bug,tui,chat,input, eval-scheduled |
| Eval score | 0.78 |
| └ blocking impact | 0.85 |
| └ completeness | 0.75 |
| └ constraint fidelity | 0.85 |
| └ coordination overhead | 0.85 |
| └ correctness | 0.80 |
| └ downstream usability | 0.80 |
| └ efficiency | 0.80 |
| └ intent fidelity | 0.79 |
| └ style adherence | 0.85 |
Description
Description
When a chat agent inside a TUI chat tab runs a bash subprocess that hangs (e.g., the agent invoked wg nex from bash and got stuck waiting on stdin per fix-agent-guide-nex), the user cannot cancel it. The user-visible freeze blocks the chat tab; Ctrl+C / Ctrl+] / etc. don't propagate to interrupt the hung subprocess.
User report 2026-05-04: 'I just got a freeze in this state and I can't even cancel it.'
What should happen
The chat tab is a tmux-wrapped PTY (per implement-tmux-wrapped). Sending an interrupt to the chat agent should:
- Reach the chat agent (claude/codex/nex CLI process)
- Propagate down to whatever bash subprocess it spawned (
wg nex "..."in this case) - Interrupt that subprocess
Investigate WHY this isn't happening. Possible causes:
- Ctrl+C in the chat tab is being captured by the TUI wrapper (treated as 'cancel chat input', not 'send SIGINT to PTY child')
- SIGINT reaches the chat agent process but isn't propagated to its bash subprocess (process group / session leadership issue)
- The hung wg nex subprocess is in a different process group from the chat agent and SIGINT doesn't reach it
Fix candidates
- Ensure Ctrl+C in the chat pane sends SIGINT to the FOREGROUND PROCESS GROUP of the PTY (standard terminal behavior)
- Verify chat agent's bash subprocesses inherit proper process group / can be signaled
- Add a TUI-level keybinding for 'kill all subprocesses of the focused chat agent' (escape hatch when the standard signal path fails)
Validation
-
Failing repro: in a chat tab, have agent run
sleep 999. Press Ctrl+C in the chat pane. Pre-fix: sleep doesn't terminate; chat tab feels frozen. Post-fix: sleep is interrupted; agent regains control. - Same test with the wg nex hang scenario
- Chat agent itself is NOT killed (only its hung subprocess) — agent still runs and can process the next message
- No regression of normal Ctrl+C behavior elsewhere in the TUI
- cargo build + cargo test pass
- cargo install --path . was run before claiming done
Coordinate
- fix-agent-guide-nex (sibling task) — addresses WHY agents trigger this hang. This task addresses the user's recovery path WHEN it happens.
- implement-tmux-wrapped — established the tmux+PTY wrap pattern; this task verifies signal propagation through that wrap
Depends on
Required by
Log
- 2026-05-04T21:38:44.952359836+00:00 Task paused
- 2026-05-04T21:39:45.154025494+00:00 Task published
- 2026-05-04T21:40:48.195116886+00:00 Lightweight assignment: agent=Careful Programmer (02e87968), exec_mode=full, context_scope=task, reason=Careful Programmer is the only implementation-capable agent and its Careful tradeoff is essential for correctness-critical signal handling; the task requires verifying signal propagation through process groups and PTY semantics without breaking existing Ctrl+C behavior.
- 2026-05-04T21:40:57.715655691+00:00 Spawned by coordinator --executor codex --model gpt-5.5
- 2026-05-04T21:41:17.586816634+00:00 Starting implementation: investigating TUI chat PTY signal handling and smoke coverage
- 2026-05-04T21:44:28.622831086+00:00 Implemented explicit chat PTY interrupt path and added live TUI smoke scenario
- 2026-05-04T21:49:23.921732969+00:00 USER CLARIFICATION 2026-05-04: the bug is NOT 'Ctrl+C doesn't propagate from chat agent to subprocess'. The bug is more upstream: > 'control+anything is not being sent to the pty... for reasons unclear b/c claude and codex do see ctrl+ whatever' So: - Normal chat interaction (typing prose to claude/codex): Ctrl+keys ARE delivered to the inner PTY - During this freeze: NO Ctrl+anything reaches the PTY That's a STATEFUL bug in the TUI's input dispatch — depending on what state the chat tab is in, Ctrl+ keys may or may not be forwarded. Specifically: - Pre-freeze active typing: works - Post-freeze (agent running a tool / waiting on a hung subprocess): doesn't work REVISED INVESTIGATION: Find the input dispatch code path for chat tabs. There's likely a state machine that gates input forwarding. Possible states: 1. Chat tab focused + agent idle: input → PTY child stdin (works) 2. Chat tab focused + agent running tool: input → ? (may go to a buffer / queue / nowhere — this is the bug) 3. Chat tab focused + agent waiting for response: input → ? (similar potential bug) Check whether there's a 'tool_running' or 'agent_busy' flag that suppresses Ctrl+ key forwarding. The original intent may have been 'don't let user keystrokes interrupt the agent's tool call', but the side effect is 'user can't send SIGINT to a hung tool either.' EXACT TEST CASES: - Test A: in a chat tab with agent IDLE, press Ctrl+C. Does the inner PTY child receive SIGINT? - Test B: in a chat tab with agent ACTIVELY RUNNING A TOOL (e.g., a long-running cargo build), press Ctrl+C. Does it reach the tool subprocess? - Test C: same as B but with a HUNG tool (`sleep 999` or the wg nex hang). Does it reach? If A works and B/C fails, the input dispatch is gating Ctrl+ keys when the agent is busy. The fix is to ALWAYS forward Ctrl+ keys to the inner PTY (let the inner CLI's signal handling deal with it) — never gate on agent-busy state. User's pattern observation: 'claude and codex do see ctrl+ whatever' — confirms gate is conditional, not always-on. UPDATED VALIDATION: - [ ] Failing test: chat tab with agent running a hung tool; Ctrl+C does not reach the subprocess - [ ] Fix: Ctrl+ keys ALWAYS forward to inner PTY regardless of agent-busy / tool-running state - [ ] Cross-check: typing prose into a chat (pre-freeze) still works - [ ] No regression of any other input behavior The original task framing assumed the bug was at the SIGINT-propagation layer (signal not reaching subprocess). User's correction is that the bug is at the EVENT-DISPATCH layer (keystroke not reaching the PTY at all when agent is busy). Different fix surface — likely in src/tui/viz_viewer/event.rs or similar.
- 2026-05-04T21:57:40.576094218+00:00 Validation: cargo build passed; targeted ctrl_c_maps_to_etx passed; live smoke scenario tui_chat_ctrl_c_interrupts_hung_subprocess passed; full cargo test blocked by unrelated prompt snapshot hash drift in pre-existing agency WIP
- 2026-05-04T21:58:13.337423185+00:00 Committed and pushed: 1f0e7dc04
- 2026-05-04T21:58:56.051286261+00:00 Task pending eval (agent reported done; awaiting `.evaluate-*` to score)
- 2026-05-04T22:00:25.293471898+00:00 PendingEval → Done (evaluator passed; downstream unblocks)