← Commit history

Publish 1.0.0

John Lauer ·0074e38182 ·3mo ago ·parent 8b8d92f
5 files changed +276
SKILL.mdadded+234
@@ -0,0 +1,234 @@+---+name: ralph-loop-test+description: >-+  The Adom "ralph test" (Ralph Wiggum loop) — a screenshot-driven fix loop for apps. Point it at the+  user's running app (almost always a WEB APP in a webview / pup / the native browser, sometimes a+  DESKTOP APP driven via an adom-desktop bridge): load it, screenshot it, feed the shot to the AI, the+  AI analyzes what's wrong and fixes it, then reload the page (or reload the file in the desktop app),+  screenshot again, and loop until it's right. Covers every Adom screenshot surface — Hydrogen webview+  (adom-cli), pup, the native Chrome/Edge extension (nbrowser_*), and desktop bridges — plus the+  shotlog viewer workflow (how to actually see shots when the VS Code extension can't show images+  inline). Use when the user says "ralph", "ralph test", "ralph wiggum", "ralph loop",+  "screenshot loop", "visual fix loop", "loop until it's fixed", "test my app with screenshots", or+  "keep screenshotting and fixing until it works".+---++# Ralph Test (Adom) — the screenshot-driven fix loop++In the Adom world a **ralph test** (a Ralph Wiggum loop) is a **visual fix loop**, not a code-build+loop. You point it at the user's *running app* — almost always a **web app** (shown in a Hydrogen+webview, in pup, or in the native Chrome/Edge browser), sometimes a **desktop app driven through an+adom-desktop bridge** — and you grind this cycle:++1. **Load** the app on a surface you can screenshot.+2. **Screenshot** it.+3. **Feed the shot to the AI** → it analyzes what's wrong (broken layout, wrong/missing data, a+   console error, off-brand styling, an element that should be there and isn't).+4. **Fix** the cause — edit the app's code / config / data (or the desktop file).+5. **Reload** — reload the page in the browser, or reload the file in the desktop app.+6. **Screenshot again**, and `shotlog inject` it — that's how you *and* the user actually SEE the shot+   (the Claude Code VS Code extension can't show images inline).+7. **Loop** — repeat until the screenshot matches intent.++"Ralph" because it's gloriously dumb and persistent: the same *look → fix → reload* cycle, over and+over, until the shot is correct. Memory of what's been tried lives in the **app's own state + the+shotlog history**, not the context window.++## Where you're running+The AI always runs from a **container**, and they all carry the same screenshot tools, so this loop+works identically everywhere:+- **Hydrogen Web** — a Docker cloud container.+- **Hydrogen Desktop** — a WSL2 container (Windows), a Lima container (Mac), or an Ubuntu container+  (Ubuntu).++What changes per task is only **which surface** you load the app on. Pick it in Step 1.++> Targeting: `adom-desktop` verbs hit the user's laptop. If more than one desktop is on the relay you+> MUST name one (`-t AdomLapper`) or it errors `ambiguous_target` (`adom-desktop targets` lists them).++---++## ⛔ ALWAYS run the surface in the BACKGROUND+A ralph loop runs for a long time, so it must **never steal the user's focus or disturb their main+work. Always launch the browser/app surface in the background — never foreground to "look at" your+app.** Adom engineers have put enormous work into making every web surface fully operable while buried,+so background operation is always possible:++- **pup** — its default launch puts Chrome-for-Testing into a **non-occluding background mode**: the+  page keeps painting even when fully covered, so **3D views still render** and **screen recording runs+  at full framerate** in the background. Open and capture; never raise the window.+- **Native Chrome/Edge (`nbrowser_*`)** — opens windows **unfocused** by default, and+  `nbrowser_screenshot` captures an **occluded** window with zero OS-window interaction. If you need the+  *real* browser to keep painting while buried (background 3D / full-fps recording), it can **offer a+  full relaunch of the native browser in non-occlusion "full refresh" mode** (the user's profile ++  logins survive), then offer to revert afterward.+- **adom-desktop** — `desktop_screenshot_window` captures a window by **hwnd in the background** (no+  foregrounding). It also returns a **full ARRAY of screenshots including the window's CHILD windows**,+  so **error/dialog boxes — almost always child windows of the parent hwnd — are captured+  automatically.** A ralph loop therefore *sees* the error popup without hunting for it.+- **Hydrogen webview (`adom-cli`)** — captures the user's workspace panels without foregrounding.++Only ever foreground when the **user explicitly asks to watch** (`desktop_bring_to_front`).++---++## Window, tab & taskbar etiquette (be a tidy guest)+The loop opens browser surfaces on the user's real machine, so don't clutter or hijack it:++- **One window per topic — use TABS for the rest.** Keep a pup or native-browser **window pinned to a+  single topic**; when the task spans several pages, open them as **tabs in that same window**, not a+  new window each. `browser_open_tab {sessionId,url}` "adds a tab to the same Chrome window … avoids a+  new taskbar icon" (native: `nbrowser_open_tab`). Editing five wiki pages? Five **tabs in one window**,+  then `browser_list_tabs` → `browser_switch_tab {tabId}` (or just screenshot a specific `tabId`) as you+  go. One taskbar button, not five.+- **NEVER take over a window that's open for another reason.** Always open your OWN fresh window+  (`browser_open_window` / `nbrowser_open_window`). Navigating or reloading a window the user — or+  another AI thread — already had open yanks their page out from under them; it's the rudest move the+  loop can make, and the AI **drifts into it unless it stops to check first**. Open fresh, every time.+- **Clean up after yourself.** When done with a window, **close it** (`browser_close_window` /+  `nbrowser_close_window`; `close_tab` for stray tabs). Long loops otherwise leave a graveyard of stale+  pup/native windows cluttering the taskbar — tidy as you go and again at the end.+- **Use the taskbar FLASH to say "come look," gently.** Whenever the loop updates a window during a+  ralph test (reloaded the page, applied a fix, grabbed a fresh shot), **flash its taskbar icon orange**+  — `browser_alert_window {sessionId}` (native: `nbrowser_flash {sessionId}`). It does **NOT** steal+  foreground; it just glows, so the user thinks *"oh, the AI updated that window — I'll peek if I want."*+  That gentle nudge is the whole point: **never force a window to the foreground** to show progress —+  that's rude and disruptive.++---++## Step 1 — Load + screenshot the app (pick the surface)++### A. Web app in a Hydrogen webview — the default for the user's OWN app+The user's app usually renders right in their Hydrogen workspace.+```bash+adom-cli hydrogen screenshot workspace               # the whole workspace+adom-cli hydrogen screenshot panel --panel-id <id>   # just the app's panel  (ids: hydrogen workspace get)+```+Reload between iterations by reloading the webview — or just save a file if the app hot-reloads.++**Pro/con — `adom-cli` hydrogen screenshots are SMART but Web Hydrogen pays a price.** These are the+only **smart** captures: they target a specific **webview / panel / tab** (not just an OS window), which+`adom-desktop` cannot do — it only targets **hwnds**. The catch is the permission model, and it splits+by environment:++- **Web Hydrogen (cloud):** the first `adom-cli hydrogen screenshot` makes the user approve the+  browser's native **screen-sharing prompt and pick the window** (a one-time browser security gate).+  That also flips the machine into a **screen-share mode like a Google Meet**, with side effects the+  user may not expect during a long loop: **displays won't sleep**, **screensavers won't fire**, a+  **laptop panel won't turn off at the hardware level**, and (likely) **Windows suppresses+  notifications**.+- **Hydrogen Desktop:** does **everything Web Hydrogen's smart targeting can** (webviews/panels/tabs),+  but with **no permission prompt and none of the Google-Meet side effects** — it turns screenshotting+  (and **screen recording**) **on and off on demand** because it never has to ask.+- **pup** and the **native browser** (with the extension) also capture with **no prompt**, but they+  target a window/page, not a Hydrogen panel.++So for an unattended ralph loop, prefer **Hydrogen Desktop / pup / native browser**; reach for **Web+Hydrogen's** smart panel targeting knowing it imposes the screen-share mode for the session.++### B. Web app in pup (Puppeteer) — fast, scriptable+```bash+adom-desktop -t AdomLapper browser_open_window '{"sessionId":"app","profile":"Default","url":"<url>"}'+adom-desktop -t AdomLapper browser_screenshot  '{"sessionId":"app","fullPage":true}'   # → /tmp/adom-desktop-screenshots+adom-desktop -t AdomLapper browser_reload      '{"sessionId":"app"}'+```+Great for your own apps and open public pages. **But** pup is an empty controlled-Chromium: more and+more sites **detect and block it** (e.g. `digikey.com`), and it's **logged in to nothing**. When that+bites, jump to C.++### C. Web app in the NATIVE browser via the Adom extension — logged-in, undetectable ⭐+When a site **blocks pup** or **needs you logged in**, drive the user's **real Chrome/Edge** with the+`nbrowser_*` verbs. Real cookies, SSO, saved logins and human-trust all apply, so it sails past the+login walls and captchas that stop pup. This is your best friend for surfing the web (or local apps)+with a full logged-in context.+```bash+adom-desktop -t AdomLapper nbrowser_status                                         # confirm connected+adom-desktop -t AdomLapper nbrowser_open_window '{"sessionId":"app","url":"<url>"}' # opens in the BACKGROUND+adom-desktop -t AdomLapper nbrowser_screenshot  '{"sessionId":"app","toFile":true}' # → a laptop PNG path+adom-desktop -t AdomLapper pull_file '{"filePaths":["<path>"],"saveTo":"/tmp"}'      # bring it into the container+adom-desktop -t AdomLapper nbrowser_reload '{"sessionId":"app"}'+```+Rules that matter (full reference: the **driving-the-extension** skill):+- **One-time install — AD installs it for you** (Step 1.5); it's not there by default.+- **Never reuse a window the user is working in — always open a FRESH one**, and `nbrowser_close_window`+  it when done. Yanking their live page is hostile.+- **Stay in the background — never foreground to grab a shot.** `nbrowser_screenshot` captures an+  occluded window fine (it reads the page bitmap, no OS-window interaction).+- Active clicking/typing makes Chrome show the yellow *"Adom… started debugging this browser"* bar+  (that's CDP). `navigate` / `reload` / `screenshot` go through native paths and keep it quiet.+- Bonus: `nbrowser_login_state {url}` checks if you're signed in now; `nbrowser_fetch_url` grabs a file+  behind a login using the real cookies — no clicking.++### D. Desktop app via an adom-desktop bridge+If the "app" is a desktop program (KiCad, Fusion 360, …), reload the file through its bridge and+screenshot the window:+```bash+adom-desktop -t AdomLapper desktop_list_windows                                    # find the hwnd+adom-desktop -t AdomLapper desktop_screenshot_window '{"hwnd":<hwnd>}'             # any native window+adom-desktop -t AdomLapper kicad_screenshot_all '{}'                              # or fusion_screenshot_all+```+"Reload" = re-open / re-load the file in the app (e.g. `kicad_open_board` again after you edit it).+`desktop_screenshot_window` captures the window **in the background** and returns an **array that+includes child windows**, so a popped-up **error/dialog box is captured automatically** — exactly what a+ralph loop needs to diagnose a failed reload.++## Step 1.5 — Installing the native browser extension (adom-desktop installs it for you)+It isn't there by default, but **it largely self-installs — don't just hand the user manual steps.**+Your container never talks to the extension directly; it drives **adom-desktop (AD)** on the laptop and+AD does the setup. First-time flow (the extension page's `INSTALL-FLOW.md` walks every step):++1. **Get the skills + mechanics:** `adom-wiki skills install adom/adom-browser-extension` — installs+   `driving-the-extension`, `native-browser-safety`, `driving-the-desktop`, the site recipes, etc.+2. **AD installs the bridge** (one call) and registers the tiny **native-messaging host** on the laptop.+3. **The extension gets loaded into Chrome/Edge.** Chrome 137+ removed `--load-extension`, so this is a+   one-time `chrome://extensions → Developer mode → Load unpacked`. **AD can drive that OS-level flow for+   the user** — the **driving-the-desktop** skill owns the extension's whole install / uninstall / reload+   lifecycle with a proven, validated recipe. Production uses a Chrome Web Store force-install.+4. **Confirm:** `nbrowser_status` → connected, and the full `nbrowser_*` surface (navigate, screenshot,+   reload, click, type, login_state, fetch_url…) is live.++So **install it FOR the user, not at them** — only ask them to approve a click when their machine isn't+Adom-managed and AD can't complete the OS step silently.++## Step 2 — Analyze → fix → reload+- **Analyze:** read the screenshot. Compare against intent — what's broken, wrong, missing, or ugly.+- **Fix:** edit the app's source / config / data file (or the desktop file).+- **Reload:** the matching reload for your surface — reload the Hydrogen webview, `browser_reload`,+  `nbrowser_reload`, or re-open the desktop file. (Web apps with hot-reload refresh on save.)++## Step 3 — shotlog: how you AND the user actually SEE every shot (do NOT skip)+**This is the most important habit in the loop, and the AI keeps forgetting it — don't.** The Claude+Code **VS Code extension can't render images inline** (Claude Desktop can; the VS Code one still+can't), so shotlog is the surface where **both you and the user actually look at each screenshot as the+loop runs.** It is *not* mainly a phone thing — the phone is ~5% of why it matters.++Two rules, every single iteration:+1. **Open a shotlog TAB in the topic's browser window — up front.** Add the channel's live gallery as a+   tab alongside your ralph-test tabs (`browser_open_tab {sessionId,url:"<shotlog gallery url>"}` /+   `nbrowser_open_tab`) so every new shot appears right next to the app you're debugging. The AI+   routinely forgets this — make it the **first** thing you do when a ralph test starts.+2. **Inject EVERY screenshot from EVERY surface.** Hydrogen, pup, native browser, desktop window — no+   matter where the shot came from, it goes into shotlog immediately:+   ```bash+   shotlog inject -c <channel> -d "iter-<N>-<what-changed>" -s <source> <file.png>   # +--orig-w/--orig-h if pre-resized+   ```+   The gallery live-updates over WebSocket, newest-first, in that tab (and on the phone if the user+   wants it). **Never take a shot that doesn't land in shotlog.**++## Running the loop+- **Unattended:** drive it with the `/loop` skill (self-paced). Each pass: screenshot → analyze → fix →+  reload → screenshot → `shotlog inject`. `/loop` keeps the harness + Adom tools live between passes.+- **Stop when fixed:** the loop ends when the screenshot matches intent (the AI judges the shot), or on+  a manual stop. **Always cap iterations** so a stubborn fix doesn't spin forever.++## Surface cheat-sheet+| App / situation | Load + screenshot | Reload |+| --- | --- | --- |+| User's own web app in their workspace | `adom-cli hydrogen screenshot workspace \| panel` | reload webview / hot-reload on save |+| Your web app or a public page (no login, allows automation) | pup: `browser_open_window` → `browser_screenshot` | `browser_reload` |+| Site that blocks pup or needs login (DigiKey, vendor portals) | native: `nbrowser_open_window` → `nbrowser_screenshot` + `pull_file` | `nbrowser_reload` |+| Desktop app (KiCad / Fusion / …) | `desktop_screenshot_window` / `kicad_screenshot_all` | re-open the file via its bridge |++Then **always** finish each iteration with `shotlog inject` → the **shotlog tab in your topic window**+(where you and the user both watch — the VS Code extension can't show images inline). Phone is a bonus.
install.shadded+11
@@ -0,0 +1,11 @@+#!/bin/bash+set -e+PKG_DIR="$(cd "$(dirname "$0")" && pwd)"+SKILLS_DIR="$HOME/.claude/skills"+mkdir -p "$SKILLS_DIR/ralph-loop-test"+for f in "$PKG_DIR"/*; do+  base=$(basename "$f")+  case "$base" in package.json|install.sh|uninstall.sh|README.md|page.json|screenshots) continue ;; esac+  cp -r "$f" "$SKILLS_DIR/ralph-loop-test/"+done+echo "Installed ralph-loop-test -> $SKILLS_DIR/ralph-loop-test"
package.jsonadded+27
@@ -0,0 +1,27 @@+{+  "type": "skill",+  "slug": "ralph-loop-test",+  "title": "Ralph Test",+  "brief": "Screenshot, fix, reload. Loop until your app is right.",+  "version": "1.0.0",+  "description": "The Adom 'ralph test': a screenshot-driven fix loop. Load the user's web or desktop app, screenshot it, let the AI analyze and fix what is wrong, reload, screenshot again, and loop until it is right. Covers every Adom screenshot surface (Hydrogen webview, pup, the native Chrome/Edge extension, desktop bridges) and the shotlog viewer workflow.",+  "tags": ["ai-agent", "screenshot", "debugging", "ralph", "loop", "browser-automation", "shotlog", "testing"],+  "dependencies": {},+  "scripts": {"install": "./install.sh", "uninstall": "./uninstall.sh"},+  "needs_sudo": false,+  "discovery_triggers": [+    "ralph",+    "ralph test",+    "ralph loop",+    "ralph wiggum",+    "ralph wiggum loop",+    "screenshot loop",+    "visual fix loop",+    "loop until fixed",+    "test my app with screenshots",+    "screenshot and fix",+    "fix loop"+  ],+  "discovery_pitch": "Run a ralph test: load your app, screenshot it, and let the AI loop on fix, reload, screenshot until it looks right.",+  "hero": {"type": "image", "path": "screenshots/hero.png"}+}
screenshots/hero.pngadded
⋯ 1 unchanged line ⋯
uninstall.shadded+4
@@ -0,0 +1,4 @@+#!/bin/bash+set -e+rm -rf "$HOME/.claude/skills/ralph-loop-test"+echo "Uninstalled ralph-loop-test"