master
John Lauer docs: dev-skills audit 2026-09-15, 36 discrepancies between the dev skills and the Rust bridge, for joint review 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-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.