Files
docmost-sync/AGENTS.md
vvzvlad c6edd73324 refactor(pull): extract tested vault-layout module; harden pull; close review findings
Address the Increment-1 code review (3 warnings + suggestions).

- layout: new pure src/layout.ts (buildVaultLayout) — page-tree -> vault paths,
  sibling + full-path collision disambiguation (sanitized ~slugId suffix), parent
  cycle guard; pull.ts is now a thin I/O loop
- layout: resolve orphan/root collisions at the NAME stage so an orphan ancestor
  can't desync its children's folder segments (fixes review Major); covered by test
- pull: per-page try/catch (one bad page no longer aborts the mirror), bounded
  concurrency (6), progress logging, process.exitCode=1 on partial mirror
- security: filename disambiguation suffix now passes through sanitizeTitle
- docs: AGENTS.md -> Increment 1 status/structure/run targets; pull.ts meta-block
  comment; collectRecentSince JSDoc (lexicographic UTC-ISO precondition)
- tests: layout (9), markdown-document round-trip (no comments block, SPEC §3),
  firstDivergence; export firstDivergence. 49 tests green.
2026-06-16 21:09:40 +03:00

3.7 KiB

AGENTS.md

Onboarding notes for agents working on docmost-sync (Node / TypeScript, ESM).

What this is

A daemon that bidirectionally syncs Docmost articles with a local Markdown git vault (git is the state store). It reuses the sibling project docmost-mcp as a library (DocmostClient, ProseMirror ↔ Markdown converter, collab-write).

Status: Increment 1. src/index.ts is still a thin config-validating entry, but the engine now has a working READ-ONLY pull (Docmost -> FS mirror) and a Phase-0 round-trip idempotency harness. Bidirectional sync, conflict handling, and git are NOT implemented yet (see the SPEC phases). See SPEC.md for the full design and the phased plan before adding engine logic.

Project structure

The project is now an npm-workspaces monorepo. packages/docmost-client is the extracted DocmostClient + lib/ — a verbatim 1:1 copy of docmost-mcp/src/ with the sync-specific methods appended under a clear banner (changes are backported into docmost-mcp manually). The ROOT remains the engine app (src/, test/, build/, data/) and depends on docmost-client. npm run build builds the lib first, then compiles the app to build/.

  • src/ — application code.
    • src/settings.ts — the single config entry point (zod schema keyed by the real ENV var names; parseSettings is pure, loadSettings reads .env).
    • src/config-errors.tsloadSettingsOrExit turns a config error into a clear startup message that names the missing/invalid variable, then exits.
    • src/index.ts — thin entry point.
    • src/sanitize.ts — filesystem-safe filename sanitization (SPEC §12).
    • src/layout.ts — pure page-tree -> vault path mapping.
    • src/roundtrip.ts — Phase-0 idempotency harness (SPEC §11).
    • src/pull.ts — read-only Docmost -> FS mirror (SPEC §6).
  • test/ — vitest tests (*.test.ts).
  • data/ — all mutable runtime state (the git vault lives here). Gitignored; mounted as a docker volume in production. Never put code/static assets here.
  • build/ — compiled output (tsc). Gitignored.

Relative imports inside src/ use the .js extension (NodeNext), e.g. import { loadSettings } from './settings.js'.

Setup

  • make install — install dependencies (npm ci).
  • make env — create .env from .env.example (or cp .env.example .env), then fill in the values.

Running

  • make test — run the test suite (vitest).
  • make run — build and run the app.
  • make dev — run in watch mode (tsx).
  • make roundtrip — run the offline round-trip idempotency harness.
  • make pull — mirror the configured space into the vault (read-only).

make (or make help) lists all targets.

Conventions

  • All mutable state lives ONLY under data/. Static assets are code, never in data/.
  • All config and credentials come ONLY from ENV / .env, read through src/settings.ts. Credentials and the addresses of our own services that the user provides go ONLY into .env (never into code, never as inline env vars on the command line) and are read through settings.
  • No default/example credentials in code. Addresses of our own services (Docmost) have NO default either. A missing required variable must FAIL AT STARTUP with a clear message that names the variable — no raw stack trace.
  • Defaults are allowed only for non-secret tunables (log level, intervals, vault path under data/).
  • All code comments are written in ENGLISH.
  • Repeated actions go through the Makefile.
  • Tests are required for new code. In CI the build job needs test (tests gate the docker build).
  • No EXPOSE in the Dockerfile — this is a daemon with no inbound HTTP port.