docs(openspec): add SDD artifact trail for recent alarm and EQ changes
Persist the exploration, proposal, spec, design, tasks, and verify/archive reports produced during the multi-device EQ, alarm-countdown, and notification-visual-polish SDD cycles.
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
# Verification Report: snooze-reschedule-fix
|
||||
|
||||
## Mode
|
||||
Strict TDD (RED-GREEN-REFACTOR), hybrid artifact store.
|
||||
|
||||
## Test & Analysis Evidence
|
||||
- `flutter analyze`: 0 issues.
|
||||
- `flutter test`: 238 passed, 0 failed.
|
||||
- `git diff --stat` on touched files: 295 changed lines (within 400-line review budget; tasks.md forecast of Low risk confirmed).
|
||||
|
||||
## Spec Compliance Matrix
|
||||
|
||||
| Requirement | Scenario | Status | Evidence |
|
||||
|---|---|---|---|
|
||||
| Permission Pre-Check Before Snooze Scheduling | Permission revoked since alarm created | PASS | `posponerAlarma()` L211 / `posponerProximaDesdePreaviso()` L242 call `_solicitarPermisosNecesariosParaAlarma()` before `android.programar()` |
|
||||
| Permission Pre-Check Before Snooze Scheduling | Permission already granted (no-op) | PASS | Mirrors guardarAlarma()'s pre-check; covered implicitly by all passing-path tests |
|
||||
| Native Scheduling Failure Must Not Corrupt UI State | Native scheduling succeeds (happy path) | PASS | `estado_alarmas_snooze_test.dart` L30-56, L336-363 |
|
||||
| Native Scheduling Failure Must Not Corrupt UI State | Native scheduling throws (failure path) | PASS | `estado_alarmas_snooze_test.dart` L252-279 — no throw, notifyListeners fires, _error set, state committed |
|
||||
| Native Scheduling Failure Must Not Corrupt UI State | Pre-notice snooze failure (variant) | PASS | `estado_alarmas_snooze_test.dart` L305-334 — identical assertions for posponerProximaDesdePreaviso |
|
||||
| User-Facing Failure Feedback | Snooze fails, screen dismisses, SnackBar shown | PASS | `pantalla_alarma_sonando_dismiss_guard_test.dart` L300-337 |
|
||||
| User-Facing Failure Feedback | Snooze succeeds, no failure SnackBar | PASS | `pantalla_alarma_sonando_dismiss_guard_test.dart` L339-357 |
|
||||
|
||||
All 7 scenarios PASS with runtime-passing covering tests.
|
||||
|
||||
## Design Compliance
|
||||
|
||||
| Decision | Status | Evidence |
|
||||
|---|---|---|
|
||||
| D1: try/catch + trailing unconditional notifyListeners() (NOT finally) | PASS | Confirmed in both methods, lib/estado/estado_alarmas.dart |
|
||||
| D2: untyped catch(e), not `on StateError` | PASS | L214, L245 |
|
||||
| D3: stays Future<void>, records into _error, UI reads after await | PASS | No throw/rethrow; both UI call sites read .error post-await |
|
||||
| D4: ScaffoldMessenger captured BEFORE dismiss | PASS | pantalla_alarma_sonando.dart L179 |
|
||||
| D5: _error = null at start of each method | PASS | L195, L226 + regression-guard tests |
|
||||
| D6: no Kotlin edits | PASS | All touched files are Dart-only |
|
||||
| D7: fallaProgramar switch on FakePuertoAlarmasAndroid | PASS | test/helpers/fakes_alarmas.dart L23, L36-38 |
|
||||
|
||||
## Task Completion
|
||||
Phases 1-4 and 6: fully complete, matches code. Phase 5: GREEN code change (5.2-equivalent) implemented and verified correct; 5.1 (RED widget test) and 5.3 (refactor) not done — see gap analysis.
|
||||
|
||||
## Gap Analysis — Task 5.1 Exception (app.dart POSTPONE_NEXT widget test)
|
||||
Assessed as a justified, scoped exception, not a blocking gap:
|
||||
- Real, independently confirmed blocker: PluriWaveApp has no DI seams (EstadoAlarmas/EstadoRadio hardcoded in build()); EstadoRadio's default ServicioAudio() asserts on audio_service's _handlerGlobal, requiring AudioService.init() — unavailable in widget tests without platform channel setup. No existing test in the repo mounts PluriWaveApp for this same reason.
|
||||
- The app.dart change (L303-315) is a 6-line mechanical mirror of the already-tested Phase 4 branch logic (error != null -> error SnackBar, else success SnackBar).
|
||||
- Spec Requirement 3 explicitly names `_posponer()` in pantalla_alarma_sonando.dart, not app.dart's POSTPONE_NEXT handler — the spec's explicit test obligation is satisfied; app.dart wiring is a design-level completeness addition beyond the literal spec scenario text.
|
||||
- flutter analyze clean, no existing test broken, code verified correct by inspection.
|
||||
Conclusion: WARNING, not CRITICAL. Recommend a follow-up task to add DI seams to PluriWaveApp for future testability; does not block archive.
|
||||
|
||||
## Issues
|
||||
|
||||
**CRITICAL**: None.
|
||||
|
||||
**WARNING**:
|
||||
1. Task 5.1 (RED widget test for app.dart POSTPONE_NEXT SnackBar) not written — architecturally blocked by PluriWaveApp's lack of DI seams. Code verified correct by inspection, mirrors fully-tested Phase 4 pattern. Recommend follow-up task for DI seams, not blocking.
|
||||
|
||||
**SUGGESTION**:
|
||||
1. Consider a dedicated `alarmSnoozeFailed` l10n key instead of reusing androidExactAlarmScheduleError verbatim (deferred per design, not required).
|
||||
2. No isolated unit test distinguishes "permission pre-check no-op" from "pre-check invoked-and-granted" — implicitly covered by all passing-path tests; an explicit spy-based assertion would strengthen confidence if internals change.
|
||||
|
||||
## Verdict
|
||||
PASS WITH WARNINGS
|
||||
Reference in New Issue
Block a user