fix(ca): an agent with a pane open is not still "waking" - #1106
Merged
Conversation
Create a new cloud agent, land in its session, and the tree still calls it "waking" while you are typing into it. The row renders the platform's raw status, and `sorted_agents` already documents the vocabulary: "running first, waking next" — where the middle rank is `starting`. That status lags routability by design. #1098 established the gap: the platform routes a shell as soon as the container exists, while RUNNING additionally waits on route publication, a projection hop, and a poll interval. The launcher stopped gating attach on it and started probing the route instead — but the tree kept rendering the value the CLI itself had already decided not to trust. An attached, unfinished pane is direct evidence the agent is up: there is a shell running on it. So believe the pane over the projection. Scoped to `starting` only. A pane can outlive what it is attached to, and sleeping/crashed/failed/deleting alongside a live pane is news the user needs rather than latency to paper over. Three places, so display and state agree: - the row's status and note read `running` once a pane is open; - `sorted_agents` ranks on the displayed status, so the row does not sit in the waking band while reading `running`; - `attach_session` clears a settled wake op and its watch. A pane opening proves the wake landed, and it stops the 1.5s watch tick polling that environment for up to WAKE_PATIENCE about an agent already taking keystrokes. Sleep and delete are untouched — neither is proven by an attach. Known limitation, measured after the fact: a 10-agent benchmark put the routine lag at a few seconds, closing before the session is usable (status reached RUNNING before the harness answered in all 10 runs). The case that prompted this was an agent that stayed `starting` and had to be deleted — and this change would render that one `running` too, hiding the only signal something was wrong. A follow-up should bound the override to a short grace window after attach and surface a persistent `starting` explicitly. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The override shipped in the previous commit was unbounded: any open pane made a `starting` agent read `running`, forever. That hides the case that prompted the fix — an agent that stays `starting`, routes SSH fine, and has to be deleted. The row would have painted it green and removed the only signal the user had. Bound it to the window the lag actually lives in. Measured over ten `railway code --claude --new` runs, status reached RUNNING 5.3–14.2s after create, before the harness answered every time. 45s from pane open is generously past that, so a slow-but-healthy boot never flickers into looking stuck, while an agent still `starting` past it goes back to reporting what the platform says. `agents_with_live_panes` now carries how long each pane has been open rather than just which agents have one, via a new `Session::open_for`. The decision stays a pure function of (status, pane age), so the boundary is unit-tested directly instead of through a fabricated Session clock. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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
Create a new cloud agent, land in its session, and the tree still calls it "waking" while you're typing into it.
The row renders the platform's raw status, and
sorted_agentsalready spells out the vocabulary — "running first, waking next, sleeping last" — where the middle rank is literallystatus == "starting".That status lags routability by design. #1098 established the gap: the platform routes a shell as soon as the container exists, while
RUNNINGadditionally waits on route publication, a projection hop, and a poll interval. The launcher stopped gating attach on it and started probing the route instead — but the tree kept rendering the value the CLI had already decided not to trust.Fix
An attached, unfinished pane is direct evidence the agent is up: there's a shell running on it. Believe the pane over the projection.
displayed_statusrunningonce a pane is open.sorted_agentsrunning.attach_sessionWAKE_PATIENCEabout an agent already taking keystrokes.Scoped to
startingonly. A pane can outlive what it's attached to, andsleeping/crashed/failed/deletingalongside a live pane is news the user needs, not latency to paper over. Sleep and delete ops are untouched — neither is proven by an attach.Testing
1126 pass, 0 clippy errors. Four new tests:
running(fails withstartingif the override is removed — verified)startingstatus survives an attached paneWhy the override is bounded
An unbounded "pane open ⇒ not starting" rule would hide the case that prompted this: an agent that stays
starting, routes SSH fine, and has to be deleted. Painting that green removes the only signal the user has.So the override only covers the window the lag actually lives in. Benchmarked with 10 ×
railway code --claude --new(agents cleaned up after):RUNNINGStatus reached
RUNNINGbefore the harness answered in all 10 runs, worst case 14.2s from create — and a pane opens partway into that.STARTING_GRACEis 45s: generously clear of a slow-but-healthy boot, but bounded, so an agent stillstartingpast it goes back to reporting what the platform says.The decision is a pure function of
(status, pane age), so the boundary is unit-tested directly rather than through a fabricatedSessionclock.🤖 Generated with Claude Code