Sync loop root-cause fixes (three independent bugs):
1. Folder change clears stale file states (AddPairViewModel): when
localPath or remotePath changes on an existing pair, all
SyncFileStateEntity records are wiped. Previously those stale records
caused every sync to attempt DELETE_REMOTE on the old folder's files
and to treat all new-folder files as changed — causing both the
"deleting 32 files" loop and rewrites on every run.
2. Download stores null localModifiedAt (SyncEngine): SAF document
cursors can return a stale mtime immediately after a write. Storing
null forces the SKIP reconciliation pass on the next sync to read
the actual walkFiles cursor value, breaking the download->changed->
download loop caused by mtime inconsistency.
3. Second-precision mtime comparison (syncDecide): WebDAV RFC-1123 has
1-second precision; FAT32 has 2-second precision. Comparing at
millisecond level caused phantom "changed" detections after syncing
to/from these systems. Now uses epochSecond for both local and remote.
Icon: three bold teal/red/yellow teardrop streaks (Avast palette) flying
into a white cloud centre, on dark charcoal background.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>