Repository navigation
Conversation
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — This production change alters existing orchestration timeout, retry, provider fallback, session cleanup, credential handling, and thread-lane behavior across multiple components, with timed-out work continuing in detached fibers. An unresolved high-severity concern also questions whether a non-interruptible ACP handler can still prevent claim settlement, so the lifecycle behavior merits human review. No code changes detected at Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: unavailable · PR result: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
… restart V2 runs one non-title outbox effect per thread at a time and never reclaims a running row, so a provider call that never answered (for example a session open that hangs) left the run "starting" and blocked that thread's interrupt, detach and cleanup until the server restarted. Each provider call made while a run starts (session open, thread load and resume, and handing over the turn) is now bounded at 5 minutes; a hang fails the run with a provider_error item through the existing start-failure path. Every outbox effect also gets a 15-minute backstop through the normal retry and fail path, so a hung non-start effect can't hold the lane forever. An interrupted session open now closes its scope so a timed-out open doesn't leave the provider process behind. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
OpenCode's compaction waits for session.summarize to finish, so the 5-minute start bound could fail a legitimate compaction. Compaction keeps only the 15-minute effect backstop. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
An interrupted or failed open closed its session scope inside an uninterruptible finalizer, so a provider that never yields its message stream could hang the start timeout and keep the thread's lane blocked. Reuse release's bounded scope close for abandoned opens. Model the effect execution timeout as its own error with a timeoutMs field instead of a formatted string in cause. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… interrupted A timeout waits for the effect it interrupts to exit, so a handler parked in an uninterruptible wait, such as an ACP response waiting for its native acknowledgement, kept the thread's lane blocked past the 15 minute backstop. Run the handler in its own fiber so the timeout can settle the claim and let the interruption finish in the background. A cancellation still waits for the handler to stop. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
05f2de0 to
887ad60
Compare
|
Note This comment is posted by Julius' dot The hang and TestClock regressions are well described, but this introduces a five-minute startup deadline, failure on the first timeout, and a fifteen-minute backstop for every outbox effect. The maintainer direction in #13392 and #14183 covers settling terminal startup failures; it does not establish those broader timeout/retry choices. This is a substantial lifecycle-policy change outside the small obvious-bug exception in prior approval. Please get maintainer agreement on the deadlines, retry behavior, and all-effect scope before resubmitting; closing this submission while preserving the reproduced hung-provider problem. |
If a provider call never answers, for example a session open that hangs, the v2 run stays "starting" forever. Worse, V2 runs only one outbox effect per thread at a time and never reclaims a running row, so that thread's interrupt, detach and cleanup effects all queue behind the hung one until the server restarts. The 30-second lease on each row is written but never checked.
I reproduced it in a real client with a fake provider that never answers ACP
session/new: the run stayedstartingand itsprovider-turn.starteffect stayedrunningindefinitely.What changes:
provider_erroritem through the existing start-failure path, the same one fix(server): a turn that fails to start after its session opens now fails the run #14183 uses, so the user sees a failed run instead of a spinner. The slowest legitimate provider calls in the codebase are capped at 180 seconds.FoundationPersistence.test.ts.A turn start doesn't cover the whole turn:
RunExecutionService.startRootRunforks event ingestion and returns once the provider accepts the turn. I checked every adapter (Codex, Claude, the ACP adapters, Cursor, OpenCode, Pi), and each returns on acceptance, so these bounds can't cut off a long turn. The one exception is OpenCode's/compact, which waits forsession.summarizeto finish, so compaction is left out of the start bound and keeps only the 15-minute backstop.Tests (TestClock, no sleeps) cover a hung open, thread load and
startTurneach failing the run visibly, and a hung start freeing the lane so a laterterminal.cleanupruns through the real outbox and worker. They also cover a hung non-start effect timing out, including one that can't be interrupted, a cancellation still stopping the running handler, unchanged retries up tomaxAttempts, a start under the bound being unaffected, an interrupted open closing its scope, and an interrupted open whose scope close hangs still finishing. All seven new timeout tests fail with the bounds disabled.Decision for reviewers: a start timeout fails the run on the first attempt instead of retrying, which trades retries for a visible failure after 5 minutes.
Works with #14201, which lets users press Stop on a run that's still starting.
Model: Claude Sonnet 5, Claude Fable 5.1 and Claude Opus 5.5 (Claude Code)
🤖 Generated with Claude Code