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,71 @@
|
||||
# Alarm Snooze Reschedule Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
Snoozing an alarm (from the ringing screen or from a pre-notice) MUST reliably re-arm the native Android alarm, refresh the in-app UI, and inform the user when scheduling fails. This spec covers `EstadoAlarmas.posponerAlarma()`, `EstadoAlarmas.posponerProximaDesdePreaviso()`, and the user-facing failure feedback in `_posponer()`.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Permission Pre-Check Before Snooze Scheduling
|
||||
|
||||
The system MUST call `_solicitarPermisosNecesariosParaAlarma()` before invoking `android.programar()` in both `posponerAlarma()` and `posponerProximaDesdePreaviso()`, mirroring `guardarAlarma()`.
|
||||
|
||||
#### Scenario: Exact-alarm permission was revoked since the alarm was created
|
||||
|
||||
- GIVEN the exact-alarm permission was previously granted but has since been revoked (OEM battery manager or Android 14 auto-revoke)
|
||||
- WHEN the user snoozes the ringing alarm
|
||||
- THEN the system re-requests the exact-alarm permission before calling `android.programar()`
|
||||
|
||||
#### Scenario: Permission already granted
|
||||
|
||||
- GIVEN the exact-alarm permission is currently granted
|
||||
- WHEN the user snoozes the alarm
|
||||
- THEN the permission pre-check is a no-op and scheduling proceeds immediately
|
||||
|
||||
### Requirement: Native Scheduling Failure Must Not Corrupt UI State
|
||||
|
||||
`posponerAlarma()` and `posponerProximaDesdePreaviso()` MUST wrap the call to `android.programar()` in try/catch and MUST call `notifyListeners()` regardless of whether scheduling succeeds or fails.
|
||||
|
||||
#### Scenario: Native scheduling succeeds (happy path)
|
||||
|
||||
- GIVEN the user snoozes an alarm from the ringing screen
|
||||
- WHEN `android.programar()` completes successfully
|
||||
- THEN the in-memory alarm state reflects the new `snoozeHasta`
|
||||
- AND `notifyListeners()` is called
|
||||
- AND the "next alarm" panel updates to show the snoozed time
|
||||
- AND a per-minute countdown notification appears
|
||||
- AND the native alarm re-fires at the snoozed time
|
||||
|
||||
#### Scenario: Native scheduling throws (failure path)
|
||||
|
||||
- GIVEN the user snoozes an alarm from the ringing screen
|
||||
- WHEN `android.programar()` throws (e.g. `StateError` from a failed `scheduleAlarm` platform call)
|
||||
- THEN the exception is caught inside `posponerAlarma()` (or `posponerProximaDesdePreaviso()`)
|
||||
- AND `notifyListeners()` is still called
|
||||
- AND no real alarm is left silently un-scheduled without the UI knowing
|
||||
- AND the failure is recorded (e.g. into an error field) instead of propagating uncaught
|
||||
|
||||
#### Scenario: Pre-notice snooze failure (variant path)
|
||||
|
||||
- GIVEN the user snoozes from a pre-notice (not the ringing screen)
|
||||
- WHEN `android.programar()` throws inside `posponerProximaDesdePreaviso()`
|
||||
- THEN the same catch + `notifyListeners()` guarantee applies as in `posponerAlarma()`
|
||||
|
||||
### Requirement: User-Facing Failure Feedback
|
||||
|
||||
`_posponer()` in `pantalla_alarma_sonando.dart` MUST surface a scheduling failure to the user (e.g. via SnackBar) instead of only `debugPrint`.
|
||||
|
||||
#### Scenario: Snooze fails and ringing screen dismisses
|
||||
|
||||
- GIVEN `posponerAlarma()` reports a failure (via thrown/caught error or returned failure state)
|
||||
- WHEN `_posponer()` handles the result
|
||||
- THEN the ringing screen still dismisses (existing dismiss-by-design behavior is preserved)
|
||||
- AND the user sees an explicit failure message (e.g. SnackBar) before or immediately after dismissal
|
||||
- AND no failure is silently swallowed with only a debug log
|
||||
|
||||
#### Scenario: Snooze succeeds
|
||||
|
||||
- GIVEN `posponerAlarma()` completes successfully
|
||||
- WHEN `_posponer()` handles the result
|
||||
- THEN the ringing screen dismisses
|
||||
- AND no failure message is shown
|
||||
Reference in New Issue
Block a user