Repository navigation
fix: let Cloud Desktop browsers own route navigation - #13938
Conversation
|
Navigate logical layers of code changes, visualize relationships, and explore their blast radius. Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughCloud browser setup and route handling now use shared panel configuration. Display reuse and projection reconciliation have updated rules. New tests cover browser navigation and projection behavior. The changes also add task-owned window checks and an E2E DerivedData scope check. ChangesCloud browser lifecycle and workspace projections
Cloud Desktop window fixture
E2E DerivedData scope
Priority: ➖ Normal Estimated code review effort: 4 (Complex) | ~45 minutes Change: Bug fix Sequence Diagram(s)sequenceDiagram
participant CmuxTuiSurfaceProvider
participant BrowserPanel
participant CloudBrowserAccessState
CmuxTuiSurfaceProvider->>BrowserPanel: Configure Cloud browser
BrowserPanel->>CloudBrowserAccessState: Configure route and connect model
BrowserPanel->>BrowserPanel: Bind automatic navigation
Possibly related PRs
Merge Risk: 🔵 Low · up to The route-adoption test should also verify that the adopted page can finish loading. This gap is bounded and does not, by itself, prevent merging. Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (2 errors, 1 warning)
✅ Passed checks (22 passed)
Full details: Cmux Swift `@Concurrent`Explanation The PR introduces a main-actor-bound network server in Resolution Move the proxy server's network-serving and request-parsing path off Full details: Cmux Swift Package BoundariesExplanation The diff adds independent workspace-projection domain logic in the app target. Resolution Create a small macOS SwiftPM target named ✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
All contributors have signed the CLA ✍️ ✅ |
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
This reverts commit e0d44a0.
Opening a machine's Desktop from the sidebar or `cmux vm desktop` in a workspace bound to that machine created the pane and then closed it again within a second. Two halves combined: - The browser pane binds its Cloud resource through `SurfaceCatalog.restore` while the provider configures it (the freshly created pane still carries its local placeholder, so `configureBrowser` re-registers it). That record has no remote workspace, and `restore` inserted it as-is, so the Desktop preview never joined the workspace it mirrors. - The reuse-enabled open then found that same-panel record, treated the pane as a reused view, skipped `projectionDidMove`, and reported `reused: true`. Workspace reconciliation saw a preview with no bound workspace among its placements and closed it as obsolete. `restore` and pending-restore resolution now give a Desktop or port record without provenance the workspace its local workspace mirrors, as `record` already does, while persisted provenance is kept. A materialization whose pane registered itself is treated as this operation's pane: the record is kept and placement finishes like a fresh open. Reconciliation logs each obsolete close in Debug, since this close was invisible in the debug log. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
With a routable window, the opens and drops in this suite request focus, and focusMainWindow now resolves the fixture window and would order it front and make it key on a shared app-host runner. Stub the fixture delegate's visibility controller with activation suppressed, as #13938 does, which needs the property to be internal instead of private, and expect the window to stay hidden and not key around every action. Also require the drop to be accepted and the located route to match the fixture's manager and pane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…#14304) * test: give the Cloud Desktop fixture a routable window for pane drops "A queued Desktop click retains its same-VM destination like a drop" fails its drop on main (every case since run 35979983434): the catalog keeps one projection and the commit wait times out after 10s. The drop targets `.split(targetPane:)`. SurfacePaneFactory resolves that pane's anchor through TerminalController.v2LocatePane, which walks listMainWindowSummaries. That list skips any registered context without a window, and VaultPaneAppFixture registers its context with `window: nil`. So the lookup returns nil, the factory throws paneNotFound, and handleSurfaceResourceDrop's Task swallows the error. The click path is unaffected because it targets `.workspace(_, .split)` and never locates a pane. The same suite failed 4/4 run on its own in #14076's changed-suites lane and hung once on main before that (run 35862070143), so it depended on test order rather than on a product change. Give the fixture's context a task-owned NSWindow that is never shown, forget its route on close, and require the pane lookup before the drop so a routing failure is reported where it happens. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: keep the Cloud Desktop fixture window hidden and never key With a routable window, the opens and drops in this suite request focus, and focusMainWindow now resolves the fixture window and would order it front and make it key on a shared app-host runner. Stub the fixture delegate's visibility controller with activation suppressed, as #13938 does, which needs the property to be internal instead of private, and expect the window to stay hidden and not key around every action. Also require the drop to be accepted and the located route to match the fixture's manager and pane. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * ci: drop the fixed Desktop drop test from the known-failure catalog With the fixture fixed, capturesClickDestination must pass instead of being tolerated as a known main failure, so this PR's changed-suites run proves the fix rather than passing either way. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * test: assert the fixture window is hidden after init completes Swift rejects a method call on self before every stored property is set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…wnership # Conflicts: # cmuxTests/CloudDesktopOpenFixture.swift
…-desktop-click-ownership
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
The materialization hook re-registered every projection without its daemon tab, including the coordinator's own terminal. Reconciliation then retired and re-projected that terminal forever, so the suite hit its time limit. Only the Desktop browser pane binds its resource while it is configured. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-desktop-click-ownership # Conflicts: # cmux.xcodeproj/project.pbxproj
Main moved CloudBrowserProxyEndpoint, CloudLinkFirstValue, CloudPortForwardRelay and CloudMachineLinkManager into the CmuxCloud package, so the PR's fixtures name them through that module. Drops the project entries the first main merge kept for three files that now live in CmuxCloud; none were in a group or build phase. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Bugbot is paused — on-demand spend limit reachedBugbot uses usage-based billing for this team and has hit its on-demand spend limit. A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue. |
…-desktop-click-ownership
…wnership # Conflicts: # cmuxTests/CloudPlacementTestProvider.swift
8409047 ci: run the suites that mention an app-source change (manaflow-ai#14418) cbebee8 fix(homebrew): generate the symbol form of depends_on macos (manaflow-ai#14424) e9bb38a ci(ios): only pick simulators the active Xcode SDK can target (manaflow-ai#14422) 5b2533c fix(ios): stop calling a mutating method inside #expect (manaflow-ai#14421) 4ab2739 ci: pick the pool with the least expected wait, bounded by every run's peak (manaflow-ai#14410) 26292a4 ci(nightly): warn instead of failing when GitHub refuses the tag move (manaflow-ai#14425) f4b331d Merge pull request manaflow-ai#14090 from manaflow-ai/14078-cloud-codex-restore-garble 193f5d9 test: restore AppDelegate.shared after every XCTest case (manaflow-ai#14379) 31588d6 ci: run a tart-* pick as auto while the Tart VMs are offline (manaflow-ai#14416) 2d844cb ci: app-host rerun holds the product's canonical root (manaflow-ai#14417) d0f485e Merge remote-tracking branch 'origin/main' into 14078-cloud-codex-restore-garble a855dbf test: fix the dead-key crash and sidebar AX walk failing on main (manaflow-ai#14406) 066f300 Merge pull request manaflow-ai#13938 from manaflow-ai/13893-desktop-click-ownership 0c2bb9d Merge remote-tracking branch 'origin/main' into 13893-desktop-click-ownership 9670d83 Merge remote-tracking branch 'origin/main' into 14078-cloud-codex-restore-garble cb88a4b Merge branch 'main' of https://github.com/manaflow-ai/cmux into 13893-desktop-click-ownership 86504fb fix: import Cloud package for team picker 885a39c test: import CmuxCloud in the Desktop navigation tests 75070d9 Merge remote-tracking branch 'origin/main' into 13893-desktop-click-ownership 3dfcfb9 Merge branch 'main' of https://github.com/manaflow-ai/cmux into 13893-desktop-click-ownership 52020d3 Merge remote-tracking branch 'origin/main' into 14078-cloud-codex-restore-garble 9cafdf5 test: register cloud preview during materialization bc09ec8 test: scope desktop registration hook to the preview resource ea4242c Merge remote-tracking branch 'origin/main' into 14078-cloud-codex-restore-garble 1be4c92 fix: count retained cloud previews as planned 4f98bd3 fix: align Xcode iroh package requirement 4a0bd3a chore: update Xcode package lockfile 8cda030 Merge remote-tracking branch 'origin/main' into 14078-cloud-codex-restore-garble ddeb03d fix: pin published iroh Swift release 1d9082a chore: update iroh package lockfiles fc2b529 fix: pin attested iroh Swift artifact revision 4c33353 test: import surface catalog models in cloud actions 25c64f2 Merge branch 'main' of https://github.com/manaflow-ai/cmux into 13893-desktop-click-ownership 4bd5808 test: import shared surface catalog models 59eddd9 Merge remote-tracking branch 'origin/main' into 13893-desktop-click-ownership a157f5c Merge remote-tracking branch 'origin/main' into 14078-cloud-codex-restore-garble cbc0118 ci: pin GhosttyKit for replay fix 4a48e3d Merge remote-tracking branch 'origin/main' into 14078-cloud-codex-restore-garble 4784eb2 fix: preserve Cloud replay trailing rows d081368 Merge origin/main and fix replay API visibility 7202960 Merge remote-tracking branch 'origin/main' into 13893-desktop-click-ownership a846dfd Merge branch 'main' of https://github.com/manaflow-ai/cmux into 14078-cloud-codex-restore-garble 96d5686 fix: delimit replay rows when scrollback exists 6ac603e fix: use terminal history boundary for replay 054dc50 style: apply hosted replay formatting 90fa111 fix: preserve replay history and protect tagged resources d2d6aa3 fix: refresh Cloud renderer after replay application 91601b8 revert: remove speculative Cloud replay grid overrides cb2dc58 test: reproduce Cloud replay shifting sparse screens with history c78ffdc fix: keep replay sizing helpers in app target 1e6f928 fix: preserve Cloud sizing intent across replay e568942 fix: keep Cloud replay geometry transient c094d63 Merge remote-tracking branch 'origin/14078-cloud-codex-restore-garble' into 14078-cloud-codex-restore-garble 8ed24b2 fix: align Cloud replay with remote grid bbc466c test: cover Cloud replay grid alignment cba191e test: cover self-registered Desktop materialization 105f24f fix: keep a Cloud Desktop pane that registers itself while materializing 9397594 Revert "fix: retain local Desktop projection provenance" dc9e8af fix: retain authored colors when Cloud replay omits sidecar 58d4105 test: preserve authored Cloud colors across sidecar-free replay a5af809 Merge remote-tracking branch 'origin/main' into issue-14078-cloud-codex-restore-garble 781a063 Merge origin/main into desktop click ownership 82b100a test: cover legacy applied resize responses a9f6a92 Merge remote-tracking branch 'origin/main' into 14078-cloud-codex-restore-garble 9d90d5e fix: clear Cloud ownership after replay confirms peer loss 6a36349 fix: defer cross-client Cloud loss until replay state 9bd3588 fix: ignore no-op Cloud resize acknowledgements 99329a1 fix: retain pending Cloud claims through handshake 4c0fa87 fix: demote Cloud mirror after cross-client rejection 509b984 fix: preserve explicit Cloud claim intent dce99b4 fix: distinguish passive Cloud lease outcomes 5de372f test: allow automatic restore claim response f7a3bc7 fix: wait for Cloud resize outcome before claiming 2fdaef3 fix: block rejected cross-client Cloud sizing claims 4804326 fix: stop passive Cloud mirror claim oscillation 223eb67 fix: restore debug title formatter linkage 68fb24d test: keep replay reset marker in restore fixture 674248c Merge remote-tracking branch 'origin/main' into 14078-cloud-codex-restore-garble 1a11606 fix: reset Cloud VT state for replacement replays 2a2e092 test: reproduce stale Cloud replay cells after restore 15ba7c4 fix: preserve restore intent before process probing a900e91 test: cover click Desktop graph reconciliation ff2694f refactor: isolate workspace title debug formatting 53dd942 Read matchingObservation after it is declared in the restore liveness check 1b288aa Merge remote-tracking branch 'origin/main' into 14078-cloud-codex-restore-garble 8b8c669 test: fence passive Cloud claims with protocol traffic 62532fc fix: remove duplicate Cloud restore test registration 827d859 chore: sync Cloud restore test wiring 22a187b fix: import workspace liveness in Codex restore policy 92126bd test: assert restored Cloud resize dimensions b7e457f fix: retain Cloud geometry claim policy across hidden restores 5dccec0 test: reproduce lost Cloud geometry eligibility after hidden restore 97c4673 test: preserve Cloud replay state across hidden restore geometry e0d44a0 fix: retain local Desktop projection provenance 31f698b fix: preserve committed routes while proxy connects b976180 fix: preserve preview provenance and committed Cloud routes 80f7087 fix: retain explicit Desktop placement provenance 3ee2ece fix: preserve Cloud Desktop panes during reconciliation 39b61fc test: keep Cloud Desktop previews during reconciliation 4ce4f4f fix: let activated Cloud browsers own route navigation 519bf26 test: reproduce desktop navigation without a mounted view 7d2b58a Merge origin/main and preserve per-run E2E cleanup 1b1feb8 test: use lifecycle-safe workspace creation in Desktop fixture a722c20 ci: restore E2E products inside the owned runner temp root 903513c test: enforce E2E DerivedData cleanup ownership c0f96a2 test: keep Desktop placement fixture windows hidden e8a34f4 Merge main after Desktop ownership fix landed fb9955b fix: keep Desktop view opens on the captured destination 1e696af test: give Desktop placement fixtures a complete native window route 9d3e2d8 fix: capture the Desktop view destination before scheduling f327329 Merge remote-tracking branch 'origin/main' into 13893-desktop-click-ownership 6dc7d9f test: establish mouse event context for the Desktop regression baseline 7cdeac6 Merge remote-tracking branch 'origin/main' into 13893-desktop-click-ownership 1f9c925 fix: retain the Desktop click destination across queued work b4f17f6 test: reproduce queued Desktop click targeting another Cloud workspace # Conflicts: # .github/workflows/app-host-test-rerun.yml # .github/workflows/ci-guards.yml # .github/workflows/ci.yml # .github/workflows/nightly.yml # .github/workflows/test-e2e.yml # .github/workflows/test-ios.yml # .github/workflows/update-homebrew.yml
Cloud Desktop loading still depended on SwiftUI phase tasks even though the browser state already had a readiness observer. Production never attached that observer. Activated Cloud browser panels now own route navigation, including cold/cached opens, retries, workspace/Dock duplicates and profile changes. The admitted machine/profile store is prepared before a cached route can navigate. Stop invalidates pending observation; closing or leaving a pane keeps delayed route completion from loading it.
Follow-up for #13893. The original selected-destination fix landed in #13897. This PR retains the native window fixture needed to verify the real click/drag path, and the executable CI cleanup guard. After pulling main, the E2E workflow itself matches main; the guard checks its per-run runner-temp path and rejects workspace cleanup.
The regressions are committed before their fixes:
519bf261c892e0808abf09d300acea37d0945d00(navigation test),4ce4f4fe26cfc8fd3a5b9ec5925164c1c1d41a4b(navigation fix),39b61fcbb3(pane-retention test), then3ee2ece0f12d5efe47245dfdafc2dec6dceeecfb(pane-retention fix). It invokes the actual outline click/menu and workspace drop through CmuxTuiSurfaceProvider, BrowserPanel, WebKit, authenticated HTTP CONNECT and the WebSocket bridge, with endpoint acquisition and guest HTML substituted. It does not manually call nextURL or navigate. Additional cases cover retry, multiple projections, duplication/profile replacement, close/Stop before readiness, re-entry, and cross-VM rejection in both directions.Verification is in progress:
Limits: the fixture performs real HTTP/WebSocket navigation, but its noVNC-shaped page is not a guest RFB server. No live Cloud guest or isolated GUI proof is claimed. Carrier replacement/reconnect and guest input recovery remain separately owned in #13370. The supplied screenshot does not provide its app revision or authoritative VM/workspace IDs.
Austin explicitly requested a try-it developer build before the queued tests finish. Submission uses the controller build-fleet contract fetched in cmuxterm-hq2 and its backend helper, tag
issue-13893-desktop-click-ownership, exact pushed fix SHA. The HQ2-backed attempt was rejected before submission with HTTP 507: 47 GiB free, 50 GiB required. No controller job, app artifact, or launch exists yet. The failure was reported through build-fleet feedback (5bdbecfdd4bec5cec12f16fa). Merge and issue close remain unauthorized.— CobaltThimble (registration pending)
Run: run_13893_cmux102_20260923_0525 · Session: codex-cmux102-13893-20260923-0525
Summary by CodeRabbit
Bug Fixes
Tests