Closed general

Render ab's mirrored notify-decision prompts (bridge consent gates: pup_credential_reveal / pup_fill_card / pup_vault_sync) - choice ids are the button labels

John Lauer · 1mo ago ·closed by John Lauer

Context (adom-bridge #157, Ray's box blocks toasts)

Bridge consent gates (pup_credential_reveal / pup_fill_card / pup_vault_sync) block on notify_user {wait:true, buttons:[...]}. On a box that blocks Windows toasts the user never sees them. ab 2.1.48 now mirrors every waiting, buttoned notify through the SAME channel as its own permission prompts: POST /permission/request to Hydrogen when embedded, plus the mesh peers and ab's own permission stack.

What ab sends

Same shape as a shell prompt, new type:

{
  "id": "<notify correlation id>",
  "type": "notify-decision",
  "verb": "notify_user",
  "title": "Reveal a saved password?",
  "body": "pup wants to read the Chase login for chase.com. Reason: ...",
  "command": "<title>\n<body>",
  "reason": "<the structured reason when the bridge sends one>",
  "server": "<relay connection name>",
  "caller": { "aiThread": "...", "delegatedBy": "puppeteer", ... },
  "delegate": "puppeteer",
  "machine": "AdomLapper",
  "machineNodeId": "...",
  "choices": [ {"id":"Reveal","label":"Reveal","kind":"allow"}, {"id":"Deny","label":"Deny","kind":"deny"} ],
  "timeoutSec": 120
}

The choice ids are the BUTTON LABELS verbatim (not the shell vocabulary). Post the chosen id back exactly as for a shell prompt: POST /permission/resolve {id, decision:"<choice id>"}. ab matches it case-insensitively, records it as the notify response (the waiting verb returns {action:"Reveal"}), takes its own toast down, and sends /permission/dismiss {id, decision} to every other surface. A decision on any surface (toast, ab card, mesh peer, Hydrogen) wins; the others get the dismiss.

Asks

  1. Render type:"notify-decision" with title as the header, body (and reason when present) as the text, the delegate/caller as the requester line, the machine chip as for shell prompts, and the given choices as the buttons (no shell menu; no 1 hr / 24 hr / Auto).
  2. Post the chosen choices[].id back verbatim; ab rejects anything that is not one of the labels with unknown_decision.
  3. Honor /permission/dismiss for these ids the same way (first press anywhere wins; decision:"timeout" when the wait expired).

If Hydrogen already renders unknown types generically from choices, this is a confirm-only ask; either way, a screenshot of the dialog for a notify-decision would close it.

3 Replies

John Lauer · 1mo ago

Live check from AdomLapper on ab 2.1.48 + Hydrogen 1.0.217: the mirrored notify-decision already renders usably. The card shows the title as the header, the title+body in the command box, "The AI says: ", "Requested by chip-fetcher tab 3 · verified: hydrogen · via puppeteer · notify_user", and exactly the two buttons Reveal / Deny; posting Deny back resolved the waiting verb with {action:"Deny"}.

So asks 2 and 3 work today. What remains is ask 1, cosmetic but misleading: the chip reads SHELL COMMAND and the subtitle "A command wants to run." For type:"notify-decision" please use a chip like DECISION (or the delegate name, e.g. PUP) and a subtitle such as " is asking you", and render body as prose rather than in the monospace command box. Nothing runs on an allow here; it is an answer to the bridge's question.

John Lauer · 1mo ago

Ask 1 shipped in Hydrogen 1.0.220 (insiders, live now): type: "notify-decision" renders a chip named for the delegate (PUP for puppeteer, Native Browser, KiCad, Fusion, else the delegate string, else DECISION), the prompt's own title, and the subtitle "Pup is waiting on your answer. Nothing runs until you choose." instead of "A command wants to run." Asks 2 and 3 were already working. Verified on AdomLapper with a pup credential-reveal shaped prompt; the two choices Reveal / Deny render as before.

John Lauer · 1mo ago

Verified live on AdomLapper (Hydrogen 1.0.282, ab 2.1.72, 2026-09-08 14:57 UTC): a real notify_user {wait:true, buttons:[Reveal, Deny]} rendered in Hydrogen as DECISION / ON ADOMLAPPER with the labels verbatim; POST /permission/resolve {id, decision:"Deny"} through Hydrogen made ab send perm_mirror_dismiss to every surface within one second. One loose end for ab: notify_response {id} still reported pending:true after that resolve, so the durable click record is not written on the mirror-resolve path (the toast path writes it). Screenshot on the proof page in the preprod record.

Log in to reply.