feat(perception): qualify 1x realtime replay envelope
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def _module(name: str, relative: str):
|
||||
path = Path(__file__).resolve().parents[1] / relative
|
||||
spec = importlib.util.spec_from_file_location(name, path)
|
||||
assert spec is not None and spec.loader is not None
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
sys.modules[spec.name] = module
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
def test_camera_replay_loads_segments_lazily_and_checks_each_digest(tmp_path: Path) -> None:
|
||||
module = _module(
|
||||
"e21_source_replay_test",
|
||||
"experiments/perception/run_e12_shadow_transport_replay.py",
|
||||
)
|
||||
epoch = tmp_path / "epoch-1"
|
||||
segments = epoch / "segments"
|
||||
segments.mkdir(parents=True)
|
||||
(epoch / "init.mp4").write_bytes(b"init")
|
||||
rows = []
|
||||
for sequence, payload in ((1, b"one"), (2, b"two")):
|
||||
path = segments / f"{sequence}.m4s"
|
||||
path.write_bytes(payload)
|
||||
rows.append(
|
||||
{
|
||||
"host_epoch_ns": sequence * 100_000_000,
|
||||
"host_monotonic_ns": sequence * 100_000_000,
|
||||
"length": len(payload),
|
||||
"path": f"segments/{sequence}.m4s",
|
||||
"sequence": sequence,
|
||||
"sha256": hashlib.sha256(payload).hexdigest(),
|
||||
}
|
||||
)
|
||||
(epoch / "index.jsonl").write_text(
|
||||
"".join(json.dumps(row) + "\n" for row in rows),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
events = module._camera_events(epoch, 1.0)
|
||||
assert next(events).modality == "camera-init"
|
||||
assert next(events).payload == b"one"
|
||||
(segments / "2.m4s").write_bytes(b"changed-after-generator-start")
|
||||
with pytest.raises(RuntimeError, match="length differs"):
|
||||
next(events)
|
||||
|
||||
|
||||
def test_e21_trend_reports_accumulating_age_and_stable_memory() -> None:
|
||||
module = _module(
|
||||
"e21_analyzer_test",
|
||||
"experiments/perception/analyze_e21_realtime_envelope.py",
|
||||
)
|
||||
growing = module._trend([(float(index), float(index) * 2) for index in range(20)])
|
||||
stable = module._trend([(float(index), 100.0) for index in range(20)])
|
||||
|
||||
assert growing["slope_per_second"] == pytest.approx(2.0)
|
||||
assert growing["late_vs_early_p95"] > 0
|
||||
assert stable["slope_per_second"] == pytest.approx(0.0)
|
||||
assert stable["late_vs_early_p95"] == pytest.approx(0.0)
|
||||
|
||||
|
||||
def test_e21_profile_keeps_diagnostic_authority_and_long_1x_gate() -> None:
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
profile = json.loads(
|
||||
(
|
||||
root
|
||||
/ "experiments"
|
||||
/ "perception"
|
||||
/ "e21_realtime_envelope_profile.json"
|
||||
).read_text()
|
||||
)
|
||||
|
||||
assert profile["source"]["speed"] == 1.0
|
||||
assert profile["source"]["minimum_span_seconds"] >= 55.0
|
||||
assert profile["worker"]["minimum_detector_fps"] >= 9.5
|
||||
assert profile["worker"]["maximum_detector_drop_fraction"] <= 0.02
|
||||
assert profile["worker"]["maximum_p95_world_state_age_ms"] == 200.0
|
||||
assert profile["authority"] == {
|
||||
"commands_enabled": False,
|
||||
"navigation_or_safety_accepted": False,
|
||||
}
|
||||
Reference in New Issue
Block a user