Skill/SKILL.md

271 lines
15 KiB
Markdown

---
name: datasheet-extractor
description: >-
Extract key parameters from component datasheet PDFs into the Vecmocon master
template (18 component types incl. resistors, capacitors, inductors, diodes,
transistors, ICs, protection, power modules, connectors, sensors, and more).
Column A = MPN_make_typeid (make = first word of manufacturer, typeid from the
taxonomy). Writes ONE master workbook (Components_Master.xlsx) with sheets only for the
types whose datasheets were provided, plus a Meta sheet at the end (template version,
total components, date, time), assembles
a per-part DFS folder (datasheet, Altium footprint, Altium symbol), and pushes
design files to the Gitea DFS repo, Excel outputs to the Parameters repo, and skill
files plus templates to the Skill_Assets repo. Also appends new parameters to a
template as a new version. Use WHENEVER the user uploads component datasheets and
asks to extract parameters, build the parameter sheets or component library, or push
datasheets to Gitea. ALWAYS trigger when the user types "\datasheet".
---
# Datasheet Extractor
Read component datasheets, fill the customer's master template, assemble each part's
design-file folder, and publish everything to three Gitea repos. Be careful and honest:
put every value in the right column and unit, and flag what a datasheet does not state.
**Pushing is the default.** At the end of a run, push every output to Gitea without asking
for confirmation — that's the whole job. Only pause when there's a genuine need for the
user: a **login wall** while fetching a footprint/symbol, or an **MPN that already exists**
in Gitea (discard vs replace, because replace overwrites data). Nothing else warrants a
prompt.
## Inputs
- **Datasheet PDFs**, one per part. The filename is the part's MPN (search that exact
number inside a series datasheet to read the right variant).
- No project/version is needed — repos use a **flat layout**.
## The identifier: `MPN_make_typeid`
Column A of every sheet (header `MPN_make_type`) and each DFS folder name is:
```
<MPN>_<make>_<typeid> e.g. BAT46WJ_Nexperia_SCH
```
- **make** = the **first word of the manufacturer** name (Texas Instruments → `Texas`,
Nexperia → `Nexperia`, STMicroelectronics → `STMicroelectronics`).
- **typeid** = the Type ID for the part's subclass, from the taxonomy in
`references/taxonomy.md` (full source `assets/template/Type_ID.xlsx`). e.g. Schottky →
`SCH`, TVS → `TVS`, MOSFET → `MOS`, LDO → `LDO`, Common-mode choke → `CMC`.
## Workflow
1. **Read each datasheet.** Get MPN (from filename), manufacturer, and the parameters.
2. **Classify** to one of the 18 **types** (= template sheet names) and to a **subclass**
from `references/taxonomy.md`; record its **typeid**. The subclass name goes in the
`Class` column where the sheet has one.
3. **Extract values** into that type's columns (headers come from
`assets/template/template.xlsx`). Convert to each header's unit; leave blank if the
datasheet doesn't state it (an honest blank beats a guess).
4. **Build the master workbook** with `scripts/fill_templates.py` — a single
`Components_Master.xlsx` that mirrors the template but keeps **only the sheets for the
types you actually extracted** (the components whose datasheets were given), each with
column A = `MPN_make_typeid`, and a single **Meta** sheet appended at the end. (See
Producing outputs.)
5. **Assemble each part's DFS folder** `MPN_make_typeid/` containing `MPN_data` (the
datasheet), `MPN_fp` (footprint), `MPN_sym` (symbol). See Footprint & symbol.
6. **Push everything to Gitea — automatically.** At the end of a run, push all outputs to
all three repos with no confirmation step: DFS folders → **DFS**, per-type sheets →
**Parameters** (merged in), skill files + templates → **Skill_Assets**. The only reasons
to pause are a login wall or an already-present MPN (discard vs replace); otherwise it
all just goes. See Pushing to Gitea.
## Producing outputs
Collect what you extracted into `parts.json` (keys match template headers; `typeid` and
`subclass` from the taxonomy; `manufacturer` used for the make tag):
```json
{"parts":[
{"type":"Diode","mpn":"BAT46WJ","manufacturer":"Nexperia","typeid":"SCH","subclass":"Schottky",
"values":{"Description":"100 V 250 mA Schottky, SOD323F","Forward Voltage(V)":"0.71","Package":"SOD323F"}}
]}
```
```bash
python scripts/fill_templates.py parts.json \
--template assets/template/template.xlsx --dest <outputs-dir>
```
Produces a **single** `Components_Master.xlsx`. It starts from a copy of the reference
template (so every kept sheet keeps its exact headers, styling, widths and freeze), fills
this run's parts into the matching sheet (column A = `MPN_make_typeid`), then **drops every
type sheet with no parts** — so the file holds only the components whose datasheets were
provided. A single **Meta** sheet is appended **at the end** with: Template Version, Total
Components, Date, Time, and a per-sheet count breakdown. Deliver this one file to the user;
the Parameters repo stores the same master, accumulated across runs (see Pushing to Gitea).
Sheet naming follows the template (Diode, Resistor, …), not `Sheet1/Sheet2`. If the user
supplies a new reference template, drop it in at `assets/template/template.xlsx` and the
master mirrors whatever sheets/headers it has.
## Footprint & symbol (for the DFS folder)
For each part, the DFS folder needs `MPN_fp` (footprint) and `MPN_sym` (symbol) beside
`MPN_data` (the datasheet). **Deliver these as Altium files** — an Altium PCB footprint
(`.PcbLib`) and schematic symbol (`.SchLib`), or a single integrated library (`.IntLib`)
that carries both — because that's what the design team actually consumes. Get them in
this order:
1. **Auto-download via the user's pre-logged-in Chrome** (`scripts/fetch_cad.py`). The user
keeps signed-in CAD-site windows open; the script attaches to that running Chrome and
reuses those live sessions — it never logs in, and no password is ever handled. One-time
setup: the user quits Chrome, relaunches it with `--remote-debugging-port=9222
--user-data-dir="$HOME/cad-chrome"`, and signs into the sites. Then, per part:
```bash
python scripts/fetch_cad.py --mpn BAT46WJ --dest <DFS_folder> \
--sites snapeda,ultralibrarian,componentsearchengine,digikey
```
It tries each site in order, downloads the Altium model, and drops it into the DFS folder
named `MPN_fp` / `MPN_sym` (or `MPN_cad` for a bundle). **It never solves CAPTCHAs or
defeats bot-detection** — if a site shows a login wall, CAPTCHA, or bot-check, that
adapter stops and reports `manual` with the URL. Note: this runs on the *user's* machine
(where the browsers are), and some sites' terms restrict automated downloads — treat it
as a convenience with the manual fallback below.
2. **Manual fallback** (script returned `manual`/`notfound`, or no browser session): **share
the user the direct link** where the model lives and ask them to download it and send it
back; then attach it into the DFS folder with the agreed naming (`MPN_fp` / `MPN_sym`).
Never type, store, or ask for their password, and never write credentials into this skill
— it's pushed to Skill_Assets, and a secret in a repo is a real leak (same reason the
`GIT_TOKEN` is blanked before syncing).
Whichever path, once you have a candidate **cross-check** its pad/pin count and key
package dimensions against the datasheet's package drawing before trusting it — library
models are sometimes wrong, or drawn for a different variant of the series.
3. **If no good model exists, generate the footprint/symbol yourself** as Altium files
from the datasheet's package drawing and pinout — but only when you can do it reliably
— then **ask the user to verify** it against the datasheet before it's trusted, since a
generated land pattern that's slightly off is worse than an obvious blank.
4. **If none of that is possible**, still create the folder with the datasheet and **tell
the user that MPN needs a manual footprint/symbol build**, leaving a clearly-named
placeholder or listing it so nothing silently goes missing.
Keep the datasheet's extension on `MPN_data` (e.g. `BAT46WJ_data.pdf`). Name the
footprint/symbol files `MPN_fp` / `MPN_sym` with the Altium extension the model uses
(`.PcbLib` / `.SchLib`, or a single `.IntLib` when the source bundles both).
## Pushing to Gitea
Connection + repos are pre-configured in `config/gitea.env` (host, user, token, and the
three repos), so runs need no per-session token. Layout is **flat** (no project/version).
**Every run ends by pushing all three repos — no "shall I push?" step.** The user has
already asked for this to be automatic; don't re-ask. The reconcile step self-guards
against the one risky case (overwriting an existing part), so a straight push is safe by
default.
The three repos split into two kinds, and they're pushed differently:
- **DFS** and **Parameters** are **MPN-indexed** — DFS has one `MPN_make_typeid/` folder
per part; Parameters holds a **single master workbook** (`Components_Master.xlsx`) whose
type sheets each have one row per part (keyed on column A). Because a re-run can collide
with a part that's already there, these go through `scripts/gitea_reconcile.py`, which is
dedup-aware and **merge-safe** (it never blows away parts it isn't touching). See
*Handling parts already in Gitea* below.
- **Skill_Assets** holds the skill itself + templates — it is **not** per-part, so there's
nothing MPN-level to reconcile. Push it with `scripts/push_to_gitea.sh` as before.
```bash
# Skill files + templates -> Skill_Assets (flat copy; no dedup needed)
bash scripts/push_to_gitea.sh --repo "$SKILL_ASSETS_REPO" --src <skill-dir> --message "Sync skill assets"
```
The push script clones the repo, copies the source contents in (flat), commits, and
pushes; the repo must already exist. If the host is unreachable (e.g. Cowork without the
domain allowlisted) it fails clearly and leaves the staged files for a manual push.
**Push the skill files organised** to Skill_Assets: keep the skill's own structure
(`SKILL.md`, `scripts/`, `assets/`, `references/`, `config/`) — but do **not** push the
real token. Before syncing skill assets, blank the `GIT_TOKEN` line in the copy you push,
or push everything except `config/gitea.env`.
> Why not push Parameters with the flat script? `fill_templates.py` writes a master
> workbook holding **only this run's** rows. Copied flat over the repo, it would overwrite
> the stored master and delete every previously-stored part. `gitea_reconcile.py` opens the
> repo's master, merges this run's rows into the right sheets, and writes it back — so only
> the parts you decided on change, and the Meta sheet (totals, date, time) refreshes.
## Handling parts already in Gitea (discard vs replace)
A part's identity is its tag `MPN_make_typeid` (same tag = same part). A re-run that
brings in a *new* MPN is not a conflict — it just gets added, and you push without asking.
The prompt only exists for the case where an MPN **already lives in DFS/Parameters**,
because "replace" overwrites data that's already on the server.
The simplest path is a single push. It clones the repos, adds everything new, and stops
**only** if it hits an existing MPN it can't resolve on its own:
```bash
python scripts/gitea_reconcile.py --parts parts.json --dfs-src <dfs-stage> \
--template assets/template/template.xlsx --push
```
- **No existing MPNs** → it adds all the folders/rows and pushes. No prompt. Done.
- **An MPN already exists** → it refuses (listing which) so you can ask the user, per MPN,
**discard** (keep what's in Gitea, drop the new copy) or **replace** (overwrite that MPN's
DFS folder *and* its Parameters row with the fresh extraction). Every other folder/row is
always left alone — the Parameters sheet is merged, never wholesale-overwritten.
Feed the user's answers back as a small JSON map (`tag → replace|discard`):
```bash
# decisions.json e.g. {"BAT46WJ_Nexperia_SCH": "replace", "1N4148_onsemi_SCH": "discard"}
python scripts/gitea_reconcile.py --parts parts.json --dfs-src <dfs-stage> \
--template assets/template/template.xlsx --decisions decisions.json --push
```
**For fully unattended runs**, skip the prompt entirely with a standing policy — every
conflict resolved the same way, no questions:
```bash
python scripts/gitea_reconcile.py --parts parts.json --dfs-src <dfs-stage> \
--template assets/template/template.xlsx --on-conflict replace --push
```
`--on-conflict replace` (or `discard`) applies to all conflicts; an explicit per-MPN entry
in `--decisions` still wins over the blanket policy. Use `--report conflicts.json` (without
`--push`) if you ever want to preview conflicts first. Host unreachable → it fails clearly,
same as the push script.
## Updating a template (new parameter)
When the user wants a new parameter on a type, **append it at the end** of that type's
sheet and bump the version:
```bash
python scripts/append_parameter.py --type Diode --param "Reverse Recovery Time(ns)" \
--template assets/template/template.xlsx
```
This adds the column at the end and increments `assets/template/VERSION` (v1 → v2 → …).
Then **push the updated `assets/template/template.xlsx` + `VERSION` to the Skill_Assets
repo** so the new template version is archived. New masters record the new version in the
Meta sheet automatically.
## Resources
- `assets/template/template.xlsx` — master template, one sheet per type (source of headers,
styling, and sheet order the master workbook mirrors).
- `assets/template/Type_ID.xlsx` + `references/taxonomy.md` — Class → Subclass → Type ID.
- `assets/template/VERSION` — current template version (integer; the Meta sheet shows `vN`).
- `scripts/fill_templates.py` — build the single master workbook `Components_Master.xlsx`
(only sheets for the extracted types + a trailing Meta sheet); also exposes the shared
helpers (`part_to_row`, `template_headers`, `sheet_rows`, `read_all_rows`, `build_master`,
`MASTER_NAME`) the reconcile step reuses so the Gitea master is built and merged identically.
- `scripts/gitea_reconcile.py` — add new MPNs and push automatically; only stops on an MPN
that already exists (discard/replace), or run unattended with `--on-conflict replace`.
Merge-safe: merges into the repo's master workbook, other rows/sheets/folders untouched.
- `scripts/push_to_gitea.sh` — push a folder's contents to a Gitea repo (flat). Used for
Skill_Assets (not MPN-indexed).
- `scripts/append_parameter.py` — append a parameter to a template + bump version.
- `scripts/fetch_cad.py` — download Altium footprint/symbol by attaching to the user's
pre-logged-in Chrome (remote-debugging port); tries sites in order, defers on
CAPTCHA/login (never bypasses), and names files `MPN_fp`/`MPN_sym`. Runs on the user's
machine; needs `selenium`.
- `config/gitea.env` — host, user, token, and the DFS / Parameters / Skill_Assets repos (**secret**).