fix(web): narrow stale send spinner recovery to composer state#1706
fix(web): narrow stale send spinner recovery to composer state#1706hhharryyyyy wants to merge 1 commit intopingdotgg:mainfrom
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
ApprovabilityVerdict: Approved A targeted bug fix that narrows the condition for showing the composer's running/spinner state. The runtime change is a single 17-line pure function; the rest of the diff is comprehensive test coverage. Clear intent, limited scope, and no side effects beyond fixing the stale spinner behavior. You can customize Macroscope's approvability policy. Learn more. |
508c5ad to
1228dab
Compare
Dismissing prior approval to re-evaluate 1228dab
Root cause
The stale send-spinner symptom is local to the composer, but the session lifecycle is not.
Today the composer stop/running state is driven by
phase === "running", which comes from the thread session state. In stale cases, that session state can remainrunningafter the latest turn is actually done, so the composer keeps showing the stop state and blocks the next send.However,
latestTurn.completedAtis not a safe global replacement for running state. That was the core mistake in#1700: assistant completion can happen before the turn is fully settled.#1704reverted that broader semantic change because it overcompensated for legitimate running cases. The earlier discussion in#1393also correctly identified that follow-up sends and delayed turn-start windows must not clear busy state early.Why
#1700regressed behavior#1700changed shared running semantics by treating a completedlatestTurnas no longer running, and then reused that across the composer spinner/stop button, footer layout, auto-scroll, and timer behavior.That was too broad. It made the composer stop showing running state as soon as
latestTurn.completedAtexisted, including cases where assistant output had finished but the turn itself was still legitimately running.Why this fix is narrower and safer
This change leaves shared session semantics alone:
derivePhaseisLatestTurnSettledWorking/ running indicators outside the composerInstead, it narrows the stale-spinner recovery to the composer primary action only. The composer now stops showing the running/stop state only when:
running, andThat final checkpoint is a stronger proof of true turn settlement than
latestTurn.completedAtalone, because it occurs downstream of full turn completion. This preserves the legitimate-running case that#1700broke while still recovering the stale composer state when the session lags behind.Exact verification performed
bun fmtbun lintbun typecheckbun run --cwd apps/web test src/components/ChatView.logic.test.tsbun run --cwd apps/web test src/session-logic.test.tsbun run --cwd apps/web test:browser src/components/ChatView.browser.tsxRegression scenarios covered
runningsession whose latest turn already has a finalized checkpoint; composer returns to send state instead of staying on stoprunningsession with assistant completion but without a finalized checkpoint; composer still shows stop/runningthread.turn.start; composer stays inSendingthread.turn.startbrowser case and existing local-dispatch logic testsNote
Fix stale send spinner by narrowing composer running state to session phase and checkpoint presence
shouldShowComposerRunningStatein ChatView.logic.ts to determine composer running state based on session phase, latest turn completion, and presence of a finalized checkpoint summary for that turn.completedAtor lacks a finalized checkpoint; otherwise the Send button is restored.phase === "running"; now it reverts to idle/send once a finalized checkpoint exists for the latest turn, even if the session is still running.Macroscope summarized 1228dab.