# 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 `_hint`s, 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 install`s 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.
