pup-bridge-macos
Public Made by Adomby adom
The pup for macOS SKILL PACK: the AI skills that teach a cloud/container AI how to drive the macOS Puppeteer (pup) bridge (pup_* verbs): the everyday `pup` skill plus focused sub-skills for windows/sessions/tabs, screenshots+recording, credentials, lanes, settings, browsers+Chrome install, vendor logins and the Adom wiki. Installs into ~/.claude/skills + ~/.codex/skills. DOCS ONLY: this is NOT the bridge runtime. The bridge itself is one signed macOS binary that Adom Bridge for macOS installs an
name: pup-vendor-login description: "How to sign a user into a third-party vendor portal (Autodesk, Fusion, Mouser, DigiKey, and other SSO sites) inside a pup window, so the login PERSISTS and later visits are automatic. Covers the autonomous 'Continue with Google/Microsoft' path that needs no typed password (it reuses the profile's existing Google session), the OAuth-popup behaviour pup shows, driving Google's FedCM account chooser (which rejects ALL programmatic clicks — needs a real desktop_hover-then-click), which profile to use for crash-isolation, and the hard limit that some heavy account-admin SPAs (Autodesk's Kepler/React portal) JAM CDP so pup cannot drive the in-portal admin UI. Read this before opening any vendor login in pup. Trigger words: log into autodesk, autodesk sign in, sign into fusion, continue with google, vendor login, portal login, sso login in pup, log into mouser, digikey login, assign a license, autodesk account, manage.autodesk.com, store my login, oauth popup, account chooser."
pup-vendor-login — signing a user into a vendor portal that persists
Goal: get the user signed into a third-party site (Autodesk, Fusion, Mouser, DigiKey, …) inside a pup window so the session is stored in the durable profile and every later window is already signed in. Autodesk is the worked example; the pattern generalises.
The one-paragraph model
A vendor login is an OAuth/SSO flow. The fastest autonomous path is "Continue with Google" (or
Microsoft/Apple) because pup's durable adom-you profile usually already holds the user's Google
session — so no password is typed. The click sends the window (or an OAuth popup) to Google's
account chooser; you click the user's account; it redirects back signed-in; and the vendor cookie
persists on disk. Email+password works too but needs a credential you do not have — prefer SSO.
The recipe (Autodesk, proven 2026-07-28)
Open the login page in a durable profile, FRESH window, and pace slowly.
pup_open_window {"sessionId":"autodesk","url":"https://accounts.autodesk.com/logon"}Then WAIT ~10s before the first probe. Do NOT machine-gun navigate+eval+screenshot — rapid ops on these heavy SSO pages destabilise the CDP connection (measured: three Chrome crashes from churn alone). One op, settle, next op.
Click the SSO button (trusted CDP click via a text match; the button text often has hidden whitespace so match with a regex, not
===):pup_eval {"sessionId":"autodesk","expr":"(()=>{const b=[...document.querySelectorAll('button,a,[role=button]')].find(e=>/continue with google/i.test(e.textContent||'')&&e.offsetParent!==null); b.click(); return 'clicked';})()"}Wait ~8s.
Find where the OAuth landed — TWO shapes, handle both:
- The main window navigates to
accounts.google.com/.../accountchooser(most common), OR - An OAuth popup opens. Autodesk's popup has no opener, so pup's popup-tracker skips it
and the reclaim sweep adopts it as its own session named like
adom-you-win<rand>atsignin.autodesk.com. Runpup_list_windowsand look for the new session; drive THAT one.
- The main window navigates to
Click the account — FIRST figure out WHICH chooser you got, because they are two different things with two different answers (corrected 2026-08-22, this is the important update):
(A) The CLASSIC FULL-PAGE OAuth chooser — the common case, and it is FULLY BACKGROUND-DRIVABLE, NO foreground, NO real cursor. After "Continue with Google" the WINDOW NAVIGATES (a real top-level navigation) to
accounts.google.com/v3/signin/accountchooser?...flowName=GeneralOAuthFlow...— an ordinary Google web page, same-origin to Google, NOT an iframe. This accepts a properly dispatched synthetic click. Proven 2026-08-22 signing John into Autodesk entirely in the background (window never left z-bottom). The recipe that works — and the two traps that make a naive click fail:# find the account ROW (a <li>) whose text is JUST the account, not the whole list, get its center px: pup_eval {sessionId, expr:"(function(){var a=[...document.querySelectorAll('*')].filter(e=>/YOUR_EMAIL/i.test(e.innerText||'')&&!/another account/i.test(e.innerText||''));var t=a.sort((x,y)=>x.innerText.length-y.innerText.length)[0];var c=t.closest('li')||t;var r=c.getBoundingClientRect();return JSON.stringify({x:Math.round(r.x+r.width/2),y:Math.round(r.y+r.height/2)});})()"} # then dispatch a FULL native event sequence on the element AT THAT POINT (elementFromPoint), not on the div you matched: pup_eval {sessionId, expr:"(function(){var x=X,y=Y;var el=document.elementFromPoint(x,y);var t=el.closest('[jsaction],li')||el;var o={bubbles:true,cancelable:true,view:window,clientX:x,clientY:y,button:0};['pointerover','pointerenter','pointerdown','mousedown','focus','pointerup','mouseup','click'].forEach(function(n){try{t.dispatchEvent(new (n.slice(0,7)==='pointer'?PointerEvent:n==='focus'?FocusEvent:MouseEvent)(n,o));}catch(e){t.dispatchEvent(new MouseEvent(n==='pointerdown'?'mousedown':n,o));}});return 'clicked';})()"}- Trap 1: a bare
element.click()orpup_click {x,y}(CDP mouse) does NOTHING here — Google's rows are wired to a jsaction handler that wants the full pointer+mouse sequence, not a lone click. Measured 2026-08-22:.click()on the matched wrapper div = no-op;pup_clickat the coords = no-op; the FULL dispatched sequence above = navigated straight toprofile.autodesk.com. - Trap 2: match the tight ROW, dispatch on
elementFromPoint. The element whoseinnerTextcontains the email is often a big container that ALSO contains "Use another account"; clicking it misses. Take the shortest-text match, resolve its<li>, dispatch on whatever is actually topmost at its center pixel.
(B) The FedCM One-Tap BUBBLE — the hardened case, needs a REAL OS cursor. If "Continue with Google" shows the account WITHOUT a full navigation (a small "Sign in with Google" bubble/One-Tap, the URL stays on the vendor page, the account sits in a cross-origin FedCM iframe), then every programmatic click is rejected — DOM
.click(), the synthetic sequence,pup_click, ANDdesktop_ui_clickall fail (proven 2026-07-28). Only a real OS cursor HOVER-then-CLICK advances it:pup_raise_os_window {sessionId, foregroundReason:"<the user's words>"} # FedCM needs the window focused desktop_screenshot_window {hwnd} # get shotId + coordMap desktop_hover {space:"image", shotId, x:<account px>, y:<account px>} # MOVE the real cursor FIRST — this is the key desktop_click {space:"image", shotId, x:<same>, y:<same>} # then the real OS clickThe HOVER before the click satisfies FedCM's genuine-user-activation check. Aim by the SCREENSHOT pixel (iframe, so top-frame getBoundingClientRect can't locate it). If even that is refused, ask the USER to tap the visible account once.
So: try path (A) first — it is the common shape and needs nobody's screen. Only fall to the real-cursor path (B) when there was no navigation and the account is in a FedCM bubble.
- Trap 1: a bare
Confirm the redirect landed by SCREENSHOT, not eval — the eval often reads one beat before the redirect completes and reports the stale chooser URL while the screenshot already shows the signed-in dashboard ("Hi, "). Trust the picture.
FLUSH THE COOKIE BEFORE DOING ANYTHING ELSE — persistence is NOT automatic. Reaching the dashboard does NOT mean the login is saved. Chrome writes new cookies to disk lazily (on idle / graceful shutdown), and a fresh vendor cookie can be LOST if the Chrome crashes before it flushes. Measured live 2026-07-28: sign-in reached the Autodesk dashboard, the very next navigation crashed the Chrome, and the login was gone — a later window opened SIGNED OUT (while Gmail, whose cookie was flushed days earlier, survived). So after the dashboard appears: a. Do nothing heavy for ~10-15s (let Chrome flush), OR better,
pup_close_windowthe login window — a graceful close flushes cookies to disk. b. Reopen the vendor site in the durable profile and CONFIRM it is signed in (screenshot) BEFORE promising the user anything. Only a verified reopen proves persistence. Once flushed and confirmed, the cookie survives close, Chrome kill, and bridge restart like any other durable-profile login. Only say "you're logged in and it'll stick" once the reopen check passes — that claim was made falsely once and the window came up logged out.
ORG DEFAULT (v1.9.162): ONE shared profile for everything
John's standing decision: ALL pup windows use the single durable adom-you profile so logins
accumulate into one growing store that gets nicer to use over time. So the "dedicated per-vendor
profile" advice below is the SAFER-but-not-default option — reach for {profile:"autodesk"} only
when a specific portal is known to crash and the user asks for isolation. By default, sign the user
in on the shared profile (no profile arg). The crash tradeoff is knowingly accepted: one Chrome
process, so a portal crash takes every session down together — which is exactly why the
close+reopen+verify flush discipline in step 6 matters even more.
Which profile — the isolation option (not the default)
- Persistence needs a durable profile (default
adom-you, or a named one). Neverisolated:truefor a login you want to keep. - Crash isolation argues for a DEDICATED durable profile per vendor, e.g.
pup_open_window {"profile":"autodesk", ...}. A crash/hang during a vendor login on the SHAREDadom-youprofile takes down EVERY other session in that one Chrome process — measured live: the Autodesk flow crashed the shared Chrome and killed the user's Gmail session twice, and lost the in-flight Autodesk login because its cookie had not flushed before the crash. A per-vendor durable profile keeps the login persistent AND contains the blast radius. The one cost: SSO in a dedicated profile only reuses an existing Google session if that profile already has one; the very first Google sign-in there is a real login.
HARD LIMIT: heavy account-admin SPAs jam CDP
manage.autodesk.com/billing/user-management/... (Autodesk's "Kepler"/React account portal) reliably
jams pup's CDP pipe: the window signature is HUNG-alive / CDP-DEAD — the process lives, the log
shows KEPLER: Auth is not yet ready to mount providers, and every page.eval/page.screenshot
times out (20s), then the frame detaches. pup CANNOT reliably drive the in-portal admin UI (assigning
a license seat, editing users). Do not promise to click through it. Options, in order:
- Hand the in-portal action to the USER — pup got them signed in; the window is theirs to finish the seat assignment by hand. This is the honest, reliable answer today.
- Use the vendor's API instead of the web UI where one exists (Autodesk has account-management APIs) — no CDP, no jam.
- Never deep-link straight to the admin URL right after login — it JAMS and can CRASH the Chrome, and if the login cookie has not flushed yet (step 6) that crash DESTROYS the fresh login. Flush first (close+reopen+verify), THEN, in a SEPARATE dedicated-profile window, hand the admin page to the user — so a portal crash can never cost the sign-in again.
The RESPECTFUL way to do the FedCM click
pup_assisted_click is not available on macOS (unsupported_platform). For the account chooser,
ask the USER to click their account once in the raised window: toast and caption first, then wait for
them. If you drive it yourself with real-cursor input, follow the warn-and-wait protocol below and keep
the sequence TIGHT: any screenshot/eval between the raise and the click can steal focus and make the
click silently no-op (measured: interleaved ops failed 5x; a tight raise→capture→hover→click worked).
Pitfalls recap (each paid for on 2026-07-28)
- Rapid ops crash the Chrome → pace slowly, one op + settle.
- Shared-profile crash kills all sessions + loses un-flushed logins → dedicated durable profile.
- Google FedCM chooser rejects ALL clicks (DOM/synthetic/page.mouse/UIA) → real OS desktop_hover THEN desktop_click; the hover is mandatory.
- Button text has hidden whitespace → regex match, not
===. - Eval reads stale mid-redirect → confirm with a screenshot.
- The account-admin SPA jams CDP → hand off to the user or the API; do not fight it.
- A fresh login is NOT persisted until Chrome flushes it → close+reopen+verify BEFORE claiming it stuck; a portal crash before flush silently destroys the just-completed sign-in (happened once).
⛔ BEFORE any real-cursor step: WARN THE USER AND WAIT (John, 2026-07-29)
The desktop_hover-then-desktop_click recipe below is native OS input. It does NOT target a
window — it goes to whatever window has OS focus at that instant. This user runs several AI
threads and alt-tabs back to their own work almost immediately after any window is foregrounded.
An agent fired desktop_type here without warning; the user had already alt-tabbed away and the
text landed in THEIR document. The agent then blamed the OS for "failing to foreground the window"
instead of the obvious: the human took their focus back because nobody asked them not to.
So for EVERY native step in this skill:
notify_usertoast +desktop_captionBEFORE asking for the screen.- Say it explicitly: "please don't type or click until I say done."
- Wait until the window is genuinely the OS foreground; if they alt-tab away, HOLD, don't dispatch.
- Re-verify foreground immediately before each event — focus can move between two keystrokes, and half a password typed into the wrong window is real harm.
- Caption when DONE so they know they can use their keyboard again.
Remember the ordering rule: CDP input (pup_click/pup_type/pup_hover) needs no
foreground and disturbs nobody — native input is the LAST resort, only for what CDP genuinely
cannot drive (the FedCM chooser, native OS dialogs, sites that reject synthetic events).
---
name: pup-vendor-login
description: "How to sign a user into a third-party vendor portal (Autodesk, Fusion, Mouser, DigiKey, and other SSO sites) inside a pup window, so the login PERSISTS and later visits are automatic. Covers the autonomous 'Continue with Google/Microsoft' path that needs no typed password (it reuses the profile's existing Google session), the OAuth-popup behaviour pup shows, driving Google's FedCM account chooser (which rejects ALL programmatic clicks — needs a real desktop_hover-then-click), which profile to use for crash-isolation, and the hard limit that some heavy account-admin SPAs (Autodesk's Kepler/React portal) JAM CDP so pup cannot drive the in-portal admin UI. Read this before opening any vendor login in pup. Trigger words: log into autodesk, autodesk sign in, sign into fusion, continue with google, vendor login, portal login, sso login in pup, log into mouser, digikey login, assign a license, autodesk account, manage.autodesk.com, store my login, oauth popup, account chooser."
---
# pup-vendor-login — signing a user into a vendor portal that persists
Goal: get the user signed into a third-party site (Autodesk, Fusion, Mouser, DigiKey, …) inside a
pup window so the session is **stored in the durable profile** and every later window is already
signed in. Autodesk is the worked example; the pattern generalises.
## The one-paragraph model
A vendor login is an OAuth/SSO flow. The **fastest autonomous path is "Continue with Google"** (or
Microsoft/Apple) because pup's durable `adom-you` profile usually already holds the user's Google
session — so no password is typed. The click sends the window (or an OAuth popup) to Google's
account chooser; you click the user's account; it redirects back signed-in; and the vendor cookie
persists on disk. Email+password works too but needs a credential you do not have — prefer SSO.
## The recipe (Autodesk, proven 2026-07-28)
1. **Open the login page in a durable profile, FRESH window, and pace slowly.**
```
pup_open_window {"sessionId":"autodesk","url":"https://accounts.autodesk.com/logon"}
```
Then WAIT ~10s before the first probe. Do NOT machine-gun navigate+eval+screenshot — rapid ops
on these heavy SSO pages destabilise the CDP connection (measured: three Chrome crashes from
churn alone). One op, settle, next op.
2. **Click the SSO button** (trusted CDP click via a text match; the button text often has hidden
whitespace so match with a regex, not `===`):
```
pup_eval {"sessionId":"autodesk","expr":"(()=>{const b=[...document.querySelectorAll('button,a,[role=button]')].find(e=>/continue with google/i.test(e.textContent||'')&&e.offsetParent!==null); b.click(); return 'clicked';})()"}
```
Wait ~8s.
3. **Find where the OAuth landed — TWO shapes, handle both:**
- The main window navigates to `accounts.google.com/.../accountchooser` (most common), OR
- An OAuth **popup** opens. Autodesk's popup has **no opener**, so pup's popup-tracker skips it
and the reclaim sweep adopts it as its **own session** named like `adom-you-win<rand>` at
`signin.autodesk.com`. Run `pup_list_windows` and look for the new session; drive THAT one.
4. **Click the account — FIRST figure out WHICH chooser you got, because they are two different
things with two different answers (corrected 2026-08-22, this is the important update):**
**(A) The CLASSIC FULL-PAGE OAuth chooser — the common case, and it is FULLY BACKGROUND-DRIVABLE,
NO foreground, NO real cursor.** After "Continue with Google" the WINDOW NAVIGATES (a real
top-level navigation) to `accounts.google.com/v3/signin/accountchooser?...flowName=GeneralOAuthFlow...`
— an ordinary Google web page, same-origin to Google, NOT an iframe. This accepts a properly
dispatched synthetic click. **Proven 2026-08-22 signing John into Autodesk entirely in the
background** (window never left z-bottom). The recipe that works — and the two traps that make a
naive click fail:
```
# find the account ROW (a <li>) whose text is JUST the account, not the whole list, get its center px:
pup_eval {sessionId, expr:"(function(){var a=[...document.querySelectorAll('*')].filter(e=>/YOUR_EMAIL/i.test(e.innerText||'')&&!/another account/i.test(e.innerText||''));var t=a.sort((x,y)=>x.innerText.length-y.innerText.length)[0];var c=t.closest('li')||t;var r=c.getBoundingClientRect();return JSON.stringify({x:Math.round(r.x+r.width/2),y:Math.round(r.y+r.height/2)});})()"}
# then dispatch a FULL native event sequence on the element AT THAT POINT (elementFromPoint), not on the div you matched:
pup_eval {sessionId, expr:"(function(){var x=X,y=Y;var el=document.elementFromPoint(x,y);var t=el.closest('[jsaction],li')||el;var o={bubbles:true,cancelable:true,view:window,clientX:x,clientY:y,button:0};['pointerover','pointerenter','pointerdown','mousedown','focus','pointerup','mouseup','click'].forEach(function(n){try{t.dispatchEvent(new (n.slice(0,7)==='pointer'?PointerEvent:n==='focus'?FocusEvent:MouseEvent)(n,o));}catch(e){t.dispatchEvent(new MouseEvent(n==='pointerdown'?'mousedown':n,o));}});return 'clicked';})()"}
```
- **Trap 1: a bare `element.click()` or `pup_click {x,y}` (CDP mouse) does NOTHING here** — Google's
rows are wired to a jsaction handler that wants the full pointer+mouse sequence, not a lone click.
Measured 2026-08-22: `.click()` on the matched wrapper div = no-op; `pup_click` at the coords =
no-op; the FULL dispatched sequence above = navigated straight to `profile.autodesk.com`.
- **Trap 2: match the tight ROW, dispatch on `elementFromPoint`.** The element whose `innerText`
contains the email is often a big container that ALSO contains "Use another account"; clicking it
misses. Take the shortest-text match, resolve its `<li>`, dispatch on whatever is actually topmost
at its center pixel.
**(B) The FedCM One-Tap BUBBLE — the hardened case, needs a REAL OS cursor.** If "Continue with
Google" shows the account WITHOUT a full navigation (a small "Sign in with Google" bubble/One-Tap,
the URL stays on the vendor page, the account sits in a cross-origin FedCM iframe), then every
programmatic click is rejected — DOM `.click()`, the synthetic sequence, `pup_click`, AND
`desktop_ui_click` all fail (proven 2026-07-28). Only a real OS cursor HOVER-then-CLICK advances it:
```
pup_raise_os_window {sessionId, foregroundReason:"<the user's words>"} # FedCM needs the window focused
desktop_screenshot_window {hwnd} # get shotId + coordMap
desktop_hover {space:"image", shotId, x:<account px>, y:<account px>} # MOVE the real cursor FIRST — this is the key
desktop_click {space:"image", shotId, x:<same>, y:<same>} # then the real OS click
```
The HOVER before the click satisfies FedCM's genuine-user-activation check. Aim by the SCREENSHOT
pixel (iframe, so top-frame getBoundingClientRect can't locate it). If even that is refused, ask the USER to tap the visible account once.
**So: try path (A) first — it is the common shape and needs nobody's screen.** Only fall to the
real-cursor path (B) when there was no navigation and the account is in a FedCM bubble.
5. **Confirm the redirect landed** by SCREENSHOT, not eval — the eval often reads one beat before the
redirect completes and reports the stale chooser URL while the screenshot already shows the
signed-in dashboard ("Hi, <name>"). Trust the picture.
6. **FLUSH THE COOKIE BEFORE DOING ANYTHING ELSE — persistence is NOT automatic.** Reaching the
dashboard does NOT mean the login is saved. Chrome writes new cookies to disk lazily (on idle /
graceful shutdown), and a fresh vendor cookie can be LOST if the Chrome crashes before it flushes.
Measured live 2026-07-28: sign-in reached the Autodesk dashboard, the very next navigation crashed
the Chrome, and the login was gone — a later window opened SIGNED OUT (while Gmail, whose cookie was
flushed days earlier, survived). So after the dashboard appears:
a. Do nothing heavy for ~10-15s (let Chrome flush), OR better, `pup_close_window` the login
window — a graceful close flushes cookies to disk.
b. Reopen the vendor site in the durable profile and CONFIRM it is signed in (screenshot) BEFORE
promising the user anything. Only a verified reopen proves persistence.
Once flushed and confirmed, the cookie survives close, Chrome kill, and bridge restart like any
other durable-profile login. Only say "you're logged in and it'll stick" once the
reopen check passes — that claim was made falsely once and the window came up logged out.
## ORG DEFAULT (v1.9.162): ONE shared profile for everything
John's standing decision: ALL pup windows use the single durable `adom-you` profile so logins
accumulate into one growing store that gets nicer to use over time. So the "dedicated per-vendor
profile" advice below is the SAFER-but-not-default option — reach for `{profile:"autodesk"}` only
when a specific portal is known to crash and the user asks for isolation. By default, sign the user
in on the shared profile (no `profile` arg). The crash tradeoff is knowingly accepted: one Chrome
process, so a portal crash takes every session down together — which is exactly why the
close+reopen+verify flush discipline in step 6 matters even more.
## Which profile — the isolation option (not the default)
- **Persistence needs a durable profile** (default `adom-you`, or a named one). Never `isolated:true`
for a login you want to keep.
- **Crash isolation argues for a DEDICATED durable profile per vendor**, e.g.
`pup_open_window {"profile":"autodesk", ...}`. A crash/hang during a vendor login on the SHARED
`adom-you` profile takes down EVERY other session in that one Chrome process — measured live: the
Autodesk flow crashed the shared Chrome and killed the user's Gmail session twice, and lost the
in-flight Autodesk login because its cookie had not flushed before the crash. A per-vendor durable
profile keeps the login persistent AND contains the blast radius. The one cost: SSO in a dedicated
profile only reuses an existing Google session if that profile already has one; the very first
Google sign-in there is a real login.
## HARD LIMIT: heavy account-admin SPAs jam CDP
`manage.autodesk.com/billing/user-management/...` (Autodesk's "Kepler"/React account portal) reliably
**jams pup's CDP pipe**: the window signature is HUNG-alive / CDP-DEAD — the process lives, the log
shows `KEPLER: Auth is not yet ready to mount providers`, and every `page.eval`/`page.screenshot`
times out (20s), then the frame detaches. pup CANNOT reliably drive the in-portal admin UI (assigning
a license seat, editing users). Do not promise to click through it. Options, in order:
1. **Hand the in-portal action to the USER** — pup got them signed in; the window is theirs to finish
the seat assignment by hand. This is the honest, reliable answer today.
2. **Use the vendor's API** instead of the web UI where one exists (Autodesk has account-management
APIs) — no CDP, no jam.
3. Never deep-link straight to the admin URL right after login — it JAMS and can CRASH the Chrome,
and if the login cookie has not flushed yet (step 6) that crash DESTROYS the fresh login. Flush
first (close+reopen+verify), THEN, in a SEPARATE dedicated-profile window, hand the admin page
to the user — so a portal crash can never cost the sign-in again.
## The RESPECTFUL way to do the FedCM click
`pup_assisted_click` is not available on macOS (`unsupported_platform`). For the account chooser,
ask the USER to click their account once in the raised window: toast and caption first, then wait for
them. If you drive it yourself with real-cursor input, follow the warn-and-wait protocol below and keep
the sequence TIGHT: any screenshot/eval between the raise and the click can steal focus and make the
click silently no-op (measured: interleaved ops failed 5x; a tight raise→capture→hover→click worked).
## Pitfalls recap (each paid for on 2026-07-28)
- Rapid ops crash the Chrome → pace slowly, one op + settle.
- Shared-profile crash kills all sessions + loses un-flushed logins → dedicated durable profile.
- Google FedCM chooser rejects ALL clicks (DOM/synthetic/page.mouse/UIA) → real OS desktop_hover THEN desktop_click; the hover is mandatory.
- Button text has hidden whitespace → regex match, not `===`.
- Eval reads stale mid-redirect → confirm with a screenshot.
- The account-admin SPA jams CDP → hand off to the user or the API; do not fight it.
- A fresh login is NOT persisted until Chrome flushes it → close+reopen+verify BEFORE claiming it
stuck; a portal crash before flush silently destroys the just-completed sign-in (happened once).
## ⛔ BEFORE any real-cursor step: WARN THE USER AND WAIT (John, 2026-07-29)
The `desktop_hover`-then-`desktop_click` recipe below is **native OS input**. It does NOT target a
window — it goes to **whatever window has OS focus at that instant**. This user runs several AI
threads and alt-tabs back to their own work almost immediately after any window is foregrounded.
An agent fired `desktop_type` here without warning; the user had already alt-tabbed away and the
text landed in THEIR document. The agent then blamed the OS for "failing to foreground the window"
instead of the obvious: the human took their focus back because nobody asked them not to.
**So for EVERY native step in this skill:**
1. `notify_user` toast + `desktop_caption` BEFORE asking for the screen.
2. Say it explicitly: **"please don't type or click until I say done."**
3. Wait until the window is genuinely the OS foreground; if they alt-tab away, HOLD, don't dispatch.
4. Re-verify foreground **immediately before each event** — focus can move between two keystrokes,
and half a password typed into the wrong window is real harm.
5. Caption when DONE so they know they can use their keyboard again.
Remember the ordering rule: **CDP input (`pup_click`/`pup_type`/`pup_hover`) needs no
foreground and disturbs nobody** — native input is the LAST resort, only for what CDP genuinely
cannot drive (the FedCM chooser, native OS dialogs, sites that reject synthetic events).