feat(sync): add automatic scheduled sync - #159
Merged
ClaudiaFang merged 1 commit intoSep 21, 2026
Merged
Conversation
ClaudiaFang
force-pushed
the
claude/automatic-sync-141
branch
from
September 16, 2026 09:01
0b2061e to
bd12bbf
Compare
|
ClaudiaFang
merged commit Sep 21, 2026
bc9caa3
into
claude/mobile-source-control-density
50 of 67 checks passed
12 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Closes #141
Summary
Adds v1 Automatic Sync: an optional, configurable schedule that keeps the vault and remote repository in sync using the same default Sync action routing as the manual Sync button, while leaving conflicts for manual resolution.
Stacked on
claude/mobile-source-control-density(PR #156, still open). This PR contains only Automatic Sync changes; retarget tomainif #156 merges first.Behavior
local-only/local-modified→ pushlocal-deleted→ delete remoteremote-only/remote-modified→ pullmoved→ push/move through the existing planning pathconflict→ skipped, left for manual resolutionsynced→ no-opBackground conflict semantics (critical)
PushCoordinator.planSyncBatch()gains a UI-freePushConflictBehavior = 'prompt' | 'skip'.skip: conflicting paths are left out of the plan (skippedConflicts/conflictedPaths) and the batch is never cancelled, so unrelated safe paths continue in the same run.idle, so they are never reported as operation success even though they were in the original target set. Regression test:SourceControlActionService.test.ts→ "never marks a path that became a conflict as operation success…".Settings and defaults
automaticSyncEnabledfalseautomaticSyncIntervalMinutes5automaticSyncOnStartupfalseautoRefreshOnStartup(existing)truenormalizeAutomaticSyncIntervalMinutes) so0, negative,NaN,Infinity, or non-numeric values can never create a zero/tight-loop timer.Startup behavior
onLayoutReady, ifautomaticSyncEnabled && automaticSyncOnStartup, one background automatic sync runs without opening or focusing Source Control.autoRefreshOnStartupbehavior is preserved.Concurrency
SyncExecutionGuardserializes all provider mutations.Architecture
Reuses one engine —
Source Control application layer → SyncWorkspace → Sync domain → provider:AutomaticSyncService.runOnce(): refresh →ChangeRepository→ excludesynced/conflict→ default intents viaChangeActionPolicy→SourceControlActionService.sync(intents, 'background')→ refresh.SyncExecutionMode = 'interactive' | 'background'is a per-execution policy (not a loose set of booleans, so invalid combinations can't be expressed).AutomaticSyncScheduler(plugin runtime) and are wired viacreateSyncRuntime;main.tsonly owns lifecycle.Notifications
What's New — 1.7.0
src/changelog/1.7.0/index.ts, registered first insrc/changelog/index.ts(hand-curated release entry; release-specific localized copy stays in the entry, not the shared UI catalog).Test coverage added
synced/conflict; default actions via policy; background mode; no-op on no changes; overlappingrunOnce()does not execute concurrently; errors do not permanently lock.Verification (exact commands)
Manual verification
Not performed — no executable Obsidian environment was available. Checklist for a reviewer with Obsidian:
Release note
Semantic-release performs the actual 1.7.0 version bump.
manifest.json,package.json,versions.json, and the generatedCHANGELOG.mdwere intentionally not hand-edited.Base branch integrity
claude/mobile-source-control-density(a1f01b3) and is opened as a stacked PR.