Repository navigation
Composer Cloud: a chat starting in Cloud shows its progress under the message - #26921
teamleaderleo wants to merge 7 commits into
Conversation
|
Owned by an agent session · session |
… message, as metadata The card shows the message, a spinner with the step, and the folder, machine, secrets and network as the host learns them (a cloudStartProgress push keyed by the start), never a modal. Three layouts behind the cloud-start-look experiment (chips, fact rows, step list), compared in the gallery's agent-pane.cloud-start. On the New Tab page it shows over the box, without the bubble. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
…r, opening) as the start reaches it cloud.startChat pushes a cloudStartProgress event keyed by the page's send before it takes a machine, copies the folder and opens the chat; the shared page host hands it to the bridge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
…6.6 could not type the map) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
…led card goes when the person picks another place Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
c6ad6d4 to
072682b
Compare
|
Review (codex gpt-6-astra): SHIP at 072682b Three rounds, run with high effort in fast mode:
Known limit: secrets and network show once the host pushes them. Neither has a source on the client yet; it comes from the derived environment on the server side. At this head:
Held per the body's HOLD line, since it is Swift and stacked. |
|
Found 42 test failures on Blacksmith runners: Failures
...and 32 more test failures. View all on Blacksmith
|
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Probably yours: CI failed on
Failures:
Matched log linesNot re-run automatically: Written by
Agents: |
…ne does not load) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
|
Review (codex gpt-6-astra): SHIP at bb706c7 A delta review of 072682b..bb706c7, given the full changed file. The Checked on cmux-ci (Linux pool): |
…the seed's Cloud runner for Xcode 26.6 next-review's P2: CloudStartChat built the remote seed with the harness and prompt only, so the model the page picked was dropped. AgentPaneCloudStart.seed(cwd:) now builds it with the model too, with a test. The request carries no effort, so there is none to forward. AgentPageChats.seed's Cloud runner is written out with its type, as #26921 does: #26921 found Xcode 26.6 could not type the map form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504
|
Folded into #28686 (original commits kept, on current feat-cmux-next). Review and landing continue there; the owner closes this one. |
…Cloud fold CloudStartChat takes #28111's owner's version (each send its own copy, a retry stays on its machine and opens without copying again) with #26921's progress steps added back. CloudStartChatDestinationsTests goes: it tested this lane's Destinations, which #28111's owner replaced (CloudStartChatMachineTests covers theirs). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504
|
Owned by an agent session · session · took over from an earlier session (its owning session is closed) |
* cmux NEXT Cloud: pick a chat's machine from its folder (repo, ref, size, task kind), sent as autosize A chat sent to Cloud no longer needs a machine or size choice: CloudWorkPick reads the chat's folder (repo key and GitHub repo from the remote, branch and whether it is pushed, git object size, root files, task kind, .cmux/machine.toml, Codex broker) and Move to Cloud with no machine to reuse, and New Cloud Machine from a chat, send its autosize with POST /api/vm. The answer's sizePick stays on the machine's session for the hand-off. Behind Labs preview features. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud pick: clone the upstream's branch name, no GitHub repo from a local remote, no pick on the app-server link Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud: cloud.startChat, a new chat's first send started in Cloud with no machine or environment prompt The page's Send with Cloud picked asks the host (`cloud.startChat {task, cwd, harness?, model?, key}`), with Sandboxed's guards (a new chat, the Send's gesture, the replacements held, one at a time; both now share AgentPaneHandOff). The App takes a Cloud machine as Move to Cloud does (a new one sized by CloudChatPick), copies the folder with Move to Cloud's sync, opens the chat on the machine with the prompt seeded as the person's, and closes this Mac's unstarted tab. Behind Labs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the page's folder is optional; the tab's own folder otherwise Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: a started chat keeps the pane's hold; the folder must exist; the hand-off body is main-actor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: only a chat on this Mac starts one; the App checks the tab's daemon is local Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the machine's chat starts on the picked model; type the seed's Cloud runner for Xcode 26.6 next-review's P2: CloudStartChat built the remote seed with the harness and prompt only, so the model the page picked was dropped. AgentPaneCloudStart.seed(cwd:) now builds it with the model too, with a test. The request carries no effort, so there is none to forward. AgentPageChats.seed's Cloud runner is written out with its type, as #26921 does: #26921 found Xcode 26.6 could not type the map form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: a retry opens the same tab on the machine; the folder check reads off the main thread next-review's BLOCK at b3389d1 (Codex gpt-6-astra): CloudStartChat opened the machine's chat tab with a fresh creation key, so a retry of the same send after a lost answer could make a second chat and send the prompt twice. The tab's key is now the send's own (AgentPaneCloudStart.tabKey), with a test that a retry's key matches and another send's does not. The folder check (FileManager.fileExists) ran on the main actor; it now runs in a @Concurrent helper (guardrails main-blocking). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: copy only a folder the pane may name, each send into its own copy on the machine Two blocking findings from the Codex review of #28686, both in this PR's code: - The page named the folder whose tree is copied to Cloud, and the host only checked that it was absolute. A page script could name any folder on this Mac. The hand-off now takes the folder's canonical path (realpath, off the main actor) only when it is inside one of the pane's roots by components, the same roots AcpmuxPathPolicy uses for a chat that starts here: the pane's own and the New Tab scan's, never home or above it, plus the folders the person added. Anything else is refused with transport.path_outside_roots before the hold and the gesture. No folder from the page still means the tab's own folder, which the host reads. - Every Cloud start from the same folder synced into the same folder on a reused machine, and Move to Cloud's sync overwrites every file the machine changed, so a second Cloud chat could write over the first one's work. A start now copies into its own place under the work root (chats/<send key>). A retry of the same send lands in the same copy. Tests: a folder outside the roots, a link out of a root, a `..` path out of it, a missing folder, the disk's root, home, and a folder under home when the pane's folder is home are all refused and never reach the runner. The root's own folder still starts with its canonical path, and a send's place is its own and stable for a retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-672a743921bc7917cca7 * fix(cloud.startChat): a first send takes this person's free machine, and its retry stays there Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". - The machine: never the team's first connected one (often someone's busy lane VM). A machine this person created that is free (no chat open, or idle-paused) or named for chats (cloud-chats[-N]), else a new one named cloud-chats. Lane-pool VMs (fs-lane-N, lane-vm-N) are never picked. - #28845: CloudStartChat.Destinations pins each send key to the machine its first try took (newest 64, kept in the app's defaults), so a retry names that machine and its tab key gets the first try's tab back instead of a second chat with the prompt on another machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(acpmux): a chat's first send that a revoked OAuth token failed goes again once, 2 s later Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". On a fresh Cloud VM the first Claude call failed once with "Failed to authenticate: OAuth token revoked" and the same call 2 s later ran (cmux#28111 hand-walk, gap 5). - claude_auth::is_revoked_token: only a revoked token, never expired/missing sign-in or an outage. - hub/auto_resume/first_send.rs: on the chat's first turn only, and only for a prompt of its own (never a ~resume- attempt), the turn is resent once as P~resume-1 after 2 s through the Retry button's resend (retry_turn.rs resend_turn), under the chat's continuation mark, so Stop, close, a move or a person's prompt during the wait keep it from going. A retry that fails the same way is shown as before. Decisions are logged (first_send_retry, auto_resume_skipped). - daemon/cloud_handoff.rs: such a turn is not reported failed before its retry is decided. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): copy only a checked upload root, never copy a finished send again, create under the send's key router-review BLOCK at 8b117be (gpt-6-astra), all three findings: - [P1] The copy uploads the Git working copy that holds the page's folder. The pane now checks that upload root against its roots too (AgentPaneHandOff), hands it on as AgentPaneCloudStart.uploadRoot, and the App copies only that folder (CloudStartChat.uploads): a grant of /repo/paint never uploads /repo. - [P1] Destinations records, per send key and machine, that the send's copy finished. A retry whose copy finished opens its chat by its tab key without pushing again, which would overwrite what the chat already changed there. - [P2] A new machine for a send is created under AgentPaneCloudStart.createKey (from the send key), so a retry after a lost create answer gets the same machine, never a second VM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): no await inside the upload root check's autoclosure (fleet compile) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): not behind Labs; its machine is sized for the chat without Labs Leo (2026-10-30), on cloud.startChat refusing with Labs off: "that seems dumb. i dont like putting so much stuff in labs". The labs_off refusal goes (cloud_disabled and not_signed_in stay), and the send's create reads the chat's size pick without Labs. Move to Cloud and the setup wizard keep their Labs-gated pick (requiresLabs defaults to true). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud sizing): the chat's size pick is never behind Labs Leo (2026-10-30): "WHAT GOOD REASON DO WE HAVE IN THE FIRST PLACE TO KEEP THIS SHIT IN FUCKING LABS IF I FUCKING ASKED FOR THESE FUCKING FEATURES". CloudChatPick.read no longer checks Labs, so drop the requiresLabs parameter added in 4c71cc8: every caller (cloud.startChat, Move to Cloud, the setup wizard) sizes the chat's machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): a send with no folder copies only the tab's own folder, never a working copy above it router-review BLOCK at 39364d9 (gpt-6-astra): with no cwd, the tab's folder was copied as CloudMoveFolder expands it, so a tab in /repo/project uploaded /repo, which no scope check covered. Now such a send copies only when that folder is its own upload root. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): a scanned project is copied only once the person picked it router-review BLOCK at 10fb9a8 (gpt-6-astra): folderInScope took the New Tab page's scan and open folders (gestureRoots) as roots on the Send's gesture alone, so a page could copy any scanned project off this Mac without the person picking it. Only the pane's own roots and the folders the person added count now. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): a retry whose record is gone copies into a new folder, never over a started chat router-review BLOCK at ddd40fa (gpt-6-astra): Destinations keeps the newest 64 sends, so a retry of an older one lost its finished-copy record and pushed into chats/<key> again, over what the chat there had changed. Each send's copy folder (chats/<key>/<id>) is now kept before the copy starts: a retry reuses its own, and one with no record gets a fresh folder, so a copy never writes over a chat that started (its tab key still gets that chat's tab back). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): the Cloud app server's link is refused before any machine is created router-review BLOCK at 3b0af5d (gpt-6-astra), and #28979: on the app server's link a send created a VM and then CloudMove refused its appLink session (the CLIs need their own socket), leaving an unused VM. cloud.startChat now refuses that link up front (`unavailable`). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): a send with no folder never copies the home folder or a folder above it router-review BLOCK at a090a49 (gpt-6-astra): the tab's own folder (no cwd) skipped every scope check, and isTooBroad refuses only / and the exact home folder, so a tab in /Users would upload every readable home folder. The fallback is now refused when it, or its canonical path, is the home folder or above it (AgentHome.isHomeOrAbove), as a page-named folder already is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * acpmux: read the first-send retry's turn fields with get/set, no indexing The panic ratchet counts serde_json Value indexing as indexing_slicing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: take and copy to a machine only of the account the send began in Router review at 2a315af (blocking): after a team switch the previous team's machines stay in the store until the new list lands, with the same user, so the pick could copy the folder to the previous team's VM. The send now refreshes until the list is the current account's, pins its machine under its account, and rechecks the account before copying. Test: aSendNeverGoesToAMachineOfTheTeamItWasNotSentIn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: create in the send's team, recheck the account before admitting and after the copy Router review at 2208632 (blocking): a classic create read the app's team again on each try, so a team switch during a slow create could make the VM in the other team; and the account was not checked after a long copy. The create now fixes the send's team (CloudMachineRequest.team, honoured by the classic create via CloudService.createTeam), checks the account before the machine joins the list, and the chat opens only if the account is unchanged after the copy. Test: aNewMachineIsCreatedUnderTheSendsKeyInTheSendsTeam. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: reach AcpmuxPathPolicy.canonical through public AgentHome.canonical The /Users fix (d76a98d) called the CmuxNextAgentPane-internal enum from CmuxNextApp, so the app target did not compile. Same fix as the DEV integration commit a36789a3. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: count a creatorless machine as yours only by this account's sends; one ledger entry per send Router review at 020b012 (blocking): every kept send's machine counted as the person's own when the server names no creator, across users signed in on this Mac. Now only this account's sends (Destinations.machines(of:)) do. The copy record uses the same account-scoped key as the pin, so a send's pin and copy are one entry and are evicted together (review P2). Test: onlyThisAccountsSendsMakeAMachineWithNoCreatorItsOwn. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: walk up to the upload root in bounded steps, no while-true check-concurrency flags an unbounded loop in AgentPaneCloudStart.uploadRoot(of:). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: read .git through the checked FileManager seam Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * arch-ratchet: app_lines exception for cloud.startChat until its logic moves to Rust Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * guardrails: dated reviewed exceptions for a new App file (guardrail-exceptions.json); cloud.startChat's two files until the Rust move The app-size rule's only escape was CMUX_GUARDRAILS_SKIP_REASON, which CI never reads. guardrails.excepted reads plans/cmux-next/guardrail-exceptions.json at the pushed head: an entry with arch-ratchet's fields (independent receipt, expiry) turns one file's app-size or app-type hits into a warning. Entries for CloudStartChat.swift and CloudStartChat+Machine.swift, expiring 2026-11-21, owned by the cloud.startChat Rust move. Test: test_a_dated_reviewed_exception_turns_a_new_app_file_into_a_warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * guardrails: read the exceptions file only when an app-size or app-type hit could be excused Router review at 7b6cb60 (blocking): the unconditional read added a git process to every push, breaking test_a_typical_push_runs_git_a_fixed_number_of_times. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: refuse a working copy whose git folders lie outside the pane's roots Router review at 7149eba (blocking): a .git file (linked worktree, --separate-git-dir) can name a repository outside the pane's roots, and cmux link sync push copies its objects and refs. The send now resolves the working copy's git folder and its commondir (AgentPaneCloudStart.gitFolders) and refuses unless each is in scope. Test: aWorkingCopyWhoseGitFolderIsOutsideTheRootsIsNeverCopied. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: a folderless send checks the tab folder's git folders too Router review at 6beb0f2 (blocking): with no cwd the tab's own folder was copied without checking where its .git file or commondir points. Now every git folder must lie inside that folder. Test: aTabsFolderWhoseGitFolderIsElsewhereIsNeverCopied. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: pick and pin only machines the current account's list named; guardrail exception dates are real dates Router review at c1d0cf8 (blocking): after a team switch the store keeps the previous team's sessions while an omission waits on a newer read, so the pick could take one of them. CloudService.listedMachineIDs holds the machines the loaded list named (and ones made since); candidates come only from it, and a pin stands while listed, or while only the store has it. Test: aPinStandsOnlyOnThisAccountsList. Review P2: exception dates parse as calendar dates. 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>
…d start progress (fold of #26801, #26920, #26921) (#28686) * cmux NEXT Cloud: pick a chat's machine from its folder (repo, ref, size, task kind), sent as autosize A chat sent to Cloud no longer needs a machine or size choice: CloudWorkPick reads the chat's folder (repo key and GitHub repo from the remote, branch and whether it is pushed, git object size, root files, task kind, .cmux/machine.toml, Codex broker) and Move to Cloud with no machine to reuse, and New Cloud Machine from a chat, send its autosize with POST /api/vm. The answer's sizePick stays on the machine's session for the hand-off. Behind Labs preview features. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud pick: clone the upstream's branch name, no GitHub repo from a local remote, no pick on the app-server link Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud: cloud.startChat, a new chat's first send started in Cloud with no machine or environment prompt The page's Send with Cloud picked asks the host (`cloud.startChat {task, cwd, harness?, model?, key}`), with Sandboxed's guards (a new chat, the Send's gesture, the replacements held, one at a time; both now share AgentPaneHandOff). The App takes a Cloud machine as Move to Cloud does (a new one sized by CloudChatPick), copies the folder with Move to Cloud's sync, opens the chat on the machine with the prompt seeded as the person's, and closes this Mac's unstarted tab. Behind Labs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the page's folder is optional; the tab's own folder otherwise Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: a started chat keeps the pane's hold; the folder must exist; the hand-off body is main-actor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: only a chat on this Mac starts one; the App checks the tab's daemon is local Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer: Cloud as where a new chat runs, a row at the top of the environment picker's Cloud section Behind Labs. Picking it makes the first send call cloud.startChat; attachments are refused on Cloud for now. Gallery: four states of the row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a Cloud pick not offered now is refused, never sent here; picking Cloud drops a saved environment and refocuses the prompt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: tests for the picker's Cloud row, a saved environment dropped by a Cloud pick, and a refused send keeping its prompt The not-offered refusal moves into cloudRun.ts so it is tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: format the new-tab test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: the folder a Cloud send copies is the one the chip names, also when the tab inherited home Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Gallery: the two other designs of where a new chat runs, gallery-only, beside the shipped Cloud row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: one start at a time from a page; another Return while it waits starts nothing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Gallery: the switch design's group is a fieldset Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a new chat's run location defaults from its folder's newest chat A folder whose newest chat went to a Cloud machine (a Cloud start or Move to Cloud) opens new chats with Cloud picked; otherwise this Mac, as before. The history is acpmux's chat list: a Cloud chat is matched to the folder by the folder the app's copy made on the machine (CloudMoveFolder remoteName under CloudMoveSetup workRoots). Labs only, and a pick in the pane always wins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a new chat's carried-over Cloud is a default its folder may undo; archived chats are not history Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a carried-over Cloud is marked in the folder default's effect, per chat Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: no change while a Cloud start is out Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: the folder default looks again once a Cloud start ends Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a chat starting here keeps the mode it starts with Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a chat starting in Cloud shows its progress under the message, as metadata The card shows the message, a spinner with the step, and the folder, machine, secrets and network as the host learns them (a cloudStartProgress push keyed by the start), never a modal. Three layouts behind the cloud-start-look experiment (chips, fact rows, step list), compared in the gallery's agent-pane.cloud-start. On the New Tab page it shows over the box, without the bubble. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: the host tells the page's card each step (machine, folder, opening) as the start reaches it cloud.startChat pushes a cloudStartProgress event keyed by the page's send before it takes a machine, copies the folder and opens the chat; the shared page host hands it to the bridge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start card: spacing and sizes on the design token scale Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * AgentPageChats: the Cloud start runner's pane closure, typed (Xcode 26.6 could not type the map) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: the host pushes the folder and the machine's size; a failed card goes when the person picks another place Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: format Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start gallery: the experiment's script has one step (an empty one does not load) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the machine's chat starts on the picked model; type the seed's Cloud runner for Xcode 26.6 next-review's P2: CloudStartChat built the remote seed with the harness and prompt only, so the model the page picked was dropped. AgentPaneCloudStart.seed(cwd:) now builds it with the model too, with a test. The request carries no effort, so there is none to forward. AgentPageChats.seed's Cloud runner is written out with its type, as #26921 does: #26921 found Xcode 26.6 could not type the map form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: a retry opens the same tab on the machine; the folder check reads off the main thread next-review's BLOCK at b3389d1 (Codex gpt-6-astra): CloudStartChat opened the machine's chat tab with a fresh creation key, so a retry of the same send after a lost answer could make a second chat and send the prompt twice. The tab's key is now the send's own (AgentPaneCloudStart.tabKey), with a test that a retry's key matches and another send's does not. The folder check (FileManager.fileExists) ran on the main actor; it now runs in a @Concurrent helper (guardrails main-blocking). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: copy only a folder the pane may name, each send into its own copy on the machine Two blocking findings from the Codex review of #28686, both in this PR's code: - The page named the folder whose tree is copied to Cloud, and the host only checked that it was absolute. A page script could name any folder on this Mac. The hand-off now takes the folder's canonical path (realpath, off the main actor) only when it is inside one of the pane's roots by components, the same roots AcpmuxPathPolicy uses for a chat that starts here: the pane's own and the New Tab scan's, never home or above it, plus the folders the person added. Anything else is refused with transport.path_outside_roots before the hold and the gesture. No folder from the page still means the tab's own folder, which the host reads. - Every Cloud start from the same folder synced into the same folder on a reused machine, and Move to Cloud's sync overwrites every file the machine changed, so a second Cloud chat could write over the first one's work. A start now copies into its own place under the work root (chats/<send key>). A retry of the same send lands in the same copy. Tests: a folder outside the roots, a link out of a root, a `..` path out of it, a missing folder, the disk's root, home, and a folder under home when the pane's folder is home are all refused and never reach the runner. The root's own folder still starts with its canonical path, and a send's place is its own and stable for a retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-672a743921bc7917cca7 * fix(cloud.startChat): a first send takes this person's free machine, and its retry stays there Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". - The machine: never the team's first connected one (often someone's busy lane VM). A machine this person created that is free (no chat open, or idle-paused) or named for chats (cloud-chats[-N]), else a new one named cloud-chats. Lane-pool VMs (fs-lane-N, lane-vm-N) are never picked. - #28845: CloudStartChat.Destinations pins each send key to the machine its first try took (newest 64, kept in the app's defaults), so a retry names that machine and its tab key gets the first try's tab back instead of a second chat with the prompt on another machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(acpmux): a chat's first send that a revoked OAuth token failed goes again once, 2 s later Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". On a fresh Cloud VM the first Claude call failed once with "Failed to authenticate: OAuth token revoked" and the same call 2 s later ran (cmux#28111 hand-walk, gap 5). - claude_auth::is_revoked_token: only a revoked token, never expired/missing sign-in or an outage. - hub/auto_resume/first_send.rs: on the chat's first turn only, and only for a prompt of its own (never a ~resume- attempt), the turn is resent once as P~resume-1 after 2 s through the Retry button's resend (retry_turn.rs resend_turn), under the chat's continuation mark, so Stop, close, a move or a person's prompt during the wait keep it from going. A retry that fails the same way is shown as before. Decisions are logged (first_send_retry, auto_resume_skipped). - daemon/cloud_handoff.rs: such a turn is not reported failed before its retry is decided. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): copy only a checked upload root, never copy a finished send again, create under the send's key router-review BLOCK at 8b117be (gpt-6-astra), all three findings: - [P1] The copy uploads the Git working copy that holds the page's folder. The pane now checks that upload root against its roots too (AgentPaneHandOff), hands it on as AgentPaneCloudStart.uploadRoot, and the App copies only that folder (CloudStartChat.uploads): a grant of /repo/paint never uploads /repo. - [P1] Destinations records, per send key and machine, that the send's copy finished. A retry whose copy finished opens its chat by its tab key without pushing again, which would overwrite what the chat already changed there. - [P2] A new machine for a send is created under AgentPaneCloudStart.createKey (from the send key), so a retry after a lost create answer gets the same machine, never a second VM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): no await inside the upload root check's autoclosure (fleet compile) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud start): small-radius chips; picker test picks New Cloud Machine, not the Cloud row The Cloud start card's chips were 999px capsules, which agent-pane-no-capsules refuses; they are 4px small-radius rects now. The Sandboxed picker test found the Cloud row's icon (data-kind="cloud", no data-mode) before New Cloud Machine; it now matches the row element itself. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud start): the composer takes no edits while a Cloud start is out The review of #28686 at 563e8aa blocked on this: the composer stayed editable while the machine booted, later Returns were ignored, and on success the host closed the tab with only the first prompt sent, so text or files added meanwhile were lost. Now the box is inert while the start's card says starting (both the chat composer and the New Tab box), and the pane-wide paste-anywhere takes nothing then. A failed start ends it, and the prompt is still in the composer to edit and send again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud start): a Cloud start's copy counts as its folder's history The review of #28686 at 0638b7f blocked on this: a Cloud start copies into <work root>/chats/<key>/<attempt>/<name>-<hash>, while the folder default only matched <work root>/<name>-<hash>, so after a Cloud start the next chat in that folder defaulted to This Mac. The matcher now also takes the start's own place out of the path (withoutStartPlace). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * style: runLocationDefault test fits the formatter's line Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud start): no typing, paste or file drop reaches the composer while a Cloud start is out The review at f6094ea found two routes the inert box did not cover: New Tab's type-anywhere still edited the field, and the page-wide file drop (and paste) still staged attachments, which the tab then closed without sending. The intake takes a `locked` option (paste and drop stage nothing and the drop overlay stays hidden), and New Tab's type-anywhere and paste-anywhere do nothing while `cloudStarting`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud start): Do not work in a project sends nothing to Cloud; dictation writes nothing during a start The review at 53d7adf blocked on two: - With Cloud picked and Do not work in a project, the send named no folder and the host fell back to the tab's inherited folder, copying a repository the person had just said not to work in. New Tab now refuses that send ("Cloud isn't available for this chat") and keeps the prompt. #29109's folderless start (`home: true`) is the way such a chat goes to Cloud. - Dictation still wrote into the locked composer. Its field getter gives no field while a Cloud start is out, and New Tab's writeText does nothing then. 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>
…arry #29109) (#29669) * cmux NEXT Cloud: pick a chat's machine from its folder (repo, ref, size, task kind), sent as autosize A chat sent to Cloud no longer needs a machine or size choice: CloudWorkPick reads the chat's folder (repo key and GitHub repo from the remote, branch and whether it is pushed, git object size, root files, task kind, .cmux/machine.toml, Codex broker) and Move to Cloud with no machine to reuse, and New Cloud Machine from a chat, send its autosize with POST /api/vm. The answer's sizePick stays on the machine's session for the hand-off. Behind Labs preview features. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud pick: clone the upstream's branch name, no GitHub repo from a local remote, no pick on the app-server link Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud: cloud.startChat, a new chat's first send started in Cloud with no machine or environment prompt The page's Send with Cloud picked asks the host (`cloud.startChat {task, cwd, harness?, model?, key}`), with Sandboxed's guards (a new chat, the Send's gesture, the replacements held, one at a time; both now share AgentPaneHandOff). The App takes a Cloud machine as Move to Cloud does (a new one sized by CloudChatPick), copies the folder with Move to Cloud's sync, opens the chat on the machine with the prompt seeded as the person's, and closes this Mac's unstarted tab. Behind Labs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the page's folder is optional; the tab's own folder otherwise Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: a started chat keeps the pane's hold; the folder must exist; the hand-off body is main-actor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: only a chat on this Mac starts one; the App checks the tab's daemon is local Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer: Cloud as where a new chat runs, a row at the top of the environment picker's Cloud section Behind Labs. Picking it makes the first send call cloud.startChat; attachments are refused on Cloud for now. Gallery: four states of the row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a Cloud pick not offered now is refused, never sent here; picking Cloud drops a saved environment and refocuses the prompt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: tests for the picker's Cloud row, a saved environment dropped by a Cloud pick, and a refused send keeping its prompt The not-offered refusal moves into cloudRun.ts so it is tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: format the new-tab test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: the folder a Cloud send copies is the one the chip names, also when the tab inherited home Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Gallery: the two other designs of where a new chat runs, gallery-only, beside the shipped Cloud row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: one start at a time from a page; another Return while it waits starts nothing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Gallery: the switch design's group is a fieldset Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a new chat's run location defaults from its folder's newest chat A folder whose newest chat went to a Cloud machine (a Cloud start or Move to Cloud) opens new chats with Cloud picked; otherwise this Mac, as before. The history is acpmux's chat list: a Cloud chat is matched to the folder by the folder the app's copy made on the machine (CloudMoveFolder remoteName under CloudMoveSetup workRoots). Labs only, and a pick in the pane always wins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a new chat's carried-over Cloud is a default its folder may undo; archived chats are not history Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a carried-over Cloud is marked in the folder default's effect, per chat Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: no change while a Cloud start is out Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: the folder default looks again once a Cloud start ends Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a chat starting here keeps the mode it starts with Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a chat starting in Cloud shows its progress under the message, as metadata The card shows the message, a spinner with the step, and the folder, machine, secrets and network as the host learns them (a cloudStartProgress push keyed by the start), never a modal. Three layouts behind the cloud-start-look experiment (chips, fact rows, step list), compared in the gallery's agent-pane.cloud-start. On the New Tab page it shows over the box, without the bubble. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: the host tells the page's card each step (machine, folder, opening) as the start reaches it cloud.startChat pushes a cloudStartProgress event keyed by the page's send before it takes a machine, copies the folder and opens the chat; the shared page host hands it to the bridge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start card: spacing and sizes on the design token scale Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * AgentPageChats: the Cloud start runner's pane closure, typed (Xcode 26.6 could not type the map) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: the host pushes the folder and the machine's size; a failed card goes when the person picks another place Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: format Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start gallery: the experiment's script has one step (an empty one does not load) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the machine's chat starts on the picked model; type the seed's Cloud runner for Xcode 26.6 next-review's P2: CloudStartChat built the remote seed with the harness and prompt only, so the model the page picked was dropped. AgentPaneCloudStart.seed(cwd:) now builds it with the model too, with a test. The request carries no effort, so there is none to forward. AgentPageChats.seed's Cloud runner is written out with its type, as #26921 does: #26921 found Xcode 26.6 could not type the map form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: a retry opens the same tab on the machine; the folder check reads off the main thread next-review's BLOCK at b3389d1 (Codex gpt-6-astra): CloudStartChat opened the machine's chat tab with a fresh creation key, so a retry of the same send after a lost answer could make a second chat and send the prompt twice. The tab's key is now the send's own (AgentPaneCloudStart.tabKey), with a test that a retry's key matches and another send's does not. The folder check (FileManager.fileExists) ran on the main actor; it now runs in a @Concurrent helper (guardrails main-blocking). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: copy only a folder the pane may name, each send into its own copy on the machine Two blocking findings from the Codex review of #28686, both in this PR's code: - The page named the folder whose tree is copied to Cloud, and the host only checked that it was absolute. A page script could name any folder on this Mac. The hand-off now takes the folder's canonical path (realpath, off the main actor) only when it is inside one of the pane's roots by components, the same roots AcpmuxPathPolicy uses for a chat that starts here: the pane's own and the New Tab scan's, never home or above it, plus the folders the person added. Anything else is refused with transport.path_outside_roots before the hold and the gesture. No folder from the page still means the tab's own folder, which the host reads. - Every Cloud start from the same folder synced into the same folder on a reused machine, and Move to Cloud's sync overwrites every file the machine changed, so a second Cloud chat could write over the first one's work. A start now copies into its own place under the work root (chats/<send key>). A retry of the same send lands in the same copy. Tests: a folder outside the roots, a link out of a root, a `..` path out of it, a missing folder, the disk's root, home, and a folder under home when the pane's folder is home are all refused and never reach the runner. The root's own folder still starts with its canonical path, and a send's place is its own and stable for a retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-672a743921bc7917cca7 * fix(cloud.startChat): a first send takes this person's free machine, and its retry stays there Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". - The machine: never the team's first connected one (often someone's busy lane VM). A machine this person created that is free (no chat open, or idle-paused) or named for chats (cloud-chats[-N]), else a new one named cloud-chats. Lane-pool VMs (fs-lane-N, lane-vm-N) are never picked. - #28845: CloudStartChat.Destinations pins each send key to the machine its first try took (newest 64, kept in the app's defaults), so a retry names that machine and its tab key gets the first try's tab back instead of a second chat with the prompt on another machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(acpmux): a chat's first send that a revoked OAuth token failed goes again once, 2 s later Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". On a fresh Cloud VM the first Claude call failed once with "Failed to authenticate: OAuth token revoked" and the same call 2 s later ran (cmux#28111 hand-walk, gap 5). - claude_auth::is_revoked_token: only a revoked token, never expired/missing sign-in or an outage. - hub/auto_resume/first_send.rs: on the chat's first turn only, and only for a prompt of its own (never a ~resume- attempt), the turn is resent once as P~resume-1 after 2 s through the Retry button's resend (retry_turn.rs resend_turn), under the chat's continuation mark, so Stop, close, a move or a person's prompt during the wait keep it from going. A retry that fails the same way is shown as before. Decisions are logged (first_send_retry, auto_resume_skipped). - daemon/cloud_handoff.rs: such a turn is not reported failed before its retry is decided. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): copy only a checked upload root, never copy a finished send again, create under the send's key router-review BLOCK at 8b117be (gpt-6-astra), all three findings: - [P1] The copy uploads the Git working copy that holds the page's folder. The pane now checks that upload root against its roots too (AgentPaneHandOff), hands it on as AgentPaneCloudStart.uploadRoot, and the App copies only that folder (CloudStartChat.uploads): a grant of /repo/paint never uploads /repo. - [P1] Destinations records, per send key and machine, that the send's copy finished. A retry whose copy finished opens its chat by its tab key without pushing again, which would overwrite what the chat already changed there. - [P2] A new machine for a send is created under AgentPaneCloudStart.createKey (from the send key), so a retry after a lost create answer gets the same machine, never a second VM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): no await inside the upload root check's autoclosure (fleet compile) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * feat(cloud): Start New Chats In: This Mac / Cloud (agentPane.newChatsIn) Leo, 2026-10-31: "whenever i start a chat it should be able to send me to cloud autommatically". A setting, off (This Mac) by default; set to Cloud, a new chat's run location defaults to Cloud and its first send runs cloud.startChat. The composer's environment picker (This Mac / Cloud) overrides it for one chat. A chat with no project starts in the machine's own folder with nothing copied. Cloud's start is no longer behind Labs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * chore(settings): regenerate exports for agentPane.newChatsIn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud): Sandboxed stays behind Labs when only the setting offers Cloud; no copy step for a no-project start Review BLOCK at 4f6d4a5 (router-review, gpt-6-astra): [P1] Start New Chats In: Cloud exposed Sandboxed with Labs off; [P2] a no-project start's step list showed the copy step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * test(cloud): the Cloud-only picker test takes KeyboardEvent from its DOM Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud start): a no-project start compiles, rechecks the account, and never copies agent-home The review of #29109 at 21b19e1 blocked on three: - runHome called machine(for:invocation:pick:) without the `account:` base added, so the target did not compile. - runHome did not check the account after the machine connected; it now does, as a start with a folder does, so an account switch meanwhile opens nothing on the old account's machine. - cloudStartFolder sent a no-project chat's private agent-home folder as a project to copy; it is `home` now (sessionList.ts isAgentHome). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * refactor(cloud start): a no-project start shares run's open step; the chats machine names move to CmuxNextAgentPane runHome duplicated run's tail (open the chat on the machine, select it, close this Mac's tab); both now call one `open(_:tab:on:cwd:)`. With the pure machine-name rules (chatsName, isMarkedForChats, isLanePool, newMachineName) moved to CmuxNextAgentPane beside #29566's Step and sizeText, CmuxNextApp is 8 lines smaller than base, so arch-ratchet's app_lines row (which #28686 tripped) holds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * refactor(cloud start): drop RunModeRows.cloudOnly; Sandboxed is not behind Labs since #29059 cloudOnly kept Sandboxed out of the picker when only the setting offered Cloud, because the host refused sandbox.run without Labs. #29059 took that gate out, so nothing set it and the guard was unreachable (the review at 01d58a2). The picker is base's again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud start): newChatsIn has an agent policy; a tab on another machine never defaults to Cloud The review at 3c558fc blocked on two: - agentPane.newChatsIn was in neither agent-policy table, so SettingsSchemaExportTests.everyKeyHasAnExplicitAgentPolicy failed. It is refused to agents as .privacy: it decides whether a chat's project is copied to a Cloud machine. - With Start New Chats In: Cloud, a fresh SSH or Cloud tab defaulted to Cloud, and its first send went to cloud.startChat, which the host refuses there. The run-location default now applies only to tabs on this Mac. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * Keep the base streaming test tolerance in Cloud first-send carry Agent-Session: https://cmux.com/deeplink/agent?id=aid-1b76b6a4a44aaf394aea --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…orkspaces reuse and share machines (#29532) * cmux NEXT Cloud: pick a chat's machine from its folder (repo, ref, size, task kind), sent as autosize A chat sent to Cloud no longer needs a machine or size choice: CloudWorkPick reads the chat's folder (repo key and GitHub repo from the remote, branch and whether it is pushed, git object size, root files, task kind, .cmux/machine.toml, Codex broker) and Move to Cloud with no machine to reuse, and New Cloud Machine from a chat, send its autosize with POST /api/vm. The answer's sizePick stays on the machine's session for the hand-off. Behind Labs preview features. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud pick: clone the upstream's branch name, no GitHub repo from a local remote, no pick on the app-server link Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud: cloud.startChat, a new chat's first send started in Cloud with no machine or environment prompt The page's Send with Cloud picked asks the host (`cloud.startChat {task, cwd, harness?, model?, key}`), with Sandboxed's guards (a new chat, the Send's gesture, the replacements held, one at a time; both now share AgentPaneHandOff). The App takes a Cloud machine as Move to Cloud does (a new one sized by CloudChatPick), copies the folder with Move to Cloud's sync, opens the chat on the machine with the prompt seeded as the person's, and closes this Mac's unstarted tab. Behind Labs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the page's folder is optional; the tab's own folder otherwise Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: a started chat keeps the pane's hold; the folder must exist; the hand-off body is main-actor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: only a chat on this Mac starts one; the App checks the tab's daemon is local Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the machine's chat starts on the picked model; type the seed's Cloud runner for Xcode 26.6 next-review's P2: CloudStartChat built the remote seed with the harness and prompt only, so the model the page picked was dropped. AgentPaneCloudStart.seed(cwd:) now builds it with the model too, with a test. The request carries no effort, so there is none to forward. AgentPageChats.seed's Cloud runner is written out with its type, as #26921 does: #26921 found Xcode 26.6 could not type the map form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: a retry opens the same tab on the machine; the folder check reads off the main thread next-review's BLOCK at b3389d1 (Codex gpt-6-astra): CloudStartChat opened the machine's chat tab with a fresh creation key, so a retry of the same send after a lost answer could make a second chat and send the prompt twice. The tab's key is now the send's own (AgentPaneCloudStart.tabKey), with a test that a retry's key matches and another send's does not. The folder check (FileManager.fileExists) ran on the main actor; it now runs in a @Concurrent helper (guardrails main-blocking). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: copy only a folder the pane may name, each send into its own copy on the machine Two blocking findings from the Codex review of #28686, both in this PR's code: - The page named the folder whose tree is copied to Cloud, and the host only checked that it was absolute. A page script could name any folder on this Mac. The hand-off now takes the folder's canonical path (realpath, off the main actor) only when it is inside one of the pane's roots by components, the same roots AcpmuxPathPolicy uses for a chat that starts here: the pane's own and the New Tab scan's, never home or above it, plus the folders the person added. Anything else is refused with transport.path_outside_roots before the hold and the gesture. No folder from the page still means the tab's own folder, which the host reads. - Every Cloud start from the same folder synced into the same folder on a reused machine, and Move to Cloud's sync overwrites every file the machine changed, so a second Cloud chat could write over the first one's work. A start now copies into its own place under the work root (chats/<send key>). A retry of the same send lands in the same copy. Tests: a folder outside the roots, a link out of a root, a `..` path out of it, a missing folder, the disk's root, home, and a folder under home when the pane's folder is home are all refused and never reach the runner. The root's own folder still starts with its canonical path, and a send's place is its own and stable for a retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-672a743921bc7917cca7 * fix(cloud.startChat): a first send takes this person's free machine, and its retry stays there Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". - The machine: never the team's first connected one (often someone's busy lane VM). A machine this person created that is free (no chat open, or idle-paused) or named for chats (cloud-chats[-N]), else a new one named cloud-chats. Lane-pool VMs (fs-lane-N, lane-vm-N) are never picked. - #28845: CloudStartChat.Destinations pins each send key to the machine its first try took (newest 64, kept in the app's defaults), so a retry names that machine and its tab key gets the first try's tab back instead of a second chat with the prompt on another machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(acpmux): a chat's first send that a revoked OAuth token failed goes again once, 2 s later Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". On a fresh Cloud VM the first Claude call failed once with "Failed to authenticate: OAuth token revoked" and the same call 2 s later ran (cmux#28111 hand-walk, gap 5). - claude_auth::is_revoked_token: only a revoked token, never expired/missing sign-in or an outage. - hub/auto_resume/first_send.rs: on the chat's first turn only, and only for a prompt of its own (never a ~resume- attempt), the turn is resent once as P~resume-1 after 2 s through the Retry button's resend (retry_turn.rs resend_turn), under the chat's continuation mark, so Stop, close, a move or a person's prompt during the wait keep it from going. A retry that fails the same way is shown as before. Decisions are logged (first_send_retry, auto_resume_skipped). - daemon/cloud_handoff.rs: such a turn is not reported failed before its retry is decided. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): copy only a checked upload root, never copy a finished send again, create under the send's key router-review BLOCK at 8b117be (gpt-6-astra), all three findings: - [P1] The copy uploads the Git working copy that holds the page's folder. The pane now checks that upload root against its roots too (AgentPaneHandOff), hands it on as AgentPaneCloudStart.uploadRoot, and the App copies only that folder (CloudStartChat.uploads): a grant of /repo/paint never uploads /repo. - [P1] Destinations records, per send key and machine, that the send's copy finished. A retry whose copy finished opens its chat by its tab key without pushing again, which would overwrite what the chat already changed there. - [P2] A new machine for a send is created under AgentPaneCloudStart.createKey (from the send key), so a retry after a lost create answer gets the same machine, never a second VM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): no await inside the upload root check's autoclosure (fleet compile) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): not behind Labs; its machine is sized for the chat without Labs Leo (2026-10-30), on cloud.startChat refusing with Labs off: "that seems dumb. i dont like putting so much stuff in labs". The labs_off refusal goes (cloud_disabled and not_signed_in stay), and the send's create reads the chat's size pick without Labs. Move to Cloud and the setup wizard keep their Labs-gated pick (requiresLabs defaults to true). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud sizing): the chat's size pick is never behind Labs Leo (2026-10-30): "WHAT GOOD REASON DO WE HAVE IN THE FIRST PLACE TO KEEP THIS SHIT IN FUCKING LABS IF I FUCKING ASKED FOR THESE FUCKING FEATURES". CloudChatPick.read no longer checks Labs, so drop the requiresLabs parameter added in 4c71cc8: every caller (cloud.startChat, Move to Cloud, the setup wizard) sizes the chat's machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: the machine pick, the send's pin and keys and the copy move to cmux-tui Leo, 2026-10-30: "AS MUCH RUST AS POSSIBLE INSTEAD OF SWIFT" and "SPEED UP THESE FUCKING ITERATIONS". `cmux link start-chat plan|pin|copy` owns which machine a first send takes, the per-send ledger (now in the state folder, locked), the create/tab/place keys and the copy that never runs twice; the App lists its machines, creates the one asked for, opens the chat and closes its tab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * start-chat: Flags owns its lifetimes; rustfmt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * start-chat: clippy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: one Cloud machine per Mac workspace Leo, 2026-10-30: "we'll want a vm for every single workspace". The plan request now carries the Mac workspace the chat starts in. A send from a workspace goes to that workspace's own machine: the one its first send ran on, while it is listed, the person's and usable (a paused one resumes), else a new one, which pin binds to the workspace. It never takes a free or cloud-chats machine that other workspaces' chats share. A gone, teammate's or failed machine drops the binding. A retry keeps its per-send pin first. The ledger keeps up to 256 workspace bindings apart from the 64 sends and still reads the older sends-only file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud.startChat: read the send's workspace through its optional target Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud.startChat: a send from no workspace never takes a workspace's own machine Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud.startChat: a retry of an older send never takes its workspace back Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud.startChat: the machine pick, the send's pin and keys and the copy move to cmux-tui Leo, 2026-10-30: "AS MUCH RUST AS POSSIBLE INSTEAD OF SWIFT" and "SPEED UP THESE FUCKING ITERATIONS". `cmux link start-chat plan|pin|copy` owns which machine a first send takes, the per-send ledger (now in the state folder, locked), the create/tab/place keys and the copy that never runs twice; the App lists its machines, creates the one asked for, opens the chat and closes its tab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * start-chat: Flags owns its lifetimes; rustfmt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * start-chat: clippy Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * cloud.startChat: carry #29046 onto base with #28111's account and copy rules in Rust #29046 moved the machine pick, the send's pin and keys and the copy to cmux-tui, from a #28111 head that predates 15 of #28111's commits. This brings those rules into the Rust instead of dropping them: - Every send is kept under the account it began in (user and team): its pin, its copy and what makes a creatorless machine the person's own. - The App takes machines only from the list the server answered for that account, keeps a pin to a machine made since (`stored`), creates in the send's team and rechecks the account around the create and the copy. - Each copy goes to a new folder of the send's own, kept before the push: a retry whose record was evicted, one whose answer was lost, or a second copy at once never writes over another (SW-00 #2). - A ledger that cannot be read refuses instead of reading as empty, and its bytes are moved aside as they are (SW-00 #1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * start-chat: the account test expects the one machine team A's sends ran on Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud.startChat: the sends the App kept in its user defaults carry over to cmux-tui once Router review at 83b8b35 (blocking): moving the ledger to cmux-tui dropped the App's own pins on upgrade, so a send in flight could open its prompt on another machine and a creatorless machine stopped counting as the person's. The App hands its entries to `cmux link start-chat import` before the first plan and forgets them once taken in; cmux-tui keeps its own entry for a send it already has and leaves out sends kept under no account. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * start-chat: the place test moves its copy instead of cloning it (clippy redundant_clone) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * start-chat: the import test borrows its keys instead of cloning them (clippy redundant_clone) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud.startChat: one Cloud machine per Mac workspace, on the carried cmux-tui start-chat Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * ci: re-run the description checks on the edited body (no change) The perf-section and risk checks read the description from the event that started them; an edit through the broker started no new run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud.startChat: one Cloud machine per Mac workspace, on the carried cmux-tui start-chat Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud.startChat: a workspace keeps its machine while it pauses or resumes With the shown status (#28407), a workspace's machine that is pausing or starting (resuming) read as unusable while its link was down: its binding was dropped and the next send made a second machine. Starting counts as live, as CloudMachine.Status.isLive does, and pausing as paused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud.startChat: workspaces reuse and share machines; no machine per workspace Leo, 2026-10-31: "THE IDEA WAS ONE WORKSPACE PER MACHINE BUT IDK WHY THAT SHOULD BE THE LIMIT. JUST GO ARBITRARILY MANY" (leo-workspace design/cloud.md, "Solo first, then sharing a machine", rule 2). A Mac workspace's first send now reuses this person's machine (the one for chats, else a free one) before a new one is made, and keeps the machine it picked. Many workspaces share a machine, a send from no workspace may take a machine a workspace picked, and nothing caps how many machines a person has. When a workspace's machine is gone, a teammate's or failed, its next send reuses another before making one. The shared pick also skips a machine the server failed or is removing while a stale link still reads as connected (SW-05, hq#5685), so a workspace whose machine failed is never bound back to it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-515e927c20142b82a32c * cloud.startChat: a machine the server destroyed is never kept as made since Router review at f766845 (P1): a machine the server destroyed may stay in the App's store after the list dropped it, and the App sent it as `stored`, so a workspace (or send) pinned to it kept it and failed to connect. The App now leaves failed, destroyed and deleting machines out of `stored`; the pin or workspace moves on to another machine. 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>
…he Start New Chats In: Cloud choice (#29109) * cmux NEXT Cloud: pick a chat's machine from its folder (repo, ref, size, task kind), sent as autosize A chat sent to Cloud no longer needs a machine or size choice: CloudWorkPick reads the chat's folder (repo key and GitHub repo from the remote, branch and whether it is pushed, git object size, root files, task kind, .cmux/machine.toml, Codex broker) and Move to Cloud with no machine to reuse, and New Cloud Machine from a chat, send its autosize with POST /api/vm. The answer's sizePick stays on the machine's session for the hand-off. Behind Labs preview features. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud pick: clone the upstream's branch name, no GitHub repo from a local remote, no pick on the app-server link Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud: cloud.startChat, a new chat's first send started in Cloud with no machine or environment prompt The page's Send with Cloud picked asks the host (`cloud.startChat {task, cwd, harness?, model?, key}`), with Sandboxed's guards (a new chat, the Send's gesture, the replacements held, one at a time; both now share AgentPaneHandOff). The App takes a Cloud machine as Move to Cloud does (a new one sized by CloudChatPick), copies the folder with Move to Cloud's sync, opens the chat on the machine with the prompt seeded as the person's, and closes this Mac's unstarted tab. Behind Labs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the page's folder is optional; the tab's own folder otherwise Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: a started chat keeps the pane's hold; the folder must exist; the hand-off body is main-actor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: only a chat on this Mac starts one; the App checks the tab's daemon is local Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer: Cloud as where a new chat runs, a row at the top of the environment picker's Cloud section Behind Labs. Picking it makes the first send call cloud.startChat; attachments are refused on Cloud for now. Gallery: four states of the row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a Cloud pick not offered now is refused, never sent here; picking Cloud drops a saved environment and refocuses the prompt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: tests for the picker's Cloud row, a saved environment dropped by a Cloud pick, and a refused send keeping its prompt The not-offered refusal moves into cloudRun.ts so it is tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: format the new-tab test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: the folder a Cloud send copies is the one the chip names, also when the tab inherited home Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Gallery: the two other designs of where a new chat runs, gallery-only, beside the shipped Cloud row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: one start at a time from a page; another Return while it waits starts nothing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Gallery: the switch design's group is a fieldset Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a new chat's run location defaults from its folder's newest chat A folder whose newest chat went to a Cloud machine (a Cloud start or Move to Cloud) opens new chats with Cloud picked; otherwise this Mac, as before. The history is acpmux's chat list: a Cloud chat is matched to the folder by the folder the app's copy made on the machine (CloudMoveFolder remoteName under CloudMoveSetup workRoots). Labs only, and a pick in the pane always wins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a new chat's carried-over Cloud is a default its folder may undo; archived chats are not history Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a carried-over Cloud is marked in the folder default's effect, per chat Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: no change while a Cloud start is out Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: the folder default looks again once a Cloud start ends Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a chat starting here keeps the mode it starts with Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a chat starting in Cloud shows its progress under the message, as metadata The card shows the message, a spinner with the step, and the folder, machine, secrets and network as the host learns them (a cloudStartProgress push keyed by the start), never a modal. Three layouts behind the cloud-start-look experiment (chips, fact rows, step list), compared in the gallery's agent-pane.cloud-start. On the New Tab page it shows over the box, without the bubble. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: the host tells the page's card each step (machine, folder, opening) as the start reaches it cloud.startChat pushes a cloudStartProgress event keyed by the page's send before it takes a machine, copies the folder and opens the chat; the shared page host hands it to the bridge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start card: spacing and sizes on the design token scale Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * AgentPageChats: the Cloud start runner's pane closure, typed (Xcode 26.6 could not type the map) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: the host pushes the folder and the machine's size; a failed card goes when the person picks another place Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: format Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start gallery: the experiment's script has one step (an empty one does not load) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the machine's chat starts on the picked model; type the seed's Cloud runner for Xcode 26.6 next-review's P2: CloudStartChat built the remote seed with the harness and prompt only, so the model the page picked was dropped. AgentPaneCloudStart.seed(cwd:) now builds it with the model too, with a test. The request carries no effort, so there is none to forward. AgentPageChats.seed's Cloud runner is written out with its type, as #26921 does: #26921 found Xcode 26.6 could not type the map form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: a retry opens the same tab on the machine; the folder check reads off the main thread next-review's BLOCK at b3389d1 (Codex gpt-6-astra): CloudStartChat opened the machine's chat tab with a fresh creation key, so a retry of the same send after a lost answer could make a second chat and send the prompt twice. The tab's key is now the send's own (AgentPaneCloudStart.tabKey), with a test that a retry's key matches and another send's does not. The folder check (FileManager.fileExists) ran on the main actor; it now runs in a @Concurrent helper (guardrails main-blocking). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: copy only a folder the pane may name, each send into its own copy on the machine Two blocking findings from the Codex review of #28686, both in this PR's code: - The page named the folder whose tree is copied to Cloud, and the host only checked that it was absolute. A page script could name any folder on this Mac. The hand-off now takes the folder's canonical path (realpath, off the main actor) only when it is inside one of the pane's roots by components, the same roots AcpmuxPathPolicy uses for a chat that starts here: the pane's own and the New Tab scan's, never home or above it, plus the folders the person added. Anything else is refused with transport.path_outside_roots before the hold and the gesture. No folder from the page still means the tab's own folder, which the host reads. - Every Cloud start from the same folder synced into the same folder on a reused machine, and Move to Cloud's sync overwrites every file the machine changed, so a second Cloud chat could write over the first one's work. A start now copies into its own place under the work root (chats/<send key>). A retry of the same send lands in the same copy. Tests: a folder outside the roots, a link out of a root, a `..` path out of it, a missing folder, the disk's root, home, and a folder under home when the pane's folder is home are all refused and never reach the runner. The root's own folder still starts with its canonical path, and a send's place is its own and stable for a retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-672a743921bc7917cca7 * fix(cloud.startChat): a first send takes this person's free machine, and its retry stays there Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". - The machine: never the team's first connected one (often someone's busy lane VM). A machine this person created that is free (no chat open, or idle-paused) or named for chats (cloud-chats[-N]), else a new one named cloud-chats. Lane-pool VMs (fs-lane-N, lane-vm-N) are never picked. - #28845: CloudStartChat.Destinations pins each send key to the machine its first try took (newest 64, kept in the app's defaults), so a retry names that machine and its tab key gets the first try's tab back instead of a second chat with the prompt on another machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(acpmux): a chat's first send that a revoked OAuth token failed goes again once, 2 s later Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". On a fresh Cloud VM the first Claude call failed once with "Failed to authenticate: OAuth token revoked" and the same call 2 s later ran (cmux#28111 hand-walk, gap 5). - claude_auth::is_revoked_token: only a revoked token, never expired/missing sign-in or an outage. - hub/auto_resume/first_send.rs: on the chat's first turn only, and only for a prompt of its own (never a ~resume- attempt), the turn is resent once as P~resume-1 after 2 s through the Retry button's resend (retry_turn.rs resend_turn), under the chat's continuation mark, so Stop, close, a move or a person's prompt during the wait keep it from going. A retry that fails the same way is shown as before. Decisions are logged (first_send_retry, auto_resume_skipped). - daemon/cloud_handoff.rs: such a turn is not reported failed before its retry is decided. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): copy only a checked upload root, never copy a finished send again, create under the send's key router-review BLOCK at 8b117be (gpt-6-astra), all three findings: - [P1] The copy uploads the Git working copy that holds the page's folder. The pane now checks that upload root against its roots too (AgentPaneHandOff), hands it on as AgentPaneCloudStart.uploadRoot, and the App copies only that folder (CloudStartChat.uploads): a grant of /repo/paint never uploads /repo. - [P1] Destinations records, per send key and machine, that the send's copy finished. A retry whose copy finished opens its chat by its tab key without pushing again, which would overwrite what the chat already changed there. - [P2] A new machine for a send is created under AgentPaneCloudStart.createKey (from the send key), so a retry after a lost create answer gets the same machine, never a second VM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud.startChat): no await inside the upload root check's autoclosure (fleet compile) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * feat(cloud): Start New Chats In: This Mac / Cloud (agentPane.newChatsIn) Leo, 2026-10-31: "whenever i start a chat it should be able to send me to cloud autommatically". A setting, off (This Mac) by default; set to Cloud, a new chat's run location defaults to Cloud and its first send runs cloud.startChat. The composer's environment picker (This Mac / Cloud) overrides it for one chat. A chat with no project starts in the machine's own folder with nothing copied. Cloud's start is no longer behind Labs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * chore(settings): regenerate exports for agentPane.newChatsIn Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud): Sandboxed stays behind Labs when only the setting offers Cloud; no copy step for a no-project start Review BLOCK at 4f6d4a5 (router-review, gpt-6-astra): [P1] Start New Chats In: Cloud exposed Sandboxed with Labs off; [P2] a no-project start's step list showed the copy step. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * test(cloud): the Cloud-only picker test takes KeyboardEvent from its DOM Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud start): a no-project start compiles, rechecks the account, and never copies agent-home The review of #29109 at 21b19e1 blocked on three: - runHome called machine(for:invocation:pick:) without the `account:` base added, so the target did not compile. - runHome did not check the account after the machine connected; it now does, as a start with a folder does, so an account switch meanwhile opens nothing on the old account's machine. - cloudStartFolder sent a no-project chat's private agent-home folder as a project to copy; it is `home` now (sessionList.ts isAgentHome). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * refactor(cloud start): a no-project start shares run's open step; the chats machine names move to CmuxNextAgentPane runHome duplicated run's tail (open the chat on the machine, select it, close this Mac's tab); both now call one `open(_:tab:on:cwd:)`. With the pure machine-name rules (chatsName, isMarkedForChats, isLanePool, newMachineName) moved to CmuxNextAgentPane beside #29566's Step and sizeText, CmuxNextApp is 8 lines smaller than base, so arch-ratchet's app_lines row (which #28686 tripped) holds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * refactor(cloud start): drop RunModeRows.cloudOnly; Sandboxed is not behind Labs since #29059 cloudOnly kept Sandboxed out of the picker when only the setting offered Cloud, because the host refused sandbox.run without Labs. #29059 took that gate out, so nothing set it and the guard was unreachable (the review at 01d58a2). The picker is base's again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud start): newChatsIn has an agent policy; a tab on another machine never defaults to Cloud The review at 3c558fc blocked on two: - agentPane.newChatsIn was in neither agent-policy table, so SettingsSchemaExportTests.everyKeyHasAnExplicitAgentPolicy failed. It is refused to agents as .privacy: it decides whether a chat's project is copied to a Cloud machine. - With Start New Chats In: Cloud, a fresh SSH or Cloud tab defaulted to Cloud, and its first send went to cloud.startChat, which the host refuses there. The run-location default now applies only to tabs on this Mac. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * Translate the Start new chats in: Cloud choice The localization debt ratchet counted the new Cloud choice as copied English in every locale. Use the translations the other Cloud labels already use, and document Cloud as the established noun in de, fr and it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * Let agents set Start new chats in; keep the default off fresh remote tabs - agentPane.newChatsIn joins the agent-settable composer keys, so `cmux settings set agentPane.newChatsIn cloud` works from a lane or an agent; each chat's composer still shows and can change the choice. The settings export says agent_settable, and a test sets it through the cli and mcp writers. - The Cloud run default also stays off in a fresh SSH or peer tab whose origin is known before its summary (review follow-up on #29109). 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>
* cmux NEXT Cloud: pick a chat's machine from its folder (repo, ref, size, task kind), sent as autosize A chat sent to Cloud no longer needs a machine or size choice: CloudWorkPick reads the chat's folder (repo key and GitHub repo from the remote, branch and whether it is pushed, git object size, root files, task kind, .cmux/machine.toml, Codex broker) and Move to Cloud with no machine to reuse, and New Cloud Machine from a chat, send its autosize with POST /api/vm. The answer's sizePick stays on the machine's session for the hand-off. Behind Labs preview features. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud pick: clone the upstream's branch name, no GitHub repo from a local remote, no pick on the app-server link Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cmux NEXT Cloud: cloud.startChat, a new chat's first send started in Cloud with no machine or environment prompt The page's Send with Cloud picked asks the host (`cloud.startChat {task, cwd, harness?, model?, key}`), with Sandboxed's guards (a new chat, the Send's gesture, the replacements held, one at a time; both now share AgentPaneHandOff). The App takes a Cloud machine as Move to Cloud does (a new one sized by CloudChatPick), copies the folder with Move to Cloud's sync, opens the chat on the machine with the prompt seeded as the person's, and closes this Mac's unstarted tab. Behind Labs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: the page's folder is optional; the tab's own folder otherwise Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: a started chat keeps the pane's hold; the folder must exist; the hand-off body is main-actor Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * cloud.startChat: only a chat on this Mac starts one; the App checks the tab's daemon is local Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer: Cloud as where a new chat runs, a row at the top of the environment picker's Cloud section Behind Labs. Picking it makes the first send call cloud.startChat; attachments are refused on Cloud for now. Gallery: four states of the row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a Cloud pick not offered now is refused, never sent here; picking Cloud drops a saved environment and refocuses the prompt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: tests for the picker's Cloud row, a saved environment dropped by a Cloud pick, and a refused send keeping its prompt The not-offered refusal moves into cloudRun.ts so it is tested. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: format the new-tab test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: the folder a Cloud send copies is the one the chip names, also when the tab inherited home Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Gallery: the two other designs of where a new chat runs, gallery-only, beside the shipped Cloud row Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: one start at a time from a page; another Return while it waits starts nothing Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Gallery: the switch design's group is a fieldset Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a new chat's run location defaults from its folder's newest chat A folder whose newest chat went to a Cloud machine (a Cloud start or Move to Cloud) opens new chats with Cloud picked; otherwise this Mac, as before. The history is acpmux's chat list: a Cloud chat is matched to the folder by the folder the app's copy made on the machine (CloudMoveFolder remoteName under CloudMoveSetup workRoots). Labs only, and a pick in the pane always wins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a new chat's carried-over Cloud is a default its folder may undo; archived chats are not history Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a carried-over Cloud is marked in the folder default's effect, per chat Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: no change while a Cloud start is out Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: the folder default looks again once a Cloud start ends Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud default: a chat starting here keeps the mode it starts with Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Composer Cloud: a chat starting in Cloud shows its progress under the message, as metadata The card shows the message, a spinner with the step, and the folder, machine, secrets and network as the host learns them (a cloudStartProgress push keyed by the start), never a modal. Three layouts behind the cloud-start-look experiment (chips, fact rows, step list), compared in the gallery's agent-pane.cloud-start. On the New Tab page it shows over the box, without the bubble. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: the host tells the page's card each step (machine, folder, opening) as the start reaches it cloud.startChat pushes a cloudStartProgress event keyed by the page's send before it takes a machine, copies the folder and opens the chat; the shared page host hands it to the bridge. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start card: spacing and sizes on the design token scale Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * AgentPageChats: the Cloud start runner's pane closure, typed (Xcode 26.6 could not type the map) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: the host pushes the folder and the machine's size; a failed card goes when the person picks another place Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start: format Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Environment picker: an Auto row and its scope line (1/2 of the #26151 fold) The picker takes an `auto` choice from its caller: an Auto row at the top, checked while Auto holds, and a scope line naming Auto's destination (an experiment with three faces: destination with a quiet Auto tag, "Auto · destination", Auto's icon). Under Auto, Cloud is the folder's default, so the Cloud row is not checked and Auto's row asks for the default back (RunModeRows.onDefault) instead of a Persistent pick. Nothing passes `auto` yet; the New Tab wiring is the next PR. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Environment picker Auto: its row shows checked; a machine row under Auto is an explicit pick The Auto row draws its check while Auto holds. Under Auto, a machine row that lands on a folder tells the caller the machine first (onComputer), so the pick ends Auto, then the folder. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Environment picker test: ⌥ New Cloud Machine is not the Cloud row The Sandboxed test clicked the first Cloud-kind row, which since #26801 is the Cloud row heading the section (it failed the same way on lane/run-location-default). It now clicks New Cloud Machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Auto scope gallery: the experiment's script opens the picker (an empty script does not load) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Auto scope gallery: covers AutoIcon Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Auto scope line: Auto · destination by default; the Cloud row's icon uncoloured The captures show the tag face reading as "Cloud Auto" (the scope row's text is already quiet, so the tag doesn't stand apart). "Auto · Cloud" reads as one phrase and matches the picker's Auto row. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Environment picker test: format Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * New Tab Auto: the folder's run location, moved only by an explicit request (2/2 of the #26151 fold) Auto is selected on a new chat's New Tab page. It sends the prompt to the folder's run location (Cloud when the folder's newest chat went to Cloud, else this Mac), and only an explicit execution request moves it: a ready machine's full name, an ask for cloud or remote work (the Cloud row), or an ask to run locally. A Run as row, machine or saved environment ends Auto; a folder pick keeps it; Auto picked again restores the folder default in App. A Cloud refusal is said for the run it refused. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * New Tab Auto: the picker alone asks for the folder default; format Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * New Tab Auto: Auto reads the chip's folder; Cloud only when offered; a start out holds every send - Auto's fallback is the run location of the folder the chip names, read on the page, so a folder picked there counts at once. - Auto sends to the Cloud row only while Cloud is offered (App `cloudOffered`); `cloudStarting` reaches the page whatever Run as shows. - A machine name before a sentence's full stop is a reference; one inside a longer host name is not. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * New Tab Auto: a possessive names the destination; a Cloud pick test picks on the page "on my gpu-box", "on my remote server" and "on our VM" are destination requests. The New Tab Cloud test picks Cloud on the page: under Auto, the Cloud mode a tab comes with is a default, not a pick. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * Cloud start gallery: the experiment's script has one step (an empty one does not load) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6 * test(cloud): a start whose link came up while connecting asks the owner answer again Red on feat-cmux-next: AgentSessionAttachClient.start reads the owner link before it connects, so a new Cloud machine's first start (link not up yet) or a down machine that reconnects on use fails closed with agent_session.host_unverified, while Retry passes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8ca79ef955c62796a1ee * Cloud agent start: ask the owner answer again on the live link instead of failing closed on a link that was coming up Leo, on NEXT nightly 4113890 (classic link), New Agent Chat on a new Cloud machine: "Couldn't start Codex: kind-aqua-sandpiper could not confirm what kind of Cloud machine it is, so no agent chat starts there." Retry cleared it. start() and trust() read CloudMachineLink.ownerLink before the connection. When the link was not up yet, or came back while the call connected, that read was nil or older than the link the call goes over, and the start was refused. ownedConnection now drops that connection and takes both reads again around a new one, at most 3 times with no wait: the answer still brackets the making of the connection the call is sent on, and a link that never answers owner (a team machine) is refused as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8ca79ef955c62796a1ee * test(cloud): an owner word goes only on a connection made inside the owner reads; an attachment is never told a retired one ended Review (codex gpt-6-astra high) BLOCK at e038bc3: the first try could reuse a connection made before the first read, and retiring a connection told an attached page it ended. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8ca79ef955c62796a1ee * Cloud agent start: count only a connection made after the first owner read, and retire a dropped one silently Fixes the review's two blockers: a connection begun before the first read (an earlier call's, or one joined in flight) is retired and remade inside the reads, and a retired connection's close tells no attachment. A client with an attachment keeps its connection and is refused instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-8ca79ef955c62796a1ee * cloud.startChat: the machine's chat starts on the picked model; type the seed's Cloud runner for Xcode 26.6 next-review's P2: CloudStartChat built the remote seed with the harness and prompt only, so the model the page picked was dropped. AgentPaneCloudStart.seed(cwd:) now builds it with the model too, with a test. The request carries no effort, so there is none to forward. AgentPageChats.seed's Cloud runner is written out with its type, as #26921 does: #26921 found Xcode 26.6 could not type the map form. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: a retry opens the same tab on the machine; the folder check reads off the main thread next-review's BLOCK at b3389d1 (Codex gpt-6-astra): CloudStartChat opened the machine's chat tab with a fresh creation key, so a retry of the same send after a lost answer could make a second chat and send the prompt twice. The tab's key is now the send's own (AgentPaneCloudStart.tabKey), with a test that a retry's key matches and another send's does not. The folder check (FileManager.fileExists) ran on the main actor; it now runs in a @Concurrent helper (guardrails main-blocking). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-22973a84aab760788504 * cloud.startChat: copy only a folder the pane may name, each send into its own copy on the machine Two blocking findings from the Codex review of #28686, both in this PR's code: - The page named the folder whose tree is copied to Cloud, and the host only checked that it was absolute. A page script could name any folder on this Mac. The hand-off now takes the folder's canonical path (realpath, off the main actor) only when it is inside one of the pane's roots by components, the same roots AcpmuxPathPolicy uses for a chat that starts here: the pane's own and the New Tab scan's, never home or above it, plus the folders the person added. Anything else is refused with transport.path_outside_roots before the hold and the gesture. No folder from the page still means the tab's own folder, which the host reads. - Every Cloud start from the same folder synced into the same folder on a reused machine, and Move to Cloud's sync overwrites every file the machine changed, so a second Cloud chat could write over the first one's work. A start now copies into its own place under the work root (chats/<send key>). A retry of the same send lands in the same copy. Tests: a folder outside the roots, a link out of a root, a `..` path out of it, a missing folder, the disk's root, home, and a folder under home when the pane's folder is home are all refused and never reach the runner. The root's own folder still starts with its canonical path, and a send's place is its own and stable for a retry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-672a743921bc7917cca7 * fix(cloud.startChat): a first send takes this person's free machine, and its retry stays there Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". - The machine: never the team's first connected one (often someone's busy lane VM). A machine this person created that is free (no chat open, or idle-paused) or named for chats (cloud-chats[-N]), else a new one named cloud-chats. Lane-pool VMs (fs-lane-N, lane-vm-N) are never picked. - #28845: CloudStartChat.Destinations pins each send key to the machine its first try took (newest 64, kept in the app's defaults), so a retry names that machine and its tab key gets the first try's tab back instead of a second chat with the prompt on another machine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(acpmux): a chat's first send that a revoked OAuth token failed goes again once, 2 s later Leo (2026-10-30): "like the initial 0 to 1 chat auto it sends to cloud". On a fresh Cloud VM the first Claude call failed once with "Failed to authenticate: OAuth token revoked" and the same call 2 s later ran (cmux#28111 hand-walk, gap 5). - claude_auth::is_revoked_token: only a revoked token, never expired/missing sign-in or an outage. - hub/auto_resume/first_send.rs: on the chat's first turn only, and only for a prompt of its own (never a ~resume- attempt), the turn is resent once as P~resume-1 after 2 s through the Retry button's resend (retry_turn.rs resend_turn), under the chat's continuation mark, so Stop, close, a move or a person's prompt during the wait keep it from going. A retry that fails the same way is shown as before. Decisions are logged (first_send_retry, auto_resume_skipped). - daemon/cloud_handoff.rs: such a turn is not reported failed before its retry is decided. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * test(cloud): cover signed NEXT DEV channel defaults Agent-Session: https://cmux.com/deeplink/agent?id=aid-8d2fb03d72fa2712cb2f * fix(cloud.startChat): copy only a checked upload root, never copy a finished send again, create under the send's key router-review BLOCK at 8b117be (gpt-6-astra), all three findings: - [P1] The copy uploads the Git working copy that holds the page's folder. The pane now checks that upload root against its roots too (AgentPaneHandOff), hands it on as AgentPaneCloudStart.uploadRoot, and the App copies only that folder (CloudStartChat.uploads): a grant of /repo/paint never uploads /repo. - [P1] Destinations records, per send key and machine, that the send's copy finished. A retry whose copy finished opens its chat by its tab key without pushing again, which would overwrite what the chat already changed there. - [P2] A new machine for a send is created under AgentPaneCloudStart.createKey (from the send key), so a retry after a lost create answer gets the same machine, never a second VM. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * fix(cloud): default signed NEXT DEV to the development app-server link Agent-Session: https://cmux.com/deeplink/agent?id=aid-8d2fb03d72fa2712cb2f * fix(cloud.startChat): no await inside the upload root check's autoclosure (fleet compile) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-3bab30503f0b9a7059e5 * test(cloud): prevent signed DEV from restoring production credentials Agent-Session: https://cmux.com/deeplink/agent?id=aid-8d2fb03d72fa2712cb2f * fix(cloud): isolate signed DEV staging authentication persistence Agent-Session: https://cmux.com/deeplink/agent?id=aid-8d2fb03d72fa2712cb2f * cloud link: add authenticated credential socket producer Agent-Session: https://cmux.com/deeplink/agent?id=aid-4a652051ce0456e674d7 * cloud link: relay connect info and dial tokens Agent-Session: https://cmux.com/deeplink/agent?id=aid-34a78e5e41128ce4751e * cloud link: harden credential socket and generation fencing Agent-Session: https://cmux.com/deeplink/agent?id=aid-4a652051ce0456e674d7 * cloud link: isolate endpoint lifecycle and add relay fences Agent-Session: https://cmux.com/deeplink/agent?id=aid-4a652051ce0456e674d7 * cloud link: fix relay initializer call order Agent-Session: https://cmux.com/deeplink/agent?id=aid-4a652051ce0456e674d7 * fix(web): allow signed NEXT DEV auth callbacks Agent-Session: https://cmux.com/deeplink/agent?id=aid-a43a05e083d615505d02 * fix(web): scope NEXT DEV callback to staging Agent-Session: https://cmux.com/deeplink/agent?id=aid-a43a05e083d615505d02 * cloud link: type startup continuation Agent-Session: https://cmux.com/deeplink/agent?id=aid-4a652051ce0456e674d7 * Integrate NEXT Worker creator ownership from #28789 Carry the Worker-only changes from 90be2e6 and a8a78db into the held new Cloud DEV integration. Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Port root-owned Native guest receiver authority and lifecycle Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * Include signed Native receiver interoperability fixture Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * Use checked filesystem access for the bounded Cloud upload-root search Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Keep every Cloud upload-root read off the main actor Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * cloud link: own relay work and use checked concurrency seams Agent-Session: https://cmux.com/deeplink/agent?id=aid-34a78e5e41128ce4751e * Preserve authenticated token issue times at the daemon boundary Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * cloud link: fit private endpoint to Darwin runtime paths Agent-Session: https://cmux.com/deeplink/agent?id=aid-34a78e5e41128ce4751e * cloud link: avoid async closure default argument Agent-Session: https://cmux.com/deeplink/agent?id=aid-34a78e5e41128ce4751e * Attach the Native receiver to the root-owned daemon startup Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * Keep guest-only parent channel gated to Linux Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * cloud image: opt in to the root Native receiver Agent-Session: https://cmux.com/deeplink/agent?id=aid-8d2fb03d72fa2712cb2f * Keep Native smoke clones owned during probe failures Agent-Session: https://cmux.com/deeplink/agent?id=aid-8d2fb03d72fa2712cb2f * Probe Native support through the host help verb Agent-Session: https://cmux.com/deeplink/agent?id=aid-8d2fb03d72fa2712cb2f * Record reviewed temporary Cloud composition exception Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Spawn the Native receiver through the descriptor-safe process wrapper Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * Record the reviewed held-child identity check Independent review confirmed that supervised.rs reads only the pid from the retained Child after try_wait, compares captured start ticks, and never enumerates processes or accepts an external pid. Keep this exact single-pid authentication read as the PID-reuse fence; retain the child handle and process_start checks. Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * Keep receiving service conversion non-panicking Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * Exercise handshake capacity reclamation before valid admission Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * cloud: add native receiver policy and dial authorization Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * cloud: read native mesh metadata for receiver policy Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * cloud: expose team authority version helper for network peers Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * cloud: authorize Native connect info and link tokens Agent-Session: https://cmux.com/deeplink/agent?id=aid-5731063c82fc91125b46 * cloud: attach VM API machines to pinned Native mesh Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * cloud: wire native link authority and network provider contract Agent-Session: https://cmux.com/deeplink/agent?id=aid-5731063c82fc91125b46 * Include the private Unix descriptor transfer dependency Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * test(cloud): cover native link token through CloudDO route Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * test(cloud): add mesh machine fixture for native route Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * Preserve Native client and receiver claims in signed Cloud tokens Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * protocol: carry Native network and proof fields Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * cloud: expose TeamDO Native dial authority RPCs Agent-Session: https://cmux.com/deeplink/agent?id=aid-5731063c82fc91125b46 * cloud link: wire outgoing Native broker Agent-Session: https://cmux.com/deeplink/agent?id=aid-f0d3ce2f11e1a4c5b647 * test(protocol): validate Native network and proof schemas Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * cloud: persist confirmed network on create result Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * Dispatch Native receiver and device policy through owner objects Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * cloud: expose UserDO network identities with grant authority Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * fix(cloud): honor install authority while checking live grants Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * test(cloud): cover UserDO network identity projection Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * Accept the current Worker signed machine-role claim in Native tokens Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * Route Native VM receiver operations through the Worker API Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Compose the Native device and owned link into Cloud lifecycle Integrates the Swift route from ed12bb900b5ef2e651cd657f4cea8a8af73663ef and dc45703a91e4 with current resolver and composer code. Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Use the authenticated Worker team for Native app enrollment Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * cloud: persist install authority in UserDO state and principals Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * test(cloud): fence user identity after install revocation Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * fix(mac): add native broker descriptor and stream transport Agent-Session: https://cmux.com/deeplink/agent?id=aid-4a652051ce0456e674d7 * cloud link: retain vm role on fresh grants Agent-Session: https://cmux.com/deeplink/agent?id=aid-f0d3ce2f11e1a4c5b647 * protocol: expose host network target and policy reads Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * cloud: add install authority read and socket fanout helpers Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * cloud: consume install authority notices and fan out socket rechecks Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * Bind Native owner gates to the authenticated connection role Agent-Session: https://cmux.com/deeplink/agent?id=aid-a488ee6f4b3a9aa8a31c * Preserve signed Native roles through the receiver handoff Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * Record reviewed Native lifecycle composition delta Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * fix(mac): route native startup blocking work through lanes Agent-Session: https://cmux.com/deeplink/agent?id=aid-4a652051ce0456e674d7 * fix(mac): cancel native descriptor receive task Agent-Session: https://cmux.com/deeplink/agent?id=aid-4a652051ce0456e674d7 * cloud: let owners recheck install authority sockets Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * cloud: stamp accepted sockets with install authority Agent-Session: https://cmux.com/deeplink/agent?id=aid-3a7046c2f0c9a8188eb8 * Use existing durable socket revocation for authority changes Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Retain socket attachment type in UserDO Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Scope Native blocking work to its route lifetime Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Close stale socket admission without throwing from the upgrade Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Admit signed Native owners through the first-chat carrier Agent-Session: https://cmux.com/deeplink/agent?id=aid-a488ee6f4b3a9aa8a31c * Preserve bounded ChildProcess input initializer alongside Native sockets Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Test existing child stdin delivery alongside Native process support Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * fix(mac): narrow Native remote handshake capabilities Agent-Session: https://cmux.com/deeplink/agent?id=aid-4a652051ce0456e674d7 * Drop unused historical writer after preserving bounded stdin API Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Apply Native handshake requirements to the app-server path Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Expose Native route session token type at package scope Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * cloud: fence membership authority changes Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * Scope client public-key discovery to its read grant Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Expose Foundation parameter types in Native route package API Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * fix(cloud): pass Native handshake capabilities in initializer order Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * fix(cloud): restore verified Native policy reads for callers Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * Carry GUI terminal attachment operations for signed Native owners Agent-Session: https://cmux.com/deeplink/agent?id=aid-a488ee6f4b3a9aa8a31c * Limit Native terminal policy changes to the GUI latest mode Agent-Session: https://cmux.com/deeplink/agent?id=aid-a488ee6f4b3a9aa8a31c * Use the transfer host test fixture from its defining module Agent-Session: https://cmux.com/deeplink/agent?id=aid-7874a399566b24c5caa4 * protocol: export Native VM receiver schemas and retain grants Agent-Session: https://cmux.com/deeplink/agent?id=aid-34a78e5e41128ce4751e * fix(cloud): export personal tenant metadata and park Agent-Session: https://cmux.com/deeplink/agent?id=aid-5731063c82fc91125b46 * cloud: consume team authority notices and close receivers Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * cloud: fence all receivers on member authority changes Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * cloud: paginate receiver authority fences Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * test(cloud): cover reducer membership ABA authority Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * test(cloud): persist authority reducer ABA state Agent-Session: https://cmux.com/deeplink/agent?id=aid-3c1de57a1d612657bbf7 * protocol: regenerate network grant clients Agent-Session: https://cmux.com/deeplink/agent?id=aid-34a78e5e41128ce4751e * fix(cloud): deduplicate receiver store import after authority integration Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * ci: add NEXT new-link cloud create E2E Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * ci: route cloud e2e through linux picker Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * ci: use the fleet Linux runner picker Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * ci: run cloud new-link e2e on integration pushes Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * ci: use available overflow size for cloud e2e Agent-Session: https://cmux.com/deeplink/agent?id=aid-507297375d7253744aa7 * cmux-link: declare sign_clone again (macOS builds) An earlier integration merge dropped `mod sign_clone` from lib.rs while caller_macos.rs still uses it, so both macOS cmux-tui artifact builds failed with E0433 (run 41221404196). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * Native link: check the bundle's signature on the blocking lane NativeCloudExecutable's SecStaticCodeCheckValidity hashes the app bundle and cmux-tui. NativeCloudLinkChild.launch built it on the actor's executor; it now runs on the child's BackgroundWork lane (mayBlock: .system), and the call carries the reviewed concurrency-allow the main-thread checker asks for. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * backend: a host network binding keeps the install grant Native dials check host-network-bind passed the grant, but HostNetworkBoundParams dropped it and reduceHostNetworkBound never wrote network.install_grant, so every binding failed cloud-native-dial's grant check and no Native token was issued (router-review BLOCK at 1d89f03). The params carry the grant (optional, so older ledger entries decode), and a confirmed binding under a new or missing grant records it instead of answering unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * cmux-app-host: regenerate the app global after the base merge bun tools/gen-cmux-global.ts: ops.json, scopes.json and cmux-app.d.ts were stale (app platform check at 1d89f03). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * ci and app platform: fix reds that surfaced once the PR merged cleanly - cloud-newlink-e2e.yml: the upload-artifact pin dropped one character of v7.0.1's sha (workflows.test.ts). - cmux-tui-spec.yml: push and pull_request paths include schemas/link-token native.json and vectors.json, inputs of acpmux's tests (test_cargo_test_verdict.py); native.json joins the tree key inputs. - CmuxNextApps AppPlatform scopes.json synced from the regenerated app global (scripts/cmux-next/sync-app-runtime.sh). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * cloud: every non-production build defaults to the new cloud, no env vars Leo: "i dont wanna do this / make it more ergonomic" (on launching a DEV build with CMUX_NEXT_CLOUD_LINK=app). Debug and tagged fleet builds now default to the app-server link, staging sign-in and the development Worker (https://cmux-api-development.debussy.workers.dev). Baked loopback origins are ignored unless the launch sets CMUX_NEXT_CLOUD_BACKEND=local; non-loopback env values, CMUX_NEXT_CLOUD_LINK=legacy and CMUX_NEXT_FEED_API_URL stay overrides. Staging sign-in accepts the cmux-dev and cmux-dev-<tag> callback schemes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * tests: drop the test that asserted the classic link is the Debug default Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * cmux-tui CLI: test that every waitsForPerson action gets the person timeout Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * cmux-tui CLI: cloud start-session waits the person deadline, not 45 s The app gives cloudStartSession (and app install/remove, classic import) personDeadline (200 s), but the CLI gave up at 45 s, so a start-session on a machine still coming up answered mutation.outcome_unknown and opened no chat (pr-capture-cloud run 41267442022). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * cloud: the app server link runs cmux link again; the Native route is opt-in 3ec47d8 swapped base's CloudLinkLauncher for CloudNativeRouteHolder on every app-server build. That holder first reads the team's Native mesh (host.network.target); the dev Worker answers 400 for an account without one, so 'cloud link ensure failed: refused(400)', the link never starts and every machine connect fails (cloud start-session: "didn't connect"; pr-capture-cloud at b9a327f). The Native route stays available behind CMUX_NEXT_CLOUD_NATIVE_LINK=1, as #28947 describes it (opt-in). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * wip: native default Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * wip: drop Auto webview (lives in #26941) Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * protocol: regenerate the catalog and clients after the base merge Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * cloud: a non-production build takes the Native route first, cmux link as its fallback The capture team's development Worker now has a Native mesh (cmux-platform #405), so a non-production build's app server link takes the Native device route by default. A team the Worker has no Native mesh for keeps a machine: the first Native failure falls back to `cmux link` until sign-out. Production keeps `cmux link`. CMUX_NEXT_CLOUD_NATIVE_LINK=0 keeps `cmux link`, =1 forces Native with no fallback. Not run: CloudNativeFirstLauncherTests (fleet step pending). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * merge repair: drop blocks the base merge doubled; cmux backend/apps stays base's The -X theirs base merge kept both copies of code that both sides added (CloudLinkLauncher's credential socket helpers, cmux-host's test modules, server.rs's native_owner, user.ts's liveInstallGrant). The cmux backend/apps changes this branch carried landed through their own PRs and cmux-platform, so they take base's copy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * merge repair: fs_wire's admit_native_owner was doubled by the base merge Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * cloud: name the link's build apart from init's own build local Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * merge repair: the Mac link's Native broker wiring and start-session's person timeout The -X theirs base merge took base's side of the conflicting hunks, which dropped this branch's outgoing Native broker (cloud_broker channel and run, native_broker and native_route modules, CloudSource, serve's broker) and cloud start-session's place in PERSON_ACTIONS with its catalog test. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * cloud: the Native route is opt-in again, with cmux link as its fallback Review at 30a7996 (BLOCK, P1): a team that has a Native mesh can still hold machines made on the direct transport. Their connect_info carries no Native network, and the Native link cannot dial them, while a startup-only fallback never reaches cmux link. Development also took the capture team back off the VM API (cmux-platform #471), so Native is not the default for any build. CMUX_NEXT_CLOUD_NATIVE_LINK=1 takes Native first, and falls back to cmux link when it does not start. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * cloud: a debug build's owner API is the development Worker in CloudShareAPITests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 * cloud: a development Cloud owner's previews come from cmux-platform-development #28950 made debug builds' owner API the development Worker, so platformPreviewAPIBaseURL (staging-only) returned nil and CloudLivePreviewTests failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-548f18c0a6d1ebb48240 --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
HOLD: stacked on #26920, which is on #26801 and Swift #26791, all held. This PR changes Swift too.
Composer Cloud: a chat starting in Cloud shows how the start goes as metadata under the person's message. The card shows:
It is never a modal and has no Full Access warning. Working is a spinner. A failure shows the host's words, and the message stays in the composer.
Leo, 2026-10-28: "whatever's convenient for cloud, like that can be productionized, operationalized, we ought to just put out there"
Leo, 2026-10-28: "you can just say ... where should this chat run and stuff, and that's just about it ... the sort of metadata that you get to see, the UI elements ... their little warning for the full access thing, but I don't know if we really need to do that"
Gallery: agent-pane.cloud-start
What changes
cloudStartProgress.ts(new): the card's state.cloud.startChatkey), a step never goes back, text is one line and capped, and anything else is ignored.CloudStartView.tsxandcloudStart.css(new): the card, in three layouts behind thecloud-start-lookexperiment:I picked chips because it reads as metadata, like a "Building environment" line. It stays one or two lines while the start runs for minutes, and it doesn't push the composer down. The rows layout spends four lines on facts that matter less than the step. The steps layout spends three lines on a checklist.
App.tsx:cloudStartProgress;pageHost.ts: the shared page host hands thecloudStartProgressevent to the bridge.Swift
CloudStartChatpushes each step as the start reaches it (machine, then folder, then opening), with the folder's name and, once known, the machine and its size.AgentPaneCloudStart.progress(_:folder:machine:size:to:)delivers the event.Swift
AgentPageChats.seed: the Cloud start closure is written out with its type. Xcode 26.6 could not type themapform that cmux NEXT: Cloud as where a new chat runs, a row in the composer's environment picker #26801's base has.Not yet filled
With each step the host pushes the folder, the machine and its size ("4 CPU · 16 GB"). Secrets and network have fields and show when pushed. They come from the derived environment, which is being built on the server side and isn't pushed yet.
Before / after
agent-pane.cloud-startgallery entry:The gallery advisory captures only PRs into feat-cmux-next, so it runs once this PR's base retargets.
Tests
cloudStartProgress.test.ts: begin, pushes (checked fields, other keys, a step that never goes back, after a failure), and the answer.CloudStartView.test.tsx: every arm shows the message, a spinner and the same facts; the steps arm marks done, current and next; a failure shows the host's words with no spinner; no bubble on New Tab.test/cloud-start-host-event.test.ts: the host event reaches the bridge.cloudRun,NewTabScreenanddesign-selectionpass, andbun run checkis green.AgentPaneCloudStartTestsandCloudWorkPickTests.Risk: low, behind Labs and only for a Cloud start.
Agent session: agent session
🤖 Generated with Claude Code