component
JST SM04B-GHS-TB(LF)(SN) GH 4-circuit side entry SMT header
Public Made by Adomby adom
JST GH 1.25 mm pitch, 4 circuits, side entry (right angle) SMT shrouded header with two solder tabs; mates with GHR-04V-S and SSHL-002T-P0.2.
← Commit history
Add provenance, manifests, verification log, licenses and README
18 files changed
+1822−2
LICENSE+9LICENSE-KICAD.md+27README.md+188−2THIRD_PARTY.md+10models.json+155provenance/3d-model.json+130provenance/footprint-vs-jst.json+160provenance/sources.json+72provenance/symbol-create.json+57provenance/tools/__pycache__/glbtool.cpython-312.pycprovenance/tools/build_manifests.py+118provenance/tools/compare_footprint.py+48provenance/tools/glb_parts.mjs+51provenance/tools/glbtool.py+108provenance/tools/render.py+120provenance/tools/symbol_post.py+37provenance/upstream/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.kicad_mod+350verification.json+182LICENSEadded+9@@ -0,0 +1,9 @@+Adom-authored files on this page are licensed under the Creative Commons Attribution 4.0 International+License (CC-BY-4.0): https://creativecommons.org/licenses/by/4.0/legalcode++Adom-authored files: sm04b-ghs-tb-lf-sn.kicad_sym, README.md, page.json, models.json, verification.json,+lod/manifest.json, provenance/ (except provenance/upstream/), docs/models/, docs/proof/, docs/hero.png,+docs/*.svg, viewers/, and the symbol parts of sm04b-ghs-tb-lf-sn.lbr and altium/.++Files that are not Adom-authored keep their own terms; see THIRD_PARTY.md. This license does not+relicense them.
LICENSE-KICAD.mdadded+27@@ -0,0 +1,27 @@+### KiCad Libraries License++The KiCad libraries are licensed under the [Creative Commons CC-BY-SA 4.0 License](https://creativecommons.org/licenses/by-sa/4.0/legalcode), with the following exception:++---------++_To the extent that the creation of electronic designs that use 'Licensed Material' can be considered to be 'Adapted Material', then the copyright holder waives article 3 of the license with respect to these designs and any generated files which use data provided as part of the 'Licensed Material'._++---------++You can read more about KiCad library licensing [here](http://kicad.org/libraries/license).++**What does this mean?**++KiCad libraries are licensed in such a way to ensure free use of library data for commercial, closed, and non-commercial projects without restriction. KiCad does not wish to exert any control over designs produced using the library data, or force users to reveal proprietary information contained in their designs. Neither do we wish to force users to attribute the KiCad libraries _within their design_.++Use of the library data in a project does not (by itself) require that the design or any files generated from the design are licensed under the CC-BY-SA 4.0 License. You are free to use the library data in your own projects without the obligation to share your project files under this or any other license agreement.++However, if you wish to redistribute the KiCad libraries, or parts thereof (including in modified form) as a collection then the exception above does not apply. Redistributed library collections must be shared under the same license agreement. Under these circumstances, the libraries must also retain attribution information, including the license documents which are distributed with the library files.++----------------------++**Warranty**++The KiCad libraries are provided in the hope that they will be useful, but are provided without warranty of any kind, express or implied.++The KiCad libraries are compiled by the KiCad community - if you find an error in the library data, please help the community and contribute a fix!
README.md+188−2@@ -1,3 +1,189 @@-# JST SM04B-GHS-TB(LF)(SN) GH 4-circuit side entry SMT header+# SM04B-GHS-TB(LF)(SN) -JST GH 1.25 mm pitch, 4 circuits, side entry (right angle) SMT shrouded header with two solder tabs; mates with GHR-04V-S and SSHL-002T-P0.2.+**JST** · GH series, 1.25 mm pitch, 4 circuits · side entry (right angle) SMT shrouded header with two solder tabs++SM04B-GHS-TB(LF)(SN) is the 4 circuit, side entry member of JST's GH wire-to-board family: the cable plugs in parallel to the board. It is a surface mount header with four tin plated phosphor bronze contacts on a 1.25 mm pitch and two brass solder tabs that hold it to the board. The (LF)(SN) suffix is JST's lead free, tin plated product label (JST eGH.pdf p.2). It mates with the **GHR-04V-S** housing fitted with **SSHL-002T-P0.2** crimp contacts.++::adom-verified{src="/adom/sm04b-ghs-tb-lf-sn/render/verification.json"}++## Key specifications++| | |+|---|---|+| Circuits | 4, pitch 1.25 mm |+| Entry | Side entry (right angle), surface mount, 2 solder tabs |+| Current rating | 1.0 A AC, DC (AWG #26) |+| Voltage rating | 50 V AC, DC |+| Temperature range | -25 to +85 C, including the temperature rise from current |+| Contact resistance | 30 mOhm max initial, 50 mOhm max after environmental tests |+| Insulation resistance | 100 MOhm min |+| Withstanding voltage | 500 V AC for 1 minute |+| Applicable wire | AWG #30 to #26, insulation O.D. 0.76 to 1.0 mm |+| Contacts | Phosphor bronze, copper undercoated, tin plated (reflow treatment) |+| Housing | PA9T, UL94V-0, natural (ivory) |+| Solder tabs | Brass, copper undercoated, tin plated |+| Size | 8.25 mm wide (B), 4.05 mm deep plus 0.8 mm tails, 4.25 mm tall; 4.35 mm tall mated |+| Packaging | Embossed tape, 2,500 per reel |+| Standards | UL Recognized E60389 |++Source: JST GH catalog eGH.pdf p.1 (Specifications, PC board layout and Assembly layout) and p.2 (Shrouded header, Material and Finish).++++## Circuit numbering and pin 1++| Pin | Name | What it is |+|---|---|---|+| 1 | 1 | Circuit No.1: the left contact seen from the mating face with the board below |+| 2 | 2 | Circuit No.2 |+| 3 | 3 | Circuit No.3 |+| 4 | 4 | Circuit No.4: the right contact seen from the mating face |+| MP | MP | The two solder tabs, one at each end. Mechanical only, not a contact; both pads share the number MP |++The pin numbers are contact positions. What each circuit carries is the design's choice; check the cable's wiring against the mating face before assembly.++JST marks circuit 1 only in its drawing (p.2, side entry view, looking into the mating face): it is at the left. On the footprint the mating face points toward +Y (down in KiCad's top view), so a person facing the opening has -X on the left, and **pad 1 is the -X end** (x = -1.875 mm). KiCad's F.Fab chevron and the silkscreen tick sit at the same end. Neither the real header nor the 3D model carries a pin-1 mark; the 3D hero adds a pin-1 dot beside pad 1 as reference art.++++## Mating parts++| Part | Role | Page |+|---|---|---|+| GHR-04V-S | 4 circuit cable housing, PBT natural (white); A 3.75, B 6.25 mm | [adom/ghr-04v-s](https://wiki.adom.inc/adom/ghr-04v-s) |+| SSHL-002T-P0.2 | Crimp contact, AWG #30 to #26, insulation O.D. 0.76 to 1.0 mm, 35,000 per reel | [adom/sshl-002t-p0-2](https://wiki.adom.inc/adom/sshl-002t-p0-2) |++JST notes that SSHL-003()-P0.2 contacts cannot be used in GH housings (p.1). Crimp tooling named by JST: machine AP-K2N, applicator MKS-L-10-3, dies MK/SSHL-002-02, applicator with dies APLMK SSHL002-02 (p.1). The top entry version of this header is BM04B-GHS-TBT ([adom/bm04b-ghs-tbt](https://wiki.adom.inc/adom/bm04b-ghs-tbt)); it uses a different land pattern.++++++## Footprint++[sm04b-ghs-tb-lf-sn.kicad_mod](sm04b-ghs-tb-lf-sn.kicad_mod) is KiCad's `Connector_JST:JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal` with its pads untouched (only its name, Value and 3D model path changed). Every pad was checked against JST's recommended PC board layout for the side entry type (p.1, drawn from the component side):++| Pad | JST layout (x, y, w x h, mm) | Footprint | Match |+|---|---|---|---|+| 1 | -1.875, -1.85, 0.6 x 1.7 | -1.875, -1.85, 0.6 x 1.7 | yes |+| 2 | -0.625, -1.85, 0.6 x 1.7 | -0.625, -1.85, 0.6 x 1.7 | yes |+| 3 | 0.625, -1.85, 0.6 x 1.7 | 0.625, -1.85, 0.6 x 1.7 | yes |+| 4 | 1.875, -1.85, 0.6 x 1.7 | 1.875, -1.85, 0.6 x 1.7 | yes |+| MP | -3.725, 1.35, 1.0 x 2.7 | -3.725, 1.35, 1.0 x 2.7 | yes |+| MP | 3.725, 1.35, 1.0 x 2.7 | 3.725, 1.35, 1.0 x 2.7 | yes |++How the JST numbers become coordinates: signal pads 0.6 wide on 1.25 pitch and 5.4 - 3.7 = 1.7 long; tab pads 1.0 x 2.7, inner edge 1.35 from the outer contact centre (so the tab centre is 1.875 + 1.35 + 0.5 = 3.725); in Y the signal pads run 3.7 to 5.4 behind the tabs' front edge, putting the signal row 3.2 mm behind the tab centres. JST's header outline sits 0.25 behind the tabs' front edge, which is KiCad's F.Fab front edge (y 2.45). One difference: KiCad rounds the pad corners (roundrect ratio 0.25, 0.15 mm radius on the signal pads); JST draws plain rectangles. Full comparison: [provenance/footprint-vs-jst.json](provenance/footprint-vs-jst.json), script [provenance/tools/compare_footprint.py](provenance/tools/compare_footprint.py).++++## Symbol++[sm04b-ghs-tb-lf-sn.kicad_sym](sm04b-ghs-tb-lf-sn.kicad_sym): reference J, contacts 1 to 4 on the left as passive pins, and one MP pin on the right for the two solder tabs, typed **unconnected** so ERC flags it if it is wired by accident. If a design wants the tabs on ground, change the pin type or connect them on the board. The symbol carries MPN, Manufacturer, Datasheet, Mouser, DigiKey, LCSC and Adom Wiki properties for the BOM; its Footprint property is KiCad's stock land pattern named above, which is pad-identical to this page's footprint.++Made with adom-symbol 1.2.6 ([provenance/symbol-create.json](provenance/symbol-create.json)) and then moved onto the 2.54 mm grid, because adom-symbol 1.2.6 places pins at y -2.00, -4.54 and so on, where wires do not land ([provenance/tools/symbol_post.py](provenance/tools/symbol_post.py)).++++## 3D models++::adom-models{src="/adom/sm04b-ghs-tb-lf-sn/render/models.json"}++| File | What it is |+|---|---|+| [sm04b-ghs-tb-lf-sn.step](sm04b-ghs-tb-lf-sn.step) | **The library model** for board CAD: KiCad's JST_GH_SM04B-GHS-TB model, bytes unchanged |+| [sm04b-ghs-tb-lf-sn.glb](sm04b-ghs-tb-lf-sn.glb) | The same model as GLB for boards and digital twins: `housing` and `contacts` nodes with ivory and tin materials, no reference artwork |+| [sm04b-ghs-tb-lf-sn-hero.glb](sm04b-ghs-tb-lf-sn-hero.glb) | The annotated page hero (adom-hero 1.4): the model plus teal dashed pad outlines, silkscreen with a pin-1 dot and pad numbers. Display only, never for a board |+| [lod/](lod/manifest.json) | Board-use detail levels (below) |++Frame for every file: Z up, seated on z = 0, centred on the KiCad footprint origin, contact tails toward +Y and the mating face toward -Y, contact 1 on pad 1; binds with zero offset and rotation.++### Where the model comes from, and how it was checked++JST publishes STEP files on jst-mfg.com, but on 2026-10-21 that site refused connections from the build host and jst.com answered 403, so **JST's STEP was not obtained**. The page uses **KiCad's library model** (kicad-packages3D, Frank Severinsen 2018, CC-BY-SA-4.0) and checks it against JST's drawing:++| Dimension (mm) | JST | KiCad model | Match |+|---|---|---|---|+| B overall width incl. tabs | 8.25 (p.2) | 8.250 | yes |+| A outer contact span | 3.75 (p.2) | 3.750 | yes |+| Contact pitch | 1.25 | 1.250 | yes |+| Contact tail width | 0.2 (p.2) | 0.200 | yes |+| Housing depth, mating face to rear | 4.05 (p.2) | 4.050 | yes |+| Contact tail beyond housing rear | 0.8 (p.2) | 0.895 | **no, 0.095 longer** |+| Height above board | 4.25 (p.2) | 4.250 | yes |+| Tab inner face to circuit 4 centre | 1.75 (p.2) | 1.750 | yes |+| Tab centre | 3.725 (p.1 layout) | 3.725 | yes |+| Housing front vs header outline | footprint y 2.45 (p.1) | 2.47 | within 0.02 |++The longer tails do not matter for the board: their tips still end 0.225 mm inside the 1.7 mm signal pads. The housing is a simplified envelope (latch window and ribs as boxes) and carries no marking, like the real part. Measured from the STEP's bounding box and the per-part bounds of the converted GLB; the full record is [provenance/3d-model.json](provenance/3d-model.json).++++++## Detail levels for board and digital-twin viewers++::adom-component-lod{src="/adom/sm04b-ghs-tb-lf-sn/render/lod/manifest.json"}++| Level | File | Triangles | Draw calls | Size |+|---|---|---|---|---|+| high | [sm04b-ghs-tb-lf-sn-high.glb](lod/sm04b-ghs-tb-lf-sn-high.glb) | 756 | 2 | 33 KiB |+| medium | [sm04b-ghs-tb-lf-sn-medium.glb](lod/sm04b-ghs-tb-lf-sn-medium.glb) | 756 | 2 | 24 KiB |+| low | [sm04b-ghs-tb-lf-sn-low.glb](lod/sm04b-ghs-tb-lf-sn-low.glb) | 744 | 2 | 24 KiB |+| super-low | [sm04b-ghs-tb-lf-sn-super-low.glb](lod/sm04b-ghs-tb-lf-sn-super-low.glb) | 722 | 2 | 24 KiB |++All four share the frame of the library model, carry no footprint or silkscreen artwork and keep the contacts and tabs. KiCad's model is already low-poly (all planar faces), so the lower levels save bytes mainly through quantization. Status: candidate; the cached previews were inspected, a streaming LOD viewer has not qualified them.++## CAD downloads++| Tool | Files |+|---|---|+| KiCad | [sm04b-ghs-tb-lf-sn.kicad_sym](sm04b-ghs-tb-lf-sn.kicad_sym), [sm04b-ghs-tb-lf-sn.kicad_mod](sm04b-ghs-tb-lf-sn.kicad_mod), [sm04b-ghs-tb-lf-sn.step](sm04b-ghs-tb-lf-sn.step) |+| Fusion / EAGLE | [sm04b-ghs-tb-lf-sn.lbr](sm04b-ghs-tb-lf-sn.lbr) (adom-lbr 2.47.5; attributes MPN, MANUFACTURER, DATASHEET, ADOM_WIKI, MOUSER_PN, DIGIKEY_PN, LCSC_PN; the tabs are pads MP and MP@2 joined to pin MP, direction nc) |+| Altium | [altium/SM04B-GHS-TB-LF-SN.SchLib](altium/SM04B-GHS-TB-LF-SN.SchLib), [altium/SM04B-GHS-TB-LF-SN.PcbLib](altium/SM04B-GHS-TB-LF-SN.PcbLib) (3D body embedded), hub [altium/sm04b-ghs-tb-lf-sn.adom-lbr.json](altium/sm04b-ghs-tb-lf-sn.adom-lbr.json). MP is a Passive pin in Altium, which has no unconnected pin type |+| Web | [sm04b-ghs-tb-lf-sn.glb](sm04b-ghs-tb-lf-sn.glb), [lod/](lod/manifest.json) |++The .lbr and the Altium files pass adom-lbr lint, and reading the Altium pair back gives the same five pins and six pads. They have not yet been opened in Fusion or Altium.++## Sourcing (checked 2026-10-21)++| Distributor | Part number | Stock | Note |+|---|---|---|---|+| Mouser | [306-SM04BGHSTBLFSN](https://www.mouser.com/en/ProductDetail/JST-Commercial/SM04B-GHS-TBLFSN?qs=QpmGXVUTftGayLYZQBIuZw%3D%3D) | 762 | Exact MPN; 0.39 USD each, 0.281 USD at 100 |+| DigiKey | [455-1566-2-ND](https://www.digikey.com/en/products/detail/jst-sales-america-inc/SM04B-GHS-TB/807788) | 0 | Listed as SM04B-GHS-TB (JST Sales America), tape and reel, status Active; product image labelled SM04B-GHS-TB(LF)(SN) |+| LCSC / JLCPCB | [C189895](https://www.lcsc.com/product-detail/C189895.html) | 5,852 | Exact MPN, extended part |++LCSC also lists C51940118, sold as XY-SM04B-GHS-TB by another maker; it is not this JST part.++## Manufacturer and resources++| Resource | Link |+|---|---|+| GH series catalog (datasheet) | [eGH.pdf on jst-mfg.com](https://www.jst-mfg.com/product/pdf/eng/eGH.pdf); copy on this page: [docs/sm04b-ghs-tb-lf-sn-datasheet.pdf](docs/sm04b-ghs-tb-lf-sn-datasheet.pdf) |+| Manufacturer | J.S.T. Mfg. Co., Ltd. ([jst-mfg.com](https://www.jst-mfg.com/)); in the Americas JST Sales America ([jst.com](https://www.jst.com/)) |+| KiCad footprint | [Connector_JST.pretty/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.kicad_mod](https://gitlab.com/kicad/libraries/kicad-footprints/-/blob/master/Connector_JST.pretty/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.kicad_mod) |+| KiCad 3D model | [Connector_JST.3dshapes/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.step](https://gitlab.com/kicad/libraries/kicad-packages3D/-/blob/master/Connector_JST.3dshapes/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.step) |++The page's PDF was taken from the datasheet link on the LCSC/JLCPCB part record because jst-mfg.com was unreachable from the build host; it is JST's eGH catalog (2 pages, no revision printed, PDF created 2016-11-18, sha256 `fe239aeccf170880`). Compare it with JST's current copy before relying on a later revision.++Cited pages:+++++## Provenance++- [provenance/sources.json](provenance/sources.json): datasheet (hash, source, cited pages), footprint upstream and the three edits, symbol tool and post-edit, .lbr and Altium tools, distributor lookup.+- [provenance/3d-model.json](provenance/3d-model.json): the 3D source, the attempts to reach JST's STEP, every dimension against JST, pin-1 evidence, conversion steps and hashes.+- [provenance/footprint-vs-jst.json](provenance/footprint-vs-jst.json): the pad-by-pad comparison.+- [verification.json](verification.json): what was checked, by whom, with file hashes; open items are listed as open.+- Tools: [provenance/tools/](provenance/tools/glb_parts.mjs) (GLB parts and materials, footprint comparison, symbol post-edit, manifests, renderer).++## What is not verified yet++- JST's own STEP has not been compared with the KiCad model.+- The symbol, footprint and 3D model have not been opened in KiCad, Fusion or Altium on a desktop; the files pass the tools' parsers and lint.+- No physical fit, mating, crimp or reflow qualification.++## License++Adom-authored files (symbol, README, manifests, provenance, renders, viewers) are CC-BY-4.0 ([LICENSE](LICENSE)). The footprint and the 3D model come from the KiCad libraries under CC-BY-SA-4.0 with the KiCad library exception ([LICENSE-KICAD.md](LICENSE-KICAD.md)). The datasheet and its figures are JST's document, included for reference ([THIRD_PARTY.md](THIRD_PARTY.md)).
THIRD_PARTY.mdadded+10@@ -0,0 +1,10 @@+# Third-party material on this page++| Files | Owner | Terms |+|---|---|---|+| sm04b-ghs-tb-lf-sn.kicad_mod, provenance/upstream/*.kicad_mod, and the footprint in sm04b-ghs-tb-lf-sn.lbr and altium/SM04B-GHS-TB-LF-SN.PcbLib | KiCad library contributors (kicad-footprints, Connector_JST) | CC-BY-SA-4.0 with the KiCad library exception, see LICENSE-KICAD.md |+| sm04b-ghs-tb-lf-sn.step, sm04b-ghs-tb-lf-sn.glb, sm04b-ghs-tb-lf-sn-hero.glb (chip part), lod/*.glb, the 3D body embedded in altium/SM04B-GHS-TB-LF-SN.PcbLib | Frank Severinsen and the KiCad library contributors (kicad-packages3D, 2018) | CC-BY-SA-4.0 with the KiCad library exception, see LICENSE-KICAD.md |+| docs/sm04b-ghs-tb-lf-sn-datasheet.pdf and docs/figures/* (pages and crops of it) | J.S.T. Mfg. Co., Ltd. | JST's document, reproduced unchanged for reference and citation. Not relicensed. Official copy: https://www.jst-mfg.com/product/pdf/eng/eGH.pdf |+| provenance/tools/render.py, provenance/tools/glbtool.py | Adom (copied from adom/ap2112k-3-3trg1) | CC-BY-4.0 |++JST, GH and the part numbers are JST's names and marks.
models.jsonadded+155@@ -0,0 +1,155 @@+{+ "schema": "adom/models@1",+ "part": "SM04B-GHS-TB(LF)(SN)",+ "models": [+ {+ "path": "sm04b-ghs-tb-lf-sn.step",+ "format": "step",+ "title": "SM04B-GHS-TB(LF)(SN), KiCad library model (library model for board CAD)",+ "status": "current",+ "slot": "model_3d_step",+ "variant": "plain",+ "use": [+ "board-cad"+ ],+ "unique": "KiCad's JST_GH_SM04B-GHS-TB model, bytes unchanged; checked against JST's drawing (provenance/3d-model.json)",+ "marking": null,+ "sha256": "aacba39c0ebf407941d81e202e5fc85121532adadfd38f26725330dea8815ac7",+ "git_blob": "237bf78bee3acfd66d5dc1ea495a8f4477a1b183",+ "bytes": 329331,+ "role": "community-library",+ "colours": true,+ "derived_from": null,+ "source": "https://gitlab.com/kicad/libraries/kicad-packages3D/-/raw/master/Connector_JST.3dshapes/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.step",+ "thumb": "docs/models/sm04b-ghs-tb-lf-sn-glb-top.png",+ "thumb_bottom": "docs/models/sm04b-ghs-tb-lf-sn-glb-bottom.png"+ },+ {+ "path": "sm04b-ghs-tb-lf-sn.glb",+ "format": "glb",+ "title": "SM04B-GHS-TB(LF)(SN), board-use GLB",+ "status": "current",+ "slot": "model_3d_plain",+ "variant": "plain",+ "use": [+ "render",+ "board-insertion"+ ],+ "unique": "Web and board-viewer copy of the STEP: named housing and contacts nodes with ivory and tin materials, no reference artwork",+ "marking": null,+ "sha256": "13dfd4dd38fc1ca3d2c1d013528430cc90dcf64c6989e1e4f86a380206034299",+ "git_blob": "a001b6e1041410a020a91e8c00d2909a3d860b82",+ "bytes": 33808,+ "role": "derived",+ "colours": true,+ "derived_from": "sm04b-ghs-tb-lf-sn.step",+ "source": "step2glb + provenance/tools/glb_parts.mjs",+ "thumb": "docs/models/sm04b-ghs-tb-lf-sn-glb-iso.png"+ },+ {+ "path": "sm04b-ghs-tb-lf-sn-hero.glb",+ "format": "glb",+ "title": "SM04B-GHS-TB(LF)(SN), annotated hero",+ "status": "current",+ "slot": "model_3d",+ "variant": "hero",+ "use": [+ "wiki-hero"+ ],+ "unique": "The board-use model plus nonphysical reference art: teal dashed pad outlines, silkscreen with a pin-1 dot, pad numbers (adom-hero 1.4); never for a board",+ "marking": null,+ "sha256": "e91b348f6121dab67a1498a6cb749e5fb5f503be6b8469665732a47e41d66847",+ "git_blob": "f1b990c7019132d5a501f0a04089595644598beb",+ "bytes": 98412,+ "role": "derived",+ "colours": true,+ "derived_from": "sm04b-ghs-tb-lf-sn.glb",+ "source": "adom/component-hero hero_glb.py",+ "thumb": "docs/proof/sm04b-ghs-tb-lf-sn-hero-preview.png"+ },+ {+ "path": "lod/sm04b-ghs-tb-lf-sn-high.glb",+ "format": "glb",+ "title": "SM04B-GHS-TB(LF)(SN), high detail level",+ "status": "current",+ "slot": null,+ "variant": "lod",+ "use": [+ "board-insertion"+ ],+ "unique": "Same bytes as the board-use GLB",+ "marking": null,+ "sha256": "13dfd4dd38fc1ca3d2c1d013528430cc90dcf64c6989e1e4f86a380206034299",+ "git_blob": "a001b6e1041410a020a91e8c00d2909a3d860b82",+ "bytes": 33808,+ "role": "derived",+ "colours": true,+ "derived_from": "sm04b-ghs-tb-lf-sn.glb",+ "source": "lod/manifest.json",+ "thumb": "lod/sm04b-ghs-tb-lf-sn-high.png"+ },+ {+ "path": "lod/sm04b-ghs-tb-lf-sn-medium.glb",+ "format": "glb",+ "title": "SM04B-GHS-TB(LF)(SN), medium detail level",+ "status": "current",+ "slot": null,+ "variant": "lod",+ "use": [+ "board-insertion"+ ],+ "unique": "Quantized",+ "marking": null,+ "sha256": "393bfa3c06a040406aa7d59d56b04f8ba8814703bf77bdb8d12b40c35690e6cc",+ "git_blob": "a526f1a07e6e4396e2d1a8e1903cc9cd268d7236",+ "bytes": 24912,+ "role": "derived",+ "colours": true,+ "derived_from": "sm04b-ghs-tb-lf-sn.glb",+ "source": "lod/manifest.json",+ "thumb": "lod/sm04b-ghs-tb-lf-sn-medium.png"+ },+ {+ "path": "lod/sm04b-ghs-tb-lf-sn-low.glb",+ "format": "glb",+ "title": "SM04B-GHS-TB(LF)(SN), low detail level",+ "status": "current",+ "slot": null,+ "variant": "lod",+ "use": [+ "board-insertion"+ ],+ "unique": "Simplified 0.5 and quantized",+ "marking": null,+ "sha256": "7d2ae02b8558a405c52f0731ae8677e8b7a3134c46c252751dc6aaede0cfa007",+ "git_blob": "6c1bd52b7daab53e5e1eb7c6fb7ca287749ab5ca",+ "bytes": 24584,+ "role": "derived",+ "colours": true,+ "derived_from": "sm04b-ghs-tb-lf-sn.glb",+ "source": "lod/manifest.json",+ "thumb": "lod/sm04b-ghs-tb-lf-sn-low.png"+ },+ {+ "path": "lod/sm04b-ghs-tb-lf-sn-super-low.glb",+ "format": "glb",+ "title": "SM04B-GHS-TB(LF)(SN), super-low detail level",+ "status": "current",+ "slot": null,+ "variant": "lod",+ "use": [+ "board-insertion"+ ],+ "unique": "Simplified 0.25 and quantized",+ "marking": null,+ "sha256": "91f28a6f3c7d5c33cf2cbf73260709204060677b3e3820b8775876d8e2006e0f",+ "git_blob": "5ea7632d1a189746362c309370b960ce3fc78452",+ "bytes": 24100,+ "role": "derived",+ "colours": true,+ "derived_from": "sm04b-ghs-tb-lf-sn.glb",+ "source": "lod/manifest.json",+ "thumb": "lod/sm04b-ghs-tb-lf-sn-super-low.png"+ }+ ]+}
provenance/3d-model.jsonadded+130@@ -0,0 +1,130 @@+{+ "schema": "adom/3d-model-provenance@1",+ "mpn": "SM04B-GHS-TB(LF)(SN)",+ "date": "2026-10-21",+ "classification": "KiCad library model (community CAD, nominal geometry), unchanged; checked against JST's drawing. Not JST CAD.",+ "manufacturer_step": {+ "status": "not obtained",+ "tried": [+ {+ "url": "https://www.jst-mfg.com/product/pdf/eng/eGH.pdf and the jst-mfg.com product pages",+ "result": "TCP connection refused from the build host, 2026-10-21"+ },+ {+ "url": "https://www.jst.com/products/crimp-style-connectors-wire-to-board-type/gh-connector/",+ "result": "HTTP 403 (bot wall), 2026-10-21"+ }+ ],+ "note": "JST's CAD downloads sit on jst-mfg.com behind its product pages; a browser session would be needed. When JST's STEP is added, keep its bytes in vendor/ and compare it with this model."+ },+ "source": {+ "file": "sm04b-ghs-tb-lf-sn.step",+ "sha256": "aacba39c0ebf407941d81e202e5fc85121532adadfd38f26725330dea8815ac7",+ "bytes": 329331,+ "url": "https://gitlab.com/kicad/libraries/kicad-packages3D/-/raw/master/Connector_JST.3dshapes/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.step",+ "header": "JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.step, Copyright (C) 2018 Frank Severinsen, CC-BY-SA 4.0 with the KiCad library exception",+ "bytes_changed": false,+ "units": "mm",+ "up_axis": "Z",+ "seating_plane": "z = 0 (housing underside at z = -0.005)",+ "origin": "KiCad footprint origin; binds with zero offset and rotation"+ },+ "frame": "Z up, seated on z = 0, centred on the KiCad footprint origin, 3D +Y = footprint -Y (KiCad convention): contact tails toward +Y, mating face toward -Y",+ "measured_with": "service-step2glb features (bounding box) and per-primitive bounds of the step2glb GLB (provenance/tools/glb_parts.mjs keeps the two step2glb materials: mat_0 housing, mat_1 contacts and tabs)",+ "dimensions_mm": [+ {+ "item": "B overall width incl. solder tabs (4 circuits)",+ "jst": "8.25 (p.2 table)",+ "model": "8.250 (x -4.125 .. 4.125)",+ "match": true+ },+ {+ "item": "A outer contact span",+ "jst": "3.75 (p.2 table)",+ "model": "3.750 (contact centres x -1.875 .. 1.875)",+ "match": true+ },+ {+ "item": "contact pitch",+ "jst": "1.25",+ "model": "1.250",+ "match": true+ },+ {+ "item": "contact tail width",+ "jst": "0.2 (p.2)",+ "model": "0.200",+ "match": true+ },+ {+ "item": "housing depth, mating face to rear",+ "jst": "4.05 (p.2 side view)",+ "model": "4.050 (y -2.470 .. 1.580)",+ "match": true+ },+ {+ "item": "contact tail beyond housing rear",+ "jst": "0.8 (p.2 side view)",+ "model": "0.895 (tail tip y 2.475)",+ "match": false,+ "note": "KiCad tails are 0.095 mm longer than JST draws. The tip still lands 0.225 mm inside the 1.7 mm signal pad (pad rear edge at 3D y 2.7), so it has no effect on the land pattern or the board outline."+ },+ {+ "item": "height above board",+ "jst": "4.25 (p.2 front view)",+ "model": "4.250 (z -0.005 .. 4.245)",+ "match": true+ },+ {+ "item": "solder tab inner face to circuit 4 centre",+ "jst": "1.75 (p.2 front view)",+ "model": "1.750 (tab x 3.625 .. 3.825)",+ "match": true+ },+ {+ "item": "solder tab centre (= footprint MP pad centre)",+ "jst": "3.725 (p.1 layout: 1.35 + 1.0 / 2 from the outer contact)",+ "model": "3.725",+ "match": true+ },+ {+ "item": "housing front vs footprint header outline",+ "jst": "0.25 behind the tab pad front edge (p.1 layout), footprint y 2.45",+ "model": "housing front at footprint y 2.47",+ "match": true,+ "note": "within 0.02 mm"+ },+ {+ "item": "mated height with GHR housing",+ "jst": "4.35 (p.1 assembly layout)",+ "model": "not checkable (no housing in this model)",+ "match": null+ }+ ],+ "pin1": {+ "footprint": "pad 1 at x = -1.875 (the -X end)",+ "model": "contact at x = -1.875 is circuit 1; the four contacts sit on pads 1 to 4 with zero offset",+ "datasheet": "p.2 side entry view (looking into the mating face, board below) labels Circuit No.1 at the left; with the mating face toward 3D -Y the viewer facing it has -X on the left",+ "render": "docs/models/sm04b-ghs-tb-lf-sn-glb-front.png (view along +Y onto the mating face: circuit 1 at the left, as JST draws it)",+ "note": "The KiCad model has no pin-1 mark (nor does the real header; JST marks circuit 1 only in the drawing). Its contact pattern is symmetric, so orientation rests on the footprint binding and the mating face direction, both checked."+ },+ "simplifications": [+ "Housing latch window, polarising ribs and cavity detail are simplified boxes, not JST geometry.",+ "Contacts are rectangular sections without bend radii.",+ "No marking: the real header carries none."+ ],+ "glb": {+ "converter": "step2glb convert --compress none (service-step2glb)",+ "post": "provenance/tools/glb_parts.mjs (glTF Transform 4.1.1): split into named nodes housing and contacts, materials housing PA9T ivory metallic 0 roughness 0.6, contacts tin metallic 1 roughness 0.35, dedup + join per part + prune",+ "file": "sm04b-ghs-tb-lf-sn.glb",+ "sha256": "13dfd4dd38fc1ca3d2c1d013528430cc90dcf64c6989e1e4f86a380206034299"+ },+ "hero": {+ "file": "sm04b-ghs-tb-lf-sn-hero.glb",+ "sha256": "e91b348f6121dab67a1498a6cb749e5fb5f503be6b8469665732a47e41d66847",+ "tool": "adom/component-hero hero_glb.py (adom-hero 1.4)",+ "result": "pads 6, silk items 6, pin-1 dot added (AI) beside pad 1, labels 5, align OK (offset 0.0 mm)",+ "overlay": "sm04b-ghs-tb-lf-sn-hero.overlay.json"+ },+ "virtual_mpn_mark": "Not applied. The real header has no marking and its top is a 3 mm deep ivory moulding; an etched MPN would read as a real marking. Recorded as an open item."+}
provenance/footprint-vs-jst.jsonadded+160@@ -0,0 +1,160 @@+{+ "schema": "adom/footprint-compare@1",+ "footprint": "sm04b-ghs-tb-lf-sn.kicad_mod",+ "source": "JST GH catalog eGH.pdf p.1, PC board layout, Side entry type (figure viewed from the connector mounting side)",+ "frame": "KiCad footprint frame, mm, Y down, origin centred between the tabs; Y reference = tab pad front edge (y = 2.700)",+ "pads": [+ {+ "pad": "1",+ "jst": {+ "x": -1.875,+ "y": -1.85,+ "w": 0.6,+ "h": 1.7+ },+ "footprint": {+ "x": -1.875,+ "y": -1.85,+ "w": 0.6,+ "h": 1.7+ },+ "shape": "roundrect",+ "delta": {+ "x": 0.0,+ "y": 0.0,+ "w": 0.0,+ "h": 0.0+ },+ "match": true+ },+ {+ "pad": "2",+ "jst": {+ "x": -0.625,+ "y": -1.85,+ "w": 0.6,+ "h": 1.7+ },+ "footprint": {+ "x": -0.625,+ "y": -1.85,+ "w": 0.6,+ "h": 1.7+ },+ "shape": "roundrect",+ "delta": {+ "x": 0.0,+ "y": 0.0,+ "w": 0.0,+ "h": 0.0+ },+ "match": true+ },+ {+ "pad": "3",+ "jst": {+ "x": 0.625,+ "y": -1.85,+ "w": 0.6,+ "h": 1.7+ },+ "footprint": {+ "x": 0.625,+ "y": -1.85,+ "w": 0.6,+ "h": 1.7+ },+ "shape": "roundrect",+ "delta": {+ "x": 0.0,+ "y": 0.0,+ "w": 0.0,+ "h": 0.0+ },+ "match": true+ },+ {+ "pad": "4",+ "jst": {+ "x": 1.875,+ "y": -1.85,+ "w": 0.6,+ "h": 1.7+ },+ "footprint": {+ "x": 1.875,+ "y": -1.85,+ "w": 0.6,+ "h": 1.7+ },+ "shape": "roundrect",+ "delta": {+ "x": 0.0,+ "y": 0.0,+ "w": 0.0,+ "h": 0.0+ },+ "match": true+ },+ {+ "pad": "MP",+ "jst": {+ "x": -3.725,+ "y": 1.35,+ "w": 1.0,+ "h": 2.7+ },+ "footprint": {+ "x": -3.725,+ "y": 1.35,+ "w": 1.0,+ "h": 2.7+ },+ "shape": "roundrect",+ "delta": {+ "x": 0.0,+ "y": 0.0,+ "w": 0.0,+ "h": 0.0+ },+ "match": true+ },+ {+ "pad": "MP",+ "jst": {+ "x": 3.725,+ "y": 1.35,+ "w": 1.0,+ "h": 2.7+ },+ "footprint": {+ "x": 3.725,+ "y": 1.35,+ "w": 1.0,+ "h": 2.7+ },+ "shape": "roundrect",+ "delta": {+ "x": 0.0,+ "y": 0.0,+ "w": 0.0,+ "h": 0.0+ },+ "match": true+ }+ ],+ "pads_in_footprint": 6,+ "all_match": true,+ "derived_checks": {+ "signal_row_to_tab_centre_y": -3.2,+ "signal_pad_rear_edge_from_reference": 5.4,+ "signal_pad_front_edge_from_reference": 3.7,+ "tab_centre_x": 3.725,+ "header_outline_front_y": 2.45+ },+ "notes": [+ "KiCad draws the pads as rounded rectangles (roundrect_rratio 0.25: 0.15 mm corner radius on the signal pads, 0.25 mm on the tabs); JST draws plain rectangles. Pad extents match exactly; the copper area is slightly smaller at the corners.",+ "KiCad F.Fab body outline: y -1.6 .. 2.45 (4.05 deep, JST p.2 side view 4.05) and x +-4.125 (8.25 = JST dimension B for 4 circuits).",+ "Pin 1: footprint pad 1 at x = -1.875, the -X end. JST p.2 side entry view (looking into the mating face, PCB below) labels Circuit No.1 at the left; with the opening toward +Y, the viewer facing the opening has -X on the left. KiCad F.Fab pin-1 chevron and the F.SilkS tick at x = -2.435 are on the same end."+ ]+}
provenance/sources.jsonadded+72@@ -0,0 +1,72 @@+{+ "schema": "adom/sources@1",+ "mpn": "SM04B-GHS-TB(LF)(SN)",+ "date": "2026-10-21",+ "datasheet": {+ "title": "JST GH CONNECTOR, 1.25 mm pitch disconnectable crimp style connectors (catalog eGH)",+ "file": "docs/sm04b-ghs-tb-lf-sn-datasheet.pdf",+ "sha256": "fe239aeccf1708802766d67888172423bbca155762a4d24fbd31a6f5bbe6f06b",+ "bytes": 210351,+ "pages": 2,+ "pdf_info": "Title eGH.doc, created 2016-11-18 (Acrobat Distiller 4.05); no revision identifier printed",+ "official_url": "https://www.jst-mfg.com/product/pdf/eng/eGH.pdf",+ "retrieved_from": "https://jlcpcb.com/api/file/downloadByFileSystemAccessId/8588905132734365696 (the datasheet JLCPCB links for C189895)",+ "retrieval_note": "On 2026-10-21 www.jst-mfg.com refused TCP connections from the build host and jst.com answered 403, so the file was taken from the JLCPCB part record. It is JST eGH.pdf (JST title, layout and page numbering). Compare with the official URL before relying on a later revision.",+ "cited_pages": {+ "p.1": "Specifications; PC board layout, side entry type; Contact SSHL-002T-P0.2",+ "p.2": "Housing GHR-xxV-S; Shrouded header side entry type (Circuit No.1, A and B dimensions, 4.05 / 0.8 / 4.25); Material and Finish; RoHS (LF)(SN) label"+ },+ "figures": [+ "docs/figures/sm04b-ghs-tb-lf-sn-ds-p1-contact-sshl-002t-p0-2.png",+ "docs/figures/sm04b-ghs-tb-lf-sn-ds-p1-side-entry-layout.png",+ "docs/figures/sm04b-ghs-tb-lf-sn-ds-p1-specifications.png",+ "docs/figures/sm04b-ghs-tb-lf-sn-ds-p1.png",+ "docs/figures/sm04b-ghs-tb-lf-sn-ds-p2-housing-ghr.png",+ "docs/figures/sm04b-ghs-tb-lf-sn-ds-p2-shrouded-header.png",+ "docs/figures/sm04b-ghs-tb-lf-sn-ds-p2.png"+ ]+ },+ "footprint": {+ "file": "sm04b-ghs-tb-lf-sn.kicad_mod",+ "sha256": "8a5b9cf624c8776a11b69533ce0a854a9d2f90308db4821cd78e0713df3f96be",+ "upstream": "KiCad Connector_JST:JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal (kicad-footprint-generator, file version 20260206)",+ "upstream_url": "https://gitlab.com/kicad/libraries/kicad-footprints/-/raw/master/Connector_JST.pretty/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.kicad_mod",+ "upstream_sha256": "d28e139f60db2bef02272b37d5075e87f3e804aef0b442d0fd81a3f7cfe07ebe",+ "changes": [+ "footprint name -> sm04b-ghs-tb-lf-sn (matches the file name)",+ "Value -> SM04B-GHS-TB(LF)(SN)",+ "3D model path -> ${KIPRJMOD}/sm04b-ghs-tb-lf-sn.step"+ ],+ "pads_changed": false,+ "check": "provenance/footprint-vs-jst.json",+ "license": "CC-BY-SA-4.0 with the KiCad library exception (LICENSE-KICAD.md)"+ },+ "symbol": {+ "file": "sm04b-ghs-tb-lf-sn.kicad_sym",+ "sha256": "f705bb40a8fd7fd7effcfb19e49c05ef0a519072ac9aa4b27761c23c6ee8c142",+ "tool": "adom-symbol 1.2.6 create (provenance/symbol-create.json), --no-chip-outline",+ "post_edit": "provenance/tools/symbol_post.py: pins moved onto the 2.54 mm grid (adom-symbol 1.2.6 put them at y -2.00, -4.54, ...), body narrowed, Footprint property set, generator sentence trimmed from Description",+ "license": "CC-BY-4.0 (Adom-authored)"+ },+ "lbr": {+ "file": "sm04b-ghs-tb-lf-sn.lbr",+ "sha256": "e4bc5f23ea29d9c0d481329e0562af3f5741b2e13c1a5c018d51760db1557df7",+ "tool": "adom-lbr 2.47.5 generate --symbol-layout keep --part-metadata page.json --package-name SM04B-GHS-TB",+ "post_edit": "MP pin direction io -> nc (adom-lbr 2.47.5 writes a KiCad no_connect pin as io); lint passes after the edit"+ },+ "altium": {+ "files": {+ "SM04B-GHS-TB-LF-SN.PcbLib": "58dd92e456386ff52c9fd1fc97c56a45f5dba0fbabd5bc6efb764a57d4154a50",+ "SM04B-GHS-TB-LF-SN.SchLib": "0cfdfdb6184b0700cd992b4da2e5cfaa8424dfe91555f33bc6adb2ecb7810e48",+ "sm04b-ghs-tb-lf-sn.adom-lbr.json": "272049baecd3a1637a2b748a1df2f4b476096b4f29479b83521049b5e836867b"+ },+ "tool": "adom-lbr 2.47.5 import-kicad, then assemble-altium --no-dedupe with the page STEP beside the hub JSON (1 model embedded)",+ "round_trip": "adom-lbr import-altium of the SchLib + PcbLib gives the same 5 pins and 6 pads; MP reads back as Passive (Altium has no no-connect pin type)"+ },+ "distributors": {+ "tool": "adom-parts-search search SM04B-GHS-TB(LF)(SN), 2026-10-21",+ "mouser": "306-SM04BGHSTBLFSN (exact MPN, 762 in stock)",+ "digikey": "455-1566-2-ND (listed as SM04B-GHS-TB, JST Sales America; 0 in stock; status Active)",+ "lcsc": "C189895 (exact MPN, 5,852 in stock)"+ }+}
provenance/symbol-create.jsonadded+57@@ -0,0 +1,57 @@+{+ "symbolName": "SM04B-GHS-TB(LF)(SN)",+ "value": "SM04B-GHS-TB(LF)(SN)",+ "mpn": "SM04B-GHS-TB(LF)(SN)",+ "manufacturer": "JST",+ "description": "JST GH 1.25 mm pitch, 4 circuits, side entry (right angle) SMT shrouded header with two solder tabs. Mates with GHR-04V-S housing and SSHL-002T-P0.2 crimp contacts.",+ "datasheetUrl": "https://www.jst-mfg.com/product/pdf/eng/eGH.pdf",+ "footprint": "adom:sm04b-ghs-tb-lf-sn",+ "wikiUrl": "https://wiki.adom.inc/adom/sm04b-ghs-tb-lf-sn",+ "distributors": {+ "mouser": "306-SM04BGHSTBLFSN",+ "digikey": "455-1566-2-ND",+ "lcsc": "C189895"+ },+ "pinLayout": "left-right",+ "preferences": {+ "chipOutline": false+ },+ "pins": [+ {+ "number": "1",+ "name": "1",+ "type": "passive",+ "group": "Contacts",+ "side": "left"+ },+ {+ "number": "2",+ "name": "2",+ "type": "passive",+ "group": "Contacts",+ "side": "left"+ },+ {+ "number": "3",+ "name": "3",+ "type": "passive",+ "group": "Contacts",+ "side": "left"+ },+ {+ "number": "4",+ "name": "4",+ "type": "passive",+ "group": "Contacts",+ "side": "left"+ },+ {+ "number": "MP",+ "name": "MP",+ "type": "no_connect",+ "group": "Mounting tabs",+ "side": "right"+ }+ ],+ "referencePrefix": "J"+}
provenance/tools/__pycache__/glbtool.cpython-312.pycadded⋯ 1 unchanged line ⋯
provenance/tools/build_manifests.pyadded+118@@ -0,0 +1,118 @@+#!/usr/bin/env python3+"""Write provenance/sources.json, provenance/3d-model.json, lod/manifest.json and models.json for+adom/sm04b-ghs-tb-lf-sn from the files in the page tree (run from the page root).+Hashes are sha256 of the bytes as published; git_blob is the git blob id (what the wiki serves)."""+import hashlib, json, os, subprocess, sys+D = '2026-10-21'+def sha(p): return hashlib.sha256(open(p, 'rb').read()).hexdigest()+def blob(p):+ b = open(p, 'rb').read(); return hashlib.sha1(b'blob %d\0' % len(b) + b).hexdigest()+def size(p): return os.path.getsize(p)+stats = {s['file']: s for s in json.loads(subprocess.check_output([sys.executable, 'provenance/tools/glbtool.py', 'stats',+ 'sm04b-ghs-tb-lf-sn.glb', 'sm04b-ghs-tb-lf-sn-hero.glb'] + [f'lod/sm04b-ghs-tb-lf-sn-{l}.glb' for l in ('high', 'medium', 'low', 'super-low')]))}+STEP = 'sm04b-ghs-tb-lf-sn.step'+KICAD_STEP_URL = 'https://gitlab.com/kicad/libraries/kicad-packages3D/-/raw/master/Connector_JST.3dshapes/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.step'+KICAD_FP_URL = 'https://gitlab.com/kicad/libraries/kicad-footprints/-/raw/master/Connector_JST.pretty/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.kicad_mod'+DS = 'docs/sm04b-ghs-tb-lf-sn-datasheet.pdf'+sources = {+ 'schema': 'adom/sources@1', 'mpn': 'SM04B-GHS-TB(LF)(SN)', 'date': D,+ 'datasheet': {'title': 'JST GH CONNECTOR, 1.25 mm pitch disconnectable crimp style connectors (catalog eGH)', 'file': DS,+ 'sha256': sha(DS), 'bytes': size(DS), 'pages': 2, 'pdf_info': 'Title eGH.doc, created 2016-11-18 (Acrobat Distiller 4.05); no revision identifier printed',+ 'official_url': 'https://www.jst-mfg.com/product/pdf/eng/eGH.pdf',+ 'retrieved_from': 'https://jlcpcb.com/api/file/downloadByFileSystemAccessId/8588905132734365696 (the datasheet JLCPCB links for C189895)',+ 'retrieval_note': 'On 2026-10-21 www.jst-mfg.com refused TCP connections from the build host and jst.com answered 403, so the file was taken from the JLCPCB part record. It is JST eGH.pdf (JST title, layout and page numbering). Compare with the official URL before relying on a later revision.',+ 'cited_pages': {'p.1': 'Specifications; PC board layout, side entry type; Contact SSHL-002T-P0.2', 'p.2': 'Housing GHR-xxV-S; Shrouded header side entry type (Circuit No.1, A and B dimensions, 4.05 / 0.8 / 4.25); Material and Finish; RoHS (LF)(SN) label'},+ 'figures': sorted('docs/figures/' + f for f in os.listdir('docs/figures'))},+ 'footprint': {'file': 'sm04b-ghs-tb-lf-sn.kicad_mod', 'sha256': sha('sm04b-ghs-tb-lf-sn.kicad_mod'),+ 'upstream': 'KiCad Connector_JST:JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal (kicad-footprint-generator, file version 20260206)', 'upstream_url': KICAD_FP_URL,+ 'upstream_sha256': '%s' % sha('provenance/upstream/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.kicad_mod'),+ 'changes': ['footprint name -> sm04b-ghs-tb-lf-sn (matches the file name)', 'Value -> SM04B-GHS-TB(LF)(SN)', '3D model path -> ${KIPRJMOD}/sm04b-ghs-tb-lf-sn.step'],+ 'pads_changed': False, 'check': 'provenance/footprint-vs-jst.json', 'license': 'CC-BY-SA-4.0 with the KiCad library exception (LICENSE-KICAD.md)'},+ 'symbol': {'file': 'sm04b-ghs-tb-lf-sn.kicad_sym', 'sha256': sha('sm04b-ghs-tb-lf-sn.kicad_sym'), 'tool': 'adom-symbol 1.2.6 create (provenance/symbol-create.json), --no-chip-outline',+ 'post_edit': 'provenance/tools/symbol_post.py: pins moved onto the 2.54 mm grid (adom-symbol 1.2.6 put them at y -2.00, -4.54, ...), body narrowed, Footprint property set, generator sentence trimmed from Description',+ 'license': 'CC-BY-4.0 (Adom-authored)'},+ 'lbr': {'file': 'sm04b-ghs-tb-lf-sn.lbr', 'sha256': sha('sm04b-ghs-tb-lf-sn.lbr'), 'tool': 'adom-lbr 2.47.5 generate --symbol-layout keep --part-metadata page.json --package-name SM04B-GHS-TB',+ 'post_edit': 'MP pin direction io -> nc (adom-lbr 2.47.5 writes a KiCad no_connect pin as io); lint passes after the edit'},+ 'altium': {'files': {f: sha('altium/' + f) for f in sorted(os.listdir('altium'))}, 'tool': 'adom-lbr 2.47.5 import-kicad, then assemble-altium --no-dedupe with the page STEP beside the hub JSON (1 model embedded)',+ 'round_trip': 'adom-lbr import-altium of the SchLib + PcbLib gives the same 5 pins and 6 pads; MP reads back as Passive (Altium has no no-connect pin type)'},+ 'distributors': {'tool': 'adom-parts-search search SM04B-GHS-TB(LF)(SN), 2026-10-21', 'mouser': '306-SM04BGHSTBLFSN (exact MPN, 762 in stock)',+ 'digikey': '455-1566-2-ND (listed as SM04B-GHS-TB, JST Sales America; 0 in stock; status Active)', 'lcsc': 'C189895 (exact MPN, 5,852 in stock)'},+}+json.dump(sources, open('provenance/sources.json', 'w'), indent=1)++def dim(item, jst, model, ok, note=''):+ return {'item': item, 'jst': jst, 'model': model, 'match': ok, **({'note': note} if note else {})}+model3d = {+ 'schema': 'adom/3d-model-provenance@1', 'mpn': 'SM04B-GHS-TB(LF)(SN)', 'date': D,+ 'classification': "KiCad library model (community CAD, nominal geometry), unchanged; checked against JST's drawing. Not JST CAD.",+ 'manufacturer_step': {'status': 'not obtained', 'tried': [+ {'url': 'https://www.jst-mfg.com/product/pdf/eng/eGH.pdf and the jst-mfg.com product pages', 'result': 'TCP connection refused from the build host, 2026-10-21'},+ {'url': 'https://www.jst.com/products/crimp-style-connectors-wire-to-board-type/gh-connector/', 'result': 'HTTP 403 (bot wall), 2026-10-21'}],+ 'note': "JST's CAD downloads sit on jst-mfg.com behind its product pages; a browser session would be needed. When JST's STEP is added, keep its bytes in vendor/ and compare it with this model."},+ 'source': {'file': STEP, 'sha256': sha(STEP), 'bytes': size(STEP), 'url': KICAD_STEP_URL,+ 'header': 'JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.step, Copyright (C) 2018 Frank Severinsen, CC-BY-SA 4.0 with the KiCad library exception',+ 'bytes_changed': False, 'units': 'mm', 'up_axis': 'Z', 'seating_plane': 'z = 0 (housing underside at z = -0.005)', 'origin': 'KiCad footprint origin; binds with zero offset and rotation'},+ 'frame': 'Z up, seated on z = 0, centred on the KiCad footprint origin, 3D +Y = footprint -Y (KiCad convention): contact tails toward +Y, mating face toward -Y',+ 'measured_with': 'service-step2glb features (bounding box) and per-primitive bounds of the step2glb GLB (provenance/tools/glb_parts.mjs keeps the two step2glb materials: mat_0 housing, mat_1 contacts and tabs)',+ 'dimensions_mm': [+ dim('B overall width incl. solder tabs (4 circuits)', '8.25 (p.2 table)', '8.250 (x -4.125 .. 4.125)', True),+ dim('A outer contact span', '3.75 (p.2 table)', '3.750 (contact centres x -1.875 .. 1.875)', True),+ dim('contact pitch', '1.25', '1.250', True),+ dim('contact tail width', '0.2 (p.2)', '0.200', True),+ dim('housing depth, mating face to rear', '4.05 (p.2 side view)', '4.050 (y -2.470 .. 1.580)', True),+ dim('contact tail beyond housing rear', '0.8 (p.2 side view)', '0.895 (tail tip y 2.475)', False, 'KiCad tails are 0.095 mm longer than JST draws. The tip still lands 0.225 mm inside the 1.7 mm signal pad (pad rear edge at 3D y 2.7), so it has no effect on the land pattern or the board outline.'),+ dim('height above board', '4.25 (p.2 front view)', '4.250 (z -0.005 .. 4.245)', True),+ dim('solder tab inner face to circuit 4 centre', '1.75 (p.2 front view)', '1.750 (tab x 3.625 .. 3.825)', True),+ dim('solder tab centre (= footprint MP pad centre)', '3.725 (p.1 layout: 1.35 + 1.0 / 2 from the outer contact)', '3.725', True),+ dim('housing front vs footprint header outline', '0.25 behind the tab pad front edge (p.1 layout), footprint y 2.45', 'housing front at footprint y 2.47', True, 'within 0.02 mm'),+ dim('mated height with GHR housing', '4.35 (p.1 assembly layout)', 'not checkable (no housing in this model)', None)],+ 'pin1': {'footprint': 'pad 1 at x = -1.875 (the -X end)', 'model': 'contact at x = -1.875 is circuit 1; the four contacts sit on pads 1 to 4 with zero offset',+ 'datasheet': 'p.2 side entry view (looking into the mating face, board below) labels Circuit No.1 at the left; with the mating face toward 3D -Y the viewer facing it has -X on the left',+ 'render': 'docs/models/sm04b-ghs-tb-lf-sn-glb-front.png (view along +Y onto the mating face: circuit 1 at the left, as JST draws it)',+ 'note': 'The KiCad model has no pin-1 mark (nor does the real header; JST marks circuit 1 only in the drawing). Its contact pattern is symmetric, so orientation rests on the footprint binding and the mating face direction, both checked.'},+ 'simplifications': ['Housing latch window, polarising ribs and cavity detail are simplified boxes, not JST geometry.', 'Contacts are rectangular sections without bend radii.', 'No marking: the real header carries none.'],+ 'glb': {'converter': 'step2glb convert --compress none (service-step2glb)', 'post': 'provenance/tools/glb_parts.mjs (glTF Transform 4.1.1): split into named nodes housing and contacts, materials housing PA9T ivory metallic 0 roughness 0.6, contacts tin metallic 1 roughness 0.35, dedup + join per part + prune',+ 'file': 'sm04b-ghs-tb-lf-sn.glb', 'sha256': sha('sm04b-ghs-tb-lf-sn.glb')},+ 'hero': {'file': 'sm04b-ghs-tb-lf-sn-hero.glb', 'sha256': sha('sm04b-ghs-tb-lf-sn-hero.glb'), 'tool': 'adom/component-hero hero_glb.py (adom-hero 1.4)', 'result': 'pads 6, silk items 6, pin-1 dot added (AI) beside pad 1, labels 5, align OK (offset 0.0 mm)', 'overlay': 'sm04b-ghs-tb-lf-sn-hero.overlay.json'},+ 'virtual_mpn_mark': 'Not applied. The real header has no marking and its top is a 3 mm deep ivory moulding; an etched MPN would read as a real marking. Recorded as an open item.',+}+json.dump(model3d, open('provenance/3d-model.json', 'w'), indent=1)++levels = []+deriv = {'high': 'board-use GLB: housing and contacts batched per part, uncompressed (lossless; same file as sm04b-ghs-tb-lf-sn.glb)',+ 'medium': 'high, KHR_mesh_quantization', 'low': 'weld + meshopt simplify ratio 0.5 error 0.002, quantized',+ 'super-low': 'weld + meshopt simplify ratio 0.25 error 0.01, quantized'}+for l in ('high', 'medium', 'low', 'super-low'):+ p = f'lod/sm04b-ghs-tb-lf-sn-{l}.glb'; s = stats[os.path.basename(p)]; png = p[:-4] + '.png'+ levels.append({'level': l, 'path': p, 'sha256': s['sha256'], 'sizeBytes': s['bytes'], 'decodedBufferBytes': s['decodedBytes'], 'triangles': s['triangles'],+ 'primitives': s['primitives'], 'boundsMm': s['boundsMm'], 'markingIncluded': False, 'helperNodes': s['helperNodes'], 'extensions': s['extensions'],+ 'derivation': deriv[l], 'review': 'candidate: inspected as cached images; not qualified in a streaming LOD viewer',+ 'preview': {'path': png, 'sha256': sha(png), 'sizeBytes': size(png), 'width': 400, 'height': 400, 'view': 'iso (front-left, from above), same camera on every level', 'sourceLevelSha256': s['sha256']}})+lod = {'schema': 'adom/component-lod@1', 'mpn': 'SM04B-GHS-TB(LF)(SN)', 'units': 'metres (glTF)', 'upAxis': 'Z (Adom/KiCad frame; seated on z = 0, centred on the footprint origin)',+ 'status': 'candidate', 'source': {'path': STEP, 'sha256': sha(STEP)},+ 'generator': 'step2glb convert --compress none -> provenance/tools/glb_parts.mjs (glTF Transform 4.1.1, meshoptimizer 0.22.0); previews by provenance/tools/render.py',+ 'note': 'The KiCad model is already low-poly (756 triangles, all planar faces), so simplification removes few triangles (744 low, 722 super-low); the lower levels mainly save bytes through quantization. No level carries footprint copper, pad labels or silkscreen; none carries a marking (the part has none).',+ 'levels': levels}+json.dump(lod, open('lod/manifest.json', 'w'), indent=1)++def rec(path, fmt, title, slot, variant, use, unique, role, derived_from, source, thumb, thumb_bottom=None):+ r = {'path': path, 'format': fmt, 'title': title, 'status': 'current', 'slot': slot, 'variant': variant, 'use': use, 'unique': unique,+ 'marking': None, 'sha256': sha(path), 'git_blob': blob(path), 'bytes': size(path), 'role': role, 'colours': True,+ 'derived_from': derived_from, 'source': source, 'thumb': thumb}+ if thumb_bottom: r['thumb_bottom'] = thumb_bottom+ return r+models = {'schema': 'adom/models@1', 'part': 'SM04B-GHS-TB(LF)(SN)', 'models': [+ rec(STEP, 'step', 'SM04B-GHS-TB(LF)(SN), KiCad library model (library model for board CAD)', 'model_3d_step', 'plain', ['board-cad'],+ "KiCad's JST_GH_SM04B-GHS-TB model, bytes unchanged; checked against JST's drawing (provenance/3d-model.json)", 'community-library', None,+ KICAD_STEP_URL, 'docs/models/sm04b-ghs-tb-lf-sn-glb-top.png', 'docs/models/sm04b-ghs-tb-lf-sn-glb-bottom.png'),+ rec('sm04b-ghs-tb-lf-sn.glb', 'glb', 'SM04B-GHS-TB(LF)(SN), board-use GLB', 'model_3d_plain', 'plain', ['render', 'board-insertion'],+ 'Web and board-viewer copy of the STEP: named housing and contacts nodes with ivory and tin materials, no reference artwork', 'derived', STEP,+ 'step2glb + provenance/tools/glb_parts.mjs', 'docs/models/sm04b-ghs-tb-lf-sn-glb-iso.png'),+ rec('sm04b-ghs-tb-lf-sn-hero.glb', 'glb', 'SM04B-GHS-TB(LF)(SN), annotated hero', 'model_3d', 'hero', ['wiki-hero'],+ 'The board-use model plus nonphysical reference art: teal dashed pad outlines, silkscreen with a pin-1 dot, pad numbers (adom-hero 1.4); never for a board',+ 'derived', 'sm04b-ghs-tb-lf-sn.glb', 'adom/component-hero hero_glb.py', 'docs/proof/sm04b-ghs-tb-lf-sn-hero-preview.png')] + [+ rec(f'lod/sm04b-ghs-tb-lf-sn-{l}.glb', 'glb', f'SM04B-GHS-TB(LF)(SN), {l} detail level', None, 'lod', ['board-insertion'],+ {'high': 'Same bytes as the board-use GLB', 'medium': 'Quantized', 'low': 'Simplified 0.5 and quantized', 'super-low': 'Simplified 0.25 and quantized'}[l],+ 'derived', 'sm04b-ghs-tb-lf-sn.glb', 'lod/manifest.json', f'lod/sm04b-ghs-tb-lf-sn-{l}.png') for l in ('high', 'medium', 'low', 'super-low')]}+json.dump(models, open('models.json', 'w'), indent=1)+print('OK sources, 3d-model, lod manifest, models.json')
provenance/tools/compare_footprint.pyadded+48@@ -0,0 +1,48 @@+#!/usr/bin/env python3+"""Compare the page footprint pad by pad with JST's recommended PC board layout for the side entry GH+header (JST GH catalog eGH.pdf p.1, 'PC board layout and Assembly layout', Side entry type).++JST gives the layout as dimensions, not coordinates. For n = 4 circuits, with KiCad's frame+(origin centred between the solder tabs in X, Y down, the header opening toward +Y):+ signal pad 0.6 wide (X) x (5.4 - 3.7) = 1.7 long (Y), pitch 1.25+ solder tab pad 1.0 wide (X) x 2.7 long (Y)+ tab inner edge 1.35 from the outer signal pad centre (X)+ Y reference the tab pads' outer (front) edge; signal pads span 3.7 .. 5.4 behind it+ header outline 0.25 behind the tab pads' front edge+ circuit 1 the leftmost circuit seen from the mating face (p.2 side entry view) = -X in this+ top view (opening toward the viewer at +Y, so the viewer's left is -X)+usage: compare_footprint.py footprint.kicad_mod out.json"""+import json, re, sys+fp = open(sys.argv[1]).read()+pads = []+for m in re.finditer(r'\(pad "([^"]+)" smd (\w+)\s*\(at ([-\d.]+) ([-\d.]+)\)\s*\(size ([-\d.]+) ([-\d.]+)\)', fp):+ pads.append(dict(number=m.group(1), shape=m.group(2), x=float(m.group(3)), y=float(m.group(4)), w=float(m.group(5)), h=float(m.group(6))))+n, pitch = 4, 1.25+xs = [(i - (n - 1) / 2) * pitch for i in range(n)] # circuit 1 at -X+tab_cx = xs[-1] + 1.35 + 1.0 / 2 # 3.725+front = None+# the drawing's Y reference: front edge of the tab pads; take it from the footprint's tabs and check the rest relative to it+tabs = [p for p in pads if p['number'] == 'MP']+front = max(p['y'] + p['h'] / 2 for p in tabs)+want = [dict(number=str(i + 1), x=xs[i], y=front - (3.7 + 5.4) / 2, w=0.6, h=1.7) for i in range(n)]+want += [dict(number='MP', x=-tab_cx, y=front - 2.7 / 2, w=1.0, h=2.7), dict(number='MP', x=tab_cx, y=front - 2.7 / 2, w=1.0, h=2.7)]+rows, ok = [], True+for w in want:+ p = min((p for p in pads if p['number'] == w['number']), key=lambda p: abs(p['x'] - w['x']) + abs(p['y'] - w['y']))+ d = {k: round(p[k] - w[k], 4) for k in ('x', 'y', 'w', 'h')}+ good = all(abs(v) < 0.001 for v in d.values())+ ok &= good+ rows.append(dict(pad=w['number'], jst=dict((k, round(w[k], 4)) for k in ('x', 'y', 'w', 'h')),+ footprint=dict((k, p[k]) for k in ('x', 'y', 'w', 'h')), shape=p['shape'], delta=d, match=good))+res = dict(schema='adom/footprint-compare@1', footprint=sys.argv[1],+ source='JST GH catalog eGH.pdf p.1, PC board layout, Side entry type (figure viewed from the connector mounting side)',+ frame='KiCad footprint frame, mm, Y down, origin centred between the tabs; Y reference = tab pad front edge (y = %.3f)' % front,+ pads=rows, pads_in_footprint=len(pads), all_match=ok,+ derived_checks=dict(signal_row_to_tab_centre_y=round(want[0]['y'] - want[4]['y'], 3),+ signal_pad_rear_edge_from_reference=5.4, signal_pad_front_edge_from_reference=3.7,+ tab_centre_x=tab_cx, header_outline_front_y=round(front - 0.25, 3)),+ notes=['KiCad draws the pads as rounded rectangles (roundrect_rratio 0.25: 0.15 mm corner radius on the signal pads, 0.25 mm on the tabs); JST draws plain rectangles. Pad extents match exactly; the copper area is slightly smaller at the corners.',+ 'KiCad F.Fab body outline: y -1.6 .. 2.45 (4.05 deep, JST p.2 side view 4.05) and x +-4.125 (8.25 = JST dimension B for 4 circuits).',+ 'Pin 1: footprint pad 1 at x = -1.875, the -X end. JST p.2 side entry view (looking into the mating face, PCB below) labels Circuit No.1 at the left; with the opening toward +Y, the viewer facing the opening has -X on the left. KiCad F.Fab pin-1 chevron and the F.SilkS tick at x = -2.435 are on the same end.'])+json.dump(res, open(sys.argv[2], 'w'), indent=1)+print('all_match', ok, [ (r['pad'], r['match']) for r in rows ])
provenance/tools/glb_parts.mjsadded+51@@ -0,0 +1,51 @@+// Turn step2glb's single-mesh GLB of the KiCad SM04B-GHS-TB model into named, batched parts with physical materials.+// step2glb (service-step2glb) writes one mesh with two base-colour materials: mat_0 = housing, mat_1 = contacts and+// solder tabs (checked by bounds: mat_1 spans the four contacts at x = +-0.625, +-1.875 and the tabs at x = +-3.725).+// Output nodes: "housing" (PA9T, natural ivory: metallic 0, roughness 0.6) and "contacts" (tin plated phosphor bronze+// contacts and brass solder tabs: metallic 1, roughness 0.35). Geometry and the Z-up frame are unchanged.+// usage: node glb_parts.mjs in.glb out.glb [--simplify ratio:error] [--quantize] (run with glTF Transform 4.1)+import { NodeIO } from '@gltf-transform/core';+import { ALL_EXTENSIONS } from '@gltf-transform/extensions';+import { dedup, join, prune, weld, simplify, quantize } from '@gltf-transform/functions';+import { MeshoptSimplifier } from 'meshoptimizer';+const [, , src, out, ...opts] = process.argv;+const io = new NodeIO().registerExtensions(ALL_EXTENSIONS);+const doc = await io.read(src);+const root = doc.getRoot();+const scene = root.getDefaultScene() || root.listScenes()[0];+const SPEC = {+ mat_0: { part: 'housing', name: 'Adom.Housing (PA9T, natural ivory)', color: [0.80, 0.78, 0.66, 1], metal: 0, rough: 0.6 },+ mat_1: { part: 'contacts', name: 'Adom.Contacts (tin plated)', color: [0.72, 0.72, 0.70, 1], metal: 1, rough: 0.35 },+};+const srcNodes = root.listNodes().filter(n => n.getMesh());+if (srcNodes.length !== 1) throw new Error('expected one mesh node from step2glb, got ' + srcNodes.length);+const srcNode = srcNodes[0];+const meshes = {};+const srcPrims = srcNode.getMesh().listPrimitives().map(p => [p, p.getMaterial()?.getName()]);+for (const [p, matName] of srcPrims) {+ const s = SPEC[matName];+ if (!s) throw new Error('unexpected material ' + matName);+ if (!meshes[s.part]) {+ const m = p.getMaterial();+ m.setName(s.name).setBaseColorFactor(s.color).setMetallicFactor(s.metal).setRoughnessFactor(s.rough);+ meshes[s.part] = doc.createMesh(s.part);+ }+ meshes[s.part].addPrimitive(p);+}+const parent = doc.createNode('SM04B-GHS-TB(LF)(SN)').setTranslation(srcNode.getTranslation()).setRotation(srcNode.getRotation()).setScale(srcNode.getScale());+for (const [part, mesh] of Object.entries(meshes)) parent.addChild(doc.createNode(part).setMesh(mesh));+scene.addChild(parent);+srcNode.dispose();+const steps = [dedup(), join({ keepNamed: true }), prune()];+const si = opts.indexOf('--simplify');+if (si >= 0) {+ const [ratio, error] = opts[si + 1].split(':').map(Number);+ await MeshoptSimplifier.ready;+ steps.push(weld(), simplify({ simplifier: MeshoptSimplifier, ratio, error, lockBorder: false }), prune());+}+if (opts.includes('--quantize')) steps.push(quantize());+await doc.transform(...steps);+await io.write(out, doc);+let prims = 0, tris = 0;+for (const m of root.listMeshes()) for (const p of m.listPrimitives()) { prims++; const i = p.getIndices(); tris += (i ? i.getCount() : p.getAttribute('POSITION').getCount()) / 3; }+console.log(JSON.stringify({ out, prims, tris, nodes: root.listNodes().map(n => n.getName()) }));
provenance/tools/glbtool.pyadded+108@@ -0,0 +1,108 @@+#!/usr/bin/env python3+"""GLB stats + preview render (numpy/PIL, flat shading), reading quantized accessors correctly.+usage: glbtool.py stats a.glb [...] -> JSON per file+ glbtool.py render a.glb out.png [view=iso|top] [size=400]"""+import sys, json, hashlib, math, struct+import numpy as np+from pygltflib import GLTF2+from PIL import Image, ImageDraw+CT = {5120: np.int8, 5121: np.uint8, 5122: np.int16, 5123: np.uint16, 5125: np.uint32, 5126: np.float32}+NC = {"SCALAR": 1, "VEC2": 2, "VEC3": 3, "VEC4": 4, "MAT4": 16}+def acc(g, blob, i):+ a = g.accessors[i]; bv = g.bufferViews[a.bufferView]; dt = np.dtype(CT[a.componentType]); n = NC[a.type]+ off = (bv.byteOffset or 0) + (a.byteOffset or 0); stride = bv.byteStride or dt.itemsize * n+ raw = np.frombuffer(blob, dtype=np.uint8, count=stride * (a.count - 1) + dt.itemsize * n, offset=off)+ arr = np.lib.stride_tricks.as_strided(raw, shape=(a.count, n * dt.itemsize), strides=(stride, 1)).copy().view(dt).reshape(a.count, n).astype(np.float64)+ if a.normalized:+ arr = {np.int8: lambda x: np.maximum(x / 127, -1), np.uint8: lambda x: x / 255, np.int16: lambda x: np.maximum(x / 32767, -1), np.uint16: lambda x: x / 65535}[dt.type](arr)+ return arr+def node_mat(n):+ if n.matrix: return np.array(n.matrix).reshape(4, 4).T+ M = np.eye(4)+ if n.scale: M = np.diag(list(n.scale) + [1]) @ M+ if n.rotation:+ x, y, z, w = n.rotation+ R = np.array([[1-2*(y*y+z*z), 2*(x*y-z*w), 2*(x*z+y*w)], [2*(x*y+z*w), 1-2*(x*x+z*z), 2*(y*z-x*w)], [2*(x*z-y*w), 2*(y*z+x*w), 1-2*(x*x+y*y)]])+ R4 = np.eye(4); R4[:3, :3] = R; M = R4 @ M+ if n.translation:+ T = np.eye(4); T[:3, 3] = n.translation; M = T @ M+ return M+def walk(g):+ out = []+ def rec(i, P, path):+ n = g.nodes[i]; M = P @ node_mat(n); p = path + [n.name or str(i)]+ if n.mesh is not None: out.append((n, M, p))+ for c in n.children or []: rec(c, M, p)+ for r in g.scenes[g.scene or 0].nodes: rec(r, np.eye(4), [])+ return out+def load(f):+ g = GLTF2().load(f); return g, g.binary_blob()+def tris(f):+ g, blob = load(f); res = []+ for n, M, path in walk(g):+ for pr in g.meshes[n.mesh].primitives:+ P = acc(g, blob, pr.attributes.POSITION); P = (M @ np.c_[P, np.ones(len(P))].T).T[:, :3]+ I = acc(g, blob, pr.indices).astype(int).reshape(-1, 3) if pr.indices is not None else np.arange(len(P)).reshape(-1, 3)+ mat = g.materials[pr.material] if pr.material is not None else None+ col = mat.pbrMetallicRoughness.baseColorFactor if mat and mat.pbrMetallicRoughness else [0.6, 0.6, 0.6, 1]+ res.append(dict(path="/".join(path), P=P, I=I, col=col))+ return g, res+def stats(f):+ g, res = tris(f); data = open(f, "rb").read()+ allP = np.vstack([r["P"] for r in res])+ dec = 0+ for a in g.accessors: dec += a.count * NC[a.type] * np.dtype(CT[a.componentType]).itemsize+ names = [n.name or "" for n in g.nodes]+ helpers = [n for n in names if any(k in n.lower() for k in ("pad outline", "silkscreen", "signal name", "reference artwork", "footprint pads", "courtyard"))]+ mark = [r for r in res if "LaserEtch" in r["path"]]+ chip = [r for r in res if "LaserEtch" not in r["path"]]+ mz = None+ if mark:+ mp = np.vstack([r["P"] for r in mark]); top = max(r["P"][:, 2].max() for r in chip)+ mz = dict(mark_z_min_mm=round(mp[:, 2].min() * 1000, 4), mark_z_max_mm=round(mp[:, 2].max() * 1000, 4), chip_top_mm=round(top * 1000, 4),+ lift_um=round((mp[:, 2].min() - top) * 1e6, 2))+ return dict(file=f.split("/")[-1], sha256=hashlib.sha256(data).hexdigest(), bytes=len(data), triangles=int(sum(len(r["I"]) for r in res)),+ primitives=len(res), decodedBytes=int(dec), boundsMm=[round(v * 1000, 3) for v in (*allP.min(0), *allP.max(0))],+ helperNodes=helpers, mark=mz, extensions=g.extensionsUsed or [])+def render(f, out, view="iso", size=400):+ g, res = tris(f)+ allP = np.vstack([r["P"] for r in res]); c = (allP.min(0) + allP.max(0)) / 2+ if view == "top":+ R = np.eye(3)+ elif view.startswith("hero"):+ # pose: reading direction (-Y in the board frame) turned to +X, then a 3/4 view from the front, above+ P90 = np.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]])+ a = math.radians(28); b = math.radians(-48)+ Rz = np.array([[math.cos(a), -math.sin(a), 0], [math.sin(a), math.cos(a), 0], [0, 0, 1]])+ Rx = np.array([[1, 0, 0], [0, math.cos(b), -math.sin(b)], [0, math.sin(b), math.cos(b)]])+ R = Rx @ Rz @ P90+ else: # iso: rotate -45 about z then tilt 55 about x (camera from front-left-up, pin-1 side)+ a = math.radians(-35); b = math.radians(-55)+ Rz = np.array([[math.cos(a), -math.sin(a), 0], [math.sin(a), math.cos(a), 0], [0, 0, 1]])+ Rx = np.array([[1, 0, 0], [0, math.cos(b), -math.sin(b)], [0, math.sin(b), math.cos(b)]])+ R = Rx @ Rz+ light = np.array([0.3, -0.5, 0.8]); light /= np.linalg.norm(light)+ polys = []+ for r in res:+ Q = (r["P"] - c) @ R.T+ for t in r["I"]:+ v = Q[t]; nrm = np.cross(v[1] - v[0], v[2] - v[0]); ln = np.linalg.norm(nrm)+ if ln == 0: continue+ nrm /= ln+ if nrm[2] < 0: nrm = -nrm+ sh = 0.35 + 0.65 * max(0, float(nrm @ light))+ col = tuple(int(255 * min(1, (x ** (1 / 2.2)) * sh)) for x in r["col"][:3])+ polys.append(((1 if "LaserEtch" in r["path"] else 0), v[:, 2].mean(), v[:, :2], col))+ polys.sort(key=lambda p: (p[0], p[1]))+ polys = [(p[1], p[2], p[3]) for p in polys]+ Q = np.vstack([p[1] for p in polys]); ext = (Q.max(0) - Q.min(0)).max()+ s = size * 0.86 / ext; S = 3+ im = Image.new("RGBA", (size * S, size * S), (0, 0, 0, 0) if view.startswith("hero") else (36, 40, 46, 255)); d = ImageDraw.Draw(im)+ for _, v, col in polys:+ d.polygon([(size * S / 2 + x * s * S, size * S / 2 - y * s * S) for x, y in v], fill=col)+ im.resize((size, size), Image.LANCZOS).save(out)+if __name__ == "__main__":+ if sys.argv[1] == "stats":+ print(json.dumps([stats(f) for f in sys.argv[2:]], indent=1))+ else:+ render(sys.argv[2], sys.argv[3], *(sys.argv[4:5] or ["iso"]), *(map(int, sys.argv[5:6])))
provenance/tools/render.pyadded+120@@ -0,0 +1,120 @@+#!/usr/bin/env python3+"""Depth-buffered orthographic render of a chip GLB (or STEP), for LOD previews and close-ups.+Reads geometry with the page's glbtool loader (quantized accessors handled), shades with a key + fill+light, Lambert plus a Blinn specular that follows each material's metallic/roughness (so matte tin+reads as tin and epoxy as epoxy). Orthographic, 3x supersampled.+usage: render.py model.glb|model.step out.png [--view iso|top|front|side|corner] [--size 400]+ [--box x0,x1,y0,y1,z0,z1 (mm: frame only this region)] [--bg 36,40,46] [--alpha]+views: top, bottom, iso = from front-left-up (pin-1 side); corner = low 3/4 view onto a lead corner;+front = along +Y; side = along -X."""+import sys, math, argparse+import numpy as np+from PIL import Image+sys.path.insert(0, sys.argv[0].rsplit("/", 1)[0])++def load(path):+ if path.lower().endswith((".step", ".stp")):+ import cadquery as cq+ s = cq.importers.importStep(path).val()+ v, t = s.tessellate(0.002, 0.1)+ P = np.array([[p.x, p.y, p.z] for p in v]) / 1000.0+ return [dict(path="step", P=P, I=np.array(t), col=[0.6, 0.6, 0.6, 1], metal=0.0, rough=0.6)]+ from pygltflib import GLTF2+ import importlib.util+ spec = importlib.util.spec_from_file_location("glbtool", ARGS.glbtool)+ gt = importlib.util.module_from_spec(spec); spec.loader.exec_module(gt)+ g, res = gt.tris(path)+ # attach metallic/roughness per primitive (glbtool keeps only the colour)+ i = 0+ for n, M, p in gt.walk(g):+ for pr in g.meshes[n.mesh].primitives:+ m = g.materials[pr.material] if pr.material is not None else None+ pbr = m.pbrMetallicRoughness if m else None+ res[i]["metal"] = (pbr.metallicFactor if pbr and pbr.metallicFactor is not None else 1.0)+ res[i]["rough"] = (pbr.roughnessFactor if pbr and pbr.roughnessFactor is not None else 1.0)+ i += 1+ return res++def view_matrix(name):+ def rz(a): a = math.radians(a); return np.array([[math.cos(a), -math.sin(a), 0], [math.sin(a), math.cos(a), 0], [0, 0, 1]])+ def rx(a): a = math.radians(a); return np.array([[1, 0, 0], [0, math.cos(a), -math.sin(a)], [0, math.sin(a), math.cos(a)]])+ if name == "top": return np.eye(3)+ if name == "bottom": return rx(180) # from below, X still to the right+ if name == "front": return rx(-90) # look along +Y: X right, Z up+ if name == "side": return rx(-90) @ rz(-90) # look along -X: Y right, Z up+ if name == "corner": return rx(-68) @ rz(-38) # low 3/4 onto the -X/-Y lead corner+ return rx(-55) @ rz(-35) # iso++ap = argparse.ArgumentParser()+ap.add_argument("model"); ap.add_argument("out")+ap.add_argument("--view", default="iso"); ap.add_argument("--size", type=int, default=400)+ap.add_argument("--box"); ap.add_argument("--bg", default="36,40,46")+ap.add_argument("--turn", type=float, default=0.0, help="extra turn about Z before the view (deg)")+ap.add_argument("--alpha", action="store_true", help="transparent background (RGBA PNG)")+ap.add_argument("--glbtool", default="/tmp/claude-1001/-home-adom-project/43add640-14a6-413a-b15b-ffdadeb7cf16/scratchpad/stm32/provenance/tools/glbtool.py")+ARGS = ap.parse_args()+parts = load(ARGS.model)+R = view_matrix(ARGS.view)+if ARGS.turn:+ _a = math.radians(ARGS.turn)+ R = R @ np.array([[math.cos(_a), -math.sin(_a), 0], [math.sin(_a), math.cos(_a), 0], [0, 0, 1]])+allP = np.vstack([p["P"] for p in parts]) * 1000.0+if ARGS.box:+ b = [float(v) for v in ARGS.box.split(",")]+ corners = np.array([[x, y, z] for x in b[0:2] for y in b[2:4] for z in b[4:6]])+else:+ corners = allP+Q = corners @ R.T+lo, hi = Q.min(0), Q.max(0); ctr = (lo + hi) / 2; ext = max(hi[0] - lo[0], hi[1] - lo[1]) * 1.08+SS = 3; N = ARGS.size * SS; s = N / ext+img = np.zeros((N, N, 3)); zb = np.full((N, N), -1e9)+L1 = np.array([0.35, 0.45, 0.82]); L1 /= np.linalg.norm(L1) # key, in view space+L2 = np.array([-0.6, -0.2, 0.5]); L2 /= np.linalg.norm(L2) # fill+V = np.array([0, 0, 1.0])+for p in parts:+ X = (p["P"] * 1000.0) @ R.T+ sx = (X[:, 0] - ctr[0]) * s + N / 2; sy = N / 2 - (X[:, 1] - ctr[1]) * s; z = X[:, 2]+ col = np.array(p["col"][:3]); metal, rough = p.get("metal", 0.0), max(p.get("rough", 0.6), 0.08)+ shin = 2.0 / (rough ** 4) - 2.0+ for t in p["I"]:+ a, b2, c = t+ v0, v1, v2 = X[a], X[b2], X[c]+ nrm = np.cross(v1 - v0, v2 - v0); ln = np.linalg.norm(nrm)+ if ln == 0: continue+ nrm /= ln+ if nrm[2] < 0: nrm = -nrm+ diff = 0.18 + 0.62 * max(0, nrm @ L1) + 0.2 * max(0, nrm @ L2)+ H = (L1 + V); H /= np.linalg.norm(H)+ spec = max(0, nrm @ H) ** min(shin, 400) * (0.9 if metal > 0.5 else 0.25) * (1 - rough * 0.6)+ base = col * (0.55 + 0.45 * (1 - metal)) if metal > 0.5 else col+ shade = np.clip(base * diff + spec * (col if metal > 0.5 else np.ones(3)), 0, 1)+ shade = shade ** (1 / 2.2)+ xs = np.array([sx[a], sx[b2], sx[c]]); ys = np.array([sy[a], sy[b2], sy[c]]); zs = np.array([z[a], z[b2], z[c]])+ x0, x1 = int(max(0, np.floor(xs.min()))), int(min(N - 1, np.ceil(xs.max())))+ y0, y1 = int(max(0, np.floor(ys.min()))), int(min(N - 1, np.ceil(ys.max())))+ if x0 > x1 or y0 > y1: continue+ gx, gy = np.meshgrid(np.arange(x0, x1 + 1) + 0.5, np.arange(y0, y1 + 1) + 0.5)+ d = (ys[1] - ys[2]) * (xs[0] - xs[2]) + (xs[2] - xs[1]) * (ys[0] - ys[2])+ if abs(d) < 1e-12: continue+ w0 = ((ys[1] - ys[2]) * (gx - xs[2]) + (xs[2] - xs[1]) * (gy - ys[2])) / d+ w1 = ((ys[2] - ys[0]) * (gx - xs[2]) + (xs[0] - xs[2]) * (gy - ys[2])) / d+ w2 = 1 - w0 - w1+ m = (w0 >= -1e-6) & (w1 >= -1e-6) & (w2 >= -1e-6)+ if not m.any(): continue+ zz = w0 * zs[0] + w1 * zs[1] + w2 * zs[2]+ sub = zb[y0:y1 + 1, x0:x1 + 1]+ upd = m & (zz > sub)+ sub[upd] = zz[upd]+ img[y0:y1 + 1, x0:x1 + 1][upd] = shade+bg = np.array([int(v) for v in ARGS.bg.split(",")]) / 255.0+img[zb < -1e8] = bg+if ARGS.alpha:+ a = (zb > -1e8).astype(np.float64)[..., None]+ rgba = np.concatenate([img * a, a], 2) # premultiplied so the LANCZOS edge stays clean+ out = np.asarray(Image.fromarray((rgba * 255).astype(np.uint8), "RGBA").resize((ARGS.size, ARGS.size), Image.LANCZOS)).astype(np.float64)+ al = out[..., 3:] / 255.0+ out[..., :3] = np.where(al > 0, out[..., :3] / np.maximum(al, 1e-6), 0)+ Image.fromarray(np.clip(out, 0, 255).astype(np.uint8), "RGBA").save(ARGS.out)+else:+ Image.fromarray((img * 255).astype(np.uint8)).resize((ARGS.size, ARGS.size), Image.LANCZOS).save(ARGS.out)+print("wrote", ARGS.out)
provenance/tools/symbol_post.pyadded+37@@ -0,0 +1,37 @@+#!/usr/bin/env python3+"""Post-edit the adom-symbol 1.2.6 output for SM04B-GHS-TB(LF)(SN).+adom-symbol 1.2.6 places pins at y = -2.00, -4.54, ... (off the 2.54 mm grid, so wires do not land on them)+and sizes the body for IC pin names. This keeps every property adom-symbol wrote and only:+ * puts the pins on the 2.54 mm grid (1..4 left at y 0, -2.54, -5.08, -7.62; MP right at y 0),+ * narrows the body to suit one-character pin names (x -10.16 .. 10.16),+ * moves the group captions, Reference and Value to match,+ * sets Footprint to KiCad's stock land pattern, which is pad-identical to this page's footprint,+ * trims the generator's layout sentence from Description.+usage: symbol_post.py in.kicad_sym out.kicad_sym"""+import re, sys+src, out = sys.argv[1], sys.argv[2]+t = open(src).read()+name = 'SM04B-GHS-TB(LF)(SN)'+t = t.replace('(property "Footprint" ""', '(property "Footprint" "Connector_JST:JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal"')+t = t.replace(' 2-column symbol, pins grouped by function.', '')+t = re.sub(r'\(property "Reference" "J"\n\s+\(at [^)]*\)', '(property "Reference" "J"\n (at 0.00 5.08 0)', t)+t = re.sub(r'\(property "Value" "([^"]*)"\n\s+\(at [^)]*\)', r'(property "Value" "\1"\n (at 0.00 -12.70 0)', t)+t = re.sub(r'\(rectangle \(start [^)]*\) \(end [^)]*\)', '(rectangle (start -10.16 2.54) (end 10.16 -10.16)', t)+t = re.sub(r'\(text "Contacts" \(at [^)]*\)', '(text "Contacts" (at -9.14 1.85 0)', t)+t = re.sub(r'\(text "Mounting tabs" \(at [^)]*\)', '(text "Mounting tabs" (at 9.14 1.85 0)', t)+ys = {'1': 0.0, '2': -2.54, '3': -5.08, '4': -7.62}+def pin(m):+ kind, num = m.group(1), m.group(3)+ if num == 'MP':+ return f'(pin {kind} line (at 12.70 0.00 180) (length 2.54) (name "MP") (number "MP"))'+ return f'(pin {kind} line (at -12.70 {ys[num]:.2f} 0) (length 2.54) (name "{num}") (number "{num}"))'+t = re.sub(r'\(pin (\w+) line \(at [^)]*\) \(length [^)]*\) \(name "([^"]*)"\) \(number "([^"]*)"\)\)', pin, t)+# hidden property column under the shorter body+def shift(m):+ y = float(m.group(2))+ return f'{m.group(1)}{y + 2.54 + 2.46:.2f} 0)'+t = re.sub(r'(\(property "(?:Footprint|Datasheet|Description|Manufacturer|MPN|Adom Wiki|DigiKey|LCSC|Mouser)" "[^"]*"\n\s+\(at 0 )(-?[\d.]+) 0\)', shift, t)+for k in ys: assert f'(number "{k}")' in t+assert '(number "MP")' in t+open(out, 'w').write(t)+print('OK', out)
provenance/upstream/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.kicad_modadded+350@@ -0,0 +1,350 @@+(footprint "JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal"+ (version 20260206)+ (generator "kicad-footprint-generator")+ (layer "F.Cu")+ (descr "JST GH series connector, SM04B-GHS-TB (http://www.jst-mfg.com/product/pdf/eng/eGH.pdf)")+ (tags "connector JST GH horizontal")+ (property "Reference" "REF**"+ (at 0 -3.9 0)+ (layer "F.SilkS")+ (effects+ (font+ (size 1 1)+ (thickness 0.15)+ )+ )+ )+ (property "Value" "JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal"+ (at 0 3.9 0)+ (layer "F.Fab")+ (effects+ (font+ (size 1 1)+ (thickness 0.15)+ )+ )+ )+ (property "KiLib_Generator" "connector/SMD_single_row_plus_mounting_pad"+ (at 0 0 0)+ (layer "F.SilkS")+ (hide yes)+ (effects+ (font+ (size 1 1)+ (thickness 0.15)+ )+ )+ )+ (attr smd)+ (duplicate_pad_numbers_are_jumpers no)+ (fp_line+ (start -4.235 -1.71)+ (end -2.435 -1.71)+ (stroke+ (width 0.12)+ (type solid)+ )+ (layer "F.SilkS")+ )+ (fp_line+ (start -4.235 -0.26)+ (end -4.235 -1.71)+ (stroke+ (width 0.12)+ (type solid)+ )+ (layer "F.SilkS")+ )+ (fp_line+ (start -2.965 2.56)+ (end 2.965 2.56)+ (stroke+ (width 0.12)+ (type solid)+ )+ (layer "F.SilkS")+ )+ (fp_line+ (start -2.435 -1.71)+ (end -2.435 -2.7)+ (stroke+ (width 0.12)+ (type solid)+ )+ (layer "F.SilkS")+ )+ (fp_line+ (start 4.235 -1.71)+ (end 2.435 -1.71)+ (stroke+ (width 0.12)+ (type solid)+ )+ (layer "F.SilkS")+ )+ (fp_line+ (start 4.235 -0.26)+ (end 4.235 -1.71)+ (stroke+ (width 0.12)+ (type solid)+ )+ (layer "F.SilkS")+ )+ (fp_line+ (start -4.73 -0.5)+ (end -4.63 -0.5)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start -4.73 3.2)+ (end -4.73 -0.5)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start -4.63 -2.1)+ (end -2.68 -2.1)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start -4.63 -0.5)+ (end -4.63 -2.1)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start -2.72 2.95)+ (end -2.72 3.2)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start -2.72 3.2)+ (end -4.73 3.2)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start -2.68 -3.2)+ (end 2.68 -3.2)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start -2.68 -2.1)+ (end -2.68 -3.2)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start 2.68 -3.2)+ (end 2.68 -2.1)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start 2.68 -2.1)+ (end 4.63 -2.1)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start 2.72 2.95)+ (end -2.72 2.95)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start 2.72 3.2)+ (end 2.72 2.95)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start 4.63 -2.1)+ (end 4.63 -0.5)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start 4.63 -0.5)+ (end 4.73 -0.5)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start 4.73 -0.5)+ (end 4.73 3.2)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start 4.73 3.2)+ (end 2.72 3.2)+ (stroke+ (width 0.05)+ (type solid)+ )+ (layer "F.CrtYd")+ )+ (fp_line+ (start -4.125 -1.6)+ (end -4.125 2.45)+ (stroke+ (width 0.1)+ (type solid)+ )+ (layer "F.Fab")+ )+ (fp_line+ (start -4.125 -1.6)+ (end 4.125 -1.6)+ (stroke+ (width 0.1)+ (type solid)+ )+ (layer "F.Fab")+ )+ (fp_line+ (start -4.125 2.45)+ (end 4.125 2.45)+ (stroke+ (width 0.1)+ (type solid)+ )+ (layer "F.Fab")+ )+ (fp_line+ (start -2.375 -1.6)+ (end -1.875 -0.892893)+ (stroke+ (width 0.1)+ (type solid)+ )+ (layer "F.Fab")+ )+ (fp_line+ (start -1.875 -0.892893)+ (end -1.375 -1.6)+ (stroke+ (width 0.1)+ (type solid)+ )+ (layer "F.Fab")+ )+ (fp_line+ (start 4.125 -1.6)+ (end 4.125 2.45)+ (stroke+ (width 0.1)+ (type solid)+ )+ (layer "F.Fab")+ )+ (fp_text user "${REFERENCE}"+ (at 0 0 0)+ (layer "F.Fab")+ (effects+ (font+ (size 1 1)+ (thickness 0.15)+ )+ )+ )+ (pad "1" smd roundrect+ (at -1.875 -1.85)+ (size 0.6 1.7)+ (layers "F.Cu" "F.Mask" "F.Paste")+ (roundrect_rratio 0.25)+ )+ (pad "2" smd roundrect+ (at -0.625 -1.85)+ (size 0.6 1.7)+ (layers "F.Cu" "F.Mask" "F.Paste")+ (roundrect_rratio 0.25)+ )+ (pad "3" smd roundrect+ (at 0.625 -1.85)+ (size 0.6 1.7)+ (layers "F.Cu" "F.Mask" "F.Paste")+ (roundrect_rratio 0.25)+ )+ (pad "4" smd roundrect+ (at 1.875 -1.85)+ (size 0.6 1.7)+ (layers "F.Cu" "F.Mask" "F.Paste")+ (roundrect_rratio 0.25)+ )+ (pad "MP" smd roundrect+ (at -3.725 1.35)+ (size 1 2.7)+ (layers "F.Cu" "F.Mask" "F.Paste")+ (roundrect_rratio 0.25)+ )+ (pad "MP" smd roundrect+ (at 3.725 1.35)+ (size 1 2.7)+ (layers "F.Cu" "F.Mask" "F.Paste")+ (roundrect_rratio 0.25)+ )+ (embedded_fonts no)+ (model "${KICAD10_3DMODEL_DIR}/Connector_JST.3dshapes/JST_GH_SM04B-GHS-TB_1x04-1MP_P1.25mm_Horizontal.step"+ (offset+ (xyz 0 0 0)+ )+ (scale+ (xyz 1 1 1)+ )+ (rotate+ (xyz 0 0 0)+ )+ )+)
verification.jsonadded+182@@ -0,0 +1,182 @@+{+ "schema": "adom/verification@1",+ "part": "SM04B-GHS-TB(LF)(SN)",+ "variants": [],+ "entries": [+ {+ "date": "2026-10-21",+ "by": {+ "name": "Claude (AI agent)",+ "handle": ""+ },+ "status": "verified",+ "title": "Footprint matches JST's recommended PC board layout, pad by pad",+ "scope": [+ "footprint"+ ],+ "variants": [+ "*"+ ],+ "checks": [+ {+ "text": "Signal pads 0.6 x 1.7 mm on 1.25 mm pitch, centres x -1.875, -0.625, 0.625, 1.875 (JST p.1: 0.6, 1.25, 5.4 - 3.7)",+ "result": "pass"+ },+ {+ "text": "Solder tab pads 1.0 x 2.7 mm at x +-3.725 (JST p.1: 1.35 from the outer contact to the tab inner edge, tab 1.0 wide)",+ "result": "pass"+ },+ {+ "text": "Signal row to tab centre 3.2 mm in Y; signal pads 3.7 to 5.4 behind the tab front edge (JST p.1)",+ "result": "pass"+ },+ {+ "text": "Header outline 0.25 behind the tab front edge = F.Fab front edge y 2.45",+ "result": "pass"+ },+ {+ "text": "KiCad rounds the pad corners (roundrect ratio 0.25); JST draws plain rectangles. Extents match exactly.",+ "result": "note"+ }+ ],+ "evidence": [+ {+ "label": "comparison",+ "href": "provenance/footprint-vs-jst.json"+ },+ {+ "label": "JST layout (p.1)",+ "href": "docs/figures/sm04b-ghs-tb-lf-sn-ds-p1-side-entry-layout.png"+ }+ ],+ "files": {+ "sm04b-ghs-tb-lf-sn.kicad_mod": "8a5b9cf624c8776a11b69533ce0a854a9d2f90308db4821cd78e0713df3f96be",+ "provenance/footprint-vs-jst.json": "40c12d04c4b66a5892ad497d5a81c4fcb12451490581cc3eef520aa9796fc234"+ }+ },+ {+ "date": "2026-10-21",+ "by": {+ "name": "Claude (AI agent)",+ "handle": ""+ },+ "status": "verified",+ "title": "Pin 1: circuit 1 on footprint pad 1 and on the model's contact 1",+ "scope": [+ "pin1",+ "footprint",+ "3d"+ ],+ "variants": [+ "*"+ ],+ "checks": [+ {+ "text": "JST p.2 side entry view (mating face, board below): Circuit No.1 at the left",+ "result": "pass"+ },+ {+ "text": "Footprint: mating face toward +Y, so the viewer facing it has -X on the left; pad 1 is at x = -1.875 (-X end), F.Fab chevron and F.SilkS tick on the same end",+ "result": "pass"+ },+ {+ "text": "3D model: contact at x = -1.875 sits on pad 1 with zero offset; front render onto the mating face shows circuit 1 at the left, as JST draws it",+ "result": "pass"+ },+ {+ "text": "Symbol pins 1 to 4 = footprint pads 1 to 4; MP = both tab pads",+ "result": "pass"+ },+ {+ "text": "The real header and the model carry no pin-1 mark; the hero adds an AI pin-1 dot beside pad 1",+ "result": "note"+ }+ ],+ "evidence": [+ {+ "label": "JST header drawing (p.2)",+ "href": "docs/figures/sm04b-ghs-tb-lf-sn-ds-p2-shrouded-header.png"+ },+ {+ "label": "model front view",+ "href": "docs/models/sm04b-ghs-tb-lf-sn-glb-front.png"+ }+ ],+ "files": {+ "sm04b-ghs-tb-lf-sn.kicad_mod": "8a5b9cf624c8776a11b69533ce0a854a9d2f90308db4821cd78e0713df3f96be",+ "sm04b-ghs-tb-lf-sn.step": "aacba39c0ebf407941d81e202e5fc85121532adadfd38f26725330dea8815ac7",+ "sm04b-ghs-tb-lf-sn.kicad_sym": "f705bb40a8fd7fd7effcfb19e49c05ef0a519072ac9aa4b27761c23c6ee8c142"+ }+ },+ {+ "date": "2026-10-21",+ "by": {+ "name": "Claude (AI agent)",+ "handle": ""+ },+ "status": "verified",+ "title": "KiCad 3D model checked against JST's drawing",+ "scope": [+ "3d"+ ],+ "variants": [+ "*"+ ],+ "checks": [+ {+ "text": "B 8.25, A 3.75, pitch 1.25, contact 0.2, depth 4.05, height 4.25, tab inner face 1.75 from circuit 4: all match",+ "result": "pass"+ },+ {+ "text": "Contact tails stick out 0.895 mm behind the housing; JST draws 0.8. The tip stays 0.225 mm inside the signal pad.",+ "result": "fail"+ },+ {+ "text": "JST's own STEP could not be fetched (jst-mfg.com refused connections, jst.com 403); the model is KiCad community CAD",+ "result": "note"+ }+ ],+ "evidence": [+ {+ "label": "dimension table",+ "href": "provenance/3d-model.json"+ }+ ],+ "files": {+ "sm04b-ghs-tb-lf-sn.step": "aacba39c0ebf407941d81e202e5fc85121532adadfd38f26725330dea8815ac7"+ }+ },+ {+ "date": "2026-10-21",+ "by": {+ "name": "Claude (AI agent)",+ "handle": ""+ },+ "status": "open",+ "title": "Open: JST STEP comparison, native EDA imports, physical fit",+ "scope": [+ "3d",+ "eda"+ ],+ "variants": [+ "*"+ ],+ "checks": [+ {+ "text": "Compare with JST's STEP from jst-mfg.com once a browser session can fetch it",+ "result": "note"+ },+ {+ "text": "Native KiCad, Fusion and Altium imports not yet opened and inspected; files pass adom-lbr lint and the Altium round trip",+ "result": "note"+ },+ {+ "text": "No physical mating, crimp or reflow qualification",+ "result": "note"+ }+ ],+ "evidence": [],+ "files": {}+ }+ ]+}