"""Prove native review parse/tools match inherited PinScope before switching the live loop.""" from __future__ import annotations import json from backend.periscopex.constraints_lookup import match_constraints from backend.periscopex.finding_engine import complete_finding from backend.periscopex.models import DesignGraph from backend.periscopex.review_parse import parse_submit_review from backend.periscopex.validate import _load_datasheets, _match_constraints, _parse_review from backend.periscopex.validation_tools import execute_tool as inherited_execute from backend.periscopex.review_tools import execute_tool as native_execute from tests.paths import SIMPLE_PROJECT _PAYLOAD = { "findings": [ { "finding": "FB5 floating", "why": "FB5 is NC; DCDC5 SW is loaded.", "status": "ERROR", "source_page": 12, "source_quote": "Connect FB5 to the output sense node.", "recommendation": "Connect FB5.", }, { "finding": "no quote", "why": "maybe missing cap", "status": "ERROR", "source_page": 3, "source_quote": "", }, ], "checked_areas": ["power", "decoupling"], } def test_native_parse_matches_inherited(): inherited = _parse_review(_PAYLOAD, "U16", "AXP2101") native = parse_submit_review(_PAYLOAD, "U16", "AXP2101") assert len(native.findings) == len(inherited.findings) assert native.checked_areas == inherited.checked_areas for a, b in zip(native.findings, inherited.findings, strict=True): assert a.model_dump() == b.model_dump() def test_native_llm_finding_is_review_and_recommended_not_error(): native = parse_submit_review(_PAYLOAD, "U16", "AXP2101") f = native.findings[0] complete_finding(f) assert f.finding_class == "REVIEW" assert f.facts == "FB5 floating" assert f.requirement assert f.status != "ERROR" f2 = native.findings[1] complete_finding(f2) assert f2.status != "ERROR" assert f2.why.startswith("Unverified:") def test_match_constraints_matches_inherited(): datasheets = _load_datasheets(SIMPLE_PROJECT / "extracted") if not datasheets: datasheets = _load_datasheets(SIMPLE_PROJECT / "datasheets" / "extracted") mpns = list(datasheets)[:5] or ["MSPM0G3507SPTR"] for mpn in mpns: assert match_constraints(mpn, datasheets) == _match_constraints(mpn, datasheets) assert match_constraints(None, datasheets) is None def test_native_graph_tools_match_inherited_on_simple_project(): graph = DesignGraph.model_validate( json.loads((SIMPLE_PROJECT / "design_graph.json").read_text()) ) cmap = {} native_txt, _ = native_execute( graph, cmap, "get_net_for_pin", {"designator": "U3", "pin": "1"}, ) inherited_txt, _ = inherited_execute( graph, cmap, "get_net_for_pin", {"designator": "U3", "pin": "1"}, ) assert native_txt == inherited_txt n2, _ = native_execute( graph, cmap, "find_connected_components", {"designator": "U3", "pin": "1", "designator_filter": "C"}, ) i2, _ = inherited_execute( graph, cmap, "find_connected_components", {"designator": "U3", "pin": "1", "designator_filter": "C"}, ) assert n2 == i2 def test_native_session_does_not_import_pinscope_loop(): import ast from pathlib import Path import backend.services.review_session as rs tree = ast.parse(Path(rs.__file__).read_text()) imported = [ node.module for node in ast.walk(tree) if isinstance(node, ast.ImportFrom) and node.module ] assert "backend.periscopex.validate" not in imported assert "backend.periscopex.validation_tools" not in imported assert "backend.services.llm" in imported assert "backend.periscopex.review_tools" in imported assert "backend.periscopex.review_parse" in imported from backend.services import validation as val import backend.services.review_session as rs assert val.review_ic_async is rs.review_ic_async