app
Pup - the AI's own browser
Public Made by Adomby adom
pup gives your AI a real browser on your desktop that it drives completely, in the background, signed in as you: windows that never jump in front of your work, one shared profile that learns your logins, and every window labeled on the taskbar with its AI thread's name.
← Commit history
dev skills: pup-real-images (real screenshots only, never generated art) + pup-no-firewall (loopback-only invariant, the stacked --disable-features root cause)
2 files changed
+150
dev-skills/pup-no-firewall/SKILL.mdadded+84@@ -0,0 +1,84 @@+---+name: pup-no-firewall+description: "DEV skill (source-only) - HARD RULE: pup must NEVER cause a Windows Firewall / Windows Security dialog ('Do you want to allow public and private networks to access this app?') to pop at an Adom user, and must never NEED any firewall feature. Every socket pup or its Chrome opens must be LOOPBACK-ONLY. Documents the measured 2026-08-23 root cause (three stacked --disable-features flags: Chrome honors only the LAST, silently re-enabling MediaRouter's 0.0.0.0:5353 mDNS bind) and the merge rule that prevents it. Read BEFORE adding any Chrome launch flag, any --disable-features/--enable-features entry, any listener/server/socket, or when a user reports a firewall prompt naming chrome.exe or node. Trigger words: firewall, Windows Firewall, windows security dialog, allow public and private networks, firewall prompt, mDNS, 5353, MediaRouter, 0.0.0.0 bind, non-loopback, disable-features, enable-features, duplicate flag, launch flags, chrome flags, new listener, bind host."+---++# ⛔ pup must NEVER pop a firewall dialog. Loopback-only, forever.++John, 2026-08-23, after the Windows Security dialog ("Do you want to allow public and private+networks to access this app?" - Google Chrome for Testing) appeared on ConfRoomROG: "shame on you.+we never want to ever popup dialogs like this in front of the adom user. and we should NOT need any+firewall features turned on for pup ever."++## The invariant++**Every socket pup opens - its own Node server AND every socket of every Chrome it launches - binds+127.0.0.1/::1 only.** Windows Firewall prompts exactly when a program LISTENS on a non-loopback+address with no matching rule, and it prompts PER-EXE - so every CfT version bump (new+`win64-<ver>\chrome.exe` path) re-pops the dialog. Loopback listeners are firewall-exempt: keep+everything loopback and the dialog is structurally impossible. pup needs no inbound access, no+Allow rule, no exception - "needing a firewall feature" is itself a defect.++- The bridge's own HTTP server: loopback bind (`BIND_HOST`), guaranteed since the ADOM_BIND_HOST+ work - the startup line even prints "no firewall prompt". Never bind 0.0.0.0.+- Chrome's one non-loopback offender is **MediaRouter** (Cast/DIAL): its mDNS responder binds+ **UDP 0.0.0.0:5353 + :::5353** in the PARENT process. pup never casts - it must stay disabled+ (v2.0.120's fix, restored 2.0.293). `--disable-background-networking` does NOT cover it.+- The CDP debug port (`--remote-debugging-port`) binds 127.0.0.1 - safe, leave it.++## The 2026-08-23 root cause - HOW the fix silently died (measure, don't assume)++v2.0.120 added `--disable-features=...MediaRouter,DialMediaRouteProvider,CastMediaRouteProvider`.+It worked. Then two OTHER eras of code each appended their own flag:++- v1.9.198: `--disable-features=CalculateNativeWinOcclusion`+- v1.8.95 (`noBrowserIdentityFlags`, appended by the detached Windows launch path):+ `--disable-features=SigninIntercept,...,ProfilePicker`++**Chrome honors only the LAST occurrence of a switch.** Three `--disable-features` on the command+line meant only the sign-in list applied; MediaRouter came back, mDNS bound 0.0.0.0:5353, and every+fresh CfT exe re-popped the firewall dialog. Measured live on ConfRoomROG (CfT 148): parent cmdline+carried all three flags, `Get-NetUDPEndpoint` showed `0.0.0.0:5353` owned by the CfT parent, and+two Block rules for the exact exe path (John hitting Cancel) sat in the firewall.++## The rules that keep it fixed++1. **Never hand-append a second `--disable-features` / `--enable-features`.** Add feature names to+ the EXISTING list, or rely on `mergeChromiumFeatureFlags()` (server.js, v2.0.293), which unions+ duplicates into one flag at BOTH launch sites (puppeteer.launch args + the detached+ `chromeArgs`). Any new launch path MUST run its final argv through it.+2. **Every separate Chrome launch gets the MediaRouter disables.** The desktop recorder's own+ Chrome (`--disable-features=Translate,MediaRouter,DialMediaRouteProvider,CastMediaRouteProvider`)+ was missed for years - a first recording would have popped the dialog. Grep for+ `puppeteer.launch` / spawn sites when adding one.+3. **New listeners (Node or flags) must justify their bind address in a comment**; anything not+ 127.0.0.1 is a defect unless John explicitly ordered otherwise.+4. **Never "fix" a prompt by adding firewall rules** (netsh/New-NetFirewallRule need admin and+ treat the symptom). Kill the non-loopback bind instead. The Block rules a user's Cancel created+ are harmless - leave them; pup_uninstall can remove them on request.++## Verify after any launch-flag change (the empirical loop)++On a Windows machine over ab (ConfRoomROG), with a pup window open:++```powershell+# 1. exactly ONE --disable-features on the parent cmdline, containing MediaRouter:+(Get-CimInstance Win32_Process -Filter "Name='chrome.exe'" |+ Where-Object { $_.ExecutablePath -like '*puppeteer*' -and $_.CommandLine -notmatch '--type=' }).CommandLine+# 2. ZERO non-loopback endpoints owned by any CfT pid:+Get-NetUDPEndpoint | Where-Object { $_.LocalAddress -notin @('127.0.0.1','::1') } # filter to CfT pids+Get-NetTCPConnection -State Listen | Where-Object { $_.LocalAddress -notin @('127.0.0.1','::1') }+```++Expected: one merged flag; UDP 5353 absent; only 127.0.0.1 TCP listeners (the CDP port). If 5353+is bound on 0.0.0.0 the firewall dialog WILL eventually pop - the flag list regressed or Chrome+renamed the feature: find the current kill switch, verify by socket probe, and update this skill.++## Review checklist - fail the change if ANY is true++- [ ] It adds a second `--disable-features` / `--enable-features` instead of merging.+- [ ] It adds a Chrome launch site whose argv skips `mergeChromiumFeatureFlags` or lacks the+ MediaRouter disables.+- [ ] It binds any server/socket to something other than loopback.+- [ ] It adds/needs a firewall Allow rule, or asks the user to click a firewall dialog.+- [ ] A flag change shipped without the socket probe above actually being run.
dev-skills/pup-real-images/SKILL.mdadded+66@@ -0,0 +1,66 @@+---+name: pup-real-images+description: "DEV skill (source-only) - HARD RULE: every image shown to a user (settings example images, README/wiki screenshots, skill illustrations) must be a REAL SCREENSHOT of the real feature running, never generated/drawn/mocked art (PIL, SVG mockups, hand-drawn taskbar buttons). John's words: 'never fucking make fake windows taskbar icons. these look like dog shit. ONLY screenshot real icons... you can make a progress bar for a windows icon and screenshot it, crop it, then use it.' Read BEFORE adding ANY image to the dashboard settings dialog, a SKILL.md, the wiki README, or docs. Trigger words: settings example image, example screenshot, settings-ex, imgBy, illustration, mockup image, PIL image, generate an image, draw a taskbar button, fake icon, example img, dashboard settings image, anncapbar, tbactprogress, toolbarext."+---++# ⛔ NEVER ship generated/mock images. REAL SCREENSHOTS ONLY.++Set by John 2026-08-23 after PIL-generated "taskbar button" illustrations shipped in the settings+dialog: "this is fucking hideous... these look like dog shit. ONLY screenshot real icons. stop+being lazy."++## The rule++Any image a user will see - a settings-dialog example (`img:` / `imgBy:` in SETTINGS_DEF, files in+`src/icons/settings-ex/`), a wiki README screenshot, a skill illustration, docs art - MUST be a+**real screenshot of the real feature actually running**. Never:++- PIL / Pillow / ImageMagick generated art+- Hand-drawn SVG/canvas mockups of OS chrome (taskbar buttons, window frames, dialogs)+- "Illustrative" recreations of any UI, however faithful+- AI-generated imagery of UI++A fake image misleads the user about what they will actually see, and it looks like dog shit next+to real OS rendering. There is no "good enough" fake.++## How to make the real image instead (proven recipe, 2026-08-23)++You control real machines over ab - USE them. The lazy path is the banned path.++1. **Put the feature into the real state.** Examples that were done for the settings dialog:+ - Taskbar progress bar: `desktop_taskbar {hwnd, progress:{state:"normal", value:55}}` on a real+ pup window, on a test machine (ConfRoomROG).+ - Taskbar flash: `desktop_flash_window {hwnd}` (clear afterwards with `{stop:true}` ++ `desktop_clear_window_attention` - the pink lingers).+ - Annotation caption bar: arm `pup_annotate`, draw a REAL stroke (dispatch PointerEvents at the+ overlay canvas; verify `paintedPx > 0` via getImageData BEFORE releasing - CDP+ `pup_input_dispatch` has no press/drag primitives), let quick-capture fire, use the real+ capture from `screenshots/annotate-*.png`.+ - Toolbar extension: raise the real window (captioned, on the test machine), screenshot the real+ toolbar.+2. **Capture at NATIVE resolution.** `desktop_screenshot_screen` / `desktop_screenshot_window`+ auto-downscale (1568px) - too blurry for a cropped example. Run a PowerShell native capture on+ the machine (`SetProcessDPIAware` + `Graphics.CopyFromScreen` of the target rect, save PNG) via+ `desktop_run_script`, then `pull_file` it back.+3. **Crop tight, but keep honest context.** Crop to the real pixels of the feature plus just enough+ neighborhood to read as "this is the taskbar / the toolbar". Watch for misleading neighbors (an+ unrelated app showing its own progress bar next to your "off" example - crop it out).+4. **Verify by READING the final image** before shipping it. If the state you staged isn't visible+ in the pixels, you captured the wrong thing - re-stage, re-capture.+5. **Clean up the machine state** (clear progress/flash, lower raised windows - captioned raises+ only, per foreground etiquette).++## Where this has already been applied++`src/icons/settings-ex/`: `tbactprogress.png`, `tbactflash.png`, `tbactoff.png` (real ConfRoomROG+taskbar states), `anncapbar.png` (a real annotate capture with the real baked caption strip),+`toolbarext.png` (the real CfT toolbar with the real extension tiles). `jumplist.png` and friends+were already real screenshots - that was always the right pattern.++## Review checklist - fail the change if ANY is true++- [ ] An image shown to users was produced by an image library, drawing code, or an AI generator.+- [ ] A "temporary placeholder" fake image is shipped "until we can screenshot the real thing".+ (No. Capture the real thing FIRST - the machines are reachable over ab right now.)+- [ ] The screenshot was staged but never read back to confirm the feature state is visible.+- [ ] OS chrome (taskbar, window frame, dialog) is recreated rather than captured.