Files
gps-denied-onboard/_docs/03_implementation/batch_94_cycle1_report.md
T
Oleksandr Bezdieniezhnykh 02208c577e [AZ-623] [AZ-625] Phase E: c282_ransac + c5 helpers; split handle work
Wire 4 stateless / cached helpers into airborne_bootstrap.build_pre_constructed:
c282_ransac_filter, c5_imu_preintegrator (cached on calibration path),
c5_se3_utils (helpers.se3_utils module as namespace handle), c5_wgs_converter.

The original AZ-623 5th deliverable (c5_isam2_graph_handle) hit an
unresolvable construction-order conflict between c4_pose (consumes the handle)
and c5_state (creates it inside build_state_estimator's tuple return) under
the umbrella's "MUST NOT touch any per-component factory signature" constraint.
Per AZ-623 spec's escalation gate, scope was split: AZ-625 captures the handle
ordering work; AZ-624 dependency edge updated to require both.

Tests: tests/unit/runtime_root/test_az623_pre_constructed_phase_e.py adds 7
tests covering AC-623.1..3 (4 new keys + correct types, IMU preintegrator
caching, operator-actionable error messages for empty / unreadable / malformed
calibration paths). Autouse stubs added to test_az619/620/621/622 so prior
phase tests remain isolated from new builders.

Quality gates: ruff format clean, ruff lint clean, 24/24 phase tests pass,
247/247 runtime_root + c5_state regression suite passes. Code review verdict
PASS_WITH_WARNINGS (3 Low findings; full report in
_docs/03_implementation/reviews/batch_94_review.md).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 09:20:28 +03:00

6.9 KiB

Batch Report

Batch: 94 Tasks: AZ-623 (Phase E narrowed: build_pre_constructed seeds c282_ransac_filter + c5_imu_preintegrator + c5_se3_utils + c5_wgs_converter; c5_isam2_graph_handle work split out to AZ-625) Date: 2026-05-19 Cycle: 1

Task Results

Task Status Files Modified Tests AC Coverage Issues
AZ-623_pre_constructed_phase_e_ransac_c5_helpers (narrowed) Done 7 files 24 passed 4/4 ACs covered 0 blocking

Original AZ-623 had a 5th deliverable (c5_isam2_graph_handle) that uncovered an unresolvable construction-order conflict between c4_pose (consumes the handle) and c5_state (creates the handle inside build_state_estimator's tuple return) under the umbrella's "MUST NOT touch any per-component factory signature" constraint. Per the AZ-623 spec's own escalation gate ("if the resolution requires a Protocol seam change, escalate"), the question was surfaced; user chose to split scope:

  • This batch lands the 4 stateless / cached helpers (narrowed AZ-623).
  • New PBI AZ-625 ("AZ-618 Phase E.5: c5_isam2_graph_handle ordering", 3pt, parent AZ-618) holds the handle work.
  • AZ-624 dependency edge updated to require both AZ-623 AND AZ-625.

Files Changed

Production

  • src/gps_denied_onboard/runtime_root/airborne_bootstrap.py — added imports (json, pathlib.Path, numpy, _types.calibration.CameraCalibration, helpers.imu_preintegrator.{ImuPreintegrator, make_imu_preintegrator}, helpers.ransac_filter.RansacFilter, helpers.wgs_converter.WgsConverter); added module-level _IMU_PREINTEGRATOR_CACHE dict + clear_imu_preintegrator_cache() helper; added _load_camera_calibration (mirrors _replay_branch._load_camera_calibration but raises AirborneBootstrapError); added 4 builders _build_c282_ransac_filter, _build_c5_imu_preintegrator (cached on calibration path), _build_c5_se3_utils (returns the helpers.se3_utils module as a namespace handle, matching existing C5 estimator's MagicMock fixture pattern), _build_c5_wgs_converter; extended build_pre_constructed to populate the 4 new keys after the existing AZ-619..AZ-622 keys.

Tests

  • tests/unit/runtime_root/test_az623_pre_constructed_phase_e.py (NEW, 7 tests):
    • test_ac_623_1_adds_c282_ransac_and_c5_helpers — AC-623.1 (4 keys + correct types).
    • test_ac_623_1_keeps_existing_keys_intact — additivity invariant (AZ-619..AZ-622 keys still present).
    • test_ac_623_2_imu_preintegrator_cached_across_calls — AC-623.2 (cache short-circuit via per-test counter).
    • test_ac_623_2_imu_preintegrator_per_path_cache — AC-623.2 (per-path cache isolation).
    • test_ac_623_3_empty_calibration_path_raises_named_error — AC-623.3 (operator-actionable error).
    • test_ac_623_3_unreadable_calibration_path_raises_named_error — AC-623.3 (file not found path).
    • test_ac_623_3_malformed_json_raises_named_error — AC-623.3 (JSON decode wrap).
  • tests/unit/runtime_root/test_az619_pre_constructed_phase_a.py — added autouse _stub_c5_builders.
  • tests/unit/runtime_root/test_az620_pre_constructed_phase_b.py — added autouse _stub_c5_builders.
  • tests/unit/runtime_root/test_az621_pre_constructed_phase_c.py — added autouse _stub_c5_builders.
  • tests/unit/runtime_root/test_az622_pre_constructed_phase_d.py — added autouse _stub_c5_builders.

Specs

  • _docs/02_tasks/todo/AZ-623_*.md → narrowed (handle work removed); ARCHIVED to _docs/02_tasks/done/.
  • _docs/02_tasks/todo/AZ-624_*.md — Dependencies updated (AZ-625 added).
  • _docs/02_tasks/todo/AZ-625_c5_isam2_graph_handle_ordering.md (NEW) — 3pt, parent AZ-618, holds the handle ordering work.

AC Test Coverage: 4 of 4 covered

AC Test Status
AC-623.1 test_ac_623_1_adds_c282_ransac_and_c5_helpers + test_ac_623_1_keeps_existing_keys_intact Covered
AC-623.2 test_ac_623_2_imu_preintegrator_cached_across_calls + test_ac_623_2_imu_preintegrator_per_path_cache Covered
AC-623.3 test_ac_623_3_empty_calibration_path_raises_named_error (+ 2 variants for unreadable/malformed) Covered
AC-623.4 File tests/unit/runtime_root/test_az623_pre_constructed_phase_e.py exists Covered

Code Review Verdict: PASS_WITH_WARNINGS

Full report: _docs/03_implementation/reviews/batch_94_review.md. Three Low findings:

  1. F1 (Low / Maintainability)_load_camera_calibration duplicates _replay_branch._load_camera_calibration (different exception class). Defer to a hygiene PBI (~2pt) bundled with batch 93's F2 leftover.
  2. F2 (Low / Maintainability) — empty-path check duplicated across _build_c5_imu_preintegrator and _load_camera_calibration (defense-in-depth). No change recommended.
  3. F3 (Low / Style)c5_se3_utils returns a Python module as a namespace handle. Documented; matches existing C5 test fixture pattern. YAGNI — defer Protocol introduction.

No Critical / High / Medium findings. Auto-fix not invoked.

Auto-Fix Attempts: 0

Stuck Agents: None

Test Run Summary

  • Targeted test set (AZ-619..AZ-623): 24 passed in 1.07s.
  • Regression check (tests/unit/runtime_root/ + tests/unit/c5_state/): 247 passed in 1.78s.

Scope-Split Decision Trail

The split was driven by an irreconcilable construction-order issue between two umbrella constraints:

  • Constraint A (umbrella AZ-618): "MUST NOT touch any per-component factory signature" + "All changes confined to runtime_root/airborne_bootstrap.py, runtime_root/__init__.py, and the new test file."
  • Constraint B (existing seam): build_state_estimator returns (StateEstimator, ISam2GraphHandle) as a tuple — the handle is a structural side-product of the estimator, not separately constructable.
  • Constraint C (existing seam): C4's build_pose_estimator consumes c5_isam2_graph_handle from pre_constructed, so compose_root topologically requires it to exist before C4 runs, which is before C5 runs.

Possible resolutions all touched at least one of A/B/C; the user-approved Option B preserves all three constraints by:

  • Keeping the C4 ↔ C5 seam intact (no Protocol changes).
  • Promoting the (estimator, handle) build into airborne_bootstrap, where AZ-618 explicitly permits orchestration.
  • Documenting the strategy in AZ-625's spec § "Decision" with full rationale.

Tier-2 / Deferred Work

  • AZ-625 (3pt) — handle ordering work, blocks AZ-624.
  • Hygiene PBI to consolidate _load_camera_calibration between airborne_bootstrap and _replay_branch (F1) and _is_build_flag_on triple-duplication (batch 93 F2). Bundle as ~2pt cleanup PBI post-AZ-618.

Next Batch

  • Batch 95: AZ-625 (Phase E.5: c5_isam2_graph_handle ordering) — 3pt.
  • Then Batch 96: AZ-624 (Phase F: wire main() + AC-1..AC-5 verification incl. Jetson tier-2) — 2pt.
  • Cumulative review window: next due at batch 96 (K=3 from last cumulative at 88-92).