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
NEW ralph render test (John's taskbar-hover method, automated): tools/ralph-render-test.ps1 captures the DWM thumbnail (ground truth for whether an occluded window PAINTED, without forcing a render like a screenshot does) + dev-skills/pup-render-test. Proven: DigiKey/TI render in background (distinct 13-14), a blank window ~9; pair with DOM bodyLen to tell a render bug from an empty bot-wall page.
2 files changed
+147
dev-skills/pup-render-test/SKILL.mdadded+88@@ -0,0 +1,88 @@+---+name: pup-render-test+description: "DEV skill (source-only) - how to RALPH-TEST whether a BACKGROUND (occluded) pup window actually PAINTED its content, vs sitting BLANK. The trap: a normal screenshot (CDP Page.captureScreenshot, or PrintWindow PW_RENDERFULLCONTENT) FORCES a fresh render, so it shows content even when the live window is blank - it masks the exact bug you are testing for. The ground-truth signal is the Windows DWM taskbar THUMBNAIL (what you see hovering a taskbar icon): DWM generates it from the window's last COMPOSITED surface without forcing a render, so a blank thumbnail means the window never painted. Read this before claiming a background window renders, before touching the occlusion/focus-emulation/park code, or when a user reports 'pup windows are blank'. Trigger words: blank pup window, window not rendering, background window blank, did it paint, taskbar thumbnail, DWM thumbnail, requestAnimationFrame not firing, visibilityState hidden, occluded window blank, setFocusEmulationEnabled, one rAF, render test, ralph render, prove it rendered."+---++# Ralph-testing background-window rendering (blank vs painted)++John's method, made automatable: **hover a pup window's taskbar icon; Windows shows a thumbnail+preview. Blank preview = the window never rendered. Content in the preview = it rendered.** That+thumbnail is the ground truth, and this skill captures it programmatically so you can prove it in a+test instead of by eye.++## Why a normal screenshot LIES here (the trap)++The whole failure mode is: a window born off-screen and parked occluded reports+`visibilityState: 'hidden'`, `requestAnimationFrame` is paused, and the compositor never produces a+frame - so the window is **blank** even though its DOM is fully loaded. But the usual ways to look+at a window all **force a render**, which hides exactly that:++- **CDP `Page.captureScreenshot`** (what `pup_screenshot` uses) forces the renderer to produce a+ frame for the capture. Always shows content. Useless for this test.+- **`PrintWindow` with `PW_RENDERFULLCONTENT`** (flag 2, what most window-grab tools use for Chrome)+ also forces a full render. Same problem.++So "I screenshotted it and saw the page" does NOT prove the live window rendered. It proves the+capture forced a render.++## The ground truth: the DWM thumbnail++The DWM taskbar thumbnail is composited by the Desktop Window Manager from the window's **last+already-composited surface** - it does NOT ask the window to render. If the window never painted,+the thumbnail is empty. `tools/ralph-render-test.ps1` reproduces this:++1. Create a tiny top-left host form.+2. `DwmRegisterThumbnail(host, sourceWindow)` + `DwmUpdateThumbnailProperties` to draw the source's+ thumbnail into the host.+3. `Graphics.CopyFromScreen` the host region (captures what DWM actually drew).+4. Count distinct sampled colors: **`>= 12` = RENDERED**, fewer = **BLANK**. A magenta-bleed result+ (the host's own backcolor showing through) = **THUMBNAIL_EMPTY** (no composited surface at all).++Measured baseline (2026-08-22): DigiKey 14, TI 13 (rendered); a blank/empty window ~9.++## How to run it++```bash+# 1. resolve the pup windows' hwnds by their property tags (see dev-skills/pup-no-wiggle):+# enumerate Chrome_WidgetWin_1 windows, GetProp each for "AdomPupSid=<sid>".+# 2. run the render test on those hwnds (on the desktop, via ab shell_execute or directly):+powershell -NoProfile -ExecutionPolicy Bypass -File tools/ralph-render-test.ps1 -Hwnds "5380294,2824624,12061336"+# -> 2824624 -> RENDERED(distinct=14)+# 12061336 -> RENDERED(distinct=13)+# 5380294 -> BLANK(distinct=9)+```++The test briefly flashes a small 280x200 host window at the top-left corner (~0.5s per window) - that+is the thumbnail host, expected. It never touches or foregrounds the window under test.++## ALWAYS pair with a DOM check, or you will misread it++A BLANK thumbnail has TWO very different causes; disambiguate with `pup_eval`+`document.body.innerText.length`:++| thumbnail | DOM bodyLen | meaning |+|---|---|---|+| RENDERED | any | window painted - the render path is healthy |+| BLANK | **> 0** | **RENDER BUG**: content exists but never painted - this is what the fix addresses |+| BLANK | **0** | empty page (bot-wall / 403 / 404 / still loading) - NOT a render bug; see `pup-bot-walls` |++The Mouser case on 2026-08-22 was exactly the second row: `BLANK` thumbnail but `bodyLen == 0`+because Mouser served a 403 bot-wall - a blank *page*, not a blank *paint*. Do not "fix" rendering+for that; it is a sourcing/bot-wall problem.++## The fix this verifies (so nobody regresses it)++`createPageInNewWindow` pulses `Emulation.setFocusEmulationEnabled` ON for two animation frames at+birth, then OFF (v2.0.280 -> made a one-shot in 2.0.281). This is John's "one rAF to get a rendering+to occur": the occluded window composites a single frame (Chrome retains the last frame for an+occluded window, so it stays painted), then returns to throttled/idle. Do **NOT** leave focus+emulation ON, and do **NOT** reach for the highFps anti-throttle LAUNCH flags to solve blankness -+both keep the page rendering continuously and reintroduce the issue-#14 battery drain. The whole+point is: paint once, then idle. Re-run this render test after any change to the birth/park/occlusion+path and confirm a freshly-opened background vendor page still scores RENDERED.++## Known limitation / TODO++- The birth pulse fixes NEW windows. A window brought back by crash/sleep RECOVERY does not go+ through `createPageInNewWindow`, so it can still come back blank - apply the same one-shot pulse on+ the recovery/re-attach path, then verify with this test.
tools/ralph-render-test.ps1added+59@@ -0,0 +1,59 @@+# ralph-render-test.ps1 — prove a BACKGROUND pup window actually PAINTED, without forcing a render.+#+# WHY this and not a screenshot: a CDP screenshot (Page.captureScreenshot) and PrintWindow with+# PW_RENDERFULLCONTENT both FORCE a fresh render, so they show content even when the live window is+# blank — they MASK the bug. The Windows taskbar thumbnail (what you see hovering a taskbar icon) is+# generated by DWM from the window's LAST COMPOSITED surface, WITHOUT forcing a new render. So the+# DWM thumbnail is ground truth for "did this occluded window ever paint?". This script captures that+# thumbnail programmatically (DwmRegisterThumbnail into a tiny top-left host form, then screen-grab+# the host) and classifies rendered-vs-blank by counting distinct sampled colors.+#+# Usage: powershell -NoProfile -ExecutionPolicy Bypass -File ralph-render-test.ps1 -Hwnds "5380294,2824624,12061336"+# Output: one line per hwnd: "<hwnd> -> RENDERED(distinct=N) | BLANK(distinct=N) | THUMBNAIL_EMPTY(...)"+#+# INTERPRETING (pair with a DOM check — pup_eval document.body.innerText.length):+# RENDERED -> the window painted; the fix is working.+# BLANK + DOM bodyLen > 0 -> RENDER BUG: content exists but never painted (the thing we fix).+# BLANK + DOM bodyLen == 0 -> empty page (bot-wall / 404 / still loading) — NOT a render bug.+# Measured baseline (2026-08-22): a rendered vendor page scores distinct >= 12 (DigiKey 14, TI 13);+# a blank/empty window scores ~9. Threshold 12 separates them cleanly.+#+# The fix this verifies: createPageInNewWindow pulses Emulation.setFocusEmulationEnabled on for two+# animation frames at birth then off (v2.0.280/281), so an off-screen-born, occluded window paints+# ONE frame (Chrome retains it) instead of sitting blank — without continuous render / battery cost.+param([string]$Hwnds = "")+Add-Type -AssemblyName System.Windows.Forms,System.Drawing+Add-Type @"+using System;using System.Runtime.InteropServices;+public class DWMT {+ [StructLayout(LayoutKind.Sequential)] public struct RECT { public int L,T,R,B; }+ [StructLayout(LayoutKind.Sequential)] public struct TP { public int dwFlags; public RECT rcDestination; public RECT rcSource; public byte opacity; public bool fVisible; public bool fSourceClientAreaOnly; }+ [DllImport("dwmapi.dll")] public static extern int DwmRegisterThumbnail(IntPtr dest, IntPtr src, out IntPtr thumb);+ [DllImport("dwmapi.dll")] public static extern int DwmUpdateThumbnailProperties(IntPtr thumb, ref TP props);+ [DllImport("dwmapi.dll")] public static extern int DwmUnregisterThumbnail(IntPtr thumb);+}+"@+function Test-Render([long]$srcHwnd) {+ $W=280; $H=200+ $form = New-Object System.Windows.Forms.Form+ $form.FormBorderStyle='None'; $form.StartPosition='Manual'; $form.Location=New-Object System.Drawing.Point(0,0)+ $form.Size=New-Object System.Drawing.Size($W,$H); $form.TopMost=$true; $form.BackColor=[System.Drawing.Color]::Magenta+ $form.Show(); [System.Windows.Forms.Application]::DoEvents()+ $thumb=[IntPtr]::Zero+ $hr=[DWMT]::DwmRegisterThumbnail($form.Handle,[IntPtr]$srcHwnd,[ref]$thumb)+ if($hr -ne 0){ $form.Close(); return "REGISTER_FAIL(hr=$hr)" }+ $p=New-Object DWMT+TP; $p.dwFlags=0x1 -bor 0x8 -bor 0x4 -bor 0x10+ $r=New-Object DWMT+RECT; $r.L=0;$r.T=0;$r.R=$W;$r.B=$H; $p.rcDestination=$r; $p.opacity=255; $p.fVisible=$true; $p.fSourceClientAreaOnly=$true+ [void][DWMT]::DwmUpdateThumbnailProperties($thumb,[ref]$p)+ [System.Windows.Forms.Application]::DoEvents(); Start-Sleep -Milliseconds 450; [System.Windows.Forms.Application]::DoEvents()+ $bmp=New-Object System.Drawing.Bitmap($W,$H); $g=[System.Drawing.Graphics]::FromImage($bmp)+ $g.CopyFromScreen($form.Location.X,$form.Location.Y,0,0,$bmp.Size)+ $colors=@{}; $magenta=0; $tot=0+ for($y=0;$y -lt $H;$y+=8){ for($x=0;$x -lt $W;$x+=8){ $c=$bmp.GetPixel($x,$y); $colors["$($c.R),$($c.G),$($c.B)"]=1; $tot++; if($c.R -gt 200 -and $c.B -gt 200 -and $c.G -lt 80){$magenta++} } }+ [DWMT]::DwmUnregisterThumbnail($thumb)|Out-Null; $g.Dispose(); $bmp.Dispose(); $form.Close()+ $distinct=$colors.Count+ if($magenta -gt ($tot*0.5)){ return "THUMBNAIL_EMPTY(magenta bleed - src has no composited DWM surface)" }+ elseif($distinct -ge 12){ return "RENDERED(distinct=$distinct)" }+ else { return "BLANK(distinct=$distinct)" }+}+foreach($h in ($Hwnds -split ',')){ $h=$h.Trim(); if($h){ Write-Output ("{0} -> {1}" -f $h, (Test-Render ([long]$h))) } }