app
Adom Concur
Public Made by Adomby adom
Cross-source consensus check for chip libraries — scores whether the KiCad, EAGLE, and Altium libraries AND the adom-ds2sf datasheet extraction all AGREE on pins, pads, names, and package, across seve
← Commit history
README.mdadded+198@@ -0,0 +1,198 @@+# adom-concur++**Cross-source consensus check for chip libraries.**++A small Rust CLI that runs downstream of `adom-ds2sf` and `adom-chip-fetcher`: it loads every available source-of-truth for a chip's symbol and footprint (datasheet-extracted, KiCad UL bundle, Fusion 360 EAGLE `.lbr`, Altium binary), compares them across seven axes, and emits a result.json with `status: golden | divergent | unrecoverable` plus tagged `hints[]` so the upstream caller can either re-fetch a suspect library or escalate to a human.++The pipeline:++```+adom-chip-fetcher → adom-ds2sf (status: ok) → adom-concur (status: golden) → downstream is happy+ ↓ divergent+ adom-chip-fetcher refetches a lib+ OR human reviews+```++## Why this matters++Concur is **opinionated** about whether a divergence requires upstream work or is safe to ship. Many "disagreements" between sources are known-benign patterns (exposed-pad counted as pin N+1 in one source but not the other, JEDEC-outline-name vs marketing-name, alt-function pin labels, pad-array span misread as body dim). Concur classifies these as **variants** and ships the dataset with `status: golden_with_variants` (exit 0) so the upstream caller can move forward and just remember the variants downstream. Real disagreements stay `divergent` (exit 2).++Real example from this release's smoke tests:++```+$ adom-concur check ~/project/adom-chip-fetcher/library/ADS1115IDGSR+ adom-ds2sf — 10 pins, 10 pads, package "VSSOP-10"+ kicad — 10 pins, 10 pads, footprint "SOT_ADS1115IDYNR_TEX"+ eagle (.lbr) — 10 pins, 10 pads, package "DGS0010A_N"++OK: ADS1115IDGSR — GOLDEN with variants [variants: label_only, stub_pin_names, body_dim_artifact]+```++What adom-concur figured out:++- `label_only_mismatch` — KiCad's footprint name starts with `SOT_` because that's TI's UL library prefix convention, but the geometry (pad count, pad layout, pitch) all agrees with EAGLE's `DGS0010A_N` and adom-ds2sf's `VSSOP-10`. The package family really is VSSOP. Cosmetic only.+- `stub_symbol_pin_names` — the KiCad UL symbol has pin "names" of "1", "2", "3"… instead of real labels. Downstream can use adom-ds2sf's or EAGLE's pin labels.+- `body_dim_measurement_artifact` — adom-ds2sf and EAGLE report different body dimensions (5.05×3.10 vs 4.45×2.00). Body dim is courtyard-only, doesn't affect placement; the diff is a measurement-method artifact (lead-tip span vs pad-array span vs body D dim).++All three are flagged but explained, exit 0, adom-chip-fetcher moves forward.++## Outputs++`<chip-dir>/<MPN>-concur.result.json` — the audit + agent contract:++```json+{+ "schema_version": "1",+ "status": "golden_with_variants",+ "exit_code": 0,+ "mpn": "ADS1115IDGSR",+ "summary": "ADS1115IDGSR — GOLDEN with variants [variants: label_only,stub_pin_names,body_dim_artifact]",+ "sources_compared": ["adom-ds2sf","kicad","eagle"],+ "sources_missing": ["altium"],+ "variants": [+ { "kind": "label_only_mismatch",+ "notes": "adom-ds2sf: VSSOP-10 → family=VSSOP | eagle: DGS0010A_N → family=VSSOP | kicad: SOT_ADS1115IDYNR_TEX → family=SOT" },+ { "kind": "stub_symbol_pin_names",+ "stub_sources": ["kicad"],+ "canonical_sources": ["adom-ds2sf","eagle"] },+ { "kind": "body_dim_measurement_artifact",+ "notes": "adom-ds2sf: 5.05×3.10 mm | eagle: 4.45×2.00 mm" }+ ],+ "axes": [+ { "axis": "pad_count", "verdict": "agree" },+ { "axis": "pin_names", "verdict": "disagree",+ "conflicts": ["kicad has stub-only pin names …"] },+ { "axis": "package_family","verdict": "disagree",+ "conflicts": ["Package families disagree across sources: adom-ds2sf=VSSOP, kicad=SOT, eagle=VSSOP"] }+ ],+ "hints": [+ { "action": "ul_symbol_has_stub_names", "source": "kicad", "pin_count": 10,+ "suggestion": "Use ds2sf-extracted symbol JSON or refetch the .kicad_sym from a manufacturer-direct source" }+ ]+}+```++### Status ladder++| Status | Exit | Caller action |+|---|---|---|+| `golden` | 0 | Ship it, no caveats. |+| `golden_with_variants` | 0 | **Ship it.** Every disagreement is explained by `variants[]`. Downstream tools can use the variant list to decide which source to prefer (adom-ds2sf for pin labels when the KiCad symbol has stubs, etc). |+| `divergent` | 2 | Real disagreement. Refetch a library or escalate to a human. |+| `unrecoverable` | 3 | Couldn't parse ≥2 sources. |++### Variant kinds (v0.3)++| Kind | When | What it means |+|---|---|---|+| `exposed_pad_variant` | Pad count diff is exactly 1 | One source counts the EP/thermal pad as pin N+1; the other rolls it into the body. EE practice varies; both are correct. |+| `module_extra_pads` | Pad count diff > 1 (one source has more) | KiCad/EAGLE footprint includes mounting/shield/test pads beyond the module datasheet's user-facing pinout. |+| `label_only_mismatch` | Package family names differ but geometry agrees | Naming-convention artifact (e.g. TI's `SOT_` prefix on a VSSOP footprint, JEDEC outline `DGS0010A` → VSSOP, IPC-7351 generic name `SOP65P640X120-20N` → TSSOP). Cosmetic only. |+| `stub_symbol_pin_names` | One source's pin names are pin numbers ("1","2"…) | UL stub case. Downstream should use a richer source (adom-ds2sf or EAGLE) for labels. |+| `body_dim_measurement_artifact` | Body dim disagrees but pad geometry agrees | Different sources measured "body" differently (lead-tip span vs body D-dim vs pad-array span). Body dim is courtyard-only; doesn't affect placement. |+| `naming_convention_mismatch` | Pin names differ but every disagreement is a benign convention swap | Channel-digit position (`OUT1` ↔ `1OUT` for op-amps and multi-channel parts) or power-pin alias (`V+` ↔ `VCC`, `V-` ↔ `GND`). |++## Comparison axes++| Axis | What it checks |+|---|---|+| `pad_count` | Number of pads in the footprint |+| `pad_numbers` | Set of pad numbers/labels (1..N or A1, A4, B7…) |+| `symbol_pin_count` | Number of pins in the symbol |+| `pin_names` | Per-pin name across sources (slash → underscore, case-insensitive). Sources that emit stub names ("1","2"…) are flagged as `ul_symbol_has_stub_names` hint. |+| `pin_to_pad_map` | Does pin VDD map to the same pad number across sources? |+| `package_family` | SOIC / VSSOP / QFN / SOT / etc., with JEDEC outline aliases (DGS0010A → VSSOP, RGE → QFN, RUG → VQFN, …) |+| `body_dims` | Body x/y in mm, ±0.5 mm tolerance |++## Agent-to-agent contract++`hints[]` is a tagged-union list (separate from `variants[]` — variants explain *why* a disagreement is benign; hints tell the caller *what action to take*). v0.3 enriches refetch hints with concrete `suggested_sources` (priority-ordered) and `expected_resolution` so adom-chip-fetcher knows where to refetch from AND how to verify the refetch worked.++| Action | Carries | When |+|---|---|---|+| `refetch_library_source` | `{format, suspect, notes}` | A specific lib looks wrong; adom-chip-fetcher should try a different upstream. |+| `ul_symbol_has_stub_names` | `{source, pin_count, suggestion}` | KiCad UL stub case (pin "names" are pin numbers). |+| `accept_with_caveats` | `{caveats}` | Soft diffs within tolerance. |+| `human_review` | `{reason, notes}` | No automated repair safe. |+| `source_parse_failed` | `{format, path, error}` | A file couldn't be parsed at all. |++## Calling recipe++```rust+let r = run_concur(chip_dir);+match r.status.as_str() {+ "golden" => mark_chip_dir_clean(),+ "divergent" => {+ for h in &r.hints {+ match h {+ Hint::RefetchLibrarySource { format, .. } => {+ refetch_lib_from_alternate_source(format);+ return run_concur(chip_dir); // re-call after refetch+ }+ Hint::UlSymbolHasStubNames { .. } => {+ // Replace .kicad_sym from adom-ds2sf JSON via downstream sym_create.+ }+ _ => {}+ }+ }+ }+ "unrecoverable" => log_for_human(&r),+ _ => unreachable!(),+}+```++## CLI++```+adom-concur check <CHIP-DIR> # run cross-source check+adom-concur inspect <CHIP-DIR> # print summary of an existing adom-concur.result.json+adom-concur health # parser readiness check+adom-concur install # drop SKILL.md+```++`check` flags: `--ds2sf-symbol`, `--ds2sf-footprint`, `--kicad-sym`, `--kicad-mod`, `--eagle`, `--mpn`, `--out-dir`, `--force`, `--json-only`.++## Validated chips (v0.3 release — 9-chip suite)++| MPN | Pkg | Status | Variants caught | Notes |+|---|---|---|---|---|+| ADS1115IDGSR | VSSOP-10 | golden_with_variants | label_only, stub_pin_names, body_dim_artifact | TI's `SOT_` prefix on VSSOP footprint; UL symbol stubs; adom-ds2sf body-dim picked up the lead-tip span |+| DRV8316RRGFR | VQFN-40 | golden_with_variants | ep | EP counted as pin 41 by KiCad/EAGLE, omitted by adom-ds2sf |+| VL53L8CX | OLGA-16 | golden_with_variants | ep, label_only, body_dim_artifact | Custom optical LGA; thermal pad EP variant |+| ESP32-S3-WROOM-1-N4 | SMD module | golden_with_variants | module_extras, body_dim_artifact | KiCad has 8 extra shield/test pads beyond the module's 41 castellations |+| LM358D | SOIC-8 | golden_with_variants | naming_convention | `OUT1`↔`1OUT` channel-digit + `V+`↔`VCC`, `V-`↔`GND` power-pin aliases |+| TPS62840YBGR | DSBGA-8 | golden_with_variants | body_dim_artifact | Cleanest of the suite; only courtyard body-dim diff |+| BMI270 | LGA-14 | golden_with_variants | label_only, body_dim_artifact | Bosch IMU; EAGLE 7.x .lbr now parses (DTD support) |+| **MSP430G2553IPW20** | TSSOP-20 | **divergent** | — | **Real bug.** KiCad symbol shifts pin functions: adom-ds2sf says pin 14=NC, KiCad says pin 14=P1.6 with 8 alt-functions. Likely wrong sub-variant in UL bundle. |+| **R7FA4M1AB3CFP** | LQFP-100 | **divergent** | — | **Real bug.** Pin 1: adom-ds2sf=`P108_TMS_SWDIO`, KiCad=`P400`. AVCC0 lands on pad 90 vs pad 88. **Wrong sub-variant of the Renesas RA4M1 family.** |++7/9 pass cleanly (`golden_with_variants` exit 0). 2/9 are real wrong-variant findings the upstream caller should refetch. **Zero false positives** in v0.3.++## Out of scope (current)++- **Altium .SchLib (symbol-side) parsing.** v0.6 added .PcbLib (pads) via the sister `altium-pcblib` crate; .SchLib pin labels are still pending.+- **Body-thickness comparison** (z-dim). Sources don't reliably report this.+- **Tolerance-aware lead/pad-pitch checks** beyond raw body dims.++## Altium multi-variant selection (v0.7)++Many vendor `.PcbLib`s ship multiple footprint variants in the same file — for example DRV8316RRGFR carries `RGF0040E-IPC_A` (41-pad IPC standard) AND `RGF0040E-MFG` (57-pad manufacturing layout with extra fiducials and test points). The upstream `altium-pcblib` crate picks one as "primary" by stream order.++If adom-concur naively trusts the primary, it can disagree with kicad+eagle 100% of the time. v0.7 computes the pad-count consensus from already-parsed sources (adom-ds2sf / kicad / eagle) and asks `altium-pcblib` for the variant whose pad count is closest to the median. Names containing `-MFG` / `_MFG` / `DEBUG` / `FIDUCIAL` / `TEST` get a tiebreak penalty so the IPC-standard variant wins when in doubt.++Effect on the benchmark: DRV8316RRGFR was reporting `divergent` with altium engaged (57 vs 41) → now reports `golden_with_variants` (41 across all four sources, only EP-counting differs).++## Build++```bash+cargo build --release+sudo cp target/release/adom-concur /usr/local/bin/+adom-concur install+```++Or just `./build.sh`.++## Related++- [`adom-ds2sf`](https://github.com/adom-inc/adom-ds2sf) — datasheet → symbol + footprint + provenance JSON. Upstream of adom-concur.+- adom-chip-fetcher — pulls the libraries that adom-concur cross-checks.
page.jsonadded+29@@ -0,0 +1,29 @@+{+ "slug": "adom-concur",+ "version": "1.0.0",+ "type": "app",+ "description": "Cross-source consensus check for chip libraries — compares adom-ds2sf-extracted symbol+footprint against adom-chip-fetcher's KiCad/EAGLE/Altium libraries and emits agent-to-agent hints.",+ "dependencies": {},+ "tags": [+ "eda",+ "validation",+ "kicad",+ "cli"+ ],+ "scripts": {+ "install": "./install.sh",+ "uninstall": "./uninstall.sh"+ },+ "install": {+ "binary_name": "adom-concur"+ },+ "needs_sudo": true,+ "hero": {+ "type": "image",+ "path": "adom-concur.png"+ },+ "author": {+ "name": "John Lauer",+ "email": "[email protected]"+ }+}