mirror of
https://github.com/azaion/gps-denied-onboard.git
synced 2026-06-22 12:01:13 +00:00
[AZ-345] [AZ-346] [AZ-347] [AZ-349] C3 matchers + C3.5 AdHoP refiner
Implement the three concrete C3 CrossDomainMatcher strategies plus the C3.5 production-default AdHoPRefiner. C3 (AZ-345/346/347): - DiskLightGlueMatcher + AlikedLightGlueMatcher share a single shared _pipeline.run_lightglue_pipeline orchestrator (decode -> query extract -> per-candidate loop -> RANSAC sort -> health update -> FDR emit) so the only per-backbone delta is the keypoint+descriptor extractor closure. ALIKED adds a create-time engine output-schema probe (AC-special-1). - XFeatMatcher owns its own per-candidate loop (single forward fuses extraction + matching); it re-uses the shared FDR emission helpers to keep telemetry byte-identical across strategies. lightglue_runtime parameter accepted by factory but discarded (AC-special-1). - All three consume the shared LightGlueRuntime / RansacFilter / RollingHealthWindow helpers; no helper forks. InferenceRuntimeCut consumer-side Protocol added per AZ-507. C3.5 (AZ-349): - AdHoPRefiner implements the <= conditional gate, runs the OrthoLoC AdHoP TRT engine over best-candidate correspondences, re-runs RANSAC on the perspective-preconditioned set, and emits an enriched MatchResult with refinement_label="adhop". - Invariant 4 passthrough fall-through: any RefinerBackboneError (TRT failure, OOM, NaN, bad shape) is caught, logged ERROR, FDR-emitted with error: true, and converted to passthrough that still counts against the rolling invocation-rate window. MemoryError and other non-listed exceptions propagate by design (AC-5 closed-set semantics). - Rolling 60-s invocation-rate window + rate-limited WARN log (configurable via ratelimited_warn_window_ns; default 60 s). Shared changes: - C3MatcherConfig + C3_5RefinerConfig extended with the new weights/threshold/window fields. - matcher_factory + refiner_factory optionally forward clock + fdr_client to the strategy's create(); backward-compatible. - fdr_client.records registers five new kinds: matcher.frame_done, matcher.backbone_error, matcher.insufficient_inliers, matcher.all_failed, refiner.frame_done. Tests: 66 new (43 C3 parametrised + 23 AdHoP) covering 47/47 ACs; focused suite green; full project test suite green except for one pre-existing flaky CLI cold-start timing test unrelated to this batch. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
# Batch 57 — Cycle 1 Report
|
||||
|
||||
**Date**: 2026-05-14
|
||||
**Tasks**: AZ-345 (DISK+LightGlue), AZ-346 (ALIKED+LightGlue), AZ-347 (XFeat), AZ-349 (AdHoP refiner)
|
||||
**Verdict**: COMPLETE — PASS_WITH_WARNINGS
|
||||
|
||||
## Summary
|
||||
|
||||
Implemented the three concrete C3 `CrossDomainMatcher` strategies plus
|
||||
the C3.5 production-default `AdHoPRefiner`. All four wire into the
|
||||
existing AZ-344 / AZ-348 factories via module-level `create(...)`
|
||||
entry points and consume the shared `LightGlueRuntime` (AZ-285) /
|
||||
`RansacFilter` (AZ-282) / `RollingHealthWindow` helpers — no helper
|
||||
forks. The DISK + ALIKED strategies share a single
|
||||
`_pipeline.run_lightglue_pipeline` orchestrator (decode → query
|
||||
extract → per-candidate loop → RANSAC sort → health update → FDR
|
||||
emit) so the only per-backbone delta is the keypoint+descriptor
|
||||
extractor closure. XFeat owns its own per-candidate loop because its
|
||||
backbone fuses extraction + matching into one forward pass — but it
|
||||
re-uses the shared FDR emission helpers verbatim so all four strategies
|
||||
produce byte-identical telemetry shapes.
|
||||
|
||||
The AdHoP refiner implements the conditional gate at exact `<=`
|
||||
semantics (Invariant 3), runs the OrthoLoC AdHoP TRT engine over the
|
||||
best-candidate correspondences, re-runs RANSAC on the
|
||||
perspective-preconditioned set, and emits an enriched `MatchResult`
|
||||
with `refinement_label="adhop"`. Invariant 4 passthrough fall-through
|
||||
is preserved: any `RefinerBackboneError` (TRT failure, OOM, NaN, bad
|
||||
shape) is caught, logged at ERROR, FDR-emitted with `error: true`, and
|
||||
converted to a passthrough that still counts against the rolling
|
||||
invocation-rate window. `MemoryError` and other non-listed exception
|
||||
types propagate by design (AC-5 closed-set semantics).
|
||||
|
||||
Closes the AZ-345/346/347/349 dependency block. The next downstream
|
||||
consumer in cycle 1 is the e2e pipeline wiring (C3 + C3.5 →
|
||||
pose-estimator) which now has all four strategies available at runtime.
|
||||
|
||||
## Files added / modified
|
||||
|
||||
### Added (9)
|
||||
|
||||
- `src/gps_denied_onboard/components/c3_matcher/disk_lightglue.py` —
|
||||
`DiskLightGlueMatcher` + module-level `create`. Hard-coded
|
||||
preprocessor (NCHW float32 RGB 480×480 ImageNet-normalised).
|
||||
- `src/gps_denied_onboard/components/c3_matcher/aliked_lightglue.py` —
|
||||
`AlikedLightGlueMatcher` + `create`. Same preprocessor footprint as
|
||||
DISK; adds the create-time engine output-schema probe (AZ-346
|
||||
AC-special-1).
|
||||
- `src/gps_denied_onboard/components/c3_matcher/xfeat.py` —
|
||||
`XFeatMatcher` + `create`. Hard-coded grayscale 384×384 preprocessor;
|
||||
per-candidate loop owns its own orchestration (does not call
|
||||
`_pipeline.run_lightglue_pipeline`). `lightglue_runtime` parameter
|
||||
accepted in factory signature but discarded — AC-special-1.
|
||||
- `src/gps_denied_onboard/components/c3_matcher/_pipeline.py` —
|
||||
shared per-frame orchestration used by DISK + ALIKED. Owns the
|
||||
drop-and-continue loop, RANSAC sort, residual warn, health-window
|
||||
update, and the four FDR record kinds (`matcher.frame_done`,
|
||||
`matcher.backbone_error`, `matcher.insufficient_inliers`,
|
||||
`matcher.all_failed`).
|
||||
- `src/gps_denied_onboard/components/c3_matcher/inference_runtime_cut.py`
|
||||
— consumer-side `InferenceRuntimeCut` Protocol over C7 (AZ-507).
|
||||
Includes `TilePixelHandle` duck-typing note.
|
||||
- `src/gps_denied_onboard/components/c3_matcher/_engine_output_assertion.py`
|
||||
— `assert_keypoint_engine_output_schema` helper. Single home for
|
||||
the AZ-346 create-time probe so future keypoint-backbone strategies
|
||||
reuse the same error envelope.
|
||||
- `src/gps_denied_onboard/components/c3_5_adhop/adhop_refiner.py` —
|
||||
`AdHoPRefiner` + `create`. Owns the conditional gate, the rolling
|
||||
60-s invocation-rate window, the rate-limited WARN log, and the
|
||||
passthrough fall-through on `RefinerBackboneError`.
|
||||
- `src/gps_denied_onboard/components/c3_5_adhop/inference_runtime_cut.py`
|
||||
— consumer-side `InferenceRuntimeCut` Protocol over C7 (AZ-507).
|
||||
- `tests/unit/c3_matcher/test_az345_346_347_concrete_matchers.py` —
|
||||
43 parametrised tests covering AC-1..AC-12 for all three
|
||||
strategies plus AZ-346 AC-special-1 (engine schema mismatch ×2) and
|
||||
AZ-347 AC-special-1 (no LightGlue call).
|
||||
- `tests/unit/c3_5_adhop/test_az349_adhop_refiner.py` — 23 tests
|
||||
covering AZ-349 AC-1..AC-11.
|
||||
|
||||
### Modified (5)
|
||||
|
||||
- `src/gps_denied_onboard/components/c3_matcher/config.py` — added
|
||||
`ransac_threshold_px`, `disk_weights_path`, `aliked_weights_path`,
|
||||
`xfeat_weights_path`. Each new field validated in `__post_init__`.
|
||||
- `src/gps_denied_onboard/components/c3_5_adhop/config.py` — added
|
||||
`adhop_weights_path`, `ransac_threshold_px`,
|
||||
`ratelimited_warn_window_ns`.
|
||||
- `src/gps_denied_onboard/runtime_root/matcher_factory.py` — extended
|
||||
`build_matcher_strategy` to optionally forward `clock` + `fdr_client`
|
||||
to the strategy's `create`; older strategies that don't accept them
|
||||
remain unbroken.
|
||||
- `src/gps_denied_onboard/runtime_root/refiner_factory.py` — same
|
||||
extension for AdHoP / passthrough.
|
||||
- `src/gps_denied_onboard/fdr_client/records.py` — registered four
|
||||
new C3 matcher record kinds (`matcher.frame_done`,
|
||||
`matcher.backbone_error`, `matcher.insufficient_inliers`,
|
||||
`matcher.all_failed`) and one C3.5 refiner kind
|
||||
(`refiner.frame_done`).
|
||||
- `tests/unit/c3_5_adhop/test_protocol_conformance.py` — updated the
|
||||
AZ-348 AC-7 "AdHoP module not yet built" stop-gap to assert the
|
||||
module now imports AND that the factory raises `RefinerConfigError`
|
||||
when the weights path is missing (the AZ-349 cold-fail-fast
|
||||
behaviour).
|
||||
- `tests/unit/test_az272_fdr_record_schema.py` — added round-trip
|
||||
fixture payloads for all five new kinds.
|
||||
|
||||
## Task Results
|
||||
|
||||
| Task | Status | Files Modified | Focused tests | AC Coverage | Issues |
|
||||
|---------|--------|---------------------------|---------------|--------------|--------|
|
||||
| AZ-345 | Done | 5 added / 2 modified | 39/39 pass | 12/12 covered | None |
|
||||
| AZ-346 | Done | 4 added / 2 modified | 41/41 pass | 14/14 covered | None |
|
||||
| AZ-347 | Done | 2 added / 2 modified | 27/27 pass | 13/13 covered (AC-special-2 informational) | None |
|
||||
| AZ-349 | Done | 2 added / 2 modified | 23/23 pass | 11/11 covered | None |
|
||||
|
||||
## AC Test Coverage: 47/47 covered
|
||||
|
||||
(AZ-347 AC-special-2 latency benchmark is informational per spec and
|
||||
deferred to C3-PT-01 / E-BBT.)
|
||||
|
||||
## Code Review Verdict: PASS_WITH_WARNINGS
|
||||
|
||||
See `_docs/03_implementation/reviews/batch_57_review.md`. Three Low
|
||||
findings recorded; no Critical / High / Architecture findings. Auto-fix
|
||||
not required.
|
||||
|
||||
## Auto-Fix Attempts: 0
|
||||
|
||||
## Stuck Agents: None
|
||||
|
||||
## Next Batch
|
||||
|
||||
This concludes the C3 matcher + C3.5 refiner concrete-strategy track
|
||||
for cycle 1. The cumulative-review window (batches 55–57) is now due
|
||||
under the K=3 cadence.
|
||||
Reference in New Issue
Block a user