493 lines
20 KiB
Python
493 lines
20 KiB
Python
"""Executable Milestone 4 baseline binding.
|
|
|
|
The profile points at immutable local evidence without copying large or sensitive
|
|
artifacts into Git. Verification is explicit: missing evidence is a failure, not
|
|
an invitation to silently select a different source or experiment result.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import hashlib
|
|
import json
|
|
import re
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
from typing import Final
|
|
|
|
BASELINE_SCHEMA: Final = "missioncore.perception-m4-baseline/v1"
|
|
REUSE_INVENTORY_SCHEMA: Final = "missioncore.perception-reuse-inventory/v1"
|
|
BASELINE_PROFILE_ID: Final = "m4-ravnoves00-recorded-realtime/v1"
|
|
BASELINE_SOURCE_ID: Final = "RAVNOVES00"
|
|
BASELINE_SESSION_ID: Final = "20260720T065719Z_viewer_live"
|
|
BASELINE_CAMERA_SOURCE_ID: Final = "sensor.camera.right"
|
|
BASELINE_RECORDED_JOB_ID: Final = "recorded-camera-602ac89026ed12978619801d"
|
|
BASELINE_CAMERA_STREAM_SHA256: Final = (
|
|
"cadd1696ff000904eb78633a0a8418104b8024f178b91f3421789021ccb160e8"
|
|
)
|
|
BASELINE_CAMERA_SUMMARY_SHA256: Final = (
|
|
"b280f40b198aad5d5335819107fb1405ad65d5695d187c61a2c027ad853a3181"
|
|
)
|
|
BASELINE_CAMERA_INDEX_SHA256: Final = (
|
|
"e029815a60ad9fbfedb6169142c7449df2b119a51d1ce001f08806e04eb0be14"
|
|
)
|
|
BASELINE_SOURCE_PACK_ID: Final = (
|
|
"e10-lidar-pack-576c994a6c814e2592dd6240ace3902a5db94843312c759a73ba0c9166157d2b"
|
|
)
|
|
BASELINE_SOURCE_PACK_MANIFEST_SHA256: Final = (
|
|
"7e4af82eb7dfd47e242dc5207d55456cd0a5ab4c6780c584d4685ef854a73bf5"
|
|
)
|
|
BASELINE_SOURCE_PACK_SHA256: Final = (
|
|
"0685d24219d8236caf8b7f1685e93f6d6b59e7fd015a768d88a92bbe8b154944"
|
|
)
|
|
BASELINE_PREPROCESS_PROFILE_SHA256: Final = (
|
|
"19c17dbc23f2b1c539eb6b8214e69fa487ea3fec8db9d88768dffc714895fb88"
|
|
)
|
|
BASELINE_FILE_SHA256: Final = (
|
|
"ea10359339e6cce31b5780a2710299771cab7cc0c1c2a2b56a1621f786b31fa8"
|
|
)
|
|
|
|
_SHA256 = re.compile(r"^[a-f0-9]{64}$")
|
|
_EXPECTED_EVIDENCE_ROLES: Final = {
|
|
"source-fusion",
|
|
"track-geometry",
|
|
"source-paced-worker",
|
|
"temporal-occupied",
|
|
"degradation-recovery",
|
|
"raw-fisheye-detector-capacity",
|
|
}
|
|
_BASELINE_KEYS: Final = {
|
|
"schema_version",
|
|
"profile_id",
|
|
"source",
|
|
"calibration",
|
|
"detector",
|
|
"evidence",
|
|
"authority",
|
|
"non_goals",
|
|
"rollback",
|
|
}
|
|
_EVIDENCE_KEYS: Final = {
|
|
"role",
|
|
"relative_path",
|
|
"schema_version",
|
|
"result_id",
|
|
"identity_sha256",
|
|
"file_sha256",
|
|
}
|
|
_SOURCE_KEYS: Final = {
|
|
"source_id",
|
|
"session_id",
|
|
"camera_source_id",
|
|
"recorded_job_id",
|
|
"frame_count",
|
|
"duration_seconds",
|
|
"frame_rate",
|
|
"modalities",
|
|
"camera_stream_sha256",
|
|
"source_pack_id",
|
|
"source_pack_artifact_sha256",
|
|
}
|
|
_EXPECTED_CALIBRATION: Final[dict[str, object]] = {
|
|
"slot": "camera_1",
|
|
"model": "KB4",
|
|
"sha256": "05f3ad9b38b3a4fc95388a8ec83da83c745e217709e51787b3d5aad0969f6fa9",
|
|
"valid_fov_result_id": (
|
|
"valid-fov-mask-b4dd8ddf2b87c1d520ee8a0868c4fea062d7c14d1bae73ccabd3abe1f3acbac2"
|
|
),
|
|
"valid_fov_mask_sha256": (
|
|
"a40cee06b7c6f69b6a09a11563dcfd237f3de833b1ccd31459e66692e528ba63"
|
|
),
|
|
}
|
|
_EXPECTED_DETECTOR: Final[dict[str, object]] = {
|
|
"provider_id": "triton-yolox-s-raw-kb4/v1",
|
|
"model_id": "yolox_s",
|
|
"model_version": 1,
|
|
"model_sha256": "c5c2d13e59ae883e6af3b45daea64af4833a4951c92d116ec270d9ddbe998063",
|
|
"config_sha256": "5795c737a7935a655961b069e8404d336d891f9762fb6dffb93956a076479604",
|
|
"preprocess_profile_sha256": BASELINE_PREPROCESS_PROFILE_SHA256,
|
|
"minimum_score": 0.5,
|
|
"nms_iou_threshold": 0.45,
|
|
"runtime": "NVIDIA Triton 2.70.0 ONNX Runtime GPU backend",
|
|
}
|
|
_EXPECTED_NON_GOALS: Final = (
|
|
"semantic-class-quality",
|
|
"persistent-reidentification",
|
|
"physical-live-k1",
|
|
"physical-threat-authority",
|
|
"navigation-or-command-authority",
|
|
"second-source-transfer",
|
|
"second-worker-bootstrap",
|
|
"ros2-nav2-px4-gazebo-integration",
|
|
"deepstream-migration",
|
|
)
|
|
_EXPECTED_ROLLBACK: Final[dict[str, object]] = {
|
|
"worker_id": "worker-006",
|
|
"worker_node": "DESKTOP-OPJ8J04",
|
|
"container_name": "ndc-mission-core-perception-worker",
|
|
"container_image": (
|
|
"nvcr.io/nvidia/tritonserver:26.06-py3@"
|
|
"sha256:58df7489c3f2276f9591d500a012dee03e23d35543ce3c390b4c001e6bf90794"
|
|
),
|
|
"worker_package_id": (
|
|
"e15-worker-package-dbf55ccb75664b778a2e0f5d34284af10ec0971945bbbee67b27bc264b765b51"
|
|
),
|
|
"runner_sha256": "86e9b25c80908a520ed483541b708cde1d1c74605e094053fcb62b610ecefb20",
|
|
"orchestrator_sha256": (
|
|
"82de50ae83debe26fc5463799b1e1e15217a8db8cc090671ba2993200b8ed95c"
|
|
),
|
|
"entrypoint": "python3 /runner/run_e15_shadow_inference.py serve",
|
|
"observed_container_id": (
|
|
"db2024d05098a6beb6b73bbf43f02c88ede586a4664b2c91182f436a42b3e3ff"
|
|
),
|
|
"observed_at_utc": "2026-08-05T10:30:00Z",
|
|
}
|
|
|
|
|
|
class BaselineContractError(ValueError):
|
|
"""The recorded-realtime baseline is ambiguous, mutated or incomplete."""
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class BaselineEvidence:
|
|
role: str
|
|
relative_path: str
|
|
schema_version: str
|
|
result_id: str
|
|
identity_sha256: str
|
|
file_sha256: str
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class BaselineProfile:
|
|
path: Path
|
|
document: dict[str, object]
|
|
evidence: tuple[BaselineEvidence, ...]
|
|
|
|
|
|
@dataclass(frozen=True, slots=True)
|
|
class BaselineVerification:
|
|
profile_id: str
|
|
source_id: str
|
|
session_id: str
|
|
verified_paths: tuple[str, ...]
|
|
|
|
|
|
def load_m4_baseline(path: Path) -> BaselineProfile:
|
|
"""Load and fail-closed validate the one admitted M4 baseline profile."""
|
|
|
|
document = _read_object(path)
|
|
_exact_keys(document, _BASELINE_KEYS, "baseline")
|
|
if document.get("schema_version") != BASELINE_SCHEMA:
|
|
raise BaselineContractError("baseline schema is incompatible")
|
|
if document.get("profile_id") != BASELINE_PROFILE_ID:
|
|
raise BaselineContractError("baseline profile identity changed")
|
|
|
|
source = _object(document.get("source"), "source")
|
|
_exact_keys(source, _SOURCE_KEYS, "source")
|
|
if source.get("source_id") != BASELINE_SOURCE_ID:
|
|
raise BaselineContractError("M4 source must remain RAVNOVES00")
|
|
if source.get("session_id") != BASELINE_SESSION_ID:
|
|
raise BaselineContractError("M4 source session identity changed")
|
|
if source.get("camera_source_id") != BASELINE_CAMERA_SOURCE_ID:
|
|
raise BaselineContractError("M4 camera source identity changed")
|
|
if source.get("recorded_job_id") != BASELINE_RECORDED_JOB_ID:
|
|
raise BaselineContractError("M4 recorded job identity changed")
|
|
if source.get("source_pack_id") != BASELINE_SOURCE_PACK_ID:
|
|
raise BaselineContractError("M4 source pack identity changed")
|
|
if source.get("source_pack_artifact_sha256") != BASELINE_SOURCE_PACK_SHA256:
|
|
raise BaselineContractError("M4 source pack artifact identity changed")
|
|
if source.get("camera_stream_sha256") != BASELINE_CAMERA_STREAM_SHA256:
|
|
raise BaselineContractError("M4 camera stream identity changed")
|
|
if source.get("frame_count") != 4489:
|
|
raise BaselineContractError("baseline source frame count changed")
|
|
if source.get("duration_seconds") != 448.723:
|
|
raise BaselineContractError("baseline source duration changed")
|
|
if source.get("frame_rate") != 10.003944527024467:
|
|
raise BaselineContractError("baseline source frame rate changed")
|
|
modalities = _string_array(source.get("modalities"), "source modalities")
|
|
if modalities != ("image", "registered-point-increment", "pose"):
|
|
raise BaselineContractError("baseline source must bind image, points and pose")
|
|
|
|
calibration = _object(document.get("calibration"), "calibration")
|
|
if calibration != _EXPECTED_CALIBRATION:
|
|
raise BaselineContractError("baseline calibration identity changed")
|
|
detector = _object(document.get("detector"), "detector")
|
|
if detector != _EXPECTED_DETECTOR:
|
|
raise BaselineContractError("baseline detector identity changed")
|
|
|
|
authority = _object(document.get("authority"), "authority")
|
|
if authority != {
|
|
"mode": "replay-simulated",
|
|
"ground_truth": False,
|
|
"physical_live": False,
|
|
"physical_collision_accepted": False,
|
|
"commands_enabled": False,
|
|
"actuation_allowed": False,
|
|
"navigation_or_safety_accepted": False,
|
|
}:
|
|
raise BaselineContractError("M4 authority must remain replay-simulated and false")
|
|
|
|
if _string_array(document.get("non_goals"), "non-goals") != _EXPECTED_NON_GOALS:
|
|
raise BaselineContractError("baseline non-goals changed")
|
|
|
|
evidence_items = document.get("evidence")
|
|
if not isinstance(evidence_items, list):
|
|
raise BaselineContractError("baseline evidence must be an array")
|
|
evidence = tuple(_evidence(item) for item in evidence_items)
|
|
roles = [item.role for item in evidence]
|
|
if len(set(roles)) != len(roles) or set(roles) != _EXPECTED_EVIDENCE_ROLES:
|
|
raise BaselineContractError("baseline evidence roles are incomplete or duplicated")
|
|
paths = [item.relative_path for item in evidence]
|
|
if len(set(paths)) != len(paths):
|
|
raise BaselineContractError("baseline evidence paths must be unique")
|
|
|
|
rollback = _object(document.get("rollback"), "rollback")
|
|
if rollback != _EXPECTED_ROLLBACK:
|
|
raise BaselineContractError("rollback E15 identity changed")
|
|
if _file_sha256(path) != BASELINE_FILE_SHA256:
|
|
raise BaselineContractError("baseline file bytes changed")
|
|
|
|
return BaselineProfile(path=path, document=document, evidence=evidence)
|
|
|
|
|
|
def verify_m4_baseline(repository_root: Path, profile: BaselineProfile) -> BaselineVerification:
|
|
"""Resolve every immutable evidence document and verify its exact digest."""
|
|
|
|
root = repository_root.resolve()
|
|
source_paths = _repository_source_paths(root, profile)
|
|
verify_m4_execution_source(
|
|
profile,
|
|
camera_summary_path=source_paths[0],
|
|
camera_index_path=source_paths[1],
|
|
source_pack_manifest_path=source_paths[2],
|
|
source_pack_path=source_paths[3],
|
|
)
|
|
verified = [str(path.relative_to(root)) for path in source_paths]
|
|
for item in profile.evidence:
|
|
evidence_path = (root / item.relative_path).resolve()
|
|
if root not in evidence_path.parents:
|
|
raise BaselineContractError("baseline evidence escapes the repository root")
|
|
if not evidence_path.is_file():
|
|
raise BaselineContractError(f"baseline evidence is missing: {item.relative_path}")
|
|
if _file_sha256(evidence_path) != item.file_sha256:
|
|
raise BaselineContractError(f"baseline evidence digest changed: {item.role}")
|
|
evidence_document = _read_object(evidence_path)
|
|
if evidence_document.get("schema_version") != item.schema_version:
|
|
raise BaselineContractError(f"baseline evidence schema changed: {item.role}")
|
|
if evidence_document.get("identity_sha256") != item.identity_sha256:
|
|
raise BaselineContractError(f"baseline evidence identity changed: {item.role}")
|
|
result_id = evidence_document.get("result_id")
|
|
if result_id is None and item.role == "source-fusion":
|
|
result_id = evidence_path.parent.name
|
|
if result_id != item.result_id:
|
|
raise BaselineContractError(f"baseline evidence result changed: {item.role}")
|
|
verified.append(item.relative_path)
|
|
|
|
source = _object(profile.document.get("source"), "source")
|
|
return BaselineVerification(
|
|
profile_id=BASELINE_PROFILE_ID,
|
|
source_id=_string(source.get("source_id"), "source id"),
|
|
session_id=_string(source.get("session_id"), "session id"),
|
|
verified_paths=tuple(verified),
|
|
)
|
|
|
|
|
|
def verify_m4_execution_source(
|
|
profile: BaselineProfile,
|
|
*,
|
|
camera_summary_path: Path,
|
|
camera_index_path: Path,
|
|
source_pack_manifest_path: Path,
|
|
source_pack_path: Path,
|
|
) -> tuple[Path, ...]:
|
|
"""Verify only immutable source inputs required by a deployed replay runner."""
|
|
|
|
source = _object(profile.document.get("source"), "source")
|
|
camera_source_id = _string(source.get("camera_source_id"), "camera source id")
|
|
source_pack_id = _string(source.get("source_pack_id"), "source pack id")
|
|
expected_frames = _integer(source.get("frame_count"), "source frame count")
|
|
source_inputs = (
|
|
camera_summary_path,
|
|
camera_index_path,
|
|
source_pack_manifest_path,
|
|
source_pack_path,
|
|
)
|
|
if any(path.is_symlink() or not path.is_file() for path in source_inputs):
|
|
raise BaselineContractError("execution source inputs must be regular non-symlink files")
|
|
paths = tuple(path.resolve(strict=True) for path in source_inputs)
|
|
summary_path, index_path, pack_manifest_path, pack_artifact_path = paths
|
|
if _file_sha256(summary_path) != BASELINE_CAMERA_SUMMARY_SHA256:
|
|
raise BaselineContractError("camera recording summary digest changed")
|
|
if _file_sha256(index_path) != BASELINE_CAMERA_INDEX_SHA256:
|
|
raise BaselineContractError("camera recording index digest changed")
|
|
summary = _read_object(summary_path)
|
|
if summary.get("schema_version") != "missioncore.camera-recording/v1":
|
|
raise BaselineContractError("camera recording summary schema changed")
|
|
if summary.get("source_id") != camera_source_id:
|
|
raise BaselineContractError("camera recording source identity changed")
|
|
if summary.get("status") != "complete":
|
|
raise BaselineContractError("camera recording is incomplete")
|
|
if _integer(summary.get("media_segment_count"), "camera segment count") != expected_frames:
|
|
raise BaselineContractError("camera recording frame count changed")
|
|
if summary.get("stream_sha256") != source.get("camera_stream_sha256"):
|
|
raise BaselineContractError("camera recording stream digest changed")
|
|
if _file_sha256(index_path) != summary.get("index_sha256"):
|
|
raise BaselineContractError("camera recording index digest changed")
|
|
|
|
if _file_sha256(pack_manifest_path) != BASELINE_SOURCE_PACK_MANIFEST_SHA256:
|
|
raise BaselineContractError("source pack manifest file digest changed")
|
|
pack_manifest = _read_object(pack_manifest_path)
|
|
if pack_manifest.get("schema_version") != "missioncore.e10-lidar-replay-pack/v1":
|
|
raise BaselineContractError("source pack schema changed")
|
|
if pack_manifest.get("pack_id") != source_pack_id:
|
|
raise BaselineContractError("source pack identity changed")
|
|
identity = _object(pack_manifest.get("identity"), "source pack identity")
|
|
if _integer(identity.get("frame_count"), "source pack frame count") != expected_frames:
|
|
raise BaselineContractError("source pack frame count changed")
|
|
artifact = _object(pack_manifest.get("artifact"), "source pack artifact")
|
|
expected_pack_sha = _string(
|
|
source.get("source_pack_artifact_sha256"),
|
|
"source pack artifact digest",
|
|
)
|
|
if artifact.get("sha256") != expected_pack_sha:
|
|
raise BaselineContractError("source pack manifest digest changed")
|
|
if _file_sha256(pack_artifact_path) != expected_pack_sha:
|
|
raise BaselineContractError("source pack artifact digest changed")
|
|
return paths
|
|
|
|
|
|
def _repository_source_paths(root: Path, profile: BaselineProfile) -> tuple[Path, ...]:
|
|
source = _object(profile.document.get("source"), "source")
|
|
recorded_job_id = _string(source.get("recorded_job_id"), "recorded job id")
|
|
camera_source_id = _string(source.get("camera_source_id"), "camera source id")
|
|
source_pack_id = _string(source.get("source_pack_id"), "source pack id")
|
|
camera_root = (
|
|
root
|
|
/ ".runtime/compute-jobs"
|
|
/ recorded_job_id
|
|
/ "input/camera"
|
|
/ camera_source_id
|
|
/ "epoch-1"
|
|
)
|
|
pack_root = root / ".runtime/compute-experiments/e10/lidar-packs" / source_pack_id
|
|
return (
|
|
camera_root / "summary.json",
|
|
camera_root / "index.jsonl",
|
|
pack_root / "manifest.json",
|
|
pack_root / "lidar-pack.npz",
|
|
)
|
|
|
|
|
|
def validate_reuse_inventory(path: Path) -> dict[str, object]:
|
|
"""Validate the M4 primitive/wrapper split used by architecture tests."""
|
|
|
|
document = _read_object(path)
|
|
_exact_keys(
|
|
document,
|
|
{
|
|
"schema_version",
|
|
"profile_id",
|
|
"reusable_primitives",
|
|
"historical_wrappers",
|
|
"rules",
|
|
},
|
|
"reuse inventory",
|
|
)
|
|
if document.get("schema_version") != REUSE_INVENTORY_SCHEMA:
|
|
raise BaselineContractError("reuse inventory schema is incompatible")
|
|
reusable = document.get("reusable_primitives")
|
|
wrappers = document.get("historical_wrappers")
|
|
if not isinstance(reusable, list) or not reusable:
|
|
raise BaselineContractError("reuse inventory has no admitted primitives")
|
|
if not isinstance(wrappers, list) or not wrappers:
|
|
raise BaselineContractError("reuse inventory has no historical wrappers")
|
|
reusable_modules = {_module(item, "reusable primitive") for item in reusable}
|
|
wrapper_modules = {_module(item, "historical wrapper") for item in wrappers}
|
|
if reusable_modules & wrapper_modules:
|
|
raise BaselineContractError("a module cannot be reusable and historical")
|
|
rules = _object(document.get("rules"), "reuse rules")
|
|
expected_rules = {
|
|
"historical_wrappers_are_product_dependencies": False,
|
|
"contracts_may_import_compute": False,
|
|
"graph_may_import_experiment_modules": False,
|
|
"providers_may_import_admitted_primitives": True,
|
|
"bulk_legacy_migration_required": False,
|
|
}
|
|
if rules != expected_rules:
|
|
raise BaselineContractError("reuse dependency rules changed")
|
|
return document
|
|
|
|
|
|
def _evidence(value: object) -> BaselineEvidence:
|
|
document = _object(value, "evidence item")
|
|
_exact_keys(document, _EVIDENCE_KEYS, "evidence item")
|
|
relative_path = _string(document.get("relative_path"), "evidence path")
|
|
path = Path(relative_path)
|
|
if path.is_absolute() or ".." in path.parts or path.suffix != ".json":
|
|
raise BaselineContractError("evidence path must be a relative JSON path")
|
|
return BaselineEvidence(
|
|
role=_string(document.get("role"), "evidence role"),
|
|
relative_path=relative_path,
|
|
schema_version=_string(document.get("schema_version"), "evidence schema"),
|
|
result_id=_string(document.get("result_id"), "evidence result id"),
|
|
identity_sha256=_digest(document.get("identity_sha256"), "evidence identity"),
|
|
file_sha256=_digest(document.get("file_sha256"), "evidence file digest"),
|
|
)
|
|
|
|
|
|
def _module(value: object, label: str) -> str:
|
|
document = _object(value, label)
|
|
return _string(document.get("module"), f"{label} module")
|
|
|
|
|
|
def _read_object(path: Path) -> dict[str, object]:
|
|
try:
|
|
value = json.loads(path.read_text("utf-8"))
|
|
except (OSError, json.JSONDecodeError) as exc:
|
|
raise BaselineContractError(f"cannot read baseline document: {path}") from exc
|
|
return _object(value, str(path))
|
|
|
|
|
|
def _file_sha256(path: Path) -> str:
|
|
digest = hashlib.sha256()
|
|
with path.open("rb") as handle:
|
|
for chunk in iter(lambda: handle.read(1024 * 1024), b""):
|
|
digest.update(chunk)
|
|
return digest.hexdigest()
|
|
|
|
|
|
def _object(value: object, label: str) -> dict[str, object]:
|
|
if not isinstance(value, dict) or any(not isinstance(key, str) for key in value):
|
|
raise BaselineContractError(f"{label} must be an object")
|
|
return value
|
|
|
|
|
|
def _exact_keys(document: dict[str, object], expected: set[str], label: str) -> None:
|
|
if set(document) != expected:
|
|
raise BaselineContractError(f"{label} fields are incompatible")
|
|
|
|
|
|
def _string(value: object, label: str) -> str:
|
|
if not isinstance(value, str) or not value:
|
|
raise BaselineContractError(f"{label} must be a nonempty string")
|
|
return value
|
|
|
|
|
|
def _integer(value: object, label: str) -> int:
|
|
if not isinstance(value, int) or isinstance(value, bool):
|
|
raise BaselineContractError(f"{label} must be an integer")
|
|
return value
|
|
|
|
|
|
def _string_array(value: object, label: str) -> tuple[str, ...]:
|
|
if not isinstance(value, list):
|
|
raise BaselineContractError(f"{label} must be an array")
|
|
return tuple(_string(item, label) for item in value)
|
|
|
|
|
|
def _digest(value: object, label: str) -> str:
|
|
digest = _string(value, label)
|
|
if _SHA256.fullmatch(digest) is None:
|
|
raise BaselineContractError(f"{label} must be a SHA-256 digest")
|
|
return digest
|