Option A (minimum-deprecation, 2 SP) per user complexity-budget decision. Auto-sync stays importable as a raising stub for one cycle so external callers see a clean ReplayInputAdapterError instead of an ImportError. Full physical removal is filed as AZ-908 (cycle-5+ backlog). Production: - auto_sync.py: 700+ LOC -> 56-line no-op stub raising "auto-sync removed; supply --imu CSV instead" - tlog_video_adapter.py: 700+ LOC -> 105-line deprecated stub; ReplayInputAdapter.open() raises immediately, close() is a no-op - _replay_branch.py: dropped legacy auto-sync branch + _build_auto_sync_config; _validate_replay_paths now requires imu_csv_path; replay_input_adapter_factory parameter removed - cli/replay.py: --time-offset-ms / --skip-auto-sync / --auto-trim emit DeprecationWarning + stderr line; values ignored - tlog_replay_adapter.py + tlog_ground_truth.py docstrings: AUDIT-ONLY Tests: - DELETED test_az405_auto_sync, test_az405_replay_input_adapter, test_az698_window_alignment (covered code no longer runs) - ADDED test_az895_auto_sync_deprecated_stub (5 parametrised, pins AC-1) - test_az402_replay_cli: deprecation warnings + ignored-value asserts - test_az401_compose_root_replay: new imu_csv_path-required gate; deleted the calibration-loading test that relied on the removed replay_input_adapter_factory injection point - test_derkachi_real_tlog: xfail reason refreshed to AZ-848 + AZ-883 (AC-4 "AZ-848-scoped reason") Docs: - module-layout.md: replay_input file list flags deprecated modules, adds csv_ground_truth.py - _dependencies_table.md: +AZ-908 row, preamble + totals updated (179 -> 180 tasks, 567 -> 570 SP) - AZ-908 backlog spec added; AZ-895 spec moved todo -> done - batch_03_cycle4_report.md written Touched-module tests green (111 passed, 1 skipped). Full unit suite green: 2287 passed, 85 skipped, 1 deselected (pre-existing flaky perf test, unrelated). Co-authored-by: Cursor <cursoragent@cursor.com>
12 KiB
Batch Report — cycle 4, batch 03
Batch: 03 Cycle: 4 Tasks: AZ-895 Total complexity: 2 SP Date: 2026-05-26 Commit: pending (this batch)
Task Selection
AZ-895 (deprecate auto_sync surface) ships solo. It is the natural
follow-up to AZ-894 (CSV adapter, batch 02): now that the CSV-driven
path is the primary replay surface, the legacy tlog auto-sync
infrastructure can be retired. Per _dependencies_table.md, AZ-895
has a hard dependency on AZ-894 which closed in batch 02.
Complexity-budget user decision (Option A — minimum)
A naïve full removal of the auto-sync surface would have touched:
- 4 production modules:
auto_sync.py(delete),tlog_video_adapter.py(delete),interface.py(drop AutoSync DTOs +ReplayInputBundlefield),_replay_branch.py(strip legacy branch +_build_auto_sync_config) - 3 config files:
config/schema.py(dropReplayConfigauto-sync fields + theReplayAutoSyncConfigclass),config/loader.py(dropREPLAY_TIME_OFFSET_MSenv + auto_sync block handler),config/__init__.py(drop re-exports) - 1 CLI: drop the three deprecated flags entirely
- 4 test files needing rewrite or deletion
- Cascading docs in
replay_protocol.md(AZ-842 sibling work)
Estimated at 4–5 SP, well over the ticket's 2 SP budget. Per
meta-rule.mdc Complexity Budget Check, the user was offered four
options and chose Option A — minimum:
"Minimum (~2 SP): no-op-stub auto_sync.py (raises documented error), strip tlog_video_adapter.open() to raise too, drop the unreachable legacy branch in _replay_branch.py, deprecate --time-offset-ms / --skip-auto-sync / --auto-trim CLI flags (emit warning + ignored), keep config fields, delete obsolete tests, update docstrings. File AZ-902 (cycle 5) for hard surface removal."
The follow-up ticket was filed as AZ-908 (Jira renumbered from the
proposed AZ-902 because AZ-902–AZ-907 were already taken). AZ-908 is
in backlog/ and depends on AZ-895 + AZ-842.
Task Results
| Task | Status | Files Modified | Tests | AC Coverage | Issues |
|---|---|---|---|---|---|
| AZ-895_deprecate_auto_sync_surface | Done | 8 modified, 1 added (test) | 3 unit-test files deleted; 1 new test added; 1 existing test file updated; 2,287 unit tests green | 5/5 | None |
Files touched
Production (src/gps_denied_onboard/**):
- REPLACED
replay_input/auto_sync.py— was a 700+ LOC detector module; now a 56-line no-op stub whose every public callable raisesReplayInputAdapterError("auto-sync removed; supply --imu CSV instead").__all__preserved so any external import still resolves. - REPLACED
replay_input/tlog_video_adapter.py— was a 700+ LOC coordinator; now a 105-line deprecated-stub that keeps theReplayInputAdapterclass signature for source-compat.open()raisesReplayInputAdapterError(...)immediately;close()is a no-op. Re-exportsReplayPaceso_replay_branch.pycan continue to import it from the same path (preserving the AZ-401 AC-8 import boundary). - MODIFIED
runtime_root/_replay_branch.py— removed the legacyReplayInputAdapterinstantiation branch in_build_replay_input_bundle; deleted the_build_auto_sync_confighelper; tightened_validate_replay_pathsto requireimu_csv_path(no more tlog fallback); dropped unusedWgsConverterandAutoSyncConfigimports; removed thereplay_input_adapter_factorytest-injection parameter; updated module + function docstrings; cleanedauto_sync_usedfrom the ready-log kv (always None now). - MODIFIED
replay_input/__init__.py— docstring rewritten to flag the deprecation status of thetlog_video_adapter/auto_syncsurfaces. Re-exports preserved. - MODIFIED
cli/replay.py—--time-offset-ms,--skip-auto-sync,--auto-trimhelp text replaced withDEPRECATED (AZ-895)notice;_print_startup_bannernow emits aDeprecationWarning+ stderr line when any of the three are non-default;_build_replay_confighard-codes the correspondingReplayConfigfields to None / False so the deprecated values cannot influence composition. - MODIFIED
components/c8_fc_adapter/tlog_replay_adapter.py— module docstring reframed as AUDIT-ONLY (AC-5). Code unchanged. - MODIFIED
replay_input/tlog_ground_truth.py— module docstring reframed as AUDIT-ONLY (AC-5). Code unchanged.
Tests (tests/**):
- DELETED
tests/unit/replay_input/test_az405_auto_sync.py(386 LOC). Rationale: tested the AZ-405 detector algorithm + AC-9 validator which no longer execute. Per AC-3, the deprecation-stub test below replaces it. - DELETED
tests/unit/replay_input/test_az405_replay_input_adapter.py(645 LOC). Rationale: tested theReplayInputAdaptercoordinator's six-stepopen()workflow which now raises immediately. - DELETED
tests/unit/replay_input/test_az698_window_alignment.py(745 LOC). Rationale: tested the AZ-698 IMU↔optical-flow cross-correlation aligner which no longer executes. - ADDED
tests/unit/replay_input/test_az895_auto_sync_deprecated_stub.py— 5 parametrised tests pinning the AC-1 contract: every public callable raisesReplayInputAdapterErrorwith the documented message. - MODIFIED
tests/unit/test_az402_replay_cli.py— renamedtest_ac4_time_offset_forwarded→test_ac4_time_offset_ignored_after_az895with asserts inverted (value nowNoneregardless of flag); addedtest_az895_skip_auto_sync_ignored_and_warned,test_az895_auto_trim_ignored_and_warned,test_az895_no_deprecated_flags_no_warning;_argvhelper grewskip_auto_syncandauto_trimoverrides. - MODIFIED
tests/unit/test_az401_compose_root_replay.py— renamedtest_replay_branch_rejects_both_inputs_empty→test_replay_branch_rejects_missing_imu_csv_pathwith body updated to the new gate semantics;_make_replay_confighelper now setsimu_csv_pathby default; deletedtest_replay_branch_loads_camera_calibration_from_runtime_path(only verified the now-removedreplay_input_adapter_factoryinjection path; calibration loading is exercised indirectly by the full compose-root tests and by the e2e suite). - MODIFIED
tests/e2e/replay/test_derkachi_real_tlog.py— xfail reason text refreshed to reference AZ-848 + AZ-883 (the live tlog-clock root cause) instead of the closed AZ-776 + AZ-777 (AC-4 literally specifies "AZ-848-scoped reason").
Docs (_docs/**):
- MODIFIED
_docs/02_document/module-layout.md—replay_inputfile list flagstlog_video_adapter.py+auto_sync.pyas DEPRECATED (AZ-895), addscsv_ground_truth.py, updates the package purpose to lead with the CSV path. - ADDED
_docs/02_tasks/backlog/AZ-908_replay_auto_sync_hard_removal.md— cycle-5+ follow-up spec. - MODIFIED
_docs/02_tasks/_dependencies_table.md— preamble + Total Tasks (179 → 180) + Total Complexity (567 → 570); AZ-908 row added under Cycle-4 / AZ-895 follow-up.
Tracker (Jira):
- AZ-895 — transitioned
To Do→In Progress(transition id21). - AZ-908 — created (
Replay: hard removal of deprecated auto-sync surface (AZ-895 follow-up)), 3 SP estimate, deps AZ-895 (hard) + AZ-842 (hard). Filed viacreateJiraIssueMCP.
File-Ownership Note
All touched paths are owned by the cycle-4 replay-input redesign
envelope (replay_input/ + cli/replay.py + runtime_root/_replay_branch.py)
plus the AC-5 audit-only docstring updates inside
components/c8_fc_adapter/tlog_replay_adapter.py (the c8 owner
already accepted the audit-only reframing in AZ-894). No
out-of-scope edits.
AC Test Coverage
| AC | Coverage | Test |
|---|---|---|
AC-1 (auto_sync.py is deleted or made a no-op raising the documented error) |
Direct | tests/unit/replay_input/test_az895_auto_sync_deprecated_stub.py::test_az895_public_callable_raises_with_documented_message[*] — 5 parametrised cases, one per public symbol (detect_tlog_takeoff, detect_video_motion_onset, compute_offset, validate_offset_or_fail, find_aligned_window); each asserts ReplayInputAdapterError("auto-sync removed; supply --imu CSV instead") |
| AC-2 (CLI flags removed or marked deprecated with one-cycle warning) | Direct | test_az402_replay_cli.py::test_ac4_time_offset_ignored_after_az895, ::test_az895_skip_auto_sync_ignored_and_warned, ::test_az895_auto_trim_ignored_and_warned, ::test_az895_no_deprecated_flags_no_warning — assert DeprecationWarning is emitted, the stderr banner contains the documented --flag is deprecated (AZ-895) text, the value is ignored on the ReplayConfig, and the no-flag baseline emits no warning |
AC-3 (test_az405_auto_sync tests pass against the new behaviour or are deleted with rationale recorded in the batch report) |
Direct (rationale below) | Deleted; rationale: the AZ-405 tests covered the detector algorithm + AC-9 validator which AZ-895 makes unreachable. Replaced by the AC-1 deprecation-stub test above |
AC-4 (test_derkachi_real_tlog.py continues to @xfail with the AZ-848-scoped reason) |
Direct | tests/e2e/replay/test_derkachi_real_tlog.py::test_az699_real_flight_validation_emits_verdict_and_report — @pytest.mark.xfail decorator retained; reason text now names AZ-848 + AZ-883 as the live blocker |
AC-5 (module docstrings of tlog_replay_adapter.py and tlog_ground_truth.py updated to call out their new audit-only roles) |
Direct | Manual: both module docstrings now lead with AUDIT-ONLY (AZ-895) and explain the demotion; verified by inspection at the head of each file |
Test-Run Summary
- Touched-module focused suite: 111 passed, 1 skipped (RUN_REPLAY_E2E gate, expected).
- Full unit suite: 2,287 passed, 85 skipped (hardware/Docker gates),
1 deselected (the timing-flaky perf test
test_cli_console_script.py::TestConsoleScript::test_cold_start_under_1000ms_p99— unrelated to this batch, pre-existing).
Open Items → AZ-908 (cycle-5+ backlog)
The deferred hard-removal surface (full spec in
_docs/02_tasks/backlog/AZ-908_replay_auto_sync_hard_removal.md):
- Delete
replay_input/auto_sync.py+replay_input/tlog_video_adapter.py. - Drop
AutoSyncConfig/AutoSyncDecision/AlignedWindowDTOs +ReplayInputBundle.auto_sync_result/aligned_windowfields. - Drop the three deprecated CLI flags + their tests.
- Drop
ReplayConfig.time_offset_ms/.skip_auto_sync_validation/.auto_trim/.auto_sync+ReplayAutoSyncConfigclass. - Drop
BUILD_TLOG_REPLAY_ADAPTERbuild flag fromREPLAY_BUILD_FLAGS. - Coordinate with AZ-842 to remove the auto-sync surface narrative
from
replay_protocol.md.
Lessons Captured
- The user-decision Choose A/B/C/D flow worked exactly as designed: the agent surfaced the budget overrun before writing code, the user picked the minimum path with a clear follow-up ticket, and the batch shipped within its SP budget.
- Keeping deprecated symbols as raising stubs (rather than deleting
them outright in this cycle) gives operators one cycle of upgrade
signal: they import the same name, get a clean
ReplayInputAdapterErrorwith a "supply --imu CSV instead" hint, and have aDeprecationWarningto silence in any test fixtures. - Architectural lint (
test_ac8_replay_branch_imports_only_public_apis) caught a mid-batch attempt to importReplayPacedirectly from the c8 internals — the lint forces the import to go through the documented re-export path (replay_input.tlog_video_adapter). Even though that re-export sits inside a deprecated module, the lint's allow-list is the architectural contract; routing around it would have been the wrong fix.