Devlog — 2026-07-06#

TL;DR#

This was a watch week. Most of the effort went into making the Wear OS/watchOS side actually reliable offline — proper token handling, a durable action queue, working complications — plus a webapp overhaul of the Sessions view and a fix for an iOS login bug that would silently log people out.

User-facing features#

  • Renamed “Calendar” to “Sessions” everywhere — mobile and web. It’s a work log, not a planner, and the old name kept setting the wrong expectations.
  • Webapp Sessions view redesigned: timeline is now the main view, with a compact month picker (activity-colored dots, KPIs) alongside it. Add/edit/delete sessions inline.
  • Bulk actions on the webapp Tasks page — select multiple tasks, then complete/archive/tag/set energy in one go.
  • Archiving a task now actually syncs across devices instead of being a local-only flag, and finished tasks auto-archive overnight if untouched.
  • If a sync change gets permanently rejected (bad permissions, failed validation, etc.), you now get a visible notice instead of it silently vanishing.
  • Daily morning digest rewritten — no more emoji or a pointless “3 daily goals” counter, now shows your actual focus task plus yesterday’s stats.
  • Fixed an iOS bug where login wouldn’t stick — the app could silently drop your session due to stale token storage and auth caching. [VERIFY: shipped as three follow-up fixes in one day, worth confirming it’s fully resolved]
  • Watch app should now behave much better without the phone nearby — timer actions taken offline are queued and delivered later instead of quietly dropped, and watch face complications (corner timer, live countdown) no longer freeze or drift.
  • Minor webapp polish: calendar cell overflow and a bug showing raw icon names instead of icons in session rows.

Technical improvements#

  • Backend now detects and merges overlapping work sessions (e.g. logged from two devices at once) instead of double-counting focus time.
  • New watch-scoped auth endpoints let the watch fetch and refresh its own access token directly from the backend, so it’s no longer dependent on the phone being reachable.
  • Watch client got a persistent, app-group-backed action queue that survives the app being suspended — it drains through the phone first, falls back to a direct HTTP call, and only holds if both fail.
  • Added real sync-correctness test coverage: two-client convergence and replay-idempotency tests, plus edge cases around auto-archiving.
  • CI was OOMing on release builds — fixed by splitting phone/watch build jobs, bumping the runner size and JDK version, and trimming lint on release builds.
  • Consolidated the cross-client sync architecture doc into the hub repo as the single source of truth (was previously duplicated in the mobile repo).
  • Centralized time handling behind an injectable Clock instead of scattered direct timestamp calls — mostly groundwork for the sync work above. [VERIFY: minor/foundational, low direct user impact]
  • Two patch releases (1.5.1 → 1.5.2) shipped mid-week alongside Firebase-under-R8 and auth-logging fixes.