Skip to content

cmux-next: wire explicit read-only remote agent observation - #21258

Merged
teamleaderleo merged 23 commits into
feat-cmux-nextfrom
feat/acpmux-observer-ui
Oct 21, 2026
Merged

teamleaderleo merged 23 commits into
feat-cmux-nextfrom
feat/acpmux-observer-ui

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

Problem

The server-side agent-session-observe-v1 capability (on feat-cmux-next via #21386) is not yet consumable by the macOS remote agent viewer. Without an explicit client mode, a viewer could accidentally use writable attach semantics.

Change

This branch now carries only the observer client. The server half is already on base via #21386 (#21253 was closed for that reason). The base merge at 4438f6c dropped the unrelated work this branch had picked up: sidebar priority projection, motion debug menu, window snapshot encoding, agent-chat orchestration gallery, Codex voice capability negotiation, and new-tab fixes. Those commits are still in the branch history.

  • add an explicit .observe mode on AgentSessionAttachClient with its own capability handshake (agent-session-observe-v1) and its own agent-session-observe verb; a daemon without it refuses, and there is no fallback to writable attach;
  • an observing client refuses start and trust locally;
  • propagate observe mode through AgentTabRemoteHost / AgentTabRemoteClient (isReadOnly) and RemoteAcpmuxWire;
  • RemoteAcpmuxWire refuses session/prompt, session/cancel and _acpmux/permission_respond locally with agent_session.read_only, while record, permission and session-changed pushes stay visible;
  • add DaemonCapabilities.agentSessionObserve to the optional list and to plans/cmux-next/daemon-capabilities.json; update plans/cmux-next/remote-agent-attach.md;
  • tests: RemoteAcpmuxObserverTests (wire refusals, pushes still flow) and AgentSessionAttachClientObserverTests (mode capability/command, no start).

Selected chats can opt into AgentTabRemoteHost(mode: .observe) in a follow-up; nothing uses .observe yet, so default behavior is unchanged.

No capture: no visible UI change (observe mode is a client protocol mode; no selected chat opts in yet)

Validation (at 4438f6c)

  • swiftc -parse on every changed Swift file;
  • check-daemon-capabilities-fresh.py and check-app-capability-references.py pass;
  • check-concurrency.sh ok; crash_ratchet.py reports the same hits on the pure base tree (base reds, none from this diff);
  • the Swift compile and tests run on CI (never on this Mac).

Agent session: cosmic-gray

@teamleaderleo
teamleaderleo temporarily deployed to cmux-tui-merge-tree October 17, 2026 01:47 — with GitHub Actions Inactive
@coderabbitai

coderabbitai Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 21715061-5ad7-4cb8-a3e6-c9a2753735ed

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-dsbss created for this PR by the cmux coordinator.

@teamleaderleo

teamleaderleo commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator Author

Visual preview of 7641db5: in the maintainers' private review feed.

@teamleaderleo
teamleaderleo force-pushed the feat/acpmux-observer-ui branch from 184add5 to 5eb16aa Compare October 17, 2026 08:06
@teamleaderleo
teamleaderleo temporarily deployed to cmux-tui-merge-tree October 17, 2026 08:06 — with GitHub Actions Inactive
@github-actions

github-actions Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

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

Review 118c9c7: 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=pr21258 -f ref=feat/acpmux-observer-ui -f platform=macos -f backend_mode=local

Not verified: macOS jobs did not run: compile and app tests were skipped on 118c9c71f8; ci-status is green without them.

CI passes on 118c9c71f8 (run 39574719542 attempt 1).
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped (the macos job needs both to succeed). Re-run CI once they pass, before merging.

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.

red: cmux-next checks (god files, concurrency, crash safety, l10n); base red: the same failure on the base d0d5292; does not block

CI fast guards passes on 118c9c71f8 (run). This covers only the fast guards, not CI: CI's result is ci-status.

Tour of 118c9c71f8 (run): no media. The tour job failed before the tour ran (build or setup); the run log has the output.

@github-actions

github-actions Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Unclear: web / react-apps-check (2) failed: no known signature; failed step: Check webviews (Oxlint, Oxfmt, type check).

CI failed on 0c372043b6 (run 39018471427 attempt 1): 3 unknown.
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped.

Job Verdict Why
web / react-apps-check (2) unknown no known signature; failed step: Check webviews (Oxlint, Oxfmt, type check)
web / react-apps-check (1) unknown no known signature; failed step: Check webviews (Oxlint, Oxfmt, type check)
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Not re-run automatically: web / react-apps-check (2), web / react-apps-check (1), web / react-apps-check are not machine failures.

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.

@github-actions

github-actions Bot commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

CI fast guards failed on 0c372043b6 (https://github.com/manaflow-ai/cmux/actions/runs/39018471427). It does not block the merge; a red guard merged into main breaks it for every open PR.
The log named no failed step; see the run.

Agents: python3 scripts/ci/guard_attribution.py fix applies the mechanical fixes locally. This comment is updated in place on each push.

@blacksmith-sh

blacksmith-sh Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Found 4 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmp9yvsnk0o/summary-fail.json (live):/summary-fail.json (live): View Logs
/tmp/tmpvwmrnvnb/summary-missing.json (live):/summary-missing.json (live): View Logs
convention violations found (ERROR lines above)./
convention violations found (ERROR lines above).
View Logs
test_every_source_and_test_directory_is_a_target (main.GraphCoversThePackage.test_e
very_source_and_test_directory_is_a_target) (directory='CmuxNextHomeEngineTests')/
test_every_source_and_test_directory_is_a_target (main.GraphCoversThePackage.test_e
very_source_and_test_directory_is_a_target) (directory='CmuxNextHomeEngineTests')
View Logs

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

@teamleaderleo
teamleaderleo force-pushed the feat/acpmux-observer-ui branch from 7224079 to 0c37204 Compare October 17, 2026 08:43
@teamleaderleo
teamleaderleo temporarily deployed to cmux-tui-merge-tree October 17, 2026 08:44 — with GitHub Actions Inactive
- vp fmt webviews/src/agent-session/acpmux/conversation/TurnRows.tsx
- vp fmt webviews/test/new-tab-ask-model.test.tsx
- vp fmt webviews/test/voice-operations.test.ts

Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/39018471327
@cursor

cursor Bot commented Oct 20, 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.

viewFrame: view?.frame, viewAlpha: view?.alphaValue, inList: view?.superview === list,
suppressed: list.suppressed.contains(row.key), selected: view?.isSelected == true, muted: muted,
activity: activity, icon: view?.debugIcon, shownFrame: view?.shownFrame, clips: view?.clipsToBounds == true, group: row.group?.rawValue,
activity: activity, priority: priority, icon: icon ?? view?.debugIcon, shownFrame: view?.shownFrame, clips: view?.clipsToBounds == true, group: row.group?.rawValue,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Hidden icons appear drawn

debugRows() now reports workspace.icon before checking what the view draws. When a user hides icons through the row settings, WorkspaceRowContent removes the icon but this report still says it is visible. That can hide rendering bugs during sidebar checks. Keep view?.debugIcon as the reported value.

Suggested change
activity: activity, priority: priority, icon: icon ?? view?.debugIcon, shownFrame: view?.shownFrame, clips: view?.clipsToBounds == true, group: row.group?.rawValue,
activity: activity, priority: priority, icon: view?.debugIcon, shownFrame: view?.shownFrame, clips: view?.clipsToBounds == true, group: row.group?.rawValue,

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next guards / defaults-snapshot is red on 22 of 22 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

CI / web / react-apps-check (2) is red on 13 of 20 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

CI / web / react-apps-check (3) is red on 14 of 19 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

CI / web / react-apps-check (1) is red on 13 of 18 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

CI / web / react-apps-check (4) is red on 13 of 18 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by orphan-sweep on cosmic-gray · session

…rver client

Base merge at 7fbe570. The branch had picked up unrelated work
(sidebar priority projection, motion debug menu, window snapshot encoding,
agent-chat orchestration gallery, Codex voice capability negotiation,
new-tab fixes); none of it is on base, and it is not this PR's intent, so
those paths are restored to base here. Their commits stay in this branch's
history. The net diff is now the read-only remote observation client only;
the server half is on base via #21386.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cfc-663f-7650-b9f7-64d198c6b88b&host=cosmic-gray
@cursor

cursor Bot commented Oct 21, 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 teamleaderleo added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 21, 2026
teamleaderleo and others added 2 commits October 21, 2026 01:57
# Conflicts:
#	Packages/macOS/CmuxNext/Sources/CmuxNextDaemon/Connection/DaemonEndpoint.swift
Synchronization.Mutex needs macOS 15 and the package supports 14, so the
CmuxNextAgentPaneTests target would not build (base moved its tests to
CmuxNextCompat in 330d4cc). The two test helpers are marked nonisolated,
as OneShotRelay is, since the target defaults to the main actor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cfc-663f-7650-b9f7-64d198c6b88b&host=cosmic-gray
@cursor

cursor Bot commented Oct 21, 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.

[String: Any] is not Sendable, so handing it out of Mutex.withLock is a
region-isolation error in Swift 6 mode. Store the frame text and decode
outside the lock, as base's FrameBox does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15cfc-663f-7650-b9f7-64d198c6b88b&host=cosmic-gray
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (independent subagent): SHIP at 118c9c7

Independent review subagent with a fresh context, run by orphan-sweep on cosmic-gray. It took three rounds.

  • 4438f6c / c00bb68: BLOCK. RemoteAcpmuxObserverTests imported Synchronization, whose Mutex needs macOS 15 while the package supports macOS 14.
  • 17776d2: BLOCK. The test's Frames handed non-Sendable [String: Any] out of Mutex.withLock, which is a region-isolation error in Swift 6 mode.
  • Fixed in 17776d2 and 118c9c7. The tests now use CmuxNextCompat's Mutex, and only the frame text stays under the lock.

At 118c9c7:

  • The client matches the server on base (acpmux: fence mailbox identities by session receipts #21386): verb agent-session-observe, capability agent-session-observe-v1, the request params, the reply page, and the local agent_session.read_only code.
  • Observe mode has no path that falls back to a writable attach or sends a prompt, cancel, permission answer, trust change or start.
  • Every changed call site and initializer fits base's current APIs. daemon-capabilities.json is fresh.
  • A full Swift 6 concurrency and availability sweep of the diff found nothing more.
  • No merged PR duplicates this one.

Non-blocking:

  • This is plumbing only: no production caller sets mode = .observe yet.
  • The tests don't check the .observe → read-only mapping in AgentTabRemoteClient, and don't check that a daemon without the capability is refused.
  • waitUntil sleeps 5 ms between checks.
  • Observe-mode trust() throws startUnsupported; read_only would describe the refusal better.

Nothing was compiled during the review. CI swift test on this head is the compile proof.

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…nly (#23362)

#21258 made isReadOnly a requirement of AgentSessionRemoteClient, and
#23163, merged after it, added a FakeClient without it, so
CmuxNextAppTests stopped compiling on feat-cmux-next and no Swift suite
runs. The fake is a writable daemon attachment, so it says false.


Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15ba2-c7ad-7850-9e71-5b51f1c9ed9f&host=cosmic-gray

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
Conflicts resolved, keeping both sides:
- AgentSessionWorkspace: the remote adopt path and #22809's `group` argument
  (now passed to the local open too, and its listed-key reuse applies to adopt);
  base's firstPane(mirroring:) replaces this branch's duplicate mirroredPane(of:).
- AgentTabRemoteHost/AgentTabRemoteClient: the client moved to CmuxNextAgentPane
  here; it carries #21258's observe `mode`/isReadOnly and #23163's children().
- AgentSessionAttachClient: attach sends mode.command (attach or observe) with
  this branch's mode_events and bypass notes; the mode read is chatMode() so it
  does not clash with the `mode` property; adopt refuses in observe mode.
- DaemonEndpoint capability list: agentSessionAdopt plus base's observe,
  children, cloudAttachments and cloudSelfHost.
- cmux-tui agent_session_attach/stream: adopt module and children module,
  mode-read fields and children set; a session_changed of the session or a
  followed descendant streams, and only the session's own mode change re-reads.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15ba7-3152-78b2-bfdf-bb6eb0d5a053&host=cosmic-gray
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…eaches (#23423)

* test(ci): the fleet compile check compiles the test targets a change can break (red)

fleet/compile-check compiles only the app executable, so #23360 (a
throwing call in #expect without try, CmuxNextActionsTests) and #23163
(a FakeClient that missed #21258's requirement, CmuxNextAppTests) passed
it and broke feat-cmux-next's test build. This test pins the plan the
check must compile and the new package-test-lane.sh compile-tests
argument check; neither exists yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a3aef81402c7&host=cosmic-gray

* ci(fleet compile-check): also compile the test targets the change reaches

fleet/compile-check compiled only the app executable, which links no test
target, and merge_compile_guard accepts it in place of a queued Release
compile. #23360 (CmuxNextActionsTests) and #23163 (CmuxNextAppTests)
passed it while every Mac job that builds tests sat queued, and broke the
base's test build.

The workflow now reads the head's merge base with feat-cmux-next from the
compare API and runs `package-test-lane.sh compile-tests MERGE_BASE` on a
fleet Mac beside the Linux app compile; success needs both. The plan
(scripts/ci/compile_test_plan.py) is the CmuxNext test targets that depend
on a changed target in the existing SwiftPM target graph (the routing
cmux_next_route.py gives the swift test tier), plus the macOS package
lane's packages whose sources or path dependencies changed. Each CmuxNext
test target builds with `swift build --target`, so nothing links or runs.
The Linux pool cannot do it: its SDK has no Testing module.

A head whose package-test-lane.sh predates the phase gets no verdict
(error), with "merge feat-cmux-next and dispatch again".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a3aef81402c7&host=cosmic-gray

* ci: the test-target compile is an advisory check; fleet/compile-check is the app compile again

coord-deputy: an ~11 min Mac queue on every PR's merge gate costs too much.
fleet-compile-check.yml and merge_compile_guard.py are back to feat-cmux-next's
(the Linux app compile, same status semantics).

fleet-test-compile.yml runs on pull requests into feat-cmux-next that touch
Packages/ or vendor/: a Linux job plans with compile_test_plan.py over the
merge commit's diff; an empty plan passes there in seconds and queues no
Mac; a plan runs `package-test-lane.sh compile-tests BASE` as a light fleet
step, and the check `fleet/test-compile (advisory)` goes red only when a
planned test target does not compile. It is a bridge until the Linux pool
image carries cmuxterm-hq #2750 (Testing search paths).

Tests: the guard ignores the advisory check, red or pending, and it never
stands in for the Release compile; CI and app-host changes plan nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a3aef81402c7&host=cosmic-gray

* test(ci): compile-tests stays red after a later setup failure; one fallback per package; advisory verdicts

Red on c150a5c: a target failure followed by a later package's setup
failure exits before the failure marker, so the check only warns; a refused
--target falls back to --build-tests once per target; the job's 45 min
timeout is shorter than the client's queue plus run timeouts, so a slow
fleet ends red; exit 128 after the marker maps to a warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a3aef81402c7&host=cosmic-gray

* ci(fleet-test-compile): a compile failure stays red; a slow fleet never does

- package-test-lane.sh compile-tests prints the failure marker as soon as a
  target fails, so a later package's setup failure cannot hide it.
- A refused --target falls back to --build-tests once per package, in place
  of its remaining targets.
- fleet-test-compile.yml: red on the marker whatever the exit; the job
  timeout (55 min) outlasts the client's queue plus run timeouts (45 min),
  so a timeout is a warning, never red.
- cmux-next.yml runs tests/test_ci_compile_test_plan.py with the merge guard tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a3aef81402c7&host=cosmic-gray

* ci(package tests): compile_test_plan.py is a global input of the package test job

package-test-lane.sh compile-tests runs it, so test_ci_select_package_tests.py
requires it in GLOBAL_INPUTS (red on b96188a: "scripts the package test
job runs are not global inputs").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15bf1-fdac-78a0-ac2e-a3aef81402c7&host=cosmic-gray

---------

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

Copy link
Copy Markdown
Collaborator Author

merge-audit: #21258 merged at 118c9c7 without no green compile (its own red: cmux-next / cmux-next Release compile (Xcode 26)), and its revert could not be opened (abort and get back to the state before "git revert",
hint: run "git revert --abort".
hint: Disable this message with "git config set advice.mergeConflict false"). Fix forward or revert it by hand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant