diff --git a/SKILL.md b/SKILL.md old mode 100644 new mode 100755 index c3a72b6..f76b0a5 --- a/SKILL.md +++ b/SKILL.md @@ -2,16 +2,15 @@ name: library-manager description: >- Manage Vecmocon's component library. Extract parameters from a component datasheet PDF into the - per-typeid Excel template, check Gitea for a duplicate MPN_make, classify to a - typeid, update that typeid's template (versioning, changelog, backfill), fill a per-part - workbook, verify with a human, read the Altium symbol/footprint refs, and push a part folder to - Gitea. Can UPDATE an existing part instead of hard-stopping on a duplicate. WRITES the mandatory - SOP parameters (from the verified Excel) directly into the .SchLib symbol and COMPILES an Altium - integrated library (.IntLib) bundling symbol + footprint, so every part folder holds five files - (workbook, datasheet, .SchLib, .PcbLib, .IntLib). Every Description follows Vecmocon's strict - Altium Description Format. Use whenever the user uploads a datasheet, builds/updates a library - entry, adds a parameter, fills .SchLib parameters, builds an integrated library, or pushes to - Gitea. ALWAYS trigger on "\datasheet", "\library", "\library-manager", or "\schlib". + per-typeid Excel template. Checks Gitea for a duplicate MPN_make, classifies to a typeid, updates that typeid's template (versioning, changelog, backfill), fills + a per-part workbook with human verification, reads the Altium symbol/footprint refs, assembles + a part folder and pushes to Gitea. Can UPDATE an existing part instead of hard-stopping, and can + WRITE the mandatory SOP parameters directly into a .SchLib symbol while stripping Ultra-Librarian + defaults. On the .SchLib task it also fills that component's Excel (Description + all parameters) + and pushes the updated symbol to Gitea, no verification loop. Descriptions + follow Vecmocon's strict Altium Description Format. Use whenever the user uploads a datasheet, + builds/updates a library entry, adds a template parameter, fills/updates .SchLib parameters, or + pushes a part to Gitea. Always trigger on "\datasheet", "\library", "\library-manager", "\schlib". --- # Library Manager @@ -42,6 +41,16 @@ own, without asking for confirmation**. Never add a "shall I push?" step — jus the user where it landed. (You still flag a genuine symbol/footprint mismatch, because that's a correctness issue, not a push confirmation.) +**Symbol parameters are a second exception — stamp them without asking, every time.** This +holds in both directions. As a standalone task (the engineer hands over a `.SchLib`): fill that +component's Excel (Description + all parameters) and push the updated symbol automatically, +without pausing to confirm the values. And **inside the normal new-part flow**: once the symbol +is uploaded at step 6, stamp the SOP + sheet parameters onto it and strip the Ultra-Librarian +defaults as a matter of course — do **not** offer it as a follow-up, do **not** ask whether the +engineer wants it, and never push a part folder whose symbol still carries UL defaults. See +*Mandatory symbol parameters* for why this path skips the loop. Every other flow keeps the +normal interactive asks below. + ## Inputs - **A datasheet PDF whose filename is the MPN** (e.g. `BAT46WJ.pdf`). If it's a series @@ -75,16 +84,10 @@ library repo/ __/ e.g. BAT46WJ_Nexperia_SCH __.xlsx this part's own one-row parameter sheet _data.pdf the datasheet - .SchLib user-provided, with all parameters written in + .SchLib user-provided .PcbLib user-provided - .IntLib integrated library (symbol + footprint, compiled by the skill) ``` -**Every part folder holds five files** — the workbook, the datasheet, the `.SchLib` (with the -full parameter set written into it), the `.PcbLib`, and the compiled `.IntLib`. The `.SchLib` -parameter fill and the `.IntLib` build are **not optional** — they run on every part before the -push (see *Mandatory symbol parameters* and *Build the integrated library* below). - There is **no single master workbook** — each part carries its own sheet inside its folder. Connection + repo names live in `config/gitea.env` (`SKILL_REPO`, `LIBRARY_REPO`), so runs need no per-session token. If the host is unreachable, the git steps fail clearly and write @@ -257,7 +260,9 @@ The part workbook has up to **two sheets**: Deliver the filled workbook to the user and ask them to verify it. If they report an error or say it isn't right, **go back to step 4, re-read the datasheet more carefully, re-fill, and hand it back.** Repeat until the user confirms it's verified. Nothing is pushed until -this passes — the engineer is the ground truth for the numbers. +this passes — the engineer is the ground truth for the numbers. (The standalone `.SchLib` task +is the exception: it fills the Excel and pushes without this loop — see *Fill the component's +Excel and push* under *Mandatory symbol parameters*.) ### 6. Symbol + footprint → the design columns @@ -292,23 +297,33 @@ python scripts/fill_templates.py part.json \ --template assets/template/template.xlsx --dest // --design design.json ``` -Once you have the symbol and its Library Ref, **always** write the full parameter set into the -`.SchLib` from the verified per-part Excel — see *Mandatory symbol parameters* below. **This is -compulsory on every run; do not ask the engineer whether to do it — just do it.** It is how the -verified workbook values (and the Description) land in the Altium symbol's properties, and the -`.IntLib` is then built from this enriched symbol. +Once you have the symbol and its Library Ref, **stamp the mandatory symbol parameters onto the +`.SchLib` — always, automatically, without asking.** This is not an optional extra and it is not +something to offer the engineer: a symbol that reaches Gitea carrying Ultra-Librarian defaults +instead of the SOP set is an incomplete part. Do it in this same run, before step 7, so the +folder is pushed complete the first time. -### 7. Assemble the part folder — build the `.IntLib`, then five files +Build the parameter set from the datasheet values you already read for the workbook (they are the +same values — Manufacturer, Manufacturer Part, Value, Tolerance, Operating Temperature, RoHS, +Datasheet, Process, Vecmocon Part Code, …), **plus every engineering parameter from this typeid's +sheet** and `Component Type` = the part's Class, then write them in and strip the UL defaults — +see *Mandatory symbol parameters* below for the full set and the exact commands. Skip only the +housekeeping columns (`MPN_make_type`, Skill/Template Version) and the four Library/Footprint +Ref/Path columns — those are Altium's own model links, so duplicating them as parameters would +create two sources of truth. -The staging folder `/` should hold the per-part `.xlsx`, the datasheet (name it -`_data.`), the enriched symbol (`.SchLib` with parameters written in, step 6), and the -footprint (`.PcbLib`). Now **compile the integrated library** from the enriched symbol + footprint -so the folder carries all **five** files — see *Build the integrated library* below: +Don't stop to confirm the values here either; the engineer validates the symbol by opening it in +Altium, which is the real check. Leave genuinely-unknown fields blank (the SOP hides blank +parameters) and **note the gaps in your summary** rather than blocking on a question — the one +field that is never on a datasheet is `Vecmocon Part Code`, so use it if the engineer supplied it +and otherwise leave it blank and say so. -```bash -python scripts/build_intlib.py --schlib //.SchLib \ - --pcblib //.PcbLib --out //.IntLib -``` +### 7. Assemble the part folder + +The staging folder `/` should now hold the four files: the per-part `.xlsx`, the +datasheet (name it `_data.`), the symbol (the **stamped** one from step 6, not the raw +upload), and the footprint. If the engineer's upload carried extra files (a `.step` 3D model, a +`.LibPkg`), ask whether to include them — the standard folder is these four. ### 8. Push to the library repo, under the part's Class @@ -324,11 +339,10 @@ user where it landed. ## Mandatory symbol parameters (.SchLib) The SOP (§5) requires every schematic symbol to carry a fixed parameter set in its Altium -properties — `Manufacturer`, `Manufacturer Part`, `Value`, `Tolerance`, `Operating -Temperature`, `ROHS`, `Datasheet`, `Process`, `Vecmocon Part Code`, and the two second-source -fields — with the **Comment** set to the MPN. The skill stamps these onto the symbol from the -verified workbook. **This step is compulsory on every part build — never ask whether to fill the -`.SchLib` parameters; always do it** before assembling the folder and building the `.IntLib`. +properties — `Component Type`, `Manufacturer`, `Manufacturer Part`, `Value`, `Tolerance`, +`Operating Temperature`, `ROHS`, `Datasheet`, `Process`, `Vecmocon Part Code`, and the two +second-source fields — with the **Comment** set to the MPN. The skill can stamp these onto the +symbol from the datasheet. This runs **as its own task too**, not only inside new-part creation: whenever the user hands over one or more `.SchLib` files and wants their parameters filled/updated (e.g. "\schlib", "add @@ -337,9 +351,13 @@ build its `params.json`, and run `scripts/schlib_write.py` per file — same ste The skill writes these **directly into the `.SchLib` in pure Python** with `scripts/schlib_write.py` (it rebuilds the OLE around the enlarged `Data` stream, preserving -every other byte, and strips the Ultra-Librarian `Manufacturer_Name` / `Manufacturer_Part_Number` -defaults that duplicate the SOP fields). Three kinds of value: +every other byte, and strips the Ultra-Librarian defaults that shouldn't ship: `Manufacturer_Name` +/ `Manufacturer_Part_Number` (they duplicate the SOP fields), the UL `Copyright` notice, and the +UL `Component_Type` — replaced by Vecmocon's own spaced `Component Type`). Kinds of value: +- **Derived** — `Component Type` = the part's **Class** (`Resistor`, `Capacitor`, `Diode`, + `Transistor`, `IC`, …), from `scripts/common.py:class_folder(typeid)` for this part's typeid. + This is the same Class that names its library-repo folder, so the symbol carries it too. - **Read from the datasheet** (don't just echo given text — open the PDF and fill the real, verified values): `Value` = the **value only** in shorthand (e.g. `1u`, `12p`, `10k` — no package), plus `Manufacturer`, `Manufacturer Part`, `Operating Temperature`, `Tolerance`, @@ -348,40 +366,21 @@ defaults that duplicate the SOP fields). Three kinds of value: populate these by default; they stay hidden in Altium until filled later. (An optional cross-reference search to find a second source is documented in `references/schlib_parameters.md` but is currently off — only do it if the engineer asks.) -- **Ask the engineer** — only `Vecmocon Part Code` (internal, not derivable). +- **Fill without pausing** — the `.SchLib` task is non-interactive, so don't stop to ask. The + only genuinely non-derivable field is `Vecmocon Part Code` (internal): use it if the engineer + already supplied it in the request, otherwise leave it blank (the SOP hides blank parameters) + and note the gap in your summary rather than blocking on a question. Leave any genuinely-unknown field blank — the SOP hides blank parameters, so a gap simply stays empty until filled. The full method for the second-source search is in `references/schlib_parameters.md`. -Write the **full parameter set** — the typeid template's engineering columns **plus** the SOP -params above (see `references/schlib_parameters.md`) — and **source it from the verified per-part -Excel** so the symbol and the workbook can never disagree. After the sheet is verified (step 5), -pass that `.xlsx` to the writer with `--from-xlsx`: every engineering column **and the -Description** are read straight out of it and written into the `.SchLib`. Then layer on the -**SOP-only** fields that aren't template columns (the `Value` shorthand, `Manufacturer Part`, -`Operating Temperature`, `ROHS`, `Datasheet`, `Process`, `Vecmocon Part Code`, and the blank -second-source pair) via a small `params.json`; on any name collision the `params.json` value -wins. Pass `--typeid` too, so any template column the datasheet left silent is still present -(blank): +Collect the values into a `params.json` and write them into the symbol: ```bash -python scripts/schlib_write.py --schlib .SchLib \ - --from-xlsx //.xlsx --params params.json \ - --out //.SchLib --typeid +python scripts/schlib_write.py --schlib .SchLib --params params.json --out //.SchLib ``` -(`--params` is optional if the Excel already carries everything you need; `--from-xlsx` is -optional if you'd rather hand-build the whole set in `params.json` — give at least one.) The -`Description` written onto the symbol (and into the component's ComponentDescription field) is -the exact one from the Excel, which was built to `references/description_format.md`. - -Passing `--typeid` also fills the symbol's **`Type`** parameter with the component type for that -typeid — the taxonomy **Class** (e.g. `Resistor`, `Capacitor`, `Diode`, `Transistor`, -`Relay / Contactor`, `Inductor / Magnetics`, `Integrated Circuit (IC)`) — so the symbol -self-describes what kind of part it is. It's derived from the typeid (which came from the -datasheet), so it's set automatically; only an explicit `Type` in the Excel/params overrides it. - Deliver the resulting `.SchLib`; the engineer opens it in Altium once to confirm it loads, then **Saves to Server** with a revision note. The full parameter set, each value's source, the `params.json` shape (incl. the `remove` list), and the mini-stream size caveat are in @@ -390,39 +389,54 @@ round-trip, fall back to `scripts/altium_params.py` (emits an Altium DXP script parameters from inside Altium). Always have the engineer confirm the file opens in Altium — the skill writes Altium's own binary format, so Altium is the final validator. -## Build the integrated library (.IntLib) +### Fill the component's Excel and push — automatically, no verification loop -Every part also gets a compiled **integrated library** — one file that bundles the schematic -symbol (with the parameters written in) and its footprint, so the component resolves in Altium -with no separate `.PcbLib` to locate. `scripts/build_intlib.py` compiles it in pure Python, no -Altium needed, and it's the **fifth file** in every part folder. +The datasheet values you just read for the symbol belong in that component's per-part Excel +workbook too, so fill them in the **same pass and push the result without asking**. This is a +deliberate exception to the skill's usual "verify before Gitea" rule: when the engineer hands +over a symbol for the `.SchLib` task, they want the library entry brought fully up to date in +one shot — the Description and every parameter written into the Excel, the updated symbol saved +beside it, and the whole thing pushed — not a round of confirmation questions. The engineer is +already reviewing the symbol in Altium, so a separate spreadsheet verification loop adds delay +without adding safety. The one check that still stands is the symbol/footprint-vs-part match: if +the symbol clearly isn't this component, stop and flag it rather than pushing the wrong part. -```bash -python scripts/build_intlib.py --schlib //.SchLib \ - --pcblib //.PcbLib --out //.IntLib -``` +1. **Fill the Excel automatically.** Reuse the values you already read for the symbol to build + `part.json` — with `Description` built to `references/description_format.md` and every + parameter the datasheet states — and fill the per-part sheet **directly, skipping the human + verification loop (step 5)**. Do this inside a checkout of the library repo so it can be + pushed; for a part already in Gitea, locate it with `find-part` exactly as in *Updating an + existing part*, and re-derive the design columns from the symbol/footprint already in the + folder so they carry through unchanged: -How it works and what it needs: + ```bash + python scripts/gitea_components.py checkout --dest work/ + python scripts/gitea_components.py find-part --mpn --make --root work/ --json + python scripts/altium_refs.py design \ + --symbol work///.SchLib \ + --footprint work///.PcbLib > design.json + python scripts/fill_templates.py part.json \ + --template assets/template/template.xlsx --dest work/// --design design.json + ``` -- Feed it the **enriched `.SchLib`** (after `schlib_write.py` has written the parameters in) so the - integrated symbol carries the full parameter set and the correct ComponentDescription. -- The symbol **must contain a footprint model link** (an Altium RECORD=45 `ModelName` / - `ModelType=PCBLIB` in its `Data` stream — Ultra-Librarian and Altium exports include this). The - builder reads that link to know which footprint to bind, and errors clearly if it's absent — in - that case the symbol has no footprint assigned, so fix the symbol (or re-export it) first. -- It builds the `.IntLib` as an OLE compound file with five streams — the embedded `.schlib` and - `.pcblib` (zlib-compressed at Altium's default level), plus `LibCrossRef.Txt`, `Parameters .bin`, - and `Version.Txt` — reusing a bundled container skeleton - (`assets/templates/intlib_container.IntLib`) for the exact directory layout Altium expects, and a - **FAT-first** compound-file writer (`build_intlib.write_cfb`). Both the outer container and the - embedded symbol are written FAT-first — this matters: a FAT-last layout re-opens fine in olefile - and even standalone in Altium, but Altium's **IntLib extractor** throws "Stream read error" on it. - The two embedded libraries are compressed at zlib's **default level** (`0x789c`); Altium's - decompressor rejects other levels (e.g. level-9 `0x78da`). -- The builder self-validates: it re-opens the output, decompresses both embedded libraries, and - confirms they round-trip and that the cross-reference names the symbol + footprint. Even so, - Altium is the final validator — have the engineer open the `.IntLib` once (or, as a guaranteed - fallback, compile a `.LibPkg` in Altium from the same `.SchLib` + `.PcbLib`). + (If `find-part` returns `NOT FOUND`, the part isn't in Gitea yet — assemble the folder as a + new part per steps 4–7, still without the verification loop, then push with `push-part`.) + +2. **Drop in the updated symbol and push — no confirmation.** Copy the `.SchLib` you wrote with + `schlib_write.py` into the same part folder under its proper name, then push the updated part + — the symbol and the freshly filled Excel together — automatically: + + ```bash + cp //.SchLib work///.SchLib + python scripts/gitea_components.py commit-push --root work/ \ + --message "update : fill parameters + symbol (by )" \ + --author " <>" + ``` + + Pushing without asking is consistent with the skill's standing rule that pushing is automatic; + what's new here is that the Excel fill is automatic too. Tell the user which parameters you + filled, that the symbol was updated, and where in Gitea it landed. (A part-data fill isn't a + template change, so nothing version-bumps and the changelog is untouched.) ## Per-typeid versioning @@ -533,81 +547,4 @@ change: nothing is overwritten until the engineer has verified the new version. - **Symbol/footprint** → copy the new `.SchLib`/`.PcbLib` into the folder under their proper names (replacing the old ones), then re-derive against the **new** files and rebuild with `--design` exactly as above (this is step 6 of the add flow). Still flag a genuine - symbol/footprint-vs-part mismatch — that's a correctness issue. - - **Datasheet** → drop the newer PDF in as `_data.`, replacing the old one. If the - values should reflect it, also redo the values step above. - -4. **Verify, then push.** Hand the rebuilt `.xlsx` back and run the same human - verification loop (step 5) — the engineer is still the ground truth. Once confirmed, commit - the checkout and push (attributed to the operator, with a message that says it's an update): - - ```bash - python scripts/gitea_components.py commit-push --root work/ \ - --message "update : (by )" \ - --author " <>" - ``` - - The authored commit and message are the record of the revision (visible in `git log`, the - Gitea commit view and `git blame`); the changelog stays reserved for template/version - changes, not per-part data fixes. Tell the user what changed and where it landed. - -## Pushing the skill repo - -When skill files change (a new typeid template, a parameter add, a version/changelog bump), -push the skill's own files to the skill repo with `push-skill` **automatically** (no -confirmation): - -```bash -python scripts/gitea_components.py push-skill --author " <>" \ - --message "Sync skill files + changelog" -``` - -`push-skill` clones the skill repo, copies the skill files in with the **`GIT_TOKEN` blanked -out** (the real token never leaves the machine), and **merges** `CHANGELOG.xlsx` — appending -this run's new rows onto the changelog already in Gitea so earlier entries are preserved — then -writes the merged changelog back locally. (The older `push_to_gitea.sh` still exists for a -plain flat push, but it does not merge the changelog or blank the token, so prefer -`push-skill` for the skill repo.) - -## Resources - -- `assets/template/template.xlsx` — the master template: one sheet per **typeid** (125), - source of every sheet's headers, styling and order. Columns A/B/C are always - `MPN_make_type` / `Skill Version` / `Template Version`; `Library Ref/Path`, - `Footprint Ref/Path` and `Manufacturer` sit near the end. -- `assets/template/Type_ID.xlsx` + `references/taxonomy.md` — Class → Subclass → Type ID. -- `references/description_format.md` — Vecmocon's Altium **Description Format** (the `_`-joined - engineering string for each part's Description column). Defines a format for **every** type: - the four SOP-defined ones (RES/CAP/Zener/TVS) are strict, the rest are the house extension on - the same basis. Read it before filling any Description. -- `references/schlib_parameters.md` — the SOP **mandatory symbol parameters** (§5) for the - `.SchLib`: the parameter set, where each value comes from, and how the generated Altium script - stamps them onto the symbol. -- `assets/template/versions.json` — per-typeid `template_version` + `skill_version`. -- `assets/CHANGELOG.xlsx` — global version/parameter changelog (created on first add; - merged into the skill repo's copy in Gitea by `push-skill`). -- `scripts/common.py` — taxonomy loader (`load_taxonomy`, `class_folder`), version store - (`get_versions`, `version_labels`, `bump_versions`), and the tag helper (`part_tag`). -- `scripts/fill_templates.py` — build one per-part `.xlsx` (version-stamped); reused for - backfill. -- `scripts/append_parameter.py` — append parameter(s) to a typeid, bump its versions, write - the changelog. -- `scripts/altium_refs.py` — read Library/Footprint Ref from `.SchLib`/`.PcbLib`. -- `scripts/schlib_write.py` — write the SOP mandatory parameters **directly into a `.SchLib`** - (pure-Python OLE rebuild; removes the Ultra-Librarian `Manufacturer_Name` / - `Manufacturer_Part_Number` defaults). Primary path; see `references/schlib_parameters.md`. -- `scripts/altium_params.py` — fallback: generate an Altium DelphiScript that stamps the same - parameters onto a `.SchLib` from inside Altium (DXP → Run Script). -- `scripts/build_intlib.py` — compile a component's `.SchLib` + `.PcbLib` into an Altium - **integrated library** (`.IntLib`) in pure Python (FAT-first OLE writer + Altium-level zlib); - the fifth file in every part folder. Needs the enriched `.SchLib` (parameters written) with a - footprint model link. Uses `assets/templates/intlib_container.IntLib` as the container skeleton. -- `assets/templates/intlib_container.IntLib` — a known-good single-component `.IntLib` reused - purely as the OLE container skeleton by `build_intlib.py` (all its streams are overwritten). -- `scripts/gitea_components.py` — `check-mpn`, `find-part` (locate an existing part to - update), `checkout`, `list-type`, `place-part`, `commit-push`, `push-part` (library repo), - and `push-skill` (skill repo: token-blanked push + append-only changelog merge). -- `scripts/push_to_gitea.sh` — push a folder's contents to a Gitea repo (used for the skill - repo). -- `config/gitea.env` — host, user, token, and the `SKILL_REPO` / `LIBRARY_REPO` names - (**secret** — do not push the token). + symbol/footprint-vs-part misma \ No newline at end of file diff --git a/assets/CHANGELOG.xlsx b/assets/CHANGELOG.xlsx index 822d231..16a0459 100644 Binary files a/assets/CHANGELOG.xlsx and b/assets/CHANGELOG.xlsx differ diff --git a/assets/template/Type_ID.xlsx b/assets/template/Type_ID.xlsx old mode 100644 new mode 100755 diff --git a/assets/vecmocon-logo.png b/assets/vecmocon-logo.png old mode 100644 new mode 100755 diff --git a/references/description_format.md b/references/description_format.md old mode 100644 new mode 100755 diff --git a/references/schlib_parameters.md b/references/schlib_parameters.md old mode 100644 new mode 100755 index b84b496..d6a1b5e --- a/references/schlib_parameters.md +++ b/references/schlib_parameters.md @@ -9,7 +9,9 @@ How the parameters get in: the skill writes them **directly into the `.SchLib` i via `scripts/schlib_write.py` — it rebuilds the OLE compound file around the enlarged component `Data` stream while preserving every other byte (all other streams, the directory tree, the Altium CLSIDs). It also **removes the Ultra-Librarian default params `Manufacturer_Name` and -`Manufacturer_Part_Number`**, which just duplicate the SOP `Manufacturer` / `Manufacturer Part`. +`Manufacturer_Part_Number`** (which duplicate the SOP `Manufacturer` / `Manufacturer Part`), the +UL **`Copyright`** notice (Vecmocon symbols don't carry it), and the UL **`Component_Type`** +(underscore) — replaced by Vecmocon's own spaced **`Component Type`** parameter (see below). The output is a ready `.SchLib`. Because this writes Altium's own format from outside Altium, the script self-checks that the result re-opens as a valid OLE with the params present — but **always open the result in Altium once to confirm it loads** before relying on it. (An older path, @@ -20,10 +22,24 @@ inside Altium; keep it as a fallback if a particular file doesn't round-trip.) Use these exact Altium parameter names (they must match the symbol, per the SOP screenshot). The **Comment** field is set to the MPN (SOP §4), and the **Description** field is the strict -string from `references/description_format.md`. +string from `references/description_format.md` — which **overwrites** whatever prose Ultra +Librarian put in `Description` (UL's text is often wrong: a real 6N137 export read +`SMD-8 CPLR SNGL 10MBD 100V/us -e3` when the datasheet CMR is 1000 V/µs). + +Beyond this SOP set, also stamp on **every engineering parameter from the part's typeid sheet** +(for an `ISO`: Isolator Type, Isolation Voltage, No. of Channels, Data Rate, Supply Voltage, +Creepage, Package, Power, Max Output Current). Skip the housekeeping columns (`MPN_make_type`, +Skill/Template Version) and the four Library/Footprint Ref/Path columns — Altium already holds +those as the symbol's model links, so repeating them as parameters makes two sources of truth. + +**Encoding gotcha:** Altium parameter records are **latin-1**, so a value containing `≥`, `≤`, +`±`-beyond-latin1, `µ` (U+00B5 is fine, U+03BC is not) or similar will crash `schlib_write.py` +with a `UnicodeEncodeError`. Rephrase into latin-1 (`≥ 7 mm` → `7 mm min.`) rather than dropping +the value; `°` (U+00B0) is latin-1 and safe. The workbook keeps the original notation. | Parameter | Source | Notes | |-----------|--------|-------| +| `Component Type` | derived | the part's **Class** — `Resistor`, `Capacitor`, `Diode`, `Transistor`, `IC`, … — from the taxonomy row for its typeid (`scripts/common.py:class_folder(typeid)`) | | `Value` | datasheet | the component **value only** (no package), in shorthand — e.g. `1u`, `12p`, `100n`, `10k` | | `Manufacturer Part` | datasheet | the MPN; also the **Comment** field | | `Manufacturer` | datasheet | manufacturer name as printed, e.g. `YAGEO` | @@ -41,7 +57,9 @@ handed to you.** Open the PDF, find each real value (`Value`, `Manufacturer Part `Manufacturer`, `Operating Temperature`, `Tolerance`, `Datasheet`, `ROHS`, and `Process` by inference from the package), and fill them verified. An honest blank beats a guess — the SOP hides blank parameters, so a gap just stays empty until someone fills it. Only **one** field is -purely internal and must come from the engineer: `Vecmocon Part Code` — ask for it. +purely internal and is never on a datasheet: `Vecmocon Part Code`. Use it if the engineer already +supplied it; otherwise **leave it blank and note the gap in your summary — don't stop to ask**. +Stamping the symbol is automatic and non-interactive (SKILL.md, step 6), so no field blocks it. The second-source pair (`Manufacturer 2` / `Manufacturer Part 2`) is **left blank for now** — don't populate it by default. It simply stays hidden in Altium until someone fills it later. @@ -78,6 +96,7 @@ symbol's Library Ref (from `altium_refs.py`); omit it to apply to every componen "component": "CC0402FRNPO9BN120", "comment": "CC0402FRNPO9BN120", "parameters": { + "Component Type": "Capacitor", "Value": "12pF_0402", "Manufacturer Part": "CC0402FRNPO9BN120", "Manufacturer": "YAGEO", @@ -93,41 +112,22 @@ symbol's Library Ref (from `altium_refs.py`); omit it to apply to every componen } ``` -## The full parameter set (template + SOP) - -Every `.SchLib` should carry the **complete** parameter set for its part: the **typeid -template's engineering columns** (all columns of that typeid's `template.xlsx` sheet except the -internal bookkeeping ones — the tag `MPN_make_type`, `Skill Version`, `Template Version`, and the -four `Library/Footprint Ref/Path` columns) **plus** the mandatory SOP params above. So a CER -(ceramic MLCC) symbol gets `Capacitance(uF)`, `Tolerance`, `Voltage(V)`, -`Dielectric(temp. Coefficient)`, `Operating Temp(°C)`, `Max operating temp(°C)`, `Package`, -`Description`, `Manufacturer` from the template, alongside `Value`, `Manufacturer Part`, -`Process`, `Vecmocon Part Code`, `ROHS`, `Datasheet`, and the second-source fields. Fill each -from the datasheet; leave blank what the datasheet doesn't state. - ## Writing them into the symbol -Write the parameters straight into the `.SchLib`, producing a new file. Pass `--typeid` so the -writer guarantees the whole template column set is present (blank where you didn't supply a -value) — this is what keeps every symbol's parameter set complete and consistent: +Write the parameters straight into the `.SchLib`, producing a new file: ```bash -python scripts/schlib_write.py --schlib .SchLib --params params.json --out .SchLib --typeid +python scripts/schlib_write.py --schlib .SchLib --params params.json --out .SchLib ``` -`params.json` carries your filled values (and may include a `"remove"` list — defaults to -`["Manufacturer_Name", "Manufacturer_Part_Number"]`, the Ultra-Librarian duplicates that get -stripped). The script targets the component named in `"component"` (its Library Ref / storage -name), or every component if omitted, and self-checks the output re-opens as a valid OLE. It -handles any parameter-set size — small sets stay in Altium's mini-stream, larger ones are written -as a regular stream automatically. Deliver the resulting `.SchLib`; have the engineer open it in -Altium once to confirm it loads, then Save to Server with a revision note per the SOP. +`params.json` may carry a `"remove"` list (defaults to `["Manufacturer_Name", +"Manufacturer_Part_Number", "Copyright", "Component_Type"]`); those Ultra-Librarian defaults are +stripped and the SOP params — including the spaced `Component Type` = Class — added. Real UL +exports also ship **placeholder** params whose Text is just the name back again (`Type` = `Type`, +`RefDes` = `RefDes`, sometimes `TYPE`); add those to `remove` too — they're noise, not data. After +writing, grep the output for `Ultra Librarian` / `Manufacturer_Name` and confirm the count is 0. The script targets the component named in `"component"` (its Library Ref / storage name), +or every component if omitted, and self-checks the output re-opens as a valid OLE. Deliver the +resulting `.SchLib`, and have the engineer open it in Altium once to confirm it loads, then Save +to Server with a revision note per the SOP. -Fallback (apply from inside Altium): - -```bash -python scripts/altium_params.py script --params params.json --out apply_params.pas -``` - -Then in Altium: open the `.SchLib`, **DXP → Run Script… → ApplyParameters**, review, **Save to -Server**. +Scope note: the d \ No newline at end of file diff --git a/references/taxonomy.md b/references/taxonomy.md old mode 100644 new mode 100755 diff --git a/scripts/altium_params.py b/scripts/altium_params.py old mode 100644 new mode 100755 diff --git a/scripts/altium_refs.py b/scripts/altium_refs.py old mode 100644 new mode 100755 diff --git a/scripts/append_parameter.py b/scripts/append_parameter.py old mode 100644 new mode 100755 diff --git a/scripts/common.py b/scripts/common.py old mode 100644 new mode 100755 diff --git a/scripts/fill_templates.py b/scripts/fill_templates.py old mode 100644 new mode 100755 diff --git a/scripts/gitea_components.py b/scripts/gitea_components.py old mode 100644 new mode 100755 diff --git a/scripts/push_to_gitea.sh b/scripts/push_to_gitea.sh old mode 100644 new mode 100755 diff --git a/scripts/schlib_write.py b/scripts/schlib_write.py old mode 100644 new mode 100755 index d33937c..cc4288a --- a/scripts/schlib_write.py +++ b/scripts/schlib_write.py @@ -12,39 +12,33 @@ move are recomputed. What it does to the target component's Data stream: - removes the Ultra-Librarian default params ``Manufacturer_Name`` / ``Manufacturer_Part_Number`` - (they duplicate the SOP ``Manufacturer`` / ``Manufacturer Part`` — override with --keep or a - "remove" list in params.json), + (they duplicate the SOP ``Manufacturer`` / ``Manufacturer Part``), the UL ``Copyright`` notice, + and the UL ``Component_Type`` (Vecmocon adds its own spaced ``Component Type`` = Class instead); + override this default set with a "remove" list in params.json, - adds/updates the SOP parameters from params.json (see references/schlib_parameters.md), - leaves pins, graphics, the Comment and all other records exactly as they were. Usage: - # source parameters + Description from the verified per-part workbook (preferred): - python schlib_write.py --schlib IN.SchLib --from-xlsx .xlsx \ - [--params sop.json] --typeid ELE --out OUT.SchLib - # or from a params.json alone: python schlib_write.py --schlib IN.SchLib --params params.json --out OUT.SchLib ---from-xlsx reads the filled per-part `.xlsx` (the same workbook the engineer verified) and -writes every engineering column + the Description into the symbol, so the .SchLib and the sheet -never diverge. --params then layers on the SOP-only fields that aren't template columns -(Value shorthand, Process, ROHS, Datasheet, Manufacturer Part, Vecmocon Part Code, ...); on a -name collision the params.json value wins. Give either or both (at least one). - params.json (same shape altium_params.py uses): {"component":"JMK105BJ105KV-F", # LibRef / component-storage name; omit -> all comps - "parameters":{"Value":"1u","Manufacturer":"Taiyo Yuden", ...}, - "remove":["Manufacturer_Name","Manufacturer_Part_Number"]} # optional; this is the default + "parameters":{"Value":"1u","Manufacturer":"Taiyo Yuden","Component Type":"Capacitor", ...}, + "remove":["Manufacturer_Name","Manufacturer_Part_Number","Copyright","Component_Type"]} # optional; default IMPORTANT: this writes Altium's own binary format from outside Altium. It is validated to re-open as a well-formed OLE with every other stream byte-identical, but ALWAYS open the result in Altium once to confirm it loads before relying on it. """ -import argparse, json, os, struct, sys, hashlib +import argparse, json, struct, sys, hashlib import olefile FREESECT=0xFFFFFFFF; ENDOFCHAIN=0xFFFFFFFE; FATSECT=0xFFFFFFFD SEC=512; MINI=64; CUTOFF=4096 -DEFAULT_REMOVE=["Manufacturer_Name", "Manufacturer_Part_Number"] +# Ultra-Librarian defaults we strip: the two that duplicate the SOP Manufacturer / Manufacturer +# Part, the UL "Copyright" notice (Vecmocon symbols don't carry it), and the UL "Component_Type" +# (underscore) — Vecmocon adds its own spaced "Component Type" = the part's Class instead. +DEFAULT_REMOVE=["Manufacturer_Name", "Manufacturer_Part_Number", "Copyright", "Component_Type"] def le16(b,o): return struct.unpack('.xlsx`) — row 1 is the - headers, row 2 is the single data row this skill writes. Returns {header: value} for every - engineering column (i.e. NOT the bookkeeping/design columns in NON_PARAM_COLS), INCLUDING the - Description column. This is what lets the .SchLib carry exactly the parameters + Description - the engineer already verified in Excel — the two never diverge. Blank cells stay blank. - - By default it reads the first sheet (the typeid parameter sheet). A `Version History` second - sheet, if present, is skipped.""" - import openpyxl - wb = openpyxl.load_workbook(xlsx_path, read_only=True, data_only=True) - ws = wb[sheet] if sheet else wb[wb.sheetnames[0]] - headers = [ws.cell(1, c).value for c in range(1, ws.max_column + 1)] - values = [ws.cell(2, c).value for c in range(1, ws.max_column + 1)] - out = {} - for h, v in zip(headers, values): - if not h or h in NON_PARAM_COLS: - continue - out[str(h)] = "" if v is None else str(v) - return out - - # ----------------------------------------------------------------- read the container def read_container(path): @@ -159,7 +97,7 @@ def _uid(name): def _param_record(idx, name, value): s=(f"|RECORD=41|IndexInSheet={idx}|OwnerPartId=1|Justification=4|FontID=2|IsHidden=T" f"|Text={value}|Name={name}|UniqueID={_uid(name)}") - payload=s.encode('utf-8')+b'\x00' # utf-8: handles Ω, µ, °, ± in names/values + payload=s.encode('latin-1')+b'\x00' return struct.pack('