← Commit history

docs: dev-skills audit 2026-09-15, 36 discrepancies between the dev skills and the Rust bridge, for joint review

John Lauer ·5236e66930 ·1mo ago ·parent 96ea8eb
1 file changed +256
docs/DEV-SKILLS-AUDIT-2026-09-15.mdadded+256
@@ -0,0 +1,256 @@+# 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.