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.
This commit is contained in:
vvzvlad
2026-06-16 21:09:40 +03:00
parent 447d2508ae
commit c6edd73324
8 changed files with 511 additions and 87 deletions

View File

@@ -8,9 +8,11 @@ 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: scaffold only — the sync engine is NOT implemented yet.** `src/index.ts`
is a thin stub that validates config and exits. See `SPEC.md` for the full design
and the phased plan before adding engine logic.
**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
@@ -27,6 +29,10 @@ build` builds the lib first, then compiles the app to `build/`.
- `src/config-errors.ts``loadSettingsOrExit` 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.
@@ -46,6 +52,8 @@ Relative imports inside `src/` use the `.js` extension (NodeNext), e.g.
- `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.