cloud sidebar: a paused Cloud machine reads Paused, not a forever spinner

Merged
TE
8d ago
+674-7

Leo (2026-10-31): "let's work on improving this a LOT / cmux-platform, cmux when necessary / lots and lots of code".

What was broken

In the right sidebar's Cloud section, every paused Cloud machine showed a spinner next to its name, and it never stopped. The Cloud page listed the same machines as "Paused" with a Resume button, and cmux machine list reported them as paused and not connectable. Nothing was connecting to them, so the spinner was wrong. MachineSectionRow.rows took isConnecting from the daemon store's connectionState == .connecting alone, and a paused machine's store sits in .connecting. It never read the machine's server status.

What changed

  • MachineServerState (CmuxNextServer, a pure value) is what the machine's server says when the machine is not just running: paused, resuming, failed, deleted. MachineSectionRow takes it as serverState. A settled state (paused, failed or deleted) turns the spinner off, and stateText writes the state ("Paused" and so on). resuming keeps a spinner. A connected link always wins. Running machines and all non-Cloud machines behave as before.
  • MachineSectionRow.cloudServerState(status:stage:) (CmuxNextApp) maps the Cloud record to a row state. It uses CloudMachineStage, the same stage the Cloud page reads. A paused machine with no attach reads Paused. One that an attach or click is resuming (booting or connecting) reads Resuming… with a spinner. A failed resume reads Failed. failed reads Failed and destroyed reads Deleted. Everything else returns nil and the row follows its link.
  • The view is unchanged apart from a showsSpinner accessor for tests. Compact rows already write the state at the trailing edge when they are neither connected nor connecting.
  • New strings machines.paused, machines.resuming, machines.failed, machines.deleted in all 21 languages. Paused and Failed reuse the Cloud page's existing translations.
  • The fixture (machines.section.fixture) gains a paused Cloud sample (night-batch), so the gallery and captures show the state.

Prior art: cmux#28407 (open, carry of the Cloud machine transitions) adds pendingChange and shownStatus to the Cloud record, but it does not touch the right sidebar's Machines section. Once it lands, its transitions (pausing, starting, deleting) can feed cloudServerState as a follow-up, and this PR does not conflict with it. cmux#28409 (merged) and cmux#28051 (held) change the left sidebar only.

Design spec: design/cloud-sidebar.md (Rows), updated in a leo-workspace PR to add the Paused state.

Risk

Low. This is a display-only change to the right sidebar's machine rows. Connect, resume and New Workspace behaviour are unchanged: New Workspace was already disabled for a machine that is not connected.

Tests

  • New MachineSectionServerStateTests: maps a status and stage to a row state, including a paused machine whose daemon sits in .connecting, built from a real CloudMachineStageInput.
  • MachineSectionLayoutTests: aCloudMachinesServerStateReplacesTheConnectingSpinner (fails before this change: there is no server state and a paused row spins), plus a fixture check for the paused sample. MachineSectionViewTests.aPausedCloudRowShowsPausedAndNoSpinner checks that the compact row shows "night-batch · Paused" with no spinner, while a connecting row keeps its spinner.
  • cmux-ci compile-check --ref 24c360a26773b6e546e3bdc1f22a1a81677a5462 --app: passed (fleet job 3d884eab4500d326d865b391, 90 s).
  • Suites MachineSectionLayoutTests,MachineSectionViewTests,MachineSectionServerStateTests (fleet step addcf8ef244d89b0d37e347d) and the AAMachineSectionGalleryTests stills (step 3c97d2d88d9344d1ba4d84e2): queued; results follow in a comment.

Screenshots

Gallery stills (AAMachineSectionGalleryTests, compact, light and dark, with the new paused sample) follow in a comment once the fleet run returns.

Agent session: agent session

🤖 Generated with Claude Code


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


Summary by cubic

Fixes the right sidebar's Machines section, where every paused Cloud machine showed a spinner that never stopped. Rows now read the machine's server status and stage, so a paused machine reads "Paused" with no spinner, a resume in progress keeps a spinner as "Resuming…", and failed or deleted machines read "Failed" or "Deleted".

  • A connected link always wins; running and non-Cloud machines behave as before.
  • Display-only change: connect, resume, and New Workspace behavior are unchanged.
  • State strings are added in all 21 languages; the fixture gains a paused Cloud sample.