Skip to content

reconcile provider session state and settle stuck turns#2666

Draft
justsomelegs wants to merge 13 commits into
pingdotgg:mainfrom
justsomelegs:t3code/4b95a799
Draft

reconcile provider session state and settle stuck turns#2666
justsomelegs wants to merge 13 commits into
pingdotgg:mainfrom
justsomelegs:t3code/4b95a799

Conversation

@justsomelegs
Copy link
Copy Markdown
Contributor

@justsomelegs justsomelegs commented May 12, 2026

What Changed

Fixes several provider session / turn lifecycle cases where T3 Code could leave a thread in the wrong state after provider runtime events, interrupts, stop failures, or server restart.

Main changes:

  • Treat active turn.completed events as lifecycle-ending events:

    • successful turns move the session back to ready
    • failed turns move the session to error
    • activeTurnId is cleared
  • Treat active turn.aborted events as lifecycle-ending events:

    • interrupted/aborted turns move the session back to ready
    • activeTurnId is cleared
  • Ignore completion/abort events for non-active turns so auxiliary provider work, like OpenCode title generation, does not incorrectly stop the main running turn.

  • Reconcile projected running sessions on server startup:

    • if the provider still has a live session, mirror the live provider state
    • if the provider no longer has the session, mark the projected session stopped
    • if live session listing fails, leave projected state alone instead of guessing
  • Make thread.session.stop non-destructive on provider stop failure:

    • generic stop failures keep the current session and record lastError
    • typed “session already gone” errors are treated as a successful idempotent stop
  • Preserve failed turn state in server and web projections:

    • sessions entering error settle the latest running turn as error
    • stopped/interrupted/ready inactive sessions settle the latest running turn as interrupted
  • Fix OpenCode adapter interrupt handling:

    • interrupt clears active adapter state and returns the session to ready
    • interrupted sessions can then be stopped cleanly
    • prompt-start failures no longer emit a misleading turn.aborted event

Why

A few different provider lifecycle paths were being treated too loosely.

The main symptom was that a thread could stay stuck as “working” even after the provider had already finished, aborted, or lost the active session. This was especially visible with OpenCode, but the underlying fixes are in shared provider orchestration and projection code, so they apply more broadly than just OpenCode.

This approach keeps the existing event model, but makes the lifecycle rules stricter:

  • only the active turn can settle the active session
  • provider runtime state is reconciled instead of blindly overwritten
  • stop failures do not pretend the session stopped
  • failed turns remain failed instead of being flattened into interrupted turns

Fixes #2644
Fixes #2633
Fixes #2573

UI Changes

No UI changes.

Testing

  • bun run test src/orchestration/Layers/ProviderRuntimeIngestion.test.ts src/orchestration/Layers/ProjectionPipeline.test.ts src/orchestration/Layers/ProviderCommandReactor.test.ts src/provider/Layers/OpenCodeAdapter.test.ts
  • bun run test src/store.test.ts
  • bun fmt
  • bun lint
  • bun typecheck

bun lint passes with existing unrelated warnings.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Handle stale provider runtime state by settling running turns on session stop or error

  • On reactor startup, reconcileStaleRunningSessions compares projected running sessions against live provider sessions; sessions with no live counterpart are stopped and given a descriptive lastError, while live ready sessions are mirrored and their latest turn settled.
  • processSessionStopRequested now treats 'session not found' as a benign stop; other stop failures record a provider.session.stop.failed activity and preserve running state with lastError.
  • turn.aborted events in ProviderRuntimeIngestion now mark the thread session as ready and clear the active turn, matching the behavior of turn.completed.
  • interruptTurn in OpenCodeAdapter immediately clears activeTurnId and session state before emitting turn.aborted; prompt-start failures no longer emit turn.aborted.
  • UI and projection layers settle a running latestTurn to interrupted or error with completedAt when a session transitions to a non-running status or a stop is requested optimistically.

Macroscope summarized d2742fc.

@reactreview
Copy link
Copy Markdown

reactreview Bot commented May 12, 2026

React health score gauge

React Review found 0 ❌ errors and 1 ⚠️ warning. This PR leaves the React health score unchanged.

Copy prompt for agent
Check if these React Review issues are valid. If so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.

Run this before and after your changes to verify the result:
npx react-doctor@latest --verbose --diff

Do not modify the react-doctor configuration unless explicitly asked.
Fix the underlying code issues instead of changing or suppressing the rules.

React Review found 0 errors and 1 warning. This PR leaves the React health score unchanged.

<file name="apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts">

<violation number="1" location="apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts:369">
Severity: Warning

Sequential `await` without a data dependency on the previous result — wrap the independent calls in `Promise.all([...])` so they race instead of waterfalling

Wrap independent awaits in `Promise.all([...])` so they race instead of waterfalling — second call doesn't depend on the first

Rule: `server-sequential-independent-await`
</violation>

</file>

Reviewed by react-review for commit d2742fc. Configure here.

@github-actions github-actions Bot added the vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. label May 12, 2026
Comment thread apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 086d6983-1ee6-4bdd-b5b0-5057d66fe7b7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@justsomelegs justsomelegs changed the title Handle stale provider runtime state reconcile provider session state and settle stuck turns May 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

1 participant