Files
gps-denied-onboard/_docs/03_implementation/batch_91_cycle1_report.md
T
Oleksandr Bezdieniezhnykh 7dc38fdd3e [AZ-620] Phase B: build_pre_constructed seeds c6_descriptor_index + c6_tile_store
Second of six subtasks of AZ-618. Extends
airborne_bootstrap.build_pre_constructed(config) additively with the
two C6 storage entries on top of AZ-619's c13_fdr + clock contract:

- c6_descriptor_index: via storage_factory.build_descriptor_index
- c6_tile_store:       via storage_factory.build_tile_store

When BUILD_FAISS_INDEX=OFF, the lower-level RuntimeNotAvailableError
from the descriptor index factory is translated into an
AirborneBootstrapError that names the missing key
(c6_descriptor_index), the gating flag (BUILD_FAISS_INDEX), and the
consuming component slug(s) drawn from
AIRBORNE_REQUIRED_PRE_CONSTRUCTED_KEYS. The original error is
preserved as __cause__ so operators still see the upstream reason.

Tests: 3 new unit tests cover AC-620.1 + AC-620.2 (twice, with and
without a configured consumer, so the bootstrap fails loudly in
either branch). AZ-619 tests updated to add an autouse stub for the
Phase B builders (keeps them focused on Phase A keys) and to relax
the "exactly two keys" assertion to "AZ-619 keys remain present
under AZ-620 additivity" per the original test's own forward-pointer.

Bonus: ruff --fix removed 12 pre-existing UP037 quoted-annotation
warnings in airborne_bootstrap.py (covered by `from __future__ import
annotations`). All in modified-area scope per quality-gates.mdc.

Run: pytest tests/unit/runtime_root/ -q -> 15/15 passed in 1.06s.

Spec moved to _docs/02_tasks/done/ in the previous commit (audit-trail
backfill of batch_90 also landed there).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 06:36:11 +03:00

6.3 KiB

Batch 91 Report — AZ-620 Phase B: build_pre_constructed seeds c6_descriptor_index + c6_tile_store (cycle 1)

Batch: 91 Date: 2026-05-19 Context: Product implementation (greenfield Step 7 — Implement; AZ-618 umbrella, Phase B of 6) Tasks: AZ-620 (3 cp) — 1 task Cycle: 1 Verdict: COMPLETE — PASS (self-reviewed inline; 15/15 runtime_root tests green)

Summary

Second of six subtasks decomposing the AZ-618 umbrella. Phase B extends airborne_bootstrap.build_pre_constructed(config) additively, adding the two C6 storage entries (c6_descriptor_index, c6_tile_store) on top of AZ-619's foundational c13_fdr + clock. Wraps the existing C6 factories so a BUILD_FAISS_INDEX=OFF mismatch surfaces a clear operator-facing AirborneBootstrapError instead of bubbling up the lower-level RuntimeNotAvailableError with no consuming-component context.

