Repository navigation
carry of #26791: cloud.startChat first send - #28111
Conversation
…ze, 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
…o 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
…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
…otherwise Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-4ba8980ae4e8eecb82d6
…t 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
…he 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
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
web and size checks: green Default changesThis pull request changes 1 default at
Signed off on this commit by Merge receipt: merged as Regenerate the snapshot with Shipped in:
|
|
Found 3 test failures on Blacksmith runners: Failures
|
|
Review (codex gpt-6-astra high, next-review): BLOCK at acbeafe
|
|
Owned by an agent session · session |
…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
…r 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
Bugbot needs on-demand usage enabledBugbot uses usage-based billing for this team and requires on-demand usage to be enabled. A team admin can enable on-demand usage in the Cursor dashboard. |
|
Review (codex gpt-6-astra, router-review): BLOCK at f832258 BLOCK at f832258 Visual verdict: no images supplied (range review); the visual verdict must come separately
Static review completed; Swift tests could not run because this Linux box has no Swift toolchain. Follow-ups:
exit=1 |
…t 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
|
Review (codex gpt-6.1-sol xhigh, router-review): SHIP at 52d4e01 Reviewed the range from the merge base to 52d4e01. No blocking findings. Follow-ups (owned by this PR's lane, to be filed as issues linking this receipt):
|
…26791-crash # Conflicts: # plans/cmux-next/arch-ratchet.json
|
Review (codex gpt-6-astra high, router-review): SHIP at 403c5ba Reviewed the range 1fd321e..403c5ba, the base merge of the head that got SHIP at 52d4e01. No blocking findings. Follow-ups:
|
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
Carry of #26791: cloud.startChat makes a new chat's first send run in Cloud.
Original purpose: add
cloud.startChat {task, cwd?, harness?, model?, key}. With it, a new chat's first send picks or makes a Cloud machine, copies the folder there, starts the chat on the machine and closes the local tab. The Sandboxed guards and the AgentPaneHandOff path stay as they are.This carry merges feat-cmux-next, with hand-resolved conflicts in the Cloud move, account handlers, machine model, work-pick, setup wizard and related tests. It refreshes the crash-class selector comparison. #26791 remains the source PR; this PR supersedes it for landing.
Leo, 2026-10-30: "why is it >10 hours and it's not been progressed on? how it blocked #28111 for no reason?"
Fixes for the first send (Leo, 2026-10-30: "can you guys just do it", "like the initial 0 to 1 chat auto it sends to cloud")
cloud.startChatno longer takes the team's first connected machine, which on Leo's account is often someone's busy lane VM. It now takes a machine this person created (CloudMachine.createdByagainst the signed-in user) that is free: connected with no chat open, or paused by the idle timer. A machine named for chats (cloud-chats,cloud-chats-N) comes first. If none fits, it creates one namedcloud-chats. Lane-pool VMs (fs-lane-N,lane-vm-N) are never picked. Move to Cloud's own pick is unchanged.hub/auto_resume/first_send.rs). The resend goes through the Retry button's path (retry_turn.rsresend_turn) under the chat's continuation mark. Stop, close, a move, or a person's prompt during the wait cancels it. It applies only to the chat's first turn and the prompt's own id, never to a~resume-attempt. A resend that fails the same way shows the failure as before.daemon/cloud_handoff.rsholds that turn's failed report until the retry is decided. Expired or missing sign-ins and outages are unchanged.AgentPaneHandOff) and hands it on asAgentPaneCloudStart.uploadRoot. The App copies only that folder (CloudStartChat.uploads), so a grant of/repo/paintnever uploads/repo.Destinationsrecords, 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.AgentPaneCloudStart.createKey, derived from the send key, so a retry after a lost create answer gets the same machine back.cloud.startChatno longer refuses withlabs_off. It refuses only when Cloud is off by policy (cloud_disabled) or nobody is signed in (not_signed_in), and the person still picks Cloud for the send. The chat's machine size pick (CloudChatPick.read) no longer checks Labs for any caller. The other shipped Labs gates (Move to Cloud's menus, the setup wizard, Sandboxed runs) come off in their own PR.Fixes since the carry (taken over from its unreachable owner)
AgentPaneCloudStart.seed(cwd:)now builds the seed with the model too. The request has no effort field, so there is no effort to forward.AgentPageChats.seedwrites the closure out with its type (as Composer Cloud: a chat starting in Cloud shows its progress under the message #26921 found it must), in place of themapform.AgentPaneCloudStart.tabKey). A retry after a lost answer gets that tab back, so the prompt is never sent to a second chat.CloudStartChat.Destinations(CloudStartChat+Machine.swift) pins each send key to the machine its first try took, keeping the newest 64 in the app's defaults. A retry names that machine, so its tab key gets the first try's tab back, never a second chat with the prompt on another machine. A pin to a machine that no longer exists is dropped.@concurrent,FileManager.checked).chats/<send key>,AgentPaneCloudStart.remotePlace), and a retry of the same send reuses that copy, so a second chat never writes over the first one's changes.No capture: the method has no UI caller until the composer's Cloud row (#28686).
Risk
risk:high (a new host method that starts a remote machine and copies a folder to it). Not behind Labs. A signed-out or Cloud-disabled account refuses with its own code. The method has no UI caller until the composer's Cloud row (#28686), and only the person's Send gesture reaches it. A refusal releases the hold so the person can send again; a started chat keeps it.
The guardrails'
app-sizerule was skipped for the push, with this reason: CloudStartChat composes App-only services (AppServices, CloudMove, CloudHandlers, AgentTabStore), beside its siblings CloudMove and CloudStartSession. CmuxNextCloud can't see those services until the B4 host protocols land, and CloudMove.swift is at 366 of 400 lines.Tests
AgentPaneCloudStartTests: the hand-off guards; the remote seed carries the prompt, agent and model; a retry's tab key matches its first try's, and another send's doesn't.AgentPaneCloudStartTests:aFolderInsideAGitWorkingCopyIsCopiedOnlyWhenTheWholeCopyIsInScope,aRetryOfTheSameSendCreatesUnderTheSameKey.CloudStartChatMachineTests(new):aFinishedCopyIsKeptPerSendAndMachineAcrossARelaunch,aPageNamedFolderIsCopiedOnlyAsItsCheckedUploadRoot,aNewMachineIsCreatedUnderTheSendsKey; and the pick (a teammate's machine is never taken, a busy machine is passed over for a free one, a machine named for chats comes first, lane-pool VMs are never picked, idle-paused is free and a person's pause is not, a machine with no creator counts only when an earlier send used it, new-machine naming);aRetryOfTheSameSendStaysOnItsFirstTrysMachine(cloud.startChat: pin a retry to the send's first machine (follow-up of #28111) #28845); a gone machine's pin is dropped; Destinations survive a relaunch and keep the newest 64.claude_auth::tests::a_revoked_token_is_told_from_other_sign_in_failures;hub::auto_resume::first_send::tests(a first send a revoked token failed goes again once and completes; a retried one that fails again is not retried; a later turn is not retried; a Stop or a prompt during the wait cancels the retry);cloud_handoff_tests::a_revoked_token_holds_the_turn_for_its_first_send_retry.Observed / Not run
acpmux.restartStuckand this PR'scloud.startChat.cmux-next checks: on the carry's head, its two failing steps were in files this PR doesn't touch. "No literal state roots" was acpmuxhelp_examples/session.rs:179, and it passes on feat-cmux-next now. "String tables (21 languages)" is missing translations in the ActionCatalog, PaneCreation, Updater and CmuxHome tables.Agent session: agent session
🤖 Generated with Claude Code