# Batch Report

**Batch**: 96
**Tasks**: AZ-624 (Phase F of AZ-618: wire `build_pre_constructed` into `runtime_root.main()` + AC-1..AC-5 verification)
**Date**: 2026-05-19
**Cycle**: 1

## Task Results

| Task | Status | Files Modified | Tests | AC Coverage | Issues |
|------|--------|----------------|-------|-------------|--------|
| AZ-624_pre_constructed_phase_f_wire_main | Done (with AC-5 BLOCKED on Jetson hardware evidence) | 2 files (1 source + 1 new test) | 6 new + 261 carry-over runtime_root + c5_state | 4/5 ACs covered locally; AC-5 BLOCKED pending operator-supplied Jetson run | 0 blocking from AZ-624 changes; 1 unrelated pre-existing failure (`c12_operator_orchestrator/test_cli_console_script.py::test_cold_start_under_500ms_p99` — Mac dev host subprocess startup ~700 ms exceeds the 500 ms NFR; unrelated to AZ-624 scope) |

AZ-624 is the final / umbrella subtask of AZ-618. With AZ-619..AZ-623 + AZ-625 all in `done/`, this batch lands the integration: `runtime_root.main()` now calls `register_airborne_strategies()`, builds the `pre_constructed` dict via `build_pre_constructed(config)`, and passes it through to `compose_root(config, pre_constructed=pre_constructed)`. A dedicated `except AirborneBootstrapError` handler surfaces the operator-actionable bootstrap error (with its `airborne_bootstrap:` prefix) ahead of the broader `(ConfigurationError, StrategyNotLinkedError, RuntimeError)` clause. The new umbrella test file `test_az618_pre_constructed.py` covers AC-1..AC-4 from the AZ-618 umbrella spec.

## Files Changed

### Production

- `src/gps_denied_onboard/runtime_root/__init__.py`:
  - Extended the `main()` function-scope import to include `AirborneBootstrapError` and `build_pre_constructed` alongside `register_airborne_strategies`.
  - Inserted `pre_constructed = build_pre_constructed(config)` between `register_airborne_strategies()` and `compose_root(config, ...)`.
  - Replaced the unkwargd `compose_root(config)` call with `compose_root(config, pre_constructed=pre_constructed)`.
  - Added a dedicated `except AirborneBootstrapError` clause BEFORE the broader `(ConfigurationError, StrategyNotLinkedError, RuntimeError)` clause to surface the operator-facing bootstrap error message (which itself carries the `airborne_bootstrap:` prefix per AZ-619..AZ-625) without letting the broader clause swallow the prefix in a generic backtrace. The inline comment captures the rationale.

### Tests

