fix(orchestration): clear stale active turn after interrupt#2360
fix(orchestration): clear stale active turn after interrupt#2360joshmeads wants to merge 2 commits 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 |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit dcd2fef. Configure here.
ApprovabilityVerdict: Approved Straightforward bug fix that clears stale session state (activeTurnId, lastError) after turn interrupts/aborts. Changes are self-contained within orchestration state management and include comprehensive test coverage. You can customize Macroscope's approvability policy. Learn more. |
dcd2fef to
acceb5f
Compare
A provider can already be idle while the projected session still points at an older active turn. Interrupt now clears projected session state after the provider accepts the interrupt, and runtime ingestion lets a provider-current turn replace stale projected active-turn state. Constraint: Lifecycle guard must still reject unrelated stale runtime events. Rejected: Make this OpenCode-specific | the stale projection logic is shared across providers. Confidence: high Scope-risk: moderate Tested: bun run test src/orchestration/Layers/ProviderCommandReactor.test.ts src/orchestration/Layers/ProviderRuntimeIngestion.test.ts Tested: bun fmt Tested: bun lint Tested: bun typecheck Tested: bun run build:desktop
acceb5f to
edd9310
Compare

What Changed
Fixes stale projected provider turn state after a successful interrupt.
After the provider accepts an interrupt, the shared orchestration layer now clears the projected active turn and marks the session ready. Runtime ingestion also allows the provider-current turn to replace stale projected active-turn state while still rejecting unrelated stale lifecycle events.
Why
A provider could already be idle while T3 Code still projected an older turn as active. In that state, pressing Stop could call the provider interrupt successfully, but the UI stayed stuck as “Working” because no later provider event cleared the stale active turn.
This is shared orchestration logic, so the fix applies across providers. OpenCode exposed the issue, but the stale turn projection bug was not OpenCode-specific.
Diagnosed from persisted projection/event state during a live repro: the provider had completed later turns, while
projection_thread_sessions.active_turn_idstill pointed at an older running turn. Stop/interrupt succeeded, but no later provider event cleared the stale projected turn.Checklist
Constraint: Lifecycle guard must still reject unrelated stale runtime events.
Confidence: high
Scope-risk: moderate
Tested:
bun run test src/orchestration/Layers/ProviderCommandReactor.test.ts src/orchestration/Layers/ProviderRuntimeIngestion.test.tsTested:
bun fmtTested:
bun lintTested:
bun typecheckTested:
bun run build:desktopScreenshots
Note
Medium Risk
Touches shared orchestration session/turn lifecycle projection logic; mistakes could incorrectly clear or accept turn state and affect UI/session consistency across providers.
Overview
Fixes cases where a successful Stop/interrupt still leaves a thread projected as running.
ProviderCommandReactornow clears projected session state afterthread.turn.interrupt(sets session toready, clearsactiveTurnId, and resetslastError).ProviderRuntimeIngestionnow (1) treatsturn.abortedliketurn.completedfor closing lifecycle state and finalizing buffered assistant/proposed-plan output, and (2) allows a conflictingturn.startedto replace a stale projectedactiveTurnIdwhen it matches the provider’s currently active turn (while continuing to reject unrelated stale lifecycle events).Reviewed by Cursor Bugbot for commit 1a9b981. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Clear stale active turn and session state after thread interrupt
thread.turn.interruptevent,ProviderCommandReactornow sets the thread session status toready, clearsactiveTurnId, and clearslastError.ProviderRuntimeIngestionnow treatsturn.abortedas a lifecycle-closing event: clears the active turn, sets session toready, and finalizes buffered assistant messages and proposed plan content.turn.startedevent that conflicts with the projected active turn is now accepted when the provider's expected active turn matches the incoming event, allowing the provider's current turn to replace stale projected state.readywith no active turn.Macroscope summarized 1a9b981.