docs: mark M3 done
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+38
-7
@@ -10,12 +10,14 @@ Status legend: ✅ done · 🚧 in progress · ⬜ not started
|
|||||||
|
|
||||||
## Current state (one line)
|
## Current state (one line)
|
||||||
|
|
||||||
✅ **M2 done.** Clockula owns its storage: a Room database of four tables with
|
✅ **M3 done.** Clockula's alarms ring. Next-fire resolution is a pure function
|
||||||
the schema exported and committed, plain-Kotlin domain models behind four
|
over a repeat mask and a zone, DST-correct in both directions; skip and snooze
|
||||||
Flow-based repository interfaces, DataStore preferences, Hilt wiring, and the
|
each have a persisted watermark; the engine registers only the single next alarm
|
||||||
first `ARCHITECTURE.md`. **M3** (the alarm engine — next-fire resolution over
|
via `setAlarmClock`, is driven by five thin receivers, and rings through a
|
||||||
repeat masks and DST, `AlarmScheduler`, the receivers, and the ringing service)
|
foreground service that survives process death and reboot and never degrades to
|
||||||
is next, and is the hard one.
|
silence. Schema v2 adds `alarm_states`, and M2's reboot blind spot is closed.
|
||||||
|
**M4** (the app shell — navigation host, four tabs, the live pill, and the ring
|
||||||
|
screen's UI) is next.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -121,7 +123,7 @@ The whole storage stack, headless. No UI.
|
|||||||
each other's edits or persist a torn record. 151 JVM tests over fake DAOs and
|
each other's edits or persist a torn record. 151 JVM tests over fake DAOs and
|
||||||
injected fake clocks; the migration test is the only thing needing a device.
|
injected fake clocks; the migration test is the only thing needing a device.
|
||||||
|
|
||||||
### ⬜ M3 — Alarm engine
|
### ✅ M3 — Alarm engine
|
||||||
The hard part (`PLAN.md` §4), still headless apart from the ring screen's
|
The hard part (`PLAN.md` §4), still headless apart from the ring screen's
|
||||||
plumbing.
|
plumbing.
|
||||||
- Next-fire resolution: local time-of-day + repeat mask → next instant in the
|
- Next-fire resolution: local time-of-day + repeat mask → next instant in the
|
||||||
@@ -137,6 +139,33 @@ plumbing.
|
|||||||
- **Tests:** DST spring-forward and fall-back, every repeat configuration, skip,
|
- **Tests:** DST spring-forward and fall-back, every repeat configuration, skip,
|
||||||
snooze-vs-next-occurrence. These are the tests the app lives or dies on.
|
snooze-vs-next-occurrence. These are the tests the app lives or dies on.
|
||||||
|
|
||||||
|
✅ 326 JVM tests, 172 of them new. The engine is a plain Kotlin class that
|
||||||
|
reaches Android through four interfaces it does not implement, so the
|
||||||
|
behaviour the app lives or dies on is pinned without an emulator —
|
||||||
|
`ArchitectureRulesTest` fails the build if `android.*` ever appears in
|
||||||
|
`domain/`, `AlarmEngine.kt` or `system/`. Occurrences are generated by walking
|
||||||
|
local dates through `ZonedDateTime.of` rather than by adding 24 hours to an
|
||||||
|
instant, which is the whole DST story: a 02:30 alarm rings at 03:30 on a
|
||||||
|
spring-forward night instead of vanishing, and once rather than twice on a
|
||||||
|
fall-back night. Asserted for Berlin and New York and across all 128 repeat
|
||||||
|
masks. Two rules keep constant re-resolution honest: a two-minute grace window
|
||||||
|
so a late fire still counts, and a `handled_occurrence` watermark that can
|
||||||
|
suppress a re-fire but — because suppression also requires the candidate to be
|
||||||
|
at-or-before now — can never silence the future. Skip needed a watermark of its
|
||||||
|
own, since a bare flag eats a second alarm once the skipped occurrence passes.
|
||||||
|
At most one alarm rings and a newly-firing one takes over, so closing a cycle
|
||||||
|
touches the shared ring and auto-silence slots only when that alarm is the one
|
||||||
|
ringing; every write to `alarm_states` runs under one mutex, because a cold
|
||||||
|
start triggered by the fire broadcast otherwise races its own reschedule pass.
|
||||||
|
The "never to silence" chain is a testable invariant, not a hope: full-screen
|
||||||
|
intent, else a heads-up notification that still rings, else the default
|
||||||
|
ringtone, else forced vibration. Schema v2 adds `alarm_states`, and the boot id
|
||||||
|
closes M2's blind spot for running timers **and** the stopwatch — a scope move
|
||||||
|
from M7, recorded in `ARCHITECTURE.md` §5. Knowingly open: the migration and
|
||||||
|
the other 12 instrumentation tests compile but have never run on hardware, as
|
||||||
|
no device was attached; an auto-silenced alarm is silently missed, with no
|
||||||
|
missed-alarm notification until someone asks for one.
|
||||||
|
|
||||||
### ⬜ M4 — App shell
|
### ⬜ M4 — App shell
|
||||||
- Navigation host, four tabs, M3 navigation bar, adaptive rail on wide layouts.
|
- Navigation host, four tabs, M3 navigation bar, adaptive rail on wide layouts.
|
||||||
- The **live pill** (`PLAN.md` §9) — shared running-state surface, pause + stop
|
- The **live pill** (`PLAN.md` §9) — shared running-state surface, pause + stop
|
||||||
@@ -159,6 +188,8 @@ Elapsed-realtime anchored.
|
|||||||
Start/stop/reset, laps with splits and cumulative times, best/worst lap emphasis.
|
Start/stop/reset, laps with splits and cumulative times, best/worst lap emphasis.
|
||||||
Foreground service so it survives backgrounding; laps persist across process
|
Foreground service so it survives backgrounding; laps persist across process
|
||||||
death. This is where the big-readout typography gets settled for the whole app.
|
death. This is where the big-readout typography gets settled for the whole app.
|
||||||
|
The post-reboot repair is **not** here — M3 took it (`ARCHITECTURE.md` §5);
|
||||||
|
M7 owns only how the paused result is presented.
|
||||||
|
|
||||||
### ⬜ M8 — World clock
|
### ⬜ M8 — World clock
|
||||||
IANA zone list with search, ICU-localised city and zone display names, offset and
|
IANA zone list with search, ICU-localised city and zone display names, offset and
|
||||||
|
|||||||
Reference in New Issue
Block a user