Repository navigation
Cloud: a machine's creator can start chats on it from the app, team machines included - #29107
Merged
Merged
Conversation
… API's owner word The start, folder trust and chat move-in gate refused a team VM before it read the caller's vm_kind. Since #28788 the Cloud API answers vmKind owner per caller for a machine's creator only, so that word now lets the creator in on a team VM; every other caller still gets agent_session.team_vm_blocked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5
Contributor
|
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)
Shipped in:
|
|
Found 3 test failures on Blacksmith runners: Failures
|
teamleaderleo
temporarily deployed
to
ci-routing-agent
October 31, 2026 08:26 — with
GitHub Actions
Inactive
Collaborator
Author
|
Review (codex, router-review): SHIP at f14d2ba Reviewer: codex gpt-6-astra high, fast tier. Follow-ups: 1. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward. SHIP at f14d2ba Visual verdict: no images; Leo tries the build.
Follow-ups:
|
teamleaderleo
temporarily deployed
to
artifacts
October 31, 2026 08:48 — with
GitHub Actions
Inactive
teamleaderleo
temporarily deployed
to
sentry-dsyms
October 31, 2026 08:48 — with
GitHub Actions
Inactive
teamleaderleo
temporarily deployed
to
artifacts
October 31, 2026 08:56 — with
GitHub Actions
Inactive
teamleaderleo
added a commit
that referenced
this pull request
Oct 31, 2026
… still refuses Codex there After #29107 a team VM passes host_gate on vm_kind owner, so a Codex or opencode start there is refused by the family check (not_asking), not team_vm_blocked. Without the word it is still team_vm_blocked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c
cmux-bot Bot
added a commit
that referenced
this pull request
Oct 31, 2026
* test: Codex and opencode start and send on the person's own Cloud VM only (red) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * Cloud: Codex and opencode chats run on the person's own Cloud VM On a Cloud VM with no team evidence and the caller's vm_kind owner (the Cloud API's answer on the link), agent-session-start skips the refused-family check and the asking-mode settle, so Codex and opencode start in their default mode with policy ask (agent-session-start-owner-cloud-v1). The app's remote wire names ownerCloud in initialize while the link's owner answer holds, and the composer lets those chats send. A Mac, an SSH host, a team VM, a remote browser and paired devices keep D10's refusal; acpmux's Web rules are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * test: drop an unused frame list Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * gallery: a Codex chat on a team Cloud machine and on the person's own Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * webviews: format remoteComposer's signature Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * Cloud owner chats: the owner answer's wire closure lives in CmuxNextAgentPane, not the App Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * Cloud: the link owner answer's closure moves from the App to CloudLinkSession Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * Cloud owner chats: list agent-session-start-owner-cloud-v1 in the daemon capabilities export The export (plans/cmux-next/daemon-capabilities.json) is generated from DaemonEndpoint.swift by check-daemon-capabilities-fresh.py --write; the "Daemon capabilities export is fresh" check was red on the new capability. Also rustfmt the server.rs re-export list the capability joined. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * Cloud owner chats: advertise agent-session-start-owner-cloud-v1 only on an owner Cloud VM The daemon advertised the capability on every host that serves agent-session-start, so the app's ownerCloud rested on the Cloud API's owner answer alone for sends to an attached Codex or opencode session. Now the daemon advertises it only where its own host read is a Cloud VM with no team evidence (OwnerCloud/UnknownCloud), so a Mac, an SSH host or a VM with team evidence never lets such a chat send, whatever the Cloud API says. agent_session_start_starts_codex_on_the_callers_own_cloud_vm_only now also checks that the SSH and team daemons do not advertise it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * RemoteAcpmuxOwnerCloudTests: build the owner closures outside #require The swift-test job failed to compile the suite (run 41164536291, job 124435466356): #require's expansion passed the literal closures on without the parameter's @sendable ("passing non-Sendable parameter '$1' to function expecting a '@sendable' closure" at lines 55 and 57). The closures are now typed @sendable values and each call's answer is computed before the macro. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud: owner-cloud start is a Cloud-only capability, not a DaemonCapability case The bundled-daemon probe (check-daemon-capabilities.sh) starts a Mac daemon, which never serves agent-session-start-owner-cloud-v1: only a Cloud VM with no team evidence advertises it. Like fs-v1, the app now gates on a constant (RemoteAcpmuxWire.ownerCloudCapability) listed in CONDITIONAL, so the probe no longer requires it of the Mac daemon. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cmux-tui test: a team VM takes the creator's owner word (#29107), and still refuses Codex there After #29107 a team VM passes host_gate on vm_kind owner, so a Codex or opencode start there is refused by the family check (not_asking), not team_vm_blocked. Without the word it is still team_vm_blocked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * arch-ratchet: allow #28613's 3 App lines of owner-Cloud wiring Base's #29365 moved the owner-answer helper out of CmuxNextApp itself (CloudMachineLinks), which took away this PR's own offset. What's left is AgentTabRemoteHost.ownerCloud and the one wiring line that builds it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c --------- 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
Oct 31, 2026
…hine and starts once more (#29497) * cmux NEXT Cloud: a first chat an older daemon refused updates the machine and starts once more A fresh Cloud machine boots its image's cmux-tui (images/cmux-vm pins 308bd36, from before #29107), so its daemon refuses its creator's chat on a team VM with agent_session.team_vm_blocked. The app's automatic update of that machine runs in the background from its handshake, so a chat started right after the machine came up (cloud.startChat, cmux cloud start-session, the first send) reached the old daemon. Now such a refusal (team_vm_blocked or host_unverified) on the caller's own machine (the link's owner answer) runs the same update at the front of the shared DaemonUpdatePolicy queue (DaemonUpdatePolicy.updateNow, joining an update of that machine that already runs), waits for its turn to end, and starts once more. A teammate's machine is never retried; any other refusal stands. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * DaemonUpdatePolicy.updateNow: a capped wait stream; an explicit request is due now and outlasts a turn that never reached its update Review of #29497 (follow-ups #29498, #29499) and the concurrency gate's unbounded AsyncStream. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cmux NEXT Cloud: updateNow uses the injected policy; joining a running update never runs it twice Review of #29497 at 872a507: #28271 removed DaemonUpdatePolicy.shared (the policy is services.daemonUpdates.policy), and a refusal that arrived while the machine's update was inside target.update re-marked it, so a failed update ran a second time. The policy now marks the target inside its update and updateNow only waits for that turn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>
austinywang
added a commit
that referenced
this pull request
Nov 1, 2026
Keep explicit folder-trust coverage in HOME/project, since the base now auto-trusts an owner's HOME/work (#29556). Verify the creator can start a chat on a team machine (#29107), including the machine session and store binding. Refuse missing owner answers on both plain and team hosts. Reproduced at 23adfaf via cmux-ci step 64a6dadbad022f88b748f474: scripts/ci/package-test-lane.sh suite Packages/macOS/CmuxNext CloudAgentChatTests,CloudLinkReconnectingTests,PlacementDocumentWriteOrderTests Cloud chat failed 3/4 due to these stale expectations; reconnect passed 5/5. Placement's pre-operation ordering assertion also fails independently. Scoped syntax, localization defaults, feature flags and namespace lint pass. The workspace package-group finding is unchanged base debt. Exact-head fleet verification follows the normal push; no local builds.
lawrencecchen
pushed a commit
that referenced
this pull request
Nov 1, 2026
…agent on the VM (#25680) * test(next cloud): an ACP chat in a Cloud workspace runs its agent on the machine (#25583) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: frames collector off the main actor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a reconnected page reattaches to the machine's chat Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the GUI's default first send in a Cloud workspace Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: prove the agent runs with the machine's environment; check the default folder Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the machine's HOME is the agent's (acpmux passes no ACPMUX_HOME) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the Cloud machine's link gives the owner answer a chat start needs (#26323) Since #26323 the app starts a chat on a Cloud machine only on the Cloud API's vmKind owner answer of the running link. The stand-in machine now runs a stand-in link whose attach answer says owner; a new case checks that with no owner answer no chat starts and the page says why. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test(next cloud): an ACP chat in a Cloud workspace runs its agent on the machine (#25583) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: frames collector off the main actor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: a reconnected page reattaches to the machine's chat Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the GUI's default first send in a Cloud workspace Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: prove the agent runs with the machine's environment; check the default folder Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the machine's HOME is the agent's (acpmux passes no ACPMUX_HOME) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the Cloud machine's link gives the owner answer a chat start needs (#26323) Since #26323 the app starts a chat on a Cloud machine only on the Cloud API's vmKind owner answer of the running link. The stand-in machine now runs a stand-in link whose attach answer says owner; a new case checks that with no owner answer no chat starts and the page says why. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: the stand-in Cloud machine's daemon gates on the owner word; setup always cleans up Review fixes for the Cloud ACP chat tests: - the machine's daemon is told it is a Cloud machine of unknown kind (CMUX_AGENT_START_HOST=unknown-cloud), so a start and a trust answer run there only with the app's vm_kind owner; the no-owner-link case stays on a plain host so only the app can refuse it - the Cloud workspace's terminal starts in the machine's work folder, and the no-folder case checks the chat starts there - both daemons end with the test process (exitWithProcess), and every launch sits inside the cleanup scope; this Mac's acpmux home is shut down too - waits stop on cancellation; an unreadable acp ls answer is an issue, not an empty list; refusal text comes from AgentRemoteStartRefusal - the stand-in link outlives the 2-minute limit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: isolate Cloud chat sidebar document ownership CloudAgentChatTests binds AppActions and awaits live daemon work, which changes process-wide SidebarDocStore.current. Hold the existing suite ownership gate so concurrent sidebar suites retain their document. Swift syntax and diff checks pass; focused fleet execution follows on the pushed head. * test: isolate Cloud chat harness startup Use private homes for both test machines and disable login-shell import, live catalog fetches and unrelated model probes, matching MachineCatalogAppFixture. Login import and catalog reload precede the first remote-start preflight, whose individual RPCs are bounded at five seconds. Fleet step 411470d1a2e191624d761bfc on 71e8a84 compiled all test targets, then CloudAgentChatTests failed 2/4 with agent_session.timeout before folder-trust refusal. Reconnect tests passed 5/5 and sidebar placement passed 1/1. The same focused Cloud command will be rerun through cmux-ci on this repair; no assertion or production timeout is changed. * test: report Cloud chat timeout context * test: follow current Cloud chat owner and folder rules Keep explicit folder-trust coverage in HOME/project, since the base now auto-trusts an owner's HOME/work (#29556). Verify the creator can start a chat on a team machine (#29107), including the machine session and store binding. Refuse missing owner answers on both plain and team hosts. Reproduced at 23adfaf via cmux-ci step 64a6dadbad022f88b748f474: scripts/ci/package-test-lane.sh suite Packages/macOS/CmuxNext CloudAgentChatTests,CloudLinkReconnectingTests,PlacementDocumentWriteOrderTests Cloud chat failed 3/4 due to these stale expectations; reconnect passed 5/5. Placement's pre-operation ordering assertion also fails independently. Scoped syntax, localization defaults, feature flags and namespace lint pass. The workspace package-group finding is unchanged base debt. Exact-head fleet verification follows the normal push; no local builds. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: cmux-bot[bot] <348531757+cmux-bot[bot]@users.noreply.github.com>
This branch was previously deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Leo, 2026-10-31, on a chat on his own Cloud machine refused with "Agent chats cannot be started from this Mac on a team VM yet.": "let's do option 1" / "but what's the sharing flow? we can't simply block always. we need to be able to get stuff running asap."
Why
In the DEV build on production, Leo picked his own machine (fs-firstsend-exercise, which he created) and sent a chat. It was refused with
agent_session.team_vm_blocked. Every machine on his account sits on a Stack team, so cmux-host writesteamto/etc/cmux/vm-kind. cmux-tui's start gate refused a team record before it read the caller's word.The caller's word is already right. Since #28788 (main) and #28789, the Cloud API's attach answer is
vmKind: "owner"only for the machine's creator, team machines included. Every other teammate getsteam. The app sendsvm_kind: "owner"per start only on that answer (#26323). The guest's team record was the only thing still blocking.What changes
AgentSessionStarts::host_gate(cmux-tui-core): a team VM now lets a call through on the caller'svm_kind: "owner", the same as any other Cloud VM. The same gate guards three calls:agent-session-start,agent-session-trustand the chat move-in (agent-transfer-receive/-finish).What still refuses:
agent_session.team_vm_blocked.agent_session.host_unverified.owneris still refused on any host.No new capability: the param and its meaning are unchanged; only the team record no longer overrides it. The app bundles and pushes its own cmux-tui to the VM, so the next DEV or nightly build carries this. Nothing to deploy.
Risk: the creator's own chat on a team machine now runs there. The VM boundary (unsandboxed at the VM) already followed that same owner answer (#28788), so this adds nothing new on that axis. Teammates, the shared case #26323 protects, still can't start chats there; that goes to the grant flow (a later PR: "Share machine…", with grants in the attach answer).
Prior art: #26323 (the boundary), #26330, #28479 and #28788 (the owner answer for the creator on a team), #28613 (open, Codex on owner VMs; it doesn't touch
host_gate's team arm).Which link
The app's default link is classic (
CloudConfiguration.linkSource = .legacy:/api/vm/{id}/attach-endpoint, web deployed from main), and there #28788 answersownerto the creator. That is Leo's DEV build, so this PR is all his case needs. The app-server link (CMUX_NEXT_CLOUD_LINK=app, cmux-apicallerVmKind) still answersteamto a shared-team creator until #28789 (open, another lane) lands. Until then that path stays refused, as it is today.Review: router-review SHIP at 8ec04cd (gpt-6.1-sol). Its one follow-up (P1) is the app-server link above, which #28789 covers.
Tests
a_call_on_a_cloud_vm_needs_the_callers_owner_word(unit): a team VM with the owner word goes on; without it, it is refused.a_cloud_vm_start_needs_the_callers_owner_word_not_the_vms_record(CLI, real daemon with ateamrecord):ownergets past the host gate (next comesuntrusted_folder); no word andteamgiveteam_vm_blocked.agent_session_trust_on_a_cloud_vm_needs_the_callers_owner_word: the same on a team VM for trust.cmux-ci test --setup rust, job 1382a4dc7688347c089972e8, at 8ec04cd):cargo fmt --check; coreagent_session_start(1) andagent_transfer(48); CLIagent_session_st*(37) andagent_session_trust(2). All pass.No UI change.
Agent session: agent session
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Allows a machine's creator to start chats on their own team Cloud VM from the app; previously the start gate refused it with
agent_session.team_vm_blockedeven when the caller sent the correctvm_kind: "owner"word.agent-session-start,agent-session-trust, and chat move-in now honors the caller'svm_kind: "owner"on team VMs, matching the Cloud API's per-caller answer that grantsownerto the machine's creator only.agent_session.team_vm_blockedon team VMs,agent_session.host_unverifiedon other Cloud VMs.Written for commit f14d2ba. Summary will update on new commits.