← Commit history

Publish 2.7.0

Ray ·45cdc54d23 ·2mo ago ·parent 9796fe6
4 files changed +10−136
SKILL.md−126
@@ -23,40 +23,6 @@ adom-lbr generator / EDA translator. The **adom-lbr JSON** — Adom's own canoni  ("lbr" here = Adom Library / the adom-lbr JSON, not EAGLE's `.lbr` — that's just one output.) -## ⚡ Altium user? The reliable workflow — READ THIS FIRST--Helping someone add parts to their **real Altium** library? The native generators (`export-altium`,-`export-intlib`, `encode-sym`) have burned entire sessions producing symbols/footprints that render-**catastrophically wrong in Altium with NO error** — pins dropped or flung thousands of mils away,-footprints with copper pads and nothing else. **Prefer Altium-authored bytes over generation.** The-golden path — quick AND correct:--1. **Get genuine bytes; don't generate.**-   - **From a vendor `.IntLib` the user provides** — the reliable source. It's an OLE2 file whose-     `SchLib/0.schlib` + `PCBLib/0.pcblib` streams are **zlib-compressed at offset 1**-     (`zlib.decompress(data[1:])`) → real Altium `.SchLib`/`.PcbLib` that render perfectly. Extract and-     use them directly. (`adom-lbr import-altium foo.IntLib --mpn X` also ingests one.) This needs only-     Python `olefile`+`zlib` — no special binary — so it ALWAYS works.-   - **Many similar parts?** Have the user perfect ONE in Altium and save it, then byte-clone the rest-     (copy the component's `Data` stream verbatim, edit only the name/value/footprint text records).-   - **Footprints with real silk / fab / courtyard / 3D:** use genuine footprints from IntLibs. The-     pad generator writes copper ONLY (see the footprint reality-check below).-2. **Standard package → standard KiCad footprint** (SOT-223, 0402/0603/0805), never a ds2sf datasheet-   extraction (it mis-lays pads).-3. **Back up the user's file BEFORE overwriting it** (`pull_file` + keep a copy). Originals have been-   lost this way with no recovery.-4. **Deploy** with `adom-desktop send_files`, `dest` = the user's-   `C:\Users\<user>\Documents\Altium\Libraries\{Symbols,Footprints}\` folder. Verify by pulling it back-   and comparing sha256.-5. **Tell the user to RESTART Altium.** It caches file-based libraries and freezes already-placed parts;-   most "it's still broken/old" reports are stale caches. If the lib is open with unsaved edits (title-bar-   `*`), close WITHOUT saving — a Save clobbers your deployed file.-6. **Verify in Altium's Properties panel, not your own parser.** Reader and writer can agree with each-   other and both be wrong (a 79-mil pin read as 66,630 mil). Get this ground truth EARLY.--Everything below is detail. The two must-read deep sections: **"⚠️ Altium .SchLib symbols — READ FIRST"**-and the **footprint reality-check** callout.- ## Native Altium commands (both directions)  ```bash@@ -78,17 +44,6 @@ the footprint link. Value/Manufacturer/MPN/Package become Altium component property fields (Value drawn on the symbol; the rest hidden), and are read back out on import. -> ⚠️ **Reality check on the CLI (`altium-codec` binary) — verified 2026-07-13.** The neutral-> `Footprint` model is `{name, pads}` with **no graphics fields**, so `encode-fp` / `encode-fp-many`-> (and `import-kicad`, which drops `F.SilkS`/`F.Fab`/`F.CrtYd`) emit **copper pads ONLY** — no silk,-> fab, courtyard, keepout, or 3D. The "graphics carry across" claim above is the intended full-> pipeline, NOT what the CLI does today. If the user needs real footprint layers, **do not generate** —-> extract genuine full footprints from vendor `.IntLib`s (streams zlib-compressed at offset 1) and-> combine them with **`altium-codec merge-fp-libs <out.PcbLib> <spec.json>`** (spec = `[{pcblib,name}]`):-> it byte-copies each footprint's primitives (pads + tracks on Mech13 fab / Mech15 courtyard + text)-> **and** its embedded STEP model verbatim, renaming only the footprint so existing symbol links still-> resolve. Same clone-don't-generate rule as symbols (see the READ-FIRST symbol section below).- ### Footprint layer mapping (Altium)  Graphics carry a neutral layer role (`silk` / `courtyard` / `fab`), mapped on@@ -222,84 +177,3 @@ adom-lbr generate --sym <mpn>.kicad_sym → .lbr (for Fusion) adom-lbr lint suspicious.lbr # JSON output with error codes for programmatic handling ```--## ⚠️ Altium .SchLib symbols — READ FIRST (hard-won 2026-07-10..13)--The native Altium **symbol** encoder (`export-altium` / `encode-sym` / `add-to-schlib`)-has repeatedly produced symbols that render **catastrophically wrong in real Altium with-NO error** — pins dropped, or one pin shot thousands of mils off to the side — while the-bytes looked fine to our own parser. Over one session it needed *four* separate byte-level-fixes and was **still** wrong. So:--### RULE 0 — DON'T generate the symbol; CLONE a known-good one.-Whenever a symbol must render in the user's real Altium, do **not** trust the codec's pin-encoder. Instead reuse Altium-authored bytes:-- **From a vendor `.IntLib`** the user provides: it's an OLE2 file whose `SchLib/0.schlib`-  and `PCBLib/0.pcblib` streams are **zlib-compressed at offset 1** (`zlib.decompress(data[1:])`)-  → the real `.SchLib`/`.PcbLib`. Use those directly (Altium's own format = renders perfectly).-- **From one symbol the user fixes in Altium + saves:** then byte-clone it to the rest with-  **`altium-codec replace-clone <in.SchLib> <src_comp> <out.SchLib> <specs.json>`**-  (specs = `[{storage,libref,value,package,footprint,description}, …]`). It copies the source-  component's Data stream **verbatim** (pins + graphics untouched) and edits only the metadata-  text records. This is the reliable fix and mirrors the machine-pin flow (user fixes one, we-  clone). Only *generate* from scratch when nothing Altium-authored exists — and then VERIFY-  in Altium (RULE 1) before trusting it.--### RULE 1 — Verify in ALTIUM, never in your own parser.-Reader and writer can agree with each other and **both be wrong**. Ground truth = the-**Properties panel** (Pin Length / Location) on the actual pin. A "Pin Length" of tens of-thousands of mils = a byte bug. Get this ground truth EARLY instead of theorising for an hour.--### RULE 2 — Altium CACHES file-based libraries and FREEZES placed instances.-After you overwrite a `.SchLib`/`.PcbLib`, the user must **restart Altium** (or the library-panel serves the stale copy) and **delete any already-placed part** (placed instances don't-update). Tell them this up front — most "it still looks broken/old" reports this session were-stale caches, and they cost hours. Also: a title-bar `*` = unsaved edits; if you overwrite the-file while it's open and the user then Saves, they clobber your fix — tell them to close-WITHOUT saving, or restart.--### RULE 3 — Never call altium-bridge verbs with empty/partial args.-`altium_clone_symbol` / `altium_build_footprint` with `{}` **time out** and pop-`"value cannot be null"` / `"save file error"` dialogs inside the user's live Altium. Only-call bridge verbs with complete, correct payloads and an appropriate active doc.--### RULE 4 — Back up the user's original before overwriting it.-Pull + keep a copy first. This session the user's original SnapEDA symbol got overwritten with-a broken codec version and couldn't be recovered.--### Byte-level reference (only if you MUST generate — and still verify in Altium)-Binary pin record, calibrated vs genuine pins (STM32F072/ADS1220/caps). NOTE: even after all-of these the encoder was STILL wrong on negative X (Altium's own save writes byte `[19]=0xFF`-sign-extension; the codec writes `0x00` → giant pin), so **treat this as incomplete → clone**.-- `[14]` conglom (0x04).-- `[15:17]` **length field** — length in **bits 6-15** (unit 1/25.6 mil), orient in bits 0-1,-  and **bit 5 (0x20) is a REQUIRED flag**. Genuine low bytes are only ever `0x20/0x22/0x38/0x3a`,-  **never 0x00**. A round length + orient 0 (100 mil → 0x0A00, low byte 0x00) → GIANT pin.-  Encode: `field = (len & 0xFFC0) | 0x20 | orient`.-- **X and Y must be snapped to a 10-mil grid** (multiple of 256 internal units) or the low-  bytes bleed into neighbouring fields (off-grid X = the 66,630-mil pin). Exact X/Y widths are-  context-dependent and NOT fully nailed — clone instead.-- **Pins before graphics**; **arcs → tessellated RECORD=6 polylines** (a hand-rolled RECORD=12-  arc dropped the pin). **µ → ASCII** ("uF" not "µF" — codec writes UTF-8 → shows as "µ").-  **Zero-width KiCad polylines are dropped by import-kicad** (give leads a real width).-- The `altium-schlib` READER decodes Y at the wrong offset — don't trust it either.--### Non-symbol notes--> **Which binary?** `replace-clone` and `merge-fp-libs` currently live in the lower-level-> **`altium-codec`** dev crate (`/home/adom/project/altium-writer/altium-codec/`), not yet folded into-> the shipped `adom-lbr` binary — `cargo build --release` there, or fall back to the manual-> `olefile`+`zlib` extraction (golden-path step 1), which needs no special binary and always works.-> `adom-lbr` itself ships `import/export-altium`, `export-intlib`, `add-to-schlib`, `import-altium`.--- `encode-fp-many <[Footprint]> <out.PcbLib>` builds a multi-footprint PcbLib — but writes **copper-  pads ONLY** (no silk/fab/courtyard/keepout/3D; the model is `{name,pads}`). Pad *placement* is-  reliable; the footprint is just bare. For real layers use genuine footprints + `merge-fp-libs` (see-  the ⚠️ reality-check note up top).-- `merge-fp-libs <out.PcbLib> <spec.json>` (spec=`[{pcblib,name}]`) — merge N genuine single-footprint-  PcbLibs into one, renaming each. Copies every primitive + embedded STEP verbatim; source[0] supplies-  the shared `Library/*` boilerplate (all sources must be from the same converter). The way to get-  full-layer footprints into a user's library without generating them.-- Symbol model has a `description` field → RECORD=1 ComponentDescription.-- For a STANDARD package (SOT-223, 0402/0603/0805), use the **KiCad standard footprint**, not a-  ds2sf datasheet extraction — ds2sf mis-laid the SOT-223 pads.
bin/adom-lbr
⋯ 1 unchanged line ⋯
package.json+8−8
@@ -1,8 +1,8 @@ {   "slug": "adom-lbr",-  "version": "2.6.3",+  "version": "2.7.0",   "type": "app",-  "description": "adom-lbr — the EDA library translator. Bring a component in from any supported EDA tool and convert it to any other (KiCad ⇄ Altium ⇄ EAGLE/Fusion) through one canonical adom-lbr JSON — symbol + footprint + 3D + pin↔pad map. Altium is written natively (no Altium needed). Includes the adom-lbr Manager: browse wiki components and view symbol/footprint/3D + the per-EDA layer stackup.",+  "description": "adom-lbr \u2014 the EDA library translator. Bring a component in from any supported EDA tool and convert it to any other (KiCad \u21c4 Altium \u21c4 EAGLE/Fusion) through one canonical adom-lbr JSON \u2014 symbol + footprint + 3D + pin\u2194pad map. Altium is written natively (no Altium needed). Includes the adom-lbr Manager: browse wiki components and view symbol/footprint/3D + the per-EDA layer stackup.",   "dependencies": {},   "tags": [     "eda",@@ -19,7 +19,7 @@   "hero": {     "type": "billboard",     "headline": "One part, every EDA tool.",-    "subhead": "The adom-lbr JSON is the hub — convert it to native Altium, EAGLE/Fusion, or KiCad. Altium output is written natively, no Altium at conversion time.",+    "subhead": "The adom-lbr JSON is the hub \u2014 convert it to native Altium, EAGLE/Fusion, or KiCad. Altium output is written natively, no Altium at conversion time.",     "screenshot": "screenshots/shot.png",     "accent": "#00b8b1"   },@@ -52,15 +52,15 @@     "view footprint layer stackup",     "json to kicad"   ],-  "discovery_pitch": "Convert electronic-component symbols + footprints between any two EDA tools — KiCad, Altium (written natively, no Altium needed), and EAGLE/Fusion — through one canonical adom-lbr JSON, silk/courtyard/fab layers preserved. Plus a Manager to browse and inspect any wiki part.",+  "discovery_pitch": "Convert electronic-component symbols + footprints between any two EDA tools \u2014 KiCad, Altium (written natively, no Altium needed), and EAGLE/Fusion \u2014 through one canonical adom-lbr JSON, silk/courtyard/fab layers preserved. Plus a Manager to browse and inspect any wiki part.",   "sample_prompts": [     {       "prompt": "Convert this KiCad symbol and footprint to an Altium SchLib and PcbLib",-      "label": "KiCad → Altium"+      "label": "KiCad \u2192 Altium"     },     {       "prompt": "Import this Altium footprint into the adom-lbr JSON",-      "label": "Altium → JSON"+      "label": "Altium \u2192 JSON"     },     {       "prompt": "Bundle this part into a single Altium IntLib",@@ -68,11 +68,11 @@     },     {       "prompt": "Convert this Altium SchLib and PcbLib to a KiCad symbol and footprint",-      "label": "Altium → KiCad"+      "label": "Altium \u2192 KiCad"     },     {       "prompt": "Export this adom-lbr JSON to a KiCad .kicad_sym and .kicad_mod",-      "label": "JSON → KiCad"+      "label": "JSON \u2192 KiCad"     },     {       "prompt": "Open the adom-lbr Manager to browse wiki components and view the layer stackup",
page.json+2−2
@@ -1,6 +1,6 @@ {   "slug": "adom-lbr",-  "version": "2.6.3",+  "version": "2.7.0",   "type": "app",   "description": "adom-lbr — the EDA library translator. Bring a component in from any supported EDA tool and convert it to any other (KiCad ⇄ Altium ⇄ EAGLE/Fusion) through one canonical adom-lbr JSON — symbol + footprint + 3D + pin↔pad map. Altium is written natively (no Altium needed). Includes the adom-lbr Manager: browse wiki components and view symbol/footprint/3D + the per-EDA layer stackup.",   "dependencies": {},@@ -85,4 +85,4 @@       "label": "Browse parts"     }   ]-}+}\ No newline at end of file