fix(chat): keep the working indicator on a thread opened mid-turn - #554
Merged
Merged
Conversation
Opening a running thread sometimes showed no working indicator or timer until the turn ended. Two causes: - The snapshot fold marks the replica idle unless the status replica says the turn runs. Status and events are separate topics (and reconnect resubscribes in hash order), so the fold could be settled by the stale status cached from the last visit; the fresh running status never revived it. A change of the selected status's turn_running now idles the replica in place or refolds the held records. - A snapshot window is byte-bounded from the tail, so a large running turn can be cut after the record that opened it, leaving a fold that neither runs nor times the turn. While the status runs and the replica holds only that partial turn, earlier pages load until the turn's start arrives.
yermakoffivan
pushed a commit
to yermakoffivan/tcode
that referenced
this pull request
Sep 30, 2026
A client folds a byte-bounded window of a session's log and used to decide liveness itself: mark_idle unless the status said the turn ran. That lost the pending question and the working indicator whenever a stale cached status settled the fold, and Tryanks#554 patched it with a refold on every running flip plus back-to-back history pages until the running turn's start arrived, downloading the whole running turn (often several MB). The host already holds the complete fold and knows whether its provider is live, so SessionStatus now carries the running turn (its index in the whole log and start time), the pending approvals and the pending question, gated on an in-flight turn. The client folds held records purely and settles which held turn runs from the status, in place and without discarding anything, whenever either topic changes. An unready plan is hidden while its turn is not running instead of being discarded. PROTOCOL_VERSION 7.
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.
Behaviour
Opening a running thread (most often on a phone) sometimes showed no working indicator or timer at the bottom of the chat until the turn ended.
Cause
Two independent paths left the selected session's timeline replica not running while the host's status said the turn ran:
mark_idleunless the status replica saysturn_running. On selection that replica is the status cached from the last visit, and status and events are separate topics (reconnect resubscribes from aHashMap, so either can arrive first). A fold settled by a stale idle status stayed idle when the fresh running status arrived, since nothing re-evaluated it.session_events_snapshotbounds the window by bytes from the tail, so a large running turn can be cut after the record that opened it. The client's fold of that window has noTurnStarted, so the turn neither runs nor has a start time, and if the tail already covers enough screens no earlier page is ever requested.Fix
fold_held_recordsis the one place that folds held records and applies the status (previously duplicated in the snapshot and history-page handlers).reconcile_replica_liveness: when the selected status'sturn_runningchanges, the replica is idled in place, or refolded when it must come back to life (mark_idlediscarded the live turn's state).running_turn_opening_unheld: while the status runs and the replica holds only a partial, non-running turn, earlier history pages load until the turn's start arrives, so the timer counts from the real start.Test
status_arriving_after_the_snapshot_settles_the_running_turn: a stale idle status, a snapshot withTurnStarted, then a running status; the last turn runs from theTurnStartedtime, and an idle status afterwards stops it.a_window_cut_inside_the_running_turn_loads_back_to_its_start: a snapshot window without the turn's start requests the earlier page; once it arrives the turn runs from its start.Both fail with the fix disabled.
Checks run
cargo fmt --all --checkcargo clippy -p tcode-ui --all-targets --locked -- -D warningscargo nextest run -p tcode-ui --locked(322 passed)Full workspace tests and the mobile/Web checks are left to CI. Not exercised on a real phone.