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.
4.2 KiB
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)mirroringarmNextSnoozeCountdownTick. - 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 /
MainActivitywork (preNoticeCountdownkey 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-countdownchange already shipped the l10n template,setNotificationStringsplumbing, 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).