name: kicad-bridge-publish user-invocable: false description: DEVELOPER-only PUBLISH skill (user-invocable:false — for maintainers, never offered to everyday users). The exact recipe to ship a new version of the Adom Desktop KiCad bridge to wiki.adom.inc: version lockstep, the zip build, adom-wiki repo push + release create, the skills pkg, pushing to a target AD, and verify steps. Trigger words — publish kicad bridge, release kicad bridge, ship kicad bridge, bump kicad bridge, kicad bridge manifest, kicad bridge pkg.

kicad-bridge-publish

How to cut and publish a KiCad-bridge release. Use the adom-wiki CLI for ALL wiki interactions — never raw curl. Two independent artifacts: the RUNTIME (zip + manifest, on the page /files) and the SKILLS PKG (adom/adom-desktop-kicad-bridge, container-side docs).

1. Version lockstep (bump ALL three together)

  • bridge.json"version"
  • BRIDGE_VERSION (plain text)
  • the manifest JSON → "version"

They must match. bridge.json also carries updateManifestUrl (durable auto-update), docs (your page), homepage (a wiki.adom.inc URL, NEVER github), detect (host-app paths incl. %LocalAppData%\Programs\KiCad), verbPrefixes, complete verbs[], statusVerb.

2. Build the zip — KEEP IT TINY (it is auto-bundled into AD)

The runtime zip ships inside Adom Desktop for every user, so it carries ONLY what the bridge needs to RUN. No docs, no images, no skills, no samples. (Audited 2026-07-15: the zip had grown to 488.9 KB carrying 219 KB of hero fonts, five skills/ trees, demo scripts and READMEs — none referenced by runtime code. Slimming it to 335.7 KB was a 31% cut with zero functional change.)

KEEP (runtime-required):

  • all *.py (server + handlers/ + plugin_payload/)
  • certs/cacert.pem — AD's portable Python has no CA bundle
  • *.ps1 (launch_editor.ps1, navigate_symbol.ps1) — UIA scripts the handlers shell out to
  • templates/blank-board.kicad_pcb — read by handlers/place_footprint.py
  • bridge.json, BRIDGE_VERSION, start.bat, start.sh
  • root SKILL.md ONLY (the runtime skill adom-desktop-kicad, public: true — AD installs it)

EXCLUDE (everything else): skills/** (container-side docs — they ship in the PKG, duplicating them here is pure bloat), demo/**, docs/**, tour*/**, every *.md except root SKILL.md, every image/font (*.png *.jpg *.svg *.gif *.ttf *.otf *.woff*), every archive/video (*.zip *.tar.gz *.bundle *.mp4 — note mesa-llvmpipe-x64.zip is 22 MB and must NEVER land in the zip), __pycache__, *.pyc, .git, .github, node_modules, .DS_Store, and the generated adom-bridge-kicad-manifest.json.

Compute sha256 + byte size for the manifest. Verify before publishing: every local import resolves inside the zip, and the data files above are all present — then deploy and call kicad_describe (verb count) + one data-file-dependent verb on a real target.

Manifest fields: manifest_version:1, name:"kicad", version, url (the /blob/app/.../adom-bridge-kicad-v<ver>.zip), sha256, size, verbPrefixes:["kicad_"], healthEndpoint:"/status", released_at, hero, languages.

3. Publish the runtime (CLI)

adom-wiki repo push adom/adom-desktop-kicad-bridge \
  --files adom-bridge-kicad-v<ver>.zip adom-bridge-kicad-manifest.json bridge.json \
  -m "v<ver>: <what changed>"
adom-wiki release create adom/adom-desktop-kicad-bridge <ver> \
  --title "KiCad bridge v<ver>" --changelog "..." \
  --binary-path adom-bridge-kicad-v<ver>.zip

