fix(client-runtime): port turn-keyed settling — mobile/Windows stop flipping Running→Done→Running - #454
Merged
Merged
Conversation
…le/ready The thread detail reducer folded every `idle`/`ready` session status into a `completed` turn. Sessions bounce through `ready` mid-turn on start, restart, steer, and reconnect, so mobile and Windows flipped Running -> Done -> Running on each of those and pushed phantom completions. Port the turn-keyed settling PR #442 gave the mac (see apps/server/src/orchestration/projector.ts): non-terminal statuses settle nothing, an explicit `settledTurn` marker settles exactly the turn it names, a marker with `turnId: null` sweeps every still-running turn, and terminal statuses (error/interrupted/stopped) still sweep on their own. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…l lane A dispatched command rode an unary RPC with no deadline, and thread commands share one serial per-thread lane. A server that accepted the frame and never answered therefore parked the lane forever: every later command for that thread — including Stop and approval answers — queued behind it with no way out short of a reconnect. Two changes: dispatch now fails with a TimeoutError after 30s, releasing the lane; and the commands whose whole point is to reach a busy thread (interrupt, task stop, session stop, approval and user-input responses) run in their own per-thread lane so they never queue behind an in-flight or wedged send. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ptions Two failure modes of the same code path, so one change. A subscription that failed for a reason the server would keep repeating — a deleted or never-created thread — was retried after a flat 250ms, forever: roughly four subscribe+snapshot requests a second against a thread that will never exist, each one painting "Could not synchronize the thread." The retry delay now doubles from 250ms up to a 30s cap with jitter (so a fleet recovering from one incident does not resubscribe in lockstep), and a caller can classify a failure as terminal. A thread the server reports as not found is terminal: the state settles as deleted and stops resubscribing. A durable stream that died with a transport error was logged and silently drained to wait for the next session. When only that one multiplexed stream died the session never changed, so the atom kept serving frozen data labelled "live". Transport failures now run an `onTransportFailure` hook — thread and shell state mark themselves stale — and resubscribe on the same session under the same backoff. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…shell The shell/detail merge copied workspace metadata from the shell but left autoReviewPhase, settledOverride, settledAt, and scenery on whatever the detail carried. A detail that resumes from cache by events alone never rewrites those fields, so a thread the shell already reports as settled (or past its review phase, or rebranded) kept rendering the cached values until a full snapshot arrived. Co-Authored-By: Claude Fable 5 <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.
Summary
#442 fixed turn settling on the server and mac; mobile and Windows consume
packages/client-runtimedirectly and never got the fix — every session start/restart/steer/reconnect still flipped threads Running→Done→Running with a phantom completion push. Ported the same rule (mirrorsapps/server/src/orchestration/projector.ts:46-105exactly): non-terminal statuses settle nothing;thread.session-setsettles fromevent.payload.settledTurn; a running session-set naming a settled turn re-opens it.Also, while auditing the same subscription/command code paths:
autoReviewPhase/settledOverride/settledAt/scenerynow come from the shell inmergeEnvironmentThread, so an event-only resume can't leave them frozen at cached values.Area
apps/macapps/windows— Windows desktop appapps/mobile— iPhone companion appapps/serverpackages/client-runtime)Release size
size:XSsize:Ssize:Msize:Lsize:XLVerification
pnpm run verify --allafter merging current main: 5/5 steps, exit 0🤖 Generated with Claude Code