Repository navigation
acpmux: a guest's prompt waits for the owner - #26747
teamleaderleo wants to merge 50 commits into
Conversation
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Passes: CI passes on CI passes on Written by web and size checks: green Gallery before/after for
States
Pick other states with a |
|
Found 3 test failures on Blacksmith runners: Failures
|
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Bead |
…ed in order Review of #26747: a restart applied an approval to a later prompt reusing the id, and an approval logged after the author's removal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
…gent Review of #26747: a Send now racing the guest's prompt could set its steer flag, and nothing checked the hold where a steer is let out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
…t stays the answer Review of #26747. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
Review of #26747: an older peer ignores author.approval and would run the prompt unapproved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
857e92b to
5c8b8e6
Compare
…ed in order Review of #26747: a restart applied an approval to a later prompt reusing the id, and an approval logged after the author's removal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
…gent Review of #26747: a Send now racing the guest's prompt could set its steer flag, and nothing checked the hold where a steer is let out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
…t stays the answer Review of #26747. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
Review of #26747: an older peer ignores author.approval and would run the prompt unapproved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
Review of #26747: a move to an older build would restore the held prompt as an ordinary queued one and run it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
# Conflicts: # cmux-tui/crates/acpmux/src/peer.rs # cmux-tui/crates/acpmux/src/server/requests.rs
|
Review (codex gpt-6.1-sol high fast, next-review; Sol because Astra through SR2 hangs fleet-wide): SHIP at ce95f4a No blocking findings. Reviewed against the merge base, after a base merge for #28016/#28141/#28172 (peer feature flags, person Stop). Local on this head: clippy -D warnings clean; prompt_approval 14/14, peer_integration 51/51, peer_queue_approval 1/1, lib peer/queue_approve/person_stop 233/233. |
# Conflicts: # cmux-tui/crates/acpmux/src/hub/views.rs # cmux-tui/crates/acpmux/src/protocol/session.rs
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
# Conflicts: # cmux-tui/crates/acpmux/docs/acpmux-schema.json # cmux-tui/crates/acpmux/src/hub/prompt_ledger.rs
…ives a restart Red first (review of #26747 at f856ef2, P1): enqueue logged `queued` after releasing the queue lock, so an owner's decline in that window logged queue_declined and queue_removed first. A restart then restored the declined prompt ("a restart brought the declined prompt back"), and a resend lost the decline. A test-only seam runs right before the `queued` record is logged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-649f36111561cf88ba8e
enqueue released the queue lock before logging `queued`, so an owner's decline (or an edit) in that window was logged first, and a restart read the decline as naming nothing and restored the prompt (review of #26747). `queued`, `queue_order` and `queue_paused`, and the superseded prompts' removals before them, are now logged under the queue lock, as approvals, declines and edits already were. The record and its kept images are made before the lock is taken, so a large image never holds up the queue. Green: a_decline_racing_the_queued_record_stays_declined_after_a_restart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-649f36111561cf88ba8e
|
Review (independent Codex gpt-6.1-sol, high, via the review router; full diff from merge base 8f5dfe0 to this head): BLOCK at f856ef2. [P2] |
…Web's rules Red first (review of #26747 at f856ef2, P1): an owner's approval from the Web left the guest's prompt its Local control, so after the policy stopped asking it was dispatched and ran, where a Web prompt is refused remote.policy_not_asking. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-649f36111561cf88ba8e
_acpmux/queue_approve passed no control, trust gate or device, so a guest's prompt the owner approved from the Web kept the guest's Local control: a policy or mode change after the approval let it run where a Web prompt is refused, and its turn skipped the Web's floor (review of #26747, P1). The approval now folds the approver's rules into the queued run under the queue lock (PromptRun::restricted, the rule an edit already used): the stricter control, the trust gate when either asks it, and a Full-access machine only when both name it. check_dispatch reads them at dispatch. queue_approved records the control and trust gate, and a restart restores them (a record without them restores as the Web's, the strictest). Green: a_held_prompt_approved_from_the_web_is_dropped_when_the_policy_stops_asking (web_mode_current), an_approval_keeps_the_approvers_rules_across_a_restart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-649f36111561cf88ba8e
# Conflicts: # cmux-tui/crates/acpmux/src/peer.rs # cmux-tui/crates/acpmux/src/server/peer_forward.rs # cmux-tui/crates/acpmux/src/server/requests.rs
# Conflicts: # cmux-tui/crates/acpmux/src/hub/queue.rs
# Conflicts: # cmux-tui/crates/acpmux/src/hub/transfer_out.rs
|
Review (codex gpt-6-astra high, router-review): BLOCK at 726c942 BLOCK
|
|
Lander note at 726c942: under the 2026-10-30 rule, this PR's BLOCK findings are P2 or edge-case P1 and can land with follow-up issues. It conflicts with feat-cmux-next and update-branch cannot merge it. Next step for the owner: resolve the conflicts. The new head then needs a fresh independent review and its own reds checked against base. |
Resolves the log-load kind index (#27xxx store/kind_index.rs): the owner's queue_approved and queue_declined are indexed, as QUEUE_KINDS reads them (the_log_loads_kinds_are_indexed; a restored load read the whole log without them). logged_prompt keeps base's started/orphan reading with this branch's decline answer and new-incarnation arm. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-649f36111561cf88ba8e
… no notice back Red first (Astra review of #26747 at 726c942): waking_children subtracted only held prompts, so a hibernated child with a guest's prompt waiting for the owner took a parent width slot ("an owner-held prompt woke the child"); prompt_waits passed only held prompts, so that prompt kept other agents' notices out of the running turn ("an owner-held prompt held a notice"). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-649f36111561cf88ba8e
… notice back Every queue test that set aside the prompts a failed turn holds now sets aside the ones that wait for the owner too (QueuedPrompt::aside): the inbox's prompt_waits and first_work_waits, a sub-session's waking_children (its parent's width slots), and the restart's auto-resume claim, as the retry's busy test already did (review of #26747 at 726c942, Astra). Green: a_child_with_only_an_owner_held_prompt_takes_no_width_slot, an_owner_held_prompt_does_not_hold_back_a_notice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-649f36111561cf88ba8e
# Conflicts: # cmux-tui/crates/acpmux/src/peer.rs # cmux-tui/crates/acpmux/src/peer_features.rs # cmux-tui/crates/acpmux/src/server/requests.rs
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (codex gpt-6.1-sol high fast, review-router; started by the backlog lander): BLOCK at 4dd329b BLOCK
|
|
Thanks for the update-branch and the review. This PR is superseded by its carry, #28859 (same commits with authorship kept, plus a base merge and the ratchet fix), so please don't land #26747 itself. Its branch can't be pushed from the carrying lane: the claim names an earlier owner.
|
|
Superseded by its carry #28859 (this PR's own HOLD says not to land it). Review and landing happen there. Closing this copy. |
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
HOLD: superseded by #28859 (carries all of this plus the ratchet fixes and both Astra P1 fixes). Do not land this PR.
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 the owner shares a chat by link, "each message they send waits for you", and the owner approves each one: Approve sends it to the agent, Decline drops it.
This is the first PR of the plan in manaflow-ai/cmuxterm-hq#4766 (section 4, "First PR to build"). It changes acpmux only: no UI and no proxy change.
What it does
_meta.acpmux.authoralso acceptsguest:<opaque>ids, for a link guest who is on no tailnet and has no account. It also acceptsapproval: "owner". Any otherapprovalvalue getsauthor.value_refused. The prompt'sperson_messageprovenance keepsapproval: "owner", and the hold is keyed on that field, not on the id prefix.approval: "owner"always goes into the queue, even when nothing is running. Itsqueuedrecord hasawaitingOwner: true, revision: 0, and itsprompt_acceptedsaysawaitingOwner.steer,steerNoworinterruptit asks for (prompt_unless_held).QueuedPrompt::aside): turn order, the digest of agent messages, the busy check of a retry or continuation, and a restart._acpmux/queue_approve {sessionId, promptId, revision}. The prompt waits no more and runs in its place in the queue as an ordinary queued prompt, never as a steer. The log recordsqueue_approved {promptId, turnId, revision, approvedAt}.revisionis not the current one, the request getsqueue.stale(data.revisionis the current one). The owner can only approve the words they saw._acpmux/queue_decline {sessionId, promptId}. The prompt leaves the queue and never runs.session/promptgets an error (-32000) withdata {reason: "queue.declined", promptId, turnId}.queue_declined {promptId, turnId, revision, declinedAt}, thenqueue_removed {reason: "declined"}._meta.acpmux.authorgetsqueue.owner_only.remote_guard.rs, the same check as a Web prompt).full_access_hold).queue.not_found(-32002) withdata.decided(approved,declinedorremoved) once the log says which.revision + 1, and thequeue_updatedrecord carriesawaitingOwnerandrevision.queue.awaiting_owner.queue.approved.queue.not_author.queue.too_many_heldbefore it is recorded.queued {awaitingOwner, revision}, then edits, thenqueue_approvedfor that revision,queue_declined, or a removal.QueuedPromptSummary(session summaryqueue) and_acpmux/composersexposeawaitingOwnerandrevision.queue_approvedandqueue_declinedare transcript kinds.queue-approval-v1and featurequeueApproval.docs/acpmux-schema.json, the README method list,spec/acpmux-protocol.json, and the TS types regenerated withbun scripts/acpmux-protocol-codegen.ts._acpmux/queue_removemoved unchanged intoserver/requests/queued.rs, next to the two new methods. That keepsrequests.rsfrom growing.Not touched: the files of cmux#26707 (
claude_stdio/steer_batch.rs,hub/steer_end.rs). Thecmux host shareproxy (agent_proxy.rs) only lets through a fixed list ofagent-session-*commands, so a teammate cannot reach the new methods. Stampingapproval: "owner"for anaskerrole comes in the next PR (plan item 2).Risk
risk:high (labelled). Queue scheduling now skips prompts that wait for the owner, the same way it skips
heldones. For a prompt with noapproval, nothing changes: the new paths only run when the provenance carriesapproval: "owner", which only a stamped author sets today. The approval methods sit behind owner-only, Web-control and Full-access checks.Tests
tests/hub_integration/prompt_approval.rs:queue.owner_only, and a stale revision getsqueue.stale.queue.declined, and the turn never starts.queue.awaiting_owner, the owner's edit getsqueue.not_author, an edit after approval getsqueue.approved, and a late answer getsqueue.not_foundwithdecided. The 17th held prompt getsqueue.too_many_held.racing_edits_are_logged_in_revision_order: two clients edit the held prompt 20 times each, concurrently. The log'squeue_updatedrecords name revisions 1 to 40 in log order. An edit is now logged under the queue lock that gave it its revision, asqueue_approvedandqueue_declinedalready were (review BLOCK at f86a848: an edit logged after the lock let a slower, older edit land last, and a restart then paired a later approval with other words).a_restart_never_rolls_an_edit_back_to_an_older_revision: a log that holds revision 1's edit after revision 2's (as an older daemon could write it) restores revision 2's words. An approval of revision 1 getsqueue.stale, and approving revision 2 runs "second rewrite".Ran on the merged head with
cargo test -p acpmux --test hub_integration -- prompt_approval: 14 passed.cargo test -p acpmux --lib protocol(the IR check): 9 passed. Red on the tests-only commit d890b18 (the fix left out):a_restart_never_rolls_an_edit_back_to_an_older_revisionFAILED,left: (true, 1)right: (true, 2), the restart restored the older revision.racing_edits_are_logged_in_revision_orderpassed there too: the race needs an unlucky interleaving and did not hit in 20 rounds, so it guards the order without proving the old bug.A second base merge (234b0a8) resolved conflicts with #27523 (inbox digest), #27660 (queue remove
fromAgentsOnly) and #27685 (Stop holds agent messages):gone_reply) and the owner's decline (gone_or_declined). A prompt that still waits for the owner (take_queued→Ok(None)) frees its turn and waits on.queue_remove's newfromAgentsOnlymoved intoserver/requests/queued.rswith it.digestible).logged_prompt's new-incarnation arm also clears the digest a requeued copy left.cargo clippy -p acpmux --tests -D warningsis clean. This VM's test runs hit its own TMPDIR/home permission checks (private-store refusals), so the merged head's acpmux tests are CI's.The first base merge resolved conflicts with #27519 (
_acpmux/queue_text) and #27536 (a carried turn queues behind it). Both methods stay registered, and base's two newenqueuecalls take the held-prompt cap's error like the others.Also: unit tests in
author.rs, and the IR and capability tests. Results are in the cmux-ci receipt below.No capture: nothing on screen changes. The only webview file touched is the generated protocol method list (
webviews/src/agent-session/acpmux/protocol/generated/methods.ts, two new_acpmux/queue_approve/queue_declineentries); the Approve / Decline card is #26742.Changelog
none
Agent session: agent session
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Adds owner approval for prompts that link guests send in acpmux, the first step toward the guest chat flow in manaflow-ai/cmuxterm-hq#4766. A prompt whose author carries
approval: "owner"queues and waits for the owner: it is never steered in, never stops the running turn, and the queue runs past it. Prompts without that flag behave exactly as before.Changes
_acpmux/queue_approveruns the prompt in queue order at the revision the owner saw; stale revisions getqueue.stale;_acpmux/queue_declinedrops it and its writer answersqueue.declined. Both are owner-only, hold to Web control and Full-access rules, and the approved prompt runs under the approver's rules too (stricter control, trust gate, Full-access machine), recorded inqueue_approvedand restored on restart.queue_approved/queue_declinedare indexed transcript kinds.queue.awaiting_owner. At most 16 prompts wait per author (queue.too_many_held); a restart rebuilds the state from the log (a slower, older edit never rolls back a newer revision), a waiting prompt wakes no child and holds no notice back, and summaries exposeawaitingOwnerandrevision.queueApprovalat handshake; an older peer getsqueue.approval_unsupportedand nothing is forwarded. A chat with a held prompt cannot move (transfer.held_prompts), checked against every bundle log segment.Written for commit 4dd329b. Summary will update on new commits.