Files
periscope/backend/pinscopex/bom_match_check.py
T
micheleandCursor e4fd6c3849 Ship Sprint 0 CAD foundations so findings, KiCad hierarchy, BOM match, eval, and optional PCB ingest have a stable contract.
Extend Finding with rule_id/net/pins, flatten multi-sheet .kicad_sch, flag MPN mismatches, score simple_project, and parse .kicad_pcb without running layout DRC.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-10 21:54:37 +02:00

74 lines
2.5 KiB
Python

"""BOM vs schematic property matching.
Compares per-reference MPN/value from the schematic property table against
the uploaded BOM. Silent when the schematic map is empty (PADS/EDIF) so
we never invent orphans from a format that has no schematic properties.
"""
from __future__ import annotations
from backend.pinscopex.models import Finding
def _norm_mpn(value: object) -> str:
return " ".join(str(value or "").split()).upper()
def check_bom_schematic_match(
schematic: dict[str, dict],
bom: dict[str, dict],
) -> list[Finding]:
if not schematic:
return []
findings: list[Finding] = []
refs = sorted(set(schematic) | set(bom))
for ref in refs:
if ref.startswith("#"):
continue
sch = schematic.get(ref) or {}
bom_row = bom.get(ref) or {}
if ref not in schematic:
findings.append(Finding(
designator=ref,
mpn=str(bom_row.get("mpn") or ""),
aspect="bom_match",
source="bom_match",
status="WARNING",
finding=(
f"BOM lists {ref} but the schematic has no such reference."
),
why=(
"An extra BOM line that is not in the netlist will not be "
"validated against a datasheet and may indicate a stale BOM."
),
recommendation=f"Remove {ref} from the BOM or add it to the schematic.",
rule_id="PS-BOM-002",
pins=[],
))
continue
sch_mpn = _norm_mpn(sch.get("mpn"))
bom_mpn = _norm_mpn(bom_row.get("mpn"))
if sch_mpn and bom_mpn and sch_mpn != bom_mpn:
findings.append(Finding(
designator=ref,
mpn=str(sch.get("mpn") or ""),
aspect="bom_match",
source="bom_match",
status="ERROR",
finding=(
f"{ref} schematic MPN '{sch.get('mpn')}' does not match "
f"BOM MPN '{bom_row.get('mpn')}'."
),
why=(
"Datasheet review and library lookup follow one MPN. "
"A mismatch means the wrong die or a stale BOM row."
),
recommendation=(
f"Make {ref}'s BOM and schematic MPN identical, then re-run."
),
rule_id="PS-BOM-001",
pins=[ref],
))
return findings