Skill/SKILL.md

272 lines
13 KiB
Markdown

---
name: library-manager
description: >-
Manage Vecmocon's component library: extract parameters from a component datasheet PDF into
the per-typeid Excel template (125 type-IDs across 18 classes - resistors, capacitors,
diodes, transistors, ICs, connectors, sensors, etc.). The user gives a datasheet named
as its MPN plus the make. The skill checks Gitea for a duplicate MPN_make and hard-stops if
present, classifies the part to a typeid, confirms or updates that typeid's template
(per-typeid version, changelog, backfill), fills a per-part workbook, loops on human
verification, then takes the Altium symbol (.SchLib) and footprint (.PcbLib), fills the
Library/Footprint columns, assembles a part folder (xlsx, datasheet, symbol, footprint) and
pushes it to the components repo under its Class. Use WHENEVER the user uploads a component
datasheet, builds a library entry, adds a parameter to a type template, or pushes a part to
Gitea. ALWAYS trigger on "\datasheet", "\library", or "\library-manager", or any
component-library / datasheet-extraction task.
---
# Library Manager
Turn one component datasheet into a verified, versioned library entry in Gitea. The guiding
idea is honesty and traceability: every value lands in the right column and unit, anything
the datasheet doesn't state stays blank, and nothing reaches Gitea until a human has
confirmed it. This is an **interactive** skill — it asks at the few points where a person's
judgement or an upload is genuinely needed, and does everything else on its own.
## Inputs
- **A datasheet PDF whose filename is the MPN** (e.g. `BAT46WJ.pdf`). If it's a series
datasheet, search that exact MPN inside to read the correct variant.
- **The make** (manufacturer), given by the user. The `make` tag is the first word of the
manufacturer, alphanumerics only (Texas Instruments → `Texas`, Nexperia → `Nexperia`).
- **Later in the flow**, after verification: an Altium **symbol** (`.SchLib`) and
**footprint** (`.PcbLib`) file, provided by the user.
## The identifier: `MPN_make_typeid`
Every part folder, every per-part workbook, and column A of every sheet (`MPN_make_type`)
use the same tag:
```
<MPN>_<make>_<typeid> e.g. BAT46WJ_Nexperia_SCH
```
`typeid` is the part's type-ID code from the taxonomy (`references/taxonomy.md`, full source
`assets/template/Type_ID.xlsx`) — Schottky → `SCH`, MOSFET → `MOS`, LDO → `LDO`. In the new
template **each typeid is its own sheet** (125 of them). The broader **Class** (Diode,
Transistor, IC …) is used only to organise the components repo into top-level folders.
## Gitea layout (two repos)
```
skill repo/ this skill's own files (updated versions land here too)
components repo/
<Class>/ e.g. Diode, IC, Transistor, Resistor, ...
<MPN>_<make>_<typeid>/ e.g. BAT46WJ_Nexperia_SCH
<MPN>_<make>_<typeid>.xlsx this part's own one-row parameter sheet
<MPN>_data.pdf the datasheet
<symbol>.SchLib user-provided
<footprint>.PcbLib user-provided
```
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`, `COMPONENTS_REPO`), so runs
need no per-session token. If the host is unreachable, the git steps fail clearly and write
nothing.
## Workflow
Run these in order. Each `python`/`bash` command is a helper in `scripts/`.
### 1. Duplicate check first — before any real work
The part's presence is keyed on **MPN + make** (typeid not known yet). If it already exists,
stop; re-doing an existing part would only risk overwriting good data.
```bash
python scripts/gitea_components.py check-mpn --mpn <MPN> --make <make>
```
`EXISTS …` (exit 3) → **stop and tell the user the part is already present in Gitea. End
here.** `ABSENT` (exit 0) → continue.
### 2. Classify → typeid (and its Class)
Read the datasheet, identify the part, and match it to the closest subclass in
`references/taxonomy.md`; record its **typeid** (= the template sheet name). The **Class**
(for the components-repo folder) comes from the same taxonomy row —
`scripts/common.py:class_folder(typeid)` returns it (e.g. `SCH``Diode`).
### 3. Confirm the typeid's template (and add parameters if asked)
Check whether that typeid has a sheet in `assets/template/template.xlsx`.
- **No sheet for this typeid** → ask the user to upload the template sheet for it. Add it to
`assets/template/template.xlsx`, then push the updated skill files to the skill repo (see
*Pushing the skill repo*). Then continue.
- **Sheet exists** → print **all** of that sheet's parameters (its column headers) in the
chat and ask the user whether any new parameters should be added.
- **No** → go to step 4.
- **Yes** → collect the new parameter name(s), then:
```bash
python scripts/append_parameter.py --typeid <typeid> \
--param "New Parameter(unit)" [--param "Another(unit)"] \
--desc "why these were added"
```
This appends the column(s) at the end of that typeid's sheet, **bumps that typeid's
Template Version and Skill Version together** (v1→v2 — see *Per-typeid versioning*),
and writes one entry to the global changelog `assets/template/CHANGELOG.md`. Push the
updated `template.xlsx` + `versions.json` + `CHANGELOG.md` to the **skill** repo, and
make sure the components repo's copies stay consistent.
Then ask: **should this change apply to the parts of this typeid already in Gitea?**
- **No** → go to step 4 (only the current part gets the new column).
- **Yes → backfill** (see *Backfilling existing parts*), then tell the user the previous
sheets were updated, and go to step 4.
### 4. Extract and fill the per-part workbook
Read every parameter the datasheet actually states into that typeid's columns, converting to
each header's unit. **Leave blanks where the datasheet is silent — an honest blank beats a
guess.** Collect them into a small `part.json`:
```json
{"mpn":"BAT46WJ","manufacturer":"Nexperia","typeid":"SCH",
"values":{"Description":"100 V 250 mA Schottky, SOD323F","Forward Voltage(V)":"0.71",
"Reverse Voltage(V)":"100","Forward Current(A)":"0.25","Package":"SOD323F"}}
```
```bash
python scripts/fill_templates.py part.json \
--template assets/template/template.xlsx --dest <stage>/<tag>/
```
This writes `<tag>.xlsx` — just that typeid's sheet, one row — with column A = the tag,
**Skill Version (col B)** and **Template Version (col C)** stamped from this typeid's current
versions, and the four design columns left blank for now.
### 5. Human verification loop
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.
### 6. Symbol + footprint → the design columns
Once verified, ask the user to upload the **symbol (`.SchLib`)** and **footprint
(`.PcbLib`)** files. Copy them into the staging part folder **under their proper names** (so
the Path columns match the files that actually get stored — strip any upload-staging prefix
the environment may have added), then read all four design values in one shot:
```bash
cp <uploaded_symbol> <stage>/<tag>/<symbol_name>.SchLib
cp <uploaded_footprint> <stage>/<tag>/<footprint_name>.PcbLib
python scripts/altium_refs.py design \
--symbol <stage>/<tag>/<symbol_name>.SchLib \
--footprint <stage>/<tag>/<footprint_name>.PcbLib > design.json
```
This produces (verified against real Ultra-Librarian exports):
- **Library Ref** = the component name **inside** the `.SchLib` (e.g. `CGA3E3X7R1H474K080AE`)
- **Library Path** = the `.SchLib` file name
- **Footprint Ref** = the **base** pattern inside the `.PcbLib`; Altium ships IPC density
variants (`-L` / `-M` / `-N`) alongside the base, and the base is the one used (e.g.
`CAP_CGA3_TDK`, not `CAP_CGA3_TDK-L`)
- **Footprint Path** = the `.PcbLib` file name
These Ref names come from *inside* the files and can differ from the MPN or filename. If a Ref
comes back `null` (or a footprint shows several unrelated candidates), ask the user to confirm
the name from Altium's properties and edit `design.json`. Then re-fill so the columns land:
```bash
python scripts/fill_templates.py part.json \
--template assets/template/template.xlsx --dest <stage>/<tag>/ --design design.json
```
### 7. Assemble the part folder
The staging folder `<tag>/` should now hold the four files: the per-part `<tag>.xlsx`, the
datasheet (name it `<MPN>_data.<ext>`), the symbol, and the footprint.
### 8. Push to the components repo, under the part's Class
```bash
python scripts/gitea_components.py push-part --folder <stage>/<tag> --typeid <typeid>
```
This places the folder at `components/<Class>/<tag>/` — creating the Class folder if it
doesn't exist yet, or pushing into it if it does — and commits and pushes. Confirm to the
user where it landed.
## Per-typeid versioning
Versioning is **per typeid**, not global. Each typeid carries its own `template_version` and
`skill_version` in `assets/template/versions.json` (both start at 1). When a parameter is
added to a typeid, that typeid gets a new template, so its `template_version` bumps — and on
the back of that its `skill_version` bumps too (v1→v2). **Only that typeid moves**; every
other typeid keeps its versions. Those two numbers are exactly what `fill_templates` stamps
into that typeid's rows (cols B and C), so a row always records the template/skill version it
was built against. `append_parameter.py` does the bump; `common.py` is the single source for
reading and writing these numbers.
## The changelog
`append_parameter.py` maintains one **global** changelog at `assets/template/CHANGELOG.md`
(newest entry on top), recording for each change: date, typeid + class, the template and
skill version transitions, the parameter(s) added, and the description. Push it to the skill
repo alongside `template.xlsx` and `versions.json` whenever it changes.
## Backfilling existing parts
When the user wants a newly-added parameter applied to parts of that typeid already in Gitea:
```bash
python scripts/gitea_components.py checkout --dest work/
python scripts/gitea_components.py list-type --typeid <typeid> --root work/ --json
```
`list-type` lists every existing part of that typeid with the files in its folder — including
its datasheet, which is co-located. For each one: read that datasheet, re-extract the values
(including the new parameter), and rebuild its per-part sheet in place:
```bash
python scripts/fill_templates.py <that_part>.json \
--template assets/template/template.xlsx --dest work/<Class>/<that_tag>/
```
Because `fill_templates` uses the current template and current versions, each rebuilt sheet
picks up the new column and the bumped version automatically. When all are done, push once
and tell the user the previous sheets were updated:
```bash
python scripts/gitea_components.py commit-push --root work/ --message "backfill <param> into <typeid>"
```
## 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 — but **never push the real token**. Blank the `GIT_TOKEN` line in
the copy you push, or exclude `config/gitea.env`:
```bash
bash scripts/push_to_gitea.sh --repo "$SKILL_REPO" --src <skill-dir> --message "Sync skill files"
```
## 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.
- `assets/template/versions.json` — per-typeid `template_version` + `skill_version`.
- `assets/template/CHANGELOG.md` — global version/parameter changelog (created on first add).
- `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 `<tag>.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/gitea_components.py``check-mpn`, `checkout`, `list-type`, `place-part`,
`commit-push`, `push-part` against the components repo.
- `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` / `COMPONENTS_REPO` names
(**secret** — do not push the token).