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.
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;parseSettingsis pure,loadSettingsreads.env).src/config-errors.ts—loadSettingsOrExitturns 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.envfrom.env.example(orcp .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 indata/. - All config and credentials come ONLY from ENV /
.env, read throughsrc/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
buildjob needstest(tests gate the docker build). - No
EXPOSEin the Dockerfile — this is a daemon with no inbound HTTP port.