Top-right always-on-top strip while the signed morning session is
in_progress: title, "Next: <step>", "Locks return at HH:MM".
wake-alarm-strip.path starts it on every file rewrite; it re-reads
the file each second, asks for a refresh every 30 s, exits 0 when
the session ends. No display/output: warning, exit 1.
Bump gatelock pin to 0.12.0 (corner_strip).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WzxdWZd3smuxDGmEgXkYP8
Conflicting git-tag pins in the shared user site let the last install downgrade focus_project/sickdays (no harvest, no focus locker).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stakes and history move behind two tiles that open bottom sheets;
the page no longer scrolls at Pixel 6a geometry (home_fit_test).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WzxdWWcbzoov1KFZJSFcSs
check.sh now runs Dart->Python (keep, unsorted/duplicate input, a cleared
keep day, a keep-only edit that must not re-stamp state) and
Python->Dart (0.2.0 keep sets plus a 0.1.0 record with no keep, a stale
keep and a malformed one), Python 0.2.0 as the oracle with explicit
paths and HOME pointed at a scratch dir. DOCS-sick-days.md and the
SickDays.kt contract describe the alarm-only native cache.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PAhbNszs5JKdtnD4uBi3xp
Tapping today or a later normal day opens a sheet with one switch per
locker (Workout lock, LeetCode, Book, Diet, Wake alarm), all off, and
"Mark sick"; a sick day reopens with its switches, "Save" (keep-only
edit, nothing written when unchanged) and "Clear sick day". Past days
stay inert. A sick day keeping any locker carries a dot in the calendar
and a "Kept: ..." line in the list. DayCell moves to day_cell.dart for
the 250-line cap.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PAhbNszs5JKdtnD4uBi3xp
SickDayPool gains keep: mark/clear write state+actor+keep on one tick,
setKept re-stamps only keep+actor, read rules 1-5 in sick_day_keep.dart.
The native SickDays cache now holds only days on which the alarm stands
down, so a sick day that keeps the alarm rings like a normal day.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PAhbNszs5JKdtnD4uBi3xp
All PC enforcement (fallback ring, RTC self-wake, trigger, workday penalty
write/retract, audit) now asks sickdays.stands_down(LOCKER_ALARM, day) via
_sick.alarm_stands_down instead of is_sick_day, so a sick day that keeps the
alarm behaves exactly as a normal stick day. Bump sickdays pin to v0.2.0.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PAhbNszs5JKdtnD4uBi3xp
The test staged a 2026-10-01 event through stageLocalSettings, which called
stageEnforcementData on the real clock; on 2026-10-16 the event aged past
boundEvents' 14-day window and the test went red for everyone.
stageLocalSettings now forwards an optional `now` to stageEnforcementData
(callers unchanged), and the test passes its fixed clock. phone_app suite:
402 passed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xfj1sxKH9VBPqpcAni8Jry
The venv rebuild after a requirements.txt change was the largest cold-path
cost of `scripts/check_gate_stamp.sh full`. uv is also what CI installs
with, so the mirror gets closer to CI, not further. The interpreter is
passed as a path: `--python python3` let uv pick an active ~/.venv (3.13)
that crdt-sync 0.9.2 (>=3.14) cannot install into. pip stays as fallback.
Measured under capped.sh (4G, 20 %): `full` warm 10.9 s; fully cold
(no venv, empty PRE_COMMIT_HOME, empty mypy cache) 45.9 s, floor = the
pylint hook env install (~24 s, only after .pre-commit-config.yaml changes).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xfj1sxKH9VBPqpcAni8Jry
A release build gives no way to see the SharedPreferences cache that
AlarmReceiver reads at ring time (no run-as, no log of its contents), so
"the Dart UI shows it" could not prove "the alarm will stay silent".
- SickDays.store/dates log the sorted set under WakeAlarmSickDays.
- AlarmChannel getSickDays returns the cached set (null if unreadable).
- The Sick days screen reads it on open (before the sync rewrites it) and
after every sync: "Alarm cache: <dates>" / "none" / "unreadable".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xfj1sxKH9VBPqpcAni8Jry
- Sick days screen (own name, sick icon, cat-2 fill): tap today or a later
day to mark it sick, tap again to clear; past days inert. Writes the
sickdays wire format (state sick/cleared + actor, one HLC per write) to
sickdays-sync/devices via crdt_sync syncLog.
- Mutual exclusion in both pickers: each syncs the other pool on open and
refuses a date it holds, naming the pool; an unreadable pool refuses all.
- Native SickDays cache (fail closed via DayCache); AlarmReceiver skips the
ring with reason "sick_day" (no markFired, no ring_started); StickCheck
verdict sick_day, streak skips sick days; stakes card says so.
- Pre-alarm pool sync: allow-while-idle alarm at 21:00 and A-30 (request
code 1006) runs a headless engine (poolSyncMain) that pulls both pools
from RTDB and rewrites both native caches, so a PC mark arrives with the
app closed. The ring decision stays a cache read.
- JVM unit tests (JUnit 4.13.2) for DayCache, RingDecision,
PoolSyncSchedule, StickCheck; Dart tests; Dart->Python interop check.
pylint hook skipped: verify.py imports sickdays, not in the hook env until
the sickdays-v0.1.0 tag exists; run by hand in a sickdays venv (10.00/10).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xfj1sxKH9VBPqpcAni8Jry
A date in the new shared sickdays pool (not a free day) now means, on the PC:
no fallback ring (a ring in progress stops, reason sick_day), no RTC
self-wake for that morning (ours is disarmed), no morning-routine trigger,
and no workday_penalty.json; a penalty issued on a day later marked sick is
retracted (penalty_cancelled, cause sick_day) by the next session refresh or
RTC tick. The audit treats the day as one where nothing is expected.
All pool access goes through wake_alarm/_sick.py: fail closed (unreadable
pool or missing package = not sick), and act modes pull the pool from
Firebase first (RTC --arm on a stick-day target, in-window fallback ticks
and ring polls, the day's first penalty write) because the sickdays timer
pauses through hibernate. Dry runs never pull.
Pins: sickdays-v0.1.0, freedays-v0.4.0, crdt-sync-v0.9.2 (needed by both);
pre-commit 4.7.0, pylint 4.1.3, ruff 0.17.1 (freshness gate).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xfj1sxKH9VBPqpcAni8Jry
screen-locker's PC sync went Firebase-only on 2026-10-09 and nothing
maintains ~/.config/screen_locker/sync_token any more. The GitHub-fallback
token list now holds only diet_guard's repo-scoped PAT. Drop the stale
note about shutdown-wrapper.sh mirroring the list (the wrapper was removed
on 2026-08-30).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018RHwVPyiiQMPh4M3JQwQku
The .fvmrc moved in the previous commit; CI's freshness gate also reads the
flutter-version pins in python-tests.yml and release-apk.yml.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBbkN4ZB4aUPJPzR2prRan
The expectation resolved the next alarm without the earned ramp set, while
the app (correctly) re-arms with the minute the dismiss just earned. On a
non-workday that is one minute apart, so the test failed Fri-Mon on any
Flutter version. It now loads the policy exactly as the app does.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBbkN4ZB4aUPJPzR2prRan
gatelock 0.9.0 adds gatelock.morning_session (the shared reader of
wake-alarm's morning carrot, now used by screen-locker, leetcode-guard and
book-guard); nothing here changes behaviour. The tag moved the freshness
gate, so the pin moves with it, together with today's lint-tool releases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FBbkN4ZB4aUPJPzR2prRan
- pre-commit: drop the 28 s requirements.txt install (only
dependency-freshness among the system hooks needs third-party code:
pyyaml, packaging), run pre-commit directly instead of
pre-commit/action, and split mypy and pylint into their own matrix
jobs with per-group hook-env caches. Same hook set, same
SKIP=free-days-interop (the rest group).
- Tests: uv with a cached wheel store for requirements.txt (pip took
22 s), -q and -p no:sugar. No -n auto: the suite runs in ~0.5 s and
measured ~1.2 s under pytest-xdist.
- free-days-interop (the critical path): build the freedays venv with
uv instead of venv + pip (12 s).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0188kZdx3bb56QM8JFUnbHuM
_logging_setup attaches its JSONL sink the first time an entry point's
main() runs, and the conftest never redirected LOG_JSONL_FILE or
LOG_DEDUPE_FILE. Every suite run appended ~25 fixture warnings ("Synced
alarm out of range: 24:0") to ~/.local/state/wake_alarm/events.jsonl, the
log a failed wake-up is reconstructed from. Patch _logging_setup's names
(it imported them by value) in the autouse _hermetic fixture.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0188kZdx3bb56QM8JFUnbHuM