Repository navigation
Conversation
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This is a focused server-side bug fix that reports a final runtime-answer delivery failure using the existing error timeline model while preserving the answer and normal retry behavior. The new internal command is additive, server-only, and covered by integration tests for both attached and detached sessions. You can add or adjust custom eligibility rules. Learn more. |
Dismissing prior approval to re-evaluate 0ebe6f3
0ebe6f3 to
6f5a55b
Compare
|
Warning Review limit reachedOnly developers with an assigned seat can use this organization's usage-based review budget, and seats here are assigned manually. Ask an admin to assign a seat, or change the review continuation mode in Billing. Next included review available in 21 minutes. View limit detailsLimit details: You’ve used all 10 included reviews currently available. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (4)
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configuration
📒 Files selected for processing (4)
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 3 remain after this review. 📝 WalkthroughWalkthroughThe change adds a server-only command to record failed runtime-request answer delivery. After response attempts are exhausted, the worker can dispatch the command, and the orchestrator can append a failed ChangesRuntime request delivery failure
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~20 minutes Change: Bug fix Sequence Diagram(s)sequenceDiagram
participant ProviderAdapter
participant EffectWorker
participant Orchestrator
ProviderAdapter->>EffectWorker: Return response failure
EffectWorker->>Orchestrator: Dispatch delivery-failure command after final attempt
Orchestrator->>Orchestrator: Append failed error turn item when request and node exist
Suggested reviewers: Merge Risk: ⚪ Minimal · up to Failed answer delivery is reported after retries are exhausted, with no identified issue requiring a fix before merge. Security Architecture ReviewSecurity architecture risk: 🔵 Low · up to The change adds a failure notice without granting clients new permissions or automatically resending an answer. Recovery during server or storage failures remains only partially demonstrated. Retained concerns Security review detailsSecurity Blast Radius
Trust Boundaries and Controls
Resilience and Maintainability Implications
Hardening Proposals
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Comment |
6f5a55b to
cd63e55
Compare
Dismissing prior approval to re-evaluate cd63e55
|
Review requested
Logged so this PR shows when a maintainer was asked to review it. |
cd63e55 to
0ce95ad
Compare
Dismissing prior approval to re-evaluate 0ce95ad
Dispatch marks a runtime request resolved before the answer is delivered. When every delivery attempt failed, nothing reported it: the question disappeared while the provider could still be waiting, and the run spun with no question to answer and no error. The last failed delivery attempt now dispatches an internal runtime-request.delivery.fail command, which adds a failed "Answer delivery not confirmed" error item on the request's node. The answer stays recorded, because a failed delivery does not show whether the provider already accepted it, and the run is not marked failed. The user can see why the run is stuck and stop it. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The failure item took its driver from the provider session binding, so a session detached before the last attempt recorded nothing. The item id no longer depends on the session, and the session only adds provenance when it is still bound. The warning for a failed recording no longer logs the raw cause. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Upstream now forbids declaring tests inside for loops (pingdotgg#14921). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
0ce95ad to
9d7fc3e
Compare
|
Review requested
Logged so this PR shows when a maintainer was asked to review it. |
What Changed
When a user answers a question or approval on a V2 thread, dispatch marks the request
resolvedbefore the answer is delivered to the provider. If every delivery attempt failed, nothing reported it. The question disappeared, the provider could still be waiting for an answer it never got, and the run spun with nothing to answer and no error.Now the last failed
runtime-request.respondattempt dispatches a new server-only command,runtime-request.delivery.fail. It adds a failed Answer delivery not confirmed error item to the timeline, on the request's own node: "T3 Code could not confirm that your answer reached the agent. If the run stays stuck, stop it and try again." The answer stays recorded and the run is not marked failed. The item is recorded even when the provider session was detached before the last attempt.The request is not reopened. A failed delivery does not show whether the provider is still waiting. For example, OpenCode can accept a reply and drop its callback before the HTTP response returns, so a reopened question could be one nobody can answer. Reporting that delivery could not be confirmed is true in every case.
This follows the same pattern as
checkpoint.rollback.fail: the last failed attempt tells clients instead of leaving them waiting.Why
Seen on a Claude thread: the agent asked a question with AskUserQuestion, the user answered, and the delivery effect failed all 5 attempts within about 1.5 s with
No pending Claude runtime request <id>. The Claude CLI then blocked on the tool permission callback for 22 minutes while the thread showed "Working" with no question. Only a steer, which aborted the pending tool, got it moving again.The delivery failed because two servers were running against one data directory, so the effect ran on the server whose Claude session did not hold the pending request. That root cause is #14115, with a fix proposed in #8442. This PR does not address it. It makes a failed delivery visible, whatever the cause.
Verification
RuntimeRequestDelivery.integration.test.tsdrives the real orchestrator, outbox and effect worker with a fake provider that asks a live question and refuses every delivery. While retries remain there is no error item. After the fifth failed attempt there is exactly one failedtransport_erroritem on the request's node. It carries the request node's provider thread and turn, the request is stillresolvedwith its answer, and the run is stillrunning. Replaying the failure command adds nothing.vp test runonRuntimeRequestDelivery.integration,RuntimeRequestService,EffectWorker,runtimeLayer,Orchestrator.control-reads,SteeringCompletion.integration,ThreadMessageIntakeandProviderEventIngestor: 8 files, 108 tests passed.7812230572.vp test runonRuntimeRequestDelivery.integration,EffectWorker,RuntimeRequestServiceand the contractsorchestrationV2test: 4 files, 51 tests passed. The bound and detached cases are now oneit.effect.each, for main'sno-test-in-looplint rule; both pass.apps/serverandpackages/contractstypecheck clean; lint and format clean on the changed files.errorturn item type that web and mobile already render.Checklist
Diagnosed, implemented and tested by Claude Opus 5.5 in Claude Code, running inside T3 Code; reviewed by GPT-6 Astra over two rounds (its first round replaced an earlier version that reopened the question).
The 2026-10-05 rebase: Claude Opus 5.5 in T3 Code (Claude Code harness). Independent review: GPT-6.1 Sol (high reasoning) in T3 Code, no actionable findings.
🤖 Generated with Claude Code