Skip to content

feat(tui): arrow-key nav for tool-permission prompt + close P0 audit gaps#186

Merged
yishuiliunian merged 2 commits into
mainfrom
fix/plan-mode-ask-arrow-keys
May 27, 2026
Merged

feat(tui): arrow-key nav for tool-permission prompt + close P0 audit gaps#186
yishuiliunian merged 2 commits into
mainfrom
fix/plan-mode-ask-arrow-keys

Conversation

@yishuiliunian
Copy link
Copy Markdown
Contributor

Summary

  • Bug fix: tool-permission prompt (the y/n dialog shown when the LLM calls e.g. EnterPlanMode) now accepts arrow keys for selection. Previously it only accepted typed y/n.
  • P0 audit follow-up: add e2e coverage for memory_consolidation::trigger_consolidation (zero coverage before) and HubSecretClient budget/health gating (had inline unit tests but no integration coverage).

Bug detail

When the LLM calls EnterPlanMode, handle_enter_planrequest_permissionManualPermissionHandler emits a ToolPermissionRequest. The TUI shows a modal whose key handler only matched y/n/Esc. Users expected arrow-key selection between Allow/Deny.

Fix

  • PendingPermission gains a cursor: PermissionChoice field (default Allow).
  • Modal handler accepts Left/Right/Up/Down/Tab → ToolPermissionToggle; Enter → ToolPermissionConfirm. y/n shortcuts and Esc-cancel preserved.
  • Render highlights the focused choice (inverted bg) and shows the new hint: ←/→ select Enter confirm Esc cancel.

Coverage additions

File Tests Covers
permission_arrow_nav_test.rs 8 each arrow direction / Tab toggles cursor; Enter dispatches Confirm; y/n shortcuts + Esc still work; cursor flips on toggle
memory_consolidation_test.rs 3 fresh-lock pre-exists → short-circuit; no-lock → acquire synchronously; sequential trigger releases + re-acquires
hub_secret_client_test.rs 5 IpcBudget::Forbidden rejects synchronously; health starts healthy; health degrades after ≥3 consecutive failures; health() returns same Arc

Total: 16 new tests.

Required schema/API additions

  • PermissionChoice enum (Allow/Deny) with toggle(), exported from loopal-view-state
  • InputAction::{ToolPermissionToggle, ToolPermissionConfirm}
  • loopal-agent-server::testing::trigger_consolidation re-export

Test plan

  • CI passes (bazel build / test / clippy / rustfmt)
  • 16 new tests pass locally; existing 92 test targets still 92/92

Manual repro of the bug fix

  1. Enter plan mode via Shift+Tab
  2. Ask agent to do something that triggers EnterPlanMode tool call
  3. Permission prompt appears
  4. Before: only y/n work; pressing / does nothing
  5. After: //Tab toggle between Allow/Deny; Enter confirms; y/n still work as shortcuts

…dit gaps

Bug fix:
- The tool-permission prompt (the y/n dialog shown e.g. when the LLM calls
  EnterPlanMode) only accepted typed y/n. Users expected arrow-key selection,
  so the UX felt like a typing-only modal.

Fix:
- Extend `PendingPermission` with a `cursor: PermissionChoice` (Allow/Deny,
  default Allow).
- Modal handler: Left/Right/Up/Down/Tab → `ToolPermissionToggle`; Enter →
  `ToolPermissionConfirm` (commits whichever choice the cursor points at).
  y/n shortcuts and Esc-cancels preserved for backward compat.
- Render: highlight the focused choice with inverted bg, hint shows
  "←/→ select  Enter confirm  Esc cancel".

Test coverage for the fix:
- `permission_arrow_nav_test` (8 tests): each arrow direction toggles,
  Tab toggles, Enter dispatches Confirm, y/n still work, Esc still denies,
  cursor field actually flips on toggle.

Audit-driven coverage additions:

`memory_consolidation_test` (3 tests) — agent-server's
`trigger_consolidation` was the only call site of `loopal-memory`'s
lock primitives and had zero integration coverage. New tests verify:
- Fresh-lock pre-exists → trigger short-circuits, lock content untouched,
  `.last_consolidation` not written
- No-lock → trigger acquires synchronously before tokio::spawn returns
- After spawn-failure path releases the lock, a second trigger re-acquires

`hub_secret_client_test` (5 tests) — `HubSecretClient` had inline unit
tests for expand/health/placeholder/retry helpers but no end-to-end
coverage of the integration. New tests verify:
- `IpcBudget::Forbidden` rejects `get` and `list_names` synchronously
  with a clear error (no IPC issued)
- `health()` starts in healthy state
- Health transitions to degraded after consecutive failures (3+ failures
  cross the default threshold)
- `health()` returns the same Arc across calls (shared state contract)

Required schema/API additions:
- `PermissionChoice` enum (Allow/Deny) with `toggle()`, exported from
  loopal-view-state alongside PendingPermission.
- `InputAction::{ToolPermissionToggle, ToolPermissionConfirm}` for
  the new arrow-key flow.
- `loopal-agent-server::testing::trigger_consolidation` re-export so
  the agent-server tests can drive the trigger.
@yishuiliunian yishuiliunian merged commit 0db7721 into main May 27, 2026
4 checks passed
@yishuiliunian yishuiliunian deleted the fix/plan-mode-ask-arrow-keys branch May 27, 2026 01:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant