Files
pluriwave/openspec/changes/archive/2026-07-20-android-auto-local-music-phase3/archive-report.md
T
FreeTLab 49def4b276
Build & Deploy PluriWave / Análisis de código (push) Successful in 28s
Build & Deploy PluriWave / Build APK + AAB release (push) Failing after 1m18s
docs(openspec): archive android-auto-local-music-phase3
Merges its delta requirements into the android-auto-media base spec.
Completes the 3-phase local-music-in-Android-Auto feature. Standing
pre-release gate: on-device/DHU validation of every native surface
built across all 4 phases (SAF picking, metadata extraction, art
cache, queue/shuffle handler wiring) is still outstanding.
2026-07-20 01:15:46 +02:00

13 KiB

Archive Report: android-auto-local-music-phase3

Archived: 2026-07-20 (completion of entire 3-phase local-music feature)

Change Status: CLOSED — Verified PASS WITH WARNINGS, committed to main (git commit dfd40ca), implementation complete.

Executive Summary

Phase 3 of the local-music-in-Android-Auto feature — folder-scoped queue playback with shuffle and transport control wiring — is COMPLETE, verified, and archived. This change completes the entire planned 3-phase local-music feature. No further phases are planned. All 4 archived changes (Phase 1 + Paging Fast-Follow + Phase 2 + Phase 3, all dated 2026-07-19 and 2026-07-20) are now closed; the feature is ready for pre-release gate validation and eventual production release.

Phase 3 Implementation Outcome

Status

  • Verification Verdict: PASS WITH WARNINGS (0 CRITICAL issues, 3 WARNINGS, 1 SUGGESTION)
  • Test Results: 181/181 tests passed (0 failures)
  • Regression Gate: 4 pre-existing radio/reconnect test suites (21 total tests) BYTE-FOR-BYTE UNTOUCHED — identical pass counts (8/5/3/5 = 21) before and after, zero regression
  • Commit: dfd40ca on main, tagged [size:exception] per user's explicit informed choice (highest-risk change of session)
  • Delivered: Single PR, ~1400+ lines (prod 470, tests 950)

Key Achievement — Regression Isolation Proven

The highest-risk aspect of this change — modifying PluriWaveAudioHandler's event listeners and adding a queue auto-advance mechanism alongside a live-stream reconnection state machine — was isolated via a strict mode boundary (_colaLocal != null is the ONLY gate). The proof:

  1. Static proof: git diff --stat shows ZERO lines changed in _cambiarFuente, ControladorReconexion usage, _esErrorDeRed, _gestionarErrorReproduccion, _intentarReconexion, _reintentarFuente.
  2. Test proof: The 4 protected regression test suites (servicio_audio_reconnect_test.dart, servicio_audio_session_test.dart, servicio_audio_source_switch_test.dart, servicio_audio_eq_reapply_test.dart) are BYTE-FOR-BYTE UNTOUCHED — not merely "same pass count", but identical file contents and identical test results.
  3. Functional proof: playMediaItem, the public entry point for all external play actions (radio stations, groups, single tracks), unconditionally clears _colaLocal = null; _avanzandoCola = false FIRST before any handler mutation, guaranteeing zero queue leakage into radio playback.

This is the single strongest assurance available in this environment (static-review-only, no DHU/on-device testing) that radio playback is provably untouched.

Feature Completion — All 3 Phases Archived

Timeline of Archived Changes

  1. Phase 1 (2026-07-19): SAF folder pick, lazy per-level traversal, placeholder art, single-track browse + play
  2. Paging Fast-Follow (2026-07-19): On-demand pagination (replacing 50-item silent truncation)
  3. Phase 2 (2026-07-19): Embedded metadata, LRU cache, quality sort, name buckets, album art
  4. Phase 3 (2026-07-20): Folder-scoped queue, sequential/shuffled play, auto-advance, transport skip, mode isolation

Result: The local-music-in-Android-Auto feature is FEATURE-COMPLETE. Drivers can:

  • Browse a local folder hierarchy in the car
  • See real track metadata (title, album art) via embedded extraction
  • Sort/filter tracks by name and quality
  • Play a folder's tracks sequentially or shuffled
  • Use car next/previous controls to navigate the queue
  • Auto-switch between local queue and live radio with clean mode transitions

Out of scope by design (not promised, explicitly deferred):

  • Recursive whole-subtree queueing (direct children only per folder)
  • OS shuffle toggle (browsable action only, not AudioService.setShuffleMode)
  • Repeat modes, persisted/resumable queues, queue-reordering UI

Standing Pre-Release Gate — On-Device / DHU Validation Required

