[AZ-622] Phase D: build_pre_constructed seeds c3 GPU runtimes

build_pre_constructed now populates c3_lightglue_runtime
(LightGlueRuntime) + c3_feature_extractor (FeatureExtractor) on top
of AZ-619/620/621. Strategy-specific BUILD_MATCHER_* flag mismatch
raises AirborneBootstrapError naming the missing flag and the c3_matcher
consumer; the c7 InferenceRuntime built earlier in the bootstrap is
reused as the engine source so no double-build at this layer.

C3MatcherConfig gains optional lightglue_weights_path: Path | None
for the operator's deployment config; production main() (AZ-624)
populates it. Real LightGlue inference correctness is verified by
AZ-624's Jetson AC-5 run per the AZ-622 Tier-2 Note.

Phase tests for AZ-619/620/621 gain an autouse _stub_c3_matcher_builders
fixture so additivity assertions remain valid as the bootstrap grows.

Code review: PASS_WITH_WARNINGS (3 Low: signature drift from spec,
_is_build_flag_on duplication across 3 runtime_root modules, and
BuildConfig literal mirrored with per-strategy build configs). All
deferred to future hygiene PBIs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-19 08:56:04 +03:00
parent eaf2f47f69
commit 5c4d129f80
10 changed files with 856 additions and 19 deletions
@@ -37,6 +37,16 @@ by C3.5; it lives in :class:`C3_5RefinerConfig` (sibling block) —
not duplicated here. ``None`` is allowed as a placeholder for
``BUILD_MATCHER_<variant>=OFF`` binaries; the factory rejects
``None`` only for the SELECTED strategy at composition time.
``lightglue_weights_path`` (AZ-622 / Phase D) points at the LightGlue
*matcher* engine — distinct from the per-strategy DISK / ALIKED
*feature-extractor* engine. The airborne bootstrap
(``runtime_root.airborne_bootstrap.build_pre_constructed``) reads
this field to construct the single shared
:class:`gps_denied_onboard.helpers.lightglue_runtime.LightGlueRuntime`
that C3 + C2.5 both consume (R14 fix; one instance avoids double GPU
memory). ``None`` is allowed; production main() (AZ-624) populates
the path before calling ``build_pre_constructed``.
"""
from __future__ import annotations
@@ -69,6 +79,7 @@ class C3MatcherConfig:
disk_weights_path: Path | None = None
aliked_weights_path: Path | None = None
xfeat_weights_path: Path | None = None
lightglue_weights_path: Path | None = None
def __post_init__(self) -> None:
if self.strategy not in KNOWN_STRATEGIES:
@@ -91,7 +102,12 @@ class C3MatcherConfig:
"C3MatcherConfig.ransac_threshold_px must be > 0; "
f"got {self.ransac_threshold_px}"
)
for name in ("disk_weights_path", "aliked_weights_path", "xfeat_weights_path"):
for name in (
"disk_weights_path",
"aliked_weights_path",
"xfeat_weights_path",
"lightglue_weights_path",
):
value = getattr(self, name)
if value is not None and not isinstance(value, Path):
raise ConfigError(