Derived from SPEC.md. Each task lists which requirement IDs it exists to
satisfy. Tasks are sequenced by dependency, not by convenience — data model
before storage, storage before engine, engine before CLI, CLI before docs.
| # | Task | Satisfies | Depends on |
|---|---|---|---|
| 1 | Alarm dataclass: fields, time validation (zero-pad, range check), repeat enum validation |
FR-1.1, FR-1.2, FR-1.4, FR-1.5 | — |
| 2 | JSON storage: load/save, atomic write, corrupted-file handling | NFR-2, NFR-3, NFR-4 | 1 |
| 3 | Due-alarm detection function: time match, enabled check, same-day re-fire guard | FR-4.1, FR-4.2, FR-4.5 | 1, 2 |
| 4 | Ring/prompt loop: bell + banner, dismiss/snooze parsing, EOF handling | FR-5.1–FR-5.5 | 3 |
| 5 | Post-fire state transition: once→disable, daily→stays enabled, snooze reschedule |
FR-4.3, FR-4.4, FR-5.2, FR-5.3 | 3, 4 |
| 6 | Watch loop wiring: poll interval, Ctrl+C handling, persistence of state changes | FR-4.6 | 3, 4, 5 |
| 7 | CLI add command + already-passed-today notice |
FR-1.1–FR-1.6 | 1, 2 |
| 8 | CLI list command: empty state, sort by time, column output |
FR-2.1–FR-2.3 | 1, 2 |
| 9 | CLI remove command: not-found error handling |
FR-3.1, FR-3.2 | 1, 2 |
| 10 | CLI run command wiring to engine |
FR-4., FR-5. | 6 |
| 11 | Test suite: one or more tests per FR/NFR, named or documented with their ID | NFR-5 | all above |
| 12 | Traceability matrix (TRACEABILITY.md): map every FR/NFR → code location → test |
NFR-5 | 11 |
| 13 | README: install/run instructions, explicit "not built" section mirroring OS-1..5 | — | 1–10 |
Matches SPEC.md §5 — not scheduled as tasks: timezone support, weekday
repeat patterns, external audio, daemonization, concurrent multi-ring.
Storage and data model come first because everything else depends on a
stable Alarm shape — building the CLI before the model is settled would
mean rewriting CLI argument handling every time a field changes. The
due-alarm detection function (task 3) is isolated as a pure function
(now, alarms in → due list out) specifically so it can be unit-tested
without needing to fake real clock time or drive the full blocking loop —
that's what makes FR-4.1/4.2/4.5 testable in milliseconds instead of
requiring a real wait.