concur — cross-source consensus check for chip libraries
UnreviewedCompares ds2sf-extracted symbol+footprint against chip-fetcher's KiCad/EAGLE/Altium libraries across seven axes and emits an opinionated agent-to-agent result.json. v0.8 adds a KelvinSenseRepresentati
name: concur
description: Cross-source consensus check for chip libraries. Compares ds2sf-extracted symbol+footprint against chip-fetcher's KiCad/EAGLE/Altium libraries and emits a result.json with status (golden/divergent/unrecoverable), exit codes (0/2/3), and tagged hints[] so chip-fetcher can autonomously re-fetch a suspect library or escalate to a human. Trigger words — concur, golden dataset, cross-source check, kicad eagle altium agreement, lib agreement, library mismatch, ds2sf vs kicad, ul stub symbol, refetch library, chip lib consensus.
concur — cross-source consensus check
Pipeline position: chip-fetcher → ds2sf (status: ok) → concur (status: golden) → safe for downstream.
When the four sources of truth for a chip's symbol+footprint (ds2sf-extracted from the datasheet, KiCad UL bundle, EAGLE/Fusion 360 .lbr, Altium binary) all agree, you have a golden dataset. When they diverge, somebody's wrong — concur tells the upstream caller which source is suspect and what to do.
Outputs
<chip-dir>/<MPN>-concur.result.json — the audit + agent-to-agent contract:
{
"schema_version": "1",
"status": "golden | divergent | unrecoverable",
"exit_code": 0 | 2 | 3,
"mpn": "ADS1115IDGSR",
"summary": "ADS1115IDGSR — DIVERGENT. Sources: [ds2sf,kicad,eagle]. Axes: 5 agree, 2 disagree, 0 source-missing.",
"sources_compared": ["ds2sf","kicad","eagle"],
"sources_missing": ["altium"],
"axes": [
{ "axis": "pad_count", "verdict": "agree", … },
{ "axis": "pin_names", "verdict": "disagree",
"conflicts": ["kicad has stub-only pin names (UL bundle did not carry the part's real pin labels)"] }
],
"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" }
]
}
Commands
concur check <CHIP-DIR> # run the cross-source check
concur inspect <CHIP-DIR> # print summary of an existing concur.result.json
concur health # readiness check
concur install # drop SKILL.md
check flags: --ds2sf-symbol, --ds2sf-footprint, --kicad-sym, --kicad-mod, --eagle, --mpn, --out-dir, --force, --json-only.
Status ladder (agent-to-agent contract)
| Exit | status |
Meaning | Caller action |
|---|---|---|---|
| 0 | golden |
All sources agree exactly. | Accept. |
| 0 | golden_with_variants |
Disagreements exist but every one is explained by a variants[] entry (EP-only, module-extras, label-only, stub pin names, body-dim measurement artifact). |
Accept. Downstream tools use the variant list to decide which source to prefer. |
| 2 | divergent |
At least one disagreement is not covered by a variant. | Walk hints[]; refetch a library or escalate. |
| 3 | unrecoverable |
Couldn't parse ≥2 sources. | Surface to human. |
variants[].kind enum
Variants explain why a disagreement is benign, separate from hints[] which tell the caller what to do.
| Kind | When | Meaning |
|---|---|---|
exposed_pad_variant |
Pad count diff is exactly 1 | EP/thermal pad counted as pin N+1 by some sources, omitted by others. |
module_extra_pads |
Pad count diff > 1 | KiCad/EAGLE footprint includes mounting/shield/test pads beyond module datasheet pinout. |
label_only_mismatch |
Package family names differ but geometry agrees | TI's SOT_ prefix on VSSOP footprints, DGS0010A JEDEC outline → VSSOP, IPC-7351 generic names like SOP65P640X120-20N, etc. Cosmetic. |
stub_symbol_pin_names |
One source's pin names are numeric ("1","2"…) | UL bundle stub case. Use ds2sf or EAGLE for real names. |
body_dim_measurement_artifact |
Body dim disagrees but pad geometry agrees | Different "body" measurement methods. 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; power-pin aliases (V+ ↔ VCC, V- ↔ GND) for chip-vendor-vs-library naming. |
Comparison axes (what gets cross-checked)
pad_count— number of pads in the footprintpad_numbers— set of pad numbers / labelssymbol_pin_count— number of pins in the symbolpin_names— per-pin name across sources (slash-normalized, case-insensitive). Stub-only sources (UL bundles where pin "name" is the pin number) are flagged asul_symbol_has_stub_namesrather than failing the axis.pin_to_pad_map— does pin VDD map to the same pad number across sources?package_family— SOIC/QFN/SOT/VSSOP/etc., with JEDEC outline aliases (DGS0010A → VSSOP)body_dims— body x/y in mm, ±0.5 mm tolerance
hints[].action enum
| Action | Carries | When |
|---|---|---|
refetch_library_source |
{format, suspect, notes} |
A specific lib looks wrong; 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 (e.g. Altium parser not yet implemented). |
source_parse_failed |
{format, path, error} |
A file couldn't be parsed at all. |
hints[].action enum
Every hint tells the caller exactly what to do. v0.3 enriches the previously-skinny refetch hints with suggested_sources (priority-ordered list of where to refetch from) and expected_resolution (how the caller verifies the refetch worked).
| Action | Carries | What chip-fetcher should do |
|---|---|---|
refetch_library_source |
{format, suspect, notes, suggested_sources, expected_resolution} |
Walk suggested_sources in order. After each refetch, re-run concur check. The expected_resolution field tells you the specific axis that should change verdict on a successful refetch. Stop when status flips to golden / golden_with_variants. |
ul_symbol_has_stub_names |
{source, pin_count, suggestion, chip_fetcher_action} |
Don't refetch the .kicad_sym — UL stub-naming is a UL property, not a chip-fetcher choice. Instead mark the chip dir's symbol source as ds2sf-preferred so downstream sym_create authors a fresh symbol with real labels from ds2sf's JSON. |
rerun_ds2sf_with_stronger_model |
{reason, suspect_field, suggested_model} |
Re-run ds2sf extract --force --model claude-opus-4-7. ds2sf likely misread a small dimension or pin field with Haiku. Verify by re-running concur. |
accept_with_caveats |
{caveats} |
Soft diffs within tolerance — accept the dataset, just remember the caveats for UI display. |
human_review |
{reason, notes} |
Surface to a human; no automated repair safe. |
source_parse_failed |
{format, path, error} |
A source file couldn't be parsed. If format == altium and concur version < 1.0, this is expected (Altium binary parser isn't implemented yet). |
Agent-to-agent calling recipe
// (Pseudo-Rust for chip-fetcher's caller side.)
// Step 1: ds2sf
let ds2sf = run_ds2sf(chip_dir);
if ds2sf.status != "ok" {
// Handle ds2sf needs_better_pdf path — see ds2sf SKILL.md.
}
// Step 2: concur
let mut tried_refetches: HashSet<String> = HashSet::new();
loop {
let r = run_concur(chip_dir);
match r.status.as_str() {
"golden" | "golden_with_variants" => {
// Apply ul_symbol_has_stub_names by marking the chip dir's
// symbol source as ds2sf-preferred for downstream sym_create.
for h in &r.hints {
if let Hint::UlSymbolHasStubNames { .. } = h {
mark_chip_dir_symbol_source(chip_dir, "ds2sf-preferred");
}
}
mark_chip_dir_clean(chip_dir, &r.variants);
break;
}
"divergent" => {
// Walk hints in order. First action that's not yet been tried wins.
let mut acted = false;
for h in &r.hints {
match h {
Hint::RerunDs2sfWithStrongerModel { suggested_model, .. } => {
run_ds2sf(chip_dir, &["--force", "--model", suggested_model]);
acted = true; break;
}
Hint::RefetchLibrarySource { format, suggested_sources, .. } => {
for src in suggested_sources {
let key = format!("{format}|{src}");
if tried_refetches.insert(key) {
refetch_library(chip_dir, format, src);
acted = true; break;
}
}
if acted { break; }
}
_ => {}
}
}
if !acted {
// Out of automated options.
log_for_human(&r);
break;
}
}
"unrecoverable" => { log_for_human(&r); break; }
_ => unreachable!(),
}
}
Out of scope for v0.1
- Altium binary parsing (.SchLib / .PcbLib are OLE-compound). Surfaces as
human_reviewwith reasonaltium_parser_not_implemented. - Body-thickness comparison (z-dim). Sources don't reliably report this.
- Automatic pin-name slash-normalization beyond
/→_(e.g. fully-qualified mux paths).
Related
ds2sf(skill at~/.claude/skills/ds2sf/SKILL.md) — upstream: extracts symbol+footprint+provenance from the datasheet PDF.chip-fetcher(skill at~/.claude/skills/chip-fetcher/SKILL.md) — primary consumer; pulls the libraries that concur cross-checks.