CLAUDE.md — adom-desktop-puppeteer-bridge (READ THIS, it is YOUR project)

This repo is the Adom Desktop Puppeteer ("pup") bridge — the canonical source of truth, published to wiki.adom.inc/adom/adom-desktop-puppeteer-bridge. If you are an Adom AI touching anything pup / browser_* / Chrome-for-Testing, you own and maintain this code here. Adom Desktop (AD) ships a bundled SEED of this bridge for first-run/offline, but the live code is THIS repo and AD auto-pulls it via the updateManifestUrl in bridge.json. (Extracted from adom-desktop/plugins/puppeteer on 2026-06-29, mirroring the kicad/fusion cloud-owned model.)

You vs adom-desktop (AD) core — the boundary

  • AD core owns: the adom-desktop CLI, the relay / /command passthrough (relays your response VERBATIM incl. _hint/errorCode/statusVerb), bridge lifecycle (bridge_install / streaming this bridge into …\bridges-cache\puppeteer, the stable port, supervisor), desktop_install_node, and the node_not_found gate that fires BEFORE this bridge can spawn. AD also runs npm install in the bridge dir on spawn (this bridge ships source-only; node_modules is reconstructed there + present in the seed).
  • YOU (this bridge) own: every browser_* / desktop_record_* verb + its response _hints, the Chrome-for-Testing self-heal (src/chrome.js — detect / auto-install / readiness), the status-chip fields on /status, the browser_describe catalog, the pup SKILL.md (+ the source-only maintainer skills in dev-skills//publish-skills/), and the edit → publish → reinstall loop.
  • So: a browser_* verb misbehaves, a hint is missing, Chrome-for-Testing won't install, the chip lies → it's your code, fix it here and republish. It is NOT an adom-desktop request. If a GENERIC AD capability is missing (a new lifecycle verb, calling browser_prewarm on embedded first-run), file that against AD — don't re-absorb the bridge.

Map of what you manage (src/ = the runnable bridge, zipped to the cache)

  • src/server.js — the bridge HTTP server / verb router. Cold-start gate in browser_open_window; /status + /health (led/summary/tooltip chip); browser_readiness + browser_prewarm verbs.
  • src/chrome.js — Chrome-for-Testing self-heal. detect (validates the real exe), install (programmatic via the bundled @puppeteer/browsers, pinned to puppeteer's expected buildId), the install-state singleton, ensureChromeReady (the gate), readiness (powers the verb + chip).
  • src/credential_vault.js — keychain-backed HTTP-Basic creds for vendor portals.
  • src/bridge.json + src/BRIDGE_VERSION — the manifest/version (KEEP IN LOCKSTEP).
  • src/package.json / package-lock.json — the NODE deps (puppeteer, sharp, keytar). node_modules is gitignored; AD npm installs it on spawn and the bundled seed ships it.
  • src/recorder.html / welcome.html / icons — recorder UI + assets.
  • adom-bridge-puppeteer-manifest.json (repo root) — the streaming manifest AD's updateManifestUrl points at; its url is the RELEASE download URL of the zip, with matching sha256/size.
  • SKILL.md (root) — the ONLY skill the pkg ships (pup), installed into ~/.claude/skills/ (via install.sh / adom-wiki pkg). The cold-start playbook lives here. The maintainer skills (dev-skills/pup-bridge-dev, publish-skills/pup-bridge-publish) are SOURCE-ONLY — per the Bridge SDK a pkg ships only user skills, so they stay in the repo, out of files[] (open-vs-closed doesn't matter).
  • package.json (root, skillpack) — declares dependencies:{ "adom/adom-desktop": "^1.9.x" } so pkg install pulls the AD CLI + core skills. SERVER npm deps live ONLY in the Release zip's src/package.json.

The publish/reinstall loop

See PUBLISHING.md for the full recipe. Short form: edit src/ → bump src/BRIDGE_VERSION + src/bridge.json together → build adom-bridge-puppeteer-v<ver>.zip from src/ (zip-root, no top dir) → adom-wiki release upload the zip → point adom-bridge-puppeteer-manifest.json at that release URL (with the zip's real sha256/size) → adom-wiki repo push the manifest + changed source + SKILL.md → adom-desktop bridge_install {"manifestUrl": ".../files/adom-bridge-puppeteer-manifest.json","force":true} to test → verify in pup. Wiki = canonical.

ALWAYS show wiki changes in pup (standing rule from John): after ANY publish/edit to this wiki page (release, repo push, pkg, page.json), refresh the LIVE page in a pup window the user can see (cache-bust with ?v=<ver>), screenshot it, and surface the link — never just say "published." Reuse one window (sessionId: cft or pup-wiki) instead of spawning new ones; keep test windows open.

Hard rules

  • The .zip is a RELEASE asset, never a git file. *.zip is gitignored and repo push --files X.zip silently skips it. Only the small manifest JSON goes in the git repo, pointing at the release.
  • sha256/size in the manifest MUST match the served release asset or bridge_install rejects it.
  • Never hand-edit the bridges-cache or the bundled seed. They get clobbered. Edit src/, publish.
  • Source-only zip. Do NOT zip node_modules (88 MB, wiki limits, native builds) — AD reconstructs it.
  • Pup is AD-owned-ish but cloud-managed from here now. Don't republish it from the adom-desktop repo.