CRITICAL STANDING RISK applying to ALL FOUR archived changes:

None of the native Android Auto surfaces built in this session have been runtime-verified on a real Android Auto head unit or Desktop Head Unit (DHU). All of it is static-review-only or unit-tested-via-extraction:

  1. SAF folder picking (Phase 1): SAF API usage, permission persistence, DocumentFile traversal — no runtime test
  2. Native metadata extraction (Phase 2): MediaMetadataRetriever.getMetadata(), readAudioMetadataBatch — extraction logic unit-tested locally, but device behavior untested
  3. FileProvider art cache (Phase 2): Static cache file serving, no device test
  4. Queue/shuffle handler wiring + transport controls (Phase 3): ProcessingState.completed firing, car next/previous button presses, queue advance behavior — static-review-only, no device test

Pre-release sign-off MUST include:

  • Dedicated on-device QA pass on a real head unit or DHU
  • Validation of all four surfaces (SAF pick, metadata display, album art, queue advance/skip)
  • End-to-end testing of: single-track play, folder sequential play, folder shuffled play, auto-advance to next track, skip via car controls, radio-to-queue and queue-to-radio mode transitions
  • Confirmation that no regressions to radio playback, reconnect, or EQ signal chain occur

This is non-negotiable before production release. The environment constraint (no DHU/on-device testing available during SDD execution) is documented and accepted; the risk is real and does not diminish with code review alone.

Artifacts Merged into Base Specification

The base Android Auto Media specification (openspec/specs/android-auto-media/spec.md) now includes 6 new requirements from Phase 3's delta spec:

  1. Folder-Scoped Sequential Play Action — "Reproducir carpeta" prepended on page 0 of folders with audio files
  2. Folder-Scoped Shuffled Play Action — "Reproducir aleatorio" alongside sequential, deterministically seeded
  3. Local Queue Auto-Advance and Transport Skip — handler auto-advances on track completion, skipToNext/skipToPrevious move within queue
  4. Local Queue Mode Isolation From Radio Playback (Regression Guard — CRITICAL)_colaLocal nullability is the sole gate; mode boundaries prevent leakage
  5. Local Queue End-of-Queue Behavior — clean stop with no wraparound on last track
  6. New Action Media-IDs Are Collision-Freecarpeta_local_reproducir: and carpeta_local_aleatorio: collision-proven against all 8 existing prefixes

Change Artifacts

Artifact Location Notes
Proposal archive/2026-07-20-android-auto-local-music-phase3/proposal.md Honest scope reconciliation, single queue foundation feature, rationale for avoiding ConcatenatingAudioSource
Design archive/2026-07-20-android-auto-local-music-phase3/design.md 6 ADRs, mode isolation via _colaLocal nullability, Fisher-Yates shuffle, file changes
Tasks archive/2026-07-20-android-auto-local-music-phase3/tasks.md 26-item executable checklist (24 completed, 6.1 manual follow-up, 6.2 N/A), phases 0-5
Apply Progress archive/2026-07-20-android-auto-local-music-phase3/apply-progress.md 181/181 tests passed, 4 protected suites byte-identical, 4 deviations disclosed, risks for verify phase
Verify Report archive/2026-07-20-android-auto-local-music-phase3/verify-report.md Verdict PASS WITH WARNINGS, priority investigations confirmed, 3 WARNINGs (static-review-only handler wiring, flutter analyze deferred, single-PR size:exception, DHU validation gate), 1 SUGGESTION (const list)
Base Spec (merged) openspec/specs/android-auto-media/spec.md 6 new requirements appended; feature-complete specification

Test Coverage & Regression Data

New Tests (181 total passing)

  • cola_local_test.dart (18 tests): ColaLocal navigation, decidirAvanceCola state machine, identical() guard for race condition
  • navegacion_auto_test.dart (139 tests, was ~120): Fisher-Yates determinism, collision-freedom exhaustive, page-0 action prepend, 4 pre-existing assertions updated for new behavior
  • controlador_reconexion_local_test.dart (3 tests, new): Bounded retry (5 failures → agotado, no 6th retry, no hang) with default maxReintentos:5, separate from protected suite to preserve byte-identical pass count

Protected Regression Suites (21 tests, ZERO regression)

  • servicio_audio_reconnect_test.dart: 8 / 8 passing (UNCHANGED)
  • servicio_audio_session_test.dart: 5 / 5 passing (UNCHANGED)
  • servicio_audio_source_switch_test.dart: 3 / 3 passing (UNCHANGED)
  • servicio_audio_eq_reapply_test.dart: 5 / 5 passing (UNCHANGED)

