Skip to content

fix(approval): carry allow_permanent to TUI + desktop approval prompts#44534

Merged
OutThisLife merged 2 commits into
mainfrom
bb/approval-allow-permanent
Jun 11, 2026
Merged

fix(approval): carry allow_permanent to TUI + desktop approval prompts#44534
OutThisLife merged 2 commits into
mainfrom
bb/approval-allow-permanent

Conversation

@OutThisLife

@OutThisLife OutThisLife commented Jun 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Salvages #37856. When a tirith content-security warning is present, the approval backend forces allow_permanent=False and silently downgrades an "always" choice to session scope (the persistence loop in check_all_command_guards only honors "always" → permanent when no tirith finding exists). But the gateway approval.request payload that drives the TUI and the Electron desktop app never carried that flag, so both surfaces always rendered "Always allow" — offering a permanent allow the backend would quietly refuse to persist.

This plumbs allow_permanent end-to-end:

  • tools/approval.py — include allow_permanent: not has_tirith in the gateway approval_data the notify callback emits as approval.request.
  • ui-tui — thread allowPermanent through the event handler, gateway types, and ApprovalReq; ApprovalPrompt drops the "always" option (and renumbers the quick-pick keys) when it's false.
  • apps/desktop/ — thread allow_permanent through the gateway payload type, the per-session approval store, and the inline ApprovalBar, which now hides the "Always allow…" dropdown item when permanent allow is disallowed — reusing the existing DropdownMenu / confirm-Dialog UI.

Relationship to #37856 / #37812

Test plan

  • Backend: tests/tools/test_command_guards.py (20/20) — new gateway-payload tests assert allow_permanent is True without a tirith warning and False with one.
  • ui-tui: approvalAction reduced-option-set test + event-handler allowPermanent propagation (vitest, 80 passed); tsc typecheck clean.
  • desktop: store round-trip + ApprovalBar show/hide of "Always allow" (vitest --environment jsdom, 16 passed); tsc typecheck clean; eslint clean.

Supersedes #37856
Closes #37812

When a tirith content-security warning is present the approval backend
forces allow_permanent=False and silently downgrades an "always" choice to
session scope (the persistence loop in check_all_command_guards only honors
"always" → permanent when no tirith finding exists). But the gateway notify
payload that drives the TUI and the Electron desktop app never carried that
flag, so both surfaces always rendered "Always allow" — offering a permanent
allow the backend would quietly refuse to persist.

Plumb allow_permanent end-to-end:
- tools/approval.py: include `allow_permanent: not has_tirith` in the gateway
  approval_data the notify callback emits as `approval.request`.
- ui-tui: thread `allowPermanent` through the event handler, gateway types,
  and ApprovalReq; ApprovalPrompt drops the "always" option (and renumbers the
  quick-pick keys) when it's false.
- apps/desktop: thread `allow_permanent` through the gateway payload type, the
  per-session approval store, and the inline ApprovalBar, which now hides the
  "Always allow…" dropdown item when permanent allow is disallowed — reusing
  the existing DropdownMenu / confirm-Dialog UI.

The desktop/TUI render path for approvals already landed in #38578 (the root
cause of approvals not surfacing in the GUI); this completes the salvage of
#37856 by carrying allow_permanent across both surfaces. #37856's original
thread-local _block() approach is dropped: desktop/TUI approvals resolve via
approval.respond → resolve_gateway_approval (the per-session queue), not the
_block()/request_id correlation, so a worker-thread callback waiting on _block
would never be released by the real UI.

Tests: gateway notify payload carries allow_permanent (True without tirith,
False with a tirith warning); ui-tui approvalAction reduced option set +
event-handler allowPermanent propagation; desktop store round-trip + the
ApprovalBar showing/hiding "Always allow".

Supersedes #37856
Closes #37812

Co-authored-by: LeonSGP43 <cine.dreamer.one@gmail.com>
@github-actions

github-actions Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: bb/approval-allow-permanent vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 10764 on HEAD, 10764 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 5637 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

@alt-glitch alt-glitch added type/bug Something isn't working comp/tui Terminal UI (ui-tui/ + tui_gateway/) comp/agent Core agent loop, run_agent.py, prompt builder P2 Medium — degraded but workaround exists labels Jun 11, 2026
… opt set

Collapse the verbose multi-line rationale comments across the TUI/desktop/
backend approval surfaces into single-line "why" notes, and derive
APPROVAL_OPTS_NO_ALWAYS from APPROVAL_OPTS instead of re-listing it.
No behavior change.
@OutThisLife OutThisLife merged commit c6007e5 into main Jun 11, 2026
26 of 27 checks passed
@OutThisLife OutThisLife deleted the bb/approval-allow-permanent branch June 11, 2026 23:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder comp/tui Terminal UI (ui-tui/ + tui_gateway/) P2 Medium — degraded but workaround exists type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hermes Desktop App: approvals/manual confirmation prompts do not render in GUI

2 participants