fix(lab): enforce canonical replay runtime
This commit is contained in:
@@ -17,6 +17,7 @@ from fastapi.responses import FileResponse
|
||||
from fastapi.routing import APIRoute
|
||||
|
||||
import k1link.sessions.media as recorded_media_module
|
||||
import k1link.web.session_api as session_api_module
|
||||
from k1link.compute import RecordedPerceptionOverlayArtifact, RecordedPerceptionVideo
|
||||
from k1link.device_plugins.xgrids_k1 import xgrids_k1_archive_source
|
||||
from k1link.device_plugins.xgrids_k1.mqtt.capture import FRAME_HEADER, RAW_MAGIC
|
||||
@@ -458,6 +459,80 @@ def test_completed_recording_get_does_not_hold_delete_for_launch_lease(
|
||||
manager.close()
|
||||
|
||||
|
||||
def test_canonical_lab_spatial_frame_uses_ready_immutable_recording(
|
||||
tmp_path: Path,
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
repository = tmp_path / "repo"
|
||||
sessions = repository / "sessions"
|
||||
session = make_legacy_session(sessions, "20260716T205632Z_viewer_live")
|
||||
store = SessionStore(repository, data_dir=tmp_path / "data")
|
||||
store.reconcile_archive(xgrids_k1_archive_source(sessions))
|
||||
payload = b"sealed-spatial-recording"
|
||||
|
||||
def export_recording(source: Path, destination: Path) -> dict[str, object]:
|
||||
destination.write_bytes(payload)
|
||||
return {
|
||||
"source_sha256": hashlib.sha256(source.read_bytes()).hexdigest(),
|
||||
"rrd_sha256": hashlib.sha256(payload).hexdigest(),
|
||||
"rrd_bytes": len(payload),
|
||||
"timeline": "session_time",
|
||||
"timeline_start_ns": 0,
|
||||
"timeline_end_ns": 1_000_000_000,
|
||||
}
|
||||
|
||||
materializer = SessionRecordingMaterializer(store.data_dir, exporter=export_recording)
|
||||
command = store.prepare_replay(session.name)
|
||||
recording = materializer.materialize(command)
|
||||
manager = SessionRecordingPreparationManager(materializer)
|
||||
resolved = manager.resolve_cached(command)
|
||||
assert resolved is not None and resolved.recording is not None
|
||||
generation = hashlib.sha256(payload).hexdigest()
|
||||
expected = {
|
||||
"schema_version": "missioncore.canonical-recorded-lab-spatial-frame/v1",
|
||||
"target_time_ns": 500_000_000,
|
||||
"source_time_ns": 499_000_000,
|
||||
"pose_time_ns": 499_000_000,
|
||||
"trajectory_time_ns": 490_000_000,
|
||||
"body_frame": {
|
||||
"origin_map_xyz_m": [0.0, 0.0, 0.0],
|
||||
"basis_map_from_body": [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]],
|
||||
},
|
||||
"source_point_count": 1,
|
||||
"source_points_body_xyz_m": [[1.0, 2.0, 3.0]],
|
||||
"local_slam_body_xyz_m": [[0.0, 0.0, 0.0]],
|
||||
}
|
||||
|
||||
def spatial_frame(path: Path, sha256: str, time_ns: int) -> dict[str, object]:
|
||||
assert path == recording.path
|
||||
assert sha256 == generation
|
||||
assert time_ns == 500_000_000
|
||||
return expected
|
||||
|
||||
monkeypatch.setattr(session_api_module, "canonical_lab_spatial_frame", spatial_frame)
|
||||
router = build_session_router(
|
||||
store,
|
||||
recording_materializer=materializer,
|
||||
recording_preparation_manager=manager,
|
||||
)
|
||||
spatial_route = endpoint(
|
||||
router,
|
||||
"/api/v1/observation-sessions/{session_id}/canonical-lab/spatial-frame",
|
||||
"GET",
|
||||
)
|
||||
try:
|
||||
response = asyncio.run(spatial_route(
|
||||
session_id=session.name,
|
||||
generation=generation,
|
||||
time_ns=500_000_000,
|
||||
))
|
||||
assert json.loads(response.body) == expected
|
||||
assert response.headers["etag"] == f'"{generation}:499000000"'
|
||||
assert response.headers["cache-control"].endswith("immutable")
|
||||
finally:
|
||||
manager.close()
|
||||
|
||||
|
||||
def test_session_router_returns_seekable_recording_and_serves_byte_ranges(
|
||||
tmp_path: Path,
|
||||
) -> None:
|
||||
|
||||
@@ -21,11 +21,48 @@ from k1link.laboratory import LaboratoryEvidenceRegistry
|
||||
from k1link.laboratory.evidence_report import verify_laboratory_evidence_result
|
||||
from k1link.laboratory.vegetation_policy_review import seal_vegetation_policy_review
|
||||
from k1link.laboratory.vegetation_shadow_lab import seal_vegetation_shadow_lab
|
||||
from k1link.web.vegetation_shadow_lab_api import build_vegetation_shadow_lab_router
|
||||
from k1link.web.vegetation_shadow_lab_api import (
|
||||
_route_tgs_anchor_payload,
|
||||
build_vegetation_shadow_lab_router,
|
||||
)
|
||||
|
||||
REPOSITORY_ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def test_route_tgs_anchor_payload_preserves_metric_evidence(tmp_path: Path) -> None:
|
||||
path = tmp_path / "tgs-evidence.npz"
|
||||
point_counts = np.arange(1, 11, dtype=np.int64)
|
||||
offsets = np.concatenate(([0], np.cumsum(point_counts)))
|
||||
points = np.arange(int(offsets[-1]) * 3, dtype=np.float32).reshape(-1, 3)
|
||||
centers = np.arange(2244 * 2, dtype=np.float32).reshape(2244, 2) * 0.45
|
||||
states = np.tile(np.arange(2244, dtype=np.uint16) % 4, (10, 1)).astype(np.uint8)
|
||||
z_bounds = np.zeros((10, 2244, 2), dtype=np.float32)
|
||||
z_bounds[..., 0] = np.nan
|
||||
z_bounds[..., 1] = 1.25
|
||||
np.savez(
|
||||
path,
|
||||
source_frame_indices=np.array(
|
||||
[20, 408, 789, 1189, 1609, 1992, 2380, 3190, 4810, 6381],
|
||||
dtype=np.int64,
|
||||
),
|
||||
current_increment_point_offsets=offsets,
|
||||
current_increment_points_xyz_m=points,
|
||||
costmap_cell_centers_xy_m=centers,
|
||||
causal_rolling_1s_costmap_states=states,
|
||||
causal_rolling_1s_costmap_z_bounds_m=z_bounds,
|
||||
)
|
||||
|
||||
payload = _route_tgs_anchor_payload(path, 409)
|
||||
|
||||
assert payload["schema_version"] == "missioncore.lab-v1-route-tgs-anchor/v1"
|
||||
assert payload["source_sequence"] == 409
|
||||
assert payload["slot"] == 1
|
||||
assert len(payload["current_points_xyz_m"]) == 2
|
||||
assert len(payload["costmap"]["centers_xy_m"]) == 2244
|
||||
assert set(payload["costmap"]["state_codes"]) == {0, 1, 2, 3}
|
||||
assert payload["costmap"]["z_bounds_m"][0] == [None, 1.25]
|
||||
|
||||
|
||||
def test_coarse_policy_masks_mark_every_outside_fov_pixel_undefined(
|
||||
tmp_path: Path,
|
||||
monkeypatch,
|
||||
|
||||
Reference in New Issue
Block a user