app
Altium Bridge: AI for Altium Designer
Public Made by Adomby adom
Let an AI (Claude, ChatGPT, Codex or any agent) run Altium Designer for you: create symbols and footprints, place parts (also from Altium 365), wire and annotate schematics, Update PCB, set the stack-up and rules, route, pour copper, add mounting holes and stitching vias, run ERC and DRC, and make Gerbers, BOMs and STEP. Free in Hydrogen; bring your own AI and Altium licence.
← Commit history
0.2.67 docs only: README prose rewritten in plain language (no em dashes, current facts: the skills list, how the licence page and dialogs are driven); no bridge change
1 file changed
+141−151
README.md+141−151@@ -50,99 +50,94 @@ behind it (prefix `altium_`). Current, heat and EMC analysis of an Altium board runs through [AI Flow](https://wiki.adom.inc/adom/adom-aiflow). -> ### Two artifacts on this page — which one do you want?+> ### Two things on this page: which one do you want? > > | | **Release ZIP** (`adom-bridge-altium-v*.zip`) | **Package** (`adom-wiki pkg install adom/altium-bridge`) | > |---|---|---|-> | What it is | The **bridge runtime**: the native `altium-bridge.exe` (Rust) + the DelphiScript agent that drive Altium | **Skills + docs only**, for a container/agent |-> | Who loads it | **Adom Bridge** downloads it via `adom-bridge-altium-manifest.json` | You, into a container, to teach an agent the `altium_*` verbs |-> | Contains | server, handlers, agent template, process catalog parser | `SKILL.md` files (no binaries, no images) |-> | You install it manually? | **No** — Bridge handles it | Yes |+> | What it is | The **bridge itself**: the native `altium-bridge.exe` (Rust) and the DelphiScript agent that drive Altium | **Skills and docs only**, for the AI's container |+> | Who loads it | **Adom Bridge** downloads it through `adom-bridge-altium-manifest.json` | You, into a container, so the AI knows the `altium_*` verbs |+> | Contains | the exe, the agent template, the command catalog parser | `SKILL.md` files (no binaries, no images) |+> | Do you install it by hand? | **No**, Adom Bridge does | Yes | > > **The package is not the bridge.** Installing the package does not give you a working bridge; > Adom Bridge loading the release zip does. -Altium Designer is the user's **host app**. The bridge *detects* an existing install-(`%ProgramFiles%\Altium\AD*\X2.EXE`), launches it in the background, bootstraps a **resident-DelphiScript agent** inside it (the REPL lane), and hands the AI 178 `altium_*` verbs.+Altium Designer is the user's own **host app**. The bridge finds an installed Altium+(`%ProgramFiles%\Altium\AD*\X2.EXE`, Designer or Develop), starts it in the background, runs a small+**DelphiScript agent** inside it, and gives the AI 178 `altium_*` verbs. -- **Page / docs:** https://wiki.adom.inc/adom/altium-bridge+- **Page and docs:** https://wiki.adom.inc/adom/altium-bridge - **Bridge SDK:** https://wiki.adom.inc/adom/adom-bridge-sdk-- **Verb namespace:** `altium_*` · **Status verb:** `altium_status` · **Health:** `GET /health`-- **Plan of record** (every measured engine fact): the `altium-bridge-plan` skill in the package.+- **Verb prefix:** `altium_*` · **Status verb:** `altium_status` · **Health:** `GET /health`+- **Every measured engine fact:** the `altium-bridge-plan` skill in the package. -> Every screenshot below is a real capture of Altium Designer 26.9.1 driven end-to-end through the-> bridge. Two parts appear, both imported from their wiki component pages and authored into native-> libraries *by the bridge itself*: the WCH **CH340G** (USB-serial SOP-16) and the Microchip-> **LAN7800** (USB 3.1 → gigabit Ethernet, QFN-48 + EP) — the latter as ONE component with ten-> symbol display modes and seven footprint variants, each footprint carrying its own 3D body.+> Every screenshot below is a real capture of Altium Designer 26.9.1 driven through the bridge. Two+> parts appear, both imported from their wiki component pages and built into native libraries by the+> bridge: the WCH **CH340G** (USB to serial, SOP-16) and the Microchip **LAN7800** (USB 3.1 to gigabit+> Ethernet, QFN-48 with an exposed pad). The LAN7800 is one component with ten symbol display modes+> and seven footprint variants, each footprint with its own 3D body. --- -## The window tour — one imported chip, every surface+## A tour: one imported chip on every surface -### Symbol — `altium_show_symbol` (authored by `altium_create_symbol`)+### Symbol: `altium_show_symbol` (made with `altium_create_symbol`) All 16 named pins (GND/TXD/RXD/V3/UD+/UD-/XI/XO · VCC/R232/RTS#/DTR#/DCD#/RI#/DSR#/CTS#).  -### Footprint — `altium_show_footprint` (authored by `altium_create_footprint`)+### Footprint: `altium_show_footprint` (made with `altium_create_footprint`) -16 SOIC pads parsed from the component page's `pads.json` (mm → mil).+16 SOIC pads read from the component page's `pads.json` (mm to mil).  -### Library manager — `altium_show_library` / `altium_list_library`+### Library manager: `altium_show_library` / `altium_list_library`  -### Schematic — `altium_place_on_sch`+### Schematic: `altium_place_on_sch` -The symbol placed as U1 on a fresh sheet (per-primitive copy — the engine's group-`Replicate` drops children; the bridge handles that for you). `symbolName` takes a `;` list-(from 0.2.13): every part lands on the same sheet as U1..Un. Pass an existing `schPath` to ADD-symbols to that sheet; it grows to keep them inside the frame (from 0.2.45).+The symbol placed as U1 on a fresh sheet. Altium's group copy drops a component's children, so the+bridge copies it primitive by primitive. `symbolName` takes a `;` list, and every part lands on the+same sheet as U1..Un. Pass an existing `schPath` to add symbols to that sheet; it grows to keep them+inside the frame. -Sheet sizing (from 0.2.16 / 0.2.17): the sheet is sized from the parts, not the parts from the-sheet. The agent first measures every symbol's bounding box (pins included, plus 250 mil a side-for the pin numbers), then makes a custom sheet that holds the row with 500 mil between parts-and 600 mil margins, never smaller than A4 landscape (11500 x 7600 mil). Any slack is spread-evenly across the gaps. Each designator sits centred above its body and the Comment (the part-number) centred below it. `title` / `number` / `revision` / `drawnBy` fill the title block and-`description` becomes a text frame inside the drawing frame along the top; the reply's `_hints`-name whichever of those were left empty.+The sheet is sized from the parts. The agent measures every symbol's bounding box (pins included, plus+250 mil a side for the pin numbers), then makes a sheet that holds the row with 500 mil between parts+and 600 mil margins, never smaller than A4 landscape (11500 x 7600 mil), with any slack spread evenly.+Each designator sits centred above its part and the part number centred below it. `title`, `number`,+`revision` and `drawnBy` fill the title block, and `description` becomes a text frame along the top.  -### Symbol variants — `altium_build_symbol_modes`+### Symbol variants: `altium_build_symbol_modes` -The LAN7800 as one component with ten display modes (Altium's alternate symbols): here the 4-side-package look, geometry sized from the measured pin-name lengths so nothing collides.+The LAN7800 as one component with ten display modes (Altium's alternate symbols). This one is the+4-side package look, sized from the measured pin-name lengths so nothing collides.  -### 2D board — `altium_test_board` / `altium_swap_footprint`+### 2D board: `altium_test_board` / `altium_swap_footprint` -The LAN7800 **-HV-SB-RR** variant after two live footprint swaps on a wired 15×15 mm test board:-rounded pads, sixteen through-hole heatsink vias in the EP (all designator 49 → the EP net), the-silk pin-1 dot, and the PIN1 / GND_EP stub tracks that survived both swaps untouched.+The LAN7800 **-HV-SB-RR** variant after two live footprint swaps on a wired 15 x 15 mm test board:+rounded pads, sixteen through-hole heatsink vias in the exposed pad (all pad 49, so all on the EP net),+the silkscreen pin-1 dot, and the PIN1 and GND_EP stub tracks, still connected after both swaps. -`altium_test_board` takes a `;` list in `footprintName` (from 0.2.13): the parts are spread-evenly along X on one board. The parts are designated U1..Un (so `component_pins` and-`footprint_primitives` can address each one). Each part's name is its own Comment on the Top-Overlay under its footprint, so it moves with the part, and its `Pattern` is the footprint name-(from 0.2.45). Pass an existing `pcbPath` to ADD parts to that board (from 0.2.40), and-`altium_board_shape {mechOutline:true}` to give the fab Gerber an outline (from 0.2.45).+`altium_test_board` takes a `;` list in `footprintName` and spreads the parts evenly along X, named+U1..Un so `component_pins` and `footprint_primitives` can address each one. Each part's name is its+Comment on the top overlay under it. Pass an existing `pcbPath` to add parts to that board, and+`altium_board_shape {mechOutline:true}` to give the fab Gerber an outline.  -### 3D board — the STEP body on a real PCB+### 3D board: the STEP body on a real PCB  -And the underside — the sixteen drilled heatsink vias through the exposed pad. Real copper and-drill objects, exactly what the drill file gets:+The underside shows the sixteen drilled heatsink vias through the exposed pad: real copper and drill+objects, exactly what goes into the drill file.  @@ -150,22 +145,20 @@ drill objects, exactly what the drill file gets: ## How it fits together -The bridge is a `spawn.kind: exe` process Bridge launches on the user's machine-(`entrypoint: altium-bridge.exe`, a native Rust binary since 0.2.0; `port: 0`). Every request runs on-its own thread (from 0.2.28), so one slow verb never blocks the rest. It speaks HTTP (`POST /command`, `GET /health`) and reaches-Altium through ranked control surfaces, lightest first:+Adom Bridge starts the bridge on the user's PC (`altium-bridge.exe`, a native Rust program, on a port+Adom Bridge assigns). Every request runs on its own thread, so one slow verb never holds up the rest.+It answers HTTP (`POST /command`, `GET /health`) and reaches Altium four ways, lightest first: -| # | Surface | Used for |+| # | Route | Used for | |---|---------|----------|-| 1 | **Resident DelphiScript agent** (file-drop REPL inside Altium, bootstrapped via `X2.EXE -R`) | eval, open/show, library authoring, placement, compile/DRC/OutJob readback |-| 2 | **Process launcher** (1,111 `Server:Command` processes parsed from Altium's own `.rcs` tables) | zoom, view switches, document ops — `altium_run_command` / `altium_list_commands` |-| 3 | **Win32 / UIA** | window management, screenshots, dialog detection/dismissal by PID |-| 4 | **WebView2 (CDP)** | the sign-in / License Management pages — `altium_license`, `altium_signin_status` |-| 5 | **Altium 365 GraphQL** | workspace queries (`altium_a365_*`; needs a Pro/Enterprise token) |+| 1 | **The DelphiScript agent** inside Altium (requests and answers as files, started with `X2.EXE -R`) | reading and editing designs, libraries, placement, compile, DRC and OutJob results |+| 2 | **Altium's own commands** (1,111 `Server:Command` processes read from Altium's `.rcs` tables) | zoom, views, document operations: `altium_run_command`, `altium_list_commands` |+| 3 | **Windows UI Automation** | windows, screenshots, Altium's dialogs (DRC, Situs, Silkscreen Preparation, change orders), the licence page, the Components panel |+| 4 | **Altium 365 GraphQL** | workspace queries (`altium_a365_*`, with a workspace token) | -Modal dialogs freeze the script engine, so every mutating verb scans for dialogs by PID and-returns them with body screenshots (Altium paints dialog text; it is not exposed as text).-A halted engine (DelphiScript runtime errors are modal) recovers with `altium_agent_recover`.+A dialog stops Altium's script engine, so every verb that changes something looks for Altium's dialogs+afterwards and returns them with a screenshot (Altium draws its dialog text, so a picture is the only+way to read it). A stopped engine is restarted with `altium_agent_recover`. ## Every verb @@ -382,32 +375,31 @@ All 178 verbs, by area (prefix `altium_`). `altium_describe` returns the live ca ## The dock bar card -The bridge is a card in the Hydrogen **dock bar** — the launcher rail on the right edge of the-workspace — alongside KiCad and Fusion. It is in the curated fleet list-(`hydrogen-bootstrap/dock/apps.json`, order 35, featured), so every Adom user's rail picks it up-on the next poll, or instantly with *Refresh list from wiki*.+The bridge is a card in the Hydrogen **dock bar**, the launcher rail on the right edge of the workspace,+next to KiCad and Fusion. It is in the curated list (`hydrogen-bootstrap/dock/apps.json`, order 35,+featured), so every Adom user's rail shows it on the next refresh, or straight away with+*Refresh list from wiki*.  -Clicking the card runs this repo's `dockbar.json`: an install-or-update step-(`adom-wiki pkg update altium-bridge || pkg install adom/altium-bridge` — this is how the-skillpack propagates to every container), then `altium-dashboard serve --print-url`, which-self-backgrounds and prints its URL; the dock opens it in a webview tab and starts a named AI-thread with the Altium prompt. The dashboard is the standard dock anatomy:+Clicking the card runs this repo's `dockbar.json`: it installs or updates the skills+(`adom-wiki pkg update altium-bridge || pkg install adom/altium-bridge`), then starts+`altium-dashboard serve --print-url` and opens it in a webview tab with a new AI thread ready for Altium.+The dashboard has: -| Region | What it does here |+| Region | What it does | |---|---|-| **Say it** strip | six phrases you can send straight to a new AI thread — "show me my board in altium 3d", "add this wiki part to my altium library", "run drc on my altium board", … — plus the 2-minute demo player |-| **Status LEDs** | Relay · Box · Bridge · Altium (version) · Licence · Running · Agent (resident) · Updates — each with a hover hint, live over SSE from `/api/status` |-| **Boxes & actions** | the target machine, Setup / Launch Altium / Close Altium |-| **Guided demo** | the six-beat background tour of the examples that ship with Altium |+| **Say it** strip | six phrases to send to a new AI thread ("show me my board in altium 3d", "add this wiki part to my altium library", "run drc on my altium board", ...) and the 2-minute demo |+| **Status lights** | Relay · Box · Bridge · Altium (version) · Licence · Running · Agent · Updates, each with a hover hint, kept live from `/api/status` |+| **Boxes and actions** | the target machine; Setup, Launch Altium and Close Altium |+| **Guided demo** | a six-step tour of the examples that ship with Altium, in the background | -Progress for long verbs rides the **Windows taskbar button** (the app icon fills up), never a toast.+Progress for long verbs shows on Altium's **Windows taskbar button** (the icon fills up), never as a toast. -## Web control — "Add to Altium library" from a wiki page+## "Add to Altium library" from a wiki page -Component and molecule pages carry an **EXPORTS TO: KiCad · Fusion · Altium** row. The bridge's-half is `altium_install_library_bundle`, the exact peer of `kicad_install_library_bundle`:+Component and molecule pages have an **EXPORTS TO: KiCad · Fusion · Altium** row. The bridge's part of+that is `altium_install_library_bundle`, the counterpart of `kicad_install_library_bundle`:  @@ -416,91 +408,89 @@ AdomWebControl.run('altium_install_library_bundle', { zipPath, libraryName, capt // → { success, symbols, footprints, intlibs, installed:[{lib,ok}], altiumRunning, restartNeeded, thumbnailDataUrl? } ``` -The page fetches the bundle (`<Lib>.SchLib` + `<Lib>.PcbLib`, or an `.IntLib`), stages it on the-box with `write_file_chunk`, and calls the verb; the user clicks *Allow* once on Adom Bridge's-consent prompt. The verb is zip-slip hardened (256 MB / 512 MB caps), registers the libraries in-Installed Libraries, **never closes a running Altium** (it reports `restartNeeded`), and returns a-proof frame — the library as Altium actually opened it:+The page downloads the bundle (`<Lib>.SchLib` and `<Lib>.PcbLib`, or an `.IntLib`), copies it to the+PC with `write_file_chunk` and calls the verb; the user clicks *Allow* once in Adom Bridge. The verb+checks the zip's paths and sizes (256 MB / 512 MB limits), adds the libraries to Installed Libraries,+**never closes a running Altium** (it reports `restartNeeded` instead), and returns a picture of the+library as Altium opened it: -+ -`docs/webcontrol-altium-test.html` is the acceptance harness (it loads the wiki's live-`webcontrol.js`).+`docs/webcontrol-altium-test.html` is the test page (it loads the wiki's live `webcontrol.js`). -## The skillpack — ten skills, propagated like KiCad's and Fusion's+## The skills -`adom-wiki pkg install adom/altium-bridge` delivers these into `~/.claude/skills/` on every-container, and the dock's install step keeps them current:+`adom-wiki pkg install adom/altium-bridge` puts these into `~/.claude/skills/` in the AI's container,+and the dock's install step keeps them current: | Skill | For | |---|---|-| `altium-bridge` | the user skill: every verb, what it returns, and when to reach for it |-| `altium-install` | installing Altium Designer + the trial sign-in, measured step by step |-| `altium-libraries` | display modes, footprint variants, STEP bodies, the tri-vendor rule, the pin-1 check |-| `altium-boards` | test boards, board shape, placement laws, footprint swaps with surviving nets, 3D camera facts |-| `altium-outputs` | compile/ERC, DRC, OutJob media (Gerber, ODB++, NC drill, BOM, pick-and-place) |-| `altium-part-import` | add any catalog part with **Mouser (preferred) + DigiKey + LCSC** part numbers — REUSE / CREATE / APPEND |-| `altium-kicad-import` | KiCad → Altium, incl. the KiCad-10 downgrade and the native no-importer lane |-| `altium-bridge-plan` | the plan of record: every automation surface Altium exposes, measured |-| `altium-bridge-dev` | developer-only: the agent architecture, the dialog doctrine, the engine-halting identifiers |-| `altium-bridge-publish` | developer-only: the release recipe (lockstep versions, asset upload, pkg staging) |+| `altium-bridge` | the main skill: what the AI can do in Altium and which verb does it |+| `altium-libraries` | symbols (multi-part, display modes), footprints (also from a datasheet land pattern), 3D bodies, vendor numbers, the pin-1 check |+| `altium-part-import` | adding any catalog part with **Mouser (preferred), DigiKey and LCSC** numbers |+| `altium-wiki-import` | a wiki component page or a whole Cloud Library into Altium |+| `altium-kicad-import` | KiCad to Altium, including the KiCad 10 downgrade |+| `altium-schematic-edit` | placing, wiring, swapping and annotating parts, hierarchical sheets, the netlist, Update PCB, PDF |+| `altium-boards` | stack-up, net classes, diff pairs, placement, mounting holes, fiducials, stitching vias, 3D |+| `altium-outputs` | compile, ERC, DRC, Silkscreen Preparation, Gerbers, drill, pick and place, OutJobs, STEP |+| `altium-bom` | the BOM grouped by MPN, JLCPCB / Mouser / DigiKey files, variants |+| `altium-a365` | the Altium 365 workspace: components, GraphQL, library uploads |+| `altium-licensing` | the licence seat, Designer and Develop, what to do when there is no seat |+| `altium-instances` | two Altiums at once (Designer beside Develop) |+| `altium-install` | installing Altium Designer and its trial sign-in |+| `altium-bridge-plan`, `altium-uia` | reference only: every automation route Altium has, as measured | ## Parts carry all three vendors -Every component the bridge authors gets `Mouser Part #` (Adom's preferred vendor), `DigiKey Part #`,-and the exact `LCSC Part #` (so JLCPCB BOM/CPL round-trip), plus MPN / Manufacturer / Value /-Package — looked up with one `adom-parts-search` call. Parameters land hidden; `altium_set_visibility`+Every component the bridge makes gets a `Mouser Part #` (Adom's preferred vendor), a `DigiKey Part #`+and the exact `LCSC Part #` (so JLCPCB BOM and placement files match), plus MPN, Manufacturer, Value and+Package, found with one `adom-parts-search` call. The parameters are hidden; `altium_set_visibility` shows the one you want on the schematic. -## Zero dialogs, by construction--Altium's scripting debugger breaks on **any** raised exception, so a raise is a modal. The bridge-designs the class out rather than dismissing it: file reads probe with `FileOpen` before loading,-every save is preceded by a transaction clear (a dangling `PreProcess` is what draws the-save-a-copy warning), engine-halting identifiers are catalogued in the dev skill, and every verb-that could draw one scans Altium's child windows afterwards and attaches a frame if it finds any.-A dialog the user sees is logged as a defect, not handled.--**And never a half-answered one (from 0.2.35).** A dialog left mid-exchange is worse than one left-up. Altium's close-time "Save None" does not dismiss *Confirm Save Locally* — it unticks the-documents and renames the same window to *Confirm Not Saving*, which OK then commits; pressing only-the first half left Altium sitting modal. Because Windows disables a process's other top-level-windows for the duration of a modal, that state presents as a **disabled main window with nothing on-screen to answer**: no menu, no Alt+F4, no `-R` hand-off reaches it, and it keeps the licence seat.-`close` and `agent_recover` detect it (`errorCode: altium_modal_orphan`) and-`close {discardChanges:true}` ends it the way Altium's own Exit does — a posted `WM_QUIT`, which-RELEASES the seat where a `taskkill` would strand it.--**Launching does not cost the user their window (from 0.2.37).** Altium foregrounds itself at-startup and offers no switch for it, so `altium_launch` remembers the window the user was in and-hands it back once Altium settles (`foregroundReturnedTo`, `windowEtiquette: background`). Pass-`background:false` when the user asked to watch Altium come up.--## Lineage--The bridge consolidates Barrett Land's summer-2026 Altium work — his earlier repos-`barrett-land/adom-desktop-altium-bridge` (named when the product was still called Adom Desktop;-this bridge is `adom/altium-bridge`), `altium-part-importer` and `kicad10-to-altium` — into one-master repo: every verb ported onto the resident agent (his bridge forwarded one `X2.EXE` command-per call), his three-path part workflow and KiCad-10 findings carried into the skillpack, his v10→v9 downgrader vendored under `tools/`.-His pages stay up with pointers here.--## Running / dependencies--Bridge provisions everything; nothing to install by hand.--- **No runtime to install**: the bridge is one native exe inside the release zip.-- **Altium Designer** (host app). Not installed yet? Call `altium_install {}` and follow `_next`: the verb- stages the install, verifies the installer's signature, and asks the human only for a password, the UAC+## Dialogs++Altium's script debugger stops on any error, and every stop is a dialog on the user's screen. So the+bridge avoids raising errors in the first place: it checks a file exists before loading it, clears any+open edit before saving (a half-finished edit is what makes Altium offer to save a copy), keeps a list+of script identifiers that stop the engine (`release.py` refuses a build that uses one), and after every+verb that could open a dialog, looks for one and returns a picture of it.++**A dialog is answered completely, or not at all.** On close, Altium's "Save None" doesn't close+*Confirm Save Locally*: it unticks the documents and renames the same window *Confirm Not Saving*,+which OK then confirms. Pressing only the first button left Altium waiting on a dialog with its main+window disabled and nothing visible to answer, still holding the licence seat. `close` and+`agent_recover` detect that (`errorCode: altium_modal_orphan`), and `close {discardChanges:true}` ends+it the way Altium's own Exit does, which releases the seat (killing the process would strand it).++**Launching doesn't take the user's window.** Altium brings itself to the front when it starts and has+no option against it, so `altium_launch` remembers the window the user was in and gives it back once+Altium has settled (`foregroundReturnedTo`). Pass `background:false` when the user wants to watch+Altium start.++## Where it came from++The bridge brings together Barrett Land's summer-2026 Altium work: his repos+`barrett-land/adom-desktop-altium-bridge` (named when the product was still Adom Desktop),+`altium-part-importer` and `kicad10-to-altium`. Every verb moved onto the agent inside Altium (his+bridge ran one `X2.EXE` command per call), his three ways of adding a part and his KiCad 10 findings went+into the skills, and his KiCad 10 to 9 converter is in `tools/`. His pages stay up and point here.++## Running it++Adom Bridge provides everything; there's nothing to install by hand.++- **No runtime:** the bridge is one native exe in the release zip.+- **Altium Designer** (the host app, Designer or Develop). Not installed yet? `altium_install {}` walks+ through it: it checks the installer's signature and asks the person only for a password, the UAC prompt, or clicks inside the elevated installer. - **OS:** Windows. -The bridge binds a Bridge-assigned port — never `0.0.0.0`. Auto-updates via `updateManifestUrl`-in `bridge.json`.+The bridge listens on a local port Adom Bridge assigns, never `0.0.0.0`, and updates itself through+`updateManifestUrl` in `bridge.json`. --- -*Developer and publish docs live in this page's source repo (`dev-skills/`, `publish-skills/`, `PUBLISHING.md`), not in the-installed package: `adom-wiki repo clone adom/altium-bridge` to get them. `dev-skills/altium-bridge-dev` holds every measured-engine fact (the DelphiScript traps, the script-halt safety net, the UIPI lessons) and `dev-skills/altium-bridge-test` is the-verb battery that gates a promotion.*+*Developer and publishing docs live in this page's source repo (`dev-skills/`, `publish-skills/`,+`PUBLISHING.md`), not in the installed package: `adom-wiki repo clone adom/altium-bridge` to get them.+`dev-skills/altium-bridge-dev` holds every measured engine fact, and `dev-skills/altium-bridge-test` is+the verb battery every release passes on both Altium builds.*