Skip to content

Latest commit

 

History

History
66 lines (41 loc) · 6.75 KB

sync-engine.md

File metadata and controls

66 lines (41 loc) · 6.75 KB

CodeFolderSync V3 sync engine

Recursive scan

The scanner uses lstat, locale-stable name ordering, root-relative containment, portable alias checks, and the accepted root ignore compiler. It never follows symlinks or nested mounts. Unsupported object kinds stop the scan.

A matching device/inode retains node identity or infers a move. After observing the complete namespace, an inode replacement at an existing path retains that path's identity only if the old node was not found elsewhere. This handles atomic editor saves and Git restores without misidentifying rename swaps or a move followed by creation at the old path. Replacement bytes are captured again, not reused from stale observations. After accepted materialization, a trusted checkpoint projection binds cross-machine paths to accepted node IDs. Unchanged observation metadata reuses the accepted manifest during routine scans. verify --full, source seal, target planning, approval revalidation, and post-apply verification force content hashing.

.codefoldersyncignore is authority metadata rather than an ordinary event. .codefoldersync, .workspace-sync, and Git metadata are excluded. The signed synchronization policy filters leaves before their contents are captured; required ancestors are retained without including their unselected children. See Synchronization policies.

An ignore globstar followed by / matches zero or more directories. The generated **/node_modules/ rule therefore excludes dependencies directly at the root and at every nested depth before repository discovery or file capture. Ignored data stays local through adoption and synchronization. No extra root rule is required.

Source seal

adoption seal requires the authority role, adoption lifecycle, and a non-empty verified backup witness. It force-scans the included source, durably queues the signed checkpoint, transfers missing immutable objects, and accepts it at the fresh hub. A second identical seal is idempotent; a different seal is rejected.

Adoption plan and apply

Target planning force-scans without modifying the target tree, stores its derived catalog, compares with the source seal, and writes one target-local AES-256-GCM-encrypted plan.

Apply performs:

  1. target role and adoption-generation validation;
  2. a new force scan matching the approved target digest;
  3. source object-closure download and digest verification;
  4. top-level target-only/divergent/type-conflict recovery moves;
  5. moved-equivalent binding when source placement is absent;
  6. journaled included directory, leaf, and symlink materialization, preserving local-only siblings;
  7. independent force scan against source node identity;
  8. semantic digest and eligible Git-context verification;
  9. durable baseline and target-verification record.

Any target change after approval causes a new-plan requirement. The authority peer is rejected before planning or apply.

Normal synchronization

Normal mode compares three snapshots: accepted local baseline, current local scan, and accepted hub checkpoint.

Default-branch mode first discovers every repository context, then projects those snapshots onto eligible scope. It never captures leaf contents inside a suspended repository. Nested ownership uses the deepest repository root, so an eligible nested checkout remains independent of an off-branch parent. Required parent directories stay in the projection. Publication combines the merged eligible projection with unchanged suspended hub entries; local acceptance combines it with the previous suspended local baseline and observations. A suspended repository is not a deletion and does not advance its local baseline.

  • Local equals hub: update observations and cursor only.
  • Local equals baseline: download and apply remote.
  • Hub equals baseline: publish local with a sequence CAS.
  • Both changed: create a deterministic three-way merge, preserve losing stable content, publish from the current hub sequence, then apply the accepted result.

The hub sequence, not timestamps, determines the canonical side. Checkpoint publication includes whole-namespace metadata plus an explicit deterministic mutation list. Objects remain incremental, and each mutation names its immutable closure. An unchanged directory move therefore publishes a move-entry operation while uploading zero objects.

Apply ordering

Normal apply force-revalidates that the local scan is still current. Moving roots first stage deep to shallow, then occupy destinations shallow to deep so rename cycles cannot overwrite one another. Bulk subtree moves require every physical entry to be in scope. Otherwise only selected contents move to unique recovery, leaving local-only siblings and Git metadata in place. Desired directories materialize shallow to deep, followed by leaves. Default-branch apply rechecks repository context before touching live files. The accepted snapshot and any normal conflicts publish atomically.

A scoped apply journal records its eligible current/desired projections, suspended-root scope, enclosing Git guards, and the digest of the complete accepted hub event. Recovery proves that complete digest against hub history before applying the projection. It does not claim the projection itself was a whole hub checkpoint. Capture rechecks Git contexts after hashing, and apply leases guard enclosing checkouts as well as directly eligible repositories.

Existing bytes are never unlinked as the first destructive action. Cross-filesystem recovery is rejected during setup.

Daemon

The daemon is available only after cutover. One owner-only lock prevents a second mutating process. macOS uses its native recursive watcher. Linux watches each included physical directory separately so ignored dependencies and reserved control trees never enter the watcher set. A parent event dirties the full scan before a new included directory needs its own watch. The daemon counts watcher generations across asynchronous remote-checkpoint probes and synchronization, so neither a stale SSH result nor an event received during synchronization can erase a local wakeup. If local files advance while their checkpoint is being published, CodeFolderSync records that accepted checkpoint as the new baseline without creating an apply journal, then publishes the newer local state on the next pass. A scheduled full scan catches silently dropped native events, so correctness does not depend on watcher ordering. daemon --reconcile-seconds can shorten that interval for bounded acceptance runs without changing the signed service default. Services install disabled by default.

Status

clean means the live semantic digest matches the accepted checkpoint and no retained conflict is reported. conflict means synchronization completed with retained conflict evidence. offline and inconclusive are non-success states.