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.
5236e66
1mo ago
Dev-skills audit: what the skills say versus what the Rust bridge does (2026-09-15)
Written for: John, for the joint review he asked for. Read-only audit, nothing was changed by it.
Method. Every file under dev-skills/ and publish-skills/ was read in full (26 files, about 5,700 lines) and compared against the 17 source files that carry the last two days of changes. The list below is ordered most serious first. Each entry names the rule (skill file and line), the code (file and line), the kind, and why it matters. Two of the most serious claims (1 and 2) were spot-checked by hand against the code before publishing; both hold.
Kinds. violation = the code breaks a rule the skill states. stale skill = the skill describes something the code no longer does. gap = a rule with no enforcing code. ok-but-undocumented = the code does something reasonable that no skill records.
Findings that are mine, from the last two days, and that I would fix first: 10 (the re-bottom after an attention clear skips the user-is-using check), 5 and 6 (the birth diff is not pid-filtered on the CDP lane; the late rebind still matches by title), 13 (R6 text now contradicts the 2.0.584 rule), 22 to 24 (the test, selftest and publish skills describe the Node pipeline; the real gates are tools/rust-build.sh, tools/parity.py and tools/ab-smoke.sh and appear in no skill).
Findings that look like deliberate later decisions the skills never caught up with, which need your call, not a code change: 1 (focus emulation was reintroduced in 2.0.458 after a skill banned it for stealing focus), 4 (per-thread AUMIDs are the design; pup-aumid-decisions still says never), 8 and 31 (three skills prescribe three different window-birth mechanisms), 17 (the icon audit is a detector because you said "i hate sweeps"; the skill still mandates a repairing sweep), 32 (progress bar is an estimate, not indeterminate).
1. Focus emulation is banned by a skill and applied to every window by the code
- RULE:
dev-skills/pup-render-test/SKILL.md:78-81: "Emulation.setFocusEmulationEnabled(tried v2.0.280-284, REVERTED in 2.0.285)... it ACTIVATES the OS window: it foregrounded a background pup window... Do NOT reintroduce it, one-shot pulse or leased." - CODE:
rust/verbs/src/lib.rs:853-865focus_emulateturns it on for every session's active tab (plus the tab a verb drives,input.rs:344), re-applied at boot and every health tick (recovery.rs:278,435,489,492);rust/cdp/src/lib.rs:530-532is the wrapper. Reintroduced in 2.0.458 ("this tab is the one pup is driving") with no note in the skill. - KIND: violation, or the skill is stale; either way the two disagree on a focus-steal mechanism.
- WHY IT MATTERS: the skill records a measured foreground steal from exactly this call; if that measurement still holds, every pup window is a latent focus thief.
2. The focus handback that pup-bridge-dev says was deleted and must never return is back
- RULE:
pup-bridge-dev/SKILL.md:472"focus handback DELETED (v2.0.276)... if it ever fires, investigate, do NOT re-add a handback";:561-567"it FOREGROUNDED unasked-for pup windows"; R2:368-373"if the window comes up FOREGROUND: let the flaw exist." - CODE:
rust/verbs/src/lib.rs:1204-1209: if the newborn took the foreground,desktop_bring_to_front {hwnd: prev_fg}"handed it back" (the comment cites Node v1.9.253, the pre-deletion version). - KIND: violation
- WHY IT MATTERS: the 2026-08-22 regression (the handback fronting another pup window with no caption) is reachable again.
3. Taskbar paints and stamps trust an hwnd without proving it belongs to a pup process
- RULE:
pup-bridge-dev/SKILL.md:1481-1496"NEVER PAINT A TASKBAR HWND YOU CANNOT PROVE IS PUP'S... PROVES it belongs to a pup browser process (owning pid)... A cached _hwnd is NEVER trusted blind";pup-taskbar-identity/SKILL.md:125-127continuity proof = persisted hwnd AND pid. - CODE:
rust/verbs/src/recovery.rs:95readopt_extaccepts the file's_hwndonIsWindowalone;recovery.rs:217same for CDP files;window.rs:14same;identity.rs:146,226stamp and overlay paint straight ontos.hwndwith no pid check;activity.rs:434progress likewise. - KIND: violation
- WHY IT MATTERS: Windows recycles hwnd numbers; a stale session file after a long sleep is the Edge-overlay incident again.
4. pup-aumid-decisions says AUMID is settled NO; the code stamps a per-thread AUMID on every window at birth
- RULE:
pup-aumid-decisions/SKILL.md:59-63"pup does NOT stamp AUMIDs. Ever. In any mode... Branding = the composed overlay badge only";:77-83a reversal needs the named-decision process. - CODE:
rust/verbs/src/settings.rs:11-12defaultstaskbarMode=tiles,aumidIcons=on,threadTiles=on;identity.rs:99-114planmints thread, session and category AUMIDs;lib.rs:1160-1162,1438preregisters and natively stamps the newborn before it is shown. - KIND: stale skill (it contradicts
pup-taskbar-identity:8andpup-bridge-dev:1713-1726, but still claims to be the settled decision). - WHY IT MATTERS: a maintainer following this skill would rip out the current identity design as a "relapse".
5. The CDP-lane birth diff is not filtered to pup's own Chrome PIDs, and the fallback loop guesses
- RULE:
pup-bridge-dev/SKILL.md:387-390,398-401R4: set-diff "filtered to this profile's Chrome PIDs... Class Chrome_WidgetWin_1 is also Edge's";:471"If more than one window appears under the lock it refuses to guess." - CODE:
rust/verbs/src/lib.rs:1419-1423birth_watch:let pids = if ext { extdrive_pids() } else { Vec::new() }, so on the CDP lane the filter is empty (every Chrome_WidgetWin_1 on the box, Edge included) althoughb.launched.pidis known;lib.rs:1180-1184the fallback takes the FIRST new untaken frame withwindows_for_pids(&[], ...)and no refuse check. - KIND: violation
- WHY IT MATTERS: a user opening Edge or Chrome in the same second can be claimed, tagged, bottomed and stamped as a pup window.
6. Ext-lane hwnd resolution still binds by TITLE and by "first visible window"
- RULE:
pup-window-targeting/SKILL.md:34-37,81-83never by title, "leave it BARE... NEVER guess";:108-114on the ext lane "when neither birth bind nor windowId is available leave it BARE." - CODE:
rust/verbs/src/extdrive.rs:554-560lane_hwnd_formatches the active tab title against window titles;recovery.rs:96-98readopt_exttakes the first visible untaken lane window (noext_sessions <= 1guard, unlikeextdrive.rs:552-553);extdrive.rs:194adopt_tokenlesslearns lane pids from windows whose title ends with "Google Chrome for Testing". - KIND: violation (the title match is acknowledged in a code comment, the readopt guess is not).
- WHY IT MATTERS: two threads on the same page, or a stale file after a restart, can again land two sessions on one button.
7. R1's 50 ms off-screen budget is neither measured nor enforced
- RULE:
pup-bridge-dev/SKILL.md:347-352"moved IMMEDIATELY... in the same synchronous stretch... Measured 27ms (budget 50ms)";:470"Logs[birth] window moved off-screen -> on-screen (x,y) in Nms";pup-no-wiggle:117-122"The[birth]log MUST report the move time." - CODE:
rust/verbs/src/lib.rs:1170-1177:attach_tabthenbirth_rect_css(a CDP evaluate with a 3 s timeout, up to 4 tries with 300 ms sleeps,lib.rs:1054-1063) run BEFOREset_window_bounds; no[birth]timing line exists. - KIND: gap
- WHY IT MATTERS: on a slow page the window can sit at -32000 for seconds, the exact "clicked the button, nothing came up" state the rule exists to kill.
8. pup-no-wiggle mandates a birth mechanism the code (and two other skills) reject
- RULE:
pup-no-wiggle/SKILL.md:64-93mandated birth = uniquePUPBIRTH-<seq>-<rand>transientdocument.title+findChromeWindowByTitle+SetProp; "The set-diff... is DELETED... Do not bring it back." - CODE:
rust/verbs/src/lib.rs:78,1150-1184,1469-1471set-diff underBIRTH_LOCK(aspup-window-targeting:71-76andpup-bridge-dev:392-402prescribe), thenhost.tagatlib.rs:1211; no title token anywhere. - KIND: stale skill
- WHY IT MATTERS: three dev skills give three different "the one sanctioned birth";
pup-no-wigglealso frames title-based birth as fine whilepup-page-integritybans title writes.
9. No visibility or off-screen sweep exists
- RULE:
pup-user-foreground/SKILL.md:88-93,109-112"a 30s sweep asserts the invariant for the whole population (sweepVisibility)... covers hidden, off-screen";pup-bridge-dev:475;pup-bridge-test:111-114scenario 7 strand-rescue expects a rescue in about 135 s. - CODE: no sweep in
rust/;recovery.rs:457-459only clears a dead hwnd;host-winhasset_visible_no_activate(:125) with no caller. - KIND: gap (and scenario 7 is untestable as written).
- WHY IT MATTERS: any future path that strands a window has no backstop; the skill calls the backstop mandatory.
10. Demotions that skip the user-is-using check
- RULE:
pup-user-foreground/SKILL.md:69-73,158"Every demotion path checksuserIsUsingWindow(session)before acting... Adding a demotion that skips this check is a bug by definition." - CODE:
rust/verbs/src/activity.rs:507clear_attentionsends to bottom whenever the window is not the current foreground (no idle or 10-minute-memory check), and runs after every ext navigate (lib.rs:1317), everydress_after(extdrive.rs:594) and at ext birth (lib.rs:1564);recovery.rs:219bottoms a recovered window on the persistedforegroundflag only. - KIND: violation (the clear_attention part is from 2.0.585, two days old)
- WHY IT MATTERS: a window the user raised minutes ago and then alt-tabbed away from is pushed to z-bottom on the next navigation.
11. Foreground captions exceed the 2 s hard cap
- RULE:
pup-bridge-dev/SKILL.md:1588-1600,1616-1621"Hard cap is enforced in code (PUP_CAPTION_MAX_MS = 2000)"; "Show it for 2 seconds maximum." - CODE:
rust/verbs/src/window.rs:31-33,50-51captionduration=fgCaptionMs, default3500(settings.rs:22), no clamp;recovery.rs:467not-mine caption 3000 ms. - KIND: violation
- WHY IT MATTERS: John caught a long caption live and set this as a standing rule.
12. The no-fault foreground watch is off by default, open-only, and mis-documented
- RULE:
pup-bridge-dev/SKILL.md:313-319clause 4: "for 20s after a background open/nav, pup watches the OS foreground... shows a 2s caption";:1638-1648describes a still-live "FG-STEAL GUARD" that bottoms takeovers (the thing:321-327says was killed the same day). - CODE:
rust/verbs/src/recovery.rs:462-469runs only whennotMineCaption == "on"(defaultoff), is armed only byopen_window(lib.rs:1258), not by navigate, and marksforeground=truewithout checking the birth grace;settings.rs:42rejectsfgWatchas removed whilesettings.rs:22still declares it. - KIND: stale skill (both clause 4 and the FG-STEAL section) plus gap.
- WHY IT MATTERS: the attribution caption John asked for does not fire on a stock install, and the skill still carries the banned enforcement guard as current.
13. pup-bridge-dev R6 contradicts pup-user-foreground 2.0.584 and the park primitive
- RULE:
pup-bridge-dev/SKILL.md:450-458R6: in the 8 s grace a foreground pup window is "BOTTOMED, never credited to the user". - CODE:
rust/verbs/src/park.rs:26-38honors input inside the grace (the 2.0.584 rule inpup-user-foreground:118-127); the observer (recovery.rs:462-469) does not check grace at all. - KIND: stale skill (R6 text) and a small gap (observer).
- WHY IT MATTERS: two doctrine files disagree on whether a click in the first 8 s wins.
14. Close reports a bookkeeping count as chromeProcsRemaining and kills one pid, no tree, no profile sweep
- RULE:
pup-bridge-dev/SKILL.md:1133-1160"report a COUNT (chromeProcsRemaining, which must be 0)... scope by ownership (profile dir)... verify withprocess_list";pup-bridge-test:75expectschromeProcsRemaining: 0. - CODE:
rust/verbs/src/lib.rs:1660"chromeProcsRemaining": ctx.browsers.lock().unwrap().len()(number of connected browser handles);lib.rs:1656kills onlyb.launched.pid;rust/host-win/src/lib.rs:274-283killis a singleTerminateProcess, no tree, no command-line sweep. - KIND: violation
- WHY IT MATTERS: the orphan-renderer CPU freeze that produced the doctrine cannot be detected from the verb's own report.
15. No overlay enforcer: a badge the shell clears stays gone until the next navigation
- RULE:
pup-icon-consistency/SKILL.md:96-100"The enforcer backstop, a 4s sweep... repaints ANY bare-or-stuck window... This is the real guarantee";pup-taskbar-identity:58-65. - CODE:
rust/verbs/src/identity.rs:224-295paints on open and navigate plus retries at 1.5 s and 4.5 s and one 30 s generic retry;activity.rs:432-435progress pushes never touchlast_paint_sig; the health tick never repaints overlays; rescan and rebind stamp but do not repaint. - KIND: gap
- WHY IT MATTERS: the default
taskbarActivity=progresspaints a bar on every screenshot, which per the skill's own measurement clears the overlay, so windows go bare for the life of a page.
16. The Adom mark on the overlay (plain mode) and the notch fallback do not exist
- RULE:
pup-icon-consistency/SKILL.md:110-119"AUMID off: favicon + Adom mark";:101-104"baked notch fallback." - CODE:
rust/identity/src/badge.rs:75-95composedraws only the favicon on a card, in every mode;tile.rshas no notch. - KIND: stale skill or gap (pick one deliberately; in plain mode pup windows now carry no Adom branding at all).
- WHY IT MATTERS: plain-mode windows are indistinguishable from a stock window, which the skill says defeats the overlay's purpose.
17. "Audit means FIX + REAPPLY, runs on its own" versus a read-only detector
- RULE:
pup-icon-audit/SKILL.md:20-23"pup_audit_icons {}(it repairs by default;fix:falsefor a dry run)";:50-57runs on a schedule. - CODE:
rust/verbs/src/identity.rs:321-341auditis report-only with nofixargument;extras.rs:162-181a 5-minute detector that explicitly does not re-stamp, citing John 2026-09-06 "i hate sweeps". - KIND: stale skill (John's later directive reversed it).
- WHY IT MATTERS: the skill tells the next maintainer to build the sweep John since forbade.
18. Switching to plain mode strips nothing; mode flips have no generation guard
- RULE:
pup-mode-ralph/SKILL.md:45-55,59-63plain = wipe + null WM_SETICON + deleteAdom.Pup.*keys + converge to Chrome's native AUMID + nudge;_identityGenaborts in-flight stamps on a rapid flip. - CODE:
rust/verbs/src/settings.rs:56toidentity.rs:304-306reapply_alltostamptoidentity.rs:148if m == "plain" { return }: existing stamps, keys and jump lists stay; each flip spawns an unguarded thread. - KIND: gap (and
tools/selftest.sh:104-112T5/T6 "plain = zero Adom.Pup keys" will misjudge it). - WHY IT MATTERS: the RAPID double-click race and "branded buttons in plain mode" are both reachable.
19. The jump-list "blip" cause and fix are superseded, and there is no task-set dedup
- RULE:
pup-jumplist/SKILL.md:19-48cause = re-committing near the click; fix = hash the task set;pup-bridge-debug:771-795"UNRESOLVED, tracked on adom-bridge#40". - CODE:
rust/verbs/src/identity.rs:31-36measured cause = registry-only AUMID (ab#155), fix = opt-in Start Menu anchoraumidShortcut(default off);identity.rs:152-162commits the list on every full stamp with no hash. - KIND: stale skill (both files)
- WHY IT MATTERS: the next person chasing the blip is sent to the wrong cause with a fix already known not to work.
20. Jump-list launcher doctrine describes the retired PowerShell launcher
- RULE:
pup-taskbar-identity/SKILL.md:69-116tasks targetpowershell.exerunningpup-jumplist-call.ps1;ralph_jumplist.shfires "through the real deployed launcher". - CODE:
rust/verbs/src/identity.rs:46-48deletes the.ps1at boot;:88-97tasks run pup's own exe--jumplist <verb> <b64>. - KIND: stale skill (and
ralph_jumplist.shtests a path pup removes). - WHY IT MATTERS: the "real click path" test now exercises a launcher that no longer exists.
21. Foreground-window capture uses Page.captureScreenshot, the rail the skill says blips
- RULE:
pup-taskbar-identity/SKILL.md:153-164"any capture of a window the user is looking at rides the screencast rail... never captureScreenshot." - CODE:
rust/verbs/src/transport.rs:936-940annotate'scapture_viewport_pngsendsPage.captureScreenshoton the CDP lane;src/extension/worker.js:159-172the ext lane falls back to debuggerPage.captureScreenshot. - KIND: violation
- WHY IT MATTERS: annotate photographs the one window the user is watching.
22. tools/selftest.sh and pup-selftest test the Node shell; the Rust shell's real gates are undocumented
- RULE:
pup-selftest/SKILL.md:16-25T1 "static parse (server + SERVED dashboard script)", T6 "jump-list commit lines present", T7 "steady-state enum <= 2 calls/45s", "run after EVERY ship". - CODE:
tools/selftest.sh:21-23runsnode --check src/server.js(the Node tree, not the exe); T6 greps for a log line the Rust bridge emits only on failure; T7 reads/status.enumWindows, whichlib.rs:1028hardcodes to zeros (vacuous pass). The Rust ship's actual gates (tools/rust-build.shwithcargo test,check-borders.sh,gen-assets.py;tools/parity.py;tools/ab-smoke.sh) appear in neitherpup-selftestnorpup-bridge-test. - KIND: stale skill plus ok-but-undocumented.
- WHY IT MATTERS: "13/13 GREEN" from this script proves little about the shipped binary.
23. pup-bridge-test scenarios: which exist as scripts, which are stale
- RULE:
pup-bridge-test/SKILL.mdscenarios 1 to 12 and 11b. - CODE: scripted only in part: smoke is roughly
tools/ab-smoke.sh; the concurrency invariant is roughlydev-skills/pup-taskbar-identity/ralph_icons.shbut it greps log strings the Rust bridge never emits; #46 churn =tools/churn-ralph.sh. Scenarios 2 to 12 have no script. Stale expectations: scenarios 3 and 6 expect[flash] (launch)and[park]lines per window, but the default never flashes and park logs only the grace case; scenario 7 needs the missing sweep (#9); scenario 11 expects[heal]lines, Rust logs[recovery]and[health]; the standing directive at:8-13is done (lib.rs:703-721);:14-25is Node-era. Scenario 11b matches the code. - KIND: stale skill plus gap (no scripts).
- WHY IT MATTERS: the "standard test scenarios" cannot be run as written and several would fail on log strings alone.
24. pup-bridge-publish describes the Node/public-tier pipeline; ship.sh is the Rust/insiders pipeline
- RULE:
pup-bridge-publish/SKILL.md:16-20,45-60release zip =src/Node tree;:71-80edit and push the PUBLIC manifest;:96-102files[]= five files;:116-150GATES 1 to 3;pup-bridge-dev:1221-1231"Three gates now in/tmp/ship.sh". - CODE:
tools/ship.shdefault--shell rust; writes the INSIDERS manifest, never the public one (promotion viatools/promote.sh); pushesskills/,dev-skills/andpublish-skills/trees; strict-YAML gate;package.jsonfiles[]now lists 12 user skills; no repo-freshness gate, no served-zip re-download, nobridge_installin the script. - KIND: stale skill plus gap.
- WHY IT MATTERS: following the publish skill verbatim would push the public manifest and bypass the insiders tier.
25. pup-cdp-discipline's model describes the Node process; Runtime stays enabled on every tab
- RULE:
pup-cdp-discipline/SKILL.md:19-31single Node event loop; rule 1:35-43"no extra CDP domain enabled...Runtimeis the same hazard"; rule 2 balance attach and detach. - CODE:
rust/cdp/src/lib.rs:518-525page_enableenablesRuntimeon every attached tab unlesscdpQuiet=on(default off); one reader thread per browser;attach_tabnever detaches by design. - KIND: stale skill (model) with a partial rule-1 deviation.
- WHY IT MATTERS: the acceptance test and the "loop starvation" diagnosis no longer describe how this bridge fails.
26. Firewall rule: two Chrome launch sites lack the network-quieting flags
- RULE:
pup-no-firewall/SKILL.md:50-53,86-96every separate Chrome launch gets the MediaRouter disables, QUIC and WebRTC flags. - CODE:
rust/verbs/src/record.rs:239recorder HUD launch has only two disables;rust/browser/src/lib.rs:513-528stockFlags:onCDP launch carries none (the ext-lane stock launch does). - KIND: violation (recorder HUD), gap (stock CDP flags).
- WHY IT MATTERS: a first recording or a
stockFlagsexperiment can pop the Windows Firewall dialog.
27. Loop radar is mostly blind in the Rust /status
- RULE:
pup-bridge-dev/SKILL.md:1699-1711wrap EVERY loop;/statuscarriesloops,win32Calls,enumWindows,log. - CODE:
rust/verbs/src/lib.rs:1028those fields are hardcoded to zeros and empties; only 4 loops tick; identity, overlay, progress and birth-watch threads are untracked. - KIND: stale skill plus gap.
- WHY IT MATTERS: John's replacement radar for "a misbehaving pup" reports zeros.
28. background verdict is hardcoded, not measured
- RULE:
pup-bridge-dev/SKILL.md:602-605"The park's verdict comes from CDP getWindowBounds... surfaces as thebackgroundfield." - CODE:
rust/verbs/src/lib.rs:1265open always returns"background": "backgrounded"even whenparked == falseorhwnd == None;session_rowuses a different vocabulary. - KIND: violation
- WHY IT MATTERS: the self-verify verdict can say "backgrounded" for an unparked window.
29. R5 "identity is async and never gates R1" is no longer true
- RULE:
pup-bridge-dev/SKILL.md:404-407"AUMID stamping, tile art... must never gate R1." - CODE:
rust/verbs/src/lib.rs:1160-1162,1407-1409birth_watchrenders the tile and registers the AUMID through ab (8 s timeout) BEFOREcreate_target, inside the birth lock;lib.rs:1438stamps natively in-process althoughidentity.rs:3-4says every stamp goes through ab. - KIND: stale skill (R5) plus ok-but-undocumented (the 2.0.446 pre-stamp design lives only in code comments).
- WHY IT MATTERS: the placement doctrine and the identity doctrine disagree on ordering; a bridge restart also orphans the in-process icon handle until ab re-stamps.
30. Recovery has no on-disk crash breaker
- RULE:
pup-bridge-debug/SKILL.md:80-87"the only defense against a native-crash-on-boot loop is a PERSISTENT circuit breaker...recoverAttemptsin the session file." - CODE:
rust/verbs/src/recovery.rs:40,115-116RELAUNCHESis in-memory;recover_at_bootwrites no marker before the risky ops. - KIND: gap
- WHY IT MATTERS: a session file that crashes the exe at boot re-crashes every boot.
31. pup-taskbar-identity's recovered-window resolution stack contradicts pup-no-wiggle and the code
- RULE:
pup-taskbar-identity/SKILL.md:123-140items 2 to 4: natural-title match, "off-screen re-capture: move it via CDP and identify by bounds change", persisted-claims map. - CODE:
rust/verbs/src/recovery.rs:217-218persisted hwnd else the tag property lookup (thepup-no-wigglemethod); item 3 is the banned wiggle. - KIND: stale skill
- WHY IT MATTERS: two identity skills prescribe opposite fallbacks.
32. Agent-activity progress: skill says indeterminate, code is a determinate estimate bar
- RULE:
pup-bridge-debug/SKILL.md:526-535"State isindeterminate(marquee), NOT a percentage... a fake percentage would be a lie." - CODE:
rust/verbs/src/activity.rs:432-471pushesstate:"normal"with a value filling over a running-average estimate every 180 ms, capped at 92 %, then 100 %. - KIND: stale skill
- WHY IT MATTERS: the doctrine and the behavior John sees on his taskbar disagree.
33. Dead code that carries a banned behavior
- RULE:
pup-window-targeting/SKILL.mdnever stamp another thread's window. - CODE:
rust/verbs/src/extdrive.rs:620-647dress_windowstamps every visible lane window with the CALLING thread's identity; its callers are not reachable fromdispatch.rust/verbs/assets/title.jsandpage-tag.js(title injectors banned bypup-page-integrity) are unreferenced;src/extension/worker.js:5-7still says ownership rides the tab title. - KIND: ok-but-undocumented (dead), worth deleting before someone wires it back.
- WHY IT MATTERS: the next "why is this window bare" fix could re-enable a cross-thread stamp.
34. Bot-wall reporting: partial, and the hint contradicts the lane doctrine
- RULE:
pup-bot-walls/SKILL.md:198-202return abotWallfield + errorCode;:82-96,178-179check velocity and cookies and retry paced before blaming the site. - CODE:
rust/verbs/src/lib.rs:354-361render_checkaddschrome_error_page+ afallbackHintsaying "pup's Chrome for Testing is blocked... Do not retry in pup: switch lanes" tonbrowser_open_window, on both lanes, with nobotWallfield. - KIND: gap (field) and stale hint text (written before the ext lane became the vendor-site lane).
- WHY IT MATTERS: the calling AI is told to abandon the lane that the same repo says loads 20 of 20 vendor sites.
35. pup-browser-detection contradicts its own retraction
- RULE:
pup-browser-detection/SKILL.md:71-78RETRACTED the CfT-version cause;:143-144decision step 4 still says "check the CfT version matches the installed Chrome";:131table lists "matched CfT version" as a remedy. - CODE:
rust/browser/src/lib.rs:26CFT_BUILD_IDpinned;lib.rs:248-250grease_forknows only major 152 and falls back to the old GREASE for anything newer. - KIND: stale skill (internal), plus a code fragility (a Chrome 153 user gets a wrong GREASE brand).
- WHY IT MATTERS: the skill sends a diagnosis down a path it already withdrew.
36. pup-user-foreground's "ab migration" note does not match how the primitive was ported
- RULE:
pup-user-foreground/SKILL.md:208-215PS to ab verbs (desktop_get_foreground,desktop_user_idle_ms,desktop_clear_window_attention); prefer a combined ab verb. - CODE:
rust/verbs/src/park.rs:22-40reads foreground and idle in-process;activity.rs:498separately asks abdesktop_get_foregroundfor the same fact. - KIND: ok-but-undocumented (two sources of foreground truth).
- WHY IT MATTERS: minor, but the skill points at verbs the demotion path does not use.
Node-era names presented as live code (stale-skill class)
Names that present Node functions, files or runtime as current, per skill (from a repo-wide grep; each appears in running text, not only in dated history):
- pup-bridge-dev (76 hits):
server.js,chrome.js,win32.js(koffi),createPageInNewWindow,withBirthLock,resolveSessionHwndByBounds,hwndBelongsToPup,stampPupIdentity,updateWikiJumplist,osBottomUnlessForeground,userIsUsingWindow,parkSessionWindowDirect,healOffscreenWindow,sweepVisibility,recoverSessions,getOrLaunchBrowser,_launchInFlight,trackedLoop,sendJSON,adCommand,pupCaption,PUP_CAPTION_MAX_MS,captionForegroundReason,osClearFlashByActivate,osIdleMs,_bornAt,ensureSafeForNativeInput,primaryWorkArea(),birthRect()"in server.js" (the R1 to R6 implementation map at:464-475is entirely Node),node --check,npm install,tests/dashboard_ralph.sh,/tmp/ship.sh, "Repo layout":123-137, "Node is handled by AD core":155. - pup-bridge-publish (42):
server.js,chrome.js, thesrc/zip,node_modules,PUBLISHING.md, the Node-bridge gotcha section. - pup-bridge-debug (25):
recoverSessions,recoverAttempts,_launchInFlight,getOrLaunchBrowser,process.on('uncaughtException'),node.exespawn cadence,chrome.adCommanddirect-API subset,stampPupIdentity,updateWikiJumplist,brandPupWindow,updateTabCountBadge,markSessionBusy,reclaimUnmanagedWindows,rescanProfile,killBrowserProcess,execFileSync,adom-desktop-cli.exejump-list args. - pup-window-targeting (18):
windowTarget(), thechrome.adCommand(...)snippet,createPageInNewWindow,page.__pupHwnd,hwndBelongsToPup,recoverSessions,rescanProfile,updateWikiJumplist,withBirthLock. - pup-taskbar-identity (16):
createPageInNewWindow,_birthLock,hwndBelongsToPup,hwndOwnedByOtherSession,stampPupIdentity,applyAppOverlay,resolveSessionHwndByBounds,pupTask(),ensurePupJumplistLauncher(),writePupPortFile(),pupCliExe(),flickerFreeShot,sharp, "in server.js". - pup-user-foreground (10):
osBottomUnlessForeground,userIsUsingWindow,parkSessionWindowDirect,reassertBottomAfterNav,kickoffPark,healOffscreenWindow,sweepVisibility,osIdleMs, "ShowWindow(...,0)appears exactly once inserver.js",puppeteer.connect. - pup-no-wiggle (8):
server.js,src/win32.js,findChromeWindowByTitle,findWindowByProp,fixHiddenOrOffscreen,resolveSessionHwndByBounds,bestSessionHwnd,npm install. - pup-selftest (8):
windowTarget,_wikiJumplistKey,_lastPaintSig,_appOverlay,_curAppId,tests/check_dashboard_script.js, "KILL the node process", T1 "server parses". - pup-differential-diagnosis (6): Node process and pid,
uncaughtException,:64230,createCDPSession,sharp. - pup-cdp-discipline (5): Node event loop,
:64230,createCDPSession,.detach(),neutralizeDebugger,sharp. - pup-icon-consistency (4):
applyAppOverlay,resolveSessionHwndByBounds,_curAppId,resolveFaviconRich,analyzeIconBytes. - pup-no-firewall (3):
mergeChromiumFeatureFlags()"server.js, v2.0.293",puppeteer.launch args,BIND_HOST. - pup-mode-ralph (3):
_identityGen,stripAllPupIdentities, thecn-dashpup_eval driver. - pup-jumplist (3):
updateWikiJumplist,_registeredPupAumids,jarg. - pup-browser-import (3):
chrome.adCommand(...),credentialVault.mergeImportedCredentials,src/credential_vault.js. - pup-icon-audit (2):
src/server.js,NUDGE_RETRY_DELAYS,stripAllPupIdentities,_buttonBuiltAt. - pup-bridge-test (2):
callerOwnWindow(), "~line 1160" recovery loop,_profileOpenChain,reclaimUnmanagedWindows,getSessionInfoFast. - pup-bot-walls (1):
computeConsumerUA()andapplyConsumerUA()"inserver.js" (Rust:consumer_ua,apply_consumer_identity,lib.rs:266-299).
Skills with no Node-era live-code references: pup-aumid-decisions, pup-auto-mode, pup-doppelganger, pup-hero-image, pup-page-integrity, pup-real-images, pup-render-test, pup-browser-detection.
# Dev-skills audit: what the skills say versus what the Rust bridge does (2026-09-15)
**Written for: John, for the joint review he asked for.** Read-only audit, nothing was changed by it.
**Method.** Every file under `dev-skills/` and `publish-skills/` was read in full (26 files, about 5,700 lines) and compared against the 17 source files that carry the last two days of changes. The list below is ordered most serious first. Each entry names the rule (skill file and line), the code (file and line), the kind, and why it matters. Two of the most serious claims (1 and 2) were spot-checked by hand against the code before publishing; both hold.
**Kinds.** *violation* = the code breaks a rule the skill states. *stale skill* = the skill describes something the code no longer does. *gap* = a rule with no enforcing code. *ok-but-undocumented* = the code does something reasonable that no skill records.
**Findings that are mine, from the last two days, and that I would fix first:** 10 (the re-bottom after an attention clear skips the user-is-using check), 5 and 6 (the birth diff is not pid-filtered on the CDP lane; the late rebind still matches by title), 13 (R6 text now contradicts the 2.0.584 rule), 22 to 24 (the test, selftest and publish skills describe the Node pipeline; the real gates are tools/rust-build.sh, tools/parity.py and tools/ab-smoke.sh and appear in no skill).
**Findings that look like deliberate later decisions the skills never caught up with, which need your call, not a code change:** 1 (focus emulation was reintroduced in 2.0.458 after a skill banned it for stealing focus), 4 (per-thread AUMIDs are the design; pup-aumid-decisions still says never), 8 and 31 (three skills prescribe three different window-birth mechanisms), 17 (the icon audit is a detector because you said "i hate sweeps"; the skill still mandates a repairing sweep), 32 (progress bar is an estimate, not indeterminate).
---
## 1. Focus emulation is banned by a skill and applied to every window by the code
- RULE: `dev-skills/pup-render-test/SKILL.md:78-81`: "`Emulation.setFocusEmulationEnabled` (tried v2.0.280-284, REVERTED in 2.0.285)... it ACTIVATES the OS window: it foregrounded a background pup window... Do NOT reintroduce it, one-shot pulse or leased."
- CODE: `rust/verbs/src/lib.rs:853-865` `focus_emulate` turns it on for every session's active tab (plus the tab a verb drives, `input.rs:344`), re-applied at boot and every health tick (`recovery.rs:278,435,489,492`); `rust/cdp/src/lib.rs:530-532` is the wrapper. Reintroduced in 2.0.458 ("this tab is the one pup is driving") with no note in the skill.
- KIND: violation, or the skill is stale; either way the two disagree on a focus-steal mechanism.
- WHY IT MATTERS: the skill records a measured foreground steal from exactly this call; if that measurement still holds, every pup window is a latent focus thief.
## 2. The focus handback that pup-bridge-dev says was deleted and must never return is back
- RULE: `pup-bridge-dev/SKILL.md:472` "focus handback DELETED (v2.0.276)... if it ever fires, investigate, do NOT re-add a handback"; `:561-567` "it FOREGROUNDED unasked-for pup windows"; R2 `:368-373` "if the window comes up FOREGROUND: let the flaw exist."
- CODE: `rust/verbs/src/lib.rs:1204-1209`: if the newborn took the foreground, `desktop_bring_to_front {hwnd: prev_fg}` "handed it back" (the comment cites Node v1.9.253, the pre-deletion version).
- KIND: violation
- WHY IT MATTERS: the 2026-08-22 regression (the handback fronting another pup window with no caption) is reachable again.
## 3. Taskbar paints and stamps trust an hwnd without proving it belongs to a pup process
- RULE: `pup-bridge-dev/SKILL.md:1481-1496` "NEVER PAINT A TASKBAR HWND YOU CANNOT PROVE IS PUP'S... PROVES it belongs to a pup browser process (owning pid)... A cached _hwnd is NEVER trusted blind"; `pup-taskbar-identity/SKILL.md:125-127` continuity proof = persisted hwnd AND pid.
- CODE: `rust/verbs/src/recovery.rs:95` `readopt_ext` accepts the file's `_hwnd` on `IsWindow` alone; `recovery.rs:217` same for CDP files; `window.rs:14` same; `identity.rs:146,226` stamp and overlay paint straight onto `s.hwnd` with no pid check; `activity.rs:434` progress likewise.
- KIND: violation
- WHY IT MATTERS: Windows recycles hwnd numbers; a stale session file after a long sleep is the Edge-overlay incident again.
## 4. pup-aumid-decisions says AUMID is settled NO; the code stamps a per-thread AUMID on every window at birth
- RULE: `pup-aumid-decisions/SKILL.md:59-63` "pup does NOT stamp AUMIDs. Ever. In any mode... Branding = the composed overlay badge only"; `:77-83` a reversal needs the named-decision process.
- CODE: `rust/verbs/src/settings.rs:11-12` defaults `taskbarMode=tiles`, `aumidIcons=on`, `threadTiles=on`; `identity.rs:99-114` `plan` mints thread, session and category AUMIDs; `lib.rs:1160-1162,1438` preregisters and natively stamps the newborn before it is shown.
- KIND: stale skill (it contradicts `pup-taskbar-identity:8` and `pup-bridge-dev:1713-1726`, but still claims to be the settled decision).
- WHY IT MATTERS: a maintainer following this skill would rip out the current identity design as a "relapse".
## 5. The CDP-lane birth diff is not filtered to pup's own Chrome PIDs, and the fallback loop guesses
- RULE: `pup-bridge-dev/SKILL.md:387-390,398-401` R4: set-diff "filtered to this profile's Chrome PIDs... Class Chrome_WidgetWin_1 is also Edge's"; `:471` "If more than one window appears under the lock it refuses to guess."
- CODE: `rust/verbs/src/lib.rs:1419-1423` `birth_watch`: `let pids = if ext { extdrive_pids() } else { Vec::new() }`, so on the CDP lane the filter is empty (every Chrome_WidgetWin_1 on the box, Edge included) although `b.launched.pid` is known; `lib.rs:1180-1184` the fallback takes the FIRST new untaken frame with `windows_for_pids(&[], ...)` and no refuse check.
- KIND: violation
- WHY IT MATTERS: a user opening Edge or Chrome in the same second can be claimed, tagged, bottomed and stamped as a pup window.
## 6. Ext-lane hwnd resolution still binds by TITLE and by "first visible window"
- RULE: `pup-window-targeting/SKILL.md:34-37,81-83` never by title, "leave it BARE... NEVER guess"; `:108-114` on the ext lane "when neither birth bind nor windowId is available leave it BARE."
- CODE: `rust/verbs/src/extdrive.rs:554-560` `lane_hwnd_for` matches the active tab title against window titles; `recovery.rs:96-98` `readopt_ext` takes the first visible untaken lane window (no `ext_sessions <= 1` guard, unlike `extdrive.rs:552-553`); `extdrive.rs:194` `adopt_tokenless` learns lane pids from windows whose title ends with "Google Chrome for Testing".
- KIND: violation (the title match is acknowledged in a code comment, the readopt guess is not).
- WHY IT MATTERS: two threads on the same page, or a stale file after a restart, can again land two sessions on one button.
## 7. R1's 50 ms off-screen budget is neither measured nor enforced
- RULE: `pup-bridge-dev/SKILL.md:347-352` "moved IMMEDIATELY... in the same synchronous stretch... Measured 27ms (budget 50ms)"; `:470` "Logs `[birth] window moved off-screen -> on-screen (x,y) in Nms`"; `pup-no-wiggle:117-122` "The `[birth]` log MUST report the move time."
- CODE: `rust/verbs/src/lib.rs:1170-1177`: `attach_tab` then `birth_rect_css` (a CDP evaluate with a 3 s timeout, up to 4 tries with 300 ms sleeps, `lib.rs:1054-1063`) run BEFORE `set_window_bounds`; no `[birth]` timing line exists.
- KIND: gap
- WHY IT MATTERS: on a slow page the window can sit at -32000 for seconds, the exact "clicked the button, nothing came up" state the rule exists to kill.
## 8. pup-no-wiggle mandates a birth mechanism the code (and two other skills) reject
- RULE: `pup-no-wiggle/SKILL.md:64-93` mandated birth = unique `PUPBIRTH-<seq>-<rand>` transient `document.title` + `findChromeWindowByTitle` + `SetProp`; "The set-diff... is DELETED... Do not bring it back."
- CODE: `rust/verbs/src/lib.rs:78,1150-1184,1469-1471` set-diff under `BIRTH_LOCK` (as `pup-window-targeting:71-76` and `pup-bridge-dev:392-402` prescribe), then `host.tag` at `lib.rs:1211`; no title token anywhere.
- KIND: stale skill
- WHY IT MATTERS: three dev skills give three different "the one sanctioned birth"; `pup-no-wiggle` also frames title-based birth as fine while `pup-page-integrity` bans title writes.
## 9. No visibility or off-screen sweep exists
- RULE: `pup-user-foreground/SKILL.md:88-93,109-112` "a 30s sweep asserts the invariant for the whole population (`sweepVisibility`)... covers hidden, off-screen"; `pup-bridge-dev:475`; `pup-bridge-test:111-114` scenario 7 strand-rescue expects a rescue in about 135 s.
- CODE: no sweep in `rust/`; `recovery.rs:457-459` only clears a dead hwnd; `host-win` has `set_visible_no_activate` (`:125`) with no caller.
- KIND: gap (and scenario 7 is untestable as written).
- WHY IT MATTERS: any future path that strands a window has no backstop; the skill calls the backstop mandatory.
## 10. Demotions that skip the user-is-using check
- RULE: `pup-user-foreground/SKILL.md:69-73,158` "Every demotion path checks `userIsUsingWindow(session)` before acting... Adding a demotion that skips this check is a bug by definition."
- CODE: `rust/verbs/src/activity.rs:507` `clear_attention` sends to bottom whenever the window is not the current foreground (no idle or 10-minute-memory check), and runs after every ext navigate (`lib.rs:1317`), every `dress_after` (`extdrive.rs:594`) and at ext birth (`lib.rs:1564`); `recovery.rs:219` bottoms a recovered window on the persisted `foreground` flag only.
- KIND: violation (the clear_attention part is from 2.0.585, two days old)
- WHY IT MATTERS: a window the user raised minutes ago and then alt-tabbed away from is pushed to z-bottom on the next navigation.
## 11. Foreground captions exceed the 2 s hard cap
- RULE: `pup-bridge-dev/SKILL.md:1588-1600,1616-1621` "Hard cap is enforced in code (`PUP_CAPTION_MAX_MS = 2000`)"; "Show it for 2 seconds maximum."
- CODE: `rust/verbs/src/window.rs:31-33,50-51` caption `duration` = `fgCaptionMs`, default `3500` (`settings.rs:22`), no clamp; `recovery.rs:467` not-mine caption 3000 ms.
- KIND: violation
- WHY IT MATTERS: John caught a long caption live and set this as a standing rule.
## 12. The no-fault foreground watch is off by default, open-only, and mis-documented
- RULE: `pup-bridge-dev/SKILL.md:313-319` clause 4: "for 20s after a background open/nav, pup watches the OS foreground... shows a 2s caption"; `:1638-1648` describes a still-live "FG-STEAL GUARD" that bottoms takeovers (the thing `:321-327` says was killed the same day).
- CODE: `rust/verbs/src/recovery.rs:462-469` runs only when `notMineCaption == "on"` (default `off`), is armed only by `open_window` (`lib.rs:1258`), not by navigate, and marks `foreground=true` without checking the birth grace; `settings.rs:42` rejects `fgWatch` as removed while `settings.rs:22` still declares it.
- KIND: stale skill (both clause 4 and the FG-STEAL section) plus gap.
- WHY IT MATTERS: the attribution caption John asked for does not fire on a stock install, and the skill still carries the banned enforcement guard as current.
## 13. pup-bridge-dev R6 contradicts pup-user-foreground 2.0.584 and the park primitive
- RULE: `pup-bridge-dev/SKILL.md:450-458` R6: in the 8 s grace a foreground pup window is "BOTTOMED, never credited to the user".
- CODE: `rust/verbs/src/park.rs:26-38` honors input inside the grace (the 2.0.584 rule in `pup-user-foreground:118-127`); the observer (`recovery.rs:462-469`) does not check grace at all.
- KIND: stale skill (R6 text) and a small gap (observer).
- WHY IT MATTERS: two doctrine files disagree on whether a click in the first 8 s wins.
## 14. Close reports a bookkeeping count as `chromeProcsRemaining` and kills one pid, no tree, no profile sweep
- RULE: `pup-bridge-dev/SKILL.md:1133-1160` "report a COUNT (`chromeProcsRemaining`, which must be 0)... scope by ownership (profile dir)... verify with `process_list`"; `pup-bridge-test:75` expects `chromeProcsRemaining: 0`.
- CODE: `rust/verbs/src/lib.rs:1660` `"chromeProcsRemaining": ctx.browsers.lock().unwrap().len()` (number of connected browser handles); `lib.rs:1656` kills only `b.launched.pid`; `rust/host-win/src/lib.rs:274-283` `kill` is a single `TerminateProcess`, no tree, no command-line sweep.
- KIND: violation
- WHY IT MATTERS: the orphan-renderer CPU freeze that produced the doctrine cannot be detected from the verb's own report.
## 15. No overlay enforcer: a badge the shell clears stays gone until the next navigation
- RULE: `pup-icon-consistency/SKILL.md:96-100` "The enforcer backstop, a 4s sweep... repaints ANY bare-or-stuck window... This is the real guarantee"; `pup-taskbar-identity:58-65`.
- CODE: `rust/verbs/src/identity.rs:224-295` paints on open and navigate plus retries at 1.5 s and 4.5 s and one 30 s generic retry; `activity.rs:432-435` progress pushes never touch `last_paint_sig`; the health tick never repaints overlays; rescan and rebind stamp but do not repaint.
- KIND: gap
- WHY IT MATTERS: the default `taskbarActivity=progress` paints a bar on every screenshot, which per the skill's own measurement clears the overlay, so windows go bare for the life of a page.
## 16. The Adom mark on the overlay (plain mode) and the notch fallback do not exist
- RULE: `pup-icon-consistency/SKILL.md:110-119` "AUMID off: favicon + Adom mark"; `:101-104` "baked notch fallback."
- CODE: `rust/identity/src/badge.rs:75-95` `compose` draws only the favicon on a card, in every mode; `tile.rs` has no notch.
- KIND: stale skill or gap (pick one deliberately; in plain mode pup windows now carry no Adom branding at all).
- WHY IT MATTERS: plain-mode windows are indistinguishable from a stock window, which the skill says defeats the overlay's purpose.
## 17. "Audit means FIX + REAPPLY, runs on its own" versus a read-only detector
- RULE: `pup-icon-audit/SKILL.md:20-23` "`pup_audit_icons {}` (it repairs by default; `fix:false` for a dry run)"; `:50-57` runs on a schedule.
- CODE: `rust/verbs/src/identity.rs:321-341` `audit` is report-only with no `fix` argument; `extras.rs:162-181` a 5-minute detector that explicitly does not re-stamp, citing John 2026-09-06 "i hate sweeps".
- KIND: stale skill (John's later directive reversed it).
- WHY IT MATTERS: the skill tells the next maintainer to build the sweep John since forbade.
## 18. Switching to plain mode strips nothing; mode flips have no generation guard
- RULE: `pup-mode-ralph/SKILL.md:45-55,59-63` plain = wipe + null WM_SETICON + delete `Adom.Pup.*` keys + converge to Chrome's native AUMID + nudge; `_identityGen` aborts in-flight stamps on a rapid flip.
- CODE: `rust/verbs/src/settings.rs:56` to `identity.rs:304-306` `reapply_all` to `stamp` to `identity.rs:148` `if m == "plain" { return }`: existing stamps, keys and jump lists stay; each flip spawns an unguarded thread.
- KIND: gap (and `tools/selftest.sh:104-112` T5/T6 "plain = zero Adom.Pup keys" will misjudge it).
- WHY IT MATTERS: the RAPID double-click race and "branded buttons in plain mode" are both reachable.
## 19. The jump-list "blip" cause and fix are superseded, and there is no task-set dedup
- RULE: `pup-jumplist/SKILL.md:19-48` cause = re-committing near the click; fix = hash the task set; `pup-bridge-debug:771-795` "UNRESOLVED, tracked on adom-bridge#40".
- CODE: `rust/verbs/src/identity.rs:31-36` measured cause = registry-only AUMID (ab#155), fix = opt-in Start Menu anchor `aumidShortcut` (default off); `identity.rs:152-162` commits the list on every full stamp with no hash.
- KIND: stale skill (both files)
- WHY IT MATTERS: the next person chasing the blip is sent to the wrong cause with a fix already known not to work.
## 20. Jump-list launcher doctrine describes the retired PowerShell launcher
- RULE: `pup-taskbar-identity/SKILL.md:69-116` tasks target `powershell.exe` running `pup-jumplist-call.ps1`; `ralph_jumplist.sh` fires "through the real deployed launcher".
- CODE: `rust/verbs/src/identity.rs:46-48` deletes the `.ps1` at boot; `:88-97` tasks run pup's own exe `--jumplist <verb> <b64>`.
- KIND: stale skill (and `ralph_jumplist.sh` tests a path pup removes).
- WHY IT MATTERS: the "real click path" test now exercises a launcher that no longer exists.
## 21. Foreground-window capture uses `Page.captureScreenshot`, the rail the skill says blips
- RULE: `pup-taskbar-identity/SKILL.md:153-164` "any capture of a window the user is looking at rides the screencast rail... never captureScreenshot."
- CODE: `rust/verbs/src/transport.rs:936-940` annotate's `capture_viewport_png` sends `Page.captureScreenshot` on the CDP lane; `src/extension/worker.js:159-172` the ext lane falls back to debugger `Page.captureScreenshot`.
- KIND: violation
- WHY IT MATTERS: annotate photographs the one window the user is watching.
## 22. tools/selftest.sh and pup-selftest test the Node shell; the Rust shell's real gates are undocumented
- RULE: `pup-selftest/SKILL.md:16-25` T1 "static parse (server + SERVED dashboard script)", T6 "jump-list commit lines present", T7 "steady-state enum <= 2 calls/45s", "run after EVERY ship".
- CODE: `tools/selftest.sh:21-23` runs `node --check src/server.js` (the Node tree, not the exe); T6 greps for a log line the Rust bridge emits only on failure; T7 reads `/status.enumWindows`, which `lib.rs:1028` hardcodes to zeros (vacuous pass). The Rust ship's actual gates (`tools/rust-build.sh` with `cargo test`, `check-borders.sh`, `gen-assets.py`; `tools/parity.py`; `tools/ab-smoke.sh`) appear in neither `pup-selftest` nor `pup-bridge-test`.
- KIND: stale skill plus ok-but-undocumented.
- WHY IT MATTERS: "13/13 GREEN" from this script proves little about the shipped binary.
## 23. pup-bridge-test scenarios: which exist as scripts, which are stale
- RULE: `pup-bridge-test/SKILL.md` scenarios 1 to 12 and 11b.
- CODE: scripted only in part: smoke is roughly `tools/ab-smoke.sh`; the concurrency invariant is roughly `dev-skills/pup-taskbar-identity/ralph_icons.sh` but it greps log strings the Rust bridge never emits; #46 churn = `tools/churn-ralph.sh`. Scenarios 2 to 12 have no script. Stale expectations: scenarios 3 and 6 expect `[flash] (launch)` and `[park]` lines per window, but the default never flashes and park logs only the grace case; scenario 7 needs the missing sweep (#9); scenario 11 expects `[heal]` lines, Rust logs `[recovery]` and `[health]`; the standing directive at `:8-13` is done (`lib.rs:703-721`); `:14-25` is Node-era. Scenario 11b matches the code.
- KIND: stale skill plus gap (no scripts).
- WHY IT MATTERS: the "standard test scenarios" cannot be run as written and several would fail on log strings alone.
## 24. pup-bridge-publish describes the Node/public-tier pipeline; ship.sh is the Rust/insiders pipeline
- RULE: `pup-bridge-publish/SKILL.md:16-20,45-60` release zip = `src/` Node tree; `:71-80` edit and push the PUBLIC manifest; `:96-102` `files[]` = five files; `:116-150` GATES 1 to 3; `pup-bridge-dev:1221-1231` "Three gates now in `/tmp/ship.sh`".
- CODE: `tools/ship.sh` default `--shell rust`; writes the INSIDERS manifest, never the public one (promotion via `tools/promote.sh`); pushes `skills/`, `dev-skills/` and `publish-skills/` trees; strict-YAML gate; `package.json` `files[]` now lists 12 user skills; no repo-freshness gate, no served-zip re-download, no `bridge_install` in the script.
- KIND: stale skill plus gap.
- WHY IT MATTERS: following the publish skill verbatim would push the public manifest and bypass the insiders tier.
## 25. pup-cdp-discipline's model describes the Node process; Runtime stays enabled on every tab
- RULE: `pup-cdp-discipline/SKILL.md:19-31` single Node event loop; rule 1 `:35-43` "no extra CDP domain enabled... `Runtime` is the same hazard"; rule 2 balance attach and detach.
- CODE: `rust/cdp/src/lib.rs:518-525` `page_enable` enables `Runtime` on every attached tab unless `cdpQuiet=on` (default off); one reader thread per browser; `attach_tab` never detaches by design.
- KIND: stale skill (model) with a partial rule-1 deviation.
- WHY IT MATTERS: the acceptance test and the "loop starvation" diagnosis no longer describe how this bridge fails.
## 26. Firewall rule: two Chrome launch sites lack the network-quieting flags
- RULE: `pup-no-firewall/SKILL.md:50-53,86-96` every separate Chrome launch gets the MediaRouter disables, QUIC and WebRTC flags.
- CODE: `rust/verbs/src/record.rs:239` recorder HUD launch has only two disables; `rust/browser/src/lib.rs:513-528` `stockFlags:on` CDP launch carries none (the ext-lane stock launch does).
- KIND: violation (recorder HUD), gap (stock CDP flags).
- WHY IT MATTERS: a first recording or a `stockFlags` experiment can pop the Windows Firewall dialog.
## 27. Loop radar is mostly blind in the Rust `/status`
- RULE: `pup-bridge-dev/SKILL.md:1699-1711` wrap EVERY loop; `/status` carries `loops`, `win32Calls`, `enumWindows`, `log`.
- CODE: `rust/verbs/src/lib.rs:1028` those fields are hardcoded to zeros and empties; only 4 loops tick; identity, overlay, progress and birth-watch threads are untracked.
- KIND: stale skill plus gap.
- WHY IT MATTERS: John's replacement radar for "a misbehaving pup" reports zeros.
## 28. `background` verdict is hardcoded, not measured
- RULE: `pup-bridge-dev/SKILL.md:602-605` "The park's verdict comes from CDP getWindowBounds... surfaces as the `background` field."
- CODE: `rust/verbs/src/lib.rs:1265` open always returns `"background": "backgrounded"` even when `parked == false` or `hwnd == None`; `session_row` uses a different vocabulary.
- KIND: violation
- WHY IT MATTERS: the self-verify verdict can say "backgrounded" for an unparked window.
## 29. R5 "identity is async and never gates R1" is no longer true
- RULE: `pup-bridge-dev/SKILL.md:404-407` "AUMID stamping, tile art... must never gate R1."
- CODE: `rust/verbs/src/lib.rs:1160-1162,1407-1409` `birth_watch` renders the tile and registers the AUMID through ab (8 s timeout) BEFORE `create_target`, inside the birth lock; `lib.rs:1438` stamps natively in-process although `identity.rs:3-4` says every stamp goes through ab.
- KIND: stale skill (R5) plus ok-but-undocumented (the 2.0.446 pre-stamp design lives only in code comments).
- WHY IT MATTERS: the placement doctrine and the identity doctrine disagree on ordering; a bridge restart also orphans the in-process icon handle until ab re-stamps.
## 30. Recovery has no on-disk crash breaker
- RULE: `pup-bridge-debug/SKILL.md:80-87` "the only defense against a native-crash-on-boot loop is a PERSISTENT circuit breaker... `recoverAttempts` in the session file."
- CODE: `rust/verbs/src/recovery.rs:40,115-116` `RELAUNCHES` is in-memory; `recover_at_boot` writes no marker before the risky ops.
- KIND: gap
- WHY IT MATTERS: a session file that crashes the exe at boot re-crashes every boot.
## 31. pup-taskbar-identity's recovered-window resolution stack contradicts pup-no-wiggle and the code
- RULE: `pup-taskbar-identity/SKILL.md:123-140` items 2 to 4: natural-title match, "off-screen re-capture: move it via CDP and identify by bounds change", persisted-claims map.
- CODE: `rust/verbs/src/recovery.rs:217-218` persisted hwnd else the tag property lookup (the `pup-no-wiggle` method); item 3 is the banned wiggle.
- KIND: stale skill
- WHY IT MATTERS: two identity skills prescribe opposite fallbacks.
## 32. Agent-activity progress: skill says indeterminate, code is a determinate estimate bar
- RULE: `pup-bridge-debug/SKILL.md:526-535` "State is `indeterminate` (marquee), NOT a percentage... a fake percentage would be a lie."
- CODE: `rust/verbs/src/activity.rs:432-471` pushes `state:"normal"` with a value filling over a running-average estimate every 180 ms, capped at 92 %, then 100 %.
- KIND: stale skill
- WHY IT MATTERS: the doctrine and the behavior John sees on his taskbar disagree.
## 33. Dead code that carries a banned behavior
- RULE: `pup-window-targeting/SKILL.md` never stamp another thread's window.
- CODE: `rust/verbs/src/extdrive.rs:620-647` `dress_window` stamps every visible lane window with the CALLING thread's identity; its callers are not reachable from `dispatch`. `rust/verbs/assets/title.js` and `page-tag.js` (title injectors banned by `pup-page-integrity`) are unreferenced; `src/extension/worker.js:5-7` still says ownership rides the tab title.
- KIND: ok-but-undocumented (dead), worth deleting before someone wires it back.
- WHY IT MATTERS: the next "why is this window bare" fix could re-enable a cross-thread stamp.
## 34. Bot-wall reporting: partial, and the hint contradicts the lane doctrine
- RULE: `pup-bot-walls/SKILL.md:198-202` return a `botWall` field + errorCode; `:82-96,178-179` check velocity and cookies and retry paced before blaming the site.
- CODE: `rust/verbs/src/lib.rs:354-361` `render_check` adds `chrome_error_page` + a `fallbackHint` saying "pup's Chrome for Testing is blocked... Do not retry in pup: switch lanes" to `nbrowser_open_window`, on both lanes, with no `botWall` field.
- KIND: gap (field) and stale hint text (written before the ext lane became the vendor-site lane).
- WHY IT MATTERS: the calling AI is told to abandon the lane that the same repo says loads 20 of 20 vendor sites.
## 35. pup-browser-detection contradicts its own retraction
- RULE: `pup-browser-detection/SKILL.md:71-78` RETRACTED the CfT-version cause; `:143-144` decision step 4 still says "check the CfT version matches the installed Chrome"; `:131` table lists "matched CfT version" as a remedy.
- CODE: `rust/browser/src/lib.rs:26` `CFT_BUILD_ID` pinned; `lib.rs:248-250` `grease_for` knows only major 152 and falls back to the old GREASE for anything newer.
- KIND: stale skill (internal), plus a code fragility (a Chrome 153 user gets a wrong GREASE brand).
- WHY IT MATTERS: the skill sends a diagnosis down a path it already withdrew.
## 36. pup-user-foreground's "ab migration" note does not match how the primitive was ported
- RULE: `pup-user-foreground/SKILL.md:208-215` PS to ab verbs (`desktop_get_foreground`, `desktop_user_idle_ms`, `desktop_clear_window_attention`); prefer a combined ab verb.
- CODE: `rust/verbs/src/park.rs:22-40` reads foreground and idle in-process; `activity.rs:498` separately asks ab `desktop_get_foreground` for the same fact.
- KIND: ok-but-undocumented (two sources of foreground truth).
- WHY IT MATTERS: minor, but the skill points at verbs the demotion path does not use.
---
## Node-era names presented as live code (stale-skill class)
Names that present Node functions, files or runtime as current, per skill (from a repo-wide grep; each appears in running text, not only in dated history):
- **pup-bridge-dev** (76 hits): `server.js`, `chrome.js`, `win32.js` (koffi), `createPageInNewWindow`, `withBirthLock`, `resolveSessionHwndByBounds`, `hwndBelongsToPup`, `stampPupIdentity`, `updateWikiJumplist`, `osBottomUnlessForeground`, `userIsUsingWindow`, `parkSessionWindowDirect`, `healOffscreenWindow`, `sweepVisibility`, `recoverSessions`, `getOrLaunchBrowser`, `_launchInFlight`, `trackedLoop`, `sendJSON`, `adCommand`, `pupCaption`, `PUP_CAPTION_MAX_MS`, `captionForegroundReason`, `osClearFlashByActivate`, `osIdleMs`, `_bornAt`, `ensureSafeForNativeInput`, `primaryWorkArea()`, `birthRect()` "in server.js" (the R1 to R6 implementation map at `:464-475` is entirely Node), `node --check`, `npm install`, `tests/dashboard_ralph.sh`, `/tmp/ship.sh`, "Repo layout" `:123-137`, "Node is handled by AD core" `:155`.
- **pup-bridge-publish** (42): `server.js`, `chrome.js`, the `src/` zip, `node_modules`, `PUBLISHING.md`, the Node-bridge gotcha section.
- **pup-bridge-debug** (25): `recoverSessions`, `recoverAttempts`, `_launchInFlight`, `getOrLaunchBrowser`, `process.on('uncaughtException')`, `node.exe` spawn cadence, `chrome.adCommand` direct-API subset, `stampPupIdentity`, `updateWikiJumplist`, `brandPupWindow`, `updateTabCountBadge`, `markSessionBusy`, `reclaimUnmanagedWindows`, `rescanProfile`, `killBrowserProcess`, `execFileSync`, `adom-desktop-cli.exe` jump-list args.
- **pup-window-targeting** (18): `windowTarget()`, the `chrome.adCommand(...)` snippet, `createPageInNewWindow`, `page.__pupHwnd`, `hwndBelongsToPup`, `recoverSessions`, `rescanProfile`, `updateWikiJumplist`, `withBirthLock`.
- **pup-taskbar-identity** (16): `createPageInNewWindow`, `_birthLock`, `hwndBelongsToPup`, `hwndOwnedByOtherSession`, `stampPupIdentity`, `applyAppOverlay`, `resolveSessionHwndByBounds`, `pupTask()`, `ensurePupJumplistLauncher()`, `writePupPortFile()`, `pupCliExe()`, `flickerFreeShot`, `sharp`, "in server.js".
- **pup-user-foreground** (10): `osBottomUnlessForeground`, `userIsUsingWindow`, `parkSessionWindowDirect`, `reassertBottomAfterNav`, `kickoffPark`, `healOffscreenWindow`, `sweepVisibility`, `osIdleMs`, "`ShowWindow(...,0)` appears exactly once in `server.js`", `puppeteer.connect`.
- **pup-no-wiggle** (8): `server.js`, `src/win32.js`, `findChromeWindowByTitle`, `findWindowByProp`, `fixHiddenOrOffscreen`, `resolveSessionHwndByBounds`, `bestSessionHwnd`, `npm install`.
- **pup-selftest** (8): `windowTarget`, `_wikiJumplistKey`, `_lastPaintSig`, `_appOverlay`, `_curAppId`, `tests/check_dashboard_script.js`, "KILL the node process", T1 "server parses".
- **pup-differential-diagnosis** (6): Node process and pid, `uncaughtException`, `:64230`, `createCDPSession`, `sharp`.
- **pup-cdp-discipline** (5): Node event loop, `:64230`, `createCDPSession`, `.detach()`, `neutralizeDebugger`, `sharp`.
- **pup-icon-consistency** (4): `applyAppOverlay`, `resolveSessionHwndByBounds`, `_curAppId`, `resolveFaviconRich`, `analyzeIconBytes`.
- **pup-no-firewall** (3): `mergeChromiumFeatureFlags()` "server.js, v2.0.293", `puppeteer.launch args`, `BIND_HOST`.
- **pup-mode-ralph** (3): `_identityGen`, `stripAllPupIdentities`, the `cn-dash` pup_eval driver.
- **pup-jumplist** (3): `updateWikiJumplist`, `_registeredPupAumids`, `jarg`.
- **pup-browser-import** (3): `chrome.adCommand(...)`, `credentialVault.mergeImportedCredentials`, `src/credential_vault.js`.
- **pup-icon-audit** (2): `src/server.js`, `NUDGE_RETRY_DELAYS`, `stripAllPupIdentities`, `_buttonBuiltAt`.
- **pup-bridge-test** (2): `callerOwnWindow()`, "~line 1160" recovery loop, `_profileOpenChain`, `reclaimUnmanagedWindows`, `getSessionInfoFast`.
- **pup-bot-walls** (1): `computeConsumerUA()` and `applyConsumerUA()` "in `server.js`" (Rust: `consumer_ua`, `apply_consumer_identity`, `lib.rs:266-299`).
Skills with no Node-era live-code references: pup-aumid-decisions, pup-auto-mode, pup-doppelganger, pup-hero-image, pup-page-integrity, pup-real-images, pup-render-test, pup-browser-detection.