Skip to content

Agent pane: a guest's message waits for the owner (Approve / Decline) (carries #26742) - #31144

Merged
teamleaderleo merged 15 commits into
feat-cmux-nextfrom
lane/mp-card-carry-2
Nov 1, 2026
Merged

teamleaderleo merged 15 commits into
feat-cmux-nextfrom
lane/mp-card-carry-2

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Nov 1, 2026 •

Copy link
Copy Markdown
Collaborator

Leo: "also what about the group chats for inviting people to see my sessions?" and "just get the initial end to end flows working and working well adn looking good and feeling good".

Carries #26742 (its owner is not live), rebuilt on #31066 with Leo's commit cherry-picked and its authorship kept.

What

A link guest's message that waits for the owner draws in the transcript as the guest's own card ("Waiting for you"), with Approve and Decline. Approve names the revision the card shows (and acpmux's queued incarnation, turnId, which the pane reads itself); a guest's edit since makes Approve wait for the new text. Decline leaves a "Declined" line. The native pane relays _acpmux/queue_approve, queue_decline and queue_get for the page (session-scoped, with turnId allowed on approve).

Merge resolutions (base moved a lot since #26742)

  • IncomingMessageCard.tsx keeps base's DisclosureRow, lane notice, read-only and Chief face, and adds the person sender (PersonName, guest label), the whole text as sent, and file chips.
  • QueuedMessageCard.tsx keeps base's WaitingMessageMenu and footer row and adds PersonMessageCard, HeldAnswer and DeclinedLine.
  • App.tsx draws a person's queued rows on their own between the turn rows and the pending group.
  • AcpmuxPaneMethods.swift keeps base's session-scoped list plus the three queue methods; turnId is allowed on queue_approve (base's answerHeld sends it; without it the relay would refuse every approve), with its relay test.
  • multiplayer.css keeps Approve and Decline visible (base's received-line action slot shows only on hover).

Tests

bun test src/agent-session/acpmux/conversation/heldMessage.test.tsx src/agent-session/acpmux/heldPrompts.test.tsx on cmux-ci at dc8b008: 30 pass, 0 fail. The same tests against the code before the root fix (c36794f): 3 fail ("a held prompt with no author is drawn whole in the read-only transcript too", "a person's words are never a lane notice, so a declined guest prompt is never batched as one", "no notice entry point turns a person's prompt into a notice (every person row, every path)").

A person's prompt (a guest's held, queued or declined one) is never read as a lane notice: its message carries fromPerson, laneNotice returns nothing for it and noticeOf returns nothing for any row marked person, held or declined, so no card, line or batch can show part of what Approve runs (found over three review rounds; fixed at the root in round 4).

Observed / Not run

Observed: the tests above; prepush-gate.py no new violations; Swift compile of CmuxNext fails only in CloudStartChatMachineTests.swift (not in this PR); tsc fails only in test/latency/probe.ts (base). Not run: a capture of the card.

Captures

None yet: gallery entry multiplayer.guest-approval (GuestApproval.gallery.ts) renders the card states with fixture data.

Risk

Normal. Agent pane transcript rows for a guest's held prompt only; nothing changes for chats with no guest.

Changelog

Added: the chat owner approves or declines a guest's message from the transcript.

Agent session: agent session

🤖 Generated with Claude Code

teamleaderleo and others added 6 commits November 1, 2026 15:28
A queued prompt acpmux holds for the owner (awaitingOwner, from a link guest)
is tracked by its authoritative record. THE RULE (direct.ts Hold): it is
approvable only when the pane holds that record (a queued / queue_updated
record, or _acpmux/queue_get) for its current revision; a listing never makes
it so. Text, images, parts and revision always come from one record.

- answerHeld sends _acpmux/queue_approve {sessionId, promptId, revision} with
  the revision the card drew, or _acpmux/queue_decline {sessionId, promptId}.
- A held prompt whose record the pane lacks (an attach page that starts after
  it) is read with one queue_get, keyed by selection generation and prompt,
  only where acpmux names queueGet; without it the prompt stays updating.
- queueApproval and queueGet come from initialize's features.
- An owner's own queued prompt still settles its bubble on its queued record.
- Needs you lists each held prompt (where queueApproval is served) with one
  action, Review, which scrolls to and focuses its card; it never approves.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
(cherry picked from commit 9241815)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
(cherry picked from commit ee2f0a1)
…; a failed held-text read is not retried every update

The review at 63d8d08 found: initialize declared `features` twice (a compile
error after the merge); `_acpmux/queue_approve` requires `turnId` (the queued
incarnation the owner saw) and the model dropped it; a failing `queue_get`
was retried on every queue-bearing update. Held entries now carry the record's
or listing's turnId, Approve sends it (and sends nothing without one), and a
held-text read is keyed by listed revision and kept once settled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-049fca947e3297e5ccd3
…d-model-carry

# Conflicts:
#	webviews/src/agent-session/acpmux/Localizable.xcstrings
The held message's card on the pane model (lane/mp-held-model): a guest's
held prompt draws in the transcript as that person's message, its record
whole (text as sent, images, documents, audio and links), with Approve
(primary) and Decline (quiet) and the quiet label "Waiting for you"; Return
approves when the card has focus. Approve names the revision the card drew;
"Updating…" (no answers) while the pane lacks the record at its current
revision; "Edited since you looked" and "Already answered" for acpmux's
queue.stale and queue.not_found. Approved, it waits as a queued message;
declined, one quiet line "Declined: <first line>" that opens on a click.
The relay allows queue_approve (sessionId, promptId, revision; a gesture),
queue_decline and queue_get. Gallery agent-pane.guest-approval with three
looks (inline, the pick; bar; menu).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-c3300437b0af7f1bba36
(cherry picked from commit f21a9cc)
Base's direct.ts answerHeld names the held prompt's turnId with its
revision, so the native relay's queue_approve allowlist takes turnId
(relay test and the pane's allowlist test send it). The held card's
Approve and Decline stay shown in the DisclosureRow action slot, with its
quiet note in caption type, as the line draws on this base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-049fca947e3297e5ccd3
@github-actions

github-actions Bot commented Nov 1, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 69588d1: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr31144 -f ref=lane/mp-card-carry-2 -f platform=macos -f backend_mode=local

Gallery before/after for 69588d1: 16 states rendered, 0 images differ, 2893 more touched states not rendered. Images are in the run's artifact, not on this public PR; the independent review of this head reads them on its own, so the PR needs no hand-made screenshots of these states.

gh run download 41338990011 -R manaflow-ai/cmux -n gallery-advisory-31144-69588d13f59281de4ad4fca44d25f38e2f81e8c8 (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.addressed-message/relayed Apple System Colors Light unchanged 0% own IncomingMessageCard.tsx
agent-pane.addressed-message/relayed Apple System Colors unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/prompt-rest Apple System Colors Light unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/prompt-rest Apple System Colors unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/prompt-hover Apple System Colors Light unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/prompt-hover Apple System Colors unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/prompt-copied Apple System Colors Light unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/prompt-copied Apple System Colors unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/message-rest Apple System Colors Light unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/message-rest Apple System Colors unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/message-hover Apple System Colors Light unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/message-hover Apple System Colors unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/message-copied Apple System Colors Light unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/message-copied Apple System Colors unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/quiet-rest Apple System Colors Light unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/quiet-rest Apple System Colors unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/quiet-copied Apple System Colors Light unchanged 0% own IncomingMessageCard.tsx
agent-pane.card-copy/quiet-copied Apple System Colors unchanged 0% own IncomingMessageCard.tsx
agent-pane.chat-width/standard Apple System Colors Light unchanged 0% own App.tsx
agent-pane.chat-width/standard Apple System Colors unchanged 0% own App.tsx
agent-pane.chat-width/wide Apple System Colors Light unchanged 0% own App.tsx
agent-pane.chat-width/wide Apple System Colors unchanged 0% own App.tsx
agent-pane.chat-width/wide-blocks Apple System Colors Light unchanged 0% own App.tsx
agent-pane.chat-width/wide-blocks Apple System Colors unchanged 0% own App.tsx
agent-pane.composer-edge/short-edge Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-edge/short-edge Apple System Colors unchanged 0% own App.tsx
agent-pane.composer-edge/wide-edge Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-edge/wide-edge Apple System Colors unchanged 0% own App.tsx
agent-pane.composer-edge/no-edge Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-edge/no-edge Apple System Colors unchanged 0% own App.tsx
agent-pane.composer-floats/scrolled-to-end Apple System Colors Light unchanged 0% own App.tsx
agent-pane.composer-floats/scrolled-to-end Apple System Colors unchanged 0% own App.tsx

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

Passes: CI passes on 69588d13f5.

CI passes on 69588d13f5 (run 41338990205 attempt 1).

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

web and size checks: green

Shipped in:

@blacksmith-sh

blacksmith-sh Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

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

…card tests fit the card

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-049fca947e3297e5ccd3
…d-carry-2

# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextAgentPane/AcpmuxPaneMethods.swift
#	webviews/src/agent-session/acpmux/Localizable.xcstrings
#	webviews/src/agent-session/acpmux/direct.ts
teamleaderleo and others added 2 commits November 1, 2026 17:17
…never as a lane notice

The review at 75448eb found the read-only row (guest page, read-only
transcript) still read a guest's prompt as a lane notice, so one that starts
like a lane report lost its lead text there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-049fca947e3297e5ccd3
Round 3 of the review at c36794f found two more paths that read a guest's
prompt as a lane notice: a held row whose listing names no author, and a
declined guest row that lane-notice batching could regroup. Instead of one
check per caller, a held or declined guest prompt's message is marked
`fromPerson`, and laneNotice (which every card, line and batch reads) returns
nothing for it. The read-only row also draws held and declined rows whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-049fca947e3297e5ccd3
@cursor

cursor Bot commented Nov 1, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot 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.

teamleaderleo and others added 2 commits November 1, 2026 17:37
Sweeps every person row (held with and without an author, a guest's queued
prompt, declined, and a row marked only by its queue marks) through laneNotice,
noticeOf, batchLaneNotices, appendLaneNotice and the read-only transcript row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-049fca947e3297e5ccd3
A row marked person, held or declined is no notice whatever its message object
says, so lane-notice batching, inbox projection and every card agree with
laneNotice's own fromPerson rule.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-049fca947e3297e5ccd3
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, next-review): BLOCK at dc8b008

BLOCK at dc8b008

Visual verdict: Inspected all 16 after images; each is byte-identical to its baseline. None shows guest approval states.

  1. [P1] [blocking] Bind approval to the displayed turnId. QueuedMessageCard.tsx:190 passes only the displayed revision. direct.ts:7175 obtains turnId from the current queue. If a removed prompt ID is reused at revision 0—as the server explicitly supports—an old card can approve the replacement before React redraws. The request contains the replacement’s valid identifiers, so the server accepts unseen text. Carry the displayed turnId through the row and approval call alongside revision.

  2. [P2] [follow-up] Recovered held prompts can hide attached images. QueuedMessageCard.tsx:260 renders images only from row.images. The real queue_get response supplies images through prompt and inlineParts, without an images field. installHeldRecord consequently clears the image list, while heldFiles ignores image parts. Opening a chat whose held record precedes the loaded history can therefore enable Approve without showing its images. Normalize that response’s images before enabling approval.

  3. [P2] [follow-up] Capture the new approval states. GuestApproval.gallery.ts:63 defines the relevant fixtures, but the supplied captures omit them. Include held, multiple-held, approved and declined states, including a narrow pane.

An isolated check of the actual approval method reproduced finding 1. Full tests could not run: Bun and dependencies are absent.

@teamleaderleo teamleaderleo removed the risk:high Risk tier (docs/ci/risk-tiers.md) label Nov 1, 2026
@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Nov 1, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (subagent claude-opus-5-5 medium): SHIP at 6688b02 (delta from dc8b008: drops the two cursor: pointer rules that turned test/clickable-cursor.test.ts red; round 4 SHIP covers the rest).

all: unset drops the cursor desktop.css gives clickables, so Approve, Decline
and the declined line set cursor: default themselves (clickable-cursor.test.ts).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-049fca947e3297e5ccd3
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (subagent claude-opus-5-5 medium): SHIP at 69588d1 (delta from 6688b02: cursor: default on the two all: unset rules that clickable-cursor.test.ts named; round 4 SHIP covers the rest).

@teamleaderleo
teamleaderleo merged commit f2f8444 into feat-cmux-next Nov 1, 2026
184 of 191 checks passed
@teamleaderleo
teamleaderleo deleted the lane/mp-card-carry-2 branch November 1, 2026 19:40
cmux-bot Bot pushed a commit that referenced this pull request Nov 1, 2026
…eb lint) (#31281)

#31144 put one oxlint-disable-next-line above <div for both rules, but
jsx-a11y/no-noninteractive-tabindex reports on the tabIndex attribute four
lines down, so vp lint warned and web lint (fast) failed on every webviews
push. Split the disable so each rule sits above the line it reports.


Agent-Session: https://cmux.com/deeplink/agent?id=aid-2f629b93d5a20c58e6f8

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@lawrencecchen

Copy link
Copy Markdown
Contributor

This PR added _acpmux/queue_approve, queue_decline and queue_get to the Swift host's tables but not to cmux-tui/crates/cmux-agent-pane-policy/policy.json, so three crate tests are red on feat-cmux-next (tests/swift.rs the_requests_are_the_macos_hosts / the_known_params_are_the_macos_hosts, tests/typescript.rs the_allowlist_is_what_the_page_sends). Fix: #31794 (copies the Swift rule into policy.json). For next time: a new pane method goes into policy.json in the same PR.

lawrencecchen added a commit that referenced this pull request Nov 2, 2026
…t allows (#31144) (#31794)

#31144 (f2f8444) let the agent page send _acpmux/queue_approve,
_acpmux/queue_decline and _acpmux/queue_get, and added them to the Swift
host's tables (AcpmuxPaneMethods.swift requests, sessionScoped,
gestureRules; +Params.swift knownParams), but not to the crate's
policy.json. So three crate tests are red on feat-cmux-next:
tests/swift.rs the_requests_are_the_macos_hosts and
the_known_params_are_the_macos_hosts, and tests/typescript.rs
the_allowlist_is_what_the_page_sends.

policy.json now has the Swift host's exact rule: the three methods are
requests and session-scoped (only a chat in the pane's scope),
queue_approve needs the person's gesture, and the params are Swift's
(queue_approve: sessionId, promptId, turnId, revision; the other two:
sessionId, promptId). No method is allowed that the app does not allow
today; the app does not read policy.json yet.

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>
teamleaderleo added a commit that referenced this pull request Nov 2, 2026
…is turn" (#31711)

#31144 brought the label back for a guest's prompt once the owner approves
it; queued messages carry no "Read after this turn" (Leo, 2026-10-29).

Leo-ask: ask-d98e1527c4


Agent-Session: https://cmux.com/deeplink/agent?id=aid-5413c7e35e98c5ceffa7

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>
teamleaderleo added a commit that referenced this pull request Nov 2, 2026
…2371)

A held card's Approve / Decline / "Waiting for you" slot is always shown
(#31144), but it reused the shared hover slot's fade, which ends in the
hover plate's 6% tint. On a line nobody points at, that drew a gray box
over the preview's tail (share walk on DEV, 2026-11-01). At rest the fade
now ends in the bare page; the tint comes back with the plate on hover,
focus or an open menu.


Agent-Session: https://cmux.com/deeplink/agent?id=aid-e79e3dd73fdc44b36878

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 69588d13 Deployed Nov 1, 2026 by teamleaderleo via cmux-tui tree preflight #97211
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:high Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants