Files
gps-denied-onboard/_docs/_process_leftovers/2026-05-17_e2e_harness_rehabilitation.md
T
Oleksandr Bezdieniezhnykh 5c1c35da9a [autodev] step-11 path-3: calibration fix + harness drift report
Attempted Path-3 (Full SITL with community images) for the SUT Reality
Gate. Discovered sitl_observer is offline-fixture replay, not a live
SITL client -- compose-file SITL services in environment.md are
aspirational. The real Path-3 needs the fixture builders + SUT CLI
end-to-end, which surfaced 5 additional integration drifts (H-10..H-14)
on top of the prior 9.

Fixes:
- tests/fixtures/calibration/adti26.json: body_to_camera_se3 was a
  {rotation_xyzw, translation_xyz_m} dict; runtime_root/_replay_branch.py
  loader strictly expects a 4x4 SE3. Identity quaternion + zero
  translation = identity 4x4, semantically equivalent.

New files:
- tests/fixtures/replay_config_minimal.yaml: minimal replay-mode config
  for harness reproduction (mode=replay, ardupilot_plane defaults).
- .gitignore: e2e/fixtures/sitl_replay/ (generated by build_p0X_fixtures).

Documentation:
- Step 11 report: appended Path-3 attempt section.
- Leftover doc: H-10..H-14 ticket payloads added.
- Autodev state: reflects Path-3 outcome.

Step 11 stays blocked; H-13 (auto-sync AC-8 hard-fails on stationary
fixtures) requires a SUT design decision and cannot be unilaterally
fixed mid-session.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-17 21:49:32 +03:00

7.4 KiB

Leftover — E2E Tier-1 harness rehabilitation tickets deferred

  • Timestamp: 2026-05-17T17:30:00Z
  • What was blocked: Jira ticket creation for the harness drift surfaced during Step 11
  • Reason for blockage: same session as the csv_reporter fix; user skipped the structured Q&A so I did not pause for tracker writes. Full findings live in _docs/03_implementation/run_tests_step11_report.md; this leftover records the tickets that need filing.

Pending tracker writes — replay on next /autodev

Epic

type: Epic
summary: "E2E Tier-1 harness rehabilitation"
description: |
  Surfaced during /autodev Step 11 (Run Tests) cycle 1 on 2026-05-17. Both
  Tier-1 docker harnesses (top-level scripts/run-tests.sh and the fuller
  e2e/docker/run-tier1.sh) had pre-existing drift preventing them from
  running end-to-end. Local pytest suite is green (3343/88/0); SUT Reality
  Gate is unmet until at least the bootstrap harness can run
  tests/e2e/replay/ with RUN_REPLAY_E2E=1. Full report:
  _docs/03_implementation/run_tests_step11_report.md
linked_to: AZ-595, AZ-444  # related but distinct: tile-cache fixtures, Tier-2 hw loop

Story: H-7 — Bootstrap runner entrypoint

type: Story
summary: "[Bug] tests/e2e/Dockerfile entrypoint points at empty scenarios dir"
description: |
  Current entrypoint: `pytest -q /opt/tests/e2e/scenarios` (empty in repo).
  Real tests are in `tests/e2e/replay/` (test_derkachi_1min.py, etc.).
  Fix: change entrypoint to /opt/tests/e2e/ (let pytest discover both
  scenarios and replay).
story_points: 1

Story: H-8 — Install SUT in runner image

type: Story
summary: "[Bug] tests/e2e e2e-runner image doesn't install gps-denied-onboard"
description: |
  Image is python:3.10-slim with only pytest+requests+pyyaml. The replay
  tests need `gps-denied-replay` console script on PATH. Either:
   - COPY pyproject.toml + src/ and pip install -e ".[dev]", or
   - Build a wheel in a separate stage and pip install it.
  Verify the resulting image: `which gps-denied-replay`.
story_points: 3

Story: H-4..H-6 — SITL/MAVLink images choice

type: Story
summary: "[Decision] Choose SITL strategy for e2e/docker harness"
description: |
  environment.md specifies ardupilot/ardupilot-sitl:plane-stable,
  inavflight/inav-sitl:9.0.0, ardupilot/mavproxy:latest. All MISSING from
  Docker Hub. Options:
   a) Switch to community images (radarku/ardupilot-sitl etc.)
   b) Build SITLs from source in a separate stage
   c) Strip SITL services and mark SITL-bound scenarios skip(reason="sitl-unavailable")
  Track 1 doesn't depend on this; Track 2 does.
story_points: 5

Story: MAVProxy local image

type: Story
summary: "[Story] Replace ardupilot/mavproxy:latest with local pip-MAVProxy Dockerfile"
description: |
  Image doesn't exist on Docker Hub. Wrap `pip install MAVProxy` in a
  python:3.10-slim Dockerfile in e2e/fixtures/mavproxy/. Update compose
  to use the local build.
story_points: 1

