mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 04:41:13 +00:00
[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>
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
# 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.py`** —
|
||||
`iter_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.py`** — `FrameSourceReplayer`
|
||||
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.py`** — `ImuReplayer.replay(csv_path)`
|
||||
parses `data_imu.csv` (the AZ-408 schema with possibly scientific-
|
||||
notation floats), constructs typed `ImuSample`s 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.
|
||||
Reference in New Issue
Block a user