mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 14:41:15 +00:00
[AZ-624] [AZ-618] Phase F: wire build_pre_constructed into main()
Wire register_airborne_strategies + build_pre_constructed + compose_root(config, pre_constructed=...) into runtime_root.main(). The existing exception block now catches AirborneBootstrapError distinctly before the broader (ConfigurationError, StrategyNotLinkedError, RuntimeError) clause so the operator-facing "airborne_bootstrap:" prefix carried by every bootstrap error reaches stderr cleanly with EXIT_GENERIC_FAILURE rather than getting absorbed into a generic backtrace. This closes the AZ-618 umbrella: AZ-619..AZ-623 + AZ-625 had built each pre_constructed key; this batch lands the integration that the production main() actually invokes them. Both the live gps-denied-onboard and replay gps-denied-replay binaries dispatch through this main() per ADR-011, so both reach takeoff with pre_constructed populated end-to-end. Tests: tests/unit/runtime_root/test_az618_pre_constructed.py adds 6 tests covering AC-618-1..AC-618-4 + AZ-624 local handler-ordering regression guard. The strategy factories are stubbed at the airborne_bootstrap module boundary so the test exercises the integration seam without standing up gtsam / FAISS / TensorRT / PyTorch / OpenCV at unit-test scope. AC-618-5 (Jetson tier-2 e2e) is BLOCKED on operator-supplied hardware evidence: scripts/run-tests-jetson.sh tests/e2e/replay/test_derkachi_1min.py must run on Jetson Orin Nano (JetPack 6.2.2+b24) and the terminal log path + JetPack version + run timestamp captured per _docs/02_document/tests/tier2-jetson-testing.md. Quality gates: ruff format clean, ruff lint clean, 6/6 new umbrella tests pass, 261/261 runtime_root + c5_state regression suite passes, 25/25 test_az401_compose_root_replay regression passes, full Tier-1 unit suite 2150/2151 passes (1 unrelated pre-existing failure: c12_operator_orchestrator subprocess cold-start NFR fails on Mac dev host's Python startup ~700 ms; not regressed by AZ-624). Code review verdict PASS (1 Low finding; full report in _docs/03_implementation/reviews/batch_96_review.md). Archives AZ-624 task spec + AZ-618 umbrella reference to done/. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -344,9 +344,7 @@ def _compose(
|
||||
for slug, strategy in selections.items()
|
||||
}
|
||||
order = _topo_order(resolved.keys(), resolved)
|
||||
constructed: dict[str, Any] = (
|
||||
dict(pre_constructed) if pre_constructed is not None else {}
|
||||
)
|
||||
constructed: dict[str, Any] = dict(pre_constructed) if pre_constructed is not None else {}
|
||||
for slug in order:
|
||||
registration = resolved[slug]
|
||||
try:
|
||||
@@ -454,11 +452,7 @@ def compose_root(
|
||||
have to satisfy the full OpenCV / pymavlink / FDR side-effects of
|
||||
the real strategies.
|
||||
"""
|
||||
extra_env = (
|
||||
("MAVLINK_SIGNING_KEY",)
|
||||
if config.mode == "live"
|
||||
else ()
|
||||
)
|
||||
extra_env = ("MAVLINK_SIGNING_KEY",) if config.mode == "live" else ()
|
||||
if config.mode == "replay":
|
||||
replay_factory = replay_components_factory or build_replay_components
|
||||
replay_components, replay_order = replay_factory(config)
|
||||
@@ -478,9 +472,7 @@ def compose_root(
|
||||
)
|
||||
merged: dict[str, Any] = dict(replay_components)
|
||||
merged.update(components)
|
||||
full_order = tuple(replay_order) + tuple(
|
||||
slug for slug in order if slug not in replay_order
|
||||
)
|
||||
full_order = tuple(replay_order) + tuple(slug for slug in order if slug not in replay_order)
|
||||
return RuntimeRoot(
|
||||
binary="airborne",
|
||||
profile=os.environ["GPS_DENIED_FC_PROFILE"],
|
||||
@@ -659,6 +651,8 @@ def main(config: Config | None = None) -> int:
|
||||
"""
|
||||
from gps_denied_onboard.replay_input import ReplayInputAdapterError
|
||||
from gps_denied_onboard.runtime_root.airborne_bootstrap import (
|
||||
AirborneBootstrapError,
|
||||
build_pre_constructed,
|
||||
register_airborne_strategies,
|
||||
)
|
||||
|
||||
@@ -666,10 +660,18 @@ def main(config: Config | None = None) -> int:
|
||||
if config is None:
|
||||
config = load_config(env=os.environ, paths=())
|
||||
register_airborne_strategies()
|
||||
compose_root(config)
|
||||
pre_constructed = build_pre_constructed(config)
|
||||
compose_root(config, pre_constructed=pre_constructed)
|
||||
except ReplayInputAdapterError as exc:
|
||||
print(f"runtime_root: replay sync impossible: {exc}", file=sys.stderr)
|
||||
return EXIT_FDR_OPEN_FAILURE
|
||||
except AirborneBootstrapError as exc:
|
||||
# Surface the operator-actionable bootstrap error directly so the
|
||||
# operator sees the "airborne_bootstrap: ..." prefix the message
|
||||
# already carries (named missing dep + consuming component slug
|
||||
# + actionable fix), rather than the raw RuntimeError fallback.
|
||||
print(f"runtime_root: {exc}", file=sys.stderr)
|
||||
return EXIT_GENERIC_FAILURE
|
||||
except (ConfigurationError, StrategyNotLinkedError, RuntimeError) as exc:
|
||||
print(f"runtime_root: {exc}", file=sys.stderr)
|
||||
return EXIT_GENERIC_FAILURE
|
||||
|
||||
Reference in New Issue
Block a user