Files
gps-denied-onboard/_docs/03_implementation/batch_03_cycle1_report.md
T
Oleksandr Bezdieniezhnykh 3acc7f33dd [AZ-270] [AZ-272] [AZ-279] [AZ-281] [AZ-283] Compose root + FDR schema + 3 Layer-1 helpers
AZ-270: composition root with strategy registry, tier-gated lookup,
topo-order construction, all-or-nothing teardown, StrategyNotLinkedError
payload.
AZ-272: orjson-backed FdrRecord serialise/parse with forward-compat for
unknown payload + top-level fields and canonical overrun-record shape.
AZ-279: pyproj-backed WGS84/ECEF/ENU + OSM slippy-map tile math with
WgsConversionError for shape/range/zoom guards.
AZ-281: strict EngineFilenameSchema build/parse/matches_host with
anchored regex + enum validation; round-trip identity by construction.
AZ-283: dtype-preserving (fp16/fp32) single + batch L2 normaliser with
zero-norm safety and descriptor_metric() source-of-truth.
pyproject.toml pins pyproj>=3.6 and orjson>=3.9 (named-backend deps per
the AZ-272 / AZ-279 contracts). New DTOs LatLonAlt + BoundingBox and
EngineCacheKey + HostCapabilities land in _types/ to back the helper
contracts.
203 unit tests pass (64 new). Review verdict: PASS_WITH_WARNINGS;
findings are perf-NFR deferrals + dep amendment + minor docstring polish.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 02:03:36 +03:00

6.2 KiB

Batch Report — Cycle 1 · Batch 3

Tasks shipped: AZ-270, AZ-272, AZ-279, AZ-281, AZ-283 Date: 2026-05-11 Branch: dev Review verdict: PASS_WITH_WARNINGS — see reviews/batch_03_review.md

Tasks

ID Title Owner Layer Outcome
AZ-270 Composition Root cross-cutting / runtime_root.py Implemented — strategy registry, tier gating, topological-order construction, all-or-nothing teardown, StrategyNotLinkedError payload
AZ-272 FdrRecord Schema cross-cutting / fdr_client/records.py Implemented — orjson-backed serialise/parse, forward-compat for unknown payload + top-level fields, overrun-payload contract
AZ-279 WgsConverter Layer 1 / helpers/wgs_converter.py Implemented — pyproj-backed ECEF/ENU with hand-rolled OSM slippy-map tile math + WgsConversionError for shape / range / zoom guards
AZ-281 EngineFilenameSchema Layer 1 / helpers/engine_filename_schema.py Implemented — strict build/parse/matches_host with anchored regex + enum validation
AZ-283 DescriptorNormaliser Layer 1 / helpers/descriptor_normaliser.py Implemented — dtype-preserving single + batch L2 with zero-norm safety + descriptor_metric() source of truth

Files Changed

Modified:
  pyproject.toml                                            (+4 lines: pyproj, orjson pins)
  src/gps_denied_onboard/runtime_root.py                    (composition root impl)
  src/gps_denied_onboard/fdr_client/records.py              (full schema + serialiser)
  src/gps_denied_onboard/fdr_client/__init__.py             (re-exports)
  src/gps_denied_onboard/helpers/__init__.py                (re-exports)
  src/gps_denied_onboard/helpers/wgs_converter.py           (pyproj-backed converter)
  src/gps_denied_onboard/helpers/engine_filename_schema.py  (build/parse/matches_host)
  src/gps_denied_onboard/helpers/descriptor_normaliser.py   (L2 + zero-safe + dtype-preserving)
  src/gps_denied_onboard/_types/manifests.py                (EngineCacheKey, HostCapabilities)
  tests/unit/test_runtime_root_env_gate.py                  (updated to Config-typed compose_root)

Added:
  src/gps_denied_onboard/_types/geo.py                      (LatLonAlt, BoundingBox)
  tests/unit/test_az270_compose_root.py
  tests/unit/test_az272_fdr_record_schema.py
  tests/unit/test_az279_wgs_converter.py
  tests/unit/test_az281_engine_filename_schema.py
  tests/unit/test_az283_descriptor_normaliser.py
  _docs/03_implementation/reviews/batch_03_review.md

