refactor(perception): decouple replay from lab layout

This commit is contained in:
DCCONSTRUCTIONS
2026-08-05 14:51:33 +03:00
parent 95ac235122
commit c9242480c2
7 changed files with 159 additions and 26 deletions
+70 -18
View File
@@ -24,15 +24,27 @@ 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 = {
@@ -232,6 +244,8 @@ def load_m4_baseline(path: Path) -> BaselineProfile:
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)
@@ -240,7 +254,15 @@ def verify_m4_baseline(repository_root: Path, profile: BaselineProfile) -> Basel
"""Resolve every immutable evidence document and verify its exact digest."""
root = repository_root.resolve()
verified = list(_verify_source_artifacts(root, profile))
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:
@@ -270,22 +292,34 @@ def verify_m4_baseline(repository_root: Path, profile: BaselineProfile) -> Basel
)
def _verify_source_artifacts(root: Path, profile: BaselineProfile) -> tuple[str, ...]:
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")
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")
expected_frames = _integer(source.get("frame_count"), "source frame count")
camera_root = (
root
/ ".runtime/compute-jobs"
/ recorded_job_id
/ "input/camera"
/ camera_source_id
/ "epoch-1"
source_inputs = (
camera_summary_path,
camera_index_path,
source_pack_manifest_path,
source_pack_path,
)
summary_path = camera_root / "summary.json"
index_path = camera_root / "index.jsonl"
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")
@@ -300,9 +334,8 @@ def _verify_source_artifacts(root: Path, profile: BaselineProfile) -> tuple[str,
if _file_sha256(index_path) != summary.get("index_sha256"):
raise BaselineContractError("camera recording index digest changed")
pack_root = root / ".runtime/compute-experiments/e10/lidar-packs" / source_pack_id
pack_manifest_path = pack_root / "manifest.json"
pack_artifact_path = pack_root / "lidar-pack.npz"
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")
@@ -320,9 +353,28 @@ def _verify_source_artifacts(root: Path, profile: BaselineProfile) -> tuple[str,
raise BaselineContractError("source pack manifest digest changed")
if _file_sha256(pack_artifact_path) != expected_pack_sha:
raise BaselineContractError("source pack artifact digest changed")
return tuple(
str(path.relative_to(root))
for path in (summary_path, index_path, pack_manifest_path, pack_artifact_path)
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",
)