cmux-next actions: one name per command (duplicates carry the canonical name, look-alikes renamed)
Summary
This makes "one name per command" true and adds a test that keeps it true.
Every surface already reads one source. I checked the menu bar, keyboard-shortcut settings, which-key, the shortcut recorder and the palette. All of them take an action's name from registry.title(for:) / descriptor.title, so no surface had a hard-coded action name to replace. The only hand-written menu bar strings are the system items (Undo, Cut, Hide Others…), and those aren't actions.
What was wrong was the catalog itself. Several different commands shared a name, and the palette audit had folded some of them as if they were the same command.
Duplicates, now explicit data: ActionDescriptor.paletteDuplicates lists commands that do the same thing on another target. Each duplicate keeps its own target, CLI verb and menu placement. It carries the canonical action's name, and the palette folds it into the canonical row. ActionDescriptor.canonicalActionID exposes this.
| Duplicate | Canonical | Why it is the same command |
|---|---|---|
remote.newWorkspace | workspace.newOnMachine | a new workspace on a machine, from the machine's row |
remote.copyError | copyWorkspaceSSHError | the same RemoteStrings.sshError copy, from the machine's row |
sidebar.item.hideApp | app.hide | its handler forwards to app.hide |
Not duplicates (#22764 folded them by mistake): these act on different things, so they are unfolded and get distinct names.
| Action | Before | After |
|---|---|---|
switchRightSidebarToFeed (right sidebar mode; feed.show toggles the feed panel) | Show Feed | Show Feed in Right Sidebar |
appearance.interfaceSize.* (Debug opt-in chrome.interfaceSize, a different setting from Interface Scale) | folded into Interface Scale | its own row, niche |
browserShowHistory (vs history.show) | Show History | Show Browser History |
browser.selection.search (vs browser.focusSearch) | Search the Web | Search the Web for Selection (the page menu still reads Search Google for "…") |
home.renameConversation (vs workspaceGroup.rename) | Rename Group… | Rename Group Chat… (matches New Group Chat…) |
Search words: the aliases (font, theme, background, machine) were already ActionDescriptor.paletteAliases, and #22764 merges them into the palette and the rank settings. They are unchanged here.
Test: PaletteMenuVocabularyTests is committed first, so that commit fails on base. It checks three things:
everyNameBelongsToOneCommand: no two palette or menu bar actions share a name unless one is a declared duplicate of the other, and every duplicate reads its canonical's name.menuBarItemsUseTheCatalogName: every menu bar item's title is the registry's title.
Localization: the four new names are translated in all 21 locales.
Observed / Not run
- Ran
scripts/cmux-next/prepush-gate.py(no new violations). Read the catalog export to find every shared name on the palette and menu bar: the six above plus Hide App. - Not run locally: the Swift build and tests. CI covers them, and this PR waits for the compile before it merges.
- The generated exports (
action-surfaces.json,actions.md) are regenerated by the autofix.
Changelog
- Changed: Commands that did different things under the same name now have distinct names in the palette and menus (Show Feed in Right Sidebar, Show Browser History, Search the Web for Selection, Rename Group Chat…).
Agent session: cosmic-gray
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Makes "one name per command" true in the cmux-next palette and menu bar, and adds a test that keeps it true.
- Commands that only read alike now have distinct names: Show Feed in Right Sidebar, Show Browser History, Search the Web for Selection, Rename Group Chat…
- Interface Size no longer folds into Interface Scale: it is a Debug opt-in setting (
chrome.interfaceSize) and now gets its own niche row. - Real duplicates (
remote.newWorkspace,remote.copyError,sidebar.item.hideApp) are declared inActionDescriptor.paletteDuplicates, carry their canonical action's name on every surface, and fold into the canonical palette row. PaletteMenuVocabularyTestschecks that no two palette or menu bar commands share a name unless declared duplicates, and that each menu bar item reads its title from its descriptor's catalog name; the test commits first and fails on base.- The renamed actions are translated in all 21 locales.