Skip to content

fix(tui): slash-command menu — Tab completes the highlighted item, bare '/' guard, no-match row, ellipsis, footer hint, stable height (#1401) - #1402

Merged
dennisonbertram merged 3 commits into
mainfrom
issue-slash-menu
Sep 6, 2026
Merged

fix(tui): slash-command menu — Tab completes the highlighted item, bare '/' guard, no-match row, ellipsis, footer hint, stable height (#1401)#1402
dennisonbertram merged 3 commits into
mainfrom
issue-slash-menu

Conversation

@dennisonbertram

Copy link
Copy Markdown
Owner

Closes #1401

Summary

The slash-command menu now behaves and reads the way a first-time user expects: Tab completes the item highlighted with ↑/↓ instead of the input box's prefix guess; Enter on a bare / no longer runs /add-dir but explains how to choose; a query with no matches shows a dim "No matching commands" row instead of the menu vanishing; descriptions are truncated with and the command name is never cut; the highlight is a full-width bar; a footer hint lists the keys; the stray blank row is gone; and the menu borrows its rows from the top of the transcript so the screen height stays constant (previously 38 → 47 rows at 120x40).

Scope and issue reconciliation

All seven items in #1401 are addressed; nothing else changed. Two legacy tests that encoded the old behaviour (Tab on bare / is a no-op; Enter on bare / accepts the first item) were updated to the new contract and say so in comments. Out of scope per the issue: fuzzy ranking, alias display, status-message lifetime.

Impact analysis reconciliation

  • cmd/harnesscli/tui/components/slashcomplete/{model,view}.go: navigated flag, HasUserChoice, Query, rewritten View.
  • cmd/harnesscli/tui/model.go: Tab arm (only when the menu is open and no overlay), bare-/ Enter guard, viewport row trimming in View().
  • components/inputarea unchanged: its Tab completion still serves @ file paths and slash input when the menu is closed.
  • Server, API, config, persistence: unaffected (TUI-only rendering and key handling).
  • Snapshot goldens under testdata/snapshots regenerated.

Architecture and duplication check

Searched rg slashComplete cmd/harnesscli/tui, rg KeyTab cmd/harnesscli/tui, rg AutocompleteProvider. The dropdown already owned selection state; this PR routes Tab to it rather than adding a second completer. Truncation and row building live in the component's View; no new package.

Test-first evidence

Red command: go test ./cmd/harnesscli/tui/... -run 'SlashMenu|TestView_|HasUserChoice' (commit 57f5c5a)
Observed failure:

TestSlashMenu_TabCompletesHighlighted: Tab must complete the highlighted command into the input, got "/co"
TestSlashMenu_BareSlashEnterDoesNotRun: input must be preserved, got ""
TestSlashMenu_ScreenHeightStableWhenOpen: screen height changed when the menu opened: 38 -> 47 rows
TestView_NoMatchRow / TestView_EllipsisTruncation / TestView_NoTrailingNewline / TestView_FooterHint / TestHasUserChoice: FAIL

Why it proved the bug: each assertion mirrors a keystroke sequence reproduced live in tmux (issue #1401 captures).
Green command: go test ./cmd/harnesscli/tui/... -race → all packages ok (commit 7144d9b).

Verification evidence

  • go test ./cmd/harnesscli/tui/... -race PASS; go vet ./cmd/harnesscli/tui/... clean.
  • Live tmux drive of the built binary against a fake-provider daemon (real user path), 120x40:

Tab after ↓ on /co (was: input unchanged, highlight reset):

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
❯ /config
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Input cleared

Bare / + Enter (was: ran /add-dir):

  ↑↓ choose · Enter run · Tab complete · Esc close
❯ /
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Type a command name or use ↑↓ to choose one, then press Enter

No match (was: menu vanished):

  No matching commands for "/zzz"
  Enter shows the unknown-command hint · Esc close
❯ /zzz
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Input cleared

60 columns (was: chopped mid-word):

  /attach       Attach file context with @path tokens
  /cancel       Cancel a harness run
  /clear        Clear conversation history
  /compact      Compact the active run's context (/compact…
  /config       View current session configuration
  /context      View context window usage
  ▼ 30 more below
  ↑↓ choose · Enter run · Tab complete · Esc close
❯ /
────────────────────────────────────────────────────────────
Input cleared

40 columns:

  /theme      View and select a color t…
  /title      Set or show the current s…
  /attach     Attach file context with…
  /context    View context window usage
  /history    Search across stored sess…
  /stats      Show cost and token stati…
  ▼ 7 more below
  ↑↓ choose · Enter run · Tab complete…
❯ /t
────────────────────────────────────────
Input cleared

Rollout and rollback

TUI-only; rebuild with scripts/install.sh and restart the TUI. Rollback: revert.

Documentation

website/docs/cli/tui.md key table and menu section updated; engineering-log entry added.

Contract checklist

  • Linked issue follows the current structured contract and this PR closes it
  • Issue acceptance criteria, impact map, and scope were updated when the design changed
  • All callers, consumers, sources of truth, and similar abstractions were searched
  • No unrelated cleanup, hidden scope growth, duplicated wiring, or parallel abstraction was introduced
  • Tests were written first and the expected red failure was observed, or this is a strictly docs-only minor PR
  • Targeted checks and the repository-required full regression are green
  • Security, compatibility, lifecycle, deployment, observability, documentation, and rollback were reconciled
  • Real mouse/keyboard/API/operator behavior was exercised when the change is interaction- or integration-heavy

🤖 Generated with Claude Code

https://claude.ai/code/session_01WJGxhoFhA8JjkwZFcLGdS5

dennisonbertram and others added 3 commits September 6, 2026 13:20
…er, no-match row, ellipsis, footer, height

Red output:
  TestSlashMenu_TabCompletesHighlighted: Tab must complete the highlighted command into the input, got "/co"
  TestSlashMenu_BareSlashEnterDoesNotRun: input must be preserved, got ""
  TestSlashMenu_ScreenHeightStableWhenOpen: screen height changed when the menu opened: 38 -> 47 rows
  TestView_NoMatchRow / TestView_EllipsisTruncation / TestView_NoTrailingNewline / TestView_FooterHint / TestHasUserChoice: fail

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJGxhoFhA8JjkwZFcLGdS5
…bare '/'+Enter no longer runs the first command, no-match row, ellipsis truncation, footer hint, full-width highlight, stable screen height

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJGxhoFhA8JjkwZFcLGdS5
…ng-log entry

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJGxhoFhA8JjkwZFcLGdS5
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@dennisonbertram
dennisonbertram merged commit cad9640 into main Sep 6, 2026
2 checks passed
@dennisonbertram
dennisonbertram deleted the issue-slash-menu branch September 6, 2026 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant