from __future__ import annotations import hashlib import json from pathlib import Path import pytest from k1link.compute.e46e_ready_stack import ( E46E_RUNTIME_SCHEMA, E46EReadyStackError, analyze_e46e_frames, build_e46e_ready_stack, read_e46e_ready_stack, ) def test_e46e_projects_stock_deepstream_output_without_custom_tracking( tmp_path: Path, ) -> None: source, profile = _source_and_profile(tmp_path, frame_count=6) raw = _raw_output(tmp_path, profile, frame_count=6) _detector(raw, 0, "car", (10, 20, 40, 60), 0.91) _tracker(raw, 0, 7, "car", (10, 20, 40, 60), 0.88) _tracker(raw, 1, 7, "car", (12, 20, 42, 60), 0.73) _detector(raw, 5, "person", (100, 80, 130, 160), 0.93) _tracker(raw, 5, 7, "person", (100, 80, 130, 160), 0.79) result = build_e46e_ready_stack( source_job_root=source, raw_root=raw, profile_path=profile, output_root=tmp_path / "results", ) metrics = result["report"]["metrics"] assert metrics["frame_count"] == 6 assert metrics["detection_observation_count"] == 2 assert metrics["track_observation_count"] == 3 assert metrics["detection_box_clipped_count"] == 0 assert metrics["track_box_clipped_count"] == 0 assert metrics["tracker_recovered_frame_count"] == 1 assert metrics["full_layer_blackout_event_count"] == 1 assert metrics["route_id_gap_event_count"] == 1 assert metrics["track_class_switch_count"] == 1 assert result["frames"][1]["objects"][0]["object_id"] == "nvdcf-7" assert result["frames"][1]["objects"][0]["bbox"] == [12.0, 20.0, 30.0, 40.0] assert [ (component["kind"], component["role"]) for component in result["report"]["method"]["components"] ] == [ ("source", "exact recorded camera evidence"), ("model", "framewise traffic-object detection"), ("tool", "official RT-DETR output decoding"), ("algorithm", "route-local temporal association"), ("runtime", "GPU inference and media pipeline"), ] assert result["report"]["decision"]["custom_temporal_logic_used"] is False assert result["manifest"]["authority"]["navigation_or_safety_accepted"] is False repeated = build_e46e_ready_stack( source_job_root=source, raw_root=raw, profile_path=profile, output_root=tmp_path / "results", ) assert repeated["result_id"] == result["result_id"] def test_e46e_clips_only_display_geometry_at_the_source_plane(tmp_path: Path) -> None: source, profile = _source_and_profile(tmp_path, frame_count=1) raw = _raw_output(tmp_path, profile, frame_count=1) _tracker(raw, 0, 31, "person", (447, 547, 527, 608), 0.69) result = build_e46e_ready_stack( source_job_root=source, raw_root=raw, profile_path=profile, output_root=tmp_path / "results", ) item = result["frames"][0]["objects"][0] assert item["bbox"] == [447.0, 547.0, 80.0, 53.0] assert item["source_bbox_ltrb"] == [447.0, 547.0, 527.0, 608.0] assert item["source_plane_clipped"] is True assert result["report"]["metrics"]["track_box_clipped_count"] == 1 assert result["report"]["decision"]["custom_temporal_logic_used"] is False def test_e46e_rejects_tampered_immutable_artifact(tmp_path: Path) -> None: source, profile = _source_and_profile(tmp_path, frame_count=1) raw = _raw_output(tmp_path, profile, frame_count=1) result = build_e46e_ready_stack( source_job_root=source, raw_root=raw, profile_path=profile, output_root=tmp_path / "results", ) (result["result_root"] / "overlay.mp4").write_bytes(b"changed") with pytest.raises(E46EReadyStackError, match="artifact changed"): read_e46e_ready_stack(result["result_root"]) def test_e46e_frame_analyzer_requires_contiguous_source_order() -> None: with pytest.raises(E46EReadyStackError, match="not contiguous"): analyze_e46e_frames( [ { "frame_index": 1, "session_seconds": 1.0, "detections": [], "objects": [], } ] ) def _source_and_profile(tmp_path: Path, *, frame_count: int) -> tuple[Path, Path]: source = tmp_path / "source-job" camera = source / "input" / "camera" / "sensor.camera.right" / "epoch-1" camera.mkdir(parents=True) index_rows = [ { "schema_version": "missioncore.camera-recording-index/v1", "kind": "media", "sequence": sequence, "session_monotonic_ns": 1_000_000_000 + (sequence - 1) * 100_000_000, "sha256": hashlib.sha256(f"frame-{sequence}".encode()).hexdigest(), } for sequence in range(1, frame_count + 1) ] index_path = camera / "index.jsonl" index_path.write_text( "".join(json.dumps(row, sort_keys=True) + "\n" for row in index_rows), encoding="utf-8", ) stream_sha = "1" * 64 summary_path = camera / "summary.json" summary_path.write_text( json.dumps( { "schema_version": "missioncore.camera-recording/v1", "stream_sha256": stream_sha, "segment_count": frame_count, }, indent=2, ) + "\n", encoding="utf-8", ) index_sha = _sha(index_path) summary_sha = _sha(summary_path) job = { "schema_version": "missioncore.compute-job/v1", "job_id": "recorded-test", "input": { "session_id": "test-session", "source_id": "sensor.camera.right", "segment_count": frame_count, "archive_index_sha256": index_sha, "archive_summary_sha256": summary_sha, "timeline": {"start_seconds": 10.0, "end_seconds": 11.0}, }, } (source / "job.json").write_text(json.dumps(job, indent=2) + "\n", encoding="utf-8") profile_value = { "schema_version": "missioncore.e46e-ready-stack-profile/v1", "profile_id": "e46e-test/v1", "source": { "camera_source_id": "sensor.camera.right", "job_id": "recorded-test", "session_id": "test-session", "segment_count": frame_count, "stream_sha256": stream_sha, "archive_index_sha256": index_sha, "archive_summary_sha256": summary_sha, }, "runtime": { "container_image": "nvcr.io/nvidia/deepstream:9.1-samples-multiarch@sha256:" + "2" * 64, "deepstream_version": "9.1", }, "detector": { "name": "NVIDIA TrafficCamNet Transformer Lite", "version": "test", "model_sha256": "3" * 64, "custom_postprocessing": False, }, "parser": { "name": "NVIDIA DeepStream TAO custom bounding-box parser", "repository": "https://github.com/NVIDIA/DeepStream.git", "commit": "8" * 40, "symbol": "NvDsInferParseCustomDDETRTAO", "library_sha256": "9" * 64, "custom_mission_core_logic": False, }, "tracker": { "name": "NVIDIA NvDCF", "configuration": "stock-accuracy", "custom_association": False, "custom_hold_or_stitch": False, }, "output": {"frame_width": 800, "frame_height": 600}, "authority": { "ground_truth": False, "candidate_accepted": False, "commands_enabled": False, "navigation_or_safety_accepted": False, }, } profile = tmp_path / "profile.json" profile.write_text(json.dumps(profile_value, indent=2) + "\n", encoding="utf-8") return source, profile def _raw_output(tmp_path: Path, profile_path: Path, *, frame_count: int) -> Path: raw = tmp_path / "raw" detections = raw / "detections" tracks = raw / "tracks" detections.mkdir(parents=True) tracks.mkdir() for frame in range(frame_count): (detections / f"00_000_{frame:06d}.txt").write_text("", encoding="utf-8") (tracks / f"00_000_{frame:06d}.txt").write_text("", encoding="utf-8") overlay = raw / "overlay.mp4" overlay.write_bytes(b"synthetic-overlay") (raw / "deepstream.log").write_text("synthetic success\n", encoding="utf-8") profile = json.loads(profile_path.read_text(encoding="utf-8")) image = profile["runtime"]["container_image"] runtime = { "schema_version": E46E_RUNTIME_SCHEMA, "status": "completed", "worker_host": "TEST-WORKER-006", "gpu_name": "Synthetic RTX", "container_image": image, "container_image_digest": image.rsplit("@sha256:", 1)[1], "model_sha256": profile["detector"]["model_sha256"], "model_engine_sha256": "4" * 64, "deepstream_config_sha256": "5" * 64, "detector_config_sha256": "6" * 64, "parser_library_sha256": profile["parser"]["library_sha256"], "tracker_config_sha256": "7" * 64, "input_stream_sha256": profile["source"]["stream_sha256"], "overlay_sha256": _sha(overlay), } (raw / "runtime.json").write_text(json.dumps(runtime, indent=2) + "\n", encoding="utf-8") return raw def _detector( raw: Path, frame: int, label: str, box: tuple[int, int, int, int], confidence: float, ) -> None: left, top, right, bottom = box (raw / "detections" / f"00_000_{frame:06d}.txt").write_text( f"{label} 0.0 0 0.0 {left} {top} {right} {bottom} 0 0 0 0 0 0 0 {confidence}\n", encoding="utf-8", ) def _tracker( raw: Path, frame: int, track_id: int, label: str, box: tuple[int, int, int, int], confidence: float, ) -> None: left, top, right, bottom = box (raw / "tracks" / f"00_000_{frame:06d}.txt").write_text( f"{label} {track_id} 0.0 0 0.0 {left} {top} {right} {bottom} 0 0 0 0 0 0 0 {confidence}\n", encoding="utf-8", ) def _sha(path: Path) -> str: return hashlib.sha256(path.read_bytes()).hexdigest()