Preserve provider bindings when stopping sessions#2125
Preserve provider bindings when stopping sessions#2125juliusmarminge merged 3 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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 560da15384
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const reaped = yield* providerService | ||
| .stopSession({ | ||
| threadId: binding.threadId, | ||
| preserveBinding: true, |
There was a problem hiding this comment.
Clear preserved binding when explicit stop is requested
Calling providerService.stopSession with preserveBinding: true during idle reaping leaves a persisted resume binding even after the runtime session is closed, but processSessionStopRequested only performs a destructive provider stop when thread.session.status !== "stopped" (apps/server/src/orchestration/Layers/ProviderCommandReactor.ts:714-716). In the common reaped state (session already marked stopped), an explicit thread.session.stop command no longer removes that binding, so a later turn can still resume via the persisted cursor (ProviderService.startSession reuses persisted binding state). This makes explicit stop non-destructive for already-reaped threads and breaks the stated manual-stop semantics for that scenario.
Useful? React with 👍 / 👎.
ApprovabilityVerdict: Needs human review This PR changes session lifecycle behavior by removing the ability to delete provider bindings on stop. Two unresolved review comments identify that the implementation contradicts the stated intent - manual stops now preserve bindings when they should be destructive, allowing unintended session resumption. You can customize Macroscope's approvability policy. Learn more. |
|
reading this now i don't remember why we ever remove the provider binding 🤔 |
- Keep persisted provider bindings on stop/reap - Remove obsolete `preserveBinding` stop flag Co-authored-by: codex <codex@users.noreply.github.com>
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 938a082. Configure here.
| runtimePayload: { | ||
| activeTurnId: null, | ||
| }, | ||
| }); |
There was a problem hiding this comment.
Manual stop preserves binding, contradicting stated destructive intent
High Severity
stopSession now always upserts the binding with status: "stopped", but the PR intent is to only preserve bindings for idle-reaper stops while keeping manual/explicit stops destructive. The preserveBinding conditional mentioned in the PR description was never implemented — ProviderStopSessionInput still only has threadId, and the remove method was completely deleted from ProviderSessionDirectory. After a manual stop, the next sendTurn will recover the same provider thread via the persisted resumeCursor instead of starting fresh.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 938a082. Configure here.
- Keep an existing thread bound to its provider after reap - Add regression coverage for first-turn and post-bind provider changes
The `remove` method was removed from `ProviderSessionDirectoryShape` in pingdotgg#2125 (Preserve provider bindings when stopping sessions). The test mock still referenced it, causing a typecheck failure. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>


Closes #2121
Summary
Why
Idle reaping currently uses the same destructive stop path as an explicit manual stop. For the Codex provider, that drops the resume cursor and forces the next turn onto a fresh Codex thread instead of resuming the previous provider thread.
This change keeps the resume binding for idle cleanup only, so a later send can recover the same provider thread while leaving explicit stop semantics unchanged.
Verification
bun fmtbun x vitest run apps/server/src/provider/Layers/ProviderService.test.ts apps/server/src/provider/Layers/ProviderSessionReaper.test.tsbun lintbun typecheckNotes
bun lintpasses with existing repo warnings outside this patchNote
Medium Risk
Changes provider session lifecycle/persistence semantics (stop no longer unbinds), which can affect routing and recovery paths across providers and restarts; coverage is improved but behavior changes are system-wide.
Overview
Provider session stopping is changed from a destructive unbind to a soft stop:
ProviderServiceLive.stopSessionnowupserts the thread binding withstatus: "stopped"(and clearsactiveTurnId) instead of deleting it, keeping the persisted provider + resume cursor so a latersendTurncan recover/resume the same provider thread.ProviderSessionDirectoryremoves theremove(threadId)API entirely, and tests are updated/added to verify stopped bindings remain persisted and that routing can resume after a stop.ProviderCommandReactorsession restart logic is tightened to always prefer the thread-bound provider and to only dropresumeCursoron model-change restarts, with test reordering/adjustments around restart-failure and provider-switch rejection.Reviewed by Cursor Bugbot for commit b33fd1f. Bugbot is set up for automated code reviews on this repo. Configure here.
Note
Preserve provider bindings when stopping sessions instead of deleting them
ProviderSessionDirectoryremoves theremovemethod; stopped sessions are now persisted withstatus: 'stopped'andactiveTurnId: nullrather than deleted from the directory.ProviderService.stopSessionupserts the binding on stop, so a subsequentsendTurncan resume from the correctresumeCursorand provider without re-binding from scratch.ProviderCommandReactorno longer restarts a session solely due to a provider change; it always uses the thread's bound provider and preservesresumeCursorunless a runtime mode or model-change condition requires a restart.Macroscope summarized b33fd1f.