docs: mark M2 done

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-11 13:53:42 +02:00
co-authored by Claude Opus 5
parent 971ee4f7a3
commit 5ea3c798b4
+25 -5
View File
@@ -10,10 +10,12 @@ Status legend: ✅ done · 🚧 in progress · ⬜ not started
## Current state (one line)
✅ **M1 done.** floret-kit 0.4.0 ships `core-prefs` and `core-di`, and Clockula's
theme now follows its own stored preference over a typed DataStore. **M2** (the
whole storage stack — Room, domain models, repositories, and the first
`ARCHITECTURE.md`) is next.
✅ **M2 done.** Clockula owns its storage: a Room database of four tables with
the schema exported and committed, plain-Kotlin domain models behind four
Flow-based repository interfaces, DataStore preferences, Hilt wiring, and the
first `ARCHITECTURE.md`. **M3** (the alarm engine — next-fire resolution over
repeat masks and DST, `AlarmScheduler`, the receivers, and the ringing service)
is next, and is the hard one.
---
@@ -90,7 +92,7 @@ Pay the extraction the kit's roadmap has been waiting for a third app to trigger
reads the stored preference, with the DataStore built on a corruption handler
so an unreadable prefs file cannot brick startup.
### ⬜ M2 — Data layer
### ✅ M2 — Data layer
The whole storage stack, headless. No UI.
- Room: `alarms`, `timers`, `world_clocks`, `stopwatch_laps` (`PLAN.md` §5),
schema exported and committed, DAOs.
@@ -100,6 +102,24 @@ The whole storage stack, headless. No UI.
- **Tests:** mappers, repository behaviour, the elapsed-realtime vs wall-clock
distinction under a simulated clock change.
- Write the first `ARCHITECTURE.md`.
- **Done when:** the schema is exported and committed, no Room type or query
string appears above `data/`, and the build, lint and unit tests pass.
✅ Four tables (`alarms`, `timers`, `world_clocks`, `stopwatch_laps`), schema
v1 exported to `app/schemas` so migrations can be tested from the beginning.
The seam that matters: the app talks to four repository interfaces speaking
domain types and Flows, and `ArchitectureRulesTest` fails the build if Room, an
entity or a query string ever appears above `data/`. Time is a parameter rather
than an ambient read — `WallClock` and `ElapsedRealtimeClock` are distinct
types, so a running timer anchors on the monotonic clock and keeps a wall-clock
value only as a post-reboot fallback, and the stopwatch keeps none at all. That
leaves one honest gap, written down rather than glossed: once a new boot's
uptime climbs past a stored anchor the reboot goes unnoticed, so closing it
needs a persisted boot id and M3's `BOOT_COMPLETED` receiver. Every
read-modify-write runs inside a DAO transaction, and the stopwatch run record
is written whole in one DataStore edit, so concurrent writers cannot swallow
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.
### ⬜ M3 — Alarm engine
The hard part (`PLAN.md` §4), still headless apart from the ring screen's