Wires the Python side to the configurable schedule. No edit surface yet, so
nothing writes a schedule and current_schedule() returns the default -- the
derived hours are still 08/12/16/20 and the cutoff is still 22:00. Verified by
running it: before any edit the slots are unchanged, after recording 08-20 x5
they become 08:00, 11:00, 14:00, 17:00, 20:00, and a 2020 day still resolves
to the four-meal schedule.
_slots.py now takes the schedule as a *required* argument rather than reading
module constants. Required, not defaulted, on purpose: a default would let a
call site missed in this refactor keep deriving the old fixed hours on one
device, and a slot one device offers while the other does not is a checkpoint
that can never be satisfied. Making it required let mypy enumerate the nine
call sites instead of trusting a grep.
The history is forward-only and seeds the default at the epoch *before*
recording today's value, so switching to five meals leaves past days judged
against the four-meal schedule they actually ran under. Same shape and same
reasoning as _budget_history.py; it will ride the same CRDT record.
Two details worth naming:
- MEAL_SCHEDULE_FILE lands in DATA_DIR, so conftest's _isolate_state redirect
is patched in this same commit rather than a later one. Confirmed with a
canary that the redirect is live and that ~/.local/share/diet_guard/ has no
.meal_schedule after a full run.
- _mcp_read imports _budget.current_schedule already, so the meal-schedule
lookup is aliased rather than shadowing it.
_gatelock._pending_slots is spelled `is None` rather than `or` now. The two are
in fact equivalent -- if 0 is a slot it is necessarily the first slot, checked
exhaustively -- but the intent should not rest on that coincidence.
761 tests, 100% branch coverage.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159b4E5hh512jYUeaJVNxfM