From 8cee5325169f51acffd82938ec0b9bb456f6f00d Mon Sep 17 00:00:00 2001 From: Oleksandr Bezdieniezhnykh Date: Tue, 19 May 2026 06:20:06 +0300 Subject: [PATCH] [AZ-618] [AZ-619] [AZ-620] [AZ-621] [AZ-622] [AZ-623] [AZ-624] Split AZ-618 into 6 subtasks per spec sizing-note The AZ-618 spec author flagged "likely a true 8" with a recommended 6-subtask split; combined with the user-rule cap on PBI complexity (create at 2-3pt, max 5pt) the right move was to split before any implementation began. Subtasks created in Jira as children of AZ-618: AZ-619 (Phase A) c13_fdr + clock 2pt AZ-620 (Phase B) c6_descriptor_index + c6_tile_store 3pt AZ-621 (Phase C) c7_inference engine 3pt AZ-622 (Phase D) c3_lightglue_runtime + c3_feature_extractor 3pt AZ-623 (Phase E) c282_ransac_filter + c5 helpers 3pt AZ-624 (Phase F) wire main() + AC-1..AC-5 + Jetson 2pt Aggregate: 16pt actionable work (vs. AZ-618's original 5pt filing, which the author had already qualified as understated). AZ-618 stays In Progress in Jira as the umbrella tracker; its task spec file is now an umbrella reference pointing to the 6 phase-specific spec files. Deps table updated: AZ-618 row reduced to 0pt with subtask deps; six new rows added; header counts refreshed (156 -> 162 tasks, 522 -> 533 points). Autodev state set to phase=1 (parse) for the next batch = AZ-619 (Phase A) only. Co-authored-by: Cursor --- _docs/02_tasks/_dependencies_table.md | 14 +++- ...-618_airborne_bootstrap_pre_constructed.md | 19 ++++- ...9_pre_constructed_phase_a_c13_fdr_clock.md | 80 ++++++++++++++++++ ...-620_pre_constructed_phase_b_c6_storage.md | 59 ++++++++++++++ ...21_pre_constructed_phase_c_c7_inference.md | 51 ++++++++++++ ...622_pre_constructed_phase_d_c3_runtimes.md | 54 +++++++++++++ ...e_constructed_phase_e_ransac_c5_helpers.md | 58 +++++++++++++ ...Z-624_pre_constructed_phase_f_wire_main.md | 81 +++++++++++++++++++ _docs/_autodev_state.md | 2 +- 9 files changed, 410 insertions(+), 8 deletions(-) create mode 100644 _docs/02_tasks/todo/AZ-619_pre_constructed_phase_a_c13_fdr_clock.md create mode 100644 _docs/02_tasks/todo/AZ-620_pre_constructed_phase_b_c6_storage.md create mode 100644 _docs/02_tasks/todo/AZ-621_pre_constructed_phase_c_c7_inference.md create mode 100644 _docs/02_tasks/todo/AZ-622_pre_constructed_phase_d_c3_runtimes.md create mode 100644 _docs/02_tasks/todo/AZ-623_pre_constructed_phase_e_ransac_c5_helpers.md create mode 100644 _docs/02_tasks/todo/AZ-624_pre_constructed_phase_f_wire_main.md diff --git a/_docs/02_tasks/_dependencies_table.md b/_docs/02_tasks/_dependencies_table.md index 313729f..d4b1e3b 100644 --- a/_docs/02_tasks/_dependencies_table.md +++ b/_docs/02_tasks/_dependencies_table.md @@ -1,8 +1,8 @@ # Dependencies Table -**Date**: 2026-05-19 (refreshed at start of Step-7 rewind for AZ-618 — Step-11 Jetson tier-2 e2e gate identified missing internal product implementation: `runtime_root.main()` does not build the airborne `pre_constructed` infrastructure dict before `compose_root()`; AZ-618 = 5pt cross-cutting follow-up to AZ-591, lives under E-AZ-602; all 12 dep tasks are in `done/`. Earlier 2026-05-16 (cycle-1 completeness-gate post-mortem): AZ-589 + AZ-590 closed Won't Fix — were wrong abstraction (OKVIS v1 `ThreadedKFVio` API doesn't exist in OKVIS2 upstream; VINS-Mono `cpp/vins_mono/upstream/` submodule never existed; the actual production gap is the empty central `_STRATEGY_REGISTRY` affecting EVERY component with a strategy-selecting config field, not just c1_vio); replaced by AZ-591 (cross-cutting compose_root per-binary bootstrap, todo/, 5pt) + AZ-592 (AZ-332 Tier-2 validation bundle, backlog/, 5pt placeholder) + AZ-593 (AZ-333 Tier-2 validation bundle, backlog/, 5pt placeholder); AZ-332 + AZ-333 re-classified in gate report from FAIL to BLOCKED-on-Tier-2 per the original tasks' Implementation Notes deferral handles; earlier same-day after end of cycle-1 gate: AZ-589 + AZ-590 created (now closed); earlier same-day after end of Batch 64: AZ-558 implementation closed — `MavlinkTransport` seam now routes every C8 outbound MAVLink byte; AZ-401 AC-9 + AZ-404 AC-4b unskipped together; encoder helpers extracted to `_outbound_mavlink_payloads.py`; live-mode `compose_root` injection deferred to whichever future batch registers AP/iNav strategies in an airborne binary; earlier 2026-05-14: refreshed at start of Batch 63: AZ-559 closed Won't Fix — gap was illusory; `TileSource.ONBOARD_INGEST` + `TileMetadata.quality_metadata` + `write_tile`'s `FreshnessRejectionError` already cover the AZ-389 mid-flight ingest semantic without any new API; AZ-389 dep restored to AZ-303; earlier same-day after Batch 61: AZ-558 follow-up added — routes C8 outbound encoder bytes through `MavlinkTransport` seam; closes AZ-401 AC-9 deferred during batch 61 due to encoder-side routing not being in the AZ-401 task envelope; earlier same-day after cumulative review batches 52-54: AZ-528 hygiene PBI added for c1_vio strategy facade orchestration-spine 3-way duplication (Medium); earlier same-day after Batch 53: AZ-333 VINS-Mono landed — first c1_vio strategy after the AZ-332 OKVIS2 production-default; consolidation hygiene for the strategy-facade duplication deferred to a post-AZ-334 PBI; earlier same-day after Batch 51: AZ-527 hygiene PBI added from cumulative review batches 49-51 F1; 2026-05-13: AZ-526 hygiene PBI added from cumulative review batches 46-48 F1+F3; same-day refresh after Batch 44 SRP refactor: AZ-317 superseded; AZ-329 + AZ-330 specs rewritten; AZ-523 + AZ-524 audit-trail tickets added; E-C12 epic renamed `Operator Pre-flight Tooling` → `Operator Pre-flight Orchestrator`; earlier same-day refresh: AZ-507 + AZ-508 hygiene PBIs from cumulative review batches 31-33; 2026-05-11: AZ-489 + AZ-490 ADR-010 operator-origin path) -**Total Tasks**: 156 (115 product + 41 blackbox-test) — AZ-317 retained in the table marked SUPERSEDED for audit; AZ-523 (C11 gate removal) + AZ-524 (C12 rename) added as 2 closed audit-trail tasks; AZ-526 = 2pt clock-helper hygiene; AZ-527 = 2pt c2 engine-dim helper hygiene; AZ-528 = 3pt c1_vio facade-spine hygiene; AZ-558 = 3pt MavlinkTransport routing follow-up; AZ-559 closed Won't Fix; AZ-589 + AZ-590 closed Won't Fix (kept in table as 0pt audit-trail rows); AZ-591 = 5pt cross-cutting compose_root bootstrap (todo/); AZ-592 = 5pt OKVIS2 Tier-2 placeholder (backlog/); AZ-593 = 5pt VINS-Mono Tier-2 placeholder (backlog/); AZ-618 = 5pt airborne `pre_constructed` assembly (todo/, AZ-591 follow-up) -**Total Complexity Points**: 522 (389 product + 133 blackbox-test) — AZ-523 = 3pt, AZ-524 = 2pt, AZ-526 = 2pt, AZ-527 = 2pt, AZ-528 = 3pt, AZ-558 = 3pt, AZ-589 + AZ-590 retained at 5pt each but closed Won't Fix (treated as 0 effective pts going forward), AZ-591 = 5pt, AZ-592 = 5pt placeholder, AZ-593 = 5pt placeholder, AZ-618 = 5pt +**Date**: 2026-05-19 (refreshed mid-day after AZ-618 split: per the spec author's own Sizing-note recommendation + user-rule cap on PBI complexity, AZ-618 was split into 6 subtasks AZ-619..AZ-624 in Jira (subtasks of AZ-618; epic AZ-602 stays grandparent). AZ-618 retained at 0pt as the umbrella tracker; aggregate actionable work is 16pt across the subtasks (vs. AZ-618's original 5pt filing — author's "likely a true 8" caveat was understated due to c5_isam2_graph_handle ordering + GPU builder unknowns). Earlier same-day refresh at start of Step-7 rewind for AZ-618 — Step-11 Jetson tier-2 e2e gate identified missing internal product implementation: `runtime_root.main()` does not build the airborne `pre_constructed` infrastructure dict before `compose_root()`; AZ-618 = 5pt cross-cutting follow-up to AZ-591, lives under E-AZ-602; all 12 dep tasks are in `done/`. Earlier 2026-05-16 (cycle-1 completeness-gate post-mortem): AZ-589 + AZ-590 closed Won't Fix — were wrong abstraction (OKVIS v1 `ThreadedKFVio` API doesn't exist in OKVIS2 upstream; VINS-Mono `cpp/vins_mono/upstream/` submodule never existed; the actual production gap is the empty central `_STRATEGY_REGISTRY` affecting EVERY component with a strategy-selecting config field, not just c1_vio); replaced by AZ-591 (cross-cutting compose_root per-binary bootstrap, todo/, 5pt) + AZ-592 (AZ-332 Tier-2 validation bundle, backlog/, 5pt placeholder) + AZ-593 (AZ-333 Tier-2 validation bundle, backlog/, 5pt placeholder); AZ-332 + AZ-333 re-classified in gate report from FAIL to BLOCKED-on-Tier-2 per the original tasks' Implementation Notes deferral handles; earlier same-day after end of cycle-1 gate: AZ-589 + AZ-590 created (now closed); earlier same-day after end of Batch 64: AZ-558 implementation closed — `MavlinkTransport` seam now routes every C8 outbound MAVLink byte; AZ-401 AC-9 + AZ-404 AC-4b unskipped together; encoder helpers extracted to `_outbound_mavlink_payloads.py`; live-mode `compose_root` injection deferred to whichever future batch registers AP/iNav strategies in an airborne binary; earlier 2026-05-14: refreshed at start of Batch 63: AZ-559 closed Won't Fix — gap was illusory; `TileSource.ONBOARD_INGEST` + `TileMetadata.quality_metadata` + `write_tile`'s `FreshnessRejectionError` already cover the AZ-389 mid-flight ingest semantic without any new API; AZ-389 dep restored to AZ-303; earlier same-day after Batch 61: AZ-558 follow-up added — routes C8 outbound encoder bytes through `MavlinkTransport` seam; closes AZ-401 AC-9 deferred during batch 61 due to encoder-side routing not being in the AZ-401 task envelope; earlier same-day after cumulative review batches 52-54: AZ-528 hygiene PBI added for c1_vio strategy facade orchestration-spine 3-way duplication (Medium); earlier same-day after Batch 53: AZ-333 VINS-Mono landed — first c1_vio strategy after the AZ-332 OKVIS2 production-default; consolidation hygiene for the strategy-facade duplication deferred to a post-AZ-334 PBI; earlier same-day after Batch 51: AZ-527 hygiene PBI added from cumulative review batches 49-51 F1; 2026-05-13: AZ-526 hygiene PBI added from cumulative review batches 46-48 F1+F3; same-day refresh after Batch 44 SRP refactor: AZ-317 superseded; AZ-329 + AZ-330 specs rewritten; AZ-523 + AZ-524 audit-trail tickets added; E-C12 epic renamed `Operator Pre-flight Tooling` → `Operator Pre-flight Orchestrator`; earlier same-day refresh: AZ-507 + AZ-508 hygiene PBIs from cumulative review batches 31-33; 2026-05-11: AZ-489 + AZ-490 ADR-010 operator-origin path) +**Total Tasks**: 162 (121 product + 41 blackbox-test) — AZ-317 retained in the table marked SUPERSEDED for audit; AZ-523 (C11 gate removal) + AZ-524 (C12 rename) added as 2 closed audit-trail tasks; AZ-526 = 2pt clock-helper hygiene; AZ-527 = 2pt c2 engine-dim helper hygiene; AZ-528 = 3pt c1_vio facade-spine hygiene; AZ-558 = 3pt MavlinkTransport routing follow-up; AZ-559 closed Won't Fix; AZ-589 + AZ-590 closed Won't Fix (kept in table as 0pt audit-trail rows); AZ-591 = 5pt cross-cutting compose_root bootstrap (todo/); AZ-592 = 5pt OKVIS2 Tier-2 placeholder (backlog/); AZ-593 = 5pt VINS-Mono Tier-2 placeholder (backlog/); AZ-618 = 0pt umbrella (split into AZ-619..AZ-624 on 2026-05-19); AZ-619..AZ-624 = 6 subtasks of AZ-618 covering Phase A..F of the airborne `pre_constructed` assembly, summing to 16pt actionable work +**Total Complexity Points**: 533 (400 product + 133 blackbox-test) — AZ-523 = 3pt, AZ-524 = 2pt, AZ-526 = 2pt, AZ-527 = 2pt, AZ-528 = 3pt, AZ-558 = 3pt, AZ-589 + AZ-590 retained at 5pt each but closed Won't Fix (treated as 0 effective pts going forward), AZ-591 = 5pt, AZ-592 = 5pt placeholder, AZ-593 = 5pt placeholder, AZ-618 = 0pt umbrella post-split, AZ-619 = 2pt, AZ-620 = 3pt, AZ-621 = 3pt, AZ-622 = 3pt, AZ-623 = 3pt, AZ-624 = 2pt Dependencies columns list only the tracker-ID portion (descriptive tail text in each task spec is omitted here for table-readability). The @@ -169,7 +169,13 @@ are all declared and documented below under **Cycle Check**. | AZ-591 | compose_root per-binary bootstrap — populate `_STRATEGY_REGISTRY` for airborne binary | 5 | AZ-270, AZ-331, AZ-339, AZ-345, AZ-352, AZ-355, AZ-368, AZ-380 | AZ-246 | | AZ-592 | AZ-332 Tier-2 validation — OKVIS2 ThreadedSlam wiring + CI build env + Jetson (backlog) | 5 | AZ-332, AZ-276, AZ-277, AZ-591 | AZ-254 | | AZ-593 | AZ-333 Tier-2 validation — de-ROSified VINS-Mono upstream + binding + CI + Jetson (backlog) | 5 | AZ-333, AZ-276, AZ-277, AZ-591, AZ-592 | AZ-254 | -| AZ-618 | Airborne bootstrap pre_constructed assembly — runtime_root.main() builds 12-key infra dict | 5 | AZ-591, AZ-270, AZ-273, AZ-306, AZ-303, AZ-320, AZ-278, AZ-282, AZ-276, AZ-277, AZ-279, AZ-381 | AZ-602 | +| AZ-618 | Airborne bootstrap pre_constructed (UMBRELLA — split into AZ-619..AZ-624) | 0 | AZ-619, AZ-620, AZ-621, AZ-622, AZ-623, AZ-624 | AZ-602 | +| AZ-619 | AZ-618 Phase A: build_pre_constructed seeds c13_fdr + clock | 2 | AZ-591, AZ-270, AZ-273, AZ-398 | AZ-602 | +| AZ-620 | AZ-618 Phase B: build_pre_constructed seeds c6_descriptor_index + c6_tile_store | 3 | AZ-619, AZ-303, AZ-306 | AZ-602 | +| AZ-621 | AZ-618 Phase C: build_pre_constructed seeds c7_inference engine | 3 | AZ-619, AZ-620, AZ-297, AZ-320 | AZ-602 | +| AZ-622 | AZ-618 Phase D: build_pre_constructed seeds c3_lightglue_runtime + c3_feature_extractor | 3 | AZ-619, AZ-620, AZ-621, AZ-278 | AZ-602 | +| AZ-623 | AZ-618 Phase E: build_pre_constructed seeds c282_ransac_filter + c5 helpers | 3 | AZ-619, AZ-282, AZ-276, AZ-277, AZ-279, AZ-381 | AZ-602 | +| AZ-624 | AZ-618 Phase F: wire build_pre_constructed into main() + AC-1..AC-5 (incl. Jetson tier-2) | 2 | AZ-619, AZ-620, AZ-621, AZ-622, AZ-623 | AZ-602 | ## Notes diff --git a/_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md b/_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md index 3f8d325..c2185a3 100644 --- a/_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md +++ b/_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md @@ -1,9 +1,22 @@ -# AZ-618 — Airborne main() builds pre_constructed infrastructure for compose_root +# AZ-618 — Airborne main() builds pre_constructed infrastructure for compose_root (UMBRELLA — split into AZ-619..AZ-624) + +> **STATUS — split**: 2026-05-19. Per the spec author's own Sizing-note recommendation and per the user-rule cap (≤5pt per PBI), AZ-618 was split into 6 subtasks AZ-619..AZ-624 in Jira (subtasks of AZ-618; epic AZ-602 stays grandparent). This file remains as the **umbrella reference** — it carries the shared narrative, the full 12-key map, the architectural rationale, and the canonical AC-1..AC-5 list. Subtask spec files in `_docs/02_tasks/todo/AZ-619..AZ-624_*.md` carry phase-specific scope and ACs. AZ-618 itself is no longer an actionable task; its work is entirely captured in the subtasks. +> +> **Actionable subtasks** (phase order, must land in dependency order): +> +> - **AZ-619** (Phase A) — c13_fdr + clock — 2pt — `_docs/02_tasks/todo/AZ-619_pre_constructed_phase_a_c13_fdr_clock.md` +> - **AZ-620** (Phase B) — c6_descriptor_index + c6_tile_store — 3pt — `_docs/02_tasks/todo/AZ-620_pre_constructed_phase_b_c6_storage.md` +> - **AZ-621** (Phase C) — c7_inference engine — 3pt — `_docs/02_tasks/todo/AZ-621_pre_constructed_phase_c_c7_inference.md` +> - **AZ-622** (Phase D) — c3_lightglue_runtime + c3_feature_extractor — 3pt — `_docs/02_tasks/todo/AZ-622_pre_constructed_phase_d_c3_runtimes.md` +> - **AZ-623** (Phase E) — c282_ransac_filter + c5 helpers + c5_isam2_graph_handle — 3pt — `_docs/02_tasks/todo/AZ-623_pre_constructed_phase_e_ransac_c5_helpers.md` +> - **AZ-624** (Phase F) — wire main() + AC-1..AC-5 verification (incl. Jetson tier-2) — 2pt — `_docs/02_tasks/todo/AZ-624_pre_constructed_phase_f_wire_main.md` +> +> Aggregate work: 16pt across 6 subtasks (vs. AZ-618's original 5pt filing). The author's "likely a true 8" caveat in the Sizing note below was understated — c5_isam2_graph_handle ordering + GPU builder unknowns drove the honest total higher. **Task**: AZ-618_airborne_bootstrap_pre_constructed -**Name**: Airborne bootstrap pre_constructed assembly (cross-cutting Tier-1) +**Name**: Airborne bootstrap pre_constructed assembly (cross-cutting Tier-1) — UMBRELLA **Description**: Land an `airborne_bootstrap.build_pre_constructed(config) -> dict[str, Any]` function (or equivalent in-`main()` wiring) that constructs every infrastructure object the registered airborne-strategy wrappers require, and call `compose_root(config, pre_constructed=...)` with the result from `runtime_root.main()`. Without this, `compose_root()` raises `AirborneBootstrapError` on the first wrapper lookup (`c1_vio` reaches for `pre_constructed['c13_fdr']` and finds nothing) and the binary cannot reach takeoff. -**Complexity**: 5 points (cross-cutting; touches up to 12 infrastructure slots, but each slot reuses an existing per-component builder; GPU init for `c7_inference` + `c3_lightglue_runtime` + `c3_feature_extractor` is the only genuinely new wiring) +**Complexity**: 0 points (umbrella — actionable work is in AZ-619..AZ-624; original filing was 5 points before split) **Dependencies**: AZ-591 (registry registration is the prerequisite — without it the wrappers do not run at all). Helper / runtime classes consumed by the wrappers are all already in `done/` per their own task IDs (c13_fdr → AZ-273+, c6_descriptor_index → AZ-306, c6_tile_store → AZ-303+, c7_inference → AZ-320+, c3_lightglue_runtime + c3_feature_extractor → AZ-278+, c2_82_ransac_filter → AZ-358, c5_imu_preintegrator → AZ-276, c5_se3_utils → AZ-277, c5_wgs_converter → AZ-284, c5_isam2_graph_handle → AZ-381). **Component**: runtime_root (cross-cutting) **Tracker**: AZ-618 diff --git a/_docs/02_tasks/todo/AZ-619_pre_constructed_phase_a_c13_fdr_clock.md b/_docs/02_tasks/todo/AZ-619_pre_constructed_phase_a_c13_fdr_clock.md new file mode 100644 index 0000000..04ea6ea --- /dev/null +++ b/_docs/02_tasks/todo/AZ-619_pre_constructed_phase_a_c13_fdr_clock.md @@ -0,0 +1,80 @@ +# AZ-619 — Phase A: build_pre_constructed seeds c13_fdr + clock + +**Task**: AZ-619_pre_constructed_phase_a_c13_fdr_clock +**Name**: AZ-618 Phase A: build_pre_constructed seeds c13_fdr + clock +**Description**: Foundational subtask of AZ-618. Introduces `airborne_bootstrap.build_pre_constructed(config) -> dict[str, Any]` and seeds the two simplest entries: `c13_fdr` (per-binary single FdrClient via `make_fdr_client("airborne_main", config)`) and `clock` (`WallClock()`). The function is additive — phases B..F (AZ-620..AZ-624) extend it without breaking this contract. +**Complexity**: 2 points +**Dependencies**: AZ-591 (registry seam), AZ-273 (FdrClient), AZ-398 (WallClock). All in `done/`. +**Component**: runtime_root (cross-cutting) +**Tracker**: AZ-619 +**Epic**: AZ-602 (parent: AZ-618 umbrella) + +## Outcome + +- `src/gps_denied_onboard/runtime_root/airborne_bootstrap.py` exports a public `build_pre_constructed(config: Config) -> dict[str, Any]`. +- The returned dict contains at least `c13_fdr` (FdrClient) and `clock` (WallClock). +- Re-invocation in the same process returns dict where `c13_fdr` is the same FdrClient (per `make_fdr_client` cache); `clock` may be a fresh WallClock each call. +- Unit tests under `tests/unit/runtime_root/test_az619_pre_constructed_phase_a.py` cover both ACs. + +## Scope + +### Included + +- New module symbol: `airborne_bootstrap.build_pre_constructed(config)`. +- Internal builders: `_build_c13_fdr(config) -> FdrClient` and `_build_clock(config) -> WallClock`. Replay-mode clock override is NOT done here — `compose_root` already merges `replay_components` over `pre_constructed` so `WallClock` gets replaced by `TlogDerivedClock` in replay mode. The contract is "live default; replay overrides". +- `__all__` updated to export `build_pre_constructed`. +- New unit test file: `tests/unit/runtime_root/test_az619_pre_constructed_phase_a.py` (AC-619.1, AC-619.2). + +### Excluded + +- All other 10 keys in `AIRBORNE_REQUIRED_PRE_CONSTRUCTED_KEYS` — AZ-620..AZ-623. +- `runtime_root.main()` integration — AZ-624. +- Full AC-1..AC-5 of the AZ-618 umbrella — AZ-624. +- Jetson tier-2 verification — AZ-624 (per `_docs/02_document/tests/tier2-jetson-testing.md` Mandatory-Tier-2 Scope, this subtask is in scope but the actual Jetson run is consolidated at AZ-624 to avoid 6 separate Jetson runs for one feature). + +## Acceptance Criteria + +**AC-619.1: `build_pre_constructed(default_config)` returns required minimum keys** +Given a default airborne `Config` +When `build_pre_constructed(config)` is called +Then the returned dict has key `c13_fdr` mapping to an `FdrClient` instance +And key `clock` mapping to a `WallClock` instance +And no other keys are required at this phase (additional keys are allowed for forward-compat). + +**AC-619.2: c13_fdr is cached across calls** +Given `build_pre_constructed(config)` has been called once and returned `dict_a` +When `build_pre_constructed(config)` is called a second time, returning `dict_b` +Then `dict_a["c13_fdr"] is dict_b["c13_fdr"]` (same instance via `make_fdr_client` cache). + +**AC-619.3: unit tests exist** +Given the changes above are landed +When `pytest tests/unit/runtime_root/test_az619_pre_constructed_phase_a.py` is invoked +Then both AC-619.1 and AC-619.2 are exercised by named tests. + +## Non-Functional Requirements + +- The construction is single-threaded and synchronous; no GPU, no I/O beyond what `make_fdr_client` already does (FdrClient logger init). +- Builder must complete in <100 ms on Mac dev host for the default config. + +## Dependencies + +- AZ-591 (registry seam): DONE — `airborne_bootstrap.py` already exists with the required keys map. +- AZ-273 (FdrClient): DONE — `make_fdr_client` is the public entry-point. +- AZ-398 (WallClock): DONE — stateless, no-arg constructor. + +## Constraints + +- MUST NOT modify any per-component factory signature. +- MUST NOT introduce new `BUILD_*` env flags. +- MUST be additive: the function shape `build_pre_constructed(config) -> dict[str, Any]` survives unchanged through AZ-620..AZ-624. + +## Implementation Notes + +- The producer ID for `make_fdr_client` is "airborne_main" (per the bootstrap convention; consumer-side components call `make_fdr_client(, config)` separately and get their own per-component FdrClient via the per-producer cache). The single FdrClient passed via `pre_constructed["c13_fdr"]` is the one the wrapper factories pass into `build_<...>_strategy(config, fdr_client=...)`. Whether wrappers should use the shared "airborne_main" client or fetch their own per-component client is a design question that does NOT need to be resolved in this subtask — the wrappers already accept whichever client we pass. Defer the design clarification to the AZ-624 integration AC if needed. + +## Evidence + +- Umbrella spec: `_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md` +- Existing bootstrap module: `src/gps_denied_onboard/runtime_root/airborne_bootstrap.py:92` (AIRBORNE_REQUIRED_PRE_CONSTRUCTED_KEYS) +- FdrClient factory: `src/gps_denied_onboard/fdr_client/client.py:192` (`make_fdr_client`) +- WallClock: `src/gps_denied_onboard/clock/wall_clock.py` diff --git a/_docs/02_tasks/todo/AZ-620_pre_constructed_phase_b_c6_storage.md b/_docs/02_tasks/todo/AZ-620_pre_constructed_phase_b_c6_storage.md new file mode 100644 index 0000000..29d28cf --- /dev/null +++ b/_docs/02_tasks/todo/AZ-620_pre_constructed_phase_b_c6_storage.md @@ -0,0 +1,59 @@ +# AZ-620 — Phase B: build_pre_constructed seeds c6_descriptor_index + c6_tile_store + +**Task**: AZ-620_pre_constructed_phase_b_c6_storage +**Name**: AZ-618 Phase B: build_pre_constructed seeds c6_descriptor_index + c6_tile_store +**Description**: Second subtask of AZ-618. Extends `airborne_bootstrap.build_pre_constructed(config)` to populate the C6 storage entries used by C2 / C2.5 / C3. +**Complexity**: 3 points +**Dependencies**: AZ-619 (build_pre_constructed skeleton), AZ-303 (TileStore), AZ-306 (faiss DescriptorIndex). All in `done/` once AZ-619 lands. +**Component**: runtime_root (cross-cutting) +**Tracker**: AZ-620 +**Epic**: AZ-602 (parent: AZ-618 umbrella) + +## Outcome + +- `build_pre_constructed(config)` adds keys `c6_descriptor_index` (DescriptorIndex instance) and `c6_tile_store` (TileStore instance) on top of the AZ-619 contract. +- A misconfigured `BUILD_FAISS_INDEX=OFF` against a config that selects a C2 strategy needing the index raises `AirborneBootstrapError` naming both the missing flag and the consuming component. +- New unit tests under `tests/unit/runtime_root/test_az620_pre_constructed_phase_b.py`. + +## Scope + +### Included + +- Internal builders `_build_c6_descriptor_index(config)` and `_build_c6_tile_store(config)` calling the existing C6 Public API factories (likely `runtime_root.storage_factory.build_descriptor_index` and the matching tile store factory — confirm exact entry-point names during implementation). +- BUILD-flag mismatch surfaces a clear `AirborneBootstrapError` with consuming-component slug + missing flag. +- New unit tests covering AC-620.1 + AC-620.2. + +### Excluded + +- All keys outside this phase (AZ-619 / AZ-621 / AZ-622 / AZ-623). +- `runtime_root.main()` integration (AZ-624). + +## Acceptance Criteria + +**AC-620.1: c6 keys populated** +Given a default airborne `Config` with `BUILD_FAISS_INDEX=ON` +When `build_pre_constructed(config)` is called +Then the dict additionally contains `c6_descriptor_index` (DescriptorIndex instance) and `c6_tile_store` (TileStore instance). + +**AC-620.2: BUILD_* flag mismatch raises clear error** +Given a config selecting `c2_vpr.strategy="net_vlad"` (requires descriptor_index) +And `BUILD_FAISS_INDEX=OFF` +When `build_pre_constructed(config)` is called +Then it raises `AirborneBootstrapError` whose message names both `c6_descriptor_index` (the missing key) and `BUILD_FAISS_INDEX` (the gating flag) and `c2_vpr` (the consuming component slug). + +**AC-620.3: unit tests exist** — `pytest tests/unit/runtime_root/test_az620_pre_constructed_phase_b.py` exercises AC-620.1 + AC-620.2. + +## Constraints + +- MUST NOT modify per-component factory signatures. +- MUST NOT introduce new `BUILD_*` env flags. +- MUST be additive on top of AZ-619. + +## Implementation Notes + +- The exact factory entry-points for descriptor index and tile store live under `src/gps_denied_onboard/runtime_root/storage_factory.py` (or equivalent — confirm during implementation). `module-layout.md` line 159 references `runtime_root.storage_factory.build_descriptor_index`. + +## Evidence + +- Umbrella spec: `_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md` +- AZ-303 / AZ-306 task specs in `_docs/02_tasks/done/` for C6 runtime classes diff --git a/_docs/02_tasks/todo/AZ-621_pre_constructed_phase_c_c7_inference.md b/_docs/02_tasks/todo/AZ-621_pre_constructed_phase_c_c7_inference.md new file mode 100644 index 0000000..142b4b0 --- /dev/null +++ b/_docs/02_tasks/todo/AZ-621_pre_constructed_phase_c_c7_inference.md @@ -0,0 +1,51 @@ +# AZ-621 — Phase C: build_pre_constructed seeds c7_inference engine + +**Task**: AZ-621_pre_constructed_phase_c_c7_inference +**Name**: AZ-618 Phase C: build_pre_constructed seeds c7_inference engine +**Description**: Third subtask of AZ-618. Extends `airborne_bootstrap.build_pre_constructed(config)` to populate the C7 inference runtime (PyTorch FP16 vs. TensorRT, gated by `BUILD_*` env flags). +**Complexity**: 3 points +**Dependencies**: AZ-619, AZ-620, AZ-320 (engine compiler), AZ-297 (InferenceRuntime Protocol). All in `done/` once AZ-619+AZ-620 land. +**Component**: runtime_root (cross-cutting) +**Tracker**: AZ-621 +**Epic**: AZ-602 (parent: AZ-618 umbrella) + +## Outcome + +- `build_pre_constructed(config)` adds key `c7_inference` (InferenceRuntime instance) on top of AZ-619 + AZ-620. +- A misconfigured `BUILD_TENSORRT_RUNTIME=OFF` AND `BUILD_PYTORCH_FP16_RUNTIME=OFF` against a config that selects a strategy needing c7 raises `AirborneBootstrapError`. +- New unit tests under `tests/unit/runtime_root/test_az621_pre_constructed_phase_c.py` with the engine-load path stubbed (real GPU load is Tier-2-only, deferred to AZ-624's Jetson AC-5 run). + +## Scope + +### Included + +- Internal builder `_build_c7_inference(config)`. Selects PyTorch FP16 vs. TensorRT per `config.inference.backend` (or equivalent field) and the matching `BUILD_*` env flag. +- BUILD-flag mismatch raises `AirborneBootstrapError` naming flag + component. +- Unit tests with stubbed engine load. + +### Excluded + +- C3 LightGlue / feature extractor (AZ-622), C5 / RANSAC (AZ-623), main() wiring (AZ-624). +- GPU model-load NFR thresholds — verified by AZ-624's full AC-4. + +## Acceptance Criteria + +**AC-621.1**: `build_pre_constructed(config)` adds `c7_inference` (InferenceRuntime instance) for a default config with the matching `BUILD_*` flag ON. + +**AC-621.2**: with both `BUILD_TENSORRT_RUNTIME=OFF` and `BUILD_PYTORCH_FP16_RUNTIME=OFF` and a config selecting a C2 / C3 strategy that needs c7, `build_pre_constructed` raises `AirborneBootstrapError` naming both flag(s) and the consuming component slug. + +**AC-621.3**: `pytest tests/unit/runtime_root/test_az621_pre_constructed_phase_c.py` covers AC-621.1 (stubbed engine) and AC-621.2. + +## Tier-2 Note + +Real TensorRT engine load is verified by the umbrella subtask AZ-624's Jetson AC-5 run per `_docs/02_document/tests/tier2-jetson-testing.md`. This subtask's unit tests stub via `BUILD_*` flag selection or factory monkeypatch. + +## Constraints + +- MUST NOT introduce new `BUILD_*` env flags. +- MUST be additive on top of AZ-619 + AZ-620. + +## Evidence + +- Umbrella spec: `_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md` +- AZ-297 / AZ-320 task specs in `_docs/02_tasks/done/` for C7 runtime classes diff --git a/_docs/02_tasks/todo/AZ-622_pre_constructed_phase_d_c3_runtimes.md b/_docs/02_tasks/todo/AZ-622_pre_constructed_phase_d_c3_runtimes.md new file mode 100644 index 0000000..1d12089 --- /dev/null +++ b/_docs/02_tasks/todo/AZ-622_pre_constructed_phase_d_c3_runtimes.md @@ -0,0 +1,54 @@ +# AZ-622 — Phase D: build_pre_constructed seeds c3_lightglue_runtime + c3_feature_extractor + +**Task**: AZ-622_pre_constructed_phase_d_c3_runtimes +**Name**: AZ-618 Phase D: build_pre_constructed seeds c3_lightglue_runtime + c3_feature_extractor +**Description**: Fourth subtask of AZ-618. Extends `airborne_bootstrap.build_pre_constructed(config)` to populate the C3 matcher GPU runtimes shared with C2.5. +**Complexity**: 3 points +**Dependencies**: AZ-619, AZ-620, AZ-621, AZ-278 (LightGlueRuntime helper). All in `done/` once prior phases land. +**Component**: runtime_root (cross-cutting) +**Tracker**: AZ-622 +**Epic**: AZ-602 (parent: AZ-618 umbrella) + +## Outcome + +- `build_pre_constructed(config)` adds keys `c3_lightglue_runtime` (single shared `LightGlueRuntime` instance) and `c3_feature_extractor` (ALIKED / DISK extractor) on top of AZ-619..AZ-621. +- BUILD-flag mismatch raises `AirborneBootstrapError`. +- New unit tests under `tests/unit/runtime_root/test_az622_pre_constructed_phase_d.py`. + +## Scope + +### Included + +- Internal builders `_build_c3_lightglue_runtime(config)` and `_build_c3_feature_extractor(config)`. +- The `LightGlueRuntime` MUST be the SAME instance shared between C3 and C2.5 (per AZ-344 AC-10 — identity-share avoids double GPU memory). +- BUILD-flag mismatch handling. +- Unit tests. + +### Excluded + +- C282 RANSAC + C5 helpers (AZ-623), main() wiring (AZ-624). +- The cross-component identity-share assertion (one instance shared across C3 + C2.5 in the actual graph) is verified at the AZ-624 integration AC, not here. + +## Acceptance Criteria + +**AC-622.1**: `build_pre_constructed(config)` adds keys `c3_lightglue_runtime` and `c3_feature_extractor` on top of AZ-619..AZ-621. + +**AC-622.2**: BUILD-flag mismatch (e.g., `BUILD_C3_MATCHER_DISK_LIGHTGLUE=OFF` with config selecting `c3_matcher.strategy="disk_lightglue"`) surfaces a clear `AirborneBootstrapError` naming both the missing flag and consuming component. + +**AC-622.3**: `pytest tests/unit/runtime_root/test_az622_pre_constructed_phase_d.py` exercises AC-622.1 + AC-622.2. + +## Tier-2 Note + +Real LightGlue inference correctness is verified by AZ-624's Jetson AC-5 run; unit tests here stub via `BUILD_*` flag selection or factory monkeypatch. + +## Constraints + +- MUST NOT introduce new `BUILD_*` env flags. +- MUST reuse the existing per-strategy `BUILD_C3_MATCHER_*` matrix. +- MUST be additive on top of AZ-619..AZ-621. + +## Evidence + +- Umbrella spec: `_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md` +- LightGlueRuntime helper: `src/gps_denied_onboard/helpers/lightglue_runtime.py` +- C3 matcher factory: `src/gps_denied_onboard/runtime_root/matcher_factory.py` diff --git a/_docs/02_tasks/todo/AZ-623_pre_constructed_phase_e_ransac_c5_helpers.md b/_docs/02_tasks/todo/AZ-623_pre_constructed_phase_e_ransac_c5_helpers.md new file mode 100644 index 0000000..d3d6853 --- /dev/null +++ b/_docs/02_tasks/todo/AZ-623_pre_constructed_phase_e_ransac_c5_helpers.md @@ -0,0 +1,58 @@ +# AZ-623 — Phase E: build_pre_constructed seeds c282_ransac_filter + c5 helpers + +**Task**: AZ-623_pre_constructed_phase_e_ransac_c5_helpers +**Name**: AZ-618 Phase E: build_pre_constructed seeds c282_ransac_filter + c5 helpers +**Description**: Fifth subtask of AZ-618. Extends `airborne_bootstrap.build_pre_constructed(config)` to populate the small / stateless helper entries plus the special-case `c5_isam2_graph_handle`. +**Complexity**: 3 points +**Dependencies**: AZ-619, AZ-282 (RansacFilter), AZ-276 (ImuPreintegrator), AZ-277 (SE3Utils), AZ-279 (WgsConverter), AZ-381 (ISam2GraphHandle). All in `done/`. +**Component**: runtime_root (cross-cutting) +**Tracker**: AZ-623 +**Epic**: AZ-602 (parent: AZ-618 umbrella) + +## Outcome + +- `build_pre_constructed(config)` adds keys `c282_ransac_filter`, `c5_imu_preintegrator`, `c5_se3_utils`, `c5_wgs_converter`, `c5_isam2_graph_handle` on top of AZ-619..AZ-622. +- The `c5_isam2_graph_handle` ordering question (C4 wrapper consumes it BEFORE C5 wrapper runs in the topo order) is resolved here — not deferred to AZ-624. +- New unit tests under `tests/unit/runtime_root/test_az623_pre_constructed_phase_e.py`. + +## Scope + +### Included + +- Internal builders for the 5 keys above. Most are trivial constructions (`RansacFilter()`, `WgsConverter()`); `c5_imu_preintegrator` uses `make_imu_preintegrator(camera_calibration)`; `c5_se3_utils` is a thin namespace object exposing the module functions; `c5_isam2_graph_handle` is the per-strategy build (gtsam_isam2 / eskf). +- Resolution of the C4-before-C5 ordering for `c5_isam2_graph_handle`. Investigation budget ≤1 hour. +- Unit tests covering AC-623.1 + AC-623.2. + +### Excluded + +- main() wiring (AZ-624). +- Any GPU-touching builders (AZ-621 / AZ-622). + +## Acceptance Criteria + +**AC-623.1**: `build_pre_constructed(config)` adds the 5 keys above on top of AZ-619..AZ-622. + +**AC-623.2**: invoking twice produces dicts where stateless helpers (`c282_ransac_filter`, `c5_wgs_converter`, `c5_se3_utils`) may be either fresh or cached; `c5_imu_preintegrator` and `c5_isam2_graph_handle` MUST be the same instance across calls within the same process (cached) — this matches the per-component factory's identity expectations. + +**AC-623.3**: `pytest tests/unit/runtime_root/test_az623_pre_constructed_phase_e.py` covers AC-623.1 + AC-623.2. + +## Implementation Note + +The `c5_isam2_graph_handle` / `build_state_estimator` ordering question is the only non-trivial bit here. `build_state_estimator` returns `(StateEstimator, ISam2GraphHandle)` together — but the airborne wrapper for c4_pose consumes `c5_isam2_graph_handle` from `pre_constructed` BEFORE the c5_state wrapper runs in the topo order. Two paths to investigate: + +1. Construct the handle here in the bootstrap (separately from the StateEstimator) and put it in `pre_constructed["c5_isam2_graph_handle"]`. Then the `_c5_state_wrapper` consumes the SAME handle from `constructed` (which gets seeded from `pre_constructed`) instead of building a new one. +2. Reorder the bootstrap to run c5_state first (before c4_pose) so the StateEstimator + handle are built together — but this conflicts with the existing `_C5_STATE_DEPENDS_ON: ("c1_vio", "c4_pose")` declaration. + +Path 1 is preferred (no topology change). Path 2 requires editing `_AIRBORNE_REGISTRATIONS` and is potentially a larger change. Spend ≤1 hour deciding; if Path 1's separation requires a Protocol seam change to ISam2GraphHandle's construction, escalate to the user (do NOT defer to AZ-624). + +## Constraints + +- MUST NOT modify per-component factory signatures. +- MUST be additive on top of AZ-619..AZ-622. + +## Evidence + +- Umbrella spec: `_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md` +- Helper modules: `src/gps_denied_onboard/helpers/{ransac_filter,imu_preintegrator,se3_utils,wgs_converter}.py` +- `c5_state` factory: `src/gps_denied_onboard/runtime_root/state_factory.py` +- ISam2GraphHandle: `src/gps_denied_onboard/components/c5_state/_isam2_handle.py` diff --git a/_docs/02_tasks/todo/AZ-624_pre_constructed_phase_f_wire_main.md b/_docs/02_tasks/todo/AZ-624_pre_constructed_phase_f_wire_main.md new file mode 100644 index 0000000..1cb4b03 --- /dev/null +++ b/_docs/02_tasks/todo/AZ-624_pre_constructed_phase_f_wire_main.md @@ -0,0 +1,81 @@ +# AZ-624 — Phase F: wire build_pre_constructed into runtime_root.main() + AC-1..AC-5 verification + +**Task**: AZ-624_pre_constructed_phase_f_wire_main +**Name**: AZ-618 Phase F: wire build_pre_constructed into runtime_root.main() + AC-1..AC-5 verification +**Description**: Final / umbrella subtask of AZ-618. Wires `build_pre_constructed` into `runtime_root.main()` and lands the FULL AC suite from the AZ-618 umbrella (AC-1..AC-5), including the Jetson tier-2 verification. +**Complexity**: 2 points +**Dependencies**: AZ-619, AZ-620, AZ-621, AZ-622, AZ-623 (all phases must be in `done/` before this lands). +**Component**: runtime_root (cross-cutting) +**Tracker**: AZ-624 +**Epic**: AZ-602 (parent: AZ-618 umbrella) + +## Outcome + +- `runtime_root/__init__.py::main()` calls `register_airborne_strategies()` then `pre_constructed = build_pre_constructed(config)` then `compose_root(config, pre_constructed=pre_constructed)`. +- Existing exception block extended to surface `AirborneBootstrapError` cleanly with `EXIT_GENERIC_FAILURE` and a clear operator-facing stderr message (rather than the current implicit traceback). +- New unit test file `tests/unit/runtime_root/test_az618_pre_constructed.py` lands the FULL AC-1..AC-4 suite from the AZ-618 umbrella spec. +- Jetson AC-5 verified via `scripts/run-tests-jetson.sh tests/e2e/replay/test_derkachi_1min.py`. + +## Scope + +### Included + +- 2-line addition in `main()` between `register_airborne_strategies()` and `compose_root(config)`. +- Extension of the `except (ConfigurationError, StrategyNotLinkedError, RuntimeError)` block to surface `AirborneBootstrapError` distinctly. +- New unit test `tests/unit/runtime_root/test_az618_pre_constructed.py` covering AC-1..AC-4 from the umbrella spec. +- Jetson tier-2 run + evidence capture in batch report. + +### Excluded + +- Any new builders (those live in AZ-619..AZ-623). +- New `BUILD_*` env flags. +- Operator binary's pre_constructed assembly (AZ-591 explicitly deferred that; this remains airborne-only). + +## Acceptance Criteria + +The full AZ-618 umbrella AC suite plus this subtask's verification gates: + +**AC-618-1: `build_pre_constructed(config)` populates every required key** +Given `register_airborne_strategies()` has run +And a `Config` selecting every component's default strategy +When `build_pre_constructed(config)` is called +Then the returned dict contains exactly `set.union(*AIRBORNE_REQUIRED_PRE_CONSTRUCTED_KEYS.values())` +And no key maps to `None`. + +**AC-618-2: `compose_root(config, pre_constructed=...)` reaches takeoff** +Given `register_airborne_strategies()` has run +And `pre_constructed = build_pre_constructed(config)` for the default config +When `compose_root(config, pre_constructed=pre_constructed)` runs +Then it returns a `RuntimeRoot` whose `components` dict contains all 7 registered slots without raising `AirborneBootstrapError`. + +**AC-618-3: `BUILD_*` flag mismatch surfaces a clear error** +Given a config selecting a strategy whose `BUILD_*` flag is OFF +When `build_pre_constructed(config)` is called +Then it raises `AirborneBootstrapError` whose message names both the missing flag and the consuming component. + +**AC-618-4: `runtime_root.main()` end-to-end exit codes** +Given a minimal in-process Config selecting all-defaults +When `main(config)` is called with every required `BUILD_*` flag ON +Then it returns 0 (success). +And when a single required infra dep is forcibly unavailable +Then it returns `EXIT_GENERIC_FAILURE` (1) and stderr contains the `airborne_bootstrap:` prefix with the missing key + consuming component. + +**AC-618-5 / AC-624.tier2: Jetson tier-2 e2e replay tests cross compose_root.ready** +Given the AZ-624 changes are landed and AZ-619..AZ-623 are in `done/` +When the Jetson tier-2 e2e harness is invoked (`scripts/run-tests-jetson.sh tests/e2e/replay/test_derkachi_1min.py`) +Then each test crosses BOTH `replay.compose_root.ready` AND `replay.input.frame_emitted` log lines. +And the batch report's `Tier-2 evidence:` field captures the terminal log path, JetPack version, and run timestamp per `_docs/02_document/tests/tier2-jetson-testing.md`. + +**AC-624.local**: full Tier-1 pytest suite green after the wire-in. + +## Constraints + +- This subtask MUST NOT touch any per-component factory signature. +- MUST NOT introduce new `BUILD_*` env flags. + +## Evidence + +- Umbrella spec: `_docs/02_tasks/todo/AZ-618_airborne_bootstrap_pre_constructed.md` (AC-1..AC-5 narrative) +- Tier-2 testing policy: `_docs/02_document/tests/tier2-jetson-testing.md` +- Current incomplete `main()`: `src/gps_denied_onboard/runtime_root/__init__.py:636` +- Existing replay-mode merge in `compose_root`: `src/gps_denied_onboard/runtime_root/__init__.py:419-484` diff --git a/_docs/_autodev_state.md b/_docs/_autodev_state.md index d1de14e..62baeb5 100644 --- a/_docs/_autodev_state.md +++ b/_docs/_autodev_state.md @@ -8,7 +8,7 @@ status: in_progress sub_step: phase: 1 name: parse - detail: "AZ-618 single-task batch (rewind from Step 11)" + detail: "AZ-618 split into AZ-619..AZ-624 (subtasks of AZ-618; epic AZ-602). Next batch = AZ-619 (Phase A: c13_fdr + clock, 2pt). AZ-618 stays In Progress as umbrella; subtasks are To Do." retry_count: 0 cycle: 1 tracker: jira