cmux-next updates: Roll Back to Previous Version (palette, menu, CLI) and a safe rollback swap

Merged
TE
17d ago
+310-52

Problem

A nightly is now the only fresh-build path for the team, but a user stuck on a bad nightly could not get off it. Rollback to the kept previous build existed only as app call updates.rollback, which the CLI refuses on release bundles. There was no palette, menu or CLI verb for it. Separately, RollbackSwap.perform deleted the kept bundle when the swap failed part way, so a failed rollback cost the user the only build they could return to.

Change

  • New action updates.rollback, titled "Roll Back to Previous Version…". It shows in the command palette and the app menu, and on the CLI as cmux settings rollback-update --confirm. It is destructive, so every entrypoint confirms first through the registry's confirmation gate.
  • One shared path, UpdaterService.dropBack(to:checkOnly:stateDirectories:). The action and the existing updates.rollback control method both call it. The server-side train or rollback work can call it too, for example to offer a drop-back when a nightly is pulled. Refusals (nothing kept, a store newer than the kept build reads, signature mismatch) surface as the action's failure, with the existing localized messages.
  • RollbackSwap: when a swap fails, the kept bundle moves back into the store instead of being deleted.
  • Localized the new title in every ActionCatalog locale. en and ja are translated; the rest are marked needs_review, matching the neighboring update actions.

Commits follow the regression-test rule: 11ba476 adds the failing RollbackSwapTests, and dc7a525 adds the fix and the action.

The seamless-update half of this work (a background check at launch that downloads, a check after wake, and the v3 migration off the stale 24h interval) already landed directly on feat-cmux-next as 5a4aa00, before the PR-only landing rule reached me. Its CmuxUpdater suites passed on the fleet.

Verification

  • Fleet: RollbackSwapTests at 11ba476 (expected red), and RollbackSwapTests, SilentBackgroundUpdateTests and ActionCatalogTests at dc7a525 (expected green). check-action-surfaces.sh also ran at dc7a525. Results are in the comments below.
  • Not done: the generated exports (plans/cmux-next/action-surfaces.json, actions.md) are not regenerated; the feat-cmux-next autofix bots own them. There is no tagged-build dogfood of the palette flow yet.

Relay security

This adds no v2 socket method. updates.rollback already existed; only its body now calls the shared path.

🤖 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

Rollback to the previously kept build is now a user-facing action, and a failed rollback swap no longer deletes the only build the user could return to.

  • New updates.rollback ("Roll Back to Previous Version…") shows in the command palette, app menu, and CLI (cmux settings rollback-update --confirm); it is destructive, so every entrypoint confirms before relaunching into the kept build.
  • All entrypoints (the new action, the existing updates.rollback control method, and future server-side calls) take one path, UpdateDropBack, a value holding the UpdaterService; it lives in CmuxNextUpdater so CmuxNextApp doesn't grow.
  • A refused palette or menu rollback now shows the reason instead of failing silently; a CLI run gets it as an unavailable refusal.
  • A failed RollbackSwap moves the kept bundle back into the store instead of deleting it, only removes the kept build's folder after a successful swap, and drops a running build kept mid-swap so it is never offered as a rollback.
  • Localized the new title in every ActionCatalog locale; en and ja are translated, the rest are marked needs_review.