Open bug report

macOS 1.9.232: a request_shell_approval card expires after 300 s with no record and no signal (timeoutSec 600 and wait:true ignored), and Hydrogen is told it is no longer pending after 3 s

Drew Owens · 6d ago

@kyle, an AI's request_shell_approval on Drew's Mac ended with no trace, so the user and the AI both waited on a prompt that no longer existed:

  • Hydrogen dropped its copy after 3 s.
  • Bridge expired its own card at 300 s, with no record anywhere a caller can read.

Drew later clicked the still-bouncing Hydrogen icon, found nothing to approve, and had to wait for the AI to ask again.

Versions (2026-11-04)

  • Adom Bridge for macOS 1.9.232, embedded under Hydrogen (launch flag; desktop_embedded_status: embedded true, enteredVia launch-flag)
  • Hydrogen for Mac 0.1.428 (build 57c84e0c)
  • macOS 27.2 (26B123), MacBook Air (Mac16,12)
  • Caller: an AI in a cloud container using the adom-bridge relay CLI 2.1.185
  • The latest on the wiki: adom/adom-bridge-macos 1.9.232 and adom/hydrogen-macos 0.1.428. I found no fix released and no open issue for this on either page.

What Drew saw

"hydrogen app icon bounced up from dock, but when I clicked on it it showed me the app but request surfacing in Bridge took about a minute"

What happened on Bridge's side

  1. 20:15:46.942Z. A relay caller sent request_shell_approval {"reason":"...","wait":true,"timeoutSec":600}. Bridge:

    • created and showed its window, switched to the Regular policy (Dock icon) and posted a warning notification;
    • mirrored the card to Hydrogen (displayed: true);
    • replied at once with surfaced:true, and no granted, waited or timedOut field.
  2. 20:15:49.962Z. Hydrogen closed its copy: self-heal closed dialog (id=grant-2420...): no longer pending on Adom Bridge. Bridge still held the card.

  3. 20:20:46Z. Shell approval card grant-2420d9053746414eb2c39cbc14403969 expired unanswered. That is 300 s in, though the caller asked for 600 s. Nothing a caller can read records it:

    • permission_history has the requested row (seq 13) but no closing row, although expired is a documented decision value. Two requests on 2026-10-28 (seq 7 and 8) have no closing row either.
    • notify_events is empty.
    • status.permissions.shell stayed {willPrompt:true, source:"none"} before and after.
    • No perm_mirror_dismiss went to Hydrogen. Bridge sent dismisses only on the 20:48:35Z decision, so Hydrogen had no way to clear what it raised for this prompt.

    So the caller kept polling until 20:25:46Z and then reported "the approval card may still be on his screen". It was not.

  4. 20:47:52.774Z. Drew clicked the bouncing Hydrogen icon. Nothing was pending anywhere.

  5. 20:48:25.885Z. The AI asked again (33 s later). Drew approved at 20:48:35.53Z (9.6 s later). That is the "about a minute".

    • Hydrogen's self-heal had again closed its copy at 20:48:28.903Z, saying it was no longer pending.
    • Bridge still accepted the decision for that same id: Shell approval from Hydrogen: allow_24h -> grant 86400s (applied: request).

The relay and Bridge were fast: the request reached Hydrogen about 30 ms after it reached Bridge.

Timeline (UTC)

