[orchestration] Clear stale active turn when session becomes inactive#3159
[orchestration] Clear stale active turn when session becomes inactive#3159Andrew-Forster wants to merge 1 commit into
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 |
a93024a to
b636c71
Compare
ApprovabilityVerdict: Approved Straightforward bug fix that clears stale You can customize Macroscope's approvability policy. Learn more. |
Summary
This clears stale
activeTurnIdstate when a provider reports that a session is inactive.Concretely,
session.state.changednow clearsactiveTurnIdwhen it maps to:readyinterruptedstoppederrorIt still preserves
activeTurnIdforstartingandrunning.Root Cause
The projection layer could previously write an impossible session state:
That is inconsistent. A session that is
ready,interrupted,stopped, orerrorshould not also point at an active turn.Codex exposes one concrete path into this state because T3 maps Codex
session/readyintosession.state.changed: ready, which is separate fromturn.completed. This PR does not assume Codex normally omitsturn/completed; the upstream app-server docs describeturn/completedas the normal terminal turn event. The fix is about making T3's projection invariant correct whenever an inactive session-state event is processed.Why This Matters
A stale active turn can make the UI/sidebar keep treating old work as active after the provider has settled.
It can also affect cleanup.
ProviderSessionReaperskips sessions when the projected thread still hasactiveTurnId != null, so preserving stale active-turn state can make a settled provider session look unreapable.This does not try to solve every provider desync case. It fixes one small shared invariant: inactive sessions should not retain active turns.
Scope / Tradeoff
Low risk: this only changes
session.state.changedhandling for inactive statuses.Shared orchestration fix: the behavior is not Codex-specific. Codex is just the clearest known path because of its separate
session/readyevent.Preserved behavior: mid-turn
session.started/thread.startedupdates still keep the active turn. There is an existing regression test for that path, and this PR keeps it passing.Validation
pnpm --filter t3 exec vp test run src/orchestration/Layers/ProviderRuntimeIngestion.test.ts -t 'clears active turn when provider session becomes ready' --reporter=verbosepnpm --filter t3 exec vp test run src/orchestration/Layers/ProviderRuntimeIngestion.test.ts -t 'does not clear active turn when session/thread started arrives mid-turn' --reporter=verbosepnpm --filter t3 exec vp run typecheckpnpm exec vp check(existing unrelated warnings only)git diff --checkReferences
session/readytosession.state.changed: readyinCodexAdapterProviderSessionReaperskips cleanup while projectedactiveTurnIdis non-nullturn/completedas the normal terminal turn event: https://github.com/openai/codex/blob/main/codex-rs/app-server/README.md#lifecycle-overviewRelated
Note
Low Risk
Narrow change to session lifecycle projection in ProviderRuntimeIngestion; existing mid-turn lifecycle test preserved.
Overview
Provider runtime ingestion now clears projected
activeTurnIdwhen asession.state.changedevent maps to an inactive session status (ready,interrupted,stopped, orerror). Onlystartingandrunningmay retain an active turn, via new helpersessionStatusAllowsActiveTurn.This fixes inconsistent projections such as
status: readywith a non-nullactiveTurnId—notably when Codex emitssession/readyseparately fromturn.completed—which could keep the UI treating old work as active and block ProviderSessionReaper cleanup.Mid-turn
session.started/thread.startedbehavior is unchanged (still preservesactiveTurnIdwhen a turn is running). Adds a regression test and extendswaitForThreadtimeouts on related lifecycle tests.Reviewed by Cursor Bugbot for commit b636c71. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Clear stale
activeTurnIdwhen provider session transitions to an inactive statesessionStatusAllowsActiveTurnhelper in ProviderRuntimeIngestion.ts that returnstrueonly forstartingorrunningstatuses.session.state.changedevent produces a non-running/non-starting status (e.g.ready,error,stopped),session.activeTurnIdis now set tonull, preventing stale active turns from persisting.activeTurnIdis cleared when the session returns toready.Macroscope summarized b636c71.