Repository navigation
fix(sessions): stop killing slow-booting backends on the readiness timeout - #776
Merged
Merged
Conversation
…ing backends Refs #772 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kk16MNVJtWAnCeGxGRuHqa
…meout ensureSessionLive treated "not input-ready within 30 s" as "failed to start" and killed the process. Under a restart herd an opencode TUI (whose readiness is first PTY byte + 250 ms) or a Codex resume of a large rollout takes longer than that; the lifecycle journal shows kill.request at 35.6 s ×3 and 69.5 s after boot against processes that were alive, and the same sessions re-woken by hand became ready in 1.7–4.1 s. The pane then sat dead until the user retried it — observed 94 s, 217 s and 556 s after boot: the "3-minute boot" and "opencode resume is broken" reports. The wait already rejects immediately for a backend that exited or failed, so reaching the deadline means the process is alive and slow. A timeout with a live backend now resolves the wake, leaves the pane not-ready and journals wake.result code:'ready-timeout'; only an observed exit or start failure keeps the kill. Main reports disposition 'joined' when a wake attaches to a recovery another caller started, which the renderer treats like adopted, and the raw terminal pane opts out of the readiness wait entirely so it shows the TUI booting instead of a blank box. The terminal provider runtime never waits. Fixes #772 Refs #774, #775, #596, #548 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Kk16MNVJtWAnCeGxGRuHqa
Two recover-suite cases still asserted that a joiner sees 'spawned'; under #772 the joiner reports 'joined' so the renderer can skip the readiness wait for a start it did not own. Order is deterministic (synchronous claim, then join), and both cases keep asserting exactly one spawn.
…hput fixes Preserve both the readiness regression and all dispatcher, WebGL, engagement and resize coverage when resolving the shared test-file conflict. Focused renderer checks pass (14 tests). Refs #772
This was referenced Sep 5, 2026
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.
Problem
ensureSessionLivetreated "the backend did not report input-ready within 30 s" as "the backend failed to start": it killed the process and marked the pane failed (session.tsreadiness branch). On a restart with a dozen CLIs starting at once, opencode TUIs (readiness = first PTY byte + 250 ms) and Codex resumes of large rollouts take longer than that. Lifecycle journal, run 75117:kill.request cause=live-entryat 35.6–35.8 s ×3 and at 69.5 s in run 95737 — against processes that were alive (noexitin between); the same sessions re-woken by hand became ready in 1.7–4.1 s. The pane then sat dead until the user retried it, observed 94 s, 217 s and 556 s after boot. This is the "resuming a terminal on boot is like a 3 min process" and "opencode terminal resume is fucked up" reports (#772; investigations in the boot audit and the opencode report).Two amplifiers:
AgentTerminalLeafwakes on mount while the rehydrate recovery is already in flight, main joined that recovery but still reporteddisposition: 'spawned', so the leaf's wake inherited the kill timer; and the leaf retried its attach only after that wake resolved, so a raw terminal pane was blank for the whole TUI boot even when it succeeded.Behaviour
waitForSessionInputReadyalready rejects immediately for a backend that exited or failed, so reaching the deadline means the process is alive and slow. The wake now resolves ok, the pane keeps its status and stays not-ready (readiness arrives whenever the composer does), and the journal recordswake.result ok:true code:'ready-timeout'. An observed exit or start failure still fails the wake and kills a spawned backend.SessionManager.recoverreturnsdisposition: 'joined'when it dedupes onto an in-flight claim (SessionRecoverResultwidened); the renderer treatsjoined+ live likeadoptedand skips the wait. The leaf therefore attaches as soon as the recovery it joined resolves.ensureSessionLivetakes{ awaitInputReady?: boolean };AgentTerminalLeafpassesfalseat both wake sites.providerRuntime === 'terminal'sessions skip the wait everywhere.rehydrate's own 30 s deadline on the recover RPC is unchanged: its consequence is a cancelled claim and a retryable pane, not a kill.Design decisions
joinedover renderer-side detection: only main knows whether a recover call started the process; the disposition is the honest signal, and it makes the leaf's attach follow backend liveness for free.Linked issues
Fixes #772. Refs #774 (spawn herd), #775 (boot-path I/O), #596, #548.
Verification
sessionRecovery.renderer.test.tsx(+3): a spawned backend alive but not ready past the deadline → wake resolves,killOwnedSessionnot called, panestarted/not-ready; a backend that exits before ready → wake rejects, kill issued, panefailed; terminal-runtime andawaitInputReady: falsewakes resolve without the wait.sessionManager.wake.test.ts: the second wake that joins an in-flight recovery getsdisposition: 'joined'.AgentTerminalLeaf.dimensionOwnership.renderer.test.tsx(+1): a spawning backend is woken with{ awaitInputReady: false }.--project renderer src/renderer/src/workspace/hook/actions/+ the leaf suite — 9 files, 41 tests passed;--project unitwake + rehydrate — 6 passed;npx tsc -b— clean.Limitations / follow-ups
code:'ready-timeout'on an ok wake) is there to confirm on the next restart.🤖 Generated with Claude Code
https://claude.ai/code/session_01Kk16MNVJtWAnCeGxGRuHqa
Current integration verification (2026-09-04)
Integrated merged main feb6690 without discarding the dispatcher/WebGL/engagement/resize tests. Head 87ca7e9 passes both full host CI gates. Focused checks: 14 renderer tests plus six session-manager wake tests. Original live app and Bringdown were not restarted. Ready for owner merge confirmation.