"""C3.5 ``ConditionalRefiner`` config block (AZ-348). Registered into ``config.components['c3_5_adhop']`` by the package ``__init__.py``. The composition-root factory :func:`gps_denied_onboard.runtime_root.refiner_factory.build_refiner_strategy` reads this block to select the strategy and configure thresholds. ``strategy`` selects one of the two concrete refiners (``adhop`` — production-default; ``passthrough`` — baseline / smoke / IT-12 comparison). Both modules are linked unconditionally: there is NO ``BUILD_REFINER_*`` flag (NOT ADR-002 territory). Runtime selection only. ``residual_threshold_px`` is the conditional-gate threshold: a :class:`MatchResult` whose ``reprojection_residual_px <= threshold`` is passed through unchanged; ``>`` invokes the strategy's refinement procedure. Default 2.5 px (the AC-NEW-5 / R10 tunable from operator tooling). ``invocation_rate_warn_threshold`` is the rolling-60 s invocation-rate ceiling above which a WARN log fires (C3.5-IT-03 / NFT-PERF-01). Must be in ``(0, 1)``; default 0.25. """ from __future__ import annotations from dataclasses import dataclass from typing import Final from gps_denied_onboard.config.schema import ConfigError __all__ = [ "C3_5RefinerConfig", "KNOWN_STRATEGIES", ] KNOWN_STRATEGIES: Final[frozenset[str]] = frozenset({"adhop", "passthrough"}) @dataclass(frozen=True) class C3_5RefinerConfig: """Per-component config for C3.5 conditional refiner.""" strategy: str = "adhop" residual_threshold_px: float = 2.5 invocation_rate_warn_threshold: float = 0.25 def __post_init__(self) -> None: if self.strategy not in KNOWN_STRATEGIES: raise ConfigError( f"C3_5RefinerConfig.strategy={self.strategy!r} not in " f"{sorted(KNOWN_STRATEGIES)}" ) if self.residual_threshold_px <= 0.0: raise ConfigError( "C3_5RefinerConfig.residual_threshold_px must be > 0; " f"got {self.residual_threshold_px}" ) if not (0.0 < self.invocation_rate_warn_threshold < 1.0): raise ConfigError( "C3_5RefinerConfig.invocation_rate_warn_threshold must be in " f"(0, 1); got {self.invocation_rate_warn_threshold}" )