agent pane, cmux-tui: a question answered for a chat on another machine reaches that machine's acpmux with its answers

TE
16d ago
+189-18

What broke

In the Mac app, answering a question (an AskUserQuestion-style prompt that has answers) for a chat whose agent runs on another machine (huge-blue) always failed with "approve this on the Mac app: … accepted only from the cmux app". Plain allows to the same chats worked.

Part of the cause is the transport. RemoteAcpmuxWire dropped the answers and sent a bare allow. cmux-tui's agent-session-permission also refused an answers field (deny_unknown_fields). So that machine's acpmux never received the answer at all, whatever proof the pane made.

The fix

This PR only fixes the transport. The decision proof that covers the answers, the pane signing them, and the page's ticket for a question are #23869 (a separate lane's PR). This PR does not touch hub/person.rs or the person-proof protocol. Both PRs are needed for the answer to count on huge-blue.

  • RemoteAcpmuxWire forwards answers (an object; anything else is refused at the wire).
  • AgentSessionRemoteClient / AgentTabRemoteClient / AgentSessionAttachClient carry answers. The attach client re-encodes them compact and puts them in the request.
  • cmux-tui agent-session-permission takes answers (an object of at most 64 KiB) and passes it to acpmux unchanged beside the proof; acpmux still decides. New capability agent-session-permission-answers-v1, advertised with agent-session-attach-v1. If the remote daemon is older and lacks it, the app refuses the answer (agent_session.answers_unsupported) instead of sending a bare allow.
  • Spec (cmux-tui/spec/commands.md) and plans/cmux-next/daemon-capabilities.json updated.
  • Plain allows are byte-for-byte unchanged on every hop.

Tests

  • Rust a_question_answer_carries_its_answers_to_acpmux_unchanged (cmux-tui-core agent_session_attach_tests.rs): the capability is advertised, non-object answers are a bad request, and an object goes to acpmux with the proof. Red on the test commit c242d6c, green at head (fleet results below).
  • Swift RemoteAcpmuxWireAnswersTests: the wire refuses non-object answers and forwards an object with the nonce and proof.

Fleet evidence:

  • Rust GREEN at 1772179 (cmux-tui-rust-check.sh test agent_session, step 1b84acceba92214740cde9ba): 94 passed, including a_question_answer_carries_its_answers_to_acpmux_unchanged. RED run on the test commit c242d6c: pending, reported in a comment.
  • Swift GREEN at 1772179 (package-test-lane.sh suite RemoteAcpmuxWireAnswersTests, RemoteAcpmuxObserverTests, AgentPaneRelayedAllowTests, RemoteChildSessionsTests; step 712fcf758ed41d8b4d4c9ed4): all 4 suites passed. Re-run at the head 7b4c4e1 with DaemonCapabilityExportTests added (step ab63efb8018dee32f007b634): all 5 suites passed.
  • cmux-ci compile-check --app fails the same way at the base 783c2068 (job 0ba18ab3) and at this head: product 'CmuxSentryReporting' required by ... 'CmuxNextCrashReporting' not found in package 'CmuxSentryTelemetry'. That is a base red, not caused by this PR.

No capture: no UI changes. This only changes how a question's answers travel from the pane to another machine's daemon.

Observed / Not run

Observed: the fleet runs above. Not run: a live answer to a huge-blue chat (it needs #23869 too).

Changelog

Fixed: answering an agent's question in a chat on another machine no longer fails with "approve this on the Mac app" (with #23869).

Agent session: cosmic-gray

🤖 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

Fixes answering a question for a chat on another machine, which always failed with "approve this on the Mac app" because answers never reached that machine's acpmux: the wire dropped them and sent a bare allow, and cmux-tui's agent-session-permission refused the field.

  • answers (a JSON object, max 64 KiB) now flows through the wire, the attach client, and agent-session-permission to acpmux unchanged; non-object answers are refused at the wire.
  • The new agent-session-permission-answers-v1 capability gates the field and is advertised with agent-session-attach-v1; against an older daemon the app refuses the answer (agent_session.answers_unsupported) instead of sending a bare allow.
  • Plain allows are byte-for-byte unchanged on every hop.
  • This PR only fixes the transport; the decision proof covering the answers is a separate PR (#23869), and both are needed for the answer to count.