Story: H-9 — Tile-cache fixture builder

type: Story
summary: "Link H-9 to AZ-595 / tile-cache fixture seeder"
description: |
  e2e/docker/docker-compose.test.yml declares tile-cache-fixture as an
  empty named volume. Track 2 cannot run without seeded tiles. AZ-595
  exists and owns this; verify scope alignment, add a link.
story_points: 2

Story: H-10 — Fixture builder uses wrong CLI flag

type: Story
summary: "[Bug] sitl_replay_builder uses --fdr-out; CLI requires --output"
description: |
  e2e/fixtures/sitl_replay_builder/builder.py:79 passes `--fdr-out` to
  `gps-denied-replay`. The CLI's actual flag (src/gps_denied_onboard/cli/replay.py:90)
  is `--output`. Also need to add the CLI's other required args
  (--camera-calibration, --config, --mavlink-signing-key) — see H-11.
  Bundle H-10 + H-11 in one PR. Unit tests in
  e2e/_unit_tests/fixtures/test_sitl_replay_builder_builder.py assert on
  `--fdr-out` and need to be updated.
story_points: 2

Story: H-11 — Fixture builder missing required CLI args

type: Story
summary: "[Bug] sitl_replay_builder doesn't pass camera-calibration/config/signing-key"
description: |
  gps-denied-replay requires --camera-calibration PATH, --config PATH,
  --mavlink-signing-key PATH. Fixture builder omits all three. Add
  fields to FixtureBuilderConfig with defaults pointing at
  tests/fixtures/calibration/adti26.json, a new
  tests/fixtures/replay_config_minimal.yaml, and
  tests/fixtures/mavlink_signing/dev_key. Also set
  BUILD_REPLAY_SINK_JSONL=ON in the subprocess env.
story_points: 2

Bug: H-12 — Calibration JSON shape drift (FIXED)

type: Bug
summary: "[Bug] adti26.json body_to_camera_se3 used dict form; loader expects 4x4"
description: |
  tests/fixtures/calibration/adti26.json declared body_to_camera_se3 as
  {rotation_xyzw, translation_xyz_m}. _replay_branch.py:308 does
  np.asarray(..., dtype=np.float64) which can't decode the dict. Fixed
  by converting to the equivalent 4x4 identity matrix. Both forms encode
  the same SE3 (identity) so no behavior change.
story_points: 1
status_after_create: "Done"

Story: H-13 — Auto-sync hard-fails on stationary fixtures

type: Story
summary: "[Bug] AC-8 auto-sync validation rejects stationary FT-P-01 fixture"
description: |
  Auto-sync (src/gps_denied_onboard/replay_input/...) hard-fails when
  --time-offset-ms 0 is supplied for a fixture with stationary IMU + no
  video motion (FT-P-01 still-image scenario). Threshold:
  frame_window_match_pct_threshold=95% in ReplayAutoSyncConfig defaults.
  Three possible fixes (design decision needed):
   a) Add --skip-auto-sync CLI flag that bypasses AC-8 validation entirely
      when time_offset_ms is explicitly supplied
   b) Lower or expose match_threshold_pct via config (already configurable
      but not surfaced in fixture builder)
   c) Change fixture builder to inject a single motion event so auto-sync
      can find SOMETHING to align on
  Recommend (a): aligns with replay protocol intent ("manual offset
  bypasses auto-sync entirely" per ReplayConfig docstring).
story_points: 3

Story: H-14 — Document BUILD_REPLAY_SINK_JSONL in .env.example

type: Story
summary: "[Doc] add BUILD_REPLAY_SINK_JSONL=ON to .env.example for replay mode"
description: |
  src/gps_denied_onboard/components/c8_fc_adapter/noop_mavlink_transport.py
  requires BUILD_REPLAY_SINK_JSONL=ON env var to construct. Not in
  .env.example. Add with comment explaining it's a replay-mode requirement
  per replay protocol Invariant 9.
story_points: 1

Story: H-1..H-3 — fixes already committed

type: Story
summary: "[Bug] e2e/docker harness drift (already fixed in commit 6ce3158)"
description: |
  Fixed in this session: dockerfile rename, fdr-output tmpfs cap, e2e-results
  dir + gitignore. Ticket is just for tracking — already in dev branch.
story_points: 1
status_after_create: "Done"

Bug: csv_reporter --csv collision (already committed)

type: Bug
summary: "[Bug] csv_reporter --csv flag collides with pytest-csv autoload"
description: |
  See _docs/_process_leftovers/2026-05-17_csv_reporter_pytest_csv_conflict.md
  Fix already in commit eb6dc17.
linked_to: AZ-446
story_points: 2
status_after_create: "Done"

Replay obligation

Next /autodev should:

  1. Open Jira, create the Epic + Stories above (link Epic to AZ-595 and AZ-444).
  2. Update the Epic with the actual issue keys once created.
  3. Delete this leftover entry on success.