test(server): assert the read-only on-request write by its permission - #13562
Conversation
ApprovabilityVerdict: Approved at Macroscope's review found this PR approvable — This PR strengthens deterministic replay tests so the existing read-only/on-request policy is asserted by permission outcome regardless of whether a provider chooses a command or file-edit tool. All changes are limited to test assertions and replay transcripts, with no production runtime, product-default, schema, or deployment impact. Notes:
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. |
Dismissing prior approval to re-evaluate a38b183
The shared tool_call_read_only_on_request assertion pinned a shell command and a `command` request, so it only held when the agent picked the shell. The prompt allows a shell command or a file edit; live Grok uses its write tool, which asks for a file change. One assertion now covers Codex, Claude, Grok and the ACP registry agent: exactly one request, accepted and resolved, of kind command or file-change; one approval card for it; a completed command_execution or file_change for the probe file whose content, when projected, is the requested text. The Grok variant is re-recorded live, and the registry's synthetic command now writes the requested text. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
a38b183 to
cddebc6
Compare
Dismissing prior approval to re-evaluate cddebc6
…#13562) Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The shared
tool_call_read_only_on_requestassertion pinned a shellcommand_executionand acommandrequest, so it only held when the agent chose the shell. The prompt allows "a local shell command or file edit", and live Grok 1.0.41 uses itswritetool, which asks for a file change. That is why #13537 left the Grok variant synthetic.Change
The fixture tests the permission, not the tool. One assertion (
tool_call_read_only_on_request/output.ts) now covers Codex, Claude, Grok and the ACP registry agent, replacing the Codex-shaped and Claude-specific copies:accept, of kindcommandorfile-change(whichever the provider's tool needs)command_execution(forcommand) orfile_change(forfile-change) targeting.codex-probe-write-action.txtnewStr/diffStr), it contains the requested textThe Grok variant is re-recorded live:
write→session/request_permission(kind: "edit", location = the probe file) → allow-once →fs/write_text_filewith the exact text. The registry transcript is synthetic; its command now writes the requested text, so the content check covers it too.Findings, not fixed here
fs/read_text_fileon the same path twice ("requires approval…"). The cause is inAcpClientPolicy. With any approval policy other thannever,acpOperationDispositionreturnsaskfor every operation, reads included. An acceptedfile-changerecords only a write grant for its locations, so the read falls through to deny. Grok continued and wrote the file anyway. There is a broader consequence: Grok never asks permission for itsread_filetool and routes reads through clientfs/read_text_file, so under on-request or approval-required policies T3 denies every Grok read. The narrow fix is to let a file-change grant cover reads of the same locations. The broader question is whether a read-only or workspace sandbox should stillaskfor reads when approval is on-request. That's a policy call, so I left it for a maintainer.content: [{ type: "diff", path, oldText, newText }](the ACP v1 shape). The adapter'sfile_changeprojection reads only the v2patch.text, so the Grok file change reaches the timeline with nodiffStr/newStr. The assertion therefore checks content only where the projection carries it.Verification
vp test run src/orchestration-v2/testkit/OrchestratorReplayFixtures.integration.test.ts: 85 passed (all fourtool_call_read_only_on_requestvariants).printf fixture > …): the replay fails on the content check.vp exec tsc --noEmit -p .in apps/server: 0error TS/warning TS.vp run knip:check: clean.vp lint/vp fmton touched files: clean.Stacked on #13537.
Model: Claude Opus 5.5 (Claude Code)
🤖 Generated with Claude Code