The desktop and phone split-brained for 5 days (39 vs 30 notes) after the
crdt_sync cutover because one device kept running the pre-migration build
— and nothing in the UI ever said a sync had failed or skipped a peer:
- SyncResult now reports peer files that were listed but couldn't be
fetched/decoded (skippedFiles) instead of dropping them silently.
- Auto-sync no longer swallows errors: every sync (manual or automatic)
records a persisted last-sync status shown in a status line under the
editor, with failures in the error color.
- Desktop actually background-syncs now: focus loss (inactive/hidden,
debounced 5s) triggers a sync — Flutter Linux rarely delivers the
`paused` event the old code relied on. `paused` still syncs immediately
for Android.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K5C5jZ2c4mTaGedK7C1dDv
crdt_sync v0.3.0 now provides canAccessRepo() + deleteFile(), so todo syncs
through the one shared client like the other apps instead of its own copy.
SyncService loses its SHA-tracking (crdt_sync's putFileText self-resolves the
sha); lib/sync/github_client.dart + its test are deleted; capture/settings/
sync_smoke repoint to the shared client. flutter analyze clean, 169 tests at
100% coverage, device-verified (27-note backlog intact, no crash).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019KwUCPESvE5CjCtmUFz8xQ
NoteRepository is rewritten on crdt_sync's LogStore: each Note is stored *as*
a Record (per-field LWW + sticky tombstone), so the on-disk log IS the sync
wire format. Its public API is unchanged (upsert/delete/listNotes/watchNotes/
watchCount/importNotes/changes/nodeId), so the UI and most tests are
untouched; only the internals, the two sync methods (getChangeset/merge ->
exportLog/importLog over a Log), and the changeset-specific tests change.
Filtering/sorting now run in Dart over the in-memory log; watchNotes/watchCount
seed synchronously in onListen to avoid a subscription race.
SyncService moves from per-device sqlite changesets to per-device crdt_sync
Logs under a new todo-sync/notes/ path (clean format cutover; old clients
can't misread a new file). todo's own GitHubClient transport is kept.
One-time migration in NoteRepository.open: reads the legacy sqlite DB (kept
untouched as a safety net; the dep stays only for this), seeds every note --
tombstones included -- into the log with each field's HLC derived from its
updated_at (so a pre-cutover edit still wins by real edit time across two
independently-migrating devices), reuses the legacy node id, and sets a
persisted "migrated" flag so it never re-runs.
Verified: flutter analyze + dart format clean; 178 tests at 100% coverage
(incl. migration, tombstone, restore-race, and corrupt-peer cases). Device
verified on dev.kuhy.todo: real backlog of 27 live notes (+5 tombstones)
migrated intact -- confirmed against a pulled sqlite backup, the pulled
LogStore JSON, and the app's own "27 saved" -- notes render with status/
priority/dates, no crash, migration one-time.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019KwUCPESvE5CjCtmUFz8xQ
todo-sync, diet-guard-sync, and screen-locker-sync were folded into
one private github.com/kuhyx/syncs monorepo, each keeping its own
subdirectory as the Contents-API path prefix. Update the default
owner/repo, the changeset path prefix, and add a persisted-value
migration so an already-installed device that saved the old
'todo-sync' repo name picks up 'syncs' on next load.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Notes list & filtering:
- Text-search filter plus independent date-range filters for both created
and last-updated (AND-combined), a priority filter, and a new status
filter. Default view hides Done/Abandoned and renders as "unfiltered"
(no badge for the default state); fixed badge clipping.
- NoteSort options wired into the list UI; watchCount() for the "N saved".
Status & priority:
- New Status enum (toDo/inProgress/Done/Abandoned) as a settable + filterable
attribute on every note, with capture-screen dropdown.
- Removed "None" priority: every note is Low/Medium/High, default Medium.
Schema migration v2->v3 rewrites legacy priority 0 -> Medium.
Export / import:
- NotesMarkdown round-trippable single-file format with HTML-comment markers.
- Settings "Export notes" (mobile share sheet / desktop writes ~/todo/BACKLOG.md)
and "Import notes" (file picker + safe newer-wins merge by id).
Structured template:
- Every new note pre-fills the richer what/where/must/nice/out/done/depends/
estimate/refs scaffold.
Tests:
- New fast (~5s), deterministic suite via FakeNoteRepository (no DB timers) and
injected http/file-selector/url-launcher fakes. 86 tests, 96.2% line coverage
(note.dart & sync_service.dart at 100%, settings 98.7%). Mobile-only share
branch excluded via coverage:ignore (unreachable on the Linux test host).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>