fix(tmux): post-spawn liveness check for silent in-pane exit (issue #513) - #531
fix(tmux): post-spawn liveness check for silent in-pane exit (issue #513)#531bradbrok wants to merge 1 commit into
Conversation
|
Heartbeat maintenance: this branch was 16 commits behind Rebased branch: Generated by Claude Code |
0e0f0c6 to
0bdec9c
Compare
|
Heartbeat maintenance: previous rebase branch ( Fresh branch: Ready to force-push to Generated by Claude Code |
|
Heartbeat maintenance: Fresh branch: Ready to force-push to _Generated by Claude Code Generated by Claude Code |
|
Heartbeat maintenance: Fresh branch: Ready to force-push to Generated by Claude Code Generated by Claude Code |
0bdec9c to
c0595b0
Compare
|
Heartbeat maintenance (2026-05-27): rebased onto current Cherry-picked cleanly — no conflicts in Tests: 298 passed ( 🤖 Barsik heartbeat Generated by Claude Code |
c0595b0 to
8a65331
Compare
|
Heartbeat maintenance (2026-05-28): rebased onto current Rebased cleanly — no conflicts in Tests: 303 passed ( 🤖 Heartbeat maintenance Generated by Claude Code |
) tmux new-session returns 0 as long as the child shell + command launched. If the in-pane command exits immediately (bad flag, auth error, missing binary, etc.) the detached session reaps itself silently and the state machine ends up CONNECTED against nothing, queuing messages forever. Adds a ~150ms window + has_session() check after new_session() succeeds in _spawn_tmux_repl(). A dead session at that point raises RuntimeError so the existing BOOTING → DEAD via BOOT_FAILED transition fires correctly. The delay is tunable via _SPAWN_LIVENESS_DELAY_SEC (patched to 0 in tests). Also updates _make_mock_tmux() to return True for post-spawn liveness checks while keeping the pre-spawn stale-detection call returning has_session_initial (uses itertools.chain for precise call sequencing). 95 tmux_session tests pass; 208 across the tmux/agent_status/transport suite. Closes #513.
8a65331 to
9be6412
Compare
|
Heartbeat maintenance (2026-05-31): rebased onto current Tests: 332 passed ( 🤖 Heartbeat maintenance Generated by Claude Code |
Summary
Implements the structural defense from issue #513.
tmux new-sessionreturns 0 as long as the child shell + command launched. If the in-pane command exits immediately (bad flag, auth error, missing binary, API rejection, etc.) the detached session auto-reaps silently. The caller sees a successful spawn; the state machine ends upCONNECTEDagainst nothing and queued messages stack forever.new_session()succeeds in_spawn_tmux_repl(), wait ~150ms then callhas_session(). If the session is gone, raiseRuntimeErrorso the existingBOOTING → DEADviaBOOT_FAILEDtransition fires correctly — same path as any other spawn failure._SPAWN_LIVENESS_DELAY_SEC = 0.15constant alongside_COLD_START_TIMEOUT_SEC; tests patch it to 0 for speed._make_mock_tmux()updated to useitertools.chain([has_session_initial], repeat(True))so the pre-spawn stale-check and post-spawn liveness-check get the right values without breaking any existing test.Test plan
test_cold_start_session_dies_immediately_drives_to_dead: spawn succeeds, bothhas_sessioncalls return False →RuntimeError("session died immediately after spawn")→ state == DEADtest_tmux_sessiontests passtest_tmux_session/test_agent_status/test_tmux_transcript/test_transport_stateCloses #513.
🤖 Heartbeat maintenance — Barsik
Generated by Claude Code