docs: the alarm engine, and the blind spot it closes

ARCHITECTURE gains a section 11 on the engine itself — the state machine, the
two AlarmManager slots, the DST table, and the chain that keeps a denied
permission from turning into a silent morning. Section 5's known blind spot is
amended rather than deleted: the boot id exists now, and the stopwatch repair
moved from M7 to here.

Section 9's "no permissions are declared yet, deliberately" is finally untrue,
so it is replaced with the real set and why each one is there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-11 16:05:31 +02:00
co-authored by Claude Opus 5
parent c0de363db5
commit a522d68098
2 changed files with 381 additions and 57 deletions
+15 -2
View File
@@ -30,8 +30,8 @@ Tag sections feed the release notes — see [`docs/RELEASING.md`](docs/RELEASING
- floret-kit's `core-di` supplies the `@IoDispatcher` the preference store runs
on, so Clockula no longer declares its own dispatcher qualifier.
- Clockula's own storage, headless: a Room database with `alarms`, `timers`,
`world_clocks` and `stopwatch_laps`, its version-1 schema exported and
committed so every future migration is reviewable and testable.
`world_clocks` and `stopwatch_laps`, its schema exported and committed at
every version so each migration is reviewable and testable.
- Plain-Kotlin alarms, timers, world clocks and stopwatch runs behind four
repository interfaces exposing Flows — nothing above the data layer knows Room
exists, and a test fails the build if anyone reaches through. A corrupt row
@@ -49,3 +49,16 @@ Tag sections feed the release notes — see [`docs/RELEASING.md`](docs/RELEASING
since boot. Changing the device's time — forwards or backwards — cannot warp
either, and a timer that survives a reboot falls back to its wall-clock
estimate and says so instead of vanishing.
- Alarms that ring. A repeat schedule that is re-resolved against the device's
zone every time anything moves, so the clock going forwards, backwards or
through a daylight-saving transition cannot lose one: a 02:30 alarm on a
spring-forward night rings at 03:30 rather than vanishing, and on a fall-back
night rings once rather than twice.
- Skip-next-occurrence that skips exactly one occurrence, snooze with a
per-alarm interval and limit, and a snooze that is still kept after a reboot.
- An alarm that keeps ringing through a reboot or a process kill — the ring is
rebuilt from storage, not from memory — and one that still rings when the
full-screen-intent or notification permission is denied. The chain of
fallbacks ends in vibration, never in silence.
- The post-reboot repair: a running timer no longer counts down from an anchor
the reboot killed, and the stopwatch no longer invents a segment it never ran.