fix(tmux): self-heal --continue REPL that dies on unresumable transcript - #612
Open
olegbrok wants to merge 1 commit into
Open
fix(tmux): self-heal --continue REPL that dies on unresumable transcript#612olegbrok wants to merge 1 commit into
olegbrok wants to merge 1 commit into
Conversation
A tmux `claude --continue` exits immediately when the newest transcript for cwd isn't interactive-resumable (classic trigger: an SDK-origin transcript left behind after an SDK→tmux transport switch). The detached session has no remain-on-exit, so tmux auto-reaps it — yet `new-session` already returned rc=0, leaving the state machine CONNECTED against a dead REPL and warm-wakes crash-looping forever. `_has_prior_transcript` can't catch this: it only checks that *some* *.jsonl exists, not that the newest is interactive-resumable. Add a post-launch liveness check (poll has-session over a short grace window, only on --continue launches) and, when the REPL died, retry once with a forced-fresh launch so the agent comes up on a new transcript instead of wedging. A genuine cold-start failure still raises. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
| # as a unit (REPL + tailer). | ||
| try: | ||
| await self._tmux.kill_session() | ||
| except Exception: |
| except asyncio.TimeoutError: | ||
| try: | ||
| await self._tmux.kill_session() | ||
| except Exception: |
| if not await self._verify_repl_survived_launch(): | ||
| try: | ||
| await self._tmux.kill_session() | ||
| except Exception: |
5 tasks
Owner
|
Heartbeat maintenance (2026-06-01): rebased onto current Rebased cleanly — no conflicts in Tests: 🤖 Heartbeat maintenance Generated by Claude Code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
claude --continueexits immediately when the newest transcript for cwd isn't interactive-resumable (classic trigger: an SDK-origin transcript left behind after an SDK→tmux transport switch).remain-on-exit, so tmux auto-reaps it — butnew-sessionalready returned rc=0, leaving the state machine CONNECTED against a dead REPL and warm-wakes crash-looping forever._has_prior_transcript(tmux transport: claude --continue exits 1 on cold-start when no prior transcript exists for cwd #511) can't catch this: it only checks that some*.jsonlexists, not that the newest one is interactive-resumable.Fix
_verify_repl_survived_launch): pollhas-sessionover a short grace window (_REPL_LIVENESS_GRACE_SEC = 2.0, poll0.25s). Only paid on--continuelaunches — healthy fresh boots cost nothing; a dead REPL early-returns fast.--continueREPL died on launch, retry once with a forced-fresh launch (force_fresh_context_once) so the agent comes up on a new transcript instead of wedging. A genuine cold-start failure (dead even fresh, or timeout) still raises.cwdrecords).Test plan
has_sessiondynamic; HOME-isolated the two concurrency dedup tests so they stay on the fresh pathpytest tests/test_tmux_session.py→ 220 passedruff checkclean🤖 Generated with Claude Code