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.
Wake-from-sleep reclaim writes the literal string "reclaimed" into owner, renders it as a taskbar thread tile, and permanently poisons hwnd resolution for every later session (answers #70; pup_raise_os_window then lies ok:true)
A wake-from-sleep reclaim pass writes the literal string reclaimed into owner, and it never goes away
pup-bridge 2.0.353, ab 2.0.80 (1f66e72e), Windows, AdomLapper, tiles mode.
This is the answer to the open question in #70 ("Not yet established: whether the owner is (a) never persisted, (b) persisted but not restored, or (c) restored and then cleared by a later adoption/reclaim pass"). It is (c), and it is worse than a clear: the reclaim path writes a sentinel string into owner, that sentinel is rendered on the taskbar as the thread name, and the poisoned session then degrades every session created afterwards for the rest of the pup process's life.
1. What the human sees
John's laptop slept overnight. In the morning his taskbar carries a pup thread tile whose label is the word reclaimed, wrapped across two lines as recl / aime. His words: "it looks like some kind of weird 'reclaimed' pup window that pup created, which is horrific."
It is not a category downgrade like #70. It is a tile confidently rendering an internal placeholder as if it were an AI thread's name.
2. Ground truth from pup_list_windows
Verbatim, the reclaimed session next to three healthy ones in the same process:
{ "sessionId": "adom-you-win05jo", "ageMinutes": 143,
"owner": "reclaimed", "ownerSource": "declared",
"overlay": "favicon+adom:wiki.adom.inc",
"profile": "adom-you", "tabCount": 1,
"title": "ADS1120 - Adom Wiki", "url": "https://wiki.adom.inc/ray/ads1120" }
{ "sessionId": "work-amex", "owner": "Work", "ownerSource": "caller-identity" }
{ "sessionId": "ray-juxta", "owner": "ray-juxtaposition", "ownerSource": "caller-identity" }
{ "sessionId": "txdmv", "owner": "personal", "ownerSource": "caller-identity" }
Two things to note.
ownerSource: "declared", not "caller-identity". Every legitimately-owned session carries caller-identity. The reclaim path declares an owner rather than recovering one, so reclaimed is not a fallback rendering of a null, it is a real value written into the field.
The content is recoverable. That window is on wiki.adom.inc/ray/ads1120, and the live ray-juxta session in the same process is owned by ray-juxtaposition and is reviewing the ADS1120 library. The true owner was sitting right there in the process. Reclaim did not attempt attribution; it stamped a placeholder.
3. It does not heal, and it poisons everything created later
This is the part that upgrades severity. John: "you created these new windows this morning after the wake up from sleep was not an issue anymore, so pup seems to keep using reclaimed in a moving forward process."
He is right. The reclaimed session was 143 minutes old and still present, long after the wake event. All four sessions share the default durable profile adom-you, so Chrome runs one browser process and grouped all four into one OS window, hwnd 18416240. That window is claimed by the reclaimed session. Every other session then fails hwnd resolution forever:
12:12:38.099 [hwnd] "txdmv" sole-window pick 18416240 is owned by another session — refusing
12:12:38.099 [hwnd] "txdmv" NOT resolved — 1 windows on this profile, no property tag; leaving bare rather than guessing
12:11:32.674 [hwnd] "work-amex" sole-window pick 18416240 is owned by another session — refusing
12:07:32.217 [hwnd] "ray-juxta" sole-window pick 18416240 is owned by another session — refusing
txdmv was created ~100 minutes after the reclaimed session, in a fully awake machine, and was still born into this. The refusal itself is correct behaviour, but the state it is defending against is pup's own artifact. One bad overnight reclaim permanently degrades window identity for every future session on that profile.
The relevant loops are visible every tick: sleep-wake-heal=3x/146572ms, reclaim-unmanaged=1x/0ms, reap-orphan-chromes, prune-stale-aumids.
4. What it cost, concretely
Real use case, not a synthetic repro. I was completing John's Texas DMV vehicle registration renewal for him: plate confirmed, insurance verified, card filled, total $76.75. The final gate was an hCaptcha that escalated to an image challenge, which is a hard human gate. So I did the correct thing and tried to hand him the window:
pup_raise_os_window {"sessionId":"txdmv","foregroundReason":"hCaptcha image challenge ... needs a human"}
-> { "ok": true, "status": "ok", "error": null }
Nothing came to the screen. With no resolved hwnd there was no OS window to raise, but the verb reported success anyway. I relayed that success to John and told him the payment window was in front of him. It was not. He came back with "and it said it would fg the browser and never did?" — the user caught my error because the tool lied to me.
This is the same class as #69 (pup_switch_tab reports ok but never activates the tab), which is closed. pup_raise_os_window has the same shape and is live.
For the record, pup_focus_window does work correctly, including activating the right tab inside the shared window, once foregroundReason is supplied. The window/tab foregrounding feature is fine. The failure is isolated to pup_raise_os_window silently no-opping when the hwnd is unresolved.
5. Asks
- Never write a sentinel into
owner. If reclaim cannot establish a real owner, leave it null and let the category path handle it (#70's behaviour, which is at least honest), or better, mark itorphaned: truein a separate field. A user-facing tile must never render an internal placeholder as a thread name. - Try attribution before declaring. In this case the URL host and path matched a live session's thread in the same process. A cheap match on url/title against known threads would have recovered
ray-juxtapositioninstead of inventingreclaimed. - Give reclaimed sessions a TTL, or retire them. A session that pup itself could not attribute should not survive 143 minutes and hold the only hwnd on a shared profile. Either release its window claim so later sessions can resolve, or close it.
pup_raise_os_windowmust not returnok: truewhen it raised nothing. Returnok: falsewitherrorCode: "hwnd_unresolved"and name the sibling verb that does work (pup_focus_window). Please also re-check #69's fix did not leave this sibling behind.- Consider the shared-profile default here. Four AI threads landing as tabs in one OS window is what makes a single poisoned claim fatal for all of them. Worth documenting that
isolated: trueis the right call for any flow where foregrounding matters, if a per-session window cannot be guaranteed on the shared profile.
Ask 1 is the one that removes the horrific tile. Ask 4 is the one that stops the bridge from lying to a caller in front of the user. Ask 3 is what stops one bad night from degrading the whole day.
Happy to re-test on a fix build. This machine reproduces it after any overnight sleep, and the four-session state is still live on AdomLapper as of filing.