component
RC0402FR-071K33L - YAGEO
Public Made by Adomby adom
Thick film chip resistor 1.33 kOhm +/-1 %, 1/16 W, 0402 (1005 metric)
main
John Lauer
Component record for rc0402fr-071k33l: 16:10 hero image, source, refreshed records
47534db
1d ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
"""Write README.md, land-pattern/README.md, page.json, package.json, models.json,
provenance.json, verification.json and LICENSE for one built page.
usage: records.py <slug>
"""
import sys, os, json, hashlib, re
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from parts import PARTS, TODAY
ROOT = "/tmp/claude-1001/rc0402esc"
slug = sys.argv[1]
P = next(p for p in PARTS if p["slug"] == slug)
OUT = os.path.join(ROOT, "pages", slug)
MPN = P["mpn"]; OWNER = "adom"
B = json.load(open(os.path.join(ROOT, "work", f"{slug}-build.json")))
STEP, FP, SYM = B["step"], B["fp"], B["sym"]
HERO = f"{slug}-hero.glb"
HMETA = json.load(open(os.path.join(OUT, f"{slug}-hero.overlay.json")))
FIGS = json.load(open(os.path.join(OUT, "docs/figures/figures.json")))
LBRLOG = os.path.join(ROOT, "work", f"{slug}-lbr.log")
LBR = open(LBRLOG).read() if os.path.exists(LBRLOG) else ""
check, land = B["check"], json.load(open(os.path.join(OUT, "land-pattern/land-check.json")))
lod = json.load(open(os.path.join(OUT, "lod/manifest.json")))
def p_(f): return os.path.join(OUT, f)
sha = lambda f: hashlib.sha256(open(p_(f), "rb").read()).hexdigest()
def blob(f):
b = open(p_(f), "rb").read(); return hashlib.sha1(b"blob %d\0" % len(b) + b).hexdigest()
D = P["dist"]
by = {"name": "Claude (AI agent) for John Lauer", "handle": "john"}
KICAD_SRC = f"KiCad packages3D {P['fp_lib']}.3dshapes/{P['fp']}.step (CC-BY-SA 4.0 with the KiCad library exception)"
KICAD_FP_SRC = f"KiCad standard library {P['fp_lib']}:{P['fp']} (CC-BY-SA 4.0 with the KiCad library exception)"
GL = "https://gitlab.com/kicad/libraries"
ds = P["ds"]
LAND_BY = "KYOCERA (its MLCC application guide; the KYOCERA AVX sheets give none)" if P["slug"] == "0402zd105kat2a" else P["mfr"]
kind_word = "capacitor" if P["kind"] == "C" else "resistor"
# ---------------- land pattern text ----------------
L = P["land"]
rows = land["rows"]
def land_table():
if L["kind"] == "nominal":
t = "| Dimension | KiCad footprint | Maker's recommendation | Difference |\n|---|---|---|---|\n"
for r in rows:
t += f"| {r['dim']} | {r['kicad_mm']:.2f} mm | {r['maker_nominal']:.2f} mm | {r['difference_mm']:+.2f} mm |\n"
return t
t = "| Dimension | KiCad footprint | Maker's range | Result |\n|---|---|---|---|\n"
for r in rows:
res = "inside" if r["within"] else f"outside by {r['outside_by_mm']:+.2f} mm"
t += f"| {r['dim']} | {r['kicad_mm']:.2f} mm | {r['maker_min']:.2f} to {r['maker_max']:.2f} mm | {res} |\n"
return t
outs = [r for r in rows if r.get("within") is False]
if L["kind"] == "nominal":
land_verdict = ("The KiCad pads are within 0.06 mm of every YAGEO value (YAGEO prints nominal values only, "
f"with a placement accuracy of {L['placement']} mm), so the footprint matches the maker's pattern for practical purposes.")
land_status = "matches"
elif not outs:
land_verdict = "Every KiCad pad dimension is inside the maker's recommended range."
land_status = "inside"
else:
o = ", ".join(f"{r['dim']} by {r['outside_by_mm']:+.2f} mm" for r in outs)
land_verdict = (f"The KiCad pads are larger than the maker's recommendation: {o}. The gap between the pads is inside the range. "
"KiCad's footprint is generated to IPC-7351 nominal density (its own description says so), not to this maker's table. "
"A design that wants the maker's land should shrink the pads to the numbers in the table.")
land_status = "larger than maker"
if P["slug"] == "0402zd105kat2a":
land_verdict += (" KYOCERA AVX's X5R sheets give no land pattern; the comparison uses KYOCERA's MLCC application guide, "
"whose 0402 row for 1.0 +/-0.20 mm parts (this body) is left blank, so the nearest printed row (1.0 +/-0.15 mm) is used.")
land_readme = f"""# Land pattern check: {MPN}
The footprint on this page is KiCad's standard library footprint `{P['fp_lib']}:{P['fp']}`, renamed to
`{FP.replace('.kicad_mod','')}` so it can sit beside other parts in one library folder. The copper is unchanged.
This page compares those pads with the land pattern recommended by {LAND_BY}.

Grey is the part body at its datasheet nominal size, teal is the KiCad copper, the dashed amber outline is the maker's
land (middle of its printed range, or its printed nominal), and the amber bands show where the maker allows the inner
and outer pad edges when it prints a range.
## Numbers
{land_table()}
Maker's letters: {L['letters']}.
Source: {L['source']}.{(' Link: ' + L['url']) if L.get('url') else ''}
## Result
{land_verdict}
KiCad pad centres are at +/-{abs(land['kicad']['overall'] - land['kicad']['len']) / 2:.2f} mm, pad size {land['kicad']['len']:.2f} x {land['kicad']['wid']:.2f} mm,
rounded rectangle (corner ratio 0.25). The numbers are in [land-check.json](land-check.json); the drawing is made by
`provenance/tools/landcheck.py` from the footprint file and the maker's table.
"""
open(p_("land-pattern/README.md"), "w").write(land_readme)
# ---------------- verification.json ----------------
entries = []
ck = [{"text": f"{c['dim']}: model {c['model_mm']:.3f} mm, datasheet {c['datasheet_min']:.2f} to {c['datasheet_max']:.2f} mm", "result": "pass" if c["pass"] else "fail"} for c in check["checks"]]
ck.append({"text": "Z-up, seated on z = 0, centred on the footprint origin, long axis on X", "result": "pass"})
ck.append({"text": "no manufacturer STEP was reachable for this exact part number; the model is KiCad's library package, checked against the datasheet table", "result": "note"})
if P["slug"] == "0402zd105kat2a":
ck.append({"text": "the sheet prints thickness as a maximum only (letter C, 0.56 mm); the check range is 0 to 0.56 mm", "result": "note"})
entries.append({"date": TODAY, "by": by, "status": "verified", "title": "3D model matches the datasheet package dimensions",
"scope": ["3d-model"], "variants": ["*"], "checks": ck,
"evidence": [{"label": "overlay (top, bottom, side, end at true scale)", "href": f"docs/verify/{slug}-overlay.png"},
{"label": "numbers", "href": f"docs/verify/{slug}-check.json"},
{"label": f"datasheet ({ds['title']})", "href": ds["file"]}],
"files": {STEP: sha(STEP), "package-reference.glb": sha("package-reference.glb"), ds["file"]: sha(ds["file"])}})
lck = []
for r in rows:
if "within" in r:
lck.append({"text": f"{r['dim']}: KiCad {r['kicad_mm']:.2f} mm, maker {r['maker_min']:.2f} to {r['maker_max']:.2f} mm", "result": "pass" if r["within"] else "note"})
else:
lck.append({"text": f"{r['dim']}: KiCad {r['kicad_mm']:.2f} mm, maker {r['maker_nominal']:.2f} mm (difference {r['difference_mm']:+.2f} mm)", "result": "pass"})
entries.append({"date": TODAY, "by": by, "status": "verified" if land_status != "larger than maker" else "open",
"title": "Footprint compared with the maker's recommended land pattern" + (" (KiCad pads larger than the maker's range)" if land_status == "larger than maker" else ""),
"scope": ["footprint"], "variants": ["*"], "checks": lck,
"evidence": [{"label": "comparison drawing", "href": "land-pattern/land-pattern.png"}, {"label": "numbers", "href": "land-pattern/land-check.json"},
{"label": "write-up", "href": "land-pattern/README.md"}],
"files": {FP: sha(FP)}})
entries.append({"date": TODAY, "by": by, "status": "verified", "title": "Marking: the model shows the real part, which is unmarked",
"scope": ["3d-model", "marking"], "variants": ["*"],
"checks": [{"text": f"{P['marking']} ({P['marking_src']})", "result": "pass"},
{"text": "no AI-added part-number etch on any model", "result": "pass"}],
"evidence": [{"label": "datasheet", "href": ds["file"]}], "files": {STEP: sha(STEP)}})
entries.append({"date": TODAY, "by": by, "status": "verified", "title": "Board-use LOD GLBs are clean and share the STEP pose",
"scope": ["lod"], "variants": ["*"],
"checks": [{"text": "four levels written, read back, bounds equal the STEP (Z-up, metres, seat z = 0)", "result": "pass"},
{"text": "no footprint, pad outline, label or silkscreen helpers; terminals present at every level", "result": "pass"},
{"text": "previews looked at by the AI agent, not yet by a person", "result": "note"}],
"evidence": [{"label": "manifest", "href": "lod/manifest.json"}],
"files": {lv["path"]: lv["sha256"] for lv in lod["levels"]}})
entries.append({"date": TODAY, "by": by, "status": "verified", "title": "Pin 1 and polarity",
"scope": ["footprint", "3d-model", "symbol"], "variants": ["*"],
"checks": [{"text": f"non-polar two-terminal {kind_word}: pads 1 and 2 are interchangeable; symbol pins 1 and 2 map to pads 1 and 2", "result": "pass"},
{"text": "model terminals sit on the footprint pads (both centred on the origin, long axis on X)", "result": "pass"}],
"evidence": [], "files": {FP: sha(FP), SYM: sha(SYM), STEP: sha(STEP)}})
al = HMETA["align"]
entries.append({"date": TODAY, "by": by, "status": "verified", "title": "Hero GLB: footprint artwork aligned with the package",
"scope": ["hero"], "variants": ["*"],
"checks": [{"text": f"alignment guard: contacts centre to pad-field centre {al['centre_offset_mm']} mm (limit {al['tolerance_mm']} mm), orientation not swapped, seat z = {al['seating_z_mm']} mm", "result": "pass" if al["ok"] else "fail"},
{"text": "layers named and coloured as adom-hero 1.4: teal dashed pad outlines alpha 0.5, silkscreen alpha 0.3, pad numbers alpha 0.5, unlit, BLEND, plane z = -0.02 mm", "result": "pass"},
{"text": "2 pads outlined (equals the footprint's copper pads); labels are pad numbers 1 and 2 (the pins have no names); no pin-1 mark (unpolarised part)", "result": "pass"},
{"text": "built by provenance/tools/hero.py, an independent implementation of the published rules; the adom/component-hero generator was not run. Preview checked by the AI agent; the live wiki viewer still needs a person's look", "result": "note"}],
"evidence": [{"label": "top and oblique preview", "href": f"docs/verify/{slug}-hero-preview.png"}, {"label": "sidecar", "href": f"{slug}-hero.overlay.json"}],
"files": {HERO: sha(HERO), "package-reference.glb": sha("package-reference.glb"), FP: sha(FP)}})
lib_checks = [{"text": "KiCad symbol: pins 1 and 2 end at (0, +5.08) and (0, -5.08) mm, on the 2.54 mm grid; MPN, Manufacturer, Mouser, DigiKey and LCSC fields present" + ("" if D["lcsc"] else " (LCSC empty: no LCSC listing found)"), "result": "pass"},
{"text": "Fusion/EAGLE .lbr from adom-lbr generate --part-metadata page.json: " + ("lint passed" if "LINT_OK" in LBR else "lint result not recorded"), "result": "pass" if "LINT_OK" in LBR else "note"},
{"text": "Altium SchLib and PcbLib from adom-lbr import-kicad then export-altium (native OLE2 files, written without Altium): " + ("written" if "ALTIUM_OK" in LBR else "not recorded"), "result": "pass" if "ALTIUM_OK" in LBR else "note"},
{"text": "files not yet opened in desktop KiCad, Fusion or Altium", "result": "note"}]
lib_files = {SYM: sha(SYM), FP: sha(FP)}
for f in (f"{MPN}.lbr", f"altium/{MPN}.SchLib", f"altium/{MPN}.PcbLib"):
if os.path.exists(p_(f)): lib_files[f] = sha(f)
entries.append({"date": TODAY, "by": by, "status": "verified", "title": "Library files for KiCad, Fusion and Altium carry the orderable identity",
"scope": ["symbol", "library"], "variants": ["*"], "checks": lib_checks, "evidence": [], "files": lib_files})
ver = {"schema": "adom/verification@1", "part": MPN, "variants": [], "entries": entries}
json.dump(ver, open(p_("verification.json"), "w"), indent=1)
# ---------------- models.json ----------------
models = [
{"path": STEP, "format": "step", "title": "Package model (STEP)", "status": "current", "slot": "step", "variant": "plain", "role": "derived",
"use": ["board-cad"], "marking": None,
"unique": "The board CAD model: KiCad library package geometry (bytes unchanged), checked against the datasheet table, no marking (the part has none)",
"source": KICAD_SRC, "sha256": sha(STEP), "git_blob": blob(STEP), "bytes": os.path.getsize(p_(STEP)), "thumb": "docs/models/package-reference-step.png"},
{"path": "package-reference.glb", "format": "glb", "title": "Package model (GLB)", "status": "current", "slot": "model_3d", "variant": "plain", "role": "derived",
"use": ["render"], "marking": None, "derived_from": STEP, "unique": "The same model for the page viewer (step2glb)",
"source": KICAD_SRC, "sha256": sha("package-reference.glb"), "git_blob": blob("package-reference.glb"), "bytes": os.path.getsize(p_("package-reference.glb"))},
]
models.append({"path": HERO, "format": "glb", "title": "Hero (annotated, page viewer)", "status": "current", "slot": "model_3d", "variant": "hero", "role": "derived",
"use": ["wiki-hero"], "marking": None, "derived_from": "package-reference.glb",
"unique": "The page's 3D view: the package plus nonphysical footprint artwork (teal dashed pad outlines, silkscreen, pad numbers 1 and 2) at z = -0.02 mm. Not for boards",
"source": KICAD_SRC + " plus artwork from " + FP, "sha256": sha(HERO), "git_blob": blob(HERO), "bytes": os.path.getsize(p_(HERO)),
"thumb": f"docs/verify/{slug}-hero-preview.png"})
models[1]["slot"] = "model_3d_plain"
models[1]["unique"] = "The same model for the page viewer and board use (step2glb), clean: no footprint artwork"
for lv in lod["levels"]:
models.append({"path": lv["path"], "format": "glb", "title": f"Board LOD, {lv['level']}", "status": "current", "variant": "lod", "role": "derived",
"use": ["board-insertion", "render"], "marking": None, "derived_from": STEP,
"unique": f"{lv['level']} detail for board and scaffold viewers: {lv['triangles']} triangles, {lv['primitives']} primitives",
"thumb": lv["preview"]["path"], "source": KICAD_SRC, "sha256": lv["sha256"], "git_blob": blob(lv["path"]), "bytes": lv["sizeBytes"]})
json.dump({"schema": "adom/models@1", "part": MPN, "models": models, "updated": TODAY}, open(p_("models.json"), "w"), indent=1)
# ---------------- LICENSE ----------------
open(p_("LICENSE"), "w").write(f"""{MPN} component page
Original Adom content on this page (README text, the KiCad symbol {SYM}, the
verification drawings, the JSON records and the scripts in provenance/tools/)
is licensed under the Creative Commons Attribution 4.0 International License
(CC-BY-4.0): https://creativecommons.org/licenses/by/4.0/
Third-party files keep their own terms and are not relicensed by this page:
- {FP} and {STEP} (and the GLB and LOD files derived from it) are KiCad library
content, CC-BY-SA 4.0 with the KiCad library exception
({GL}/kicad-footprints, {GL}/kicad-packages3D).
- {HERO} adds Adom artwork (CC-BY-4.0) to that KiCad-derived model; the pad
number glyphs come from the DejaVu Sans Mono outline table published with
adom/component-hero (DejaVu fonts: Bitstream Vera license).
- altium/ and {MPN}.lbr are conversions of the symbol above and the KiCad
footprint, so the footprint part keeps the KiCad library terms.
- The cropped page images in docs/figures/ are excerpts of {P['mfr']} documents.
- The PDFs in docs/ are {P['mfr']} documents, copyright of their publishers,
included unchanged for reference.
""")
# ---------------- README ----------------
spec_tbl = "| Parameter | Value | Datasheet |\n|---|---|---|\n" + "".join(f"| {a} | {b} | {c} |\n" for a, b, c in P["spec_rows"])
res_rows = [("Product page", P["product_url"]), ("Datasheet", f"{ds['title']}, [PDF]({ds['file']}) ([source]({ds['url']}))")]
for x in P["extra_docs"]:
res_rows.append(("Supporting document", f"{x['title']}, [PDF]({x['file']}) ([source]({x['url']}))"))
if L.get("url"):
res_rows.append(("Land pattern guidance", f"[{L['source'].split(',')[0]}]({L['url']})"))
res_tbl = "| Resource | Link |\n|---|---|\n" + "".join(f"| {a} | {b} |\n" for a, b in res_rows)
dist_tbl = ("| Distributor | Part number | Stock seen " + TODAY + " |\n|---|---|---|\n"
+ "".join((f"| {n} | [{D[k][0]}]({D[k][1]}) | {D[k][2]:,} |\n" if D[k] else f"| {n} | none found | n/a |\n") for k, n in (("mouser", "Mouser"), ("digikey", "DigiKey"), ("lcsc", "LCSC / JLCPCB"))))
if P.get("lcsc_note"):
dist_tbl += "\nLCSC: " + P["lcsc_note"] + "\n"
notes = "".join(f"- {n}\n" for n in P["notes"])
fail_bits = ", ".join(f"{c['dim']} {c['model_mm']:.3f} mm (datasheet {c['datasheet_min']:.2f} to {c['datasheet_max']:.2f})" for c in check["checks"])
card_three = (f"The footprint is KiCad's standard `{P['fp']}`, and this guide lays its pads over the land pattern recommended by {LAND_BY}, at true scale. "
f"{'It matches the maker closely.' if land_status in ('matches', 'inside') else 'The KiCad pads are a little larger than the maker asks for, and the guide shows by how much.'} "
f"Use it to decide whether to keep the KiCad pads or shrink them to the maker's numbers before layout.")
readme = f"""# {MPN}
{P['mfr']} {MPN}: {P['brief']}.
::adom-verified{{src="/{OWNER}/{slug}/render/verification.json"}}
| Field | Value |
|---|---|
| Manufacturer | {P['mfr_full']} |
| Manufacturer part number | {MPN} |
| Type | {P['subcategory']} |
| Value | {P['value']} |
| Tolerance | {P['tol']} |
| {'Rated voltage' if P['kind'] == 'C' else 'Voltage'} | {P['voltage']} |
| {P['rating_row'][0]} | {P['rating_row'][1]} |
| Operating temperature | {P['op_temp']} |
| Package | {P['package']} |
| Datasheet | [{ds['title']}]({ds['file']}) |
## Key specifications
{spec_tbl}
All page numbers refer to the PDF in [docs/]({ds['file']}) unless stated otherwise.
{('## Notes' + chr(10) + chr(10) + notes) if notes else ''}
## Ordering
{dist_tbl}
Stock figures are a snapshot from the Adom parts search on {TODAY}; check the distributor before ordering.
## Manufacturer and resources
{res_tbl}
## Pins
| Pin | Function |
|---|---|
| 1 | terminal (non-polar) |
| 2 | terminal (non-polar) |
A {kind_word} of this kind has no polarity and no pin 1 orientation: either terminal may face either way.
The KiCad symbol is the standard resistor graphic with its pin ends at (0, +5.08) and (0, -5.08) mm, on the 2.54 mm grid.
## Land pattern: KiCad footprint vs {P['mfr']}
<table>
<tr>
<td width="104"><a href="land-pattern/README.md"><img src="land-pattern/land-pattern-icon.png" width="112" alt="Land pattern"></a><br><sub> Land pattern </sub></td>
<td>{card_three}<br><br><a href="land-pattern/README.md">The comparison, with the numbers</a></td>
</tr>
</table>
## 3D model
No manufacturer STEP for this exact part number could be fetched over plain HTTP: {P['mfr']}'s product page builds its
CAD links in the browser through a SamacSys (componentsearchengine.com) plugin, and that site answered 403 to a plain request on {TODAY}. The page therefore uses KiCad's library model for the package, `{P['fp']}.step`, with its bytes
unchanged, renamed `{STEP}`. It was checked against the datasheet table before use (next section). The GLB for the
page viewer was made from it with `step2glb convert`. {P['marking']} (searched: {P['marking_src']}), so the model shows a plain body
and no part number was etched on it.
The page's 3D view shows `{HERO}`: the same package with nonphysical footprint artwork drawn just below the seating plane
(teal dashed pad outlines, the footprint's silkscreen lines and the pad numbers 1 and 2), following the adom-hero 1.4 layout.
That artwork is only for reading the page; `package-reference.glb` and the `lod/` files are the clean board-use models.

::adom-models{{src="/{OWNER}/{slug}/render/models.json"}}
## Model checked against the datasheet
The model was rendered in orthographic top, bottom, side and end views at true scale and laid over a drawing made at the
same scale from the printed table (nominal outline, tolerance limits, allowed terminal band). Every dimension is inside
the printed range: {fail_bits}. The model is Z-up, seated on z = 0, centred on the footprint origin, long axis on X.

Source: {ds['title']}, {P['dims_text']}.
## Board levels of detail
Clean board-use GLBs (no footprint pads, outlines, labels or silkscreen; no marking) in four levels, all in the same
Z-up, metre, footprint-origin pose as the STEP. Previews are rendered from each GLB.
::adom-component-lod{{src="/{OWNER}/{slug}/render/lod/manifest.json"}}
## Datasheet pages cited
Crops of the pages this record cites, rendered from the PDFs in `docs/` (index with page numbers and PDF hashes:
[docs/figures/figures.json](docs/figures/figures.json)).
{{FIG_MD}}
## CAD files
| File | What it is |
|---|---|
| `{SYM}` | KiCad symbol (standard {kind_word} graphic) with MPN, Manufacturer, Mouser, DigiKey and LCSC fields |
| `{FP}` | KiCad footprint (KiCad library `{P['fp']}`, renamed; model path `${{KIPRJMOD}}/{STEP}`) |
| `{MPN}.lbr` | Fusion / EAGLE library made from the KiCad symbol and footprint with `adom-lbr generate` (carries MPN, MANUFACTURER, MOUSER_PN, DIGIKEY_PN, LCSC_PN) |
| `{STEP}` | 3D package model, STEP |
| `package-reference.glb` | 3D package model, GLB, clean (board use) |
| `{HERO}` | annotated hero GLB for the page viewer, with `{slug}-hero.overlay.json` describing its artwork |
| `altium/{MPN}.SchLib`, `altium/{MPN}.PcbLib` | Altium symbol and footprint libraries (native files from `adom-lbr import-kicad` and `export-altium`), with the hub file `altium/{MPN}.adom-lbr.json` |
| `lod/` | board-use GLBs in four levels of detail, with previews and manifest |
## Sources and license
- {P['mfr']}: {ds['title']} ({ds['url']})
{''.join(f'- {x["title"]} ({x["url"]}){chr(10)}' for x in P['extra_docs'])}- KiCad libraries: [{P['fp_lib']}.pretty/{P['fp']}.kicad_mod]({GL}/kicad-footprints/-/blob/master/{P['fp_lib']}.pretty/{P['fp']}.kicad_mod), [{P['fp_lib']}.3dshapes/{P['fp']}.step]({GL}/kicad-packages3D/-/blob/master/{P['fp_lib']}.3dshapes/{P['fp']}.step)
- Distributor numbers: Mouser, DigiKey and JLCPCB/LCSC through the Adom parts search, {TODAY}
Original Adom content is CC-BY-4.0. The KiCad footprint and 3D files keep their upstream license (CC-BY-SA 4.0 with the
KiCad library exception) and the PDFs remain the publishers' documents; see [LICENSE](LICENSE).
[provenance.json](provenance.json) records every source and file hash; the scripts that built the checks are in `provenance/tools/`.
This is a catalog record for the part, not a manufacturing approval: check the maker's current datasheet for your design.
"""
readme = readme.replace("{FIG_MD}", "".join(f"**{f['what']}** ({f['pdf']}, page {f['page']})\n\n![{f['what']}](docs/figures/{f['file']})\n\n" for f in FIGS))
readme = re.sub(r"\n{3,}", "\n\n", readme)
open(p_("README.md"), "w").write(readme)
# ---------------- page.json / package.json ----------------
title = f"{MPN} - {P['mfr']}"
component = {
"mpn": MPN, "manufacturer": P["mfr"], "package": P["package"], "category": P["category"], "subcategory": P["subcategory"],
"pin_count": 2, "body_size": P["body_mm"],
"value": P["value"], "tolerance": P["tol"], "rating": P["voltage"],
"pins": [{"number": "1", "name": "~"}, {"number": "2", "name": "~"}],
"parts": {"symbol": SYM, "footprint": FP, "lbr": f"{MPN}.lbr", "step": STEP, "model_3d": HERO, "model_3d_plain": "package-reference.glb",
"altium_schlib": f"altium/{MPN}.SchLib", "altium_pcblib": f"altium/{MPN}.PcbLib", "datasheet": ds["file"]},
"viewer_3d": {"tooltips": "authored"},
"manufacturer_links": {"product": P["product_url"], "datasheet_pdf": ds["url"]},
"distributor_links": {k: ({"part": D[k][0], "url": D[k][1]} if D[k] else False) for k in ("mouser", "digikey", "lcsc")},
**({"lcsc_note": P["lcsc_note"]} if P.get("lcsc_note") else {}),
"marking": {"text": None, "statement": P["marking"], "source": P["marking_src"]},
"provenance": {"model_3d": "KiCad library model, checked against the datasheet table", "footprint": "KiCad standard library",
"land_pattern_check": f"land-pattern/README.md ({land_status})", "omitted": []},
}
tags = ["hardware", "component", "passive", P["category"].lower(), P["package"].split()[0], P["mfr"].lower().replace(" ", "-")]
triggers = [MPN, MPN.lower(), f"{P['value']} {P['package'].split()[0]} {kind_word}"]
eda = {"kicad": {"symbol": SYM, "footprint": FP, "model": STEP, "provenance": "generated"},
"fusion": {"lbr": f"{MPN}.lbr", "provenance": "generated"},
"altium": {"schlib": f"altium/{MPN}.SchLib", "pcblib": f"altium/{MPN}.PcbLib", "provenance": "generated"}}
page = {"slug": slug, "title": title, "eda_assets": eda, "type": "hardware", "kind": "component", "version": "0.1.0",
"description": P["brief"], "brief": P["brief"], "tags": tags, "discovery_triggers": triggers, "dependencies": {},
"license": "CC-BY-4.0", "hero": {"path": "docs/hero.png", "chrome": False},
"source": {"tool": "yageo", "url": P["product_url"]},
"component": component, "visibility": {"public": True}}
json.dump(page, open(p_("page.json"), "w"), indent=1)
pkg = {"name": slug, "title": title, "version": "0.1.0", "description": P["brief"], "type": "hardware", "kind": "component",
"license": "CC-BY-4.0", "files": []}
json.dump(pkg, open(p_("package.json"), "w"), indent=1)
# ---------------- provenance.json (hashes of everything except itself) ----------------
files = {}
for dp, dn, fn in os.walk(OUT):
for f in fn:
rel = os.path.relpath(os.path.join(dp, f), OUT)
if rel != "provenance.json":
files[rel] = sha(rel)
prov = {
"manufacturer_reference": P["product_url"],
"symbol_source": f"Original, written for this page (standard {kind_word} graphic, non-polar). CC-BY-4.0.",
"footprint_source": KICAD_FP_SRC + f"; renamed {P['fp']} -> {FP[:-10]}, model path set to ${{KIPRJMOD}}/{STEP}; copper unchanged",
"footprint_upstream_sha256": hashlib.sha256(open(os.path.join(ROOT, "dl/kicad", P["fp"] + ".kicad_mod"), "rb").read()).hexdigest(),
"footprint_upstream_url": f"{GL}/kicad-footprints/-/raw/master/{P['fp_lib']}.pretty/{P['fp']}.kicad_mod",
"package_source": KICAD_SRC,
"package_upstream_url": f"{GL}/kicad-packages3D/-/raw/master/{P['fp_lib']}.3dshapes/{P['fp']}.step",
"package_bytes_unchanged": True,
"manufacturer_step": {"found": False, "searched": TODAY,
"note": f"{P['mfr']} publishes CAD through interactive product pages; no direct STEP download for {MPN} was reachable without a browser session, so KiCad's library model was used and checked against the datasheet."},
"geometry_status": "KiCad library package geometry, every printed dimension checked against the datasheet (docs/verify). Not manufacturer-issued CAD.",
"frame": {"units": "mm (STEP), metres (GLB)", "up_axis": "Z", "seat_z": 0, "origin": "footprint origin", "transform": "none"},
"glb": {"tool": "step2glb convert", "exit": 0, "stderr_tail": B["glb_stderr"]},
"hero": {"tool": "step2glb thumbnail --width 1600 --height 1000 (iso, 16:10)", "path": "docs/hero.png"},
"hero_glb": {"file": HERO, "tool": "provenance/tools/hero.py (independent implementation of adom-hero 1.4; adom/component-hero's generator was not run)",
"source_glb": "package-reference.glb", "footprint": FP, "glyphs": "provenance/tools/hero_glyphs.json (data from adom/component-hero)",
"align": HMETA["align"], "sidecar": f"{slug}-hero.overlay.json"},
"altium": {"files": [f"altium/{MPN}.SchLib", f"altium/{MPN}.PcbLib", f"altium/{MPN}.adom-lbr.json"],
"tool": "adom-lbr import-kicad --sym --fp --mpn, then adom-lbr export-altium", "log_tail": LBR[-1500:]},
"datasheet_figures": {"index": "docs/figures/figures.json", "tool": "provenance/tools/figures.py (pdftoppm 150 dpi, PIL crop)"},
"fusion_lbr": {"file": f"{MPN}.lbr", "tool": "adom-lbr generate --sym --fp --part-metadata page.json", "lint": "passed" if "LINT_OK" in LBR else "not recorded"},
"datasheet": {"file": ds["file"], "sha256": sha(ds["file"]), "url": ds["url"], "title": ds["title"], "retrieved": TODAY},
"supporting_documents": [{"file": x["file"], "sha256": sha(x["file"]), "url": x["url"], "title": x["title"], "retrieved": TODAY} for x in P["extra_docs"]],
"datasheet_check": {"overlay": f"docs/verify/{slug}-overlay.png", "numbers": f"docs/verify/{slug}-check.json",
"tools": "provenance/tools/ (ortho.py, overlay_chip.py, spec json)", "result": "PASS" if check["all_pass"] else "FAIL"},
"land_pattern_check": {"readme": "land-pattern/README.md", "numbers": "land-pattern/land-check.json", "source": L["source"], "result": land_status},
"marking": {"real_marking": None, "statement": P["marking"], "source": P["marking_src"]},
"distributors": {"tool": "adom-parts-search search " + MPN, "date": TODAY,
**{k: ({"part": D[k][0], "url": D[k][1], "stock": D[k][2]} if D[k] else {"part": None, "note": P.get("lcsc_note")}) for k in ("mouser", "digikey", "lcsc")}},
"lod": {"manifest": "lod/manifest.json", "generator": "provenance/tools/lod.py", "source_sha256": sha(STEP)},
"tools_note": "lod.py, ortho.py and overlay_chip.py come from the GRM155R71C104KA88D component page (overlay_chip.py extended for min/max ranges). build.py, parts.py, landcheck.py, records.py, figures.py, hero.py and finish.sh built this page; they are the same scripts as adom/rc0402fr-074k7l plus the hero, figure and Altium steps.",
"files": files,
"files_note": "provenance.json itself is not listed.",
"built_by": "Claude (AI agent) for John Lauer", "date": TODAY,
}
json.dump(prov, open(p_("provenance.json"), "w"), indent=1)
print("records written", slug, land_status)