cmux NEXT: a chat on this Mac never says it belongs to another machine after a Cloud backend switch
Leo, on a new chat tab of cmux DEV cloud-firstsend whose machine picker read " · Local": "why does it even say this "does nto run here"??"
What was wrong
The banner comes from the agent tab's host check: a tab whose record names a host other than this Mac's install:<id>, listed in this Mac's own tree, is refused with app.host_mismatch ("This chat belongs to another machine, so it does not run here.").
#35284 (select the Cloud backend at runtime) moved the Cloud device-id into the selected backend's folder (cloud-next/<namespace>/device-id). Agent tabs, window records and closed-tab history use that same id as this Mac's install:<id>. Rust gives every tagged bundle legacy_storage = false (cmux-cloud-environment/src/lib.rs, selection_with_legacy), so a tagged build's first launch after #35284 named this Mac with a new id. Every tab it had saved before then (the "workspace-1" New Tab page included) read as another machine's. Release builds could hit the same thing when a client-config moves the Stack project (client_config.rs, apply).
The fix
- This Mac's id is the build's own
cloud-next/device-idagain, whichever backend the launch selected. The tunnel (hub enrollment, network attach/detach/rotate) keeps the selected backend's id. Both live in a newCloudInstallIDs(CmuxNextCloud). - A tab a launch on another backend saved under that backend's id (a tagged build's, in the window since #35284) is this Mac's only where the listing daemon is known to be this Mac's:
AgentPaneHostKindtakes this Mac's former ids and counts one as local only when this Mac's own tree lists the tab (listedHere), the same qualification it already uses for Chief homes. When another machine's store lists such a tab, it keeps its "runs on" notice, and another Mac'sinstall:tab is still refused. Checks that compare a host directly (with no listing daemon at hand) keep base's exact match, so no check can take another machine's tab for this Mac's. Closed-window history (Cmd-Shift-T) reads windows recorded under either id (CloudInstallIDs.all()). The former ids are read off the main thread at Cloud start. AgentPaneHostKindmoves to CmuxNextHomeEngine, unchanged except for that one extra branch, and is reached throughAgentTabStore.hostKind. CmuxNextApp's line count goes down.- The banner names the machine. A real remote chat says "This chat belongs to , so it does not run on this Mac." and falls back to the host id when the record has no name. This Mac's chat listed in another machine's workspace says "This chat belongs to this Mac, so it does not run on ." The banner stays for real remote chats. Both strings are in all 21 locales.
Tests
AgentTabsAfterACloudBackendSwitchTests (CmuxNextAppTests), run with scripts/ci/run-swift-testing-suites.sh Packages/macOS/CmuxNext and CMUX_SWIFT_TEST_SUITES=AgentTabsAfterACloudBackendSwitchTests on the fleet:
- Base plus the test (
4fc4139a78c1, fleet step d6e21341ac3df9860cc693b8): fails.cloud.localDeviceID() == "mac-before"fails, and the saved tab resolves to.remote, which is the banner. - Head (
d5461847decc, fleet step 868dbce382c0ca1414ca0ade): passes, along withAgentTabHostRefusalTests,SidebarSessionTreeTests,SidebarChatHistoryObservationTests,ApprovalBannerTests,RestorePreviousLaunchTests,ChiefSubagentTabsOfAnotherChiefHomeTestsandCloudBringBackTests. - An earlier head (
ed11cf5d176e, fleet step f341e00805a81da5206555f5) passed before the review rounds narrowed where former ids count.
It builds a CloudService with a tagged build's selection (legacy_storage: false, namespace staging-2), using a bundle id of its own and a device-id written the way a launch before #35284 wrote it. It asserts that this Mac's id is still that one and that a tab saved under it is .local. It also checks that a tab saved under the backend's id is local when this Mac lists it and remote when another store does, that another Mac's tab is still remote, that the tunnel keeps the backend's id, and that both banner strings name their machine.
Observed / Not run
- Observed: the run results above, and the prepush gate (no new violations; arch
app_lineslower). - Not run: a launch of a tagged app on a Mac. The test drives
CloudServiceand the tab host decision directly with a tagged build's Cloud selection; it does not launch a tagged build. I could not read Leo's Mac from this lane VM, so the cause comes from the code (#35284 and Rust'slegacy_storagerule), not from his logs.
Changelog
- Fixed: a chat on this Mac no longer says "This chat belongs to another machine" after a dev build switches Cloud backends; a chat that does belong to another machine now names it.
No capture: the change is which host a tab resolves to, plus the banner's text; no layout changes.
🤖 Generated with Claude Code
Agent session: agent session