Commit History

latest 1000 ← Back to Activity
Clean up zombie sessions automatically and REPORT the cleanup to the next caller (John's design). Two parts. (1) Zombie detection was gated on _lostBrowser, a flag only set when a DISCONNECT EVENT fires — a Chrome killed outright (the bridge-restart tree kill) never emits one, so those sessions sat with 0 tabs, no flag, and were never dropped. That is exactly the four zombies John found cluttering browser_list_windows for every thread. Zero tabs plus a dead CDP port is now sufficient, with a _launchInFlight guard so a session mid-launch is never mistaken for one. (2) A cleanup REPORT QUEUE: each janitorial action (zombie session dropped, orphaned browser processes reaped) is recorded and attached to the NEXT verb response as _cleanupReport, then dropped — report-once. Per John, the receiving thread is usually NOT the one whose window was cleaned; that is accepted, it can ignore the note, and the information still reaches the user eventually instead of never. Verb-scoped so AD's health poll cannot swallow it, capped at 12 entries, and added to the output-merge list because anything left on the outer envelope is silently dropped on a SUCCESSFUL call.
John Lauer · b6e1cdd · 16d ago
Publish 1.9.118
John Lauer · 6794997 · 16d ago
Lint URLs at CALL TIME and reprimand the calling AI, rather than waiting for a 404 to reveal it (John: 'you should have complete awareness of how wiki urls are constructed so you can reprimand the calling ai', plus 'you should linter on localhost:{port} urls too'). 1.9.117 only fired on a render failure, which is too late: the HD thread had already reported a wrong conclusion to the user before the 404 came back. Every render verb now returns _urlLint plus urlLintCode on the URL itself, pass or fail. Two rules encoded: (1) url_wiki_missing_owner — wiki.adom.inc pages are owner-qualified /<owner>/<slug> (and /<owner>/<slug>/blob/<path>), so a single-segment URL 404s regardless of who is logged in; the lint gives the corrected URL, says to confirm the owner with 'adom-wiki page get <slug>' rather than trust the guess, and explicitly forbids concluding the page is private (the exact wrong conclusion a thread reported). Known non-page routes are excluded. (2) url_localhost — pup drives a browser on the USER'S desktop, so localhost/127.0.0.1 resolves on THEIR machine, not the caller's container; the lint now composes the container's proxy URL using the caller's own container name from X-Adom-Caller-Container. Unit-tested 7/7 including valid controls.
John Lauer · b06e261 · 16d ago
Lint a malformed wiki URL and name the real cause, instead of letting the caller invent one. The HD build thread opened https://wiki.adom.inc/adom-wiki-skillpack, got 'Page not found', and reported to John that 'org pages are invisible to logged-out readers'. That conclusion was WRONG and cost trust: the window was signed in as John the entire time (pup's auto-login had worked), the page exists and is public, and the URL was simply missing its OWNER segment — wiki.adom.inc pages are owner-qualified as /<owner>/<slug> (and /<owner>/<slug>/blob/<path> for a file). pup already knew the URL 404'd and knew the host, so it could have named the cause. It now does: on a render failure, a new wikiUrlLint() detects a wiki URL with no owner segment (including the /blob/ form), suggests the corrected URL, tells the caller to confirm the real owner with 'adom-wiki page get <slug>' rather than trust the guess, and explicitly says NOT to conclude anything about permissions or login until the URL is right and re-checked. Known non-page routes (apps, skills, components, discover, login, api, ...) are excluded. Unit-tested 6/6 against the thread's three real URLs plus valid controls.
John Lauer · 22c81fe · 16d ago
Make a bridge upgrade REPAIR the jump-list task commands on windows that already exist. This is why John's 'Switch to public view' still failed after 1.9.115 fixed the command format: a jump-list task embeds a full CLI command line, and stampPupIdentity only re-commits the list when the appId CHANGES, so any window whose category was unchanged across the upgrade kept its OLD identity-less command and the click was refused silently — while the very same verb worked perfectly when I called it from the CLI, which is exactly why my verification passed and his click did not. On every bridge start pup now clears the jump-list dedupe key for all recovered sessions before the startup brand sweep, so the re-attach is real instead of a no-op and every surviving window gets task commands matching the running version. One AD call per live window, once per boot.
John Lauer · 730995c · 17d ago
Publish 1.9.115
John Lauer · dc5955f · 17d ago
Sweep the caller-identity requirement EVERYWHERE instead of waiting for John to find each instance (his words: 'then look for that issue everywhere instead of waiting for me to discover it'). AD (>=1.9.183) refuses any command lacking caller identity, and I had only fixed the bridge's own outbound calls in 1.9.114. Audited all four categories where pup causes or teaches an AD command: (A) adCommand — 33 call sites, already unconditional since 1.9.114; (B) commands pup composes for WINDOWS to run — the jump-list TASKS and the relaunch/pin command carried no identity, so clicking 'Switch to logged-in view' was refused and silently did NOTHING (reproduced by running the exact CLI line a task runs); both now pass --ai-thread 'user: pup taskbar menu'/'...launcher', which is honest because a human clicked; (C) no other CLI invocations exist in the bridge (verified); (D) the category I would have missed — pup's own HINTS and its user SKILL.md handed out 9 example commands with no --ai-thread, so any caller copying them verbatim got refused; all now show the flag, and the skill documents why it is per-call and why exporting ADOM_AI_THREAD is wrong.
John Lauer · c8bd858 · 17d ago
Dev skill: record the caller-identity regression that un-branded and stranded every pup window, and the rule it produced — when touching a shared call path, verify the path that ALREADY worked (open a window, confirm branded + on-screen) rather than only the feature you added. Includes the two log/rect tells and the rescue procedure.
John Lauer · 73dda30 · 17d ago
Publish 1.9.114
John Lauer · 779eaf0 · 17d ago
CRITICAL FIX: pup sent NO caller identity on its own AD callbacks, and AD (>=1.9.183) refuses any command without one — so EVERY desktop_* call from the bridge was rejected. Blast radius was total and user-visible: desktop_set_window_identity refused means no window got branded (all five example windows fell back to Chrome's icon, including OTHER threads' windows), and the on-screen park being refused left windows stranded at -32768,-32768 so clicking their taskbar button showed nothing. Root cause was my own reasoning error in 1.9.104: I forwarded the originating thread for session-scoped calls but deliberately sent nothing when pup acted on its own behalf, thinking 'no caller' was the honest answer. AD's answer to no caller is a refusal, and the contract explicitly says to send your OWN caller block for your own work. adCommand now ALWAYS identifies a caller (the forwarded thread when there is one, else 'pup bridge (self)'), and sends it as BOTH a header and an args caller block because AD's precedence puts args above headers and a header-only path must not be able to silently un-brand every window again.
John Lauer · a045b8d · 17d ago
Correct the record on the jump-list blip. The v1.9.112 post-stamp jump-list re-commit did NOT fix it: three fresh windows each got exactly 1 AUMID registration plus 1 re-commit and all still showed the flyout for ~200-300ms before it vanished. The re-commit stays (attaching the destination list to the live button is correct hygiene) but its comment no longer claims to be the cure. The blip is UNRESOLVED and now tracked on adom/adom-desktop#40 with all four eliminated hypotheses and the measurements behind each, plus a decisive diagnostic AD can run on its own window (AD flips its own AUMID for the mode signal, so if AD's own flyout blips the behaviour is inherent to runtime AUMID retagging and reproduces without a bridge).
John Lauer · 36c8253 · 17d ago
Debug skill: record the jump-list blip as UNRESOLVED with the four eliminated hypotheses and how each was measured, so nobody re-derives them. Tracked as adom/adom-desktop#40. Includes the two process lessons: eliminate with measurement rather than with a shipped fix, and 'seems ok now' is not a pass unless you know which instance was tested.
John Lauer · d54f631 · 17d ago
Jump-list first-right-click dismissal: re-commit the destination list once the taskbar button actually exists. Reached by ELIMINATION, with measurements: nothing fires while windows are idle (0 log lines across 40s), windows that registered exactly ONE AUMID blip too (so it is not category churn), and a registry-only vs Start-Menu-shortcut A/B showed no difference (so it is not the missing shortcut). What every FRESH window shares is that the identity stamp RECREATES the taskbar button (Win11 bakes a button's identity at creation) while the jump list was committed BEFORE the stamp — deliberately, so the header art bakes. So the button is born pointing at a destination list committed against a button that did not yet exist, and the first right-click is the shell reconciling that, which is exactly why the second click works. pup now re-commits the list ~1.6s after a successful stamp, guarded so a superseded stamp does not clobber a newer one. Still a hypothesis until John re-tests a freshly opened window.
John Lauer · f024cc6 · 17d ago
Publish 1.9.111
John Lauer · a1b0103 · 17d ago
Name the pup MODE in the jump-list header row (John's ask). pup paints five different category icons in the taskbar (public wiki, signed-in wiki, Adom app, plain web page, mixed content) and already names them in the hover tooltip, but the right-click header row just said 'Adom Pup', so the icon's meaning was guesswork. The header now reads 'Adom Pup · wiki · LOGGED IN', 'Adom Pup · Adom app', etc. Uses a SHORTER label set than the tooltip's CAT_LABEL because the flyout is width-constrained (all five land at 19-28 chars, against 'Close ALL Adom Pup windows' at 26 which is known to fit). Applied to the per-session identity stamp and registration only; the base global identity keeps the plain name since it has no category. No new mechanism needed: the per-session AUMID already encodes the category, so a category flip mints a new appId and carries the new name with it.
John Lauer · 2586b0d · 17d ago
Publish 1.9.110
John Lauer · 69cd7b8 · 17d ago
Two fixes. (1) Close the set-enumeration gap I apologized for: RENDER_VERBS has four members and I had wired three, so browser_open_tab silently skipped the render check that browser_open_window performs. A tab is content on the user's screen exactly like a window, so it now captures its own HTTP status and runs probeRender. (2) Issue #22 (AdityaAngajala), the non-breaking half: sessions are no longer left unowned and ownership is settled at ADMISSION rather than at browser acquisition. The owner is the explicit owner arg when given, else the calling AI thread's own name from X-Adom-Caller-Thread, so 'unowned' stops being reachable for any caller that identifies itself; and a synchronous claim registry (no await between check and set) refuses a second differently-owned caller immediately with a COLD-START RACE explanation instead of handing it a provisioning hint that implies 'retry and it's yours'. Claims are released on close and close-all. Deliberately NOT included: refusing an anonymous grab of an owned session, which is a breaking contract change and is John's call.
John Lauer · 301315d · 17d ago
Publish 1.9.109
John Lauer · 5bf7900 · 17d ago
Probe on RELOAD and NAVIGATE too, and order the response by consequence. The hole John caught: only browser_open_window ran the render probe, so a thread that hit a 404, restarted its dev server, called browser_reload and got ok:true with the GENERIC 'do not assume it rendered' hint concluded 'Mockup is now live again' — reporting success on a page nobody checked. The verb used to CONFIRM a fix is exactly the verb that must verify it, so reload and navigate now capture their own HTTP status and run probeRender, and on any render verb a detected failure PREPENDS the hint ('THE PAGE IS STILL BROKEN: ...'). Also trimmed the boilerplate that the critical fields were competing with: the ~32 pre-granted permission strings collapse to a count plus a pointer to browser_describe, and the full browser inventory collapses to compact kind(source) labels since the chosen browser is already reported separately.
John Lauer · e8376da · 17d ago
A detected render failure must LEAD the response, not hide behind cosmetics (John, reading a real launcher-mockup response). The 1.9.106 verdict was correct and the calling AI did act on it ('Dev server crashed. Let me restart it'), but _hint opened with a FAVICON nag, then a power lecture, then a browser inventory, so the single most important fact — that the page was a 404 — sat screens down past 32 permission strings and an availableBrowsers list. Rich hints are the right instinct; burying the critical one behind cosmetic ones is not. When renderCheck.ok is false, _hint now opens with the failure, the signals, the HTTP status, what the page actually says, an explicit do-NOT-report-success, and the screenshot command, then appends the cosmetic hints marked as secondary.
John Lauer · 139a069 · 17d ago
Publish 1.9.107
John Lauer · 552eb12 · 17d ago
Dev skill: shipping behavior means shipping docs — skills, then pkg, then release. Records that knowing the release-vs-pkg trap did not prevent it, which is why it is now a ship gate.
John Lauer · 828d755 · 17d ago
Publish skill: make every ship THREE artifacts in order (skills, then pkg tarball, then release zip), with the two measured failures that motivate it — a user skill left stale on a whole day of shipped behavior, and releases outrunning the pkg so the max version row had no tarball and every constraint install 404'd.
John Lauer · 1fb70b7 · 17d ago
Show WHY a pup window exists, not just who opened it (John's ask, via a Gemini suggestion to abuse thumbnail-toolbar buttons). pup now captures X-Adom-Caller-Reason alongside the thread and container and surfaces it on the taskbar hover preview as a 'why:' line. Placement is deliberate: the preview HEADER is the window title and truncates around 25-30 chars, and a thumbnail-toolbar button carries a 16px ICON plus a nested hover tooltip rather than inline text, so a reason sentence can only live on the thumbnailTooltip, which is uncapped and takes newlines. The reason is also logged next to the owning thread so bridge_log_read explains why each window was opened.
John Lauer · 0fcc8fd · 17d ago
Publish 1.9.106
John Lauer · dbc4b2b · 17d ago
Stop reporting ok:true for a page that plainly did not render (John's catch). The launcher-mockup thread opened a .adom.cloud app serving '404 page not found'; pup answered ok:true, said nothing, and the AI reported success. Advising a screenshot was too weak, so pup now LOOKS: probeRender() checks the loaded document (main-frame HTTP status captured at goto, plus 404 / 'Cannot GET' / server-error / visible-stack-trace text, effectively-blank body, zero stylesheets, broken images) and the open response carries machine-readable renderCheck{ok,httpStatus,signals,excerpt}. On a detected failure _verifyRender no longer offers advice, it LEADS with 'THIS PAGE DID NOT RENDER CORRECTLY, pup checked it, do NOT report success', names the signals, quotes the page, and says not to tell the user it works while the warning is present. Also fixes a silent bug of mine: the HTTP status was assigned to a 'session' variable that does not exist inside launchSession, so it threw into a catch and captured nothing; now stashed on the page object. (1.9.105 shipped this feature DEAD because a patch anchor failed while the ship proceeded — the same patch/ship desync documented in the dev skill; markers verified before shipping this time.)
John Lauer · cc0f510 · 17d ago
Stop reporting ok:true for a page that plainly did not render (John's catch). The launcher-mockup thread opened a .adom.cloud app that served '404 page not found'; pup answered ok:true, said nothing, and the AI reported success. Telling the caller to screenshot was too weak, so pup now LOOKS: a new probeRender() checks the loaded document (main-frame HTTP status captured from goto, plus 404 / 'Cannot GET' / server-error / visible-stack-trace text, effectively-blank body, zero stylesheets loaded, broken images) and the open response carries a machine-readable renderCheck{ok,httpStatus,signals,excerpt}. When it detects a failure, _verifyRender no longer offers advice — it LEADS with 'THIS PAGE DID NOT RENDER CORRECTLY, pup checked it, do NOT report success', names the signals, quotes the page, and says do not tell the user it works while this warning is present. Fixed my own silent bug along the way: the HTTP status was being assigned to a 'session' variable that does not exist in launchSession, so it was throwing into a catch and capturing nothing; it is now stashed on the page object.
John Lauer · ad940b9 · 17d ago
Publish 1.9.104
John Lauer · 3a7d97f · 17d ago
Complete the caller-identity delegation chain on pup's side (AD 1.9.183 contract). AD fixed its half (it no longer drops X-Adom-Caller-* on the bridge's loopback callback), but the bridge half is not automatic and pup was not doing it: every AD verb pup calls back on a thread's behalf now carries X-Adom-Caller-Delegate:'pup' (unconditional — that is what turns a nameless 'via bridge' into '<thread> (via pup)'), and the 10 session-scoped callbacks that resolve a window by its session tag now forward the OWNING thread + container via a new sessionCaller() helper. Per the contract, a bridge must NOT forward a stale identity when acting on its own behalf, so pup's timers, sweeps and health polls deliberately pass no caller and read honestly as pup's own work. All of it stays self-reported and authorizes nothing.
John Lauer · b038314 · 17d ago
Put the owning AI thread ABOVE the taskbar hover-preview, where John was actually looking. The header Windows draws above the preview IS the window title (Chrome derives it from document.title), so the tooltip work in 1.9.101 was real but invisible there. The thread tag now LEADS the title — 'adom-tsci · Example Domain (session: x)' — so it survives the ~25-30 char truncation in that header and answers 'which of my 20 threads made this window' at a glance. Implemented WITHOUT adding a third title mutator: the code already documents that two observers writing the same region ping-pong forever, peg the renderer and flood CDP (which hung browser_open_tab on Edge), so the wiki glyph and the new thread tag are now ONE composed prefix slot under ONE observer, applied in a fixed order, and stripping only ever removes decorations we know we wrote (never a page title that merely contains a middot). Tag capped at 18 chars; re-asserted after navigation.
John Lauer · f579ea2 · 17d ago
Fix the owning-thread stamp missing on the window that matters most. The v1.9.101 stamp ran at dispatch and could only find a session that ALREADY existed — but on browser_open_window the session is created inside the handler, so the window a thread had just created got no identity and its hover tooltip read '(no AI-thread identity yet)'. The owner is now stamped as soon as the session is real, so a freshly opened pup window immediately shows 'adom-tsci · galliaApril' on its taskbar preview.
John Lauer · 3216b10 · 17d ago
Surface the owning AI thread on the taskbar hover preview (John's ask). pup was DISCARDING the caller identity AD stamps on every relayed bridge request (X-Adom-Caller-Thread / X-Adom-Caller-Container); it now captures both, stamps the FIRST thread to touch a session as that window's owner, tracks lastDrivenBy so a handoff stays visible, and LEADS the thumbnail tooltip with 'thread · container'. With ~20 threads running at once a pup window is effectively an AI thread, so this turns an anonymous Chrome preview into 'that's my adom-tsci thread'. The tooltip is the only UNCAPPED text surface on the preview (the header above the thumbnail is the window title and truncates ~25-30 chars). Also fixes a line that has been wrong since native-first: the tooltip claimed 'Chrome for Testing' unconditionally and now reports the browser actually driving the window, plus the sessionId.
John Lauer · d3e4b4e · 17d ago
Dev skill: record WHY an exported env var cannot clobber a sibling AI thread (per-process environment copy, demonstrated with concurrent subshells) so the next reader doesn't wrongly avoid exports — the only shared-state risk was ~/.bashrc.
John Lauer · a070e5a · 17d ago
Dev skill correction: the caller-identity env var MECHANISM is fine (a per-call PREFIX is clean and leaks nothing); only a durable shared-profile export misattributes. Records all three measured forms so the next reader picks the prefix rather than over-correcting away from env vars entirely.
John Lauer · beee1dd · 17d ago
Dev skill: caller identity must be passed PER CALL, not via a shared-container env var (John's catch) — plus the non-interactive .bashrc guard that made the documented env-var fix a silent no-op.
John Lauer · df7efdd · 17d ago
Make pup insist the AI LOOKS at what it just rendered (John's ask). browser_open_window / browser_open_tab / browser_navigate / browser_reload now return a _verifyRender instruction: the exact browser_screenshot command, a concrete checklist of what to look for (blank/white page, unstyled flash of plain HTML meaning CSS never loaded, a stack trace or framework error overlay, missing images, broken or overlapping layout, content cut off, a dev-server 'Cannot GET /', or the wrong build), and the ralph-test loop — fix the source, reload, screenshot AGAIN until the render is genuinely correct. The framing that matters: ok:true means the NAVIGATION worked and says NOTHING about whether the page painted. Wording escalates when the URL looks like the caller's own work in progress (localhost, LAN IP, file://, .adom.cloud, .local; classifier unit-tested 7/7), which is the lazy-AI case John described. Success responses only; never overwrites a handler that already spoke about verification. Also teaches ship.sh AD 1.9.180's caller-identity contract (ADOM_AI_THREAD + per-call reason on gated verbs).
John Lauer · 75582ec · 17d ago
Make pup insist the AI LOOKS at what it just rendered (John's ask): browser_open_window / open_tab / navigate / reload now return a _verifyRender instruction with the exact browser_screenshot command, a checklist of what to look for (blank page, unstyled HTML, error overlay, missing images, broken layout, Cannot GET, wrong build), and the ralph-test loop (fix, reload, screenshot AGAIN). ok:true only proves the navigation worked, never that the page painted. Wording escalates when the URL looks like the caller's own work in progress (localhost, LAN IP, file://, .adom.cloud, .local — classifier unit-tested 7/7). Also teaches ship.sh AD 1.9.180's caller-identity contract (ADOM_AI_THREAD) plus a per-call reason on the gated verbs.
John Lauer · 90ae7a4 · 17d ago
Make pup insist the AI LOOKS at what it just rendered (John's ask). The common failure: an AI generates or edits an app, opens it in pup, sees ok:true, and reports success to the user without ever screenshotting the result — but ok:true only means the NAVIGATION worked, it says nothing about whether the page painted, whether CSS loaded, or whether a stack trace is filling the viewport. browser_open_window / browser_open_tab / browser_navigate / browser_reload now return a _verifyRender instruction with the exact browser_screenshot command, a concrete checklist of what to look for (blank page, unstyled HTML, error overlay, missing images, broken layout, Cannot GET, wrong build), and the ralph-test loop: fix, reload, screenshot AGAIN until the render is genuinely correct. Wording escalates when the URL looks like the caller's own work in progress (localhost, a LAN IP, file://, .adom.cloud, .local — classifier unit-tested 7/7), which is exactly the case John described. Success responses only; never overwrites a handler that already spoke about verification.
John Lauer · 49513d4 · 17d ago
CRITICAL delivery fix found while testing the bug-report invitation: anything sendJSON attached to the OUTER response envelope was DROPPED on every SUCCESSFUL call. The conventional success shape is {success:true, output:'<json string>'} and AD/the CLI unwrap output into the top level, discarding the rest of the envelope — measured: a browser_navigate success returned {durationMs, ok, sessionId, status, tabId, url} with NO _hint, _next, related, pitfalls or _reportIssues, even though sendJSON had set them. Failures survived only because their handlers write those fields on the outer object. So the canonical VERB_META hints — the SDK's whole 'every response teaches the caller' principle — were reaching callers only on failure, exactly backwards. sendJSON now merges the advisory fields INSIDE output when output is a JSON object string, never overwriting what a handler already set there.
John Lauer · 237229a · 17d ago
Third attempt at the once-per-process bug-report invitation, this time with the actual cause. Machine traffic was eating it at TWO layers, each failing silently: AD's /health and /status probes flow through the same sendJSON chokepoint (fixed in 1.9.96 by requiring a verb), and AD ALSO calls pup's declared statusVerb (browser_readiness) through /command on spawn, so it arrived as a real verb and consumed the invite anyway. The orientation invite now fires on the first SUBSTANTIVE verb (an open/drive — the moment John described, 'when typical verbs are being invoked like open browser'), while read-only probes and enumerations neither consume nor carry it. A FAILURE still always carries the invitation regardless of verb, because that is when the evidence exists.
John Lauer · abbeeed · 17d ago
Dev skill: the bug-report invitation design (why we ask, and the throttle), plus the general trap that a response chokepoint carries machine probes too — AD's /health poll silently consumed the once-per-process invite, so anything counted at a shared response path must be scoped to real caller traffic.
John Lauer · d3cbee9 · 17d ago
Fix the once-per-process bug-report invitation never reaching an AI: AD probes /health (and /status for the bridge chip) every ~15s and those replies flow through the same sendJSON chokepoint, so the first health probe after a spawn consumed the invitation and the first real verb carried nothing (measured after a restart). The invite is now VERB-SCOPED — it only counts responses that belong to an actual AI-facing command (res._adomCommand), so a machine-facing probe can neither consume the orientation invite nor advance the periodic counter.
John Lauer · 5912ae6 · 17d ago
Ask the AI to report bugs, in the response it actually reads (John's ask). pup now attaches a _reportIssues invitation naming its own wiki repo (adom/adom-desktop-puppeteer-bridge) with the exact adom-wiki issue list/create commands and what evidence to include. Deliberately throttled so it is signal, not noise: ALWAYS on a failure (the moment a bug is most likely and the evidence is still in hand), ONCE per bridge process on the first verb (orientation before anything breaks), and every 40th call after that. It also points AD-core problems at adom/adom-desktop instead, so reports land on the repo that owns the code. Injected at the sendJSON chokepoint so all 155 response sites are covered, and never overrides a hint a handler already set. Opt out with browser_configure {reportIssues:'off'}.
John Lauer · c2f92d2 · 17d ago
Fix issue #22 Finding 4 (AdityaAngajala): a stalled background Chrome-for-Testing prewarm blocked EVERY browser_open_window on a machine that had system Chrome AND Edge, while browser_readiness simultaneously reported browserSource:'system' with a valid chrome.exe. Two defects, both mine from the native-first change: (1) getOrLaunchBrowser still kicked the retired v1.8.71 'converge this box to CfT' background prewarm on a native launch — I removed that same kick from chrome.warmup() in v1.9.90 and missed this one, so a native launch still started a ~150 MB download nobody asked for. Removed; native-first fetches CfT only as the genuine last resort. (2) chrome.readiness() computed ready = found && !installing, conflating 'a background download is in flight' with 'nothing is drivable' — so an in-flight or STALLED last-resort download made the whole subsystem not-ready and the open gate refused on !rd.ready. ready now means only 'a drivable browser exists'; installing stays a separate informational field and never gates drivability.
John Lauer · 1cb633a · 17d ago
Scrub internal hostnames (adom/wiki#77): legacy wiki links -> wiki.adom.inc, personal hosts -> placeholder
Colby Knox · 21be85e · 18d ago
Sync the pkg artifacts to the released line: adopt Kyle's mac-accurate SKILL.md and the install.sh slug fix (installs as 'pup', matching the frontmatter name, and removes the pre-1.9.86 mis-slugged copy), and un-stale page.json (was pinned at 1.9.74 while releases ran to 1.9.93; dropped the snapshot updated_at the publish linter flags).
John Lauer · 775afb7 · 18d ago
Publish 1.9.93
John Lauer · 6028d47 · 18d ago
Jump-list blip: stop the wiki auth-state churn that repeatedly destroyed and recreated the taskbar button. Every auth flip re-stamps the window identity, which mints a new AUMID, which destroys+recreates the taskbar button (documented Win11 behavior) — and a button destroyed under an open right-click flyout is exactly the reported 'menu shows ~300ms then disappears, second click works' bug. Two causes fixed: (1) checkWikiAuth collapsed a real logged-out answer, a non-ok response, and a THROWN probe (page mid-navigation, frame detached) all into authed:false, so the state flip-flopped authed->transient-failure->authed and re-stamped on every bounce; it now reports unknown:true when it could not determine, and every caller forwards that so an indeterminate probe changes nothing. (2) setWikiAuthedState now applies a 15s flip cooldown: the state is still recorded but the expensive, button-destroying re-stamp is suppressed, so rapid churn can never recreate the button repeatedly.
John Lauer · 46f698b · 18d ago
Dev skill: capture the teardown/sweep doctrine (the freeze bug), resolver purity (the session-map purge), multi-maintainer repo safety (last-push-wins + the three gates), and the release-vs-pkg trap. All four are generalizable engineering lessons, not changelog.
John Lauer · 3d92eb5 · 18d ago
Fix issue #16's residual: browser_list_windows reporting 0 windows while the windows are open and drivable by sessionId. Root cause: getActiveSession() was a RESOLVER that silently PURGED the session map — it deleted every session whose isSessionAlive() was false, with no _lostBrowser guard (unlike resolveSession, which deliberately keeps disconnected entries for rescan). And isSessionAlive() consulted ONLY the browsers map, so the instant handleBrowserDisconnect deleted that entry on a CDP blip, every session on the profile read as dead. Net effect: one call after a transient disconnect wiped the ENTIRE session map, destroying the exact entries the disconnect handler had just preserved for recovery. Fixes: (1) getActiveSession is now non-destructive — it marks _lostBrowser instead of deleting; removal belongs to the close/rescan paths. (2) isSessionAlive falls back to asking the session's own page whether its browser is still connected, so a drivable session can never report as not-alive. (3) Hardened the v1.9.89 orphan reap with the same lesson: it now REFUSES to sweep when the session map is empty while session files still exist on disk (recovery pending), so it can never mistake the user's live windows for orphans.
John Lauer · 7a20206 · 18d ago