[AZ-698] Multi-flight tlog handling: segment first, pick last flight

Real derkachi.tlog covers 3 takeoffs at the same field but the
uploaded video covers only the last. Original NCC argmax + AZ-405
head-takeoff fallback both biased toward flight 1, violating the
spec's "the last chunk in tlog is relevant" framing.

Patch: pre-NCC flight segmenter partitions the IMU energy stream
into distinct flights (threshold + gap walk); find_aligned_window
restricts NCC search to the last segment; low-confidence fallback
uses that segment's start instead of head-takeoff detection.
AlignedWindow gains flight_count_detected + selected_flight_index
for FDR-visible audit.

7 new unit tests (segmenter shapes + end-to-end multi-flight
pipeline + segmented fallback path). 19 AZ-698 tests pass, 113
in the regression slice. Zero new mypy --strict errors.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-20 16:44:41 +03:00
parent 87fe98858f
commit f5366bbca1
9 changed files with 587 additions and 21 deletions
@@ -98,6 +98,33 @@ 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.
## Follow-up commit: multi-flight handling
User-reported gap during the AZ-698 "In Testing" phase: real
`derkachi.tlog` contains **three takeoffs**; the video covers only
the last. The original AZ-698 happy path (`np.argmax`) and fallback
(`detect_tlog_takeoff` on head) were both biased toward flight 1.
Patched in a follow-up commit on top of batch 99:
- New `_segment_flights_from_imu_energy` helper partitions the IMU
energy stream into distinct flights using a motion-threshold +
gap-tolerance walk.
- `find_aligned_window` now restricts NCC search to the **last**
detected segment.
- Low-confidence fallback uses the last segment's start instead of
re-running head-takeoff detection on the whole tlog.
- `AlignedWindow` gains `flight_count_detected` + `selected_flight_index`
for observability; both are surfaced in the `replay.auto_trim.resolved` /
`…fallback_to_takeoff` log records.
- New unit tests: segmenter happy paths (1-flight, 3-flight),
ground-blip rejection, cruise-lull preservation; integration test
proving `find_aligned_window` on a 3-flight tlog picks flight 3.
Test totals after follow-up: **113 passed, 2 skipped, 0 failed.**
Zero new mypy --strict errors (12 errors in scope, all pre-existing
and unchanged).
## Next batch
Batch 100 — **AZ-699** (real-flight validation runner). Depends on