← Commit history

Upload 1 file(s)

John Lauer ·3f9484008e ·4mo ago ·parent a4aa399
1 file changed +29−2
README.md+29−2
@@ -1,3 +1,7 @@+---+name: adom-desktop-bridge-sdk+description: Author, PUBLISH, and make-discoverable an adom-desktop bridge — a small local server that adds a namespace of verbs (kicad_, fusion_, browser_, your_prefix_) to adom-desktop. Use when building, publishing, updating, prewarming, or debugging a bridge, or deciding what skills to ship. Covers the AD-core-vs-author boundary; the #1 rule (rich hints in EVERY verb's OUTPUT, because the AI reads CLI output, never your on-disk skill); bridge.json; the THREE things you publish (runtime Release zip + manifest, container skills pkg, wiki discovery_triggers); prewarm; the publish/dev/user SKILL set you must ship; and the auto-discover → install-check → use flow.+---  # Bridge SDK — build, publish, and surface a bridge for Adom Desktop @@ -25,6 +29,24 @@ If a *bridge verb* misbehaves → fix the bridge. If a *generic AD capability* i  --- +## Runtime contract — AD provisions Node/Python; you bind loopback (v1.9.63 / v1.9.69)++**The single most important change for a Node or Python bridge.** As of AD **v1.9.63** you no longer bootstrap your own interpreter, and you MUST bind loopback. Four rules:++1. **Don't bootstrap your own Node/Python.** AD owns a global, portable, **no-UAC** runtime under `~/.adom/adom-runtimes/`: a system install if one's on PATH, else a portable copy it downloads + prewarms in the background on first launch. AD spawns your `entrypoint` with that interpreter **by absolute path**. So **delete every `winget install node` / `desktop_install_node` / "please install Python" / self-download step** from your bridge and its skills. `spawn.kind: "node"|"python"` IS your runtime declaration — AD reads it and provisions the runtime. Anyone can check status with the **`runtimes`** verb (`state ∈ absent|installing|ready|failed`, `source ∈ system|cache`, version). AD pins the version (Node 22.11.0 / Python 3.12.13 today) — need a different major? ask the AD-core thread; don't ship your own.++2. **Bind `ADOM_BIND_HOST`, never `0.0.0.0`.** AD passes an **`ADOM_BIND_HOST`** env var (always `127.0.0.1`) to every bridge it spawns. A bare listen that defaults to `0.0.0.0` pops a **Windows Firewall "allow access?" dialog** on first run — and AD's hard guarantee to users is **no firewall prompt by default**.+   - Node: `server.listen(PORT, process.env.ADOM_BIND_HOST || '127.0.0.1', cb)`+   - Python: `HTTPServer((os.environ.get('ADOM_BIND_HOST', '127.0.0.1'), PORT), Handler)`++3. **Ship the Release zip source-only — AD installs your deps, and v1.9.69 makes it bulletproof.** A Node bridge's zip carries SOURCE only (no `node_modules`). AD reuses the bundled seed's `node_modules` via `NODE_PATH` when versions match, else runs **`npm install --include=optional`** for you with the managed runtime's own npm. **As of v1.9.69 AD puts the managed runtime's dir on the child PATH for that install AND for your spawned process** — so a dep's postinstall / `node-gyp` / `prebuild-install` that shells out to a **bare** `node`/`npm`/`npx` (puppeteer's own `node install.mjs`, `sharp`, `keytar`, `better-sqlite3`, `bcrypt`) resolves even on a machine with **no system Node**. **You do NOT add the runtime to PATH yourself** — AD guarantees it. (Python: the interpreter dir + `Scripts/` are on PATH too, so pip can build wheels.)++4. **Bundle deps in your SEED for an instant first spawn.** Source-only zip + a bundled-seed `node_modules` at the same version = AD reuses the seed via `NODE_PATH` (instant); a wiki version newer than the seed forces one cold `npm install` (now PATH-correct, but slower). Bump the seed in lockstep with each Release.++**Net:** declare `spawn.kind`, bind `ADOM_BIND_HOST`, ship source-only. AD does the rest — no UAC, no firewall prompt, no `'node' is not recognized`.++---+ ## Self-audit checklist — run this when asked to "audit against the SDK"  When a maintainer says *"audit your code, skills, README, and wiki page against the Bridge SDK,"* **this is the checklist.** Each item names its section below; fix every miss, then re-check.@@ -34,6 +56,11 @@ When a maintainer says *"audit your code, skills, README, and wiki page against - [ ] `updateManifestUrl` → YOUR page's manifest (durable auto-update); `docs` → your own page; **`homepage` is a `wiki.adom.inc` URL, NEVER `github.com`.** - [ ] `detect` declared iff you drive a HOST APP (KiCad/Fusion/Altium…); omitted if you bring your own runtime (pup). `prewarm.assets` declared for heavy downloads (e.g. `chrome-for-testing`). *(→ Cold-start tiers)* +**Runtime** (Node/Python bridges) *(→ Runtime contract)*:+- [ ] You bind **`ADOM_BIND_HOST`** (loopback default), never `0.0.0.0`.+- [ ] You do **NOT** bootstrap your own Node/Python — no `winget`/`desktop_install_node`/self-download in code or skills. `spawn.kind` is the declaration; AD provisions it.+- [ ] Release zip is **source-only** (no `node_modules`); you rely on AD's `npm install` (PATH-correct as of v1.9.69) + a lockstep bundled seed for instant spawn. You do NOT put the runtime on PATH yourself.+ **Verbs & output** (what the AI actually reads): - [ ] EVERY verb returns a rich **`_hint`** (+ `_next`/`related`/`pitfalls`). *(→ THE ONE PRINCIPLE)* - [ ] A `<prefix>_describe` verb lists your whole catalog. *(→ Verb contract)*@@ -220,7 +247,7 @@ A cold first call that pays multi-minute setup (npm install, downloading a runti  A bridge has TWO kinds of dependency, and **AD treats them OPPOSITELY.** Get this right or a first-install probe (e.g. HD's "what tools do I have") triggers a slow install at the worst moment. -**Tier 1 — your RUNTIME (Node, Python, your own browser download): AD prewarms + auto-installs it.** This is your plumbing. On first boot AD installs Node/Python in the background (winget) and prewarms heavy assets you declare. You may also download your own runtime asset (pup downloads Chrome-for-Testing) — fine, it's yours. **But do it in the BACKGROUND: a `*_status` / `*_readiness` / ANY probe verb must NEVER block on a heavy download.** Spawn your server fast (it usually doesn't need the asset to *start*), kick the download off detached, and report `state:"warming"` until ready. A synchronous-download-on-first-verb is the exact footgun this release fixed (pup's 150 MB Chrome fetch used to block the probe).+**Tier 1 — your RUNTIME (Node, Python, your own browser download): AD prewarms + auto-installs it.** This is your plumbing. On first boot AD **provisions** Node/Python in the background — a **portable, no-UAC** copy under `~/.adom/adom-runtimes/` (or a system install if one's on PATH), **NOT winget/MSI** (see **Runtime contract** above) — and prewarms heavy assets you declare. You may also download your own runtime asset (pup downloads Chrome-for-Testing) — fine, it's yours. **But do it in the BACKGROUND: a `*_status` / `*_readiness` / ANY probe verb must NEVER block on a heavy download.** Spawn your server fast (it usually doesn't need the asset to *start*), kick the download off detached, and report `state:"warming"` until ready. A synchronous-download-on-first-verb is the exact footgun this release fixed (pup's 150 MB Chrome fetch used to block the probe).  **Tier 2 — the HOST APP (KiCad, Fusion, Altium, …): AD DETECTS it by default and installs it ON REQUEST — never pre-emptively, and NEVER by telling the user to do it themselves.** Two rules that sound opposed but aren't: - **Don't install it unasked.** A multi-GB app nobody asked for is rude, so by default AD only DETECTS presence (a machine with KiCad belongs to a KiCad user; EDA users are mono-tool — a Fusion user isn't a KiCad user). AD won't prewarm/spawn your bridge while the app is absent — a resource decision, not a "go away."@@ -314,4 +341,4 @@ Your `/health` (200) makes the chip green. Optionally return `led` (`green`/`yel 5. **Re-seed AD's bundled copy** (AD-core thread, not you) — extract your Release zip over `plugins/<name>/` keeping bundled deps; ships in the next NSIS as the offline fallback. 6. **Verify** — `bridge_install {manifestUrl}` on a desktop → `bridge_list` shows your `version` + `skillPkg`; `bridge_check_updates` reaches your page; a container `sync_skills` pulls your USER skill; `discover find "<phrase>"` surfaces you with an instructional brief. -**Reference bridge = pup** (`adom/adom-desktop-puppeteer-bridge`): live `discovery_triggers`, a skills pkg with a core + sub-skills, a Release zip + manifest with `updateManifestUrl`, a bundled seed with prewarmed `node_modules`, and rich per-verb hints. Copy its shape. (`scripts/sample-bridges/hello-python` + `hello-rust` are the minimal skeletons.) KiCad/Fusion/Puppeteer are cloud-owned — don't edit them from the AD repo.+**Reference bridge = pup** (`adom/adom-desktop-puppeteer-bridge`): live `discovery_triggers`, a skills pkg with a core + sub-skills, a Release zip + manifest with `updateManifestUrl`, a bundled seed with prewarmed `node_modules`, and rich per-verb hints. Copy its shape. (`scripts/sample-bridges/hello-python` + `hello-rust` are the minimal skeletons.) KiCad, Fusion, Blender, Puppeteer, and the **native-browser** bridge (in the `adom-browser-extension` repo) are cloud-owned — don't edit them from the AD repo. When an AD release changes a bridge-facing contract, AD posts a migration notice to **each** of their wiki discussions (`adom-desktop-{kicad,fusion,blender,puppeteer}-bridge` + `adom-browser-extension`).