Three bugs fixed:
1. catchupScan used raw dir.walk() with no filters, causing hidden/excluded
files to appear as "new" every startup and trigger a catchup sync.
Fixed by using LocalAccessor.walkFiles(pair) which applies the same
filters and uses the same mtime source (SAF cursor) as SyncEngine.
2. catchupScan compared localModifiedAt.toEpochMilli() vs File.lastModified()
(millisecond precision) while SyncEngine uses second precision. Every file
appeared "modified" after a successful sync. Fixed by using epochSecond.
3. syncDecide() treated !localExists && remoteExists && known==null as
"user deleted local copy → delete remote" even on files that were never
synced. Fixed to treat unknown remote files as new (download them), which
is safe because a genuinely-deleted file will always have a known state
record from the previous sync.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>