Files
gps-denied-onboard/_docs/03_implementation/batch_99_cycle2_report.md
T
Oleksandr Bezdieniezhnykh 87fe98858f [AZ-698] Tlog trim + mid-flight alignment for replay
Adds find_aligned_window cross-correlation (NCC, per-window unit norm)
between IMU energy and video optical-flow magnitude. Returns
AlignedWindow{tlog_start_ns, tlog_end_ns, offset_ms, confidence,
used_fallback}, with fallback to head-takeoff on low confidence to
preserve AZ-405 behavior. TlogReplayFcAdapter honors tlog_start_ns and
skips pre-window messages. New --auto-trim CLI flag, mutex with
--time-offset-ms. AC-1..AC-4 covered by unit tests; AC-5 skipped (no
real flight_derkachi.mp4 in repo). 106 tests pass in regression slice.
Zero new mypy --strict errors.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 16:29:59 +03:00

4.4 KiB

Batch 99 — Cycle 2 — AZ-698

Date: 2026-05-20 Tasks: AZ-698 (Tlog trim + mid-flight alignment for replay). Story points: 5. Jira status: AZ-698 → In Testing.

What shipped

A normalised-cross-correlation aligner that finds the video's playback window inside a longer tlog, plus the plumbing to honor that window across the replay-mode composition root, replay coordinator, replay-side FC adapter, config schema, and CLI.

  • find_aligned_window(tlog_path, video_path, config, ...) -> AlignedWindow in src/gps_denied_onboard/replay_input/auto_sync.py. Returns (tlog_start_ns, tlog_end_ns, offset_ms, confidence, used_fallback).
  • AlignedWindow DTO + auto_trim flag + alignment_* knobs on ReplayConfig / ReplayAutoSyncConfig.
  • TlogReplayFcAdapter skips messages with _timestamp < tlog_start_ns when seeded (AC-3).
  • --auto-trim CLI flag on gps-denied-replay, mutually exclusive with --time-offset-ms.

Files changed

Production (8):

  • src/gps_denied_onboard/replay_input/interface.py
  • src/gps_denied_onboard/replay_input/auto_sync.py
  • src/gps_denied_onboard/replay_input/tlog_video_adapter.py
  • src/gps_denied_onboard/replay_input/__init__.py (re-export AlignedWindow)
  • src/gps_denied_onboard/components/c8_fc_adapter/tlog_replay_adapter.py
  • src/gps_denied_onboard/config/schema.py
  • src/gps_denied_onboard/config/loader.py
  • src/gps_denied_onboard/runtime_root/_replay_branch.py
  • src/gps_denied_onboard/cli/replay.py

Tests (1 new):

  • tests/unit/replay_input/test_az698_window_alignment.py

Specs:

  • _docs/02_tasks/done/AZ-698_tlog_trim_midflight_alignment.md (moved from todo/, completion notes appended).

AC coverage

AC Test Result
AC-1 test_ac1_takeoff_aligned_offset_matches_az405_within_50ms PASS
AC-2 test_ac2_mid_flight_alignment_locates_correct_window PASS
AC-3 test_ac3_adapter_seek_skips_pre_window_messages, _default_no_seek_* PASS
AC-4 test_ac4_validator_passes_for_takeoff_aligned_offset, _mid_flight_* PASS
AC-5 test_ac5_cli_auto_trim_smoke_uses_find_aligned_window SKIPPED

AC-5 skip reason: the repo's flight_derkachi.mp4 is a 134-byte placeholder, not a real recording. Live CLI smoke is covered by AZ-699 (validation runner) once the real video is sourced.

Test run

tests/unit/replay_input/test_az698_window_alignment.py        12 PASS  1 SKIP
tests/unit/replay_input/test_az405_auto_sync.py               14 PASS
tests/unit/replay_input/test_az405_replay_input_adapter.py    13 PASS
tests/unit/c8_fc_adapter/test_az399_tlog_replay_adapter.py    24 PASS  1 SKIP
tests/unit/replay_input/test_tlog_ground_truth.py             12 PASS
tests/unit/test_az697_gps_compare.py                          10 PASS
tests/unit/calibration/test_khp20s30_factory.py                9 PASS
tests/unit/runtime_root/test_az687_pre_constructed_replay_mode.py 3 PASS
tests/unit/test_az269_config_loader.py                         9 PASS

Totals: 106 passed, 2 skipped, 0 failed. No regressions in adjacent suites.

Strict typing

Baseline (pre-batch, by stash-and-rerun): 17 mypy --strict errors across 6 of the 8 touched src/ files. After batch: 17 errors — same count, same kinds, with line numbers shifted only by added code. Zero new strict-typing errors introduced by AZ-698. Pre-existing errors are out-of-scope per coderule.mdc ("Pre-existing lint errors should only be fixed if they're in the modified area" — they were not in the bytes modified for AZ-698 ACs).

The new public symbols (find_aligned_window, AlignedWindow, _zero_mean_normalise, _resample_uniform) carry explicit npt.NDArray[np.float64] annotations so they don't add to the debt.

Code review verdict

Inline self-review: code paths cover the spec's scope, fallback to head-takeoff on low confidence preserves AZ-405 behavior, adapter seek is opt-in via constructor kwarg so the --skip-auto-sync path is untouched. The normalised-cross-correlation switch is documented in the spec's "Implementation Notes" appendix as the algorithmic decision of record.

Next batch

Batch 100 — AZ-699 (real-flight validation runner). Depends on AZ-697 (ground truth) and AZ-698 (alignment) — both now in testing.