app
Pup - the AI's own browser
Public Made by Adomby adom
pup gives your AI a real browser on your desktop that it drives completely, in the background, signed in as you: windows that never jump in front of your work, one shared profile that learns your logins, and every window labeled on the taskbar with its AI thread's name.
← Commit history
Publish 2.0.571
5 files changed
+55−48
package.json+2−2@@ -1,6 +1,6 @@ { "slug": "pup-bridge",- "version": "2.0.570",+ "version": "2.0.571", "type": "app", "description": "The pup SKILL PACK \u2014 the AI skills that teach a cloud/container AI how to drive the Adom Desktop Puppeteer (pup) bridge (browser_* verbs): the everyday `pup` skill plus focused sub-skills for windows/sessions/tabs, screenshots+recording, browsers+Chrome install, and driving the Adom wiki. Installs into ~/.claude/skills + ~/.codex/skills. DOCS ONLY \u2014 this is NOT the bridge runtime. The bridge itself (the Node program that drives the browser) runs on the DESKTOP: Adom Desktop bundles it and auto-installs/updates it, and it's published separately on the Releases tab as adom-bridge-puppeteer-v<ver>.zip. The pkg version is kept in lockstep with the Release version so the page's max version row always carries BOTH a pkg tarball (skills) and a runtime zip (bridge) \u2014 a skills-only or runtime-only bump on the top row breaks constraint installs. TL;DR: pkg install = the skills for your AI; the bridge = the Release zip, which Adom Desktop manages for you.", "keywords": [@@ -148,5 +148,5 @@ "prompt": "Download the puppeteer-bridge zip from the wiki and walk me through server.js" } ],- "changelog": "Two fixes found by 2.0.569's proofs. (1) The extension-lane command channel is a QUEUE: it was one slot, so two callers at once (the annotate watcher polling every 500 ms and a pup_eval, or the health tick's overlay and a verb) overwrote each other, one timed out, and the annotate watcher died on its first read. Commands queue by id, results are keyed by id, the worker drains the queue on every poll, and everything the worker had taken is re-queued on a fresh hello. (2) The annotate overlay no longer uses innerHTML: pages that enforce Trusted Types (Google Docs) refused it, so annotate had never worked there on either lane. Carries 2.0.569 (annotate on the extension lane, worker self-reload after an install)."+ "changelog": "Skills describe what shipped on 2026-09-14: the thread tile and the overlay badge are composed in the binary (pup-taskbar-states); annotate works on both lanes and the CDP-only list shrinks accordingly, plus the worker self-reload note (pup-lanes, pup-settings); the extension lane's architecture for maintainers, from the shared birth watcher to the queued channel (pup-bridge-dev). The last 41 em-dashes are gone from pup-settings and pup-taskbar-states. No code change from 2.0.570." }
page.json+2−2@@ -4,7 +4,7 @@ "slug": "pup-bridge", "title": "Pup - Puppeteer Bridge", "brief": "pup is the AI's own browser: a real, full Chrome on the user's desktop that the AI fully controls (a sandbox, not the user's signed-in browser). Rides Bridge; pup_* verbs open windows and tabs, navigate, screenshot, and eval JS.",- "version": "2.0.570",+ "version": "2.0.571", "tags": [ "skills", "pup",@@ -168,5 +168,5 @@ "pup-bridge verbs are invoked through the adom-bridge CLI, not through a binary this package installs, so prefix rules cannot reach them." ] },- "changelog": "Two fixes found by 2.0.569's proofs. (1) The extension-lane command channel is a QUEUE: it was one slot, so two callers at once (the annotate watcher polling every 500 ms and a pup_eval, or the health tick's overlay and a verb) overwrote each other, one timed out, and the annotate watcher died on its first read. Commands queue by id, results are keyed by id, the worker drains the queue on every poll, and everything the worker had taken is re-queued on a fresh hello. (2) The annotate overlay no longer uses innerHTML: pages that enforce Trusted Types (Google Docs) refused it, so annotate had never worked there on either lane. Carries 2.0.569 (annotate on the extension lane, worker self-reload after an install)."+ "changelog": "Skills describe what shipped on 2026-09-14: the thread tile and the overlay badge are composed in the binary (pup-taskbar-states); annotate works on both lanes and the CDP-only list shrinks accordingly, plus the worker self-reload note (pup-lanes, pup-settings); the extension lane's architecture for maintainers, from the shared birth watcher to the queued channel (pup-bridge-dev). The last 41 em-dashes are gone from pup-settings and pup-taskbar-states. No code change from 2.0.570." }
skills/pup-lanes/SKILL.md+4−2@@ -19,7 +19,8 @@ only CDP can do. pup no longer falls back to CDP on its own for any reason. | Debug port | none | yes, and vendor edges detect it (measured: st.com and mouser RST the HTTP/2 stream, arrow denies) | | Profile | the shared adom-you browser, one process, every thread's windows in it | any profile; on adom-you it TAKES the profile from the extension lane and closes those windows | | Toolbar | four icons: pup dots, pen, identity tile, nbe | three icons (nbe rides the extension lane only) |-| Taskbar identity, tiles, overlays, jump lists | yes | yes |+| Taskbar identity, tiles, overlays, jump lists | yes: branded BEFORE the first show (2.0.567), tile and overlay badge drawn in the binary | yes |+| Annotate (pen, snip) | yes (2.0.569, Trusted-Types safe since 2.0.570) | yes | | Vendor sites (st, mouser, digikey, arrow, analog, ti, avnet, nxp, infineon, and the rest of the 20) | load | walled by several of them | ## Pros and cons@@ -28,7 +29,7 @@ only CDP can do. pup no longer falls back to CDP on its own for any reason. - Pro: sites load. This is the reason it exists and the reason it is the default. - Pro: one shared adom-you browser, so logins and cookies accumulate for every thread, and every window carries the full toolbar including nbe. - Con: `pup_eval` runs in the page's MAIN world, so a page with a strict Content-Security-Policy (wiki.adom.inc, claude.ai) refuses it with "Evaluating a string as JavaScript violates the following Content Security Policy". Use `pup_screenshot`, `pup_list_tabs`, `pup_navigate` and the other DOM-free verbs there, or `lane:"cdp"` if you truly must run script on such a page and accept that vendor sites will not load in that window.-- Con: no trusted input events, no iframe targeting, no element or full-resolution screenshots, no annotate, no recording, no selector-driven downloads, no `realKeystrokes`, no separate profile, no `highFps`, no `webSecurity:false`. Each of those verbs answers `lane_needs_cdp` with the fix.+- Con: no trusted input events, no iframe targeting, no element or full-resolution screenshots, no recording, no selector-driven downloads, no `realKeystrokes`, no separate profile (backlog: pup-bridge#113), no `highFps`, no `webSecurity:false`. Each of those verbs answers `lane_needs_cdp` with the fix. Annotate DOES work here since 2.0.569 (the overlay is file-injected, which page CSP cannot refuse, and the capture is composed in the binary). **CDP lane** - Pro: everything DevTools can do: trusted mouse and keyboard events, cross-origin iframes, `Runtime.evaluate` that ignores page CSP, element and full-res screenshots, annotate, recording, emulation, separate profiles, anti-throttle for a live view.@@ -41,6 +42,7 @@ only CDP can do. pup no longer falls back to CDP on its own for any reason. 1. Open windows with no `lane`. You get the extension lane. 2. Do not pass `profile`, `isolated`, `highFps` or `webSecurity:false` unless you also pass `lane:"cdp"`. Without it pup refuses with `cdp_lane_required` and says why. Since 2.0.563 nothing silently opens on CDP. 3. Pass `lane:"cdp"` only when the task needs a CDP-only feature, say which one in `reason`, and expect vendor sites to wall that window.+ A pup update reaches a running extension lane on its own: pup re-stages the extension and asks the worker to reload in place (2.0.569), so no window has to close for a new build to take effect. `pup_status.extensionLane.workerVersion` shows what the lane is running. 4. If a verb answers `lane_needs_cdp`, first ask whether the task can be done without it (a screenshot instead of an eval on a CSP page, a URL download instead of a click). Only then reopen with `lane:"cdp"`. ## How you tell them apart
skills/pup-settings/SKILL.md+23−20@@ -1,16 +1,16 @@ --- name: pup-settings-description: "The complete reference to pup's behavior: every Settings toggle and the feature behind it — taskbar identity (AUMID), jump lists, the toolbar extension family, annotate/capture, foreground etiquette, the credential vault (auto-capture + autofill), in-page identity, and recovery/safety. Read to know exactly what pup does on the user's machine and how to change any of it. Change settings live with pup_configure {key:value} or the dashboard gear (Settings dialog)."+description: "The complete reference to pup's behavior: every Settings toggle and the feature behind it, taskbar identity (AUMID), jump lists, the toolbar extension family, annotate/capture, foreground etiquette, the credential vault (auto-capture + autofill), in-page identity, and recovery/safety. Read to know exactly what pup does on the user's machine and how to change any of it. Change settings live with pup_configure {key:value} or the dashboard gear (Settings dialog)." --- -# pup Settings & features — the complete behavior reference+# pup Settings & features: the complete behavior reference Every knob pup exposes, what it does, its default, and how to flip it. **Change any of these live** with `pup_configure {<key>:"on"|"off"|<value>}` (no restart), or the gear icon on the pup dashboard (`http://127.0.0.1:<port>/dashboard`). Settings persist in `~/.adom/pup-settings.json`. Defaults below are what a fresh Adom user gets. -## Taskbar identity (AUMID) — one taskbar button per pup window+## Taskbar identity (AUMID): one taskbar button per pup window Windows groups taskbar buttons by an Application User Model ID. pup can stamp a per-window AUMID so each pup window gets its OWN taskbar button with its own icon, instead of all stacking under one.@@ -23,7 +23,7 @@ Taskbar identity is a LADDER of three alternate modes, picked with ONE key (v2.0 | `taskbarMode` | **tiles** | The identity ladder. `tiles` = ONE button per AI thread, its icon the thread NAME on the Adom teal tile (name bottom-left, big font, truncated not shrunk; all the thread's windows group under it; button title = thread name). `aumid` = one button per WINDOW with pup/category icons. `plain` = no branding at all, windows stack under the stock Chrome-for-Testing button. Maps onto `aumidIcons`+`threadTiles` underneath, so those older keys still work. | | `taskbarGrouping` | **split** | aumid mode only: `split` = one button per window; `grouped` = group by category. | | `aumidIconStyle` | **category** | aumid mode only: `standard` = one pup tile for every window; `category` = per-kind tiles (wiki signed-in/out, open web, Adom app, mixed). |-| `overlayBadges` | **on** | ORTHOGONAL to the ladder: paint the active tab's favicon badge on each button (tiles and aumid modes). No Adom mark on the badge since v2.0.192 — the tile itself carries Adom identity; only the GENERIC fallback glyph (faviconless page) still includes the mark. |+| `overlayBadges` | **on** | ORTHOGONAL to the ladder: paint the active tab's favicon badge on each button (tiles and aumid modes). No Adom mark on the badge since v2.0.192, the tile itself carries Adom identity; only the GENERIC fallback glyph (faviconless page) still includes the mark. | | `overlaySize` | **75** | PERCENT of full size the favicon badge is drawn at: `50` \| `66` \| `75` \| `100`. At 100 the badge covers the thread tile's bottom line of TEXT, which is the whole point of thread tiles (it is how you tell one thread's windows from another's). Windows gives no way to ask the shell for a smaller overlay slot, so pup composites the badge at this percent inside the same canvas, anchored away from the text. Added v2.0.262 after John: "the overlay tends to cover up your bottom line of text and i'm finding that the text is super valuable so i want to be able to see it." | Two keys underneath the ladder, still settable directly and surfaced by `pup_status`:@@ -31,21 +31,21 @@ Two keys underneath the ladder, still settable directly and surfaced by `pup_sta (`plain` = aumidIcons off; `tiles` = both on; `aumid` = aumidIcons on + threadTiles off), so prefer `taskbarMode` and treat these as the older, lower-level form. -The AUMID identity is registered **registry-only (no Start Menu shortcut)** — pup writes the icon+The AUMID identity is registered **registry-only (no Start Menu shortcut)**, pup writes the icon straight into HKCU and never leaves an "Adom Pup" entry in your Start Menu (v2.0.118). -## Jump lists — the right-click menu on a pup taskbar button+## Jump lists: the right-click menu on a pup taskbar button | Key | Default | What it does | |---|---|---| | `jumpLists` | **on** | The menu Windows shows when you right-click a pup taskbar icon. Requires `aumidIcons`. | | `jlViewTasks` | **on** | "Switch to logged-in view / Switch to public view" on wiki windows. | | `jlCloseAll` | **on** | "Close all pup windows" task on every pup icon. |-| `jlDashboard` | **on** | "Open pup dashboard" task — one click opens the live window/tab/thread map. |+| `jlDashboard` | **on** | "Open pup dashboard" task, one click opens the live window/tab/thread map. | | `aumidShortcut` | **off** | Anchor each taskbar identity with a visible Start Menu shortcut (ab 2.1.49 `anchor:true`, one collapsed "Adom Pup" folder). ON = the jump list stays up on the FIRST right-click; OFF = clean Start Menu, the first right-click flashes and the second stays (ab#155, measured: no invisible anchor exists). |-| `jlAnnotate` | **on** | "Annotate this page" task — draw on the page; the capture goes to the owning AI thread. |+| `jlAnnotate` | **on** | "Annotate this page" task, draw on the page; the capture goes to the owning AI thread. | -## Toolbar extension family — buttons in the browser toolbar+## Toolbar extension family: buttons in the browser toolbar pup ships a small family of MV3 toolbar tiles (pup dots, the identity avatar, the annotate pen). They ride the Chrome-for-Testing launch (`--load-extension`); pup auto-enables Developer mode and@@ -55,13 +55,16 @@ pins them at each launch (v2.0.114), so they appear with zero setup. |---|---|---| | `toolbarExtension` | **on** | The Adom Pup toolbar buttons (annotate, snip, view toggle, dashboard, owner, close). | | `tbSnipHotkey` | **on** | `Alt+Shift+A` starts annotate in Auto; `Alt+Shift+M` starts it in Multi (compose shapes, capture on Done). Either hotkey on an open toolbar switches its mode. |-| `tbFloatyPencil` | **off** | A tiny pencil in the upper-right CORNER of each page; one click starts annotate. Off by default — the corner hover zone can fight buttons in app headers, and the toolbar pen already covers discovery. |+| `tbFloatyPencil` | **off** | A tiny pencil in the upper-right CORNER of each page; one click starts annotate. Off by default, the corner hover zone can fight buttons in app headers, and the toolbar pen already covers discovery. | | `floatyHitPx` | **24** | Size (px) of the invisible corner target that reveals the floaty pencil. Applies live. | ## Annotate & capture +Works on both lanes since 2.0.569: on the default extension lane the overlay is file-injected, so+strict-CSP and Trusted-Types pages (Google Docs) take it too.+ Draw on any pup page (pen / snip). Two capture modes, switchable in the overlay toolbar (v2.0.370):-**Auto** (default) captures the instant the mouse lifts — the draw-one-circle case; **Multi**+**Auto** (default) captures the instant the mouse lifts, the draw-one-circle case; **Multi** accumulates shapes and captures ONCE on Done, auto-advancing the color after each shape (red → blue → yellow → green → purple, never white) so every shape is distinct with zero clicks. Colors are a one-click trio (red, blue, yellow) with green/purple/white in a flyout; a manual@@ -74,7 +77,7 @@ pick overrides the cycle, and the pen cursor carries the current color. Drive it: `pup_annotate {sessionId, tool:"pen"|"snip", mode:"auto"|"multi"}`, the toolbar pen, the `Alt+Shift+A` hotkey (`Alt+Shift+M` for Multi), the jump-list task, or the (off-by-default) corner pencil. -## Foreground etiquette — pup never steals your screen+## Foreground etiquette: pup never steals your screen pup opens windows in the BACKGROUND (off-screen birth, moved on-screen within 50ms so Chrome never activates them) and signals it is working via the taskbar (`taskbarActivity`, default a progress bar)@@ -92,9 +95,9 @@ Removed in 2.0.292 (Node) and 2.0.425 (Rust): `openFlash`, `autoFlash`, `agentAc Measured 2026-09-05 (pup-bridge#99): Windows 11 25H2 (build 26200) draws no taskbar progress fill for ANY app, and a background-born window's button keeps the Windows "needs attention" tint until a real user click. The verbs still run; do not promise the pixels. | `fgCaption` | **on** | When an AI brings a window to your screen, show its stated reason as an on-screen caption. | | `fgCaptionMs` | **2000** | How long (ms) that foreground-reason caption shows. |-| `notMineCaption` | **off** | The single self-foreground caption control (v2.0.292: folded in the old `fgWatch`). Off by default. When on, pup watches for ~20s after a background open/navigate and, if a window pulls ITSELF to the front (JS/focus/Chrome, not pup), briefly captions that Adom did NOT do it. The window is no longer re-parked — off-screen birth means pup no longer needs a foreground-steal watchdog; this is now purely the "not me" caption. |+| `notMineCaption` | **off** | The single self-foreground caption control (v2.0.292: folded in the old `fgWatch`). Off by default. When on, pup watches for ~20s after a background open/navigate and, if a window pulls ITSELF to the front (JS/focus/Chrome, not pup), briefly captions that Adom did NOT do it. The window is no longer re-parked, off-screen birth means pup no longer needs a foreground-steal watchdog; this is now purely the "not me" caption. | -## Credential vault — pup manages your logins (no Chrome dialog)+## Credential vault: pup manages your logins (no Chrome dialog) pup runs its own OS-keychain password manager so the AI signs you in without Chrome's foreground picker. Chrome's native "Save password?" bubble is disabled; pup captures and fills silently.@@ -102,19 +105,19 @@ picker. Chrome's native "Save password?" bubble is disabled; pup captures and fi | Key | Default | What it does | |---|---|---| | `captureLogins` | **on** | As you sign into sites, store the username + password in the OS keychain (encrypted; never logged/echoed) so return visits auto-fill. Captures on password blur to beat cross-origin SSO redirects. |-| `autoLogin` | **on** | Fill a matching saved login when a login page loads (background, no dropdown). pup never auto-SUBMITS — submitting is reason-gated via `pup_login {submit:true, submitReason}` which confirms the live domain (anti-phishing). |+| `autoLogin` | **on** | Fill a matching saved login when a login page loads (background, no dropdown). pup never auto-SUBMITS, submitting is reason-gated via `pup_login {submit:true, submitReason}` which confirms the live domain (anti-phishing). | Verbs: `pup_login` (fill/submit; `realKeystrokes:true` for React-masked fields like Gusto), `pup_credentials` (list host+username only), `credential_set` / `credential_delete`. Per-site login flows live in `login-recipes/` on the wiki page. -## In-page identity — which thread owns this window+## In-page identity: which thread owns this window | Key | Default | What it does | |---|---|---| | `ownerChip` | **on** | A tiny non-interactive chip, bottom-left, naming the owning AI thread + profile. Click-through, can't disturb the page. |-| `titleTag` | **off** | Append "(ai-thread: <name>)" to the window title. Off — many pages manage their own title. |-| `titlePrefix` | **off** | Prepend the owning thread (+ wiki signed-in/out) to the title. Off — pup does not mangle page titles by default (see the page-integrity doctrine). |+| `titleTag` | **off** | Append "(ai-thread: <name>)" to the window title. Off, many pages manage their own title. |+| `titlePrefix` | **off** | Prepend the owning thread (+ wiki signed-in/out) to the title. Off, pup does not mangle page titles by default (see the page-integrity doctrine). | ## Recovery & safety @@ -124,11 +127,11 @@ flows live in `login-recipes/` on the wiki page. | `idleBrowserQuitMin` | **10** | Minutes a pup browser may sit with NO windows before pup closes it and gives the RAM back (0 = never close it). An empty Chrome still costs 650 MB to 1.2 GB on your machine, most of it a GPU process holding allocations from pages you already closed. The next open relaunches it, still signed in, so the only cost is one cold start. | | `sleepRecovery` | **on** | After the laptop wakes or Chrome dies, bring every pup window back at its last page, signed in. Never restarts a live Chrome. | | `reportIssues` | **on** | Let pup invite AIs to file a wiki issue when they hit something broken. |-| `minimalTouch` | **on** | Safety mode from the Chrome-crash hunt: pup keeps its hands off your windows — opens + drives pages only, skips the extra Windows machinery. The per-feature toggles above win over this master switch. |+| `minimalTouch` | **on** | Safety mode from the Chrome-crash hunt: pup keeps its hands off your windows, opens + drives pages only, skips the extra Windows machinery. The per-feature toggles above win over this master switch. | ## The one profile that matters: adom-you Every pup window rides the shared durable **adom-you** profile by default, so logins persist and the credential store grows over time. Isolation (`isolated:true`) is REASON-GATED (`isolationReason` required) and a non-adom-you window wears the anonymous identity tile so it's visibly not-you. Never-log in on an isolated throwaway — the session (and 2FA-remember) won't persist.+log in on an isolated throwaway, the session (and 2FA-remember) won't persist.
skills/pup-taskbar-states/SKILL.md+24−22@@ -3,7 +3,7 @@ name: pup-taskbar-states description: "Parent skill: pup. The definitive reference for the SIX taskbar identity states (taskbarMode tiles|aumid|plain, each with overlay badges on|off): exactly what each state looks like on the Windows taskbar, where every pixel comes from, the grouping semantics per mode, and how to switch (pup_configure or clicking a cell in the Settings matrix). Trigger words: taskbar states, taskbar identity, taskbarMode, tiles vs aumid vs plain, overlay badges, thread tiles state, taskbar matrix, six states, what does plain mode look like." --- -# pup-taskbar-states — the six taskbar identity states+# pup-taskbar-states: the six taskbar identity states Taskbar identity is one three-way mode (`taskbarMode`) crossed with one independent toggle (`overlayBadges`), giving exactly six states. This skill says precisely what each state renders,@@ -12,12 +12,12 @@ preview is DERIVED from the same sources listed here, so preview and reality can ## The two axes -- **`taskbarMode`** — `tiles` (default) | `aumid` | `plain`. Set with+- **`taskbarMode`**, `tiles` (default) | `aumid` | `plain`. Set with `pup_configure {taskbarMode:"..."}` or by clicking a matrix cell in Settings.-- **`overlaySize`** — `50` | `66` | `75` (default) | `100`: the PERCENT of full size the badge is+- **`overlaySize`**, `50` | `66` | `75` (default) | `100`: the PERCENT of full size the badge is composited at (v2.0.262). At 100 the badge covers the thread tile's bottom line of TEXT; smaller keeps the name readable, which is the point of thread tiles.-- **`overlayBadges`** — `on` (default) | `off`. The favicon badge in the button's top-right+- **`overlayBadges`**, `on` (default) | `off`. The favicon badge in the button's top-right corner. Independent of the mode; works in tiles and aumid; in plain mode Windows still accepts a per-window overlay on the stacked stock button. @@ -25,12 +25,12 @@ preview is DERIVED from the same sources listed here, so preview and reality can | # | State | Button layout | Base icon (source of truth) | Overlay | |---|-------|---------------|------------------------------|---------|-| 1 | **tiles + overlay** (DEFAULT) | ONE button per AI thread; all that thread's windows group under it; button title = thread name | The thread NAME drawn on the Adom teal tile — bottom-left anchored, font floor with truncation, wrap on space/hyphen (`renderThreadTileIco`) | Active tab's favicon on an adaptive contrast card (see below) |-| 2 | **tiles** | Same grouping as 1 | Same name tile | None — clean tile |+| 1 | **tiles + overlay** (DEFAULT) | ONE button per AI thread; all that thread's windows group under it; button title = thread name | The thread NAME drawn on the Adom teal tile, bottom-left anchored, font floor with truncation, wrap on space/hyphen (`renderThreadTileIco`) | Active tab's favicon on an adaptive contrast card (see below) |+| 2 | **tiles** | Same grouping as 1 | Same name tile | None, clean tile | | 3 | **aumid + overlay** | One button PER WINDOW (split) or per category (grouped) | The registered pup/category icon: wiki signed-in padlock, public wiki book, open-web globe, Adom app mark, mixed (`pup-cat-*.ico`, style/grouping set by `aumidIconStyle` + `taskbarGrouping`) | Same favicon badge per window | | 4 | **aumid** | Same as 3 | Same category icons | None |-| 5 | **plain + overlay** | ALL pup windows stack under the STOCK Chrome-for-Testing button — no pup identity anywhere | Chrome-for-Testing's own exe icon, untouched | Favicon badge only signal |-| 6 | **plain** | Same stacking as 5 | Same stock icon | None — indistinguishable from an unautomated browser |+| 5 | **plain + overlay** | ALL pup windows stack under the STOCK Chrome-for-Testing button, no pup identity anywhere | Chrome-for-Testing's own exe icon, untouched | Favicon badge only signal |+| 6 | **plain** | Same stacking as 5 | Same stock icon | None, indistinguishable from an unautomated browser | ## Where every pixel comes from (and how the preview stays honest) @@ -41,9 +41,11 @@ preview is DERIVED from the same sources listed here, so preview and reality can - **Plain**: pup CONVERGES every CfT window onto Chrome's own native per-profile AUMID (wiping to empty is wrong: Chrome lazily re-asserts its id and the group splits in two). The button shows the browser exe's own icon; the preview shows it via `/dashboard/baseicon?profile=adom-you`.-- **Overlay badge**: the compositor takes the active tab's favicon, puts it on an **adaptive- card** — dark card normally, LIGHT card when the favicon is dark-dominant on transparency- (the GitHub-cat case) — and hands the PNG to Windows. There is **no Adom mark on the badge**+- **Overlay badge**: composed IN THE BINARY since 2.0.568 (`pup_identity::badge`; until then an in-page+ canvas that strict-CSP sites such as Google Docs refused, so those windows had no overlay). The+ compositor takes the active tab's favicon (read by the extension on the default lane, fetched by the+ bridge as a fallback), puts it on an **adaptive card**, dark card normally, LIGHT card when the favicon is dark-dominant on transparency+ (the GitHub-cat case), and hands the PNG to Windows. There is **no Adom mark on the badge** (removed 2.0.192: the tile already carries Adom identity). The preview shows the EXACT composed PNG via `/dashboard/badge?session=<sid>`. @@ -51,7 +53,7 @@ preview is DERIVED from the same sources listed here, so preview and reality can - Switching modes re-identifies every live window immediately (stamp + button-rebuild nudge); switching to `plain` CONVERGES every window onto Chrome's own native AUMID (see the pixel-sources- section above — a VT_EMPTY wipe was tried and caused the two-CfT-buttons split; do not describe+ section above, a VT_EMPTY wipe was tried and caused the two-CfT-buttons split; do not describe plain as a "wipe"). Expect a one-time sub-second button rebuild per window on a switch. - `tiles` takes precedence over the aumid grouping/style options; those two rows only apply in `aumid` mode (the dialog grays them out otherwise).@@ -60,29 +62,29 @@ preview is DERIVED from the same sources listed here, so preview and reality can ## The foreground-window tradeoff (bounded, and it self-heals for real now) -A mode switch rebuilds every button via a brief hide+re-show — EXCEPT the window you are actively+A mode switch rebuilds every button via a brief hide+re-show, EXCEPT the window you are actively using: pup will not blink the foreground window. Its identity is stamped immediately, but its BUTTON keeps the previous name and art until that window stops being focused. **This used to be permanent** (found by John's icon audit, 2026-08-18: a thread's window sat under the stock "Google Chrome for Testing" button wearing stale teal art, hours after it was stamped).-The skip was a dead end — nothing ever retried it, despite this section once claiming it healed on+The skip was a dead end, nothing ever retried it, despite this section once claiming it healed on the next focus change. Since 2.0.227 a skipped nudge becomes a PENDING state with a bounded backoff (6s, 15s, 45s, 2m, 5m); each retry re-checks the foreground, so a window you keep using simply re-queues, and the button rebuilds the moment you look away. While it is pending, the dashboard-marks that button RED with the reason — pup never reports a green match against a taskbar it knows+marks that button RED with the reason, pup never reports a green match against a taskbar it knows it has not applied. -## Formerly-known state gaps (both CLOSED — kept so nobody re-reports them)+## Formerly-known state gaps (both CLOSED, kept so nobody re-reports them) - Progress-bar targeting (issue #54): CLOSED. Root cause was `minimalTouch` gating, not titles. - Plain-switch straggler (issue #53): CLOSED.-- Structural since: the thread AUMID folds in a hash of the tile's CONTENT (v2.0.271 — Windows+- Structural since: the thread AUMID folds in a hash of the tile's CONTENT (v2.0.271, Windows caches a button's icon PER AUMID, so only a virgin AUMID can change art), and the button rebuild waits for the icon registration to land first (v2.0.275). - Owner-loss downgrade to a category glyph (part of issue #70): **CLOSED v2.0.277.** A window that lost its owning ai-thread (recovered / reclaimed popup) used to fall through to a category AUMID- (`Adom.Pup.<sid>.<cat>`) and render the pup category icon next to real thread tiles — John's+ (`Adom.Pup.<sid>.<cat>`) and render the pup category icon next to real thread tiles, John's "inconsistent taskbar icons" (2026-08-22). `tileOwnerName()` now DERIVES a stable readable tile name from the sessionId (cleaned) when no owner is present and freezes it on the session, so in tiles mode EVERY window wears a name tile, never a category glyph. Verified: an owner-less Fusion@@ -91,15 +93,15 @@ it has not applied. - Still GENUINELY OPEN (the harder half of #70): a window that **crashes on the shared `adom-you` profile** loses its birth-hwnd, and because EVERY pup window opens at the identical rect (work area, 10px inset), bounds-resolution finds N same-geometry windows and cannot disambiguate it- (`[hwnd] "<sid>" NOT resolved — N windows on this profile, N wiggle-matches; leaving bare ++ (`[hwnd] "<sid>" NOT resolved, N windows on this profile, N wiggle-matches; leaving bare + BACKING OFF`). With `titleTag` off the window carries no `(ai-thread: <sid>)` suffix either, so the stamp's `titleContains` fallback also fails and the button sits BARE (Chrome's default icon) until the window is closed+reopened (a fresh off-screen birth captures an unambiguous hwnd). The three- candidate cures each have a real cost — transiently inject the title tag via `setTitleDecor` (it+ candidate cures each have a real cost, transiently inject the title tag via `setTitleDecor` (it is exactly what `titleTag:on` does, but it mangles the title John wants clean), give each window a 1-2px unique birth offset so bounds are always distinct (changes placement, touches the- just-rewritten off-screen-birth path), or an OS wiggle (foreground/CPU risk) — so it needs a- deliberate decision, not a rushed patch. **John's call (2026-08-22): LEAVE IT AS-IS** — do NOT+ just-rewritten off-screen-birth path), or an OS wiggle (foreground/CPU risk), so it needs a+ deliberate decision, not a rushed patch. **John's call (2026-08-22): LEAVE IT AS-IS**, do NOT touch the fragile placement/resolution path for this edge unless John reopens the decision. Backoff makes it self-limiting (5 misses → 30-min retries), and a reopen fixes it immediately.