Register library components from a datasheet without an exam (2.63.1).

POST /api/library/datasheets now writes an IC inbox card or a
passive/discrete model. Empty pintables never enter library/extracted.
AF Board+AI runs after unchanged run_pcb_checks (PE-SI / HF line stay).
This commit is contained in:
2026-09-21 22:33:30 +02:00
parent 4df04df5d4
commit 6d9d21a023
18 changed files with 451 additions and 51 deletions
+60 -1
View File
@@ -5,7 +5,12 @@ Does not replace run_pcb_checks. Not DRC. Never invents Z.
from __future__ import annotations
from backend.periscopex.af_ai_hf import HfHypothesis, investigate_hf_hypotheses
from backend.periscopex.af_ai_hf import (
HfHypothesis,
append_investigated,
hypotheses_from_rows,
investigate_hf_hypotheses,
)
from backend.periscopex.hf_line_check import check_hf_lines
from backend.periscopex.models import (
Component,
@@ -144,3 +149,57 @@ def test_z0_with_stackup_does_not_invent_ohm_number():
for f in out:
assert "50 Ω" not in (f.finding or "")
assert "90 Ω" not in (f.finding or "")
def test_append_investigated_keeps_pcb_checks_and_adds_pe_af():
graph = _usb_graph()
layout = _stub_layout()
cons = _stub_constraints()
pcb = run_pcb_checks(graph, cons, layout)
n_si = sum(1 for f in pcb if f.rule_id == "PE-SI-007")
assert n_si >= 1
flags = [
HfHypothesis(net="USB_D+", issue_class="stub", why="looks long"),
HfHypothesis(net="USB_D+", issue_class="z0", why="probably 90 ohm"),
]
added = append_investigated(pcb, graph, cons, layout, flags)
assert any(f.rule_id == "PE-AF-001" for f in added)
assert sum(1 for f in pcb if f.rule_id == "PE-SI-007") == n_si
assert "si_check" in _pcb_checks_source()
assert "hf_line" in _pcb_checks_source()
def test_hypotheses_from_rows_drops_unknown_class():
rows = [
{"net": "USB_D+", "issue_class": "stub", "why": "x"},
{"net": "USB_D+", "issue_class": "clearance", "why": "drc"},
{"net": "", "issue_class": "z0", "why": "empty"},
]
hyps = hypotheses_from_rows(rows)
assert len(hyps) == 1
assert hyps[0].issue_class == "stub"
def test_pcb_pipeline_af_ai_is_after_run_pcb_checks():
import inspect
from backend.periscopex import pcb_checks
from backend.services import pcb_pipeline
src = inspect.getsource(pcb_pipeline.run_pcb_pipeline)
assert "run_pcb_checks" in src
assert "_run_af_ai_section" in src
assert src.find("run_pcb_checks") < src.find("_run_af_ai_section")
checks = inspect.getsource(pcb_checks.run_pcb_checks)
assert '("si_check"' in checks or '"si_check"' in checks
assert '"hf_line"' in checks
assert "af_ai" not in checks
assert "investigate_hf_hypotheses" not in checks
def _pcb_checks_source() -> str:
import inspect
from backend.periscopex.pcb_checks import run_pcb_checks
return inspect.getsource(run_pcb_checks)