From 15d33d5ab181c7f5e683cc6724ade2decd28d930 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Wed, 22 Jul 2026 04:43:29 -0700 Subject: [PATCH] fix(desktop,tui,docs): dedup commands.catalog, route desktop /compact to /compress, update README MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - tui_gateway commands.catalog: skip _TUI_EXTRA entries that collide with a registry command or alias (the /compact class of bug, #57133; also removes the pre-existing /sessions duplicate) — registry entry is canonical. - apps/desktop: /compact now dispatches as an alias of /compress (matching the registry's canonical alias) instead of dead-ending; /density (the renamed TUI display toggle) is marked terminal-only so the desktop palette doesn't advertise a command its dispatcher can't run. - ui-tui/README.md: document /density instead of the old /compact toggle. - tests: commands.catalog regression test asserting no duplicate advertised names and no command shadowing another command's alias; desktop routing test. --- .../src/lib/desktop-slash-commands.test.ts | 10 +++++++- .../desktop/src/lib/desktop-slash-commands.ts | 4 ++-- tests/test_tui_gateway_server.py | 24 +++++++++++++++++++ tui_gateway/server.py | 7 ++++++ ui-tui/README.md | 2 +- 5 files changed, 43 insertions(+), 4 deletions(-) diff --git a/apps/desktop/src/lib/desktop-slash-commands.test.ts b/apps/desktop/src/lib/desktop-slash-commands.test.ts index 0a108e77ba8d..dfb1bb1d2170 100644 --- a/apps/desktop/src/lib/desktop-slash-commands.test.ts +++ b/apps/desktop/src/lib/desktop-slash-commands.test.ts @@ -31,7 +31,7 @@ describe('desktop slash command curation', () => { it('hides terminal, messaging, and dedicated-UI commands from suggestions', () => { expect(isDesktopSlashSuggestion('/clear')).toBe(false) - expect(isDesktopSlashSuggestion('/compact')).toBe(false) + expect(isDesktopSlashSuggestion('/density')).toBe(false) expect(isDesktopSlashSuggestion('/redraw')).toBe(false) expect(isDesktopSlashSuggestion('/approve')).toBe(false) expect(isDesktopSlashSuggestion('/model')).toBe(false) @@ -40,6 +40,14 @@ describe('desktop slash command curation', () => { expect(isDesktopSlashSuggestion('/curator')).toBe(false) }) + it('routes /compact to /compress (context compression), not the TUI display toggle', () => { + expect(resolveDesktopCommand('/compact')?.name).toBe('/compress') + expect(isDesktopSlashCommand('/compact')).toBe(true) + // Alias stays out of the popover so /compress is the single visible entry. + expect(isDesktopSlashSuggestion('/compact')).toBe(false) + expect(isDesktopSlashSuggestion('/compress')).toBe(true) + }) + it('surfaces /tools, /save, and /personality on the desktop', () => { expect(isDesktopSlashSuggestion('/tools')).toBe(true) expect(isDesktopSlashSuggestion('/save')).toBe(true) diff --git a/apps/desktop/src/lib/desktop-slash-commands.ts b/apps/desktop/src/lib/desktop-slash-commands.ts index 20d5416f8db1..5974f25ddd4a 100644 --- a/apps/desktop/src/lib/desktop-slash-commands.ts +++ b/apps/desktop/src/lib/desktop-slash-commands.ts @@ -148,7 +148,7 @@ const DESKTOP_COMMAND_SPECS: readonly DesktopCommandSpec[] = [ surface: exec() }, { name: '/background', description: 'Run a prompt in the background', aliases: ['/bg', '/btw'], surface: exec() }, - { name: '/compress', description: 'Compress this conversation context', surface: exec() }, + { name: '/compress', description: 'Compress this conversation context', aliases: ['/compact'], surface: exec() }, { name: '/debug', description: 'Create a debug report', surface: exec() }, { name: '/goal', description: 'Manage the standing goal for this session', surface: exec() }, { name: '/personality', description: 'Switch personality for this session', surface: exec(), args: true }, @@ -187,10 +187,10 @@ const NO_DESKTOP_SURFACE: Record = terminal: [ '/busy', '/clear', - '/compact', '/config', '/copy', '/cron', + '/density', '/details', '/exit', '/footer', diff --git a/tests/test_tui_gateway_server.py b/tests/test_tui_gateway_server.py index 264089643229..ba314901e428 100644 --- a/tests/test_tui_gateway_server.py +++ b/tests/test_tui_gateway_server.py @@ -6418,6 +6418,30 @@ def test_commands_catalog_includes_tui_mouse_command(): assert "/mouse" in tui_pairs +def test_commands_catalog_has_no_duplicate_or_alias_colliding_names(): + """No command may be advertised twice, and no advertised command may + shadow an alias of a different command (e.g. the historical /compact + collision where the registry aliased compact -> compress while the TUI + also registered its own /compact display toggle; see #57133).""" + resp = server.handle_request( + {"id": "1", "method": "commands.catalog", "params": {}} + ) + + names = [name for name, _ in resp["result"]["pairs"]] + dupes = {n for n in names if names.count(n) > 1} + assert not dupes, f"duplicate commands advertised in catalog: {sorted(dupes)}" + + canon = resp["result"]["canon"] + colliding = { + name + for name in names + if canon.get(name.lower(), name) != name + } + assert not colliding, ( + f"catalog commands shadow aliases of other commands: {sorted(colliding)}" + ) + + def test_commands_catalog_filters_gateway_only_commands_and_keeps_status_visible(): resp = server.handle_request( {"id": "1", "method": "commands.catalog", "params": {}} diff --git a/tui_gateway/server.py b/tui_gateway/server.py index 612daede726d..455b532c0b0d 100644 --- a/tui_gateway/server.py +++ b/tui_gateway/server.py @@ -13342,6 +13342,13 @@ def _(rid, params: dict) -> dict: cat_map[cat].append([c, desc]) for name, desc, cat in _TUI_EXTRA: + # Dedup guard: skip TUI extras that collide with a registry + # command or one of its aliases (e.g. the historical /compact + # collision, #57133, or /sessions which the registry also + # advertises). The registry entry is canonical. + if name.lower() in canon: + continue + canon[name.lower()] = name all_pairs.append([name, desc]) if cat not in cat_map: cat_map[cat] = [] diff --git a/ui-tui/README.md b/ui-tui/README.md index 5a2094a3184f..ac1d612f75b7 100644 --- a/ui-tui/README.md +++ b/ui-tui/README.md @@ -225,7 +225,7 @@ The following commands are handled directly by the TUI client. Unrecognized comm ### Core (`core.ts`) `/help`, `/quit` (alias `/exit`), `/update`, `/clear` (alias `/new`), -`/compact`, `/copy`, `/paste`, `/details` (alias `/detail`), +`/density`, `/copy`, `/paste`, `/details` (alias `/detail`), `/statusbar` (alias `/sb`), `/queue` (alias `/q`), `/logs`, `/history`, `/save`, `/undo`, `/retry`, `/steer`, `/mouse` (alias `/scroll`), `/status`, `/title`, `/fortune`, `/redraw`, `/terminal-setup`