AZ-620 — build_pre_constructed Phase B (3 cp)

  • src/gps_denied_onboard/runtime_root/airborne_bootstrap.py:

    • Imports build_descriptor_index + build_tile_store from storage_factory, and RuntimeNotAvailableError from errors.
    • New public constant FAISS_BUILD_FLAG = "BUILD_FAISS_INDEX" (exported in __all__) — single source of truth for the flag name embedded in error messages.
    • New module-private helpers:
      • _consumers_of_pre_constructed_key(key) — reads AIRBORNE_REQUIRED_PRE_CONSTRUCTED_KEYS to find which slugs need a given key.
      • _configured_consumers_of_pre_constructed_key(config, key) — narrows to consumers present in config.components; falls back to the full theoretical set when no components are configured (so error messages stay informative under bare Config()).
      • _build_c6_descriptor_index(config) — calls build_descriptor_index; on RuntimeNotAvailableError, re-raises as AirborneBootstrapError naming c6_descriptor_index, BUILD_FAISS_INDEX, and the consuming component slug(s). Preserves the original error via raise ... from exc.
      • _build_c6_tile_store(config) — thin pass-through to build_tile_store (no BUILD_* flag gates this side).
    • build_pre_constructed(config) now returns four keys: c13_fdr, clock, c6_descriptor_index, c6_tile_store. Additivity preserved per AZ-620 Constraint "MUST be additive on top of AZ-619".
    • Bonus hygiene (mechanical): ruff --fix removed 12 pre-existing UP037 quoted-annotation warnings in the same file (covered by from __future__ import annotations at line 49). All 12 lints were in the modified-area scope per .cursor/rules/quality-gates.mdc.
  • tests/unit/runtime_root/test_az619_pre_constructed_phase_a.py:

    • New autouse fixture _stub_c6_builders monkeypatches _build_c6_descriptor_index + _build_c6_tile_store to opaque sentinels — keeps AZ-619 tests focused on Phase A keys without entangling them with the new Phase B integration paths (and avoids requiring real Postgres + FAISS for the AZ-619 cases).
    • test_phase_a_only_seeds_two_keys renamed to test_phase_a_keys_remain_present_under_az620_additivity: now asserts AZ-619 keys are a SUBSET of the returned dict (not exact equality), matching the explicit forward-pointer that the original docstring carried ("this test will be relaxed at that point").
  • tests/unit/runtime_root/test_az620_pre_constructed_phase_b.py (new):

    • test_ac_620_1_adds_c6_descriptor_index_and_c6_tile_store — stubs both C6 factories to identifiable mocks; asserts the bootstrap dict contains both Phase B keys referencing the patched returns, and AZ-619 keys are still present. Covers AC-620.1.
    • test_ac_620_2_build_flag_off_with_configured_c2_vpr_raises_named_error — stubs build_descriptor_index to raise RuntimeNotAvailableError (mirroring real BUILD_FAISS_INDEX=OFF behaviour); builds a config with c2_vpr.strategy="net_vlad"; asserts AirborneBootstrapError is raised with all three names (c6_descriptor_index, BUILD_FAISS_INDEX, c2_vpr) and the original error preserved as __cause__. Covers AC-620.2.
    • test_ac_620_2_no_configured_consumer_still_raises_with_full_set — defence-in-depth: even with no consumer configured, the bootstrap still fails loudly (rather than silently dropping the key); the message lists the full theoretical consumer set. Strengthens AC-620.2's operator-facing contract.

File Ownership

  • OWNED (component runtime_root):
    • src/gps_denied_onboard/runtime_root/airborne_bootstrap.py
    • tests/unit/runtime_root/test_az619_pre_constructed_phase_a.py
    • tests/unit/runtime_root/test_az620_pre_constructed_phase_b.py
  • READ-ONLY: imports from runtime_root.storage_factory (same package), runtime_root.errors, clock, fdr_client, config, c6_tile_cache.interface (TYPE_CHECKING via storage_factory only).
  • No FORBIDDEN-zone writes.

Test Results

  • New unit tests: 3 under tests/unit/runtime_root/test_az620_pre_constructed_phase_b.py covering AC-620.1 + AC-620.2 (twice, defence-in-depth).
  • Updated unit tests: 5 AZ-619 tests still passing after autouse-stub fixture and relaxed-equality assertion.
  • AZ-591 regression (test_az591_airborne_bootstrap.py): 7/7 passingAIRBORNE_REQUIRED_PRE_CONSTRUCTED_KEYS table consistency + airborne registration semantics + tier isolation all unchanged.
  • Combined: pytest tests/unit/runtime_root/ -q15/15 passed in 1.06 s.
  • No new ruff errors on touched files; 12 pre-existing UP037 warnings in the same file fixed.

Out of scope (deferred)

  • All other keys in AIRBORNE_REQUIRED_PRE_CONSTRUCTED_KEYS — AZ-621 (c7 inference), AZ-622 (c3 runtimes), AZ-623 (RANSAC + c5 helpers), AZ-624 (main() integration + AC-1..AC-5).
  • Real Postgres + FAISS integration testing — covered by the existing AZ-303 / AZ-305 / AZ-306 component-level tests; not duplicated at the bootstrap layer.
  • Mandatory-Tier-2 Jetson run — consolidated at AZ-624.

State

  • Spec moved: _docs/02_tasks/todo/AZ-620_pre_constructed_phase_b_c6_storage.md_docs/02_tasks/done/.
  • Tracker: AZ-620 transitioned To Do → In Progress at batch start; will transition In Progress → In Testing after this commit (per implement skill Step 12).
  • _docs/_autodev_state.md advanced to last_completed_batch: 91.

Next Batch

  • Batch 92: AZ-621 (3 cp) — Phase C of AZ-618 umbrella. Adds c7_inference engine to build_pre_constructed. Depends on AZ-619 + AZ-620 (both will be in done/ after this commit).