Files
gps-denied-onboard/_docs/03_implementation/batch_51_cycle1_report.md
T
Oleksandr Bezdieniezhnykh f6a180e5df [AZ-340] [AZ-527] Archive AZ-340 + batch 51 report + cumulative review 49-51
Bookkeeping for batch 51 close:

- Archive AZ-340 spec todo/ -> done/
- Add _docs/03_implementation/batch_51_cycle1_report.md
- Add _docs/03_implementation/cumulative_review_batches_49-51_cycle1_report.md
  Verdict: PASS_WITH_WARNINGS. F1 (Medium) escalates the 2-way
  _assert_engine_output_dim near-duplicate from cumulative-46-48 to a
  7-way duplication after AZ-339 + AZ-340; new hygiene PBI AZ-527
  formally created. F2 (Low) carries the AC-10 ConfigError vs literal
  ConfigurationError spec drift (documentation only).
- File AZ-527 hygiene PBI (Hygiene -- consolidate
  _assert_engine_output_dim into a c2-internal helper, 2pt, AZ-255
  E-C2). Add the spec stub at _docs/02_tasks/todo/AZ-527_*.md.
- Refresh _docs/02_tasks/_dependencies_table.md: +AZ-527 row, totals
  bumped to 148 tasks / 491 points.
- Bump _docs/_autodev_state.md: last_completed_batch=51,
  last_cumulative_review=batches_49-51.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 00:39:29 +03:00

7.2 KiB
Raw Blame History

Batch 51 — Implementation Report (Cycle 1)

Tasks: AZ-340 (C2 SelaVPR + EigenPlaces + SALAD Secondary Backbones — Research-only) Date: 2026-05-14 Cycle: 1 Status: COMPLETE (review verdict: PASS_WITH_WARNINGS, two Low findings)

What was done

Added three secondary VprStrategy implementations for IT-12 comparative-study: SelaVprStrategy (D=512, 224×224 input), EigenPlacesStrategy (D=2048, 480×480 input) and SaladStrategy (D=8448, 322×322 input — DINOv2-Large backbone, heaviest in the C2 family). All run via the C7 TensorRT runtime (or ONNX-Runtime fallback), apply ImageNet mean/std preprocessing + single-stage L2 normalisation, and delegate retrieval to FaissBridge. All three are gated OFF for airborne and operator-tooling per ADR-002 — BUILD_VPR_SELAVPR / BUILD_VPR_EIGENPLACES / BUILD_VPR_SALAD ON only for the research binary and replay-cli.

Files added (7)

File Purpose
src/gps_denied_onboard/components/c2_vpr/sela_vpr.py SelaVprStrategy class + create() factory + _assert_engine_output_dim helper
src/gps_denied_onboard/components/c2_vpr/_preprocessor_sela_vpr.py SelaVprBackbonePreprocessor (centre-crop + 224×224 resize + ImageNet normalise + FP16 NCHW)
src/gps_denied_onboard/components/c2_vpr/eigen_places.py EigenPlacesStrategy class + create() factory + _assert_engine_output_dim helper
src/gps_denied_onboard/components/c2_vpr/_preprocessor_eigen_places.py EigenPlacesBackbonePreprocessor (centre-crop + 480×480 resize + ImageNet normalise + FP16 NCHW)
src/gps_denied_onboard/components/c2_vpr/salad.py SaladStrategy class + create() factory + _assert_engine_output_dim helper
src/gps_denied_onboard/components/c2_vpr/_preprocessor_salad.py SaladBackbonePreprocessor (centre-crop + 322×322 resize + ImageNet normalise + FP16 NCHW)
tests/unit/c2_vpr/test_az340_sela_vpr_eigen_places_salad.py 54 parametrised AC tests across all three strategies

Files changed

  • None. The composition-root factory (runtime_root/vpr_factory.py) was already wired for sela_vpr, eigen_places, and salad strategy names at AZ-336 land time — _STRATEGY_TO_BUILD_FLAG and _STRATEGY_TO_MODULE tables already include the rows. The KNOWN_STRATEGIES frozenset in c2_vpr/config.py already includes all three. The module-layout.md Component: c2_vpr § Internal list already names sela_vpr.py, eigen_places.py, and salad.py (pre-declared by AZ-336). No CMake change required — BUILD_VPR_* gating is environment-variable-based per _is_build_flag_on in vpr_factory.py.

AC coverage

All 11 ACs verified per strategy via the parametrised test suite. See _docs/03_implementation/reviews/batch_51_review.md § Phase 2 for the AC ↔ test mapping table.

