[AZ-619] Phase A: build_pre_constructed seeds c13_fdr + clock

Adds airborne_bootstrap.build_pre_constructed(config) returning a
dict with the two foundational keys: a per-binary shared FdrClient
under "c13_fdr" (via make_fdr_client with the new
AIRBORNE_MAIN_PRODUCER_ID constant) and a fresh WallClock under
"clock". Phases B..F (AZ-620..AZ-624) extend this function
additively without breaking the AZ-619 contract.

The c13_fdr instance is identity-stable across calls (per the
make_fdr_client per-producer cache) so callers can call
build_pre_constructed twice and get the same FdrClient back -
AC-619.2.

Replay-mode override is unchanged: compose_root merges
replay_components over pre_constructed so the WallClock here is
replaced by TlogDerivedClock in replay binaries (existing
contract documented in compose_root's docstring).

Tests: 5 new unit tests under tests/unit/runtime_root/
test_az619_pre_constructed_phase_a.py, all passing. AZ-591 not
regressed (12/12 in the combined run).

Spec moved to _docs/02_tasks/done/.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-19 06:23:15 +03:00
parent 8cee532516
commit 8abfb020fe
4 changed files with 155 additions and 5 deletions
@@ -1,80 +0,0 @@
# 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`