← Commit history

Publish 2.6.2

barrett-land ·05b259a25c ·3mo ago ·parent 5b527fc
3 files changed +128−2
SKILL.md+126
@@ -23,6 +23,40 @@ 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@@ -44,6 +78,17 @@ 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@@ -177,3 +222,84 @@ 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.
package.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-lbr",-  "version": "2.6.1",+  "version": "2.6.2",   "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": {},
page.json+1−1
@@ -1,6 +1,6 @@ {   "slug": "adom-lbr",-  "version": "2.6.1",+  "version": "2.6.2",   "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": {},