Baseline (Phase 0.1): 21 total, 0 failures
Final (Phase 5.4): 21 total, 0 failures
Diff on protected files: Zero lines changed (verified via git diff --stat)

Code Changes Summary

New Files

  • lib/servicios/cola_local.dart (103 lines): Pure Dart queue holder, decision logic, identical() race guard
  • test/servicios/cola_local_test.dart (181 lines): Full unit coverage of ColaLocal and decidirAvanceCola
  • test/servicios/controlador_reconexion_local_test.dart (151 lines): Open-question regression test, bounded retry proof

Modified Files

  • lib/servicios/navegacion_auto.dart (~180 lines added): Two new prefixes, Fisher-Yates, page-0 action prepend, queue orchestration
  • lib/servicios/servicio_audio.dart (~190 lines added/changed): Queue state fields, playMediaItem split, auto-advance wiring, skip overrides, control gating
  • openspec/specs/android-auto-media/spec.md: 6 new requirements appended (delta merged)

Total Impact

~1400+ lines delivered as single PR with user's explicit informed choice (highest-risk change of session, offered chain option, user chose single-PR anyway).

Deviations from Design (All Disclosed & Justified)

  1. avanceEsValido folding: Guard placed inside _reproducirEntradaCola as optional parameter instead of external gate; functionally identical, avoids redundant URI resolve
  2. Resolve-failure defense: Auto-advance that hits dead local file deactivates + stops (not left with stuck latch); defensive, consistent with ADR-4's no-inconsistent-state principle
  3. androidCompactActionIndices dynamic: Compact-view play/pause index shifts from [0] to [1] when queue active (skip-previous prepended); necessary for correctness, negligible perf cost
  4. Test placement: Open-question regression (5-failures-default-maxReintentos:5) placed in new file to preserve protected suite's byte-identical pass count

Issues & Risks

CRITICAL

  • None in this change alone; however, see standing pre-release gate below

WARNINGS (3)

  1. Handler wiring static-review-only: ProcessingState.completed, car transport buttons, race-guard runtime behavior never executed in unit tests (environment constraint — no DHU/on-device testing). Risk mitigated by (a) pure cola_local.dart fully unit-tested, (b) careful manual diff review, confirmed by verify phase. Requires on-device QA before release.
  2. flutter analyze/coverage/gen-l10n deferred: Phase 6.1 explicitly out of scope (strict-TDD, only target test files run). Must run manually before merge.
  3. Single-PR delivery size:exception: ~1400+ lines over estimated 850-950. User was informed this was highest-risk change of day and offered chain option; chose single-PR anyway. Review workload note for PR reviewers.

STANDING PRE-RELEASE GATE (APPLIES TO ALL 4 ARCHIVED PHASES)

  • On-device / DHU validation of ALL native surfaces: SAF folder pick, MediaMetadataRetriever extraction, FileProvider art cache, queue/shuffle handler + car transport. Mandatory before production release — none runtime-tested; all static-review-only or unit-tested-locally.

Skill Compliance

  • literal-encoding scan: 0 corruption matches in all touched/new .dart files
  • work-unit-commits: No commits by apply/verify agents; orchestrator handles final commit/tag

Deferred / Out of Scope (Accepted)

  • Phase 6.1: flutter analyze, flutter test --coverage, flutter gen-l10n — manual follow-up
  • On-device / DHU QA — scheduled separately as standing pre-release gate
  • Recursive subtree queueing — explicitly out of scope by design
  • OS shuffle toggle — browsable action only
  • Repeat modes, persisted queues, queue-reordering UI — not promised

Traceability: All SDD Artifacts

Phase Artifact Topic Key Observation ID
Proposal sdd/android-auto-local-music-phase3/proposal (captured in engram)
Spec sdd/android-auto-local-music-phase3/spec (captured in engram)
Design sdd/android-auto-local-music-phase3/design (captured in engram)
Tasks sdd/android-auto-local-music-phase3/tasks (captured in engram)
Apply Progress sdd/android-auto-local-music-phase3/apply-progress (captured in engram)
Verify Report sdd/android-auto-local-music-phase3/verify-report (captured in engram)
Archive Report sdd/android-auto-local-music-phase3/archive-report (this document, saved to engram)

Closure

Change is CLOSED and ARCHIVED.

The entire 3-phase local-music-in-Android-Auto feature is now feature-complete, verified, and ready for:

  1. Pre-release gate: On-device/DHU validation (mandatory, covers all 4 archived phases)
  2. Production release: Once pre-release QA confirms all native surfaces on a real head unit

No further work on the local-music feature is planned. Subsequent PRs, if any, will be bug fixes or targeted enhancements (out of scope for SDD).