Batch 48 / Cycle 1 (greenfield Step 7). Closes cumulative review batches 31-33 F2 and 28-30 F3 by replacing the duplicated private _iso_ts_now() one-liners with a single Layer-1 helper: src/gps_denied_onboard/helpers/iso_timestamps.py iso_ts_now() -> str Output format matches the canonical FDR _TS fixture (YYYY-MM-DDTHH:MM:SS.ffffffZ); no FDR schema change. Migrated call-sites (3): c7_inference/onnx_trt_ep_runtime, c7_inference/thermal_publisher, plus the 3 c6_tile_cache callers that previously imported from the local c6_tile_cache/_timestamp shim (now deleted, superseded by the Layer-1 helper). Spec drift resolved (Choose A, user-approved): spec listed 5 call sites + +00:00 regex; on-disk reality at batch start is 3 sites + Z-suffix matching every existing helper and the FDR _TS fixture. Spec preamble + AC-2 regex updated in the task file; documented in batch_48_cycle1_report.md. Tests: 9 new AC tests (AC-1..AC-7 + Layer-1 invariant + public-surface defensive); 216 focused tests pass including the unmodified AZ-272 FDR schema suite and AZ-270 / AZ-507 layering lints. Verdict: PASS (no findings). Co-authored-by: Cursor <cursoragent@cursor.com>
11 KiB
Batch 48 / Cycle 1 — Implementation Report
Date: 2026-05-13 Tasks: AZ-508 — ISO-timestamp helper consolidation (2pt) Total complexity: 2 points Result: PASS (per-batch code review) Jira tracker state: AZ-508 transitioned To Do → In Progress (prior session) → In Testing (this batch)
Scope
Hygiene PBI from cumulative reviews batches 28–30 (Finding F3) and
batches 31–33 (Finding F2). Consolidates the duplicated private
_iso_ts_now() one-liners across c6_tile_cache and c7_inference
into a single Layer-1 helper at
src/gps_denied_onboard/helpers/iso_timestamps.py (iso_ts_now() -> str,
RFC 3339 UTC microsecond Z-suffix). Closes F2 before the upcoming
C2 batches (AZ-339 / AZ-340) and the C4/C3 batches (AZ-358 / AZ-349)
would have added the 8th and 9th copies of the helper.
Spec Drift Resolution (User-Approved Choose A)
The task spec assumed:
- 5 call-sites needing migration.
- AC-2 format regex
\.\d{6}\+00:00$. - "FDR records standardize on
+00:00pertest_az272_fdr_record_schema.py".
On-disk reality at Batch 48 start:
- 3 call-sites: c6's three callers had already been locally
consolidated under
src/gps_denied_onboard/components/c6_tile_cache/_timestamp.py(exportiso_ts_now, sameZ-suffix format);tensorrt_runtime.pycarries no local_iso_ts_nowdefinition. - All 3 existing helpers produce
%Y-%m-%dT%H:%M:%S.%fZ(Zsuffix). - The canonical FDR
tsfixture is_TS = "2026-05-11T00:00:00.000000Z"(alsoZsuffix). The+00:00strings in that test file belong to other DTO fields (manifestgenerated_at_iso,observed_at_iso), not the FDRtsenvelope.
Picking the spec's +00:00 literally would have silently changed FDR
record ts bit-shape — explicitly Excluded by the spec ("no schema
change") and would have broken AC-5 (FDR schema tests pass unmodified).
User selected Choose A: Z-format helper, byte-identical to existing
3 helpers + FDR _TS fixture; AC-2 regex corrected in the spec; drift
documented in this report and in the spec's preamble.
Files Changed
Production (new)
src/gps_denied_onboard/helpers/iso_timestamps.py—iso_ts_now() -> str. Stateless free function; stdlibdatetime+timezoneonly; formatdatetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%fZ").
Production (modified)
src/gps_denied_onboard/helpers/__init__.py— re-exportsiso_ts_nowthrough the helpers package facade (alphabetical insertion in both the import block and__all__).src/gps_denied_onboard/components/c6_tile_cache/cache_budget_enforcer.py— import pathc6_tile_cache._timestamp→helpers.iso_timestamps(one-line edit; call-sites untouched).src/gps_denied_onboard/components/c6_tile_cache/postgres_filesystem_store.py— same path swap (2 call-sites untouched).src/gps_denied_onboard/components/c6_tile_cache/freshness_gate.py— same path swap (2 call-sites untouched).src/gps_denied_onboard/components/c7_inference/onnx_trt_ep_runtime.py— removed localdef _iso_ts_now; added top-of-filefrom gps_denied_onboard.helpers.iso_timestamps import iso_ts_now as _iso_ts_now(preserves the_iso_ts_nowsymbol at 2 call-sites); removed the now-unusedfrom datetime import datetime, timezone.src/gps_denied_onboard/components/c7_inference/thermal_publisher.py— same pattern (1 call-site preserved); removed the now-unusedfrom datetime import datetime, timezone.
Production (deleted)
src/gps_denied_onboard/components/c6_tile_cache/_timestamp.py— the c6-internal consolidation shim is no longer needed; the three c6 callers now import directly fromhelpers.iso_timestamps. The Layer-1 helper supersedes the Layer-2 component-local one.
Tests (new)
tests/unit/test_az508_iso_timestamps.py— 9 tests:test_ac1_import_and_call_returns_str(AC-1)test_ac2_format_matches_canonical_regex(AC-2 format)test_ac2_fromisoformat_roundtrip_yields_utc_aware_datetime(AC-2 parseability)test_ac3_two_successive_calls_are_non_decreasing(AC-3)test_ac4_no_other_iso_ts_now_definition_exists_in_src(AC-4 AST-walk oversrc/)test_ac4_c6_and_c7_callers_import_from_helpers(AC-4 explicit call-site sweep — 5 files)test_ac6_helper_uses_stdlib_only(AC-6, stdlib whitelist)test_helper_is_layer_1_no_component_imports(Constraint § Layer-1 discipline)test_helper_public_surface_is_minimal(defensive:__all__is exactly["iso_ts_now"])
Docs (modified)
_docs/02_document/module-layout.md— appended### shared/helpers/iso_timestampsrow to the helpers section._docs/02_tasks/todo/AZ-508_hygiene_iso_timestamps_consolidation.md— drift note added to the description; AC-2 regex corrected from\+00:00$toZ$._docs/03_implementation/reviews/batch_48_review.md(new) — per-batch code review (PASS)._docs/_process_leftovers/2026-05-11_d_cross_cve_1_opencv_pin_deferred.md— replay-attempt timestamp + reason updated (PyPI showsgtsam==4.2.1butrequires_dist: numpy<2.0.0; block unchanged).
Acceptance Criteria Coverage
| AC | Description | Status | Test |
|---|---|---|---|
| AC-1 | Helper exists, importable, callable, returns str |
PASS | test_ac1_import_and_call_returns_str |
| AC-2 | Format regex match + fromisoformat round-trip |
PASS | test_ac2_format_matches_canonical_regex, test_ac2_fromisoformat_roundtrip_yields_utc_aware_datetime |
| AC-3 | Lexicographic monotonicity under normal clock | PASS | test_ac3_two_successive_calls_are_non_decreasing |
| AC-4 | All call sites migrated; no stray definitions | PASS | test_ac4_no_other_iso_ts_now_definition_exists_in_src, test_ac4_c6_and_c7_callers_import_from_helpers |
| AC-5 | FDR schema tests pass unmodified | PASS | tests/unit/test_az272_fdr_record_schema.py runs unchanged (35 tests pass) |
| AC-6 | No new third-party dependencies | PASS | test_ac6_helper_uses_stdlib_only + pyproject.toml unchanged |
| AC-7 | AZ-270 layering lint passes | PASS | tests/unit/test_az270_compose_root.py::test_ac6_only_compose_root_imports_concrete_strategies |
Test Results
- Focused suite (tests/unit/test_az508_iso_timestamps.py + test_az272_fdr_record_schema.py + tests/unit/c6_tile_cache/ + tests/unit/c7_inference/): 216 passed, 53 environment-skipped, 0 failed in 7.97s. Environment-gated skips (Docker compose for c6 integration, CUDA / TensorRT / Jetson hardware for c7) — unchanged from Batch 47.
- Focused per-helper: 9/9 new AZ-508 tests PASS in 1.36s.
- Layering lint: AZ-270 + AZ-507 lints PASS (no cross-component import violations introduced).
- Lint:
ruff checkclean on every file authored or modified by this batch. 3 pre-existing ruff findings (B905, RUF022, RUF023) inonnx_trt_ep_runtime.pyleft untouched percoderule.mdc"fix pre-existing lints only if in the modified area".
Architectural Decisions
-
Layer-1 helper supersedes the c6 internal
_timestamp.py. The c6-internal consolidation shipped earlier (cumulative review 28–30 F3) was a Layer-2 stop-gap pending the cross-component consolidation. With the Layer-1 helper now in place, the c6 shim is redundant and was deleted; the three c6 callers now import the cross-component helper directly. This collapses two abstractions into one. -
Preserve
_iso_ts_nowsymbol at c7 call-sites via import alias. The c7 modules each have 1–2 in-method_iso_ts_now()call-sites. Rather than edit every call-site, the new module-levelfrom gps_denied_onboard.helpers.iso_timestamps import iso_ts_now as _iso_ts_nowkeeps the local symbol name unchanged → minimal diff per c7 file and minimal risk of accidentally missing a call-site. Matches the task spec's preferred form (Scope § Included bullet 2). -
Stdlib-only helper, no Clock dependency. The helper is wall-clock metadata about when an FDR record envelope was emitted — explicitly NOT a payload field that might need an injectable Clock for tests. The task spec calls this out (Excluded § "Any change to flight_clock / wall_clock"), and the new module docstring reiterates it so future contributors do not route
age_seconds-style fields through it. -
AST-walk AC-4 test instead of a grep gate. AC-4 originally contemplated a CI-level
grep -rn "def _iso_ts_now" src/gate. The in-repo test intest_az508_iso_timestamps.pyuses an AST walk instead — it catches bothdef _iso_ts_nowANDdef iso_ts_nowdefined anywhere outside the helper, with file paths in the assertion message, and runs as part of the standard unit suite (no separate CI hook needed). The same test also enforces the consumer-side import discipline so the regression surface is "the import or the test breaks", not "a stray definition lingers".
Carried-over Findings (from prior batches)
- F1 from cumulative review 43–45 / Batch 46 / Batch 47: closed by
this batch.
_iso_ts_nowis now in exactly one place. - F2 from Batch 46 / Batch 47 (spec→impl drift on C7 API names for AZ-339 / AZ-340 / AZ-358 / AZ-349): NOT addressed in this batch; belongs to a spec-hygiene PBI to be filed before AZ-339 starts.
- D-CROSS-CVE-1 opencv pin leftover: replay attempted at Batch 48
bootstrap; PyPI shows
gtsam==4.2.1(newer than 4.2 referenced in the leftover) but still pinsnumpy<2.0.0. Block unchanged; leftover timestamp updated.
New Findings (per Batch 48 code review)
None.
Jira Tracker
- AZ-508 was already
In Progressat Batch 48 start (transitioned in a prior/autodevsession per the state file). Read-back viagetJiraIssueconfirmedstatus.name == "In Progress"before any source edits. Will transitionIn Progress → In Testingafter this batch's commit lands. - Task spec archived to
_docs/02_tasks/done/AZ-508_hygiene_iso_timestamps_consolidation.mdas part of the implement skill Step 13.
Next
With AZ-508 closed, the carried-over F1 from batches 43–47 is resolved and the next C2 / C4 / C3 batches can ship without re-adding the helper. Top Batch 49 candidates (per Batch 47's "Next" list, updated):
- AZ-339 — MegaLoc + MixVPR strategies (5pt). Same skeleton as UltraVPR (B47) but two strategies; F2 spec-hygiene PBI may want to ship first.
- AZ-340 — SelaVPR + EigenPlaces + SALAD strategies (5pt). Closes the C2 alternative-backbone buffet.
- AZ-358 — C4 OpenCV/GTSAM pose estimator (5pt). Changes pace from C2-heavy streak; opens C4.
- AZ-389 — C5 internal orthorectifier for mid-flight tiles (3pt).
- Spec-hygiene PBI for F2 (C7 API drift in AZ-339 / AZ-340 / AZ-358 / AZ-349 specs) — strongly recommended before AZ-339.
Per autodev orchestrator: Batch 48 is the third batch since the last cumulative review (batches 43–45). The implement skill Step 14.5 triggers a cumulative review batches 46–48 before Batch 49 starts.