cmux NEXT: Open Recovered Draft… in the palette reopens a recovered draft after its toast

Merged
TE
5d ago
+580-5

Leo's ask: "HOW THE F*** IS THIS STILL NOT FING CHANGED IT'S LITERALLY "STOP SHOWING FING NONSENSE ON LOAD" + "JUST FING REMOVE THE FING OLD DAMEMONS WHAT THE…""

This follows #28305, which shows the recovered-draft toast at launch only once per draft. Once that single toast has gone, nothing in the app could reopen a recovered draft. I checked the command palette, Home, the File and Window menus and Settings; the only paths left were the toast's Open and the Debug socket's debug.filepages {restore}. This PR adds a lasting way back.

What changes

  • New palette action file.openRecoveredDraft, titled Open Recovered Draft…:
    • It opens a page listing the recovery drafts on disk, newest first. Each row shows the file name, its path and when the draft was saved.
    • The drafts are read when the page opens, off the action's turn.
    • Return runs RecoveryDraftStore.restoreHandler, the same path as the toast's Open. The draft opens in its file page as unsaved changes, and the conflict notice still shows if the file changed on disk.
    • Opening never removes a draft. A save or Don't Save does, as before.
  • The page is RecoveredDraftPage in CmuxNextPalette. The App only binds it, in FilePageHandlers: bindEffect shows the page and returns .done, with no await and no disk access on the action's turn.
  • Surfaces:
    • Palette: offered.
    • CLI and MCP: .guiOnly. The page is a picker; scripts already read drafts through debug.filepages.
    • Context menu: .noObject.
  • Strings: the action title is in ActionCatalog.xcstrings; the page title and search placeholder are in the palette's Localizable.xcstrings. Each has 21 languages, and check-l10n.sh reports 0 errors. The row's Open button reuses the palette's existing "Open".
  • Generated files (plans/cmux-next/action-surfaces.json, actions.md, web/data/next-docs/*.generated.json) are left to the autofix, as the repo requires.

Files: CmuxNextActions/Catalog/FilePageActionCatalog.swift, CmuxNextPalette/RecoveredDraftPage.swift, CmuxNextPalette/PaletteStrings.swift, the two xcstrings, CmuxNextApp/Handlers/FilePageHandlers.swift, and the test CmuxNextAppTests/RecoveredDraftPaletteTests.swift.

Tests

Focused test: RecoveredDraftPaletteTests in CmuxNextAppTests.

  • theActionIsBoundAndOffersItsPage
  • thePageListsTheDraftsNewestFirstAndOpensTheChosenOne: Return calls restoreHandler with the chosen draft, and the draft stays on disk.
  • noDraftsListNothing
  • withoutARestoreHandlerTheRowsAreDisabled

This PR's CI compiles and runs these; Swift is not compiled on the authoring host.

Observed / Not run

  • Observed: python3 scripts/cmux-next/prepush-gate.py reports no new violations (one app-size warning: +10 lines in FilePageHandlers). scripts/cmux-next/check-l10n.sh reports 0 errors.
  • Not run: no local Swift compile or test.

Screenshots

No capture: neither state can be captured without risking private text on a shared capture runner. While you type into the root palette, it also lists workspace and tab rows (matched on their directories), and the tour recorder keeps every frame. The Recovered Drafts page lists drafts from the user's Application Support (cmux/recovery), not the tagged home. The page's rows and states are covered by RecoveredDraftPaletteTests. To try it: Cmd-Shift-P, type "Open Recovered Draft", press Return. The page lists the drafts that recovery saved, newest first.

Notes

  • Risk: risk:normal (a new palette action that runs an existing restore path; it adds no new writes or deletes).
  • It lands after #28305 and does not depend on it to compile.

Changelog

  • Added: Open Recovered Draft… in the command palette lists recovered drafts of unsaved files and opens the chosen one.

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

Adds the Open Recovered Draft… palette action so recovered drafts stay reachable after their one-time launch toast is gone.

  • The action shows a palette page listing the drafts on disk, newest first, with title, path, and save time.
  • Return runs the same restore path as the toast's Open, opening the draft as unsaved changes. Opening never removes a draft.
  • The action is palette-only; CLI and MCP are excluded since scripts already read drafts through debug.filepages.
  • The strings are localized in 21 languages.
  • Includes regenerated action exports (action-surfaces.json, actions.md).

Bug Fixes

  • No capture tour: the root palette's recorder keeps workspace and tab rows, and the drafts page lists private file names from Application Support, so neither is capturable.