Files
gps-denied-onboard/_docs/03_implementation/batch_74_report.md
T
Oleksandr Bezdieniezhnykh 1d260f7e41 [AZ-594] Implement core-three harness stubs (fdr_reader, frame_source_replay, imu_replay)
Replaces the NotImplementedError stubs AZ-406 reserved on three runner-
side helpers; these were stranded from any tracker ticket since
AZ-407/408 never came back to fill them. Concrete bodies:

* fdr_reader.iter_records: JSONL parser + wire-envelope validator;
  recursive *.jsonl walk; projects {schema_version, ts, producer_id,
  kind, payload} to runner-side FdrRecord with record_type/monotonic_ms
  renames; yields oldest-first.
* frame_source_replay.replay_video: OpenCV VideoCapture decode + JPEG
  re-encode; auto-detects file vs directory; injectable sleep_fn for
  unit-test pacing.
* imu_replay.ImuReplayer.replay: csv.DictReader parse; degrees->radians
  attitude conversion; tolerates scientific notation; same sleep_fn
  injection pattern.

Adds 34 unit tests (14 + 10 + 10). Full e2e unit suite: 558 passed (+31).
Existing scenario _harness_helpers_implemented probes still return False
because they also depend on sitl_observer / fc_proxy_runtime stubs that
remain pending; scenario probe cleanup is out of AZ-594 scope.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 08:42:12 +03:00

4.1 KiB

Batch 74 Report — Harness Stubs (cycle 1, batch 8 of test phase)

Batch: 74 Date: 2026-05-17 Context: Test implementation (greenfield Step 10 — Implement Tests) Tasks: AZ-594 (4 cp) — 1 task (umbrella ticket for the core three harness stubs) Cycle: 1 Verdict: COMPLETE — PASS (self-reviewed; see reviews/batch_74_review.md)

Summary

A planning-gap fix-up batch. The skip-gates in batches 71-73 referenced AZ-441 / AZ-407 / AZ-416 leftovers — but on inspection none of those tickets actually owned the deferred harness stubs (frame_source_replay, imu_replay, fdr_reader, sitl_observer, fc_proxy_runtime). The stubs were AZ-406 surface reservations that AZ-407/408 never came back to fill, and were stranded without a tracker entry.

This batch creates a single umbrella ticket (AZ-594) and ships the core three of the five — the ones with the lowest implementation risk and the broadest unblock surface:

  • fdr_reader.iter_records — JSONL parser + wire-schema validator.
  • frame_source_replay.replay_video — OpenCV-backed decode + sink emission.
  • imu_replay.ImuReplayer.replay — CSV parser + emitter driver.

The remaining two stubs (sitl_observer.get_observer + read_* surfaces; fc_proxy_runtime driver + docker wiring) need separate tickets — they touch live pymavlink / yamspy / TCP plumbing and don't fit in a single batch alongside the core three. Those become batch 75 candidates.

AZ-594 — Harness stubs (core three) (4 cp)

  • runner/helpers/fdr_reader.pyiter_records(fdr_archive_root) recursively walks *.jsonl files, validates each line against the wire envelope (schema_version, ts, producer_id, kind, payload), projects onto the runner-side FdrRecord dataclass (record_type for kind; monotonic_ms derived from ISO 8601 ts), and yields records oldest-first. Raises FileNotFoundError on missing root + ValueError with file+line on malformed envelopes. archive_size_bytes body was already present.
  • runner/helpers/frame_source_replay.pyFrameSourceReplayer now backs both replay_image_directory(dir) and replay_video(path). replay_video auto-detects file vs directory (so AZ-408 injector frame-directory outputs work via the same entry point). OpenCV VideoCapture decodes MP4; every frame is re-JPEG-encoded so the sink always receives JPEG bytes. Cadence pacing is parameterised via a sleep_fn injection so unit tests can drop wall-clock entirely.
  • runner/helpers/imu_replay.pyImuReplayer.replay(csv_path) parses data_imu.csv (the AZ-408 schema with possibly scientific- notation floats), constructs typed ImuSamples with attitude converted from degrees → radians, and drives FcInboundEmitter.emit. Same sleep_fn + realtime injection pattern as frame_source_replay for test parity.

Scenario-probe interaction

The existing _harness_helpers_implemented probes in batches 71-73 pass /tmp/non-existent to each helper. Previously the inner except NotImplementedError: return False fired; with the new bodies, the outer except Exception: return False catches the FileNotFoundError and still returns False. So:

  • No existing scenario silently starts running its full E2E path.
  • All eight skip-gated scenarios from batches 71-73 continue to skip cleanly because they ALSO depend on sitl_observer / mavproxy_tlog_reader (for some) / fc_proxy_runtime (for FT-N-04).
  • Probe-cleanup is explicitly excluded from AZ-594 scope and will land in the future batch that fills the remaining two stubs.

Test Results

  • New unit tests: 14 (fdr_reader) + 10 (frame_source_replay) + 10 (imu_replay) = 34 new tests.
  • Full e2e/_unit_tests suite: 558 passed in 139 s (previous cumulative: 527 → +31 net).
  • No new linter errors.

State

  • Spec moved: _docs/02_tasks/todo/AZ-594_harness_stubs_core_three.md_docs/02_tasks/done/.
  • _docs/_autodev_state.md advanced to last_completed_batch: 74.
  • Cumulative review window: last_cumulative_review = batches_70-72; next K=3 cumulative review fires at the end of batch 75.