Repository navigation
Conversation
Byntham
marked this pull request as ready for review
October 7, 2026 06:52
Byntham
force-pushed
the
t3code/end-tool-calls-on-lost-stream
branch
from
October 7, 2026 18:19
7867445 to
f22d187
Compare
…ait forever When a run's provider event stream is lost mid tool call, for example when t3_worktree_handoff detaches the session running it, the run was marked failed but its open tool call stayed running. Later runs inherited it as background work, so the thread showed "Waiting on background task" after every later run until a server restart. The lost-stream fallback now cancels the run's open command and dynamic tool items with the run, as restart recovery does for a dead process. Provider-reported terminals are unchanged: their process is alive, so open items still pass to the next run. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…calls A failure to store an event also ends a run's ingestion, but the provider can still be running the tool. Cancelling it then would hide live work from Stop and the next run. The cleanup now applies only when the provider's own stream fails, as when its session is released. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…r updates The cancellation written for a lost stream's open tool calls came from the adapter's raw item, so it skipped the image stripping the ingestor applies to every stored update. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Byntham
force-pushed
the
t3code/end-tool-calls-on-lost-stream
branch
from
October 9, 2026 16:21
3cd7adf to
2f44ec9
Compare
Contributor
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a scoped server bug fix that cancels only run-owned tool and command items when their provider stream is actually lost, while preserving existing background-work behavior for live streams. The production change is localized and supported by targeted unit and integration coverage, with no schema, default, deployment, or static-analysis configuration impact. You can add or adjust custom eligibility rules. Learn more. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When a run's provider event stream is lost mid tool call, the run is marked failed but its open tool call stays
running.t3_worktree_handoffdoes this every time, because it detaches the session that is running it. Because the run failed, later runs on the same provider thread inherit the item as background work, so the thread shows "Waiting on background task …" after every later run until a server restart. Because the item counts as pending work, the sidebar keeps the thread at Waiting and auto-settle skips it. Fixes #15993.Change
RunExecutionServicealready tracks the ids of open background items to decide when to stop ingesting. It now keeps each item's latest update as well. When the provider's own stream fails, as when its session is released, the lost-stream fallback cancels the run's own opencommand_executionanddynamic_toolitems in the same write that records the run as failed. This matches what restart recovery does when a provider process is gone. The cancellation is built from the adapter's item, so it gets the same unserved image stripping the ingestor applies to stored updates. A failure to store an event goes through the same fallback, but there the provider may still be running the tool, so its items are left as before. Subagent rows already end through the existing cascade.Terminals reported by the provider are unchanged. Their process is still alive, so open items still pass to the next run through
selectInheritedBackgroundTurnItems.The cleanup is in run finalization rather than in a change to session shutdown order, because a crashed provider can't emit its own cancellations.
The fake adapter that was inline in
BackgroundWorkStop.integration.test.tsmoved into ascriptedAdapterhelper, so the new integration test reuses it instead of copying it.Scope and approval
interruptedterminal, which bypasses this fallback. If both land, that detached terminal should pass the sameorphanedTurnItems.Verification
BackgroundWorkStop.integration.test.ts› "cancels a tool call cut off when a workspace change detaches its session". It uses the real orchestrator, session manager, and run execution with a scripted adapter that has Claude's single-thread session capabilities. A dynamic tool is running whenProviderSessionManager.detachreleases the session, as a workspace change does.running(expected 'running' to equal 'cancelled'). This matches the persisted state of the affected thread: the handoff call from a failed run was stillrunningafter 63 later runs.cancelled, andderivePendingBackgroundWorkreturns nothing.RunExecutionService.test.ts:interruptedterminal still leaves an open command for the next run.vp test runonRunExecutionService,BackgroundWorkStop.integration,ProviderSessionManager,ProviderTurnStartService,ProviderFailure,SelectionRestart.integration,SteeringCompletion.integration, andtestkit/OrchestratorReplayFixtures.integration: 290 passed.tsc --noEmitforapps/server: no errors.vp lintandvp fmt --checkon the changed files: clean.Fixed by Claude Opus 5.5 in Claude Code, running inside T3 Code.
🤖 Generated with Claude Code