"""C1 ``VioStrategy`` Protocol (AZ-331). PEP 544 ``typing.Protocol`` with ``runtime_checkable=True``; four methods that span the camera-ingest hot path (``process_frame``), F8 reboot recovery (``reset_to_warm_start``), diagnostics (``health_snapshot``), and self-identification (``current_strategy_label``). Concrete impls — :class:`Okvis2Strategy` (AZ-332), :class:`VinsMonoStrategy` (AZ-333), :class:`KltRansacStrategy` (AZ-334) — live in sibling modules and are imported lazily by :mod:`gps_denied_onboard.runtime_root.vio_factory`. The contract at ``_docs/02_document/contracts/c1_vio/vio_strategy_protocol.md`` v1.0.0 is the authoritative shape; this module mirrors it 1:1. """ from __future__ import annotations from typing import TYPE_CHECKING, Literal, Protocol, runtime_checkable if TYPE_CHECKING: from gps_denied_onboard._types.calibration import CameraCalibration from gps_denied_onboard._types.nav import ( ImuWindow, NavCameraFrame, VioHealth, VioOutput, WarmStartPose, ) __all__ = ["VioStrategy"] @runtime_checkable class VioStrategy(Protocol): """On-Jetson visual / visual-inertial odometry runtime. Implementations: :class:`Okvis2Strategy` (production-default, OKVIS2 SLAM), :class:`VinsMonoStrategy` (research-only), :class:`KltRansacStrategy` (mandatory simple-baseline per ADR-002). Selection is owned by the composition root. Invariants (see ``vio_strategy_protocol.md`` v1.0.0): - Single-threaded per instance (one camera-ingest writer thread). - ``current_strategy_label()`` is constant per instance and equals ``config.vio.strategy`` exactly. - Error envelope is closed — only members of :class:`VioError` escape ``process_frame``. """ def process_frame( self, frame: "NavCameraFrame", imu: "ImuWindow", calibration: "CameraCalibration", ) -> "VioOutput": """Camera-ingest hot-path call (one per nav-camera frame). ``VioOutput.frame_id`` MUST equal ``frame.frame_id`` (C5 alignment invariant). Raises :class:`VioInitializingError` while booting (state == INIT; no output emitted) and :class:`VioFatalError` once ``consecutive_lost`` exceeds the configured threshold. During DEGRADED operation the method returns normally with an inflated covariance — NOT raises :class:`VioDegradedError`. """ ... def reset_to_warm_start(self, hint: "WarmStartPose") -> None: """Destructive re-init from an F8-reboot warm-start hint. Clears keyframe window, IMU integration state, feature tracks. Subsequent ``process_frame`` calls re-initialise from the hint. Raises :class:`VioFatalError` only on irrecoverable backend init failure. """ ... def health_snapshot(self) -> "VioHealth": """Most-recent health state — FDR-stamped per the AC-NEW-3 audit.""" ... def current_strategy_label( self, ) -> Literal["okvis2", "vins_mono", "klt_ransac"]: """Identify which concrete strategy is wired here. Returned string equals ``config.vio.strategy`` exactly. AC-NEW-3 FDR audit relies on this property. """ ...