cmux-next: a Cloud workspace that is not connected shows why in its window and sidebar

LA
4d ago
+1179-21

Summary

Since #28358, a window keeps its Cloud workspaces when cmux Cloud is signed out, but it showed nothing useful for them: no sidebar row, and a window that held only Cloud workspaces kept its old content or an empty pane (review finding 6 of #28358; before #28358 that window closed). Now such a workspace shows as not connected, says why, and offers what brings it back.

Stacked on #28393 (which is stacked on #28358): the base is fix/pa-b7c-findings until those land.

  • The state (CloudWorkspaceAbsence, CmuxNextCloudUI): a window member on a Cloud machine that no machine lists now and that is not gone (WindowManager.isDead) is signed out (Sign In), Cloud off, paused (Resume Machine), or connecting. CloudWorkspaceAbsences decides it; the composition root builds it once behind CloudWorkspaceAbsenceHost (one-line forwards in AppServices+CloudAbsenceHost.swift), and windows and sidebars ask it.
  • The window shows a card in place of a blank pane: the workspace's name, "On ", why, and the button. A window that holds only such workspaces is presented (hasMirroredWorkspace counts a workspace that shows why), and the window invariant holds. While a workspace only connects and the window already shows content, the content stays (a redial never flashes).
  • The sidebar lists each kept workspace under its machine, with its last saved name and the reason as its second line, in the existing row style (dimmed as saved rows are, no close button). A machine with no section gets one with its saved name. A click shows it; close, drag and rename wait for the machine. Only in the window's default space: the space of a kept workspace is not saved yet (saving it with the account is P-AUSTIN B7d).
  • Two variants (cmux-next-feature rule), one state model: the card (default) and a one-line form, only why and the button (Debug Settings cloud.absentCompact). Lawrence picks one.

Owners: PL-switch (WindowController, window membership) and the sidebar owner a590 (CmuxNextSidebar/Model/SidebarSection+AbsentRows.swift, new rows). Sidebar owner a590: please give your words for the Sidebar-Look: trailer and the note in plans/cmux-next/sidebar-owner.md ("Disconnected Cloud workspace rows").

God files

Measured against b3670f4635a (#28393's head): WindowManager 1502 -> 1502 (moved out cloudAbsence 12 lines, absentContentDidAppear 7 lines and the makeController/WindowInvariants special cases; one changed line in hasMirroredWorkspace). Added: WindowController type +41 (mostly WindowController+CloudCreation.swift), SidebarBridge type +82 (SidebarBridge+Windows.swift), AppServices type +10, CaptureSceneRegistry.swift +47 (two capture scenes). CloudService unchanged. No App file is new except the Host conformance; the logic is in CmuxNextCloudUI and CmuxNextSidebar.

Testing

Focused command: scripts/ci/package-test-lane.sh suite Packages/macOS/CmuxNext CloudWorkspaceAbsentDisplayTests,CloudWorkspaceAccountListTests,CloudWorkspaceRestoreTests (fleet cmux-ci run).

Commits, in order:

  1. c24282cb1e1 red, 56974631fba fix: neither compiled (a stub edit broke CloudWorkspaceAbsence.swift; a tuple lost its labels). Kept, not rewritten; their Sidebar-Look: no visual change trailers were wrong.
  2. 24715e669ae red (valid): compiles with CloudWorkspaceAbsence.init, .action and WindowManager.cloudAbsence stubbed; also the one-line variant, the variant test and the capture scenes.
  3. ad4ad8e756b fix, with Sidebar-Look: new disconnected rows under their machine, existing row style and the sidebar-owner note.
  4. bd2a3eae236 merge of #28393's branch.
  5. 15f50ebe597 refactor: the state moves out of WindowManager into CloudWorkspaceAbsences. No behavior change.
  6. 8fa31f8efad the capture scenes seed saved names ("api-server" on "build-box").
  7. 7cbebd27359 What's New highlight.
  • Compile-check c7320e4eafac9f8d78b4072b at 24715e669ae: passed. Compile-check 713119c9a1ca4a7eb357934d at 8fa31f8efad: passed.
  • Red 1dc7ef17646eef1ca1488e49 at 24715e669ae: CloudWorkspaceAbsentDisplayTests fails with 16 issues on its assertions (the state, the shown card, the window waiting off screen, the row); aKeptWorkspaceRowGoesUnderItsMachineAndAMachineWithNoSectionGetsOne passes there (it tests the sidebar helper, which the red did not stub: coverage). The other two suites pass.
  • Green 23376edabea15d23ccb135ee at 8fa31f8efad: GREEN_RESULT

Observed / Not run

  • Observed: prepush-gate.py adds no violations; localization_catalog.py check on Cloud.xcstrings has only the 8 parity errors the base catalog has (21 locales for every new string).
  • Not run: a live sign-out in a signed-in app (the tests and the capture use the account-state seam WindowManager.cloudList, which #28398 replaces). The Sign In and Resume Machine buttons run the existing actions; no test clicks them. Austin's-day numbers: no sign-out in the scenario.

Changelog

Fixed: Signed out of cmux Cloud, your Cloud workspaces stay in their windows and sidebar and say why they are not connected, with Sign In or Resume Machine.

Proof

CAPTURE_PENDING


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

After signing out of cmux Cloud, a window keeps its Cloud workspaces but showed a blank pane or stale content for them. Each kept workspace now says why it is not connected and offers what brings it back. Stacked on #28393.

Behavior

  • A shared state model distinguishes signed out (Sign In), Cloud off, machine paused (Resume Machine), and connecting.
  • The window shows a card naming the workspace and its machine, or a one-line variant behind a Debug Settings toggle; a window holding only such workspaces is presented instead of waiting off screen.
  • The sidebar lists each kept workspace under its machine with its saved name and the reason, in the window's default space only.