[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 <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-19 06:20:06 +03:00
parent d066a23cb1
commit 8cee532516
9 changed files with 410 additions and 8 deletions
+10 -4
View File
@@ -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
@@ -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
@@ -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(<their_slug>, 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`
@@ -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
@@ -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
@@ -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`
@@ -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`
@@ -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`
+1 -1
View File
@@ -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