from __future__ import annotations import hashlib import json from pathlib import Path from fastapi import FastAPI from fastapi.testclient import TestClient from k1link.laboratory import LaboratoryEvidenceRegistry from k1link.laboratory.evidence_report import verify_laboratory_evidence_result from k1link.laboratory.vegetation_shadow_lab import seal_vegetation_shadow_lab from k1link.web.vegetation_shadow_lab_api import build_vegetation_shadow_lab_router REPOSITORY_ROOT = Path(__file__).resolve().parents[1] def _sha256(path: Path) -> str: return hashlib.sha256(path.read_bytes()).hexdigest() def _worker_result(root: Path, *, candidate: str, mode: str, vegetation_iou: float) -> None: root.mkdir(parents=True) visual_cases = [] for index in range(12): case_id = f"case-{index:02d}" case_root = root / "cases" / case_id case_root.mkdir(parents=True) keys = ["source", "prediction_semantic", "policy_urban", "policy_rural", "policy_offroad"] if mode == "goose": keys.extend(("truth_semantic", "vegetation_material_error")) files = {} for key in keys: path = case_root / f"{key}.png" path.write_bytes(b"\x89PNG\r\n\x1a\n" + f"{candidate}:{mode}:{case_id}:{key}".encode()) files[key] = { "relative_path": path.relative_to(root).as_posix(), "sha256": _sha256(path), } visual_cases.append( { "case_id": case_id, "source_width": 800 if mode == "ravnoves" else 512, "source_height": 600 if mode == "ravnoves" else 512, "center_crop_xyxy": [100, 0, 700, 600] if mode == "ravnoves" else [0, 0, 512, 512], "outside_crop_state": "undefined" if mode == "ravnoves" else "not-applicable", "focus": { "class_name": "high_grass", "label_id": 51, "truth_pixels": 16384, "truth_fraction": 0.0625, "stratum_rank": index + 1, } if mode == "goose" else None, "files": files, } ) payload = { "schema_version": "missioncore.lab-v1-goose-vegetation-run/v1", "result_id": f"lab-v1-{mode}-{candidate}-fixture", "mode": mode, "candidate": { "candidate_key": candidate, "loaded_model_name": "ddrnet_39" if candidate == "ddrnet" else "pp_lite_t_seg", "checkpoint_sha256": ("a" if candidate == "ddrnet" else "b") * 64, }, "metrics": { "mean_iou_percent": 44.0 + vegetation_iou, "published_mean_iou_percent": 46.53 if candidate == "ddrnet" else 45.09, "vegetation_mean_iou": vegetation_iou, }, "timing": { "latency_ms_p95": 20.0 if candidate == "ddrnet" else 15.0, "throughput_fps_from_mean_inference": 55.0, }, "resource": { "peak_reserved_vram_bytes": 2_000_000_000, "gpu_name": "fixture RTX 4090", }, "visual_cases": visual_cases, "authority": { "navigation_accepted": False, "safety_accepted": False, "actuation_accepted": False, "camera_semantics_can_clear_rigid_geometry": False, }, } (root / "result.json").write_text(json.dumps(payload), encoding="utf-8") def test_vegetation_shadow_lab_seals_autonomous_visual_evidence(tmp_path: Path) -> None: roots = {} for candidate, vegetation_iou in (("ddrnet", 0.64), ("ppliteseg", 0.61)): for mode in ("goose", "ravnoves"): root = tmp_path / "worker" / f"{candidate}-{mode}" _worker_result(root, candidate=candidate, mode=mode, vegetation_iou=vegetation_iou) roots[(candidate, mode)] = root result_root = seal_vegetation_shadow_lab( ddrnet_goose_root=roots[("ddrnet", "goose")], ppliteseg_goose_root=roots[("ppliteseg", "goose")], ddrnet_ravnoves_root=roots[("ddrnet", "ravnoves")], ppliteseg_ravnoves_root=roots[("ppliteseg", "ravnoves")], output_root=tmp_path / "results", ) manifest = json.loads((result_root / "result.json").read_text("utf-8")) assert manifest["decision"]["selected_candidate"] == "ddrnet" assert manifest["ground_truth"] is False assert manifest["authority"]["commands_enabled"] is False assert manifest["authority"]["navigation_or_safety_accepted"] is False assert len(manifest["catalogs"]["ravnoves"]) == 0 assert len(manifest["catalogs"]["goose"]) == 12 assert len(manifest["artifacts"]) == 76 assert manifest["catalogs"]["goose"][0]["focus"]["class_name"] == "high_grass" assert "ddrnet_error" in manifest["catalogs"]["goose"][0]["assets"] assert "ppliteseg_error" in manifest["catalogs"]["goose"][0]["assets"] assert "all_classes" not in manifest["metrics"]["candidates"]["ddrnet"]["validation_metrics"] assert (result_root / "result.json").stat().st_size <= 64 * 1024 registry = LaboratoryEvidenceRegistry.from_directory(REPOSITORY_ROOT / "config/laboratories") definition = next( row for row in registry.definitions if row.work_id == "lab-v1-vegetation-shadow" ) proof = verify_laboratory_evidence_result(definition, result_root) assert proof["result_id"] == result_root.name assert proof["artifact_count"] == 76 app = FastAPI() app.include_router(build_vegetation_shadow_lab_router(root_provider=lambda: result_root.parent)) client = TestClient(app) response = client.get(f"/api/v1/laboratory/vegetation-shadow/{result_root.name}") assert response.status_code == 200 assert response.json()["access"] == "read-only" asset_path = manifest["catalogs"]["goose"][0]["assets"]["ddrnet_error"]["path"] asset = client.get( f"/api/v1/laboratory/vegetation-shadow/{result_root.name}/assets/{asset_path}" ) assert asset.status_code == 200 assert asset.headers["cache-control"].endswith("immutable") (result_root / asset_path).write_bytes(b"tampered") assert ( client.get(f"/api/v1/laboratory/vegetation-shadow/{result_root.name}").status_code == 503 )