Promotes the android-auto-media capability spec to openspec/specs/ and moves both completed changes into openspec/changes/archive/.
8.6 KiB
8.6 KiB
Apply Progress: auto-media-art-quality
Mode: Strict TDD Batch: 1 of 1 (single delivery, no chaining — forecast was Low risk, ~170-230 est. lines; actual ~347 text lines, still under 400-line budget)
Completed Tasks
All 22 tasks in tasks.md are complete and marked [x].
- 1.1 [RED]
faviconUsabletest matrix - 1.2 [GREEN] Implement
faviconUsable - 2.1 [RED]
indiceArteParaformula/order test - 2.2 [GREEN] Implement
indiceArtePara+_nombresArte - 3.1 [RED]
artUriParaintegration test (favicon gate + rotation) - 3.2 [GREEN] Implement
artUriPara; drop_defaultArtUriand old_artUriPara - 3.3 [GREEN] Replace obsolete default-art test
- 4.1 [RED]
subtituloCalidadmatrix test - 4.2 [GREEN] Implement
subtituloCalidad - 5.1 [RED]
itemEmisorasetsdisplaySubtitletest - 5.2 [GREEN] Wire
displaySubtitleintoitemEmisora - 5.3 [REFACTOR] Cleanup pass, doc comments, dead-reference check
- 6.1 [coverage]
Emisora.fromMapunsanitized-favicon regression test - 6.2 [coverage] Phone/auto art-order parity guard
- 7.1 Add 4 native drawable copies (static-review-only)
- 7.2 Delete
default_station_art.png(static-review-only) - 7.3 Verify
applicationId/authority match (static-review-only) - 8.1 Targeted regression run (
navegacion_auto_test.dart, full suite deviation documented) - 8.2
flutter analyze— DEVIATION, not run (hangs in this environment); manual static review done - 8.3
flutter build/flutter run— DEVIATION, not run (hangs in this environment) - 8.4 Manual DHU verification note — recorded below (non-blocking, not coded)
Files Changed
| File | Action | What Was Done |
|---|---|---|
lib/servicios/navegacion_auto.dart |
Modified | Added faviconUsable, indiceArtePara, _nombresArte, artUriPara, subtituloCalidad; wired artUri/displaySubtitle into itemEmisora; dropped _defaultArtUri const and old private _artUriPara |
test/servicios/navegacion_auto_test.dart |
Modified | Added faviconUsable, indiceArtePara, artUriPara, subtituloCalidad, itemEmisora displaySubtitle extension, Emisora.fromMap unsanitized-favicon regression, and phone/auto art-order parity groups; replaced the obsolete _defaultArtUri-based default-art test; extended _emisora() test helper with a codec parameter |
android/app/src/main/res/drawable/station_art_aurora.png |
Created | Verbatim byte-for-byte copy of assets/images/station_art_aurora.png (size-verified match) |
android/app/src/main/res/drawable/station_art_cosmic.png |
Created | Verbatim byte-for-byte copy of assets/images/station_art_cosmic.png (size-verified match) |
android/app/src/main/res/drawable/station_art_pulse.png |
Created | Verbatim byte-for-byte copy of assets/images/station_art_pulse.png (size-verified match) |
android/app/src/main/res/drawable/station_art_nova.png |
Created | Verbatim byte-for-byte copy of assets/images/station_art_nova.png (size-verified match) |
android/app/src/main/res/drawable/default_station_art.png |
Deleted | Retired — rotation is total (uuid always present), launcher-icon-lookalike removed per Design Decision 3 |
TDD Cycle Evidence
| Task | RED | GREEN | REFACTOR |
|---|---|---|---|
1.1/1.2 faviconUsable |
Confirmed fail: Method not found: 'faviconUsable' (compile error across all call sites) |
Implemented; all faviconUsable cases pass. Bug found during GREEN: Uri.tryParse('http://').hasAuthority returns true even with an empty host — initial implementation used uri.hasAuthority, which wrongly accepted 'http://'. Fixed to check uri.host.isNotEmpty explicitly; re-ran, all pass. |
Doc comments added explaining the hasAuthority gotcha inline |
2.1/2.2 indiceArtePara |
Confirmed fail: Method not found: 'indiceArtePara' |
Implemented verbatim-ported formula; parity assertions pass | _nombresArte kept private per design; cross-link comment to tarjeta_emisora.dart added |
3.1/3.2/3.3 artUriPara |
Confirmed fail: Method not found: 'artUriPara' (multiple sites) |
Implemented; replaced old _artUriPara/_defaultArtUri; obsolete default-art test replaced |
Grep-confirmed zero remaining _defaultArtUri/old _artUriPara references anywhere in lib//android/ |
4.1/4.2 subtituloCalidad |
Confirmed fail: Method not found: 'subtituloCalidad' |
Implemented per design's quality-format table incl. bitrate<=0 and whitespace-codec edge cases; all pass | — |
5.1/5.2 itemEmisora wiring |
Confirmed fail: assertion targeted not-yet-set displaySubtitle |
Wired displaySubtitle: subtituloCalidad(e) into MediaItem(...); full group green |
5.3: re-read top to bottom, doc comments added, dead-reference grep clean, full suite (this file) green |
6.1 Emisora.fromMap gap regression |
Coverage-only, single-pass assertion (design already characterizes current behavior) | Passed on first run — confirms artUriPara's validity gate catches the fromMap unsanitized-favicon gap as designed |
— |
| 6.2 Phone/auto parity guard | Coverage-only, single-pass assertion | Passed — verified via artUriPara/indiceArtePara over 4 seeds covering all rotation indices (no public accessor added, keeping _nombresArte private per design) |
— |
Deviations from Design
- Test verifies canonical art-name order behaviorally, not via a public constant. Design specifies
_nombresArteas a private const (task 2.2 says "Privateconst _nombresArte"). Task 2.1/6.2 ask to assert the canonical order directly. Rather than making the list public just for test access (which would contradict the design's explicit privacy choice), the order is verified indirectly throughindiceArtePara+artUriParabehavior using single-character seeds ('d'→index 0,'a'→1,'b'→2,'c'→3) that deterministically cover all 4 rotation indices. This satisfies the same intent (pin the order, catch reorder drift) without leaking an implementation-private symbol. - No other deviations — implementation matches design (
faviconUsable,indiceArtePara,artUriPara,subtituloCalidadsignatures match the Design "Interfaces / Contracts" section exactly).
Issues Found
- Real bug caught by Strict TDD RED→GREEN cycle:
Uri('http://').hasAuthorityreturnstruein Dart even whenhostis empty — a naiveuri.hasAuthoritycheck would have let'http://'(scheme, no host) pass as a "usable" favicon, contradicting the spec's malformed-URL rejection requirement. Fixed by checkinguri.host.isNotEmptyexplicitly. Documented inline with a code comment to prevent regression. - No other issues.
Static Review Notes (Phase 7 — no Android build env available)
- 4 new drawables (
station_art_aurora/cosmic/pulse/nova.png) copied byte-for-byte fromassets/images/— file sizes verified identical to source (1,910,538 / 2,053,431 / 1,879,963 / 1,742,275 bytes respectively). default_station_art.pngdeleted;grep -rn default_station_art lib androidreturns zero matches (excluding SDD artifact prose inopenspec/changes/auto-media-art-quality/).android/app/build.gradle.kts:34confirmed unchanged:applicationId = "es.freetimelab.pluriwave", matching theandroid.resource://es.freetimelab.pluriwave/drawable/station_art_<name>authority built inartUriPara. No manifest/build.gradle change required.- A real Android build or DHU session is still required before shipping to confirm the OS art loader resolves the 4 new
station_art_*drawables viaandroid.resource://(Design's open question — unresolved, carried forward).
Manual DHU Verification Note (task 8.4, non-blocking)
Recommended before merge/ship: a Desktop Head Unit (or real car) session to visually confirm (a) all 4 rotating arts render correctly per station, (b) displaySubtitle quality text renders as expected on the browse row, (c) no stale default_station_art reference lingers anywhere in the built APK's resources.
Remaining Tasks
None — all 22 tasks complete.
Workload / PR Boundary
- Mode: single PR (no chaining needed)
- Current work unit: entire change (
auto-media-art-quality), single deliverable - Boundary: starts from the existing
_artUriPara/_defaultArtUribaseline, ends with the full validity-gate + rotation + quality-subtitle feature landed and tested - Estimated review budget impact: ~347 changed text lines (2 files) + 4 binary adds + 1 binary delete — comfortably under the 400-line budget (forecast: Low risk, confirmed)
Status
22/22 tasks complete. Ready for sdd-verify.
Working tree left uncommitted (staged-ready) per instructions — no git commit run by this agent.