P3.2 · Sync orchestrator + conflict detection
What
Central coordinator between pull and push. Maintains a SyncStateCache:
type SyncState = {
linearId: string;
lastSyncedAt: string; // ISO timestamp
lastKnownRemoteBody: string; // for diff
lastKnownLocalBody: string; // for diff
lastKnownRemoteUpdatedAt: string;
};
Conflict detection algorithm
On every sync tick:
- Fetch issues updated since
min(lastSyncedAt across all notes). - For each returned issue, compare:
- Was local modified since
lastSyncedAt? (check Obsidian file mtime vslastSyncedAt) - Was remote modified since
lastSyncedAt? (issue.updatedAt > lastSyncedAt)
- Was local modified since
- Four cases:
- Neither changed → no-op
- Only remote changed → pull (apply remote to local)
- Only local changed → push (apply local to remote)
- Both changed → conflict
- Conflict routing:
- If
|remoteUpdatedAt - localModifiedAt| < 24h→ last-write-wins (newer timestamp wins), log a Notice. - Otherwise → queue for conflict UI (P3.3).
- If
Acceptance criteria
- Integration test with a simulated remote-then-local edit produces the correct route for all four cases.
- Last-write-wins path works silently for near-simultaneous edits.
- Conflicts are queued, not auto-resolved when >24h divergence.
- Updated
- 2026-04-22