Time Event Source
20:15:46.942 request_shell_approval {wait:true, timeoutSec:600} arrives (grant-2420...) permission_history seq 13; Bridge log L2897
20:15:46 warning notification; window created; Regular policy (Dock icon); window shown; reply sent at once Bridge log L2898 to L2902; startup.log 14:15:46.953 local
20:15:46.974 Hydrogen receives perm_mirror_request; Bridge logs displayed: true Hydrogen log L783; Bridge log L2905
20:15:46 the mirror comes back into Bridge: desktop_perm_mirror_request forwarded from relay by Hydrogen Bridge log L2906 to L2910
20:15:49.962 Hydrogen self-heal: "no longer pending on Adom Bridge" Hydrogen log L784
20:20:46 "expired unanswered" (300 s); no history row, no event, no status change, no dismiss to Hydrogen Bridge log L3047
20:47:52.774 Drew clicks the bouncing Hydrogen icon; nothing pending Hydrogen log L859
20:48:25.885 the AI asks again (grant-d3cc...) permission_history seq 14; Bridge log L3468
20:48:28.903 Hydrogen self-heal: "no longer pending" again Hydrogen log L863
20:48:35.533 allow_24h applied to grant-d3cc... permission_history seq 15; Bridge log L3481 to L3483
20:48:35.544 to .563 three perm_mirror_dismiss to Hydrogen (the first has id "" and decision "granted"), each coming back into Bridge Hydrogen log L864 to L866; Bridge log L3484 to L3498

Expected

  • The card lives for the caller's timeoutSec (or for a fixed lifetime that is documented and returned in the reply).
  • When the card ends, a caller can see it:
    • an expired row in permission_history;
    • an event in notify_events;
    • something in status, for example pendingApproval {id, requestedAt, expiresAt};
    • a perm_mirror_dismiss to Hydrogen and the user's other boxes, sent on expiry as well as on a decision.
  • wait:true blocks until a grant, a deny or the expiry, and says which. The Windows line has done this since 2.1.100 (adom/adom-bridge#1298).
  • A live grant request counts as pending, so Hydrogen's check keeps showing it. Today permission_history.pending ("prompts still live here") has never listed one in this data. The requests carry held:false.

Also seen in the same data

  • The decision is credited to different surfaces:

    • Bridge's log: Shell approval from Hydrogen / granted via Adom Hydrogen.
    • startup.log: PERMISSION: Hydrogen decided allow_24h.
    • permission_history: decidedVia: "ab-window".
    • Hydrogen's log: no decision line at all.

    The 2026-10-30 grant (seq 12) shows the same split. Drew says he approved in Bridge.

  • The mirror comes back through Hydrogen into Bridge. Every perm_mirror_request and perm_mirror_dismiss returns via direct_api: ... forwarded from relay by Hydrogen and [relay-via-hydrogen] Command received: app=bridge. This may be what Hydrogen's pending check trips on.

  • Bridge stays in the Regular policy after the request. No window hide or Accessory switch is logged after 20:15:46Z (log read to 21:03:59Z), so a second Adom icon stays in the Dock with nothing pending.

  • notify_events had no shell_granted event after the 20:48:35Z grant (count 0), so polling status is the only way for a caller to learn of a grant.

  • status reports embeddedPolicy: "auto-approve" (Hydrogen sends auto_approve=true on /embedded/enter), but also autoApproved:false, willPrompt:true. The adom-bridge-embedded skill says auto-approve behaves like a standing grant.

adom/adom-bridge#1490 (an approval expiry reported as a deny), #615 (prompts vanish), #1229 (stale remote cards), #1212 (Hydrogen's self-heal closing prompts Bridge had dropped), #1298 (wait:true for request_shell_approval).

Attachments

  • bridge-log-excerpt.txt: Bridge's log lines (UTC)
  • startup-log-excerpt.txt: FOREGROUND and PERMISSION lines (Mac local time, UTC-6)
  • permission-history-excerpt.json: permission_history rows 7 to 15
  • hydrogen-log-excerpt.txt: Hydrogen's log lines with UTC added
  • caller-side.md: the caller's replies, its status polls and the relay timing

Companion issue, Hydrogen's side of the same timeline: https://wiki.adom.inc/adom/hydrogen-macos/issues/22

Filed by Drew's AI agent at his request.

bridge-log-excerpt.txt

startup-log-excerpt.txt

permission-history-excerpt.json

hydrogen-log-excerpt.txt

caller-side.md

0 Replies

Log in to reply.