repo push writes the files to the page /files (same place AD's bridge_cache fetches from). release create also registers a proper Release (SDK Artifact 1). For a field with no dedicated verb use adom-wiki api -X PUT /api/v1/pages/... --body ..., not curl.

4. Publish the skills pkg (container docs)

The pkg is skills-only — it is NOT the bridge. The pkg teaches a container agent the kicad_* verbs; the release zip is what AD downloads and runs as the bridge runtime. Users conflate them constantly, so say it — but say it in ONE LINE.

⚠️ description is rendered inside the page's Install card. Keep it to one or two sentences. A paragraph there is worse than saying nothing — it buries the install command in a wall of text. (Learned the hard way 2026-07-19: a 486-char description explaining the whole two-artifact model turned the Install card into an unreadable block; John: "you're overdoing it with that install description." Cut to 145 chars.) The full explanation belongs in the README body, not the card.

Canonical description — copy this shape:

Skills for your container so your AI knows how to drive the KiCad bridge. The bridge runtime itself is the release zip — Adom Desktop loads that.

The longer version (the "Two artifacts on this page — which one do you want?" comparison table: what it is / who loads it / contains / do you install it manually, closing with "The package is not the bridge.") lives near the TOP of README.md, where there's room for it.

No images in the pkg. The README references page art by ABSOLUTE https://wiki.adom.inc/blob/app/adom-desktop-kicad-bridge/<name>.png URLs, so the PNGs render on the page without riding in the install tarball. (Audited 2026-07-15: files[] listed hero.png + arch.png + verbs.png + outcomes.png = 496 KB downloaded by every pkg install, referenced by nothing. Removing them took the tarball to 29.5 KB.) Push page art with repo push, never list it in files[]. Before publishing, stage only the declared files[] into a clean dir and pack from there — packing from the page repo sweeps up art, zips and videos.

Stage a dir with package.json (name/version/files[]), a ROOT SKILL.md, and a skills/<name>/SKILL.md for every skill. SKILLPACK convention (SDK, replaces the dead dev-skills/*.md rule): EVERY skill — user, dev, AND publish — is a real skills/<name>/SKILL.md and ships in the tarball. Dev/publish skills are scoped by AUDIENCE, not filename: frontmatter user-invocable: false + a description that opens DEVELOPER-only, so everyday users never get them offered but maintainers still install them. List every skill path EXPLICITLY (no globs) in package.json files[] AND install.sh/uninstall.sh. Then:

cd <staging> && adom-wiki pkg pack --out /tmp/v.tgz   # verify: tar lists every skills/<x>/SKILL.md, 0 binaries
adom-wiki pkg publish --org adom --skip-lint --yes     # moves dist-tag latest

The runtime SKILL.md (adom-desktop-kicad, ships in the zip) and the pkg's root SKILL.md are DIFFERENT docs — update both when a change affects users.

5. Push to a running desktop + verify

adom-desktop --target <name> refresh_bridges '{"name":"kicad"}'   # pulls new cache
adom-desktop --target <name> bridge_kill '{"name":"kicad"}'       # force fresh spawn (old instance keeps old code)
adom-desktop --target <name> bridge_check_updates '{}'            # current == latest?
adom-wiki repo show adom/adom-desktop-kicad-bridge adom-bridge-kicad-manifest.json  # served version matches?

Verify the served bridge.json (repo show ... bridge.json) has the fields you expect and the zip's sha matches. A fresh verb call after a kill returns bridge_starting — retry.

6. Refreshing the README screenshots (window tour)

The README embeds screenshots hosted on the page /files (referenced as https://wiki.adom.inc/blob/app/adom-desktop-kicad-bridge/<name>.png). Regenerate them on a real VM (e.g. ADOMBASELINE) whenever the UI/flow changes — never hand-mock them:

  1. On the VM: kicad_enable_software_opengl (if GPU-less) → open each window with sample data from tour-pack-rp2040/ (AdomRP2040 symbol, QFN-56_AdomRP2040 footprint, the breakout board).
  2. For each: kicad_dismiss_dialogs {all:true}kicad_screenshot_allpull_file the matching .bmp → PIL bmp→png, thumbnail((1400,1400)).
  3. Save into docs/img/ with the canonical names the README uses: schematic-editor.png, symbol-editor.png, footprint-editor.png, pcb-editor-2d.png, 3d-viewer.png, dialog-firstrun-wizard.png, control-surfaces.svg.
  4. adom-wiki repo push adom/adom-desktop-kicad-bridge --files docs/img/*.png ... then curl -so /dev/null -w '%{http_code}' each blob URL to confirm 200.
  5. shotlog paste <png> -c kicad-bridge -d "<caption>" to show John the live captures.

7. Showing the published page to John (pup)

pup opens windows in the BACKGROUND by default. foreground: true on browser_open_window is the ONLY thing that puts a window on his screen — maximizing, sizing, browser_alert_window (taskbar flash) and browser_raise_os_window do NOT. (2026-07-19: he asked "show me in pup" three times because the window was open, correct and maximized — but behind everything.)

  • He asked to be shown → open with foreground: true, then desktop_set_window_state maximize ONCE. (state accepts maximize|minimize|restore — there is no "foreground" state.)
  • The standing "never foreground a window he already has" rule protects windows he is using; it does not apply to a window you just opened because he asked to see something.
  • Sessions die between turns — browser_list_windows first; if the session is gone, open fresh rather than browser_navigate into a dead sessionId.
  • Never touch a session another AI thread owns (you'll see unfamiliar sessionIds like wiki-lockdemo, plate-out). Open your own.
  • Multiple pages → ONE maximized window, browser_open_tab per page, land on the important tab.
  • Then adom-shotlog inject each capture and hand him the phone URL (SHOTLOG_AD_TARGET=AdomLapper adom-shotlog open --channel <ch> when several desktops are connected).

8. Upstream: what the SDK still owes every bridge

Two issues are open on adom/adom-desktop-bridges (filed 2026-07-19) — if you hit these problems, they're known, and the fix belongs in the SDK, not just here:

  1. SDK should require every bridge to explain pkg-vs-zip (one line, on the page + in package.json.description). The SDK documents the artifacts ("Artifact 1 — the RUNTIME…") but never tells authors to explain them to users, so no page does.
  2. SDK should document artifact hygiene — the KEEP/EXCLUDE policy in §2 + the no-images-in-pkg rule in §4, ideally enforced by a bridge lint that fails on images/videos/archives in either artifact.

9. Standing rules

  • Commit source to main in lockstep with each publish (drift = the bug that once dropped updateManifestUrl).
  • After ANY wiki change, refresh the wiki pup window showing the page.
  • The changelog must be real (≥2 words, no placeholders) — the server enforces it.