vvzvlad 5826255a2f feat(sync): runnable FS->Docmost push (dry-run default, --apply writes)
Wire the push cycle (SPEC §6) into a runnable command; SAFE BY DEFAULT.

- runPush + main(): dry-run by default (plan only, ZERO Docmost writes, no ref
  advance); --apply is the ONLY path that builds a client and mutates Docmost
- orchestration mirrors pull.ts: assertGitAvailable -> ensureRepo ->
  merge-in-progress guard (§9/§12) -> checkout main -> commit local working tree
  (Docmost-Sync-Source: local, §7.3) -> base = refs/docmost/last-pushed else
  docmost -> diffNameStatus(base, main) -> computePushActions -> (apply) ->
  write-back created pageIds + advance refs; divergent-docmost escalates (exit 1)
- npm run push (dry-run) / npm run push -- --apply (writes; needs creds)
- fix (review Blocker): pass the WHOLE VaultGit to applyPushActions (bare method
  refs lost `this` -> --apply crashed on real git); regression test exercises the
  --apply path against a REAL VaultGit temp repo + fake client (proven to catch it)
- symmetric divergent-docmost escalation in both ff branches; dry-run logs the
  local commit explicitly; SPEC §6 notes the dry-run/local-commit behavior
- 737 -> 747 green (x2 stable); build clean; corpus STABLE

Deferred (daemon increment): FS-watcher/debounce (§7.1), git-remote push (§7.2),
continuous poll loop, pull-side §10 record consumption, fractional-index position.
2026-06-21 02:30:46 +03:00

docmost-sync

Bidirectional sync between Docmost articles and a local Markdown git vault — the git repository is the state store. For the full design and the phased implementation plan, see SPEC.md (the authoritative spec).

Status: Increment 1 — monorepo scaffold + read-only pull + Phase-0 round-trip harness. Continuous two-way sync is not implemented yet; see the phased plan in SPEC.md.

It reuses the sibling project docmost-mcp as a library: the DocmostClient REST client and the lossless ProseMirror ↔ Markdown converter are extracted into this monorepo (so changes can be backported file-by-file).

Layout

This is an npm-workspaces monorepo:

  • packages/docmost-client (docmost-client) — the Docmost REST client and its lib/ (converter, markdown-document, collaboration, …). Its source layout mirrors docmost-mcp/src/ 1:1 so diffs can be backported by copying files. Sync-specific REST methods are added under clearly marked docmost-sync additions banners.
  • the repo ROOT — the sync engine app (src/, test/, build/, data/). It depends on docmost-client and holds the config (src/settings.ts), filename sanitization (src/sanitize.ts), the Phase-0 round-trip idempotency harness (src/roundtrip.ts), and the read-only pull (src/pull.ts).

Install & build

Requires Node >= 20. For local (non-Docker) runs a system git binary must also be on PATH — the vault state store shells out to it for every operation (the daemon fails fast at startup if git is missing).

npm install        # links the workspace packages
npm run build      # builds docmost-client, then compiles the app into build/

docmost-client must build before the app (the app consumes its built output); the root build script builds the lib first, then runs tsc.

Configuration

Copy .env.example to .env and fill in real values. The config is read through src/settings.ts.

Variable Required Meaning
DOCMOST_API_URL yes Base URL of our Docmost instance.
DOCMOST_EMAIL yes Docmost service-user login email.
DOCMOST_PASSWORD yes Docmost service-user login password.
DOCMOST_SPACE_ID yes Which Docmost space to mirror.
VAULT_PATH no Local vault directory (default data/vault).
GIT_REMOTE no Optional git remote the vault pushes to.
POLL_INTERVAL_MS no Poll interval in ms (default 15000).
DEBOUNCE_MS no Debounce window in ms (default 2000).
LOG_LEVEL no debug | info | warn | error (default info).

Real secrets go in .env, which is git-ignored — never commit them. The git remote grants access to the whole vault, so protect it no less than Docmost itself (SPEC §12).

Running

Round-trip idempotency harness (Phase 0, SPEC §11)

Verifies that export → import → export is byte-stable. Runs offline against a fixture (the default for CI) — no Docmost credentials needed:

npm run build
node build/roundtrip.js --fixture test/fixtures/sample-doc.json

Or against a live page (needs .env):

node build/roundtrip.js --page <pageId>

Exit code is 0 when the markdown is byte-stable, 1 on a markdown divergence (CI-able). A document-level divergence after stripping block ids is a known SPEC §11 finding and does not fail the run.

Pull (Docmost → filesystem mirror, SPEC §6)

Read-only mirror: walks the configured space's page tree and writes one .md per page under <VAULT_PATH>/<…ancestors>/<Title>.md. Requires a .env with real Docmost credentials — it makes live REST calls and does not touch Docmost state (read-only this increment):

npm run pull
Description
No description provided
Readme 416 KiB
Languages
TypeScript 99.8%
Dockerfile 0.1%
Makefile 0.1%