docs(openspec): archive android-auto-local-music-paging

Merges its delta requirements into the android-auto-media base spec.
This closes out Phase-1 polish for local music; Phase 2 (metadata,
sort/filter, real art) and Phase 3 (subfolder scoping, shuffle)
remain the only planned future work for this feature.
This commit is contained in:
2026-07-19 22:21:45 +02:00
parent 725169cd31
commit e030a0975d
8 changed files with 183 additions and 5 deletions
@@ -0,0 +1,155 @@
# Apply Progress: android-auto-local-music-paging
Status: DONE — all 18 tasks across 8 phases completed in a single apply batch
(first and only batch), delivered as one PR with `size:exception` per the
resolved delivery strategy.
## Tasks Completed: 18 / 18
- Phase 1 (Paging Primitives): 1.1-1.4 — done
- Phase 2 (Paged Media-ID Scheme): 2.1-2.2 — done
- Phase 3 (Paged `itemsLocales` + "Más…" Item): 3.1-3.5 — done
- Phase 4 (Wire Paged ID into `hijosMusicaLocal`): 4.1-4.2 — done
- Phase 5 (Friendly Folder Name): 5.1-5.2 — done
- Phase 6 (Localization): 6.1 — done (13/13 locales)
- Phase 7 (Settings UI Wiring): 7.1 — done (implementation); widget test
written but not executable in this sandbox (see Deviations)
- Phase 8 (Regression / Manual Follow-Up): 8.1 — done (verified via targeted
test re-runs); 8.2 — deviated as originally documented (manual follow-up,
unchanged from tasks.md's own note)
## TDD Discipline
Strict TDD mode was active. RED was confirmed via actual compile failures
(missing symbols / signature mismatches) before each GREEN implementation
step for:
- `paginaDe<T>` / `hayPaginaSiguiente` (Phase 1) — implemented alongside the
first test batch write (single edit pass covered both primitives), tests
then run and passed; no separate RED capture for this pair specifically
since both are trivial one-line pure functions added in the same edit as
their tests were authored.
- `esCarpetaLocalPaginadaMediaId` / `paginaCarpetaLocalDesde` / paged
`itemsLocales` / paged `hijosMusicaLocal` (Phases 2-4) — RED confirmed via
a full `flutter test test/servicios/navegacion_auto_test.dart` run showing
~20 compile errors (`Method not found`, `No named parameter`) before the
GREEN implementation, then a second run confirming 84/84 passing.
- `nombreCarpetaDesdeUri` (Phase 5) — RED confirmed via
`flutter test test/servicios/musica_local_auto_test.dart` showing 5
`Method not found: 'nombreCarpetaDesdeUri'` compile errors before GREEN,
then 10/10 passing after.
- Settings UI wiring (Phase 7) — RED attempted via
`flutter test test/pantallas/pantalla_ajustes_test.dart`, but this
surfaced a PRE-EXISTING environment blocker unrelated to this change (see
Deviations #1). The implementation was completed to spec regardless.
## Files Changed
Production code:
- `lib/servicios/navegacion_auto.dart` (+119/-lines within diff) — added
top-level `paginaDe<T>`, `hayPaginaSiguiente`; added
`_prefijoCarpetaLocalPaginada`, `esCarpetaLocalPaginadaMediaId`,
`paginaCarpetaLocalDesde`, `_tituloMasLocal`, `_itemMasLocal`; extended
`itemsLocales` signature (`documentIdPadre`, `pagina`, `tamano`,
`@visibleForTesting construirItem`) with slice-then-map ordering (ADR-3);
added paged branch to `hijosMusicaLocal`.
- `lib/servicios/musica_local_auto.dart` (+47 lines) — added pure
`nombreCarpetaDesdeUri(String treeUri, {required String nombreGenerico})`.
Signature note: takes the localized fallback text as a plain `String`
parameter rather than a `BuildContext`, so the function stays pure and
unit-testable without a widget tree (mirrors the
`_formatearDuracion(AppLocalizations l10n, ...)` precedent in
`pantalla_reproductor.dart`, minus the generated-class coupling). This is
a refinement of tasks.md's terse "`nombreCarpetaDesdeUri(String) -> String`"
description, the same kind of abbreviation gap task 3.4 already had for
`itemsLocales`'s full signature.
- `lib/pantallas/pantalla_ajustes.dart` (+5/-2 lines) — `_SeccionMusicaLocal`
subtitle now renders
`nombreCarpetaDesdeUri(carpeta, nombreGenerico: l10n.localMusicFolderGenericName)`
instead of the raw persisted URI; the unconfigured branch is unchanged
(`l10n.localMusicFolderNotConfigured`).
- `lib/l10n/app_{ar,bn,de,en,es,fr,hi,id,it,ja,pt,ru,zh}.arb` (13 files,
+1 key each) — added `localMusicFolderGenericName`, matching each locale's
existing `localMusicFolder*`/`localMusicChoosePath` register. No "Más…"
arb key added anywhere (ADR-5 — that label is hardcoded Spanish car-tree
text, matching every other car-tree label in `navegacion_auto.dart`).
Tests:
- `test/servicios/navegacion_auto_test.dart` (+453 lines) — new groups:
`paginaDe`, `hayPaginaSiguiente`,
`esCarpetaLocalPaginadaMediaId / paginaCarpetaLocalDesde`; rewrote/extended
`ConstructorArbolAuto.itemsLocales` group (call-count invariant, exact-50
boundary, 51-100 two-step, 100+ chained 3+ pages, "Más…" item shape/round
-trip, root paging, stale-page-beyond-range, plus all 8 pre-existing call
sites updated to pass `documentIdPadre`); extended `hijosMusicaLocal`
group with 4 new paged-branch tests.
- `test/servicios/musica_local_auto_test.dart` (+84 lines) — new
`nombreCarpetaDesdeUri` group: internal storage, SD card, nested folder,
storage-root empty-tail fallback, unparseable-URI fallback, never-raw
-URI/never-empty invariant.
- `test/pantallas/pantalla_ajustes_test.dart` (+57 lines) — new group
`_SeccionMusicaLocal — friendly folder name (Phase 7)`: configured folder
shows the derived friendly name (never the raw `content://` URI);
unconfigured folder keeps the existing "not configured" message. Written
to spec but NOT executable in this sandbox (see Deviations #1).
## Test Results (independently re-confirmed)
- `flutter test test/servicios/navegacion_auto_test.dart test/servicios/musica_local_auto_test.dart --concurrency=1 --timeout=60s`
**94 / 94 passing** (84 tests in `navegacion_auto_test.dart` + 10 tests
in `musica_local_auto_test.dart`) — corrected during verify, the figure
above (95/95, 85+10) originally reported here was a counting error.
- `test/pantallas/pantalla_ajustes_test.dart` — NOT run to completion; fails
to COMPILE in this sandbox for reasons that predate this change entirely
(see Deviations #1). The 2 new tests in this file are structurally
complete and should pass once `flutter gen-l10n` is run as part of the
normal manual follow-up (task 8.2), which already covers regenerating
l10n artifacts.
## Diff Size
`git diff --stat`: 19 files changed, 764 insertions(+), 40 deletions(-)
(≈804 changed lines). This exceeds the tasks.md forecast of ~480-600 lines,
mainly because task 3.5's "mechanical" call-site update also required
rewriting one pre-existing assertion (the 60-item cap test) into two new
boundary tests reflecting the spec's cap→paging behavior change, plus the
call-count-invariant test's verbosity (4 assertions × explicit spy
wiring). Delivered as a single PR with `size:exception`, as directed.
## Deviations
1. **`pantalla_ajustes_test.dart` cannot compile in this sandbox —
pre-existing, not introduced by this change.** The tracked
`lib/l10n/gen/app_localizations.dart` is stale: it predates even the
PARENT local-music change and is missing `localMusicFolderNotConfigured`,
`localMusicSectionTitle`, `localMusicFolderTitle`, etc. — getters the
file already referenced BEFORE this apply pass touched anything.
Confirmed by running the targeted test file and observing the compiler
errors point exclusively at pre-existing lines (320-383) before any new
code from this change is even reached. Regenerating the l10n artifacts
requires `flutter gen-l10n`, which is documented to hang in this
environment and was explicitly out of scope for this apply run (per
task 8.2, already flagged as a manual follow-up in the original
tasks.md). The new `localMusicFolderGenericName` getter this change adds
will appear automatically once that regeneration happens — no code
change is needed on top of what's here.
2. **The pre-existing 60-item `itemsLocales` cap test was rewritten, not
just signature-patched**, as part of task 3.5. This was flagged in
tasks.md as "mechanical, no behavior change" for the 8 call sites in
aggregate, but this ONE specific test's assertion (exactly 50 items,
full stop) is incompatible with the spec's Modified Requirement ("Local
Music Folder Item Cap and Paging" — cap-and-truncate replaced by
cap-and-page). It was split into two new tests that assert the correct
NEW behavior (exactly 50 items → no "Más…"; 51-100 items → 50 + "Más…"
then the remainder). This is an intentional, spec-mandated behavior
change, not a regression.
## Risks Carried Forward
- Re-enumerating the folder per "Más…" tap repeats one SAF query per ADR-2
(accepted, documented, out of scope to change here).
- Pure-Dart friendly-name derivation is brittle for exotic SAF providers
(accepted per ADR-4 — degrades to the generic label, never a crash/blank
/raw-URI).
- `flutter analyze` / `flutter gen-l10n` / full `flutter test` were not run
in this session (environment constraint) — task 8.2's original deviation
note stands, now also explains Deviation #1 above.