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>
9.1 KiB
Code Review Report
Batch: 94
Tasks: AZ-623 (Phase E narrowed: c282_ransac_filter + c5_imu_preintegrator + c5_se3_utils + c5_wgs_converter; original c5_isam2_graph_handle work split out to AZ-625)
Date: 2026-05-19
Verdict: PASS_WITH_WARNINGS
Phase 1: Context
Read in this review window:
_docs/02_tasks/todo/AZ-623_pre_constructed_phase_e_ransac_c5_helpers.md(narrowed scope, 4 helpers;c5_isam2_graph_handledeferred to AZ-625 with full scope-split note)_docs/02_tasks/todo/AZ-624_pre_constructed_phase_f_wire_main.md(dependency edge updated: AZ-624 now blocks on BOTH AZ-623 and AZ-625)_docs/02_tasks/todo/AZ-625_c5_isam2_graph_handle_ordering.md(NEW — captures the deferred handle-ordering work)_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md(umbrella; constraints "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")src/gps_denied_onboard/helpers/{ransac_filter,imu_preintegrator,se3_utils,wgs_converter}.py(helpers being wired)src/gps_denied_onboard/runtime_root/_replay_branch.py(existing_load_camera_calibrationpattern — template for the airborne bootstrap loader)src/gps_denied_onboard/components/c5_state/_isam2_handle.py(Protocol seam constraint that drove the AZ-625 split)src/gps_denied_onboard/runtime_root/state_factory.py(build_state_estimator return-tuple — confirms seam)src/gps_denied_onboard/runtime_root/__init__.py(compose_root pre_constructed merge — confirms construction-order issue)
The autodev orchestrator escalated the c5_isam2_graph_handle ordering question via the AZ-623 spec's own escalation gate; the user chose Option B (split scope; new PBI for handle wiring). This review covers the narrowed AZ-623 only.
Phase 2: Spec Compliance
| AC | Status | Test | Notes |
|---|---|---|---|
| AC-623.1 (4 keys added on top of AZ-619..AZ-622) | Covered | test_ac_623_1_adds_c282_ransac_and_c5_helpers + test_ac_623_1_keeps_existing_keys_intact |
Each new key is type-asserted; c5_se3_utils is the helpers.se3_utils module (matches existing C5 estimator's MagicMock fixture pattern via attribute access). |
AC-623.2 (c5_imu_preintegrator cached per camera_calibration_path; stateless 3 may be fresh) |
Covered | test_ac_623_2_imu_preintegrator_cached_across_calls + test_ac_623_2_imu_preintegrator_per_path_cache |
Cache short-circuit verified by counter; per-path isolation verified by two distinct paths producing distinct instances. |
| AC-623.3 (operator-actionable error on missing/bad calibration) | Covered | test_ac_623_3_empty_calibration_path_raises_named_error + _unreadable_ + _malformed_json_ |
All three error paths assert the message names c5_imu_preintegrator, the missing-input symptom, and the consuming component slug c5_state. Mirrors AZ-622's c3_lightglue_runtime error-message contract. |
| AC-623.4 (test file exists) | Covered | tests/unit/runtime_root/test_az623_pre_constructed_phase_e.py |
7 tests, all passing. |
Spec drift / scope split: The user-approved scope split (handle work → AZ-625) is documented in three places — AZ-623 spec § "Scope split note", AZ-625 spec § "Why split out of AZ-623", AZ-624 Dependencies update. The Jira addCommentToJiraIssue write on AZ-623 also captures the split. No silent drift.
Phase 3: Code Quality
3 findings — all Low; none blocking:
- F1 (Low / Maintainability):
_load_camera_calibration(airborne_bootstrap) duplicates_load_camera_calibration(_replay_branch.py). The bodies share the JSON shape and field defaults; they differ only in exception class (AirborneBootstrapErrorhere vsCompositionErrorin replay) and theairborne-cameravsreplay-cameradefaultcamera_id. The umbrella's "MUST be confined to runtime_root/airborne_bootstrap.py" constraint nominally permits the duplication, but a future hygiene PBI should consolidate the JSON-decode core into a shared helper that takes the exception class as a callable parameter. - F2 (Low / Maintainability): empty-path check duplicated in
_build_c5_imu_preintegratorAND_load_camera_calibration. Intentional defense-in-depth (the loader is a public-ish seam tests monkeypatch directly, so it must validate independently); the upper check enables a tighter cache lookup before the loader fires. Documented in both docstrings. No change recommended unless the seam is removed in a future refactor. - F3 (Low / Style):
c5_se3_utilsreturns a Python module (gps_denied_onboard.helpers.se3_utils) as a namespace handle. Unusual at first glance but matches the existingMagicMock()fixture pattern intests/unit/c5_state/test_az386_eskf_baseline.py; consumers store asself._se3_utils: Anyand dispatch via attribute access. The docstring spells this out and references the existing C5 test pattern. A future enhancement could introduce aSe3UtilsHandleProtocol if the inferred shape grows, but YAGNI applies here.
Phase 4: Security
No findings.
- No SQL, no command exec, no
eval/exec. - JSON parsing uses
json.loads(safe) on file content. - File paths flow from
config.runtime.camera_calibration_path(operator input via YAML, not user-provided per request);Path(path).read_text(encoding="utf-8")reads the file with explicit encoding — no path traversal, no encoding ambiguity. - No secrets in error messages: the path string is included for operator-actionability, but the file content is never echoed.
Phase 5: Performance
No findings.
_IMU_PREINTEGRATOR_CACHEis a single-key dict lookup perbuild_pre_constructedcall. The expensive path (JSON read + GTSAMPreintegrationCombinedParamsconstruction) fires at most once per process per calibration path.- The 3 stateless helpers (
RansacFilter(),WgsConverter(), these3_utilsmodule reference) are O(1) constructions. - Bootstrap is a startup path — no latency-budget concerns at this layer beyond AZ-618's NFR (60s on Jetson Orin Nano), which is dominated by C7 GPU model load (AZ-621), not the AZ-623 helpers.
Phase 6: Cross-Task Consistency
- Autouse stubs added to test_az619 / test_az620 / test_az621 / test_az622 with consistent pattern (named lambdas returning
MagicMock(name="...")orobject()sentinels). Each fixture explains why it's needed and what it stubs. No drift in stub style across the 4 prior phase test files. - Error-message contract for
AirborneBootstrapErrorfollows the AZ-622 pattern (names the missing key, the gating input, and the consuming component slug). c5_se3_utilsmodule-as-namespace pattern is documented in both the production code and the test suite.
Phase 7: Architecture Compliance
No findings.
- New imports in
airborne_bootstrap.py:json(stdlib),pathlib.Path(stdlib),numpy(stack-wide),gps_denied_onboard._types.calibration.CameraCalibration(cross-cutting types — bootstrap may import any_typesper AZ-507),gps_denied_onboard.helpers.{imu_preintegrator,ransac_filter,wgs_converter}(CC-HELPERS layer; bootstrap may import any helper). All within the bootstrap's allowed dependency surface per_docs/02_document/module-layout.md. - No new cyclic dependencies:
airborne_bootstrapimports from helpers + types + factories; helpers import from_types; no back-edge introduced. - No Public API bypass: every imported symbol is in the helper module's documented
__all__or is a stdlib-equivalent re-export. - The umbrella's "MUST NOT touch any per-component factory signature" constraint is honored: zero edits to
state_factory.py,pose_factory.py, or anyc5_state/c4_poseinternal. - The umbrella's "All changes confined to runtime_root/airborne_bootstrap.py, runtime_root/__init__.py, and the new test file" constraint is honored: production-side changes are only in
airborne_bootstrap.py(this batch did not touchruntime_root/__init__.py— AZ-624's job).
Findings Summary
| # | Severity | Category | File:Line | Title |
|---|---|---|---|---|
| F1 | Low | Maintainability | airborne_bootstrap.py (_load_camera_calibration) |
Duplicates _replay_branch._load_camera_calibration |
| F2 | Low | Maintainability | airborne_bootstrap.py (_build_c5_imu_preintegrator + _load_camera_calibration) |
Defense-in-depth duplicates the empty-path check |
| F3 | Low | Style | airborne_bootstrap.py (_build_c5_se3_utils) |
Returns a module as a namespace handle |
Verdict: PASS_WITH_WARNINGS — 0 Critical, 0 High, 0 Medium, 3 Low. Auto-fix gate not triggered.
Test Run
Targeted: tests/unit/runtime_root/test_az619..623 — 24 passed in 2.78s.
Regression: tests/unit/runtime_root/ tests/unit/c5_state/ — 247 passed in 1.41s.
Suggested Follow-Ups (informational)
- Hygiene PBI (~2pt): consolidate
_load_camera_calibrationbetween airborne_bootstrap and_replay_branchinto a sharedruntime_root/_camera_calibration_loader.pythat accepts an exception-class parameter. Mirrors the F2 of batch 93 (_is_build_flag_ontriple-duplication PBI). The two leftover hygiene PBIs (F2-batch93 + this F1-batch94) could land together.