Test Results

$ pytest tests/unit -q --timeout=30
203 passed, 2 skipped in 2.60s

Skips are environment-gated (cmake configure, actionlint), both verified in CI.

AC Coverage

Task ACs declared ACs covered locally Tier-2 deferred
AZ-270 6 + 2 NFR 6 ACs + NFR-reliability (all-or-nothing) NFR-perf (compose_root ≤ 750 ms on Jetson)
AZ-272 6 + 2 NFR 6 ACs + NFR-reliability + invariant inline-blob NFR-perf (serialise p99 ≤ 20 µs, parse p99 ≤ 50 µs on Jetson)
AZ-279 9 + 2 NFR 9 ACs + determinism NFR-perf (≤ 200 µs each on Jetson)
AZ-281 11 + 2 NFR 11 ACs NFR-perf (≤ 50 µs each on Jetson)
AZ-283 12 + 2 NFR 12 ACs NFR-perf-vector (≤ 50 µs / D=512) + NFR-perf-batch (≤ 5 ms / N=1000, D=512)

Tier-2 perf budgets are owned by AZ-428..AZ-431; same deferral as batch 2. The batch-3 modules expose stable APIs so those tasks plug in without further code changes here.

Dependency Pins

This batch amended pyproject.toml with two new runtime pins required by AZ-272 and AZ-279 contracts:

  • pyproj>=3.6,<4.0 — WGS84 geodesy backend per AZ-279 contract
  • orjson>=3.9,<4.0 — FDR wire format per AZ-272 contract

Both names appear verbatim in the upstream contract documents and were the named-backend constraint. AZ-263 left these unpinned; the pins are added by the first batch that needs them — same pattern as batch 2.

Adjacent Hygiene

This batch added four new DTOs to _types/ because the AZ-279 / AZ-281 contracts explicitly import them from _types:

  • _types/geo.py (new file): LatLonAlt, BoundingBox
  • _types/manifests.py: EngineCacheKey, HostCapabilities

AZ-263 left these out; this batch closes the gap. No other helper or component depends on them yet, so the additions are forward-compatible.

The runtime_root.py signature change (compose_root()compose_root(config)) forced an update to tests/unit/test_runtime_root_env_gate.py (now passes Config() so the env-var fail-fast still fires). AC-8 of AZ-263 is intact.

Architecture Compliance

  • helpers/wgs_converter.py imports only numpy, pyproj, _types.geo, and stdlib. AC-9 AST scan verifies no components.* imports.
  • helpers/engine_filename_schema.py imports only re, _types.manifests, and stdlib. AC-11 AST scan verifies.
  • helpers/descriptor_normaliser.py imports only numpy + stdlib. AC-12 AST scan verifies.
  • fdr_client/records.py imports only orjson + stdlib + the dataclasses decorator. No upward imports.
  • runtime_root.py imports from gps_denied_onboard.config only (the composition root is permitted to consume the config loader). The AC-6 AST scan over every file under components/ confirms no cross-component imports exist (the registry is the only sanctioned cross-component reference path).

No new circular imports.

Review Findings Summary

Verdict: PASS_WITH_WARNINGS. Four Low-severity findings:

  1. Two engine-cache types coexist (EngineCacheEntry vs EngineCacheKey) — recommend a docstring sentence on each.
  2. NFR-perf microbenchmarks deferred to Tier-2 perf suite.
  3. pyproject.toml dep amendment (pyproj + orjson) — by the consumer batch as designed.
  4. AC-6 architecture lint lives in tests; future importlinter upgrade recommended once concrete components ship.

Full details in reviews/batch_03_review.md.

Tracker Transitions

  • AZ-270: To Do → In Progress → (batch close) In Testing
  • AZ-272: To Do → In Progress → (batch close) In Testing
  • AZ-279: To Do → In Progress → (batch close) In Testing
  • AZ-281: To Do → In Progress → (batch close) In Testing
  • AZ-283: To Do → In Progress → (batch close) In Testing