[AZ-894] [AZ-896] Add CSV-driven replay adapter + format docs

Replaces the tlog two-clock replay surface with a single-clock path
driven by the Derkachi-schema CSV. --imu is the new required CLI arg;
--tlog stays as a deprecated alias (warned + ignored when --imu set)
until AZ-895 deletes it.

* csv_ground_truth.py parses the 15-column schema, fails fast at
  startup on every documented schema fault (AC-5).
* CsvReplayFcAdapter slots into ReplayInputBundle.fc_adapter alongside
  the tlog sibling; mirrors Invariant-5 outbound wiring; inbound bus is
  intentionally a no-op since the loop reads CSV directly.
* _run_replay_loop branches on imu_csv_path, stamps
  VioOutput.emitted_at_ns from the CSV-derived frame_end_ns (AC-4),
  closing the AZ-848 two-clock surface for the new path.
* AZ-896 ships the operator-facing format spec at
  _docs/02_document/contracts/replay/csv_replay_format.md plus a
  20-row example CSV (AC-3 regression-locked).

Tests: 11 + 12 new unit tests, plus updates to AZ-401 import-boundary
and AZ-402 CLI suites. Full unit suite 2,327 passed / 86 skipped.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-26 18:40:29 +03:00
parent 3020779404
commit 6be207cef3
19 changed files with 1833 additions and 93 deletions
+10 -2
View File
@@ -69,6 +69,7 @@ class DerkachiReplayInputs:
video_path: Path
tlog_path: Path
imu_csv_path: Path
calibration_path: Path
config_path: Path
signing_key_path: Path
@@ -170,6 +171,7 @@ def derkachi_replay_inputs(tmp_path_factory: pytest.TempPathFactory) -> Derkachi
return DerkachiReplayInputs(
video_path=video_path,
tlog_path=tlog_path,
imu_csv_path=csv_path,
calibration_path=_calibration_path(),
config_path=config_path,
signing_key_path=signing_key_path,
@@ -241,8 +243,8 @@ def replay_runner(derkachi_replay_inputs: DerkachiReplayInputs) -> Any:
binary,
"--video",
str(derkachi_replay_inputs.video_path),
"--tlog",
str(derkachi_replay_inputs.tlog_path),
"--imu",
str(derkachi_replay_inputs.imu_csv_path),
"--output",
str(out_path),
"--camera-calibration",
@@ -254,6 +256,12 @@ def replay_runner(derkachi_replay_inputs: DerkachiReplayInputs) -> Any:
"--pace",
pace,
]
# --tlog is deprecated under AZ-894 but we still forward it
# when the synth tlog exists, so the legacy-path e2e tests
# (test_derkachi_real_tlog.py) keep exercising the deprecation
# warning until AZ-895 deletes the path entirely.
if derkachi_replay_inputs.tlog_path.is_file():
argv.extend(["--tlog", str(derkachi_replay_inputs.tlog_path)])
if time_offset_ms is not None:
argv.extend(["--time-offset-ms", str(time_offset_ms)])
if skip_auto_sync: