Pane policy: policy.json matches the macOS host's params, with a Swift parity test (cx-ctddg)

Merged
TE
22d ago
+309-16

cx-ctddg. The Rust pane policy (cmux-agent-pane-policy/policy.json) had drifted from the macOS host's tables (AcpmuxPaneMethods.requests and knownParams). Those Swift tables are what enforce the pane's frames today. The Swift side of the parity tests was deleted, so nothing caught the drift. #20644 broke local chats when the two sides disagreed (cx-ibngi).

Change

  • New test, tests/swift.rs: reads both Swift tables and asserts that policy.json's requests and known_params equal them.
  • policy.json: gains the four params Swift already allows (scoping below).
  • src/params.rs: a _acpmux/permission_respond _meta must hold the pick's gesture ticket and nothing else. This is the same rule as Swift's breaksParamsRule. Without it, adding _meta to the list would have let an acpmux key through.
  • tests/cases/params.json:
    • the "every known param" cases now include the new params;
    • two new cases must break: _meta with more than the ticket, and _meta without it.
  • tests/typescript.rs: base has since fixed the same allowlist scan of typedRequest calls (6bf943f, cx-js8uc). After the base merge this file is identical to base.

Review fixes

  • Gesture pick, src/check.rs: GesturePick::new gains Swift's AgentPaneGesturePick branch for _acpmux/permission_respond. Its pick is {sessionId, permissionId, optionId}, and there is no pick when it carries answers. Before, Rust dropped sessionId from the pick, and this PR's _meta param made that path reachable.
  • src/lib.rs: says hosts strip a session/new's _meta.acpmux.noProject in their folder step, as AcpmuxPathPolicy does.
  • Stale references: the deleted AgentPanePolicyParityTests is no longer cited in policy.json's description, lib.rs, or the Swift checkOne doc comment. That comment is the only Swift change.
  • More params cases: _meta: {} on permission_respond breaks; a non-string ticket passes the params rule, as in Swift.

Scoping of each added param

Swift already allows each of these with the same reason, and no new method is added.

MethodParamWhat it doesScope
session/new_meta.acpmux.noProjectThe pane's "Do not work in a project". The host's path policy reads and strips it.Before any session exists, so no session scope. Grants no folder.
session/prompt_meta.acpmux.contextA chat's workspace context on its first prompt (cx-ihyx2). acpmux sends it to the agent and keeps it out of the transcript text.The prompt's sessionId must be the pane's (session_scoped).
_acpmux/modelsrefreshThe picker's Refresh models: acpmux runs again the model probes it already runs in the background.Grants nothing, so no gesture rule.
_acpmux/permission_respond_metaOnly the gesture ticket of the person's pick (cx-0q7o).Any other key, or no ticket, breaks the params rule. The ticket is checked against the pick.

Verification

All runs were on the Linux builder, with the same focused command:

cargo test -q -p cmux-agent-pane-policy --test swift
CommitResult
Red, 3eda6d1The requests check passes. the_known_params_are_the_macos_hosts fails on exactly the four params above.
Green, the fix2 passed.

Gesture pick, with the focused command cargo test -q -p cmux-agent-pane-policy --test parity full_check_order:

CommitResult
Red, c12cf36Fails on "a ticketed permission answer binds its pick…". The got pick is {optionId, permissionId}; the expected pick also names sessionId: s1.
Green, 9035b2b1 passed.

On the fix:

  • the crate's full tests pass: parity 16, swift 2, typescript 4;
  • rustfmt is clean;
  • the crash ratchet is ok.

The only Swift change is one doc comment. sbx build on the merged head (base dbb1123) completes. On the merged head, the crate passes 16 + 2 + 4 and rustfmt is clean. No host runs the Rust policy's frame check at runtime today, so nothing changes for users.

Defaults snapshot

This PR does not change schemas/defaults/cmux-next.json. The autofix bot added a line recording Lawrence's existing key.home.switchView default, and I dropped it. A red defaults-snapshot check here is the base red for that missing record, not a new default from this PR.

Changelog

none

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Restores parity between the Rust pane policy (policy.json) and the macOS host's Swift tables, which enforce the pane's frames today. The Swift parity tests were deleted, so nothing caught the drift — #20644 broke local chats when the two sides disagreed (cx-ibngi).

  • Adds tests/swift.rs, which asserts policy.json's requests and known params equal the Swift tables.
  • Adds the four params Swift already allowed: session/new noProject, session/prompt context, _acpmux/models refresh, and _acpmux/permission_respond _meta.
  • Enforces that _acpmux/permission_respond _meta holds the gesture ticket and nothing else, matching Swift's breaksParamsRule.
  • Makes a permission answer's gesture pick name its session, permission, and option — and pick nothing when it carries answers — matching Swift's AgentPaneGesturePick.
  • The allowlist test now also reads the method each typedRequest call in direct.ts names, fixing a pre-existing red test after #20576 moved _acpmux/permission_respond to that helper.
  • Documents in lib.rs that hosts strip a session/new's _meta.acpmux.noProject in their folder step, and drops stale references to the deleted AgentPanePolicyParityTests (including the Swift checkOne comment).

No Swift behavior changes, and no host runs the Rust policy's frame check at runtime, so nothing changes for users.