[AZ-776] Open-loop ESKF composition profile via c4_pose.enabled

ADR-012: add c4_pose.enabled (default True) and enforce the
(c4_pose.enabled, c5_state.strategy) 2x2 pairing matrix at compose
time. When enabled=false, compose_root removes c4_pose from the
selection map and build_pre_constructed omits c5_isam2_graph_handle.
Replay protocol Invariant 13 owns the gate. Tier-2 conftest YAML
writes the open-loop profile; un-xfails AC-1/2/5 and both AC-6
variants in Derkachi (AC-3 stays xfailed for AZ-777). 319/319
runtime_root + c4_pose + c5_state tests green.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Oleksandr Bezdieniezhnykh
2026-05-21 13:40:01 +03:00
parent 6044a33197
commit 8de2716500
10 changed files with 687 additions and 83 deletions
@@ -1135,6 +1135,33 @@ def _build_c3_feature_extractor(config: Config) -> FeatureExtractor:
return OpenCvOrbExtractor()
def _c4_pose_disabled(config: Config) -> bool:
"""True iff the airborne open-loop ESKF composition profile is active.
AZ-776 / ADR-012: when ``config.components["c4_pose"].enabled`` is
explicitly ``False`` the composition root strips ``c4_pose`` from
the component graph and the C4 wrapper never runs. The eager
``(estimator, handle)`` build inside :func:`build_pre_constructed`
therefore has no consumer for the iSAM2 graph handle slot
(``c5_isam2_graph_handle``); leaving the slot absent makes the
"no C4" property visible at the pre-bootstrap layer too.
Returns ``False`` when the block is absent or when ``enabled`` is
missing / true — the full GTSAM profile (ADR-003 steady state)
remains the default airborne pipeline. Replay-mode component-block
omission is handled separately by
:func:`_replay_omits_component_block`.
"""
components = getattr(config, "components", None) or {}
if not isinstance(components, Mapping):
return False
block = components.get("c4_pose")
if block is None:
return False
enabled = getattr(block, "enabled", True)
return not bool(enabled)
def _replay_omits_component_block(config: Config, block_name: str) -> bool:
"""True iff replay-mode :class:`Config` has no ``components[block_name]`` entry.
@@ -1301,7 +1328,14 @@ def build_pre_constructed(config: Config) -> dict[str, Any]:
fdr_client=constructed["c13_fdr"],
tile_store=constructed.get("c6_tile_store"),
)
constructed["c5_isam2_graph_handle"] = handle
# AZ-776 / ADR-012 open-loop ESKF profile: c4_pose.enabled=False
# strips c4_pose from the composition graph, so the
# c5_isam2_graph_handle slot has no consumer. ESKF returns
# handle=None by design; omitting the slot makes the open-loop
# property visible at the pre_constructed layer and refuses the
# invariant "handle is None means C4 will crash on read".
if not _c4_pose_disabled(config):
constructed["c5_isam2_graph_handle"] = handle
constructed[_C5_PREBUILT_ESTIMATOR_KEY] = estimator
return constructed