wake-alarm/wake_alarm
Krzysztof kuhy Rudnicki 801177972b Split _sync.py along the transport/resolution seam item 8 needs
371 -> 168. Token discovery and both backends move to _sync_transport.py;
_sync.py keeps resolution (cache, staleness, fallback), the Alarm dataclass
and the CLI.

The seam is chosen for item 8, not just for line count: that phase adds a
dismissal-record reader, which belongs beside the alarm reader in the
transport rather than inside the resolution chain.

ALARM_CACHE_FILE deliberately stays in _sync. The suite patches
`wake_alarm._sync.ALARM_CACHE_FILE` to keep tests off
~/.config/wake_alarm/alarm_cache.json — the file shutdown-wrapper.sh reads at
poweroff — and moving that binding would silently reconnect the tests to the
real one. That is the failure mode that once wrote 27 fake entries into a
live log while the suite still looked green.

The split broke 31 tests loudly, all of them patch targets that had to follow
the code: the three SYNC_* constants, the two fetchers, the patch.multiple on
the firebase names, and the reload test for the crdt_sync import guard. Every
one is repointed at _sync_transport; none was left silently patching nothing.

Verified after: 465 passed at 100% coverage, `python -m wake_alarm._sync
--show` prints, `--no-cache` still resolves the phone's real alarm through
Firebase, `_trigger --dry-run` prints, and wake_state.json is byte-identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EckWmyfetYq3Mi8MAnUudh
2026-08-27 23:44:24 +02:00
..
tests Split _sync.py along the transport/resolution seam item 8 needs 2026-08-27 23:44:24 +02:00
__init__.py Add tests and fix pre-commit issues across all projects 2026-04-12 20:45:24 +02:00
_alarm_display.py feat: split oversized modules for 500-line limit, fix kasa coverage gap 2026-06-14 07:19:37 +02:00
_alarm_flash.py Phase 4: wire sink reactivation into the alarm (finishes item 6) 2026-08-27 20:14:00 +02:00
_alarm_payload.py Discover alarm device directories instead of reading a fixed phone path 2026-08-09 17:06:43 +02:00
_alarm_session.py Phase 6: vmbox becomes the gate for the system scripts (item 10) 2026-08-27 20:49:16 +02:00
_alarm_state.py Phase 5: the power button no longer ends the alarm (item 2) 2026-08-27 20:26:37 +02:00
_alarm_timers.py Phase 4: wire sink reactivation into the alarm (finishes item 6) 2026-08-27 20:14:00 +02:00
_alarm_view.py Split _alarm_view.py: the fan-out proxies move to _view_proxies.py 2026-08-27 23:37:30 +02:00
_alarm.py Phase 5: the power button no longer ends the alarm (item 2) 2026-08-27 20:26:37 +02:00
_audio.py Phase 3: remove the max-fan ramp, split _alarm.py, wire the new modules 2026-08-26 23:46:10 +02:00
_beep_loop.py Phase 3: remove the max-fan ramp, split _alarm.py, wire the new modules 2026-08-26 23:46:10 +02:00
_brightness.py Phase 3: remove the max-fan ramp, split _alarm.py, wire the new modules 2026-08-26 23:46:10 +02:00
_challenges.py Fire alarm daily, harden dismissal challenge; ignore wake_state.json 2026-07-10 23:14:40 +02:00
_constants.py Make the alarm fully automatic and un-weakenable (08:00, earlier-only) 2026-08-27 23:03:00 +02:00
_correlation.py Phase 5: the power button no longer ends the alarm (item 2) 2026-08-27 20:26:37 +02:00
_countdown.py Phase 3: remove the max-fan ramp, split _alarm.py, wire the new modules 2026-08-26 23:46:10 +02:00
_curtains.py Phase 7: curtains open on the alarm, no-op until hardware exists (item 5) 2026-08-27 21:00:11 +02:00
_dismiss_view.py Phase 3: remove the max-fan ramp, split _alarm.py, wire the new modules 2026-08-26 23:46:10 +02:00
_escalation.py Phase 2b: add the 5-minute audio failsafe, and retune escalation to fit it 2026-08-26 23:17:41 +02:00
_escape_dialog.py Split _escape_flow.py: the dialog moves out, the policy stays 2026-08-27 23:34:38 +02:00
_escape_flow.py Split _escape_flow.py: the dialog moves out, the policy stays 2026-08-27 23:34:38 +02:00
_gating.py Phase 3: remove the max-fan ramp, split _alarm.py, wire the new modules 2026-08-26 23:46:10 +02:00
_inhibit.py Phase 6: vmbox becomes the gate for the system scripts (item 10) 2026-08-27 20:49:16 +02:00
_lock_setup.py Phase 3: remove the max-fan ramp, split _alarm.py, wire the new modules 2026-08-26 23:46:10 +02:00
_log_dedupe.py Phase 1: structured JSONL logging with cross-process dedupe 2026-08-26 23:00:08 +02:00
_log_sink.py Phase 1: structured JSONL logging with cross-process dedupe 2026-08-26 23:00:08 +02:00
_logging_setup.py Phase 1: structured JSONL logging with cross-process dedupe 2026-08-26 23:00:08 +02:00
_reactivate.py Phase 4: wire sink reactivation into the alarm (finishes item 6) 2026-08-27 20:14:00 +02:00
_rounds.py Phase 3: remove the max-fan ramp, split _alarm.py, wire the new modules 2026-08-26 23:46:10 +02:00
_screen_flash.py Phase 3: remove the max-fan ramp, split _alarm.py, wire the new modules 2026-08-26 23:46:10 +02:00
_sink_parsing.py Split _sinks.py and home_screen.dart under the 250-line gate 2026-08-27 23:30:02 +02:00
_sinks.py Split _sinks.py and home_screen.dart under the 250-line gate 2026-08-27 23:30:02 +02:00
_smart_plug.py Extract wake_alarm from testsAndMisc as a standalone repo 2026-06-22 12:31:40 +02:00
_startup.py Phase 7: curtains open on the alarm, no-op until hardware exists (item 5) 2026-08-27 21:00:11 +02:00
_state.py Extract wake_alarm from testsAndMisc as a standalone repo 2026-06-22 12:31:40 +02:00
_sync_transport.py Split _sync.py along the transport/resolution seam item 8 needs 2026-08-27 23:44:24 +02:00
_sync.py Split _sync.py along the transport/resolution seam item 8 needs 2026-08-27 23:44:24 +02:00
_tone.py Phase 3: remove the max-fan ramp, split _alarm.py, wire the new modules 2026-08-26 23:46:10 +02:00
_trigger.py Make the alarm fully automatic and un-weakenable (08:00, earlier-only) 2026-08-27 23:03:00 +02:00
_view_proxies.py Split _alarm_view.py: the fan-out proxies move to _view_proxies.py 2026-08-27 23:37:30 +02:00