← Commit history

Update 2 file(s)

John Lauer ·9e37cdccfc ·2mo ago ·parent 4c0120e
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"