Defines the public `CrossDomainMatcher` Protocol (PEP 544
@runtime_checkable, two methods: `match` + `health_snapshot`),
the three frozen+slotted DTOs (`CandidateMatchSet`, `MatchResult`,
`MatcherHealth`) in the L1 `_types/matcher.py` layer, the
`MatcherError` family (`MatcherBackboneError`,
`InsufficientInliersError`), and the composition-root
`build_matcher_strategy` factory with lazy-import +
`BUILD_MATCHER_<variant>` gating per ADR-002.
`RollingHealthWindow` accumulator (60 s, amortised O(1) update,
strict O(1) snapshot) is constructed by the factory and injected
into every concrete matcher so all backbones share window
semantics; this is what backs C5's spoof-promotion gate.
Legacy placeholder `MatchResult` removed from `_types/matching.py`;
import-only consumers (`c4_pose.interface`, `c3_5_adhop.interface`)
repointed at the new `_types/matcher.py` home — zero behavioural
change to those components.
AC-9 (single-thread binding) and AC-10 (LightGlueRuntime
identity-share with C2.5) deferred to AZ-270 runtime-root
composition, mirroring the AZ-342 Risk-4 escape clause. All other
ACs + NFRs covered by 70 new conformance tests.
Co-authored-by: Cursor <cursoragent@cursor.com>
Foundational scaffolding for the InlierCountReRanker (AZ-343) and
the future C3 CrossDomainMatcher consumer (AZ-344). No concrete
re-ranker is implemented here.
* ReRankStrategy Protocol (single rerank(frame, vpr_result, n,
calibration) -> RerankResult method) with all 8 invariants in the
docstring — notably INV-8 drop-and-continue (per-candidate failure
NEVER propagates unless every candidate fails).
* DTOs moved to L1 _types/rerank.py — RerankCandidate, RerankResult;
frozen+slots; tuple-not-list for RerankResult.candidates; tile_id
encoded as (zoom_level, lat, lon) tuple to keep _types/ free of any
c6_tile_cache (L3) import per module-layout.md.
* Error family: RerankError + RerankBackboneError +
RerankAllCandidatesFailedError. Only RerankAllCandidatesFailedError
escapes rerank(); RerankBackboneError is caught inside the per-
candidate loop, logged ERROR, FDR-stamped, candidate dropped.
* C2_5RerankConfig (strategy enum default "inlier_count", top_n int
default 3) with strict validation at load; registered into
Config.components on c2_5_rerank import.
* build_rerank_strategy(config, *, tile_store, lightglue_runtime)
factory: 1-strategy resolution table, lazy import,
BUILD_RERANK_<variant> gate, ImportError → StrategyNotAvailableError
mapping. The shared LightGlueRuntime is constructor-injected
(R14 fix: neither C2.5 nor C3 owns its lifecycle).
Renamed the Protocol from the existing stub "RerankStrategy" to
"ReRankStrategy" to match the contract; updated module-layout.md.
Removed the legacy RerankResult shape from _types/vpr.py — the
v1.0.0 shape lives in _types/rerank.py.
Excluded per task spec:
* Concrete InlierCountReRanker (AZ-343).
* C3 matcher protocol task (AZ-344, next in batch).
* AC-9 single-thread binding + AC-10 LightGlueRuntime identity-share
between C2.5/C3 — deferred per task spec Risk 3 until the generic
compose_root thread-binding registry and the C3 factory both land.
Tests: AC-1..AC-8 + AC-11 + NFR-perf-factory in
tests/unit/c2_5_rerank/test_protocol_conformance.py. The legacy
smoke test is removed. Full sweep: 997 passed (one pre-existing
flake in test_az296_takeoff_abort, subprocess timing, unrelated to
this commit; passes in isolation).
Co-authored-by: Cursor <cursoragent@cursor.com>
- Modified the Docker Compose configuration to include an input root for replay tests and added an environment variable for enabling SITL.
- Enhanced documentation for various testing processes, including the addition of a Runtime Completeness Decomposition Gate and clarifications on internal module testing requirements.
- Updated the implementation completeness report to reflect the current state and added new test cases for performance and resilience scenarios.
Co-authored-by: Cursor <cursoragent@cursor.com>
Keep VIO package and native bridge paths backend-neutral so BASALT remains an implementation choice rather than a component boundary.
Co-authored-by: Cursor <cursoragent@cursor.com>