acpmux: _acpmux/queue_get reads a held prompt whole for the owner

Draft
TE
5d ago
+1374-122

HOLD: stacked on #26747; rebase and drop this line once it lands.

Leo (2026-10-28), on T3 Code's "Share with guest": "we want to be having, be able to do this kind of flow for CMux multiplayer ... we can work on the agent chat multiplayer." In that flow each message a guest sends waits for the owner, who approves or declines it. Before approving, the owner's pane needs the whole prompt: its words, its images and files, and the revision the approval names. This PR adds that read. Plan: manaflow-ai/cmuxterm-hq#4766.

Only the last commit is this PR's. Everything below it is #26747.

What it does

  • New method. _acpmux/queue_get {sessionId, promptId} returns {sessionId, promptId, turnId, revision, text, prompt, inlineParts, author, provenance, awaitingOwner} for a prompt that is still in the queue:
    • prompt is the full content blocks as the prompt would run now, including the author's edits: images with their data, resource links, audio and files.
    • revision is the value _acpmux/queue_approve expects.
  • Once the prompt has left the queue (approved and run, declined or removed): queue.not_found (-32002), with data.decided set the same way queue_approve sets it.
  • Caller rules, the same as queue_approve:
    • Owner only: a caller with an author gets queue.owner_only.
    • A Web caller has to pass the Web-control check.
    • The Full-access hold applies.
  • Peer forwarding: forwarded only to a peer that lists the new feature queueGet, and sent on the link that listed it (Peer::lists_on). Otherwise it fails with queue.approval_unsupported and nothing is forwarded.
  • New capability: queue-get-v1.
  • Updated: docs/acpmux-schema.json, the README method list, spec/acpmux-protocol.json, and the TS types regenerated with bun scripts/acpmux-protocol-codegen.ts.
  • What a peer gets: a peer's caller receives the prompt unmasked. That matches the queued and queue_updated records peers already receive (peer_text.rs masks only summaries).

Risk

risk:low. A new read-only method that sits behind the same checks as queue_approve. Nothing that exists changes behavior.

Tests

  • hub_integration prompt_approval::the_owner_reads_a_held_prompt_whole_at_its_revision. After the guest edits a held prompt that had an image and a file link, queue_get returns the new text, the kept blocks, revision 1, its author and provenance. A caller with an author gets queue.owner_only. After a decline, the prompt is queue.not_found with decided: "declined".
  • peer_queue_approval:
    • A peer without queueApproval refuses get, approve and decline.
    • A peer that lists queueApproval but not queueGet refuses get, and nothing is forwarded.
    • A peer that lists queueGet is forwarded the get.
  • The cmux-ci receipt is in a comment.

Changelog

none

Agent session: agent session

šŸ¤– 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

Adds owner approval for queued guest prompts in chatbot mode: a person's prompt waits for the owner, who approves or declines it, and can read the prompt whole before answering. Previously the owner only saw the queued preview; now they get full content blocks (including images and files), the current revision, and author/provenance info. Also blocks the prompt from reaching an older daemon that would run it unapproved.

Approval flow

  • _acpmux/queue_approve runs the prompt in its queue place at the revision the owner saw; a stale revision is refused queue.stale. _acpmux/queue_decline drops it and its session/prompt answers queue.declined.
  • Owner-only (queue.owner_only), under the Web-control check and Full-access hold; the guest can edit (new revision, still waiting) or remove it.
  • Approvals and declines bind to their queued prompt under the queue lock, so a restart or a concurrent removal can't apply them to the wrong prompt.

Access and forwarding

  • _acpmux/queue_get returns the full blocks, revision, author, and provenance; once the prompt leaves the queue it returns queue.not_found with the same decided value as queue_approve.
  • Held prompts and owner answers are forwarded only to a peer listing queueApproval, on the link that listed it; queue_get requires queueGet. Otherwise queue.approval_unsupported and nothing is forwarded.
  • Moves refuse transfer.held_prompts while any prompt waits for the owner, since an older build would run it unapproved.
  • Adds capabilities queue-approval-v1 and queue-get-v1.