AC Status Notes
AC-1..AC-9 + AC-11 PASS Each AC parametrised over all three strategies (54 test cases total)
AC-10 PASS with drift Implementation raises StrategyNotAvailableError (env-flag OFF path) and ConfigError (runtime-label mismatch path); the spec literally names ConfigurationError. Mirrors the established AZ-337 / AZ-338 / AZ-339 precedent. Logged as Low finding F2.

Test results

  • tests/unit/c2_vpr/test_az340_sela_vpr_eigen_places_salad.py54 / 54 PASS.
  • tests/unit/c2_vpr/test_protocol_conformance.pyPASS (auto-extends across all 7 strategies after AZ-340; the three new ones are picked up by the parametrised _STRATEGY_MODULES table without test changes — verified by the full c2_vpr/ run below).
  • tests/unit/c2_vpr/ (full directory: faiss_bridge + net_vlad + ultra_vpr + AZ-339 + AZ-340 + protocol_conformance) — 180 / 180 PASS.
  • tests/unit/test_az508_iso_timestamps.py18 / 18 PASS (AZ-526 regression guard confirms no new _iso_ts_from_clock duplicates introduced by AZ-340).
  • tests/unit/test_az270_compose_root.py8 / 8 PASS.
  • ruff check on all 7 new files — clean (one auto-fixable RUF022 __all__ not sorted in _preprocessor_eigen_places.py was caught and fixed before commit).

Architectural decisions

  1. Single parametrised test file test_az340_sela_vpr_eigen_places_salad.py — rather than three near-identical files mirroring test_ultra_vpr.py / test_net_vlad.py. The three strategies share byte-identical behavioural contracts (same Protocol, same FDR record kinds, same log kinds, same error envelope) and differ only on three values (DESCRIPTOR_DIM, _BACKBONE_LABEL, preprocessor input_shape()). A parametrised approach keeps any future drift visible at the assertion level and reduces the test surface from ~2300 lines (three copies of test_ultra_vpr.py) to ~700 lines. Same precedent as AZ-339.
  2. Preprocessor duplication preserved (sela_vpr vs eigen_places vs salad vs mega_loc vs mix_vpr vs ultra_vpr vs net_vlad) — per components/02_c2_vpr/description.md § 6 and the task spec § Constraints. Each preprocessor owns its own input-shape constants so a future code drop can change a backbone's preprocessing without coupling other strategies' weights-versions.
  3. _assert_engine_output_dim duplicated, NOT extracted — see Spec Drift / Review Finding F1. The cleaner path is the dedicated AZ-527 hygiene PBI (now scoped to consolidate 7 copies, not 4).
  4. iso_ts_from_clock imported from the AZ-526 helper from day 1 — none of the three new strategies introduces a local _iso_ts_from_clock body. The AZ-526 regression guard test confirms this.
  5. Runtime-label guard placed inside create() (not in __init__) — runtime selection is a composition-time concern; once the strategy is constructed it's expected to work. Matches the UltraVPR / NetVLAD / MegaLoc / MixVPR precedent.
  6. SALAD's high embedding dim (8448) is non-negotiable at the strategy layer — it's the architectural output of the SALAD aggregator over DINOv2-Large patch tokens. PCA-whitening for a smaller SALAD descriptor is an operator-side decision at corpus build time (C10), gated by a future BUILD_VPR_SALAD_PCA build flag (out of scope here).

Spec drift noted (carried into review F2)

AZ-340 § AC-10 literally specifies ConfigurationError for the build-flag-OFF case. The existing AZ-336 composition-root factory raises StrategyNotAvailableError for this case (per its own contract and test coverage at test_protocol_conformance.py). The strategy module's own runtime-label guard raises ConfigError for the related "wrong C7 runtime" case. AZ-337 / AZ-338 / AZ-339 followed this same pattern; AZ-340 mirrors them. AC-10 wording should be amended in a future shared spec-pass touching AZ-337..AZ-340; no code change required.

Cumulative review obligation

This batch closes the K=3 cumulative-review window for batches 4951 (last cumulative review covered batches 46-48). The cumulative review for batches 4951 runs immediately after this batch report lands, before batch 52 starts.

Follow-on PBI

AZ-527 (Hygiene — consolidate _assert_engine_output_dim into a c2-internal helper). 2 points. Now must consolidate 7 copies (was 4 before AZ-339, became 4 again after AZ-339, now 7 after AZ-340). Depends on AZ-340. To be created and prioritised by the cumulative review for batches 49-51 (about to run).