Share library/extracted for schematic and PCB review.

PCB AI skips a second PDF exam (pintable cache, pdf_path=None) and the report
gains a PCB exam section plus power-trace, thermal, via, Kelvin, and GND-stitch
checks grounded in board geometry and extracted specs.
This commit is contained in:
2026-09-20 08:32:23 +02:00
parent f3f96ea4d1
commit 8f4ebc645c
15 changed files with 1014 additions and 107 deletions
+32 -12
View File
@@ -36,19 +36,39 @@ _ANALYSIS_BUSY = frozenset({
_PLACEMENT_ACTIVE = frozenset({"queued", "running"})
def _load_constraints_map(extracted_dir: Path) -> dict[str, ComponentConstraints]:
def _load_constraints_map(
extracted_dir: Path,
storage: StorageBackend | None = None,
) -> dict[str, ComponentConstraints]:
"""Project extracted/ plus shared ``library/extracted`` (one store for schema+PCB)."""
result: dict[str, ComponentConstraints] = {}
if not extracted_dir.is_dir():
if extracted_dir.is_dir():
for f in extracted_dir.glob("*.json"):
try:
c = ComponentConstraints.model_validate_json(
f.read_text(encoding="utf-8"),
)
except Exception:
logger.exception("skipping bad extraction %s", f)
continue
result[c.mpn] = c
if storage is None:
return result
for f in extracted_dir.glob("*.json"):
try:
c = ComponentConstraints.model_validate_json(
f.read_text(encoding="utf-8"),
)
except Exception:
logger.exception("skipping bad extraction %s", f)
try:
keys = storage.list_recursive("library/extracted/")
except Exception:
logger.exception("listing library/extracted failed")
return result
for key in keys:
if not key.endswith(".json"):
continue
result[c.mpn] = c
try:
data = storage.read_json(key)
c = ComponentConstraints.model_validate(data)
except Exception:
logger.exception("skipping bad library extraction %s", key)
continue
result.setdefault(c.mpn, c)
return result
@@ -110,7 +130,7 @@ async def run_pcb_pipeline(
return
_step(project_id, "classify", "running", "domains and groups")
cmap = _load_constraints_map(ws.local_path("extracted"))
cmap = _load_constraints_map(ws.local_path("extracted"), storage)
plan = build_placement_plan(graph, cmap)
fg_path = ws.local_path("functional_groups.json")
fg_path.write_text(plan.model_dump_json(indent=2) + "\n")
@@ -168,7 +188,7 @@ async def run_pcb_pipeline(
_finish_cancelled(storage, user_id, project_id)
return
_step(project_id, "ai_review", "running", "per-IC datasheet vs layout")
_step(project_id, "ai_review", "running", "layout vs shared library extraction")
coverage: dict[str, list[str]] = {}
skipped: list[dict] = []
try: