feat(perception): split vegetation evidence layers
This commit is contained in:
@@ -0,0 +1,139 @@
|
||||
"""Seal a benchmark-only vegetation result into its archival LAB namespace."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import copy
|
||||
import hashlib
|
||||
import json
|
||||
import shutil
|
||||
import tempfile
|
||||
from pathlib import Path, PurePosixPath
|
||||
from typing import Any, Final
|
||||
|
||||
from k1link.laboratory.evidence_registry import LaboratoryEvidenceDefinition
|
||||
from k1link.laboratory.evidence_report import verify_laboratory_evidence_result
|
||||
from k1link.laboratory.vegetation_shadow_lab import LAB_SCHEMA
|
||||
|
||||
_SOURCE_DEFINITION: Final = LaboratoryEvidenceDefinition(
|
||||
work_id="lab-v1-vegetation-shadow",
|
||||
runtime_relative_root=PurePosixPath("lab-v1-vegetation/results"),
|
||||
result_id_prefix="lab-v1-vegetation-shadow",
|
||||
document_name="result.json",
|
||||
result_schema_version=LAB_SCHEMA,
|
||||
)
|
||||
_ARCHIVE_DEFINITION: Final = LaboratoryEvidenceDefinition(
|
||||
work_id="lab-v1-vegetation-benchmark",
|
||||
runtime_relative_root=PurePosixPath("lab-v1-vegetation-benchmark/results"),
|
||||
result_id_prefix="lab-v1-vegetation-benchmark",
|
||||
document_name="result.json",
|
||||
result_schema_version=LAB_SCHEMA,
|
||||
)
|
||||
|
||||
|
||||
class VegetationBenchmarkArchiveError(ValueError):
|
||||
"""The source result is not a valid benchmark-only immutable result."""
|
||||
|
||||
|
||||
def _canonical_json(value: object) -> bytes:
|
||||
return json.dumps(
|
||||
value,
|
||||
ensure_ascii=False,
|
||||
separators=(",", ":"),
|
||||
sort_keys=True,
|
||||
).encode("utf-8")
|
||||
|
||||
|
||||
def _object(value: object, label: str) -> dict[str, Any]:
|
||||
if not isinstance(value, dict):
|
||||
raise VegetationBenchmarkArchiveError(f"{label} is invalid")
|
||||
return value
|
||||
|
||||
|
||||
def seal_vegetation_benchmark_archive(
|
||||
*,
|
||||
source_result_root: Path,
|
||||
output_root: Path,
|
||||
) -> Path:
|
||||
source = source_result_root.resolve(strict=True)
|
||||
verify_laboratory_evidence_result(_SOURCE_DEFINITION, source)
|
||||
manifest = _object(
|
||||
json.loads((source / "result.json").read_text("utf-8")),
|
||||
"source result",
|
||||
)
|
||||
if manifest.get("route_video") is not None:
|
||||
raise VegetationBenchmarkArchiveError("benchmark archive source contains route video")
|
||||
artifacts = manifest.get("artifacts")
|
||||
if not isinstance(artifacts, list):
|
||||
raise VegetationBenchmarkArchiveError("source artifacts are invalid")
|
||||
|
||||
identity = copy.deepcopy(_object(manifest.get("identity"), "source identity"))
|
||||
identity.update(
|
||||
{
|
||||
"lab_id": "lab-v1-vegetation-benchmark-archive",
|
||||
"archived_from_result_id": source.name,
|
||||
}
|
||||
)
|
||||
identity_sha256 = hashlib.sha256(_canonical_json(identity)).hexdigest()
|
||||
result_id = f"lab-v1-vegetation-benchmark-{identity_sha256}"
|
||||
|
||||
output_root.mkdir(mode=0o700, parents=True, exist_ok=True)
|
||||
destination = output_root / result_id
|
||||
if destination.exists():
|
||||
verify_laboratory_evidence_result(_ARCHIVE_DEFINITION, destination)
|
||||
return destination
|
||||
|
||||
temporary = Path(tempfile.mkdtemp(prefix=".vegetation-benchmark-", dir=output_root))
|
||||
try:
|
||||
for raw in artifacts:
|
||||
descriptor = _object(raw, "artifact descriptor")
|
||||
relative_text = descriptor.get("path")
|
||||
if not isinstance(relative_text, str):
|
||||
raise VegetationBenchmarkArchiveError("artifact path is invalid")
|
||||
relative = PurePosixPath(relative_text)
|
||||
if relative.is_absolute() or any(part in {"", ".", ".."} for part in relative.parts):
|
||||
raise VegetationBenchmarkArchiveError("artifact path is unsafe")
|
||||
source_path = source.joinpath(*relative.parts)
|
||||
destination_path = temporary.joinpath(*relative.parts)
|
||||
destination_path.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
|
||||
shutil.copyfile(source_path, destination_path)
|
||||
|
||||
archived = copy.deepcopy(manifest)
|
||||
archived.update(
|
||||
{
|
||||
"result_id": result_id,
|
||||
"identity": identity,
|
||||
"identity_sha256": identity_sha256,
|
||||
"archived_from_result_id": source.name,
|
||||
}
|
||||
)
|
||||
(temporary / "result.json").write_bytes(_canonical_json(archived) + b"\n")
|
||||
temporary.rename(destination)
|
||||
verify_laboratory_evidence_result(_ARCHIVE_DEFINITION, destination)
|
||||
return destination
|
||||
except Exception:
|
||||
shutil.rmtree(temporary, ignore_errors=True)
|
||||
raise
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--source-result-root", type=Path, required=True)
|
||||
parser.add_argument("--output-root", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
print(
|
||||
seal_vegetation_benchmark_archive(
|
||||
source_result_root=args.source_result_root,
|
||||
output_root=args.output_root,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
|
||||
__all__ = [
|
||||
"VegetationBenchmarkArchiveError",
|
||||
"seal_vegetation_benchmark_archive",
|
||||
]
|
||||
@@ -112,6 +112,7 @@ def seal_vegetation_policy_review(
|
||||
mission_policy_path: Path,
|
||||
provider_label_map_path: Path,
|
||||
m49_tgs_full_shadow_root: Path,
|
||||
valid_fov_mask_path: Path,
|
||||
output_root: Path,
|
||||
created_at_utc: str | None = None,
|
||||
) -> Path:
|
||||
@@ -142,6 +143,7 @@ def seal_vegetation_policy_review(
|
||||
raise VegetationPolicyReviewError("fine mask archive identity changed")
|
||||
raw_archive_path = base_root / "video" / "ddrnet-semantic-masks.zip"
|
||||
fine_taxonomy = _object(base_route.get("taxonomy"), "fine taxonomy")
|
||||
valid_fov_source = valid_fov_mask_path.resolve(strict=True)
|
||||
|
||||
output_root.mkdir(mode=0o700, parents=True, exist_ok=True)
|
||||
temporary = Path(tempfile.mkdtemp(prefix=".lab-v1-policy-", dir=output_root))
|
||||
@@ -152,11 +154,23 @@ def seal_vegetation_policy_review(
|
||||
artifacts=base.get("artifacts"),
|
||||
)
|
||||
policy_archive = temporary / "video" / "coarse-material-policy-masks.zip"
|
||||
valid_fov_destination = temporary / "video" / "valid-fov-mask.png"
|
||||
valid_fov_destination.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
|
||||
shutil.copyfile(valid_fov_source, valid_fov_destination)
|
||||
valid_fov_proof = {
|
||||
"role": "route-camera-valid-fov-mask",
|
||||
"path": "video/valid-fov-mask.png",
|
||||
"byte_length": valid_fov_destination.stat().st_size,
|
||||
"sha256": sha256_path(valid_fov_destination),
|
||||
"media_type": "image/png",
|
||||
}
|
||||
artifacts.append(valid_fov_proof)
|
||||
policy_counts = build_policy_mask_archive(
|
||||
source_archive=raw_archive_path,
|
||||
destination_archive=policy_archive,
|
||||
fine_taxonomy=fine_taxonomy,
|
||||
provider_label_map=provider_map,
|
||||
valid_fov_mask=valid_fov_destination,
|
||||
)
|
||||
policy_archive_proof = {
|
||||
"role": "route-coarse-material-mask-archive",
|
||||
@@ -180,6 +194,11 @@ def seal_vegetation_policy_review(
|
||||
"taxonomy": policy_taxonomy(),
|
||||
"aggregate_prediction_pixels": policy_counts,
|
||||
"linked_tgs_result_id": tgs.result_id,
|
||||
"valid_fov": {
|
||||
"mask_path": valid_fov_proof["path"],
|
||||
"mask_sha256": valid_fov_proof["sha256"],
|
||||
"outside_valid_fov_class_id": 9,
|
||||
},
|
||||
"policy": {
|
||||
"profile_id": mission_policy["profile_id"],
|
||||
"profile_sha256": sha256_path(mission_policy_path),
|
||||
@@ -196,6 +215,7 @@ def seal_vegetation_policy_review(
|
||||
"spatial_safety_veto_layer": "M4.9 full TGS gravity-local costmap",
|
||||
"temporal_consensus_owner": "TGS causal rolling 1 s and metric obstacle tracks",
|
||||
"camera_semantic_temporal_filter": "none",
|
||||
"camera_valid_fov_filter": "sealed exact KB4 valid-FOV mask",
|
||||
"reason": "No admitted TGS-to-camera pixel projection exists.",
|
||||
},
|
||||
}
|
||||
@@ -238,7 +258,7 @@ def seal_vegetation_policy_review(
|
||||
"Vegetation semantics never clears YOLOX, LiDAR, metric obstacle "
|
||||
"or TGS vetoes."
|
||||
),
|
||||
"Undefined pixels outside the 600x600 center crop remain fail-closed.",
|
||||
"Pixels outside the exact KB4 valid FOV are transparent UNOBSERVED evidence.",
|
||||
(
|
||||
"TGS remains in gravity-local space; no uncalibrated pixel "
|
||||
"projection is fabricated."
|
||||
@@ -269,6 +289,7 @@ def main() -> None:
|
||||
parser.add_argument("--mission-policy-path", type=Path, required=True)
|
||||
parser.add_argument("--provider-label-map-path", type=Path, required=True)
|
||||
parser.add_argument("--m49-tgs-full-shadow-root", type=Path, required=True)
|
||||
parser.add_argument("--valid-fov-mask-path", type=Path, required=True)
|
||||
parser.add_argument("--output-root", type=Path, required=True)
|
||||
args = parser.parse_args()
|
||||
print(seal_vegetation_policy_review(**vars(args)))
|
||||
|
||||
@@ -90,6 +90,14 @@ POLICY_CLASSES: Final = (
|
||||
"material_class": "vegetation_unknown",
|
||||
"evidence_state": "VEGETATION_UNKNOWN",
|
||||
},
|
||||
{
|
||||
"class_id": 9,
|
||||
"label": "OUTSIDE VALID FOV · NO SENSOR EVIDENCE",
|
||||
"color_rgb": [0, 0, 0],
|
||||
"disposition": "undefined",
|
||||
"material_class": None,
|
||||
"evidence_state": "UNOBSERVED",
|
||||
},
|
||||
)
|
||||
|
||||
_MATERIAL_TO_CLASS: Final = {
|
||||
@@ -155,10 +163,18 @@ def build_policy_mask_archive(
|
||||
destination_archive: Path,
|
||||
fine_taxonomy: dict[str, object],
|
||||
provider_label_map: dict[str, Any],
|
||||
valid_fov_mask: Path,
|
||||
) -> list[int]:
|
||||
"""Map every fine mask to coarse evidence; safety vetoes remain separate layers."""
|
||||
|
||||
lut = fine_to_policy_lut(fine_taxonomy, provider_label_map)
|
||||
try:
|
||||
with Image.open(valid_fov_mask) as image:
|
||||
valid_fov = np.asarray(image.convert("L"), dtype=np.uint8) > 0
|
||||
except OSError as exc:
|
||||
raise VegetationPolicyVideoError("valid-FOV mask is unreadable") from exc
|
||||
if valid_fov.shape != (HEIGHT, WIDTH) or not np.any(valid_fov) or np.all(valid_fov):
|
||||
raise VegetationPolicyVideoError("valid-FOV mask geometry is invalid")
|
||||
counts = np.zeros(len(POLICY_CLASSES), dtype=np.int64)
|
||||
destination_archive.parent.mkdir(mode=0o700, parents=True, exist_ok=True)
|
||||
try:
|
||||
@@ -175,6 +191,7 @@ def build_policy_mask_archive(
|
||||
f"fine mask {member} has shape {fine.shape}, expected {(HEIGHT, WIDTH)}"
|
||||
)
|
||||
coarse = lut[fine]
|
||||
coarse[~valid_fov] = 9
|
||||
counts += np.bincount(
|
||||
coarse.reshape(-1),
|
||||
minlength=len(POLICY_CLASSES),
|
||||
|
||||
@@ -327,6 +327,7 @@ def seal_vegetation_shadow_lab(
|
||||
mission_policy_path: Path | None = None,
|
||||
provider_label_map_path: Path | None = None,
|
||||
m49_tgs_full_shadow_root: Path | None = None,
|
||||
valid_fov_mask_path: Path | None = None,
|
||||
) -> Path:
|
||||
roots = {
|
||||
("ddrnet", "goose"): ddrnet_goose_root.resolve(),
|
||||
@@ -349,6 +350,7 @@ def seal_vegetation_shadow_lab(
|
||||
mission_policy_path,
|
||||
provider_label_map_path,
|
||||
m49_tgs_full_shadow_root,
|
||||
valid_fov_mask_path,
|
||||
)
|
||||
if any(value is not None for value in policy_inputs) and not all(
|
||||
value is not None for value in policy_inputs
|
||||
@@ -385,6 +387,7 @@ def seal_vegetation_shadow_lab(
|
||||
mission_policy_path is not None
|
||||
and provider_label_map_path is not None
|
||||
and m49_tgs_full_shadow_root is not None
|
||||
and valid_fov_mask_path is not None
|
||||
and route_video is not None
|
||||
):
|
||||
repository_root = mission_policy_path.resolve().parents[2]
|
||||
@@ -543,13 +546,25 @@ def seal_vegetation_shadow_lab(
|
||||
and linked_tgs_result_id is not None
|
||||
and mission_policy_path is not None
|
||||
and provider_label_map_path is not None
|
||||
and valid_fov_mask_path is not None
|
||||
):
|
||||
policy_archive = temporary / "video" / "coarse-material-policy-masks.zip"
|
||||
valid_fov_destination = temporary / "video" / "valid-fov-mask.png"
|
||||
shutil.copyfile(valid_fov_mask_path.resolve(strict=True), valid_fov_destination)
|
||||
valid_fov_descriptor = {
|
||||
"role": "route-camera-valid-fov-mask",
|
||||
"path": "video/valid-fov-mask.png",
|
||||
"byte_length": valid_fov_destination.stat().st_size,
|
||||
"sha256": sha256_path(valid_fov_destination),
|
||||
"media_type": "image/png",
|
||||
}
|
||||
artifacts.append(valid_fov_descriptor)
|
||||
policy_counts = build_policy_mask_archive(
|
||||
source_archive=route_video_archive,
|
||||
destination_archive=policy_archive,
|
||||
fine_taxonomy=_object(route_video["taxonomy"], "fine video taxonomy"),
|
||||
provider_label_map=provider_label_map,
|
||||
valid_fov_mask=valid_fov_destination,
|
||||
)
|
||||
policy_descriptor = {
|
||||
"role": "route-coarse-material-mask-archive",
|
||||
@@ -571,6 +586,11 @@ def seal_vegetation_shadow_lab(
|
||||
"taxonomy": policy_taxonomy(),
|
||||
"aggregate_prediction_pixels": policy_counts,
|
||||
"linked_tgs_result_id": linked_tgs_result_id,
|
||||
"valid_fov": {
|
||||
"mask_path": valid_fov_descriptor["path"],
|
||||
"mask_sha256": valid_fov_descriptor["sha256"],
|
||||
"outside_valid_fov_class_id": 9,
|
||||
},
|
||||
"policy": {
|
||||
"profile_id": mission_policy["profile_id"],
|
||||
"profile_sha256": sha256_path(mission_policy_path),
|
||||
@@ -591,6 +611,7 @@ def seal_vegetation_shadow_lab(
|
||||
"TGS causal rolling 1 s and metric obstacle tracks"
|
||||
),
|
||||
"camera_semantic_temporal_filter": "none",
|
||||
"camera_valid_fov_filter": "sealed exact KB4 valid-FOV mask",
|
||||
"reason": "No admitted TGS-to-camera pixel projection exists.",
|
||||
},
|
||||
}
|
||||
@@ -680,7 +701,11 @@ def seal_vegetation_shadow_lab(
|
||||
)
|
||||
),
|
||||
"Vegetation semantics never clears rigid LiDAR/TGS occupancy.",
|
||||
"Undefined pixels outside the 600x600 center crop remain fail-closed.",
|
||||
(
|
||||
"Pixels outside the exact KB4 valid FOV are transparent UNOBSERVED evidence."
|
||||
if mission_policy is not None
|
||||
else "Undefined pixels outside the 600x600 center crop remain fail-closed."
|
||||
),
|
||||
*(
|
||||
[
|
||||
(
|
||||
@@ -723,6 +748,7 @@ def _parse_args() -> argparse.Namespace:
|
||||
parser.add_argument("--mission-policy-path", type=Path)
|
||||
parser.add_argument("--provider-label-map-path", type=Path)
|
||||
parser.add_argument("--m49-tgs-full-shadow-root", type=Path)
|
||||
parser.add_argument("--valid-fov-mask-path", type=Path)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -739,6 +765,7 @@ def main() -> None:
|
||||
mission_policy_path=args.mission_policy_path,
|
||||
provider_label_map_path=args.provider_label_map_path,
|
||||
m49_tgs_full_shadow_root=args.m49_tgs_full_shadow_root,
|
||||
valid_fov_mask_path=args.valid_fov_mask_path,
|
||||
)
|
||||
print(destination)
|
||||
|
||||
|
||||
+15
-1
@@ -138,7 +138,6 @@ from k1link.web.m49_physical_safety_playback_api import (
|
||||
)
|
||||
from k1link.web.m49_tgs_fail_closed_api import build_m49_tgs_fail_closed_router
|
||||
from k1link.web.m49_tgs_full_shadow_api import build_m49_tgs_full_shadow_router
|
||||
from k1link.web.vegetation_shadow_lab_api import build_vegetation_shadow_lab_router
|
||||
from k1link.web.map_api import (
|
||||
MapGatewayConfiguration,
|
||||
MapGatewayProxy,
|
||||
@@ -165,6 +164,10 @@ from k1link.web.session_api import build_session_router
|
||||
from k1link.web.simulation_projects_api import build_simulation_projects_router
|
||||
from k1link.web.simulation_world_provider_api import build_simulation_world_provider_router
|
||||
from k1link.web.system_telemetry_api import build_system_telemetry_router
|
||||
from k1link.web.vegetation_shadow_lab_api import (
|
||||
build_vegetation_benchmark_lab_router,
|
||||
build_vegetation_shadow_lab_router,
|
||||
)
|
||||
from k1link.web.viewer_diagnostics_api import build_viewer_diagnostics_router
|
||||
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parents[3]
|
||||
@@ -1031,6 +1034,17 @@ app.include_router(
|
||||
),
|
||||
)
|
||||
)
|
||||
app.include_router(
|
||||
build_vegetation_benchmark_lab_router(
|
||||
root_provider=lambda: (
|
||||
REPOSITORY_ROOT
|
||||
/ ".runtime"
|
||||
/ "compute-experiments"
|
||||
/ "lab-v1-vegetation-benchmark"
|
||||
/ "results"
|
||||
),
|
||||
)
|
||||
)
|
||||
app.include_router(
|
||||
build_m49_physical_safety_playback_router(
|
||||
root_provider=lambda: (
|
||||
|
||||
@@ -5,7 +5,6 @@ from __future__ import annotations
|
||||
import copy
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import zipfile
|
||||
from collections.abc import Callable
|
||||
from functools import lru_cache
|
||||
@@ -20,10 +19,9 @@ from k1link.laboratory.evidence_report import (
|
||||
LaboratoryEvidenceReportError,
|
||||
verify_laboratory_evidence_result,
|
||||
)
|
||||
from k1link.laboratory.vegetation_shadow_lab import LAB_SCHEMA, RESULT_PREFIX
|
||||
from k1link.laboratory.vegetation_shadow_lab import LAB_SCHEMA
|
||||
|
||||
RootProvider = Callable[[], Path | None]
|
||||
RESULT_ID: Final = re.compile(rf"^{re.escape(RESULT_PREFIX)}[a-f0-9]{{64}}$")
|
||||
_MAX_DOCUMENT_BYTES: Final = 1024 * 1024
|
||||
_DEFINITION: Final = LaboratoryEvidenceDefinition(
|
||||
work_id="lab-v1-vegetation-shadow",
|
||||
@@ -32,25 +30,55 @@ _DEFINITION: Final = LaboratoryEvidenceDefinition(
|
||||
document_name="result.json",
|
||||
result_schema_version=LAB_SCHEMA,
|
||||
)
|
||||
_BENCHMARK_DEFINITION: Final = LaboratoryEvidenceDefinition(
|
||||
work_id="lab-v1-vegetation-benchmark",
|
||||
runtime_relative_root=PurePosixPath("lab-v1-vegetation-benchmark/results"),
|
||||
result_id_prefix="lab-v1-vegetation-benchmark",
|
||||
document_name="result.json",
|
||||
result_schema_version=LAB_SCHEMA,
|
||||
)
|
||||
|
||||
|
||||
def build_vegetation_shadow_lab_router(
|
||||
*, root_provider: RootProvider = lambda: None,
|
||||
) -> APIRouter:
|
||||
router = APIRouter(
|
||||
return _build_vegetation_lab_router(
|
||||
prefix="/api/v1/laboratory/vegetation-shadow",
|
||||
definition=_DEFINITION,
|
||||
root_provider=root_provider,
|
||||
)
|
||||
|
||||
|
||||
def build_vegetation_benchmark_lab_router(
|
||||
*, root_provider: RootProvider = lambda: None,
|
||||
) -> APIRouter:
|
||||
return _build_vegetation_lab_router(
|
||||
prefix="/api/v1/laboratory/vegetation-benchmark",
|
||||
definition=_BENCHMARK_DEFINITION,
|
||||
root_provider=root_provider,
|
||||
)
|
||||
|
||||
|
||||
def _build_vegetation_lab_router(
|
||||
*,
|
||||
prefix: str,
|
||||
definition: LaboratoryEvidenceDefinition,
|
||||
root_provider: RootProvider,
|
||||
) -> APIRouter:
|
||||
router = APIRouter(
|
||||
prefix=prefix,
|
||||
tags=["laboratory"],
|
||||
)
|
||||
|
||||
@router.get("/{result_id}")
|
||||
def get_result(result_id: str) -> dict[str, object]:
|
||||
candidate = _resolve_candidate(root_provider, result_id)
|
||||
return {**copy.deepcopy(_read_verified(candidate)), "access": "read-only"}
|
||||
candidate = _resolve_candidate(root_provider, definition, result_id)
|
||||
return {**copy.deepcopy(_read_verified(candidate, definition)), "access": "read-only"}
|
||||
|
||||
@router.get("/{result_id}/assets/{asset_path:path}")
|
||||
def get_asset(result_id: str, asset_path: str) -> FileResponse:
|
||||
candidate = _resolve_candidate(root_provider, result_id)
|
||||
manifest = _read_verified(candidate)
|
||||
candidate = _resolve_candidate(root_provider, definition, result_id)
|
||||
manifest = _read_verified(candidate, definition)
|
||||
artifacts = manifest.get("artifacts")
|
||||
if not isinstance(artifacts, list):
|
||||
raise HTTPException(status_code=404, detail="Vegetation LAB asset not found")
|
||||
@@ -90,8 +118,8 @@ def build_vegetation_shadow_lab_router(
|
||||
|
||||
@router.get("/{result_id}/masks/{sequence}")
|
||||
def get_video_mask(result_id: str, sequence: int) -> Response:
|
||||
candidate = _resolve_candidate(root_provider, result_id)
|
||||
manifest = _read_verified(candidate)
|
||||
candidate = _resolve_candidate(root_provider, definition, result_id)
|
||||
manifest = _read_verified(candidate, definition)
|
||||
route_video = manifest.get("route_video")
|
||||
if (
|
||||
not isinstance(route_video, dict)
|
||||
@@ -168,9 +196,13 @@ def _configured_root(provider: RootProvider) -> Path | None:
|
||||
return root if root.is_dir() else None
|
||||
|
||||
|
||||
def _resolve_candidate(provider: RootProvider, result_id: str) -> Path:
|
||||
def _resolve_candidate(
|
||||
provider: RootProvider,
|
||||
definition: LaboratoryEvidenceDefinition,
|
||||
result_id: str,
|
||||
) -> Path:
|
||||
root = _configured_root(provider)
|
||||
if root is None or RESULT_ID.fullmatch(result_id) is None:
|
||||
if root is None or definition.result_id_pattern.fullmatch(result_id) is None:
|
||||
raise HTTPException(status_code=404, detail="Vegetation LAB result not found")
|
||||
candidate = root / result_id
|
||||
if candidate.is_symlink():
|
||||
@@ -184,7 +216,10 @@ def _resolve_candidate(provider: RootProvider, result_id: str) -> Path:
|
||||
return resolved
|
||||
|
||||
|
||||
def _read_verified(candidate: Path) -> dict[str, Any]:
|
||||
def _read_verified(
|
||||
candidate: Path,
|
||||
definition: LaboratoryEvidenceDefinition,
|
||||
) -> dict[str, Any]:
|
||||
try:
|
||||
rows: list[tuple[str, int, int, int, int]] = []
|
||||
for path in sorted(candidate.rglob("*"), key=lambda item: item.as_posix()):
|
||||
@@ -202,19 +237,39 @@ def _read_verified(candidate: Path) -> dict[str, Any]:
|
||||
status_code=503,
|
||||
detail="Vegetation LAB evidence failed verification",
|
||||
) from None
|
||||
return _read_verified_cached(str(candidate), signature)
|
||||
return _read_verified_cached(
|
||||
str(candidate),
|
||||
signature,
|
||||
definition.work_id,
|
||||
str(definition.runtime_relative_root),
|
||||
definition.result_id_prefix,
|
||||
definition.document_name,
|
||||
definition.result_schema_version,
|
||||
)
|
||||
|
||||
|
||||
@lru_cache(maxsize=16)
|
||||
def _read_verified_cached(
|
||||
candidate_text: str,
|
||||
signature: tuple[tuple[str, int, int, int, int], ...],
|
||||
work_id: str,
|
||||
runtime_relative_root: str,
|
||||
result_id_prefix: str,
|
||||
document_name: str,
|
||||
result_schema_version: str,
|
||||
) -> dict[str, Any]:
|
||||
del signature
|
||||
candidate = Path(candidate_text)
|
||||
definition = LaboratoryEvidenceDefinition(
|
||||
work_id=work_id,
|
||||
runtime_relative_root=PurePosixPath(runtime_relative_root),
|
||||
result_id_prefix=result_id_prefix,
|
||||
document_name=document_name,
|
||||
result_schema_version=result_schema_version,
|
||||
)
|
||||
try:
|
||||
verify_laboratory_evidence_result(_DEFINITION, candidate)
|
||||
path = candidate / "result.json"
|
||||
verify_laboratory_evidence_result(definition, candidate)
|
||||
path = candidate / definition.document_name
|
||||
if path.stat().st_size > _MAX_DOCUMENT_BYTES:
|
||||
raise LaboratoryEvidenceReportError("Vegetation LAB document is too large")
|
||||
payload = json.loads(path.read_text("utf-8"))
|
||||
@@ -228,4 +283,7 @@ def _read_verified_cached(
|
||||
return payload
|
||||
|
||||
|
||||
__all__ = ["build_vegetation_shadow_lab_router"]
|
||||
__all__ = [
|
||||
"build_vegetation_benchmark_lab_router",
|
||||
"build_vegetation_shadow_lab_router",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user