from __future__ import annotations import json from pathlib import Path from k1link.perception.contracts import LocalObstacleMap, SourceAccounting from k1link.perception.graph_contracts import ( REFERENCE_GRAPH_ID_V2, DeliveredFrame, GraphRunMode, GraphState, TerminalOutcome, TerminalOutcomeType, build_graph_run_result_v2, ) from k1link.perception.reference_graph_parity import ( compare_reference_graph_to_accepted_ledgers, ) def _result(): obstacle_map = LocalObstacleMap( source_id="RAVNOVES00", session_id="20260720T065719Z_viewer_live", frame_id="frame-000000", graph_id=REFERENCE_GRAPH_ID_V2, generated_monotonic_ns=1, output_age_ns=0, occupied=(), unknown=(), camera_uncertainty=(), accounting=SourceAccounting(1, 1, 0, 0), ) return build_graph_run_result_v2( graph_id=REFERENCE_GRAPH_ID_V2, source_profile_id="m4-ravnoves00-recorded-realtime/v1", run_mode=GraphRunMode.LOSSLESS_REPLAY, state=GraphState.STOPPED, admitted_count=1, outcomes=( TerminalOutcome( source_id="RAVNOVES00", session_id="20260720T065719Z_viewer_live", frame_id="frame-000000", sequence=0, outcome=TerminalOutcomeType.DELIVERED, stage_id="threat", reason="object-payload-delivered", ), ), deliveries=(DeliveredFrame(0, obstacle_map, ()),), queue_high_watermarks=(("detector", 1),), ) def _write_ledgers(root: Path, *, threat_assessments: list[dict[str, object]]) -> tuple[Path, Path]: temporal = root / "temporal.jsonl" threat = root / "threat.jsonl" temporal.write_text( json.dumps( { "sequence": 0, "frame_id": "frame-000000", "current": [], "rolling_retained": [], "held": [], "expired": [], } ) + "\n", "utf-8", ) threat.write_text( json.dumps( { "sequence": 0, "frame_id": "frame-000000", "camera_proposals": [], "assessments": threat_assessments, } ) + "\n", "utf-8", ) return temporal, threat def test_reference_graph_parity_accepts_exact_frame_semantics(tmp_path: Path) -> None: temporal, threat = _write_ledgers(tmp_path, threat_assessments=[]) report = compare_reference_graph_to_accepted_ledgers( _result(), temporal_frames_path=temporal, threat_frames_path=threat, expected_frames=1, ) assert report.accepted is True assert dict(report.mismatch_counts) == { "camera_uncertainty": 0, "current": 0, "expired": 0, "held": 0, "rolling_retained": 0, "source_binding": 0, "threat_assessments": 0, } def test_reference_graph_parity_reports_threat_drift(tmp_path: Path) -> None: temporal, threat = _write_ledgers(tmp_path, threat_assessments=[{"component_id": "x"}]) report = compare_reference_graph_to_accepted_ledgers( _result(), temporal_frames_path=temporal, threat_frames_path=threat, expected_frames=1, ) assert report.accepted is False assert dict(report.mismatch_counts)["threat_assessments"] == 1