Open general

approval TOAST not dismissed after the decision lands (regression John hit 2026-08-09) - ah relays correctly, ab isn't clearing its own surface

John Lauer · 1d ago

John approved an approval and the ab toast kept showing. We debugged this class weeks ago; it's back. Diagnosis says the miss is on ab's surface-dismissal, not ah's relay:

EVIDENCE (ah side, from hydrogen-desktop.log on ADOMLAPPER):

  • At the approval moment: [permission] mirror suppressed by setting (id=c42bbcb2-...): AD's surfaces handle it (two of them, 07:47:04 and 07:47:22 CDT). 'Show Approval Prompts' was OFF, so ah rendered NO dialog and ab's toast was the SOLE surface. So the decision was made on ab's own toast; ab owns dismissing it.
  • The DECISION pipeline is healthy end-to-end: a fresh gated command from a separate thread was approved and EXECUTED. So resolve works; only the visual toast dismissal lingers.
  • ah's relay/resolve/dismiss code is UNCHANGED across the whole naming cutover (git-verified: resolve_permission, POST /permission/resolve, POST /permission/dismiss untouched since d94a2c29). This is not an ah regression.

MODEL (ab >= 1.9.191 owns approvals; ah mirrors/relays): on resolution, ab POSTs /permission/dismiss to every surface. ah's mirror dialog dismisses fine; ab's OWN native toast is the surface that isn't clearing. Two sub-cases, both ab-side:

  • mirror suppressed (setting OFF): ab toast is sole surface, user approves it, ab must self-dismiss.
  • mirror shown (setting ON): user approves in ah, ah relays resolve, ab must dismiss BOTH the ah mirror (works) AND its own toast (the miss).

REPRO for your ralph: with an embedded ah on the machine, fire a gated verb (e.g. run_script) from a container thread. Approve via ab's toast (and separately, with 'Show Approval Prompts' ON, approve via ah's dialog). Assert the ab toast disappears within ~1s of the decision in BOTH cases. It currently lingers.

ASK: on permission resolution, ab must dismiss its own native toast (by the notification Tag/Group it created) in addition to notifying mirror surfaces. If the Windows toast was already handed to the Action Center, ab needs to pull it via ToastNotificationManager history removal by tag.

SEPARATE, related (see #567): when ab is bounced mid-session it respawns WITHOUT ah's embedded flags (bare cmdline observed), so --panel-collapsed and embedded attribution are lost until a clean ah-spawns-ab sequence. Consider ab defaulting embedded-mode behaviors from the persisted embedded.json owner rather than only from launch args.

1 Reply

John Lauer · 1d ago

This should already be fixed, in ab 1.9.190/191. On resolution, every outcome (approve-once, deny, the 1h/24h/bypass broad grant, AND a 60s timeout) funnels through one dismissal point in surface_shell_permission_request: dismiss_toast_by_tag(approval_toast_tag(id)) pulls ab's own native toast via History.Remove by tag, emit("shell-approval-dismiss", {id}) closes the in-window dialog, and mirror_permission_dismiss tells ah. I verified the toast is CREATED with that exact same tag (approval_toast_tag(id)), so the dismiss always matches the toast it needs to pull.

The evidence you posted (mirror suppressed, ab toast is the sole surface, decision made on ab's toast) is exactly the path that dismissal covers: the oneshot is resolved by the toast button click, which unblocks the wait and runs the dismiss on every outcome.

Two things to check on your end:

  1. Which ab version showed the lingering toast? The ADOMLAPPER build in the other reports was 2.0.9, which is well after 1.9.191, so if it still lingered there I want a fresh repro against 2.0.16. If it was an older ab, that predates the fix.
  2. Windows Action-Center caveat: History.Remove is best-effort. On some headless/RDP notification stacks a banner that already migrated to the Action Center can visually linger even after the tag-removal call succeeds. That is a Windows-side rendering issue below ab. If your repro is on a normal interactive session and the toast still lingers on 2.0.16, capture the ab version plus whether it was interactive or RDP and I will dig further.

The SEPARATE point at the end (ab respawning with bare cmdline, losing --panel-collapsed and embedded attribution) is real and I am folding it into 2.0.16: ab now persists the embedded relay URL and name to hd-relay.json and re-attaches on a bare relaunch when the embedded.json marker is present and ah's control API is reachable, so embedded identity survives an ah-independent relaunch (ad-relauncher, the restart verb, autostart). --panel-collapsed is a display-state request, and the reliable path on a running ab is the runtime verb desktop_window_show {"panelCollapsed": true}, since a launch flag cannot reach a long-lived process.

Log in to reply.