skill
molecule-pipeline
Public Made by Adomby adom
Top-level router for moving molecules between EDA tools, the wiki, and Hydrogen: one entry point that routes publish/import intents to the right skill chain and enforces the pipeline invariants.
← Commit history
docs: the molecule pipeline step by step (EDA → wiki → Hydrogen), verified 2026-09-03
3 files changed
+327
README.md+4@@ -18,6 +18,10 @@ Your agent handles every step below from a single prompt: Works the same for Fusion 360 and Altium sources — name your tool or let the agent detect it from your files. +## The whole process, step by step++Every stage, every tool, every gate, in order: **[docs/process.html](docs/process.html)** (EDA export on the laptop, OCCT conversion, packaging, publish, render archive, Hydrogen import, wiring in the 3D editor, and the e2e regression that proves it).+ ## What happens under the hood 
docs/process.htmladded+118@@ -0,0 +1,118 @@+<!doctype html>+<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">+<title>The molecule pipeline, step by step</title>+<style>+ :root { --bg:#051d1a; --bg2:#072722; --panel:rgba(7,34,29,.6); --line:#1c5247; --text:#d7f4ec; --muted:#7fb5a9; --head:#f2fbf8; --accent:#2ee6c8; --accent2:#38a6f8; --accent3:#a06bfa; }+ * { box-sizing:border-box; }+ body { margin:0; font-family:'Segoe UI',system-ui,-apple-system,sans-serif; background:radial-gradient(1400px 900px at 20% 0%, #0c3a33 0%, var(--bg2) 45%, var(--bg) 100%) fixed; color:var(--text); line-height:1.55; }+ main { max-width:1080px; margin:0 auto; padding:48px 32px 96px; }+ .band { border-radius:18px; padding:26px 28px; margin-bottom:34px; background:linear-gradient(100deg,var(--accent) 0%,var(--accent2) 55%,var(--accent3) 100%); color:#04211c; box-shadow:0 18px 50px rgba(46,230,200,.18); }+ .band .k { font-size:13px; font-weight:800; letter-spacing:3px; text-transform:uppercase; color:#063b31; }+ .band h1 { margin:6px 0 0; font-size:34px; font-weight:800; letter-spacing:-.4px; color:#04211c; }+ h1 { color:var(--head); font-size:32px; letter-spacing:-.4px; }+ h2 { color:#9fe8d8; font-size:22px; letter-spacing:1px; margin-top:46px; padding-top:18px; border-top:1px dotted var(--line); }+ h3 { color:var(--head); font-size:17px; margin-top:28px; }+ p, li { font-size:15.5px; }+ a { color:var(--accent); text-decoration:none; } a:hover { text-decoration:underline; }+ code { font-family:'Cascadia Mono','Consolas',ui-monospace,monospace; font-size:13.5px; color:#e9fff9; background:rgba(46,230,200,.10); border:1px solid rgba(46,230,200,.18); border-radius:6px; padding:1px 6px; }+ pre { background:var(--panel); border:1.5px solid #2b6a5c; border-radius:14px; padding:16px 18px; overflow-x:auto; }+ pre code { background:none; border:0; padding:0; font-size:13px; line-height:1.5; color:#d7f4ec; }+ table { width:100%; border-collapse:collapse; margin:14px 0 22px; font-size:14.5px; }+ th, td { text-align:left; padding:9px 12px; border-bottom:1px solid var(--line); vertical-align:top; }+ th { color:#9fe8d8; font-weight:700; letter-spacing:.5px; font-size:13px; text-transform:uppercase; }+ strong { color:var(--head); }+ .foot { margin-top:60px; color:var(--muted); font-size:13px; border-top:1px dotted var(--line); padding-top:16px; }+</style></head><body><main>+<div class="band"><div class="k">adom · molecule-pipeline</div><h1>The molecule pipeline, step by step</h1></div>++<p>How a board leaves your EDA tool, becomes a molecule on the wiki, and lands in a Hydrogen account wireable in the 3D editor. Every tool in the chain, in the order it runs, with the command each step actually issues and the gate that has to pass before the next step starts.</p>+<p>This page is the process; the <a href="../README.md">README</a> is the one-sentence front door.</p>+<h2>The chain at a glance</h2>+<pre><code> YOUR LAPTOP YOUR CONTAINER ADOM CLOUD+ ─────────── ────────────── ──────────+ KiCad 10 ──kicad bridge──┐+ Fusion 360 ──fusion bridge─┼─▶ EDA export skill ─▶ step2glb (CLI) ──▶ OCCT service ─▶ anchored GLB+ Altium ──altium bridge─┘ │ ▲ (adom-step2glb) + footprint/symbol JSON+ │ │ │+ ▼ │ ▼+ molecule-publish ────────┘ package.json + gates ──▶ adom-wiki ──▶ wiki page+ │ (pkg publish + repo push)+ ▼ │+ adom-nucleus --render-board (APM render/ archive) │+ ▼+ adom-molecule import <owner>/<slug> ─────────▶ Hydrogen /api/molecules/import+ │+ ▼+ 3D Editor V2: load, place, wire</code></pre>+<p>Every arrow is a real package. Versions this page was verified against (2026-09-03):</p>+<table><thead><tr><th>Layer</th><th>Package</th><th>Version</th><th>Runs where</th></tr></thead><tbody><tr><td>Router (this page)</td><td><code>adom/molecule-pipeline</code></td><td>1.1.2</td><td>container skill</td></tr><tr><td>Laptop bridge</td><td><code>adom/adom-bridge</code> (<code>adom-bridge</code> CLI, formerly adom-desktop)</td><td>2.1.15</td><td>laptop app, driven from the container</td></tr><tr><td>KiCad bridge</td><td><code>adom/kicad-bridge</code></td><td>1.0.111</td><td>inside Adom Bridge</td></tr><tr><td>Fusion bridge</td><td><code>adom/fusion-bridge</code></td><td>1.9.352</td><td>inside Adom Bridge</td></tr><tr><td>EDA export skills</td><td><code>adom/kicad-export-molecule</code> · <code>adom/fusion-export-molecule</code> · <code>adom/altium-export-molecule</code></td><td>1.1.2 · 1.2.2 · 2.3.1</td><td>container skills</td></tr><tr><td>Convert</td><td><code>adom/adom-step2glb</code> (<code>step2glb</code> CLI) + shared OCCT service</td><td>1.2.2 CLI / service 1.3.0</td><td>container CLI, cloud service</td></tr><tr><td>Package + publish</td><td><code>adom/molecule-publish</code></td><td>2.10.0</td><td>container skill (+ scripts)</td></tr><tr><td>Wiki CLI</td><td><code>adom/adom-wiki-cli</code> (<code>adom-wiki</code>)</td><td>1.7.26</td><td>container</td></tr><tr><td>Render archive</td><td><code>adom/adom-project-manager</code> (<code>adom-nucleus</code>, alias <code>adom-project-manager</code>)</td><td>0.14.0</td><td>container</td></tr><tr><td>Import</td><td><code>adom/adom-molecule</code> (<code>adom-molecule</code> CLI, ships <code>adom-molecule-import</code> skill)</td><td>1.1.10</td><td>container</td></tr><tr><td>Destination</td><td>Hydrogen (<code>hydrogen.adom.inc</code>)</td><td>1.0.185</td><td>cloud</td></tr></tbody></table>+<p>Install the container side in one go:</p>+<pre><code>adom-wiki pkg install adom/molecule-pipeline # router; pulls molecule-publish + adom-molecule+adom-wiki pkg install adom/adom-step2glb # step2glb CLI+adom-wiki pkg install adom/kicad-export-molecule # or fusion-export-molecule / altium-export-molecule+adom-wiki pkg install adom/adom-project-manager # adom-nucleus --render-board</code></pre>+<h2>Stage 0 — Before you export: the board must be a molecule</h2>+<p>A molecule is a board that carries the Adom furniture: <strong>MP1–MP4 marker footprints</strong> (the anchoring references) and the corner <strong>machine pins / contacts</strong> from the Adom library. OCCT anchors on the markers; without at least three of them the conversion still runs but the GLB imports unanchored and unwireable.</p>+<ul><li>KiCad: <code>kicad-to-molecule</code> adds wings + machine pins to a plain board; footprints come from <code>adom/kicad-library-manager</code>.</li><li>Altium: <code>barrett-land/adom-altium-library-importer</code> puts the machine-pin libraries inside Altium.</li><li>Fusion/EAGLE: use the Adom library parts (<code>MACH_PIN_LRG_SHORT</code>, etc.); the marker names carry the pin size, which the converter reads (<code>pin_size_source: markers</code>).</li></ul>+<p>Gate: the 3D models for the pins, contacts and markers <strong>resolve in your EDA's 3D viewer on the machine that will export</strong>. A STEP only contains what resolved at export time; a model referenced by a path that only exists on someone else's machine is silently dropped, and anchoring fails downstream.</p>+<h2>Stage 1 — Export on the laptop (EDA export skill + Adom Bridge)</h2>+<p>The STEP is always exported <strong>on the design machine</strong>, driven from the container through Adom Bridge. Everything below is what the export skill does for you when you say "export molecule ABC".</p>+<h3>KiCad (<code>kicad-export-molecule</code>)</h3>+<ol><li>Preflight: <code>adom-bridge ping</code>; <code>adom-bridge commands | grep kicad_</code>; kicad-cli is KiCad 10 (<code>C:\Program Files\KiCad\10.0\bin\kicad-cli.exe version</code>).</li><li>Export the STEP with the laptop CLI (models substituted from the laptop's libraries):+<pre><code>kicad-cli pcb export step --subst-models --force -o ABC.step ABC.kicad_pcb</code></pre>+Read the output: every <code>Could not add 3D model for MPn</code> line means a marker did not bake in. Fix the model path (KiCad resolves relative model paths against the board's directory, <code>${KICAD10_3DMODEL_DIR}</code> against the install) and export again.</li><li>Optional silk PNGs (top/bottom, white art on transparent).</li><li>Pull the bundle to the container: <code>adom-bridge pull_file {"filePaths":[...], "saveTo":"..."}</code> — <code>ABC.step</code>, <code>ABC.kicad_pcb</code>, <code>ABC.kicad_sch</code>, <code>ABC.kicad_pro</code>, silks.</li></ol>+<p>Never use KiCad's own GLB export for a molecule: it bypasses anchoring, gold pins, normalization and the footprint emit. STEP in, OCCT makes the GLB.</p>+<h3>Fusion 360 Electronics (<code>fusion-export-molecule</code>)</h3>+<ol><li><code>adom-bridge fusion_start</code> if Fusion is closed (blocks until the add-in is ready; the first <code>fusion_get_app_state</code> after that can take a minute).</li><li>Open the <strong>board file directly</strong> so the multi-design picker never appears:+<pre><code>adom-bridge fusion_open_cloud_file {"projectName":"Main","folderPath":"COSMIIC","fileName":"PM COIL Molecule","fileExtension":"fbrd","recovery":"discard"}</code></pre>+Find the design first with <code>fusion_mcp_call {"tool":"fusion_mcp_read","arguments":{"queryType":"document","operation":"search","name":"..."}}</code> (APS search needs a fresh sign-in; MCP search works with any open document).</li><li>Export sources: <code>fusion_export_eagle_source</code> for the <code>.brd</code>, switch with <code>fusion_electron_run {"command":"EDIT .s1"}</code>, export the <code>.sch</code>, switch back with <code>EDIT .brd</code>.</li><li><code>fusion_show_3d_board</code>, then <code>fusion_export_step</code> (and <code>fusion_export_f3d</code> / <code>fusion_export_usdz</code> / silkscreen screenshots if you want the kitchen sink).</li><li><code>pull_file</code> the bundle: <code>.brd</code>, <code>.sch</code>, <code>.step</code> (+ extras).</li></ol>+<h3>Altium (<code>altium-export-molecule</code>)</h3>+<p>Native STEP export with the machine-pin models baked in, board metadata derived for OCCT, then the same converter call as everyone else. The skill ends when the OCCT artifacts are on the container; it never packages or publishes.</p>+<p>Gate for all three: the bundle on the container has <strong>STEP + board + schematic</strong> (a molecule without its schematic is not reproducible and <code>molecule-publish</code> refuses it).</p>+<h2>Stage 2 — Convert: STEP → anchored GLB + footprint/symbol (<code>step2glb</code>)</h2>+<p>One command, run on the container, does the whole OCCT molecule pipeline server-side:</p>+<pre><code>step2glb convert ABC.step --board ABC.kicad_pcb --pin large -o <slug>.glb # .brd boards work too</code></pre>+<p>The CLI uploads to the shared OCCT service (<code>https://step2glb-gmdoncpxdwx0.adom.cloud</code>, async <code>POST /convert</code> → <code>GET /jobs/{id}</code> → <code>/jobs/{id}/result</code>), and downloads <code><slug>.glb</code>, <code><slug>_footprint.json</code> and <code><slug>_symbol.json</code> beside it. What the service does: MP-marker anchoring (Z-up, front-left machine pin at the origin, board-surface Z), canonical gold machine-pin material, optional silkscreen overlay, meter normalization, Draco compression, and footprint + symbol JSON with the <strong>per-pad wire-attach Z</strong> — the numbers Hydrogen's wire tool snaps to.</p>+<p>Gate on the printed stats before going any further:</p>+<table><thead><tr><th>Stat</th><th>Must be</th><th>Otherwise</th></tr></thead><tbody><tr><td><code>molecule_anchored</code></td><td><code>true</code></td><td>markers missing from the STEP; go back to Stage 1</td></tr><tr><td><code>footprint_applied</code> / <code>footprint_pins</code></td><td><code>true</code> / 4</td><td>board parse failed; read the warnings</td></tr><tr><td><code>contact_z</code></td><td>2.8–8.4 mm</td><td>wrong pin size or wrong marker models</td></tr><tr><td><code>pin_size_source</code></td><td><code>markers</code></td><td><code>param</code> means the size fell back to <code>--pin</code></td></tr><tr><td><code>warnings</code></td><td>none</td><td>every entry is actionable</td></tr></tbody></table>+<p>The GLB carries <code>asset.extras.adomMolecule</code> — durable provenance you can check on any downloaded copy (do not look for a <code>molecule_anchor</code> node; the optimizer flattens it by design).</p>+<h2>Stage 3 — Package (<code>molecule-publish</code>)</h2>+<pre><code><slug>/+ package.json type "component", component.mpn, hero block, dependencies {}+ <slug>.glb the OCCT GLB, named EXACTLY <slug>.glb+ ABC.kicad_pcb | .brd board source+ ABC.kicad_sch | .sch schematic source+ ABC.step STEP (reproducibility)+ <slug>_footprint.json OCCT artifact (wire-attach Z)+ <slug>_symbol.json OCCT artifact+ README.md, screenshots/hero.png, [silk PNGs, .f3d, .usdz, gerbers, bom, cpl]</code></pre>+<p>Rules that bite:</p>+<ul><li><strong>Name the GLB <code><slug>.glb</code>.</strong> The wiki auto-converts the STEP to a plain <code><slug>.glb</code> at publish time and points <code>model_3d_path</code> at it; an anchored GLB with any other name is shadowed by the plain one and every import gets an unanchored model.</li><li>The <code>component</code> block is what creates the page's component-metadata row; without it <code>model_3d_path</code> is never set and import fails with "no published GLB".</li><li>Key the page by MPN, never by value. Do not ship a hand-made <code>page.json</code>.</li><li>Component dependencies are enforced before publish: <code>python3 scripts/component_graph.py plan <board> --out component-plan.json</code> then <code>gate package.json --plan component-plan.json --expect-board <board> --resolve</code> (declared coverage + every dependency resolves to a real page). Missing component pages: Stage 2.6 auto-creates them.</li><li>Stamp what you tested on: <code>python3 scripts/tested_with.py stamp package.json --family <model></code>.</li><li>Hero camera: <code>python3 scripts/hero_camera.py pose <slug>.glb --page page.json</code>.</li></ul>+<h2>Stage 4 — Publish + verify (<code>adom-wiki</code>)</h2>+<pre><code>adom-wiki pkg publish [--org adom] # registry version+adom-wiki repo push <owner>/<slug> --files <every file above> -m "<name> molecule"</code></pre>+<p>Two layers, both required: <code>pkg publish</code> registers the version (and generates <code>page.json</code>), <code>repo push</code> puts the files on the page. Verify before calling it done:</p>+<ul><li><code>metadata.model_3d_path</code> on the page == <code><slug>.glb</code>;</li><li>the page's GLB is byte-identical to your gated conversion (<code>curl</code> it with your token, <code>cmp</code> against the local file) — this is the anchoring proof;</li><li>the full set is present: GLB + STEP + schematic + board + footprint/symbol JSON.</li></ul>+<p>Private pages are fine end to end; nothing in the chain needs the page public.</p>+<h2>Stage 5 — Render archive (<code>adom-nucleus --render-board</code>)</h2>+<p>Run <strong>after</strong> the publish, every time (it stamps the archive with the version it reads from the published <code>package.json</code>):</p>+<pre><code>adom-nucleus --render-board <owner>/<slug> # alias: adom-project-manager --render-board</code></pre>+<p>It renders <code>render/pcb.svg</code>, <code>render/sheet-*.svg</code>, <code>render/board.glb</code>, content-hashes them and archives <code>render/<version>/</code> + <code>render/manifest.json</code> only when the content changed. Check <code>manifest.current == <version></code> and <code>python3 scripts/render_parity.py render/board.glb <slug>.glb</code> (same mesh count, else the render dropped geometry). EAGLE/Fusion sources report "nothing rendered" and skip gracefully today.</p>+<h2>Stage 6 — Import into Hydrogen (<code>adom-molecule</code>)</h2>+<pre><code>adom-molecule import <owner>/<slug> --owner <your-user-or-org> [--name <name>]</code></pre>+<p>What it does (1.1.10): reads the page owner-qualified with your container credential (private pages included), checks <code>model_3d_path</code> and that a footprint JSON or board file exists, downloads the GLB as a preflight, then POSTs <code>{wikiRef:"<owner>/<slug>", owner, name, includeSource:true}</code> to <code>https://hydrogen.adom.inc/api/molecules/import</code>. Hydrogen re-reads the page with the same credential, <strong>reuses the wiki GLB verbatim</strong> (no re-optimization, no silkscreen, no Blender), carries the sources, and attaches the footprint so the molecule lands with wire-attach points. Re-importing creates a new version of the same molecule.</p>+<p>Same thing from any script:</p>+<pre><code>curl -X POST https://hydrogen.adom.inc/api/molecules/import \+ -H "X-Api-Key: $(cat /var/run/adom/api-key)" -H "Content-Type: application/json" \+ -d '{"wikiRef":"<owner>/<slug>","owner":"<you>","includeSource":true}'</code></pre>+<p>Gate: the reply carries a <code>version</code> and no <code>warnings</code>; <code>adom-molecule list</code> shows the name under your owner; <code>https://hydrogen.adom.inc/<owner>/molecules/<name></code> renders it.</p>+<h2>Stage 7 — Use it in Hydrogen</h2>+<p>Open a repo's editor (<code>https://hydrogen.adom.inc/<owner>/<repo>/edit</code>), add a <strong>3D Editor V2</strong> tab, then:</p>+<ol><li><strong>Browse and Load Molecule</strong> → pick the owner → the molecule → Load → set the placement position → OK.</li><li><strong>More Objects tools → Add Wires</strong> (tick <em>Draw Multiple Wires</em>) → hover a machine pin until the "Machine Pin: FL/BL/FR/BR" tooltip shows → click → click the second molecule's pin. The console logs <code>New contact-based wire created from <a> - Pin: X to <b> - Pin: Y</code>.</li><li>Save the layout.</li></ol>+<p>The in-app <strong>Optimize / Regenerate 3D model</strong> button is retired (it pointed at a worker that no longer exists); optimization happens in Stage 2 and import reuses it.</p>+<h2>Regression: the e2e harness</h2>+<p><code>project/molecule-e2e/run-e2e.sh</code> on gallia republishes two private test molecules — <code>drew2/e2e-kicad-solonoid</code> (KiCad) and <code>drew2/e2e-fusion-pmcoil</code> (Fusion/EAGLE) — through the current stack every time a molecule-family package changes (cron, every 30 minutes, <code>check-and-run.sh</code>). Stages it gates: EDA export on the laptop (kicad-cli 10 / Fusion bridge), OCCT conversion stats, provenance stamp, <code>pkg publish</code> + <code>repo push</code>, wiki GLB checksum, APM render archive + manifest, and the private import into Hydrogen through <code>adom-molecule import</code>. <code>last-status.json</code> is the verdict; <code>e2e.log</code> is the trail.</p>+<h2>The one-sentence versions</h2>+<ul><li>"Move molecule ABC from KiCad on my computer up to the wiki." → Stages 1–5.</li><li>"Get molecule ABC into my Hydrogen account." → Stage 6.</li><li>"Publish my molecule ABC and import it into my Hydrogen account." → Stages 1–6, each gated before the next.</li><li>"Wire ABC to DEF in the 3D editor." → Stage 7.</li></ul>+<div class="foot">adom/molecule-pipeline · verified against the live stack on 2026-09-03 · source: docs/process.md</div>+</main></body></html>
docs/process.mdadded+205@@ -0,0 +1,205 @@+# The molecule pipeline, step by step++How a board leaves your EDA tool, becomes a molecule on the wiki, and lands in a Hydrogen account wireable in the 3D editor. Every tool in the chain, in the order it runs, with the command each step actually issues and the gate that has to pass before the next step starts.++This page is the process; the [README](../README.md) is the one-sentence front door.++## The chain at a glance++```+ YOUR LAPTOP YOUR CONTAINER ADOM CLOUD+ ─────────── ────────────── ──────────+ KiCad 10 ──kicad bridge──┐+ Fusion 360 ──fusion bridge─┼─▶ EDA export skill ─▶ step2glb (CLI) ──▶ OCCT service ─▶ anchored GLB+ Altium ──altium bridge─┘ │ ▲ (adom-step2glb) + footprint/symbol JSON+ │ │ │+ ▼ │ ▼+ molecule-publish ────────┘ package.json + gates ──▶ adom-wiki ──▶ wiki page+ │ (pkg publish + repo push)+ ▼ │+ adom-nucleus --render-board (APM render/ archive) │+ ▼+ adom-molecule import <owner>/<slug> ─────────▶ Hydrogen /api/molecules/import+ │+ ▼+ 3D Editor V2: load, place, wire+```++Every arrow is a real package. Versions this page was verified against (2026-09-03):++| Layer | Package | Version | Runs where |+|---|---|---|---|+| Router (this page) | `adom/molecule-pipeline` | 1.1.2 | container skill |+| Laptop bridge | `adom/adom-bridge` (`adom-bridge` CLI, formerly adom-desktop) | 2.1.15 | laptop app, driven from the container |+| KiCad bridge | `adom/kicad-bridge` | 1.0.111 | inside Adom Bridge |+| Fusion bridge | `adom/fusion-bridge` | 1.9.352 | inside Adom Bridge |+| EDA export skills | `adom/kicad-export-molecule` · `adom/fusion-export-molecule` · `adom/altium-export-molecule` | 1.1.2 · 1.2.2 · 2.3.1 | container skills |+| Convert | `adom/adom-step2glb` (`step2glb` CLI) + shared OCCT service | 1.2.2 CLI / service 1.3.0 | container CLI, cloud service |+| Package + publish | `adom/molecule-publish` | 2.10.0 | container skill (+ scripts) |+| Wiki CLI | `adom/adom-wiki-cli` (`adom-wiki`) | 1.7.26 | container |+| Render archive | `adom/adom-project-manager` (`adom-nucleus`, alias `adom-project-manager`) | 0.14.0 | container |+| Import | `adom/adom-molecule` (`adom-molecule` CLI, ships `adom-molecule-import` skill) | 1.1.10 | container |+| Destination | Hydrogen (`hydrogen.adom.inc`) | 1.0.185 | cloud |++Install the container side in one go:++```bash+adom-wiki pkg install adom/molecule-pipeline # router; pulls molecule-publish + adom-molecule+adom-wiki pkg install adom/adom-step2glb # step2glb CLI+adom-wiki pkg install adom/kicad-export-molecule # or fusion-export-molecule / altium-export-molecule+adom-wiki pkg install adom/adom-project-manager # adom-nucleus --render-board+```++## Stage 0 — Before you export: the board must be a molecule++A molecule is a board that carries the Adom furniture: **MP1–MP4 marker footprints** (the anchoring references) and the corner **machine pins / contacts** from the Adom library. OCCT anchors on the markers; without at least three of them the conversion still runs but the GLB imports unanchored and unwireable.++- KiCad: `kicad-to-molecule` adds wings + machine pins to a plain board; footprints come from `adom/kicad-library-manager`.+- Altium: `barrett-land/adom-altium-library-importer` puts the machine-pin libraries inside Altium.+- Fusion/EAGLE: use the Adom library parts (`MACH_PIN_LRG_SHORT`, etc.); the marker names carry the pin size, which the converter reads (`pin_size_source: markers`).++Gate: the 3D models for the pins, contacts and markers **resolve in your EDA's 3D viewer on the machine that will export**. A STEP only contains what resolved at export time; a model referenced by a path that only exists on someone else's machine is silently dropped, and anchoring fails downstream.++## Stage 1 — Export on the laptop (EDA export skill + Adom Bridge)++The STEP is always exported **on the design machine**, driven from the container through Adom Bridge. Everything below is what the export skill does for you when you say "export molecule ABC".++### KiCad (`kicad-export-molecule`)++1. Preflight: `adom-bridge ping`; `adom-bridge commands | grep kicad_`; kicad-cli is KiCad 10 (`C:\Program Files\KiCad\10.0\bin\kicad-cli.exe version`).+2. Export the STEP with the laptop CLI (models substituted from the laptop's libraries):+ ```+ kicad-cli pcb export step --subst-models --force -o ABC.step ABC.kicad_pcb+ ```+ Read the output: every `Could not add 3D model for MPn` line means a marker did not bake in. Fix the model path (KiCad resolves relative model paths against the board's directory, `${KICAD10_3DMODEL_DIR}` against the install) and export again.+3. Optional silk PNGs (top/bottom, white art on transparent).+4. Pull the bundle to the container: `adom-bridge pull_file {"filePaths":[...], "saveTo":"..."}` — `ABC.step`, `ABC.kicad_pcb`, `ABC.kicad_sch`, `ABC.kicad_pro`, silks.++Never use KiCad's own GLB export for a molecule: it bypasses anchoring, gold pins, normalization and the footprint emit. STEP in, OCCT makes the GLB.++### Fusion 360 Electronics (`fusion-export-molecule`)++1. `adom-bridge fusion_start` if Fusion is closed (blocks until the add-in is ready; the first `fusion_get_app_state` after that can take a minute).+2. Open the **board file directly** so the multi-design picker never appears:+ ```+ adom-bridge fusion_open_cloud_file {"projectName":"Main","folderPath":"COSMIIC","fileName":"PM COIL Molecule","fileExtension":"fbrd","recovery":"discard"}+ ```+ Find the design first with `fusion_mcp_call {"tool":"fusion_mcp_read","arguments":{"queryType":"document","operation":"search","name":"..."}}` (APS search needs a fresh sign-in; MCP search works with any open document).+3. Export sources: `fusion_export_eagle_source` for the `.brd`, switch with `fusion_electron_run {"command":"EDIT .s1"}`, export the `.sch`, switch back with `EDIT .brd`.+4. `fusion_show_3d_board`, then `fusion_export_step` (and `fusion_export_f3d` / `fusion_export_usdz` / silkscreen screenshots if you want the kitchen sink).+5. `pull_file` the bundle: `.brd`, `.sch`, `.step` (+ extras).++### Altium (`altium-export-molecule`)++Native STEP export with the machine-pin models baked in, board metadata derived for OCCT, then the same converter call as everyone else. The skill ends when the OCCT artifacts are on the container; it never packages or publishes.++Gate for all three: the bundle on the container has **STEP + board + schematic** (a molecule without its schematic is not reproducible and `molecule-publish` refuses it).++## Stage 2 — Convert: STEP → anchored GLB + footprint/symbol (`step2glb`)++One command, run on the container, does the whole OCCT molecule pipeline server-side:++```bash+step2glb convert ABC.step --board ABC.kicad_pcb --pin large -o <slug>.glb # .brd boards work too+```++The CLI uploads to the shared OCCT service (`https://step2glb-gmdoncpxdwx0.adom.cloud`, async `POST /convert` → `GET /jobs/{id}` → `/jobs/{id}/result`), and downloads `<slug>.glb`, `<slug>_footprint.json` and `<slug>_symbol.json` beside it. What the service does: MP-marker anchoring (Z-up, front-left machine pin at the origin, board-surface Z), canonical gold machine-pin material, optional silkscreen overlay, meter normalization, Draco compression, and footprint + symbol JSON with the **per-pad wire-attach Z** — the numbers Hydrogen's wire tool snaps to.++Gate on the printed stats before going any further:++| Stat | Must be | Otherwise |+|---|---|---|+| `molecule_anchored` | `true` | markers missing from the STEP; go back to Stage 1 |+| `footprint_applied` / `footprint_pins` | `true` / 4 | board parse failed; read the warnings |+| `contact_z` | 2.8–8.4 mm | wrong pin size or wrong marker models |+| `pin_size_source` | `markers` | `param` means the size fell back to `--pin` |+| `warnings` | none | every entry is actionable |++The GLB carries `asset.extras.adomMolecule` — durable provenance you can check on any downloaded copy (do not look for a `molecule_anchor` node; the optimizer flattens it by design).++## Stage 3 — Package (`molecule-publish`)++```+<slug>/+ package.json type "component", component.mpn, hero block, dependencies {}+ <slug>.glb the OCCT GLB, named EXACTLY <slug>.glb+ ABC.kicad_pcb | .brd board source+ ABC.kicad_sch | .sch schematic source+ ABC.step STEP (reproducibility)+ <slug>_footprint.json OCCT artifact (wire-attach Z)+ <slug>_symbol.json OCCT artifact+ README.md, screenshots/hero.png, [silk PNGs, .f3d, .usdz, gerbers, bom, cpl]+```++Rules that bite:++- **Name the GLB `<slug>.glb`.** The wiki auto-converts the STEP to a plain `<slug>.glb` at publish time and points `model_3d_path` at it; an anchored GLB with any other name is shadowed by the plain one and every import gets an unanchored model.+- The `component` block is what creates the page's component-metadata row; without it `model_3d_path` is never set and import fails with "no published GLB".+- Key the page by MPN, never by value. Do not ship a hand-made `page.json`.+- Component dependencies are enforced before publish: `python3 scripts/component_graph.py plan <board> --out component-plan.json` then `gate package.json --plan component-plan.json --expect-board <board> --resolve` (declared coverage + every dependency resolves to a real page). Missing component pages: Stage 2.6 auto-creates them.+- Stamp what you tested on: `python3 scripts/tested_with.py stamp package.json --family <model>`.+- Hero camera: `python3 scripts/hero_camera.py pose <slug>.glb --page page.json`.++## Stage 4 — Publish + verify (`adom-wiki`)++```bash+adom-wiki pkg publish [--org adom] # registry version+adom-wiki repo push <owner>/<slug> --files <every file above> -m "<name> molecule"+```++Two layers, both required: `pkg publish` registers the version (and generates `page.json`), `repo push` puts the files on the page. Verify before calling it done:++- `metadata.model_3d_path` on the page == `<slug>.glb`;+- the page's GLB is byte-identical to your gated conversion (`curl` it with your token, `cmp` against the local file) — this is the anchoring proof;+- the full set is present: GLB + STEP + schematic + board + footprint/symbol JSON.++Private pages are fine end to end; nothing in the chain needs the page public.++## Stage 5 — Render archive (`adom-nucleus --render-board`)++Run **after** the publish, every time (it stamps the archive with the version it reads from the published `package.json`):++```bash+adom-nucleus --render-board <owner>/<slug> # alias: adom-project-manager --render-board+```++It renders `render/pcb.svg`, `render/sheet-*.svg`, `render/board.glb`, content-hashes them and archives `render/<version>/` + `render/manifest.json` only when the content changed. Check `manifest.current == <version>` and `python3 scripts/render_parity.py render/board.glb <slug>.glb` (same mesh count, else the render dropped geometry). EAGLE/Fusion sources report "nothing rendered" and skip gracefully today.++## Stage 6 — Import into Hydrogen (`adom-molecule`)++```bash+adom-molecule import <owner>/<slug> --owner <your-user-or-org> [--name <name>]+```++What it does (1.1.10): reads the page owner-qualified with your container credential (private pages included), checks `model_3d_path` and that a footprint JSON or board file exists, downloads the GLB as a preflight, then POSTs `{wikiRef:"<owner>/<slug>", owner, name, includeSource:true}` to `https://hydrogen.adom.inc/api/molecules/import`. Hydrogen re-reads the page with the same credential, **reuses the wiki GLB verbatim** (no re-optimization, no silkscreen, no Blender), carries the sources, and attaches the footprint so the molecule lands with wire-attach points. Re-importing creates a new version of the same molecule.++Same thing from any script:++```bash+curl -X POST https://hydrogen.adom.inc/api/molecules/import \+ -H "X-Api-Key: $(cat /var/run/adom/api-key)" -H "Content-Type: application/json" \+ -d '{"wikiRef":"<owner>/<slug>","owner":"<you>","includeSource":true}'+```++Gate: the reply carries a `version` and no `warnings`; `adom-molecule list` shows the name under your owner; `https://hydrogen.adom.inc/<owner>/molecules/<name>` renders it.++## Stage 7 — Use it in Hydrogen++Open a repo's editor (`https://hydrogen.adom.inc/<owner>/<repo>/edit`), add a **3D Editor V2** tab, then:++1. **Browse and Load Molecule** → pick the owner → the molecule → Load → set the placement position → OK.+2. **More Objects tools → Add Wires** (tick *Draw Multiple Wires*) → hover a machine pin until the "Machine Pin: FL/BL/FR/BR" tooltip shows → click → click the second molecule's pin. The console logs `New contact-based wire created from <a> - Pin: X to <b> - Pin: Y`.+3. Save the layout.++The in-app **Optimize / Regenerate 3D model** button is retired (it pointed at a worker that no longer exists); optimization happens in Stage 2 and import reuses it.++## Regression: the e2e harness++`project/molecule-e2e/run-e2e.sh` on gallia republishes two private test molecules — `drew2/e2e-kicad-solonoid` (KiCad) and `drew2/e2e-fusion-pmcoil` (Fusion/EAGLE) — through the current stack every time a molecule-family package changes (cron, every 30 minutes, `check-and-run.sh`). Stages it gates: EDA export on the laptop (kicad-cli 10 / Fusion bridge), OCCT conversion stats, provenance stamp, `pkg publish` + `repo push`, wiki GLB checksum, APM render archive + manifest, and the private import into Hydrogen through `adom-molecule import`. `last-status.json` is the verdict; `e2e.log` is the trail.++## The one-sentence versions++- "Move molecule ABC from KiCad on my computer up to the wiki." → Stages 1–5.+- "Get molecule ABC into my Hydrogen account." → Stage 6.+- "Publish my molecule ABC and import it into my Hydrogen account." → Stages 1–6, each gated before the next.+- "Wire ABC to DEF in the 3D editor." → Stage 7.