# Local-first sync protocol

**English** · [Português](../../pt-BR/commands/sync-protocol.md)

## Purpose

Synchronize authored state and active work across machines without making the backend authoritative. The protocol uses revisions, compare-and-swap (CAS), causality, a durable outbox, expiring leases, and explicit conflicts; it never silently applies last-write-wins.

## When to use

Use `wendkeep sync push` and `pull` when one project must share its portable state across devices, branches, or worktrees. Sync is optional and creates runtime only after a write operation.

## When not to use

Do not use it as a private-data backup, transcript transport, or Git replacement. CORE, credentials, and local runtime are excluded. Private content may travel only inside an authenticated E2E envelope.

## Prerequisites

The project must be bound to a Vault and have `.wendkeep/portable/state.json`, generated by `wendkeep portable export`. Choose stable actor and device identities. Select a backend with `--remote` or `--url`; tokens are read only from the environment variable named by `--token-env`.

## Syntax

```text
wendkeep sync status [--project <dir>] [--json]
wendkeep sync push --actor <id> --device <id> (--remote <dir> | --url <url>)
wendkeep sync pull (--remote <dir> | --url <url>) [--no-import]
wendkeep sync conflicts [--json]
wendkeep sync resolve --record <key> --select <event> --reason <text> --actor <id> --device <id> (--remote <dir> | --url <url>)
```

## Options and exit codes

`--remote` uses the reference filesystem adapter; `--url` uses the replaceable HTTP adapter. `--token-env NAME` reads a secret without persisting it. `--no-import` downloads and validates without applying portable state. Exit `0` means converged, `1` an operational failure, and `2` invalid usage or a conflict requiring a human decision.

## Examples

```powershell
wendkeep portable export --project .
wendkeep sync push --project . --actor roger --device desktop --remote D:\wk-sync
wendkeep sync pull --project . --remote D:\wk-sync
wendkeep sync conflicts --project . --json
```

## Expected result

Retries are idempotent. Out-of-order events wait for causal parents. Concurrent writes from one revision form an order-independent stable conflict set. Resolution creates a new event and an auditable decision; tombstones and lease history remain intact.

`doctor`, the sanitized Observer snapshot, and the semantic MCP surface expose only health, counts, and candidate metadata; those queries never return authored payloads or local paths.

## Common errors and diagnosis

Use `wendkeep doctor` and `wendkeep sync status`. `WENDKEEP_SYNC_BACKEND_UNAVAILABLE` retains events in the outbox for retry. `WENDKEEP_SYNC_OUTBOX_CORRUPT` blocks sending until local review. Conflicts appear in `sync conflicts` and are never resolved automatically.

Threat model: duplicate delivery, replay, and reordering are contained by hashes, idempotent IDs, revisions, and causal parents. Partitions retain the outbox. Client clocks do not choose a lease winner. A malicious backend can omit or retain events, but cannot forge content without breaking hashes or read private AES-256-GCM envelopes. Key and timestamp metadata may still leak; losing a private key is unrecoverable. Backend rollback is detectable through cursors and revisions, while availability remains the operator's responsibility.

## Next steps

Review conflicts with `wendkeep sync conflicts`, resolve them explicitly, and confirm state with `wendkeep portable diff`. See [Portable state](portable.md) and [Local Observer](observer.md).
