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.
66 lines
4.2 KiB
Markdown
66 lines
4.2 KiB
Markdown
# Proposal: Pre-notice Live Countdown
|
|
|
|
## Intent
|
|
|
|
The 30-minute alarm pre-notice posts a single static notification at T-30min and never updates — it shows "30 min" frozen until the alarm fires. Users expect the same live, decrementing behavior the snooze countdown already ships (29, 28, ... 1 min). This change makes the pre-notice a TRUE per-minute live countdown, reusing the proven snooze-chain pattern already in production in this exact codebase.
|
|
|
|
## Scope
|
|
|
|
### In Scope
|
|
- Re-arm the pre-notice as a repeating per-minute chain (first post at T-30min unchanged; ticks at T-29 ... T-1).
|
|
- New `AlarmScheduler.armNextPreNoticeCountdownTick(id, remaining)` mirroring `armNextSnoozeCountdownTick`.
|
|
- Self-healing ticks: each recomputes remaining minutes from wall clock (`ceilMinutes()`), not a decrementing counter.
|
|
- Self-stop at `remaining <= 1` (final minute handled by the real fire alarm, same as snooze).
|
|
- Extend cancellation to tear down the new tick chain at all 5 sites (see Risks).
|
|
|
|
### Out of Scope
|
|
- Refactoring snooze + pre-notice into one shared countdown engine (Approach 1 — rejected; risks shipped snooze code).
|
|
- Any l10n / ARB / Dart / `MainActivity` work (`preNoticeCountdown` key already wired in all 13 locales).
|
|
- iOS pre-notice behavior.
|
|
|
|
## Capabilities
|
|
|
|
> No `openspec/specs/` exists yet. These are NEW capabilities.
|
|
|
|
### New Capabilities
|
|
- `alarm-pre-notice-countdown`: per-minute live countdown for the 30-min pre-notice notification, including arm/tick/cancel lifecycle and self-healing minute computation.
|
|
|
|
### Modified Capabilities
|
|
- None.
|
|
|
|
## Approach
|
|
|
|
Reuse `ACTION_PRE_NOTICE` for both first-post and tick (no new action constant). Keep `schedulePreNotice()` arming the first exact alarm at T-30min. After the receiver posts the pre-notice notification (skip/postpone actions stay in `PluriWaveAlarmReceiver`), it calls `AlarmScheduler.armNextPreNoticeCountdownTick(id, remaining)` to re-arm at the next minute boundary — keeping notification-building in the receiver and AlarmManager primitives in the scheduler, consistent with current separation of concerns. Switch pre-notice to `ceilMinutes()` for consistency with snooze. Use requestCode slot 9.
|
|
|
|
## Affected Areas
|
|
|
|
| Area | Impact | Description |
|
|
|------|--------|-------------|
|
|
| `android/.../AlarmScheduler.kt` | Modified | Add `armNextPreNoticeCountdownTick` + `cancelPreNoticeCountdown`; extend `cancelAlarm()` and `scheduleSpec` teardown; use `ceilMinutes()`. |
|
|
| `android/.../PluriWaveAlarmReceiver.kt` | Modified | `ACTION_PRE_NOTICE` re-arms next tick after posting; `ACTION_SKIP_NEXT`/`ACTION_POSTPONE_NEXT` now cancel the tick chain. |
|
|
|
|
## Risks
|
|
|
|
| Risk | Likelihood | Mitigation |
|
|
|------|------------|------------|
|
|
| Doze 9-min quota delays ticks over the longer 30-min window | Med | Each tick computes from wall clock → countdown "jumps" not breaks; parallel `setAlarmClock()` exits Doze near fire. |
|
|
| Missing a cancellation site leaks a repeating chain | Med | Explicit 5-site checklist: `cancelAlarm`, `scheduleSpec` no-trigger branch, snooze-transition branch, `ACTION_SKIP_NEXT`, `ACTION_POSTPONE_NEXT`. |
|
|
| Notification ID overlap with snooze countdown | Low | Invariant already holds (`scheduleSpec` branches on `snoozeUntilMillis != null`); preserve it. |
|
|
| OEM aggressive battery killers | Low | Pre-existing, already accepted for snooze; not unique to this change. |
|
|
|
|
## Rollback Plan
|
|
|
|
Revert the two Kotlin files (`AlarmScheduler.kt`, `PluriWaveAlarmReceiver.kt`) to prior commit. No schema, l10n, Dart, or config changes accompany this change, so rollback is a clean single-commit revert with zero migration. Pre-notice falls back to the existing single-shot behavior.
|
|
|
|
## Dependencies
|
|
|
|
- None. Prior `alarm-live-countdown` change already shipped the l10n template, `setNotificationStrings` plumbing, and the snooze-chain reference implementation.
|
|
|
|
## Success Criteria
|
|
|
|
- [ ] Pre-notice notification updates each minute from 29 down to 1 with the device idle/screen-off.
|
|
- [ ] Chain self-stops at the final minute; the real fire alarm takes over.
|
|
- [ ] Skip-next and postpone-next from the pre-notice cancel the tick chain (no orphaned repeating alarm).
|
|
- [ ] Snooze transition cancels the pre-notice tick chain; no double-notification.
|
|
- [ ] Snooze countdown behavior is unchanged (no regression).
|