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
Update 2 file(s)
2 files changed
+87
dev-skills/pup-taskbar-identity/SKILL.md+49@@ -58,6 +58,55 @@ bash dev-skills/pup-taskbar-identity/ralph_icons.sh 9 - **Warm the bridge before asserting** — cold-start (post-install/idle respawn) flakiness is an ab lifecycle issue (ab#61), not icon logic; it produces false failures in rounds 1-2. +## Jump-list tasks: pup calls ITSELF (the direct-callback model, v2.0.41)++A jump-list task is a Windows ShellLink `{title, target?, args?, iconPath?, description?}` that+`desktop_set_window_jumplist` writes onto the taskbar button's right-click menu. The trap: if you+OMIT `target`, ab supplies the program (its own bundled CLI) — an exe path pup neither controls nor+can verify. That path broke when the CLI RENAMED (`Adom Desktop\adom-desktop-cli.exe` →+`Adom Bridge\adom-bridge-cli.exe`), so every task (incl. "Close ALL") silently no-opped: the click+launched a missing exe. John: "be way smarter about how to call back into ab for the jump lists ...+should pup be able to talk back to itself when it's its own bridge?"++**Answer: yes, for pup_* verbs.** Every task now sets `target: 'powershell.exe'` and `args` that run+a pup-OWNED launcher script (`%LOCALAPPDATA%\Adom Bridge\pup-jumplist-call.ps1`, written on every+bind). The launcher:+1. reads pup's OWN loopback port from a discovery file pup rewrites on bind+ (`%LOCALAPPDATA%\Adom Bridge\pup-bridge-port.json`), then+2. POSTs the verb straight to `http://127.0.0.1:<port>/command` — **pup talking to itself**: no ab+ relay hop, no CLI exe, no stale path (the two things that broke it), and+3. ONLY if that direct hit throws (pup idled/died — the Chrome windows OUTLIVE the node process, and+ pup→pup can't wake a dead pup) falls back to the resolved `adom-bridge-cli.exe`, which goes+ through ab and RESPAWNS pup. Fast+accurate when up; ab-wake when asleep.++No ab feature was needed — the per-task `target` field already existed. Relevant code:+`pupTask()`, `ensurePupJumplistLauncher()`, `writePupPortFile()`, and `pupCliExe()` (disk-resolves+the renamed CLI, Bridge name first, legacy fallback) in server.js.++### Traps (each cost a debug cycle)+- **JSON args ride as BASE64**, not escaped JSON. The ShellLink→Explorer→powershell argv re-parse+ ate raw escaped JSON for years (the v1.9.9 quoting saga). Base64 is argv-safe (no spaces/quotes);+ the launcher decodes it. `pup_close`'s `{}` → `e30=`.+- **The launcher path has a SPACE** ("Adom Bridge"), so `pupTask` wraps it in quotes:+ `-File "${launcher}"`. When you TEST via `shell_execute`→cmd, you must double the backslashes in+ the JSON (`C:\\Users\\...`) AND keep the quotes, or cmd/JSON mangles the path and powershell gets+ `-File C:\...\Adom` — the exact false-negative that made me think the launcher was broken when it+ wasn't. The real ShellLink (ab-authored) has no such re-escape; it works on click.+- **`user-taskbar-menu` is the caller identity** (header `x-adom-caller-thread` + `args.caller`).+ The ownership gate in `/command` EXEMPTS it, so a human clicking Close ALL is never refused for+ "not owning" the window. Don't route jump-list clicks through a normal thread name.++### THE JUMP-LIST RALPH RULE (John: "have you ralph tested those?")+A single click looking right proves nothing here either. `ralph_jumplist.sh` (this folder) runs N+rounds: open wiki windows → fire owner-info + view-toggle + Close ALL **through the real deployed+launcher** (the actual taskbar-click path, `powershell -File launcher verb b64`) → assert the+observable effect (toggle/info don't crash the window; Close ALL empties the count to 0). Clean run+is 0 failures. Baseline proof (2.0.41): 5/5 rounds, 0 failures.++```bash+bash dev-skills/pup-taskbar-identity/ralph_jumplist.sh 5+```+ ## Known remaining gap Cold-start: the first 1-2 windows opened immediately after a bridge respawn can miss their handle
dev-skills/pup-taskbar-identity/ralph_jumplist.shadded+38@@ -0,0 +1,38 @@+#!/bin/bash+# Ralph test for pup JUMP-LIST tasks: each round opens wiki windows, then fires the ACTUAL+# jump-list task commands through the REAL deployed launcher (powershell -File launcher verb b64),+# asserting the observable effect: view-toggle + owner-info return success, Close ALL empties.+TGT=AdomLapper+ROUNDS=${1:-5}+LAUNCHER='C:\\Users\\john\\AppData\\Local\\Adom Bridge\\pup-jumplist-call.ps1'+ab(){ adom-bridge-cli --target $TGT "$@" 2>&1; }+count(){ ab pup_list_windows '{}' --ai-thread rjl 2>&1 | python3 -c "import sys,json;print(len(json.load(sys.stdin).get('sessions') or []))" 2>/dev/null; }+# fire a task through the real launcher exactly as a taskbar click does+fire(){ # $1 verb $2 json+ local b64=$(python3 -c "import base64,sys;print(base64.b64encode(sys.argv[1].encode()).decode())" "$2")+ ab shell_execute "{\"command\":\"powershell.exe -NoProfile -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass -File \\\"$LAUNCHER\\\" $1 $b64\",\"reason\":\"ralph jumplist: fire $1 via real launcher (taskbar-click path)\"}" --ai-thread rjl >/dev/null 2>&1+}+fail=0+for r in $(seq 1 $ROUNDS); do+ ab pup_open_window '{"url":"https://wiki.adom.inc/adom/pup-bridge","foreground":false}' --ai-thread "rjl-$r-a" >/dev/null 2>&1+ ab pup_open_window '{"url":"https://wiki.adom.inc/adom/pup-bridge","foreground":false}' --ai-thread "rjl-$r-b" >/dev/null 2>&1+ sleep 6+ pre=$(count)+ # owner-info + view-toggle on window a (observable: no error, window survives)+ fire pup_window_info "{\"sessionId\":\"ai-rjl-$r-a\"}"+ fire pup_wiki_set_view "{\"sessionId\":\"ai-rjl-$r-a\",\"view\":\"public\"}"+ sleep 3+ mid=$(count)+ # Close ALL via the launcher — the click John reported broken+ fire pup_close "{}"+ sleep 5+ post=$(count)+ prob=""+ [ "$pre" -lt 2 ] && prob="$prob OPEN-FAIL($pre)"+ [ "$mid" != "$pre" ] && prob="$prob VIEW/INFO-CHANGED-COUNT($pre->$mid)"+ [ "$post" != "0" ] && prob="$prob CLOSE-ALL-LEFT($post)"+ if [ -n "$prob" ]; then echo " r$r pre=$pre mid=$mid post=$post ->$prob"; fail=$((fail+1)); fi+ echo "round $r: opened=$pre after-toggle=$mid after-closeall=$post (running fails=$fail)"+done+echo "===================="+echo "JUMPLIST RALPH DONE: $ROUNDS rounds | FAILURES: $fail"