wake-alarm/phone_app
Krzysztof kuhy Rudnicki 60f79774c9 Fix the race that stopped the phone publishing at all
The PC has been firing the morning routine at 07:00 instead of 08:00, off a
record the phone published on 2026-08-09 and never superseded. The phone was
connected to Firebase the whole time and the home screen still said "Connect a
sync backend in Settings first."

initState fired three futures concurrently and the last one read what the
first two were still writing:

    unawaited(_applyPolicy());     // sets _hour/_minute
    unawaited(_loadSyncState());   // sets _service
    unawaited(_syncToPc());        // reads BOTH

`publish` takes the service as a *parameter*, so it captured `_service` by
value while it was still null. Assigning it moments later could never reach
the call. The startup publish therefore passed null every time and bailed out
before touching the network -- and `_syncToPc` had exactly one call site, that
one, so nothing published, ever. `_applyPolicy` has the same shape: a publish
that did win the race would have sent the baseline instead of an active
override. The bootstrap is now strictly sequential.

Three things conspired to hide it for three weeks:

- `publish` returned "Connect a sync backend in Settings first." for BOTH a
  missing backend and a null service, so a broken store looked like a setup
  step the user had never done. The advice pointed at something that was not
  broken. The two causes now report differently, with a regression test.
- `_loadSyncState` swallowed its exception with `on Exception catch (_)`, so
  if the store genuinely failed to open there was no trace anywhere. It logs
  now.
- `_pickEarlier` never published at all, so "Wake me earlier tomorrow" -- the
  one schedule edit the app offers -- never reached the PC either. It does now.

home_screen.dart went over the 250-line cap, so its body moves to
`screens/home_body.dart` as a stateless widget taking plain values. The screen
keeps the state and the ordering rules, which is where the bugs lived.

Verified on the Pixel 6a: home screen now reads "Synced to PC ✓", and the PC's
`_sync --show --no-cache` returns `08:00 (remote)` stamped seconds earlier,
against `07:00` from 2026-08-09 before. The phone had also minted a new device
id, so both records exist in Firebase and the HLC ranking picks the newer --
which is exactly why that reader ranks by HLC and not by listing order.

104 Dart tests pass; analyzer clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PcdngP688mW6rJye3LRkSN
2026-08-30 16:28:20 +02:00
..
android Latest stable dependencies, and the gate that keeps them there 2026-08-28 14:56:16 +02:00
assets/icon Bump gatelock pin to released v0.1.1, regenerate launcher icon 2026-07-21 21:18:02 +02:00
lib Fix the race that stopped the phone publishing at all 2026-08-30 16:28:20 +02:00
test Fix the race that stopped the phone publishing at all 2026-08-30 16:28:20 +02:00
.gitignore Add wake_alarm_sync phone-side Flutter companion app 2026-07-10 23:16:11 +02:00
.metadata Add wake_alarm_sync phone-side Flutter companion app 2026-07-10 23:16:11 +02:00
analysis_options.yaml phone_app: use the shared github_device_auth package 2026-08-15 16:16:17 +02:00
pubspec.lock Latest stable dependencies, and the gate that keeps them there 2026-08-28 14:56:16 +02:00
pubspec.yaml Latest stable dependencies, and the gate that keeps them there 2026-08-28 14:56:16 +02:00
README.md Add wake_alarm_sync phone-side Flutter companion app 2026-07-10 23:16:11 +02:00

wake_alarm_sync

A new Flutter project.

Getting Started

This project is a starting point for a Flutter application.

A few resources to get you started if this is your first Flutter project:

For help getting started with Flutter development, view the online documentation, which offers tutorials, samples, guidance on mobile development, and a full API reference.