_onDispositivoCambiado() bootstrapped a device-level preset entry for every never-seen device id, including the built-in speaker. That persistent level-3 entry masked later global-preset edits (level 3 beats level 4 on every resolution), so disconnecting a BT device or cold-starting without one could leave the EQ stuck on an outdated copy instead of the current global preset. The base speaker is now excluded from the first-seen bootstrap: disconnect and cold start always resolve through the live hierarchy. BT/wired/USB devices keep their bootstrap behavior unchanged.
2.8 KiB
2.8 KiB
Tasks: EQ Device Disconnect / Cold-Start Revert
Review Workload Forecast
| Field | Value |
|---|---|
| Estimated changed lines | ~130-160 |
| 400-line budget risk | Low |
| Chained PRs recommended | No |
| Suggested split | Single PR |
| Delivery strategy | ask-on-risk |
| Chain strategy | pending |
Decision needed before apply: No Chained PRs recommended: No Chain strategy: pending 400-line budget risk: Low
Suggested Work Units
| Unit | Goal | Likely PR | Notes |
|---|---|---|---|
| 1 | Bootstrap guard fix + proof tests (RED-GREEN-REFACTOR) | PR 1 (single PR) | Base: main. One logical change, well under 400-line budget |
Phase 1: RED — Write Failing Tests
- 1.1 Add group
'device disconnect / cold-start revert (Phase D)'totest/estado/estado_ecualizador_test.dartafter L334, reusing existing fakes (no new fake types) - 1.2 D.1 disconnect resolves+applies base preset (spec Req 1, scenario "Disconnect resolves and applies the base preset")
- 1.3 D.2 disconnect does NOT bootstrap
presetsDispositivo['builtin_speaker']from the disconnecting device (spec Req 2) - 1.4 D.3 cold start with no device applies base resolution via
cargarPersistido()only, not a stale device preset (spec Req 3) - 1.5 D.4 connect→disconnect→reconnect cycle: correct preset at each step, matrix override honored, device preset unchanged by disconnect (spec Req 4, locks 5.5b)
- 1.6 D.5 station override still wins over global on disconnect-to-base (design Testing Strategy D.5)
- 1.7 Run
flutter test test/estado/estado_ecualizador_test.dart— confirm D.1-D.5 FAIL; D.2 must fail on the real bootstrap-collision bug, not a tautology
Phase 2: GREEN — Minimal Fix
- 2.1 In
lib/estado/estado_ecualizador.dart_onDispositivoCambiado()(L216-220), gate bootstrap ondispositivo.tipo != TipoDispositivo.altavozInterno - 2.2 Leave L213 (
_dispositivoActualIdassignment) and L222-226 (resolve+apply) unchanged — single handler, no branching on event type - 2.3 Run test suite — confirm D.1-D.5 PASS
Phase 3: Regression Lock
- 3.1 Run full
estado_ecualizador_test.dart— all existing groups green (5.1-5.8, 2.1-2.4, rename API, guardarPresetDispositivo) - 3.2 Confirm 5.5a and 2.2 (both
bluetoothA2dp) unaffected — guard is base-device-scoped only - 3.3 Confirm 5.5b and toggle-off 5.7a/5.8b pass unmodified — named consistency locks
Phase 4: REFACTOR
- 4.1 Add one-line comment above the bootstrap block explaining the
altavozInternoexclusion (prevents L3 masking future L4 edits) - 4.2
flutter analyzeon both modified files — zero new warnings
Phase 5: Manual Sanity (light, non-blocking)
- 5.1 On-device: connect BT/USB with own preset, disconnect (reverts to base), reconnect (returns to device preset) — one-time confidence check