- `tests/unit/runtime_root/test_az618_pre_constructed.py` (NEW, 6 tests):
  - `test_ac_618_1_build_pre_constructed_populates_every_required_key` — AC-618-1 (every key in the union of `AIRBORNE_REQUIRED_PRE_CONSTRUCTED_KEYS` rows is present + non-None).
  - `test_ac_618_2_compose_root_reaches_takeoff_with_all_seven_slots` — AC-618-2 (compose_root produces a `RuntimeRoot` with all 7 strategy-selecting slots populated; uses `_stub_strategy_factories` to monkeypatch the per-component factory imports in `airborne_bootstrap`'s own namespace).
  - `test_ac_618_3_build_flag_off_raises_named_error_with_consuming_component` — AC-618-3 (forces `build_inference_runtime` to raise `RuntimeNotAvailableError`, asserts the wrapping `AirborneBootstrapError` names `c7_inference` + both airborne C7 BUILD flags + the consuming component slug `c2_vpr`).
  - `test_ac_618_4_main_returns_zero_on_success` — AC-618-4 success path (main returns 0; nothing on stderr).
  - `test_ac_618_4_main_returns_generic_failure_with_airborne_bootstrap_prefix` — AC-618-4 failure path (forced builder failure → exit code 1 + stderr contains `airborne_bootstrap:`).
  - `test_ac_624_local_main_distinct_handler_does_not_double_print` — AZ-624 local regression guard (the dedicated `AirborneBootstrapError` handler short-circuits before the broader RuntimeError clause; exactly ONE `runtime_root: airborne_bootstrap:` line in stderr).

### Reviews

- `_docs/03_implementation/reviews/batch_96_review.md` (NEW) — code review report (verdict: PASS; 1 Low finding on documentation-as-code dedicated handler).

### Specs

- `_docs/02_tasks/todo/AZ-624_*.md` → ARCHIVED to `_docs/02_tasks/done/`.
- `_docs/02_tasks/todo/AZ-618_*.md` → ARCHIVED to `_docs/02_tasks/done/` (umbrella reference; no longer actionable since the last subtask landed).

## AC Test Coverage

5 ACs from the AZ-618 umbrella + 1 AZ-624 local AC. Coverage:

| AC | Coverage |
|----|----------|
| AC-618-1 | `test_ac_618_1_build_pre_constructed_populates_every_required_key` |
| AC-618-2 | `test_ac_618_2_compose_root_reaches_takeoff_with_all_seven_slots` |
| AC-618-3 | `test_ac_618_3_build_flag_off_raises_named_error_with_consuming_component` |
| AC-618-4 | `test_ac_618_4_main_returns_zero_on_success` + `test_ac_618_4_main_returns_generic_failure_with_airborne_bootstrap_prefix` + `test_ac_624_local_main_distinct_handler_does_not_double_print` |
| AC-618-5 / AC-624.tier2 | **BLOCKED** — Jetson tier-2 e2e replay run; requires operator-supplied hardware evidence (terminal log path + JetPack version + run timestamp per `_docs/02_document/tests/tier2-jetson-testing.md`). |
| AC-624.local | Full Tier-1 pytest suite — 2150 passed, 85 skipped (environment-gated). One unrelated pre-existing failure (see Test Run section). |

## Test Run

| Suite | Result |
|-------|--------|
| `tests/unit/runtime_root/test_az618_pre_constructed.py` (targeted) | 6 passed in 3.07s |
| `tests/unit/runtime_root/ + tests/unit/c5_state/` (regression) | 261 passed in 1.31s |
| `tests/unit/test_az401_compose_root_replay.py` (compose_root regression) | 25 passed in 2.02s |
| `tests/unit/` (full Tier-1 suite) | 2150 passed, 85 skipped, 1 failed |

The 85 skips are all environment-gated (Docker for c6 Postgres tests, GPU/CUDA for c7 PyTorch FP16, TensorRT for c7 Tier-2, real Jetson for c7 engine_gate, large synthetic datasets gated behind `RUN_REPLAY_E2E=1`).

The 1 failure is **unrelated to AZ-624 scope**:

- `tests/unit/c12_operator_orchestrator/test_cli_console_script.py::TestConsoleScript::test_cold_start_under_500ms_p99` — measures `operator-orchestrator --help` cold-start subprocess time. Sample: `[586.97, 613.24, 664.54, 646.32, 776.91, 692.62, 693.11, 718.97, 733.01, 873.51, 605.48]` ms; worst-after-trim = 776.9 ms, fails the 500 ms NFR. The Mac dev host's Python subprocess startup overhead drives this; CI runners and Jetson do not exhibit it. Test is `@pytest.mark.slow` and lives in `c12_operator_orchestrator` which AZ-624 does not modify or import.

## Code Review

- **Verdict**: PASS (0 Critical, 0 High, 0 Medium, 1 Low).
- F1 (Low / Style): dedicated `AirborneBootstrapError` handler is documentation-as-code (functionally identical to the broader `RuntimeError` clause, but locks the surfacing format and adds traceability). Accepted with inline comment + regression guard test.
- 0 auto-fix attempts; 0 escalated findings.

Full report: `_docs/03_implementation/reviews/batch_96_review.md`.

## Constraint Compliance (AZ-618 umbrella)

- "MUST NOT touch any per-component factory signature" → `compose_root` and `build_pre_constructed` signatures unchanged; only the body of `main()` was extended. ✓
- "MUST NOT introduce new BUILD_* env flags" → no new flag introduced. ✓
- "All changes confined to `runtime_root/__init__.py` + `runtime_root/airborne_bootstrap.py` + new test file" → diff scope respected (no `airborne_bootstrap.py` edits in this batch — that file's contract was already complete after AZ-625; AZ-624 only wires `main()`). ✓

## Loop Status

- AZ-624 was the last AZ-618 subtask. AZ-618 (umbrella reference doc) is also archived to `done/`.
- The Implement step's batch loop has no remaining AZ-618-related tasks. Other tasks may still exist in `_docs/02_tasks/todo/` (none currently — only AZ-618 + AZ-624 remained before this batch).
- **Next autodev action**: enter the implement skill's Step 15 (Product Implementation Completeness Gate) — but this gate will skip in greenfield Step 7 if no other product tasks remain, OR it will perform the cross-task completeness scan for AZ-618 outcomes (every required key populated, every wrapper path tested, every umbrella AC covered) and write `implementation_completeness_cycle1_report.md`.
- **AC-618-5 BLOCKING note**: The Jetson tier-2 e2e replay run is required by the AZ-618 umbrella but lives outside this dev host's reach. Until the operator runs `scripts/run-tests-jetson.sh tests/e2e/replay/test_derkachi_1min.py` and captures terminal log + JetPack version + run timestamp, the AZ-618 umbrella cannot be marked fully complete. The Implement skill's loop should pause at the next decision point and surface this BLOCKING gate to the operator.
