[Fix] Cursor stale active turn#3748
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 Straightforward bug fix that clears the active turn reference when the provider session state changes to a non-running state. The change is limited to one conditional expression with comprehensive test coverage validating the expected behavior. You can customize Macroscope's approvability policy. Learn more. |
Clear stale active turns after interruption
What Changed
thread.session-setwith a non-running session state.session.started→session.state.changed→thread.started.Why
Interrupted Cursor threads could remain stuck on “Working” after an app or host restart. In a real incident, the turn was marked interrupted, but the session still retained that turn as active. Recovery then restored the session as running from stale state.
The fix keeps interrupt requests from optimistically marking a live provider session idle, while still allowing a provider-confirmed
ready/terminal lifecycle event to clear stale active turn state during recovery.Checklist
Tests
pnpm exec vp test run apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts.pnpm exec vp check.pnpm exec vp run typecheck.Note
Fix stale
activeTurnIdon Cursor session after turn interruptsession.state.changedtoreadyafter an interrupted turn,activeTurnIdwas not being cleared, leaving the session with a stale active turn reference.nextActiveTurnIdtonullin ProviderRuntimeIngestion.ts when asession.state.changedevent maps to a status that is notstartingorrunning.session.state.changedevents that resolve toreadyorerrornow clearactiveTurnId; previously they preserved the prior value.Macroscope summarized d21bb79.
Note
Medium Risk
Changes thread session/turn lifecycle mapping during provider recovery, which affects UI “working” state; scope is narrow with targeted tests but touches core orchestration ingestion.
Overview
Fixes interrupted Cursor threads staying on Working when recovery replays provider lifecycle events while the session still pointed at a stale
activeTurnId.Provider runtime ingestion (
ProviderRuntimeIngestion.ts) now derives session status beforeactiveTurnId. Onsession.state.changed, when the mapped status is neitherstartingnorrunning,nextActiveTurnIdis cleared instead of keeping the previous active turn. That stops the Cursor recovery sequence (session.started→session.state.changed→thread.started) from re-attaching an already-interrupted turn as running.Regression tests add an integration case for interrupt-then-Cursor-recovery and a projection test that
thread.turn-interrupt-requestedmarks the turninterruptedwhile the session row staysrunningwith the sameactiveTurnIduntil a laterthread.session-setmoves toreadywithactiveTurnId: null. The ingestion test harness also exposes a sharedreadEventshelper.ProjectionPipeline.tsonly has a trivial guard-style formatting change toapplyThreadSessionsProjection; session clearing on interrupt is not implemented there in this diff.Reviewed by Cursor Bugbot for commit d21bb79. Bugbot is set up for automated code reviews on this repo. Configure here.