← Commit history

SDK: skillpack convention (supersedes dev-skills/*.md); detect.installVerb + hostAppOptionalVerbs; key-send routing via desktop_press_key; skill_count clarified

John Lauer ·a03f913c55 ·4mo ago ·parent 12660dd
2 files changed +46−32
README.md+23−16
@@ -73,7 +73,7 @@ When a maintainer says *"audit your code, skills, README, and wiki page against - [ ] Triggers stay in YOUR niche — you don't poach a sibling's (login/forms → native-browser, not pup). `discovery_pitch` is an INSTRUCTION.  **Skills & docs** (what the container + humans read):-- [ ] You ship the publish/dev/user **3-skill set**; only the USER skill is named `SKILL.md` (dev/publish are `dev-skills/*.md`, source-only). *(→ The SKILL SET)*+- [ ] You ship the publish/dev/user **3-skill set** in the SKILLPACK layout: EVERY skill (user + dev + publish) is a real `skills/<name>/SKILL.md` with a `Parent skill:` first body line; dev/publish are scoped by `user-invocable: false` + a DEVELOPER-only description (NOT by hiding them as `dev-skills/*.md` — that convention is dead); every path listed EXPLICITLY (no globs) in `files[]` + install.sh/uninstall.sh. *(→ Artifact 2 + The SKILL SET)* - [ ] Your USER skill leads with the cold-start "read before you panic" section + the 8 conventions, and points the AI at `bridge_readiness`. *(→ USER-skill conventions)* - [ ] README + wiki page + skills all AGREE with the above (no stale github links, no wrong schema, triggers vetted). @@ -154,24 +154,29 @@ This is the code AD streams onto the user's machine. Two files on your page:  Your runtime runs on the user's DESKTOP; the AI driving it runs in a cloud/WSL2 CONTAINER. That container needs your **consumer SKILL.md** locally to know your verbs. Ship it as its own **`adom-wiki pkg`** (skills only, NO binaries): +**Layout = the wiki SKILLPACK convention** (reference: `adom/adom-wiki-skillpack`; supersedes the old "hide dev docs in `dev-skills/*.md`" guidance — pup migrated 2026-07-03):++- **EVERY skill — user, dev, AND publish — is a real `skills/<name>/SKILL.md`.** Nothing is scoped by hiding files. A ROOT `SKILL.md` (required by the registry) is the pack entry point: `user-invocable: true`, a `description` full of trigger words.+- **Each sub-skill's body opens with a `Parent skill:` line** (first line after the frontmatter): `Parent skill: **adom-desktop-<bridge>-bridge**`.+- **Dev/publish skills are scoped by AUDIENCE, not by filename:** frontmatter `user-invocable: false` + a description that opens DEVELOPER-only (e.g. "DEVELOPER skill for maintainers of this bridge — not for driving it"). Everyday users never get them offered; maintainers still install them.+- **List every skill path EXPLICITLY — no globs — in `package.json` `files[]` AND `install.sh`/`uninstall.sh`** (one `install_skill <dest> <src>` line each, kept in sync). The publish linter REQUIRES explicit listing; the skillpack's own install.sh says so. (The old "use `skills/**`" advice is dead.)+ ```bash-# Stage dir: a ROOT SKILL.md (required) + USER skills under skills/<slug>/SKILL.md, and-# package.json {name:"adom-desktop-<bridge>-bridge", version, discovery_triggers, files:[...]}.-# THREE traps that bite — verify each with `tar tzf` before publishing:-#  1. ⚠ The wiki indexes EVERY file named SKILL.md in the tarball as an INSTALLABLE,-#     Skills-tab-listed USER skill (it counts them as skill_count). So your DEV + PUBLISH-#     skills must NOT be named SKILL.md — put them in dev-skills/*.md, source-only — else-#     every user who installs your pkg also installs your dev/publish docs.-#  2. ⚠ pkg pack/publish HONORS the stage dir's .gitignore AND the package.json `files`-#     allowlist needs the GLOB: a bare "skills" entry ships ZERO skill files — use "skills/**".-#     (Set .gitignore aside across pack+publish, then restore.)-#  3. ⚠ Keep the tarball LEAN — NO release zip, NO src/ tree, NO hero PNGs (it was 16 MB+# Stage dir: ROOT SKILL.md + skills/<name>/SKILL.md per skill (user + dev + publish),+# package.json {name:"adom-desktop-<bridge>-bridge", version, discovery_triggers,+#               files:[ every path, explicitly ], scripts:{install,uninstall}}.+# TWO traps that still bite — verify each with `tar tzf` before publishing:+#  1. ⚠ pkg pack/publish HONORS the stage dir's .gitignore — a gitignored skills/ ships+#     a 3 MB tarball with ZERO skills. Set .gitignore aside across pack+publish, restore after.+#  2. ⚠ Keep the tarball LEAN — NO release zip, NO src/ tree, NO hero PNGs (it was 16 MB #     before guards). Skills + docs only.-adom-wiki pkg pack                       # then: tar tzf <tgz> → every USER SKILL.md present,-                                         #   ZERO binaries, ZERO dev/publish SKILL.md+adom-wiki pkg pack                       # then: tar tzf <tgz> → every skills/<name>/SKILL.md+                                         #   listed in files[] present, ZERO binaries adom-wiki pkg publish --org adom         # publishes adom/adom-desktop-<bridge>-bridge ``` +**What `skill_count` on your page actually shows** (measured 2026-07-03): pup — a `type:app` page whose PKG ships 3 `SKILL.md`s — shows `skill_count: 3` (correct by design: it counts the skills your published PKG carries). But the reference `adom-wiki-skillpack` — `type:skill`, 15 `SKILL.md`s in its repo — shows `skill_count: 0`, so the metric is NOT "SKILL.md files in the repo" and looks inconsistent across page types. Treat your own pkg's count as the meaningful one; don't chase parity with skill-type pages (wiki-side question, flagged).+ A container gets it **without anyone asking**: - `bridge_install` returns `skillPkg` + `installSkill` (AD derives `adom/<slug>` from your `docs`) and the `_hint` tells the AI to run it. - **`adom-desktop sync_skills`** installs every connected desktop's bridge skillPkgs (the CLI also runs it once/day in the background), so a container that connects a week later self-heals your skill.@@ -294,7 +299,7 @@ Don't cram everything into one file. Ship **three kinds** of skill, each with a 2. **A DEV skill** (for whoever edits the bridge): architecture, the verb contract, how to test locally, the boundary with AD — and, front and center, **the rich-hints-in-output rule**: *the AI never reads this file; it reads your verb OUTPUT, so every verb must return `_hint`/`_next`/`related`/`pitfalls`.* Make that the loudest thing in the dev skill. 3. **USER skill(s)** (shipped in your pkg → the container): how a cloud AI drives your verbs to get real work done. **If the verb surface is large, split it:** a small **core USER skill** (the 80% workflow + a pointer to the sub-skills) plus **sub-skills** by area (e.g. `…-recording`, `…-electronics`, `…-aps-search`). A 2,000-line monolith won't get read; a tight core skill that names the sub-skills will. (Pup ships exactly this shape: a core bridge skill + sub-skills.) -Publish the PUBLISH + DEV skills on your page for your thread; ship the USER skills in your **pkg** so containers get them. **Critical naming rule:** only USER skills may be named `SKILL.md` — the wiki indexes every `SKILL.md` in your tarball as an installable user skill, so name your DEV/PUBLISH docs `dev-skills/*.md` (source-only) or every user installs them (Artifact 2, trap #1).+Ship ALL of them — user + dev + publish — in your **pkg**, each as a real `skills/<name>/SKILL.md` (the SKILLPACK layout, Artifact 2). **Scoping is by AUDIENCE, not filename:** dev/publish skills carry `user-invocable: false` + a description that opens DEVELOPER-only, so everyday users are never offered them while your maintainer thread still installs the full set. (The old "name dev docs `dev-skills/*.md` so they don't ship" rule is DEAD — pup migrated to the skillpack layout 2026-07-03 and its `skill_count: 3` is by design.)  **Start from the templates — don't write these from scratch.** `skills/bridge-templates/` in the AD repo has a fill-in-the-blanks file for each of the three skill kinds, generalized from pup's battle-tested set: **`bridge-dev-template.md`** (architecture + the rich-hints rule), **`bridge-publish-template.md`** (the whole release/pkg/discovery dance + every trap), **`bridge-user-skill-template.md`** (the consumer skill, already encoding all eight conventions below). Copy the one you need, swap `<bridge>`/`<prefix>` for your names, delete what doesn't apply. @@ -321,6 +326,8 @@ These eight patterns are what make a cloud AI actually succeed with your bridge - **Request:** AD POSTs `{ "command":"<verb>", "args":{…} }` to your port. **Response:** JSON with at least `success` (bool); human/AI output in `output`, errors in `error` (+ an `errorCode` for machine-actionable failures). AD relays everything else verbatim — so ALWAYS add `_hint`/`_next`/`related`/`pitfalls`. - **Long-running verbs:** return promptly with a job id + set `statusVerb`; the caller polls instead of blocking. On a timeout AD auto-returns `{stillRunning:true, statusVerb, timeoutSeconds}`. - **`<prefix>describe`:** return your full verb catalog (`{verbs:[{name,summary,input,output,timeoutSeconds,statusVerb,longRunning,example,hint,related,pitfalls}]}`). AD caches it (`~/.adom/bridge-verbs/<name>.json`) and shows it in the GUI Verbs tab — but remember, `describe` is read rarely; the per-call hints are what carry the AI.+- **Keyboard input: route through AD's `desktop_press_key` — do NOT reimplement chords.** AD's key verb already does full modifier chords (`"shift+s"`, `"ctrl+shift+p"`, `"alt+f4"` — modifiers held via SendInput, key tapped, modifiers released in reverse), foregrounds the target window first (`{window|titleContains|hwnd}`) so CEF/Qt apps like Fusion receive it, and every bridge inherits it via the `/command` desktop passthrough (`{"command":"press_key", ...}` on the desktop namespace). A bridge-local `*_send_key` that parses only single keys (the Fusion bridge's `fusion_send_key` circa v1.6.x — `"shift+s"` → "Unknown key") duplicates AD's work and drifts; keep such a verb only for SendMessage-to-exact-hwnd cases AD's focus-first model can't cover, and say so in its `describe`.+- **Host-app-optional verbs (v1.9.76):** declare `detect.hostAppOptionalVerbs` (bare names, e.g. `["readiness","describe"]`) in `bridge.json` so AD forwards those verbs to your running bridge even when your host app is absent — AD's built-in read-only set {readiness, describe, get_app_state, status} is always forwarded. And declare **`detect.installVerb`** (e.g. `"kicad_upgrade"`) so `bridge_readiness` recommends YOUR installer over the generic winget fallback.  ## Health + status chip @@ -341,4 +348,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, 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`).+**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 **— or when THIS SDK doc itself changes —** AD posts a migration notice to **each** of their wiki discussions (`adom-desktop-{kicad,fusion,blender,puppeteer}-bridge` + `adom-browser-extension`). **Author-facing takeaway: watch your bridge's own wiki DISCUSSION/issues list — that's where an "SDK changed, please re-audit against the billboard" notice lands, and where you reply with your plan or blockers.** It's the only channel AD uses to reach you; AD never edits your repo.
SKILL.md+23−16
@@ -73,7 +73,7 @@ When a maintainer says *"audit your code, skills, README, and wiki page against - [ ] Triggers stay in YOUR niche — you don't poach a sibling's (login/forms → native-browser, not pup). `discovery_pitch` is an INSTRUCTION.  **Skills & docs** (what the container + humans read):-- [ ] You ship the publish/dev/user **3-skill set**; only the USER skill is named `SKILL.md` (dev/publish are `dev-skills/*.md`, source-only). *(→ The SKILL SET)*+- [ ] You ship the publish/dev/user **3-skill set** in the SKILLPACK layout: EVERY skill (user + dev + publish) is a real `skills/<name>/SKILL.md` with a `Parent skill:` first body line; dev/publish are scoped by `user-invocable: false` + a DEVELOPER-only description (NOT by hiding them as `dev-skills/*.md` — that convention is dead); every path listed EXPLICITLY (no globs) in `files[]` + install.sh/uninstall.sh. *(→ Artifact 2 + The SKILL SET)* - [ ] Your USER skill leads with the cold-start "read before you panic" section + the 8 conventions, and points the AI at `bridge_readiness`. *(→ USER-skill conventions)* - [ ] README + wiki page + skills all AGREE with the above (no stale github links, no wrong schema, triggers vetted). @@ -154,24 +154,29 @@ This is the code AD streams onto the user's machine. Two files on your page:  Your runtime runs on the user's DESKTOP; the AI driving it runs in a cloud/WSL2 CONTAINER. That container needs your **consumer SKILL.md** locally to know your verbs. Ship it as its own **`adom-wiki pkg`** (skills only, NO binaries): +**Layout = the wiki SKILLPACK convention** (reference: `adom/adom-wiki-skillpack`; supersedes the old "hide dev docs in `dev-skills/*.md`" guidance — pup migrated 2026-07-03):++- **EVERY skill — user, dev, AND publish — is a real `skills/<name>/SKILL.md`.** Nothing is scoped by hiding files. A ROOT `SKILL.md` (required by the registry) is the pack entry point: `user-invocable: true`, a `description` full of trigger words.+- **Each sub-skill's body opens with a `Parent skill:` line** (first line after the frontmatter): `Parent skill: **adom-desktop-<bridge>-bridge**`.+- **Dev/publish skills are scoped by AUDIENCE, not by filename:** frontmatter `user-invocable: false` + a description that opens DEVELOPER-only (e.g. "DEVELOPER skill for maintainers of this bridge — not for driving it"). Everyday users never get them offered; maintainers still install them.+- **List every skill path EXPLICITLY — no globs — in `package.json` `files[]` AND `install.sh`/`uninstall.sh`** (one `install_skill <dest> <src>` line each, kept in sync). The publish linter REQUIRES explicit listing; the skillpack's own install.sh says so. (The old "use `skills/**`" advice is dead.)+ ```bash-# Stage dir: a ROOT SKILL.md (required) + USER skills under skills/<slug>/SKILL.md, and-# package.json {name:"adom-desktop-<bridge>-bridge", version, discovery_triggers, files:[...]}.-# THREE traps that bite — verify each with `tar tzf` before publishing:-#  1. ⚠ The wiki indexes EVERY file named SKILL.md in the tarball as an INSTALLABLE,-#     Skills-tab-listed USER skill (it counts them as skill_count). So your DEV + PUBLISH-#     skills must NOT be named SKILL.md — put them in dev-skills/*.md, source-only — else-#     every user who installs your pkg also installs your dev/publish docs.-#  2. ⚠ pkg pack/publish HONORS the stage dir's .gitignore AND the package.json `files`-#     allowlist needs the GLOB: a bare "skills" entry ships ZERO skill files — use "skills/**".-#     (Set .gitignore aside across pack+publish, then restore.)-#  3. ⚠ Keep the tarball LEAN — NO release zip, NO src/ tree, NO hero PNGs (it was 16 MB+# Stage dir: ROOT SKILL.md + skills/<name>/SKILL.md per skill (user + dev + publish),+# package.json {name:"adom-desktop-<bridge>-bridge", version, discovery_triggers,+#               files:[ every path, explicitly ], scripts:{install,uninstall}}.+# TWO traps that still bite — verify each with `tar tzf` before publishing:+#  1. ⚠ pkg pack/publish HONORS the stage dir's .gitignore — a gitignored skills/ ships+#     a 3 MB tarball with ZERO skills. Set .gitignore aside across pack+publish, restore after.+#  2. ⚠ Keep the tarball LEAN — NO release zip, NO src/ tree, NO hero PNGs (it was 16 MB #     before guards). Skills + docs only.-adom-wiki pkg pack                       # then: tar tzf <tgz> → every USER SKILL.md present,-                                         #   ZERO binaries, ZERO dev/publish SKILL.md+adom-wiki pkg pack                       # then: tar tzf <tgz> → every skills/<name>/SKILL.md+                                         #   listed in files[] present, ZERO binaries adom-wiki pkg publish --org adom         # publishes adom/adom-desktop-<bridge>-bridge ``` +**What `skill_count` on your page actually shows** (measured 2026-07-03): pup — a `type:app` page whose PKG ships 3 `SKILL.md`s — shows `skill_count: 3` (correct by design: it counts the skills your published PKG carries). But the reference `adom-wiki-skillpack` — `type:skill`, 15 `SKILL.md`s in its repo — shows `skill_count: 0`, so the metric is NOT "SKILL.md files in the repo" and looks inconsistent across page types. Treat your own pkg's count as the meaningful one; don't chase parity with skill-type pages (wiki-side question, flagged).+ A container gets it **without anyone asking**: - `bridge_install` returns `skillPkg` + `installSkill` (AD derives `adom/<slug>` from your `docs`) and the `_hint` tells the AI to run it. - **`adom-desktop sync_skills`** installs every connected desktop's bridge skillPkgs (the CLI also runs it once/day in the background), so a container that connects a week later self-heals your skill.@@ -294,7 +299,7 @@ Don't cram everything into one file. Ship **three kinds** of skill, each with a 2. **A DEV skill** (for whoever edits the bridge): architecture, the verb contract, how to test locally, the boundary with AD — and, front and center, **the rich-hints-in-output rule**: *the AI never reads this file; it reads your verb OUTPUT, so every verb must return `_hint`/`_next`/`related`/`pitfalls`.* Make that the loudest thing in the dev skill. 3. **USER skill(s)** (shipped in your pkg → the container): how a cloud AI drives your verbs to get real work done. **If the verb surface is large, split it:** a small **core USER skill** (the 80% workflow + a pointer to the sub-skills) plus **sub-skills** by area (e.g. `…-recording`, `…-electronics`, `…-aps-search`). A 2,000-line monolith won't get read; a tight core skill that names the sub-skills will. (Pup ships exactly this shape: a core bridge skill + sub-skills.) -Publish the PUBLISH + DEV skills on your page for your thread; ship the USER skills in your **pkg** so containers get them. **Critical naming rule:** only USER skills may be named `SKILL.md` — the wiki indexes every `SKILL.md` in your tarball as an installable user skill, so name your DEV/PUBLISH docs `dev-skills/*.md` (source-only) or every user installs them (Artifact 2, trap #1).+Ship ALL of them — user + dev + publish — in your **pkg**, each as a real `skills/<name>/SKILL.md` (the SKILLPACK layout, Artifact 2). **Scoping is by AUDIENCE, not filename:** dev/publish skills carry `user-invocable: false` + a description that opens DEVELOPER-only, so everyday users are never offered them while your maintainer thread still installs the full set. (The old "name dev docs `dev-skills/*.md` so they don't ship" rule is DEAD — pup migrated to the skillpack layout 2026-07-03 and its `skill_count: 3` is by design.)  **Start from the templates — don't write these from scratch.** `skills/bridge-templates/` in the AD repo has a fill-in-the-blanks file for each of the three skill kinds, generalized from pup's battle-tested set: **`bridge-dev-template.md`** (architecture + the rich-hints rule), **`bridge-publish-template.md`** (the whole release/pkg/discovery dance + every trap), **`bridge-user-skill-template.md`** (the consumer skill, already encoding all eight conventions below). Copy the one you need, swap `<bridge>`/`<prefix>` for your names, delete what doesn't apply. @@ -321,6 +326,8 @@ These eight patterns are what make a cloud AI actually succeed with your bridge - **Request:** AD POSTs `{ "command":"<verb>", "args":{…} }` to your port. **Response:** JSON with at least `success` (bool); human/AI output in `output`, errors in `error` (+ an `errorCode` for machine-actionable failures). AD relays everything else verbatim — so ALWAYS add `_hint`/`_next`/`related`/`pitfalls`. - **Long-running verbs:** return promptly with a job id + set `statusVerb`; the caller polls instead of blocking. On a timeout AD auto-returns `{stillRunning:true, statusVerb, timeoutSeconds}`. - **`<prefix>describe`:** return your full verb catalog (`{verbs:[{name,summary,input,output,timeoutSeconds,statusVerb,longRunning,example,hint,related,pitfalls}]}`). AD caches it (`~/.adom/bridge-verbs/<name>.json`) and shows it in the GUI Verbs tab — but remember, `describe` is read rarely; the per-call hints are what carry the AI.+- **Keyboard input: route through AD's `desktop_press_key` — do NOT reimplement chords.** AD's key verb already does full modifier chords (`"shift+s"`, `"ctrl+shift+p"`, `"alt+f4"` — modifiers held via SendInput, key tapped, modifiers released in reverse), foregrounds the target window first (`{window|titleContains|hwnd}`) so CEF/Qt apps like Fusion receive it, and every bridge inherits it via the `/command` desktop passthrough (`{"command":"press_key", ...}` on the desktop namespace). A bridge-local `*_send_key` that parses only single keys (the Fusion bridge's `fusion_send_key` circa v1.6.x — `"shift+s"` → "Unknown key") duplicates AD's work and drifts; keep such a verb only for SendMessage-to-exact-hwnd cases AD's focus-first model can't cover, and say so in its `describe`.+- **Host-app-optional verbs (v1.9.76):** declare `detect.hostAppOptionalVerbs` (bare names, e.g. `["readiness","describe"]`) in `bridge.json` so AD forwards those verbs to your running bridge even when your host app is absent — AD's built-in read-only set {readiness, describe, get_app_state, status} is always forwarded. And declare **`detect.installVerb`** (e.g. `"kicad_upgrade"`) so `bridge_readiness` recommends YOUR installer over the generic winget fallback.  ## Health + status chip @@ -341,4 +348,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, 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`).+**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 **— or when THIS SDK doc itself changes —** AD posts a migration notice to **each** of their wiki discussions (`adom-desktop-{kicad,fusion,blender,puppeteer}-bridge` + `adom-browser-extension`). **Author-facing takeaway: watch your bridge's own wiki DISCUSSION/issues list — that's where an "SDK changed, please re-audit against the billboard" notice lands, and where you reply with your plan or blockers.** It's the only channel AD uses to reach you; AD never edits your repo.