Repository navigation
fix(acp): ID-only command approvals keep the tracked command and grant the terminal - #26647
Conversation
…mand An ACP agent in Supervised mode reports its execute tool call, then asks session/request_permission with only the toolCallId. The approval prompt falls back to "Session <id>" and approving it records no execute grant, so the agent's terminal/create is refused. These tests reproduce #26620. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ACP allows session/request_permission to name its tool call by ID only. Devin does this after announcing the execute call, so the prompt showed "Session <id>", the kind was unknown, and approving recorded no command grant, which made the agent's terminal/create fail. The permission handler now fills the omitted title, kind and rawInput from the tool call the active turn tracks for that toolCallId in the same session, before the prompt, disposition, flavor hooks and grant read the request. Fields the request sends still win, and an untracked toolCallId is left unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the tracked call Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — ID-only ACP approvals now show the tracked command and enable terminal execution through the existing approval flow. Session matching, execute-only inheritance and unchanged approval scopes keep the correction narrowly bounded. You can add or adjust custom eligibility rules. Learn more. |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Permission field enrichment packages/provider-acp/src/server/runtimeModel.ts, packages/provider-acp/src/server/runtimeModel.test.ts |
withTrackedPermissionToolCall fills undefined title and raw input from tracked state. It sets an undefined kind to execute only when the tracked call is an execute call. Tests check that explicit values, including null, remain unchanged. |
Active-session permission wiring packages/provider-acp/src/server/adapter.ts |
The permission handler enriches requests when their session matches the active session and tracked tool-call state is available. Other requests use the native parameters unchanged. |
Approval outcome test scenario apps/server/scripts/acp-mock-agent.ts, apps/server/src/orchestration-v2/Adapters/AcpAdapterV2.test.ts |
The mock agent can emit a pending git status tool call and wait. Adapter tests check the prompt and terminal-creation outcome for ID-only approvals with execute and other kinds. |
Priority:
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Bug fix · Severity of issue fixed: Medium
Possibly related issues
pingdotgg/t3code#26620— Reports the same ID-only ACP permission request losing tracked command context and blocking terminal execution.
Possibly related PRs
- pingdotgg/t3code#26624 — Enriches ID-only permission requests from the active turn’s tracked tool call; this PR also preserves explicit nulls and limits execute-kind inference to tracked execute calls.
- pingdotgg/t3code#20145 — Addresses command-approval presentation; this PR supplies tracked ACP title and raw input for ID-only approvals.
Suggested reviewers: t3dotgg, stienswout
Merge Risk: 
Minimal · up to 553a9
-
The ID-only approval path appears to preserve the intended terminal permission distinction. No merge-blocking issue was identified.
Pre-merge checks: 
4
-
Full details: Description check
-
Explanation
The description clearly covers the problem, change, scope, approval reference, focused verification, observed results, limitations, screenshots, and agent attribution. It matches the required template and explains the cross-component fix.
Full details: Linked Issues check
-
Explanation
Issue
#26620requires ID-only permission requests to use the tracked command, authorize a tracked execute request, and deny execution for unknown or non-execute tools. The adapter enriches matching requests before policy and grant processing. The helper preserves request fields, including explicit null values, and copies kind only for tracked execute calls. The added tests cover the execute, other-kind, unknown-kind, explicit-kind, and explicit-null cases.
Full details: Out of Scope Changes check
-
Explanation
The changes stay within issue
#26620. The adapter and runtime-model changes implement request enrichment. The ACP mock-agent option and added tests provide coverage for the reported protocol cases. No unrelated production behavior is identified.
-
Finishing Touches
-
📝 Generate docstrings
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: 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. |
Problem
An ACP agent can send
session/request_permissionwith only atoolCallIdafter it has already announced that tool call in the turn. Devin from the ACP Registry does this. T3 read only the request payload, so in Supervised mode the approval prompt showedSession <session id>instead of the command. The request's kind was alsounknown, so accepting it recorded no command grant. Devin's nextterminal/createwas then refused, and the command never ran ("Failed to create terminal").Reproduced on main (9e09926) in the web dev server, with a scripted ACP v1 agent registered as
devin(Executable override) in Supervised mode. The agent announces an executetool_call, sends an ID-only permission request, then callsterminal/createonce the request is approved.Change
When a permission request leaves out the title, raw input or kind, the ACP adapter now copies them from the tool call that the active turn of the same session is already tracking (
withTrackedPermissionToolCall). This happens once, before anything else reads the request, so the prompt, the policy disposition and the grant all see the same request. Fields the request does send are kept, including fields it explicitly clears withnull. A tracked kind is copied only when it isexecute: other and custom kinds map to command approvals, so copying them would let an approved non-execute tool open terminals. An untracked tool call is left unchanged and still gets no execute grant.Scope and approval
Fixes #26620
Verification
AcpAdapterV2.test.ts: the new table test fails on main and passes here.grants an ID-only execute approval its tracked command: on main the prompt isSession mock-session-1andterminalCreatedis false.does not grant execution to an ID-only approval of another tool: a trackedotherkind is still refused.does not turn an unknown permission approval into an execute grantpasses unchanged.runtimeModel.test.ts:keeps an explicit permission request kind over the tracked tool call's kindandkeeps explicitly cleared permission request fields over the tracked tool call(akind: nullrequest staysunknown).AcpAdapterV2,AcpRegistryAdapterV2,runtimeModelandclientPolicytests pass (145 tests).vp run check:changedpasses.T3CODE_DEV_SEED=0), Supervised mode, scripted agent asdevin, 1280×800, light theme.Session id-only-session-…python3 -c …commandterminal/createrefused with "requires approval for terminal/create"; noapproval-probe.txtapproval-probe.txtcontainsACP_APPROVAL_OKCaptures, 1280×800, light theme:
The after run used 51c60eb; the later head only changes how explicit
nullfields are handled, which this ID-only flow doesn't send. No render code changed; only the prompt text and the grant change.Protocol transcript, before (agent ↔ T3)
Protocol transcript, after (agent ↔ T3)
Scratch ACP agent used for the runtime reproduction (not committed)
Not checked: a real Devin binary (needs a Devin account) and the desktop and mobile clients. The change is server-side, and they render the same approval data.
Implemented with Claude Opus 5.5 (Claude Code) and reviewed with GPT-6.1-Sol (Codex), orchestrated in T3 Code.