# Greenfield live-collaboration rewrite — final report

## Scope delivered
- Plan: `docs/plans/2026-03-17-greenfield-collab-core-rewrite-plan.md` (diagnosis of
  issue #557 from the frozen snapshot, 9 invariants, new structure, deletions).
- New core (greenfield, no legacy authority logic):
  - `server/core/store.ts` — persistence only (persisted Y state load/save,
    derived projection write that never bumps document revision).
  - `server/core/projector.ts` — markdown <-> Y.Doc conversion (fragment
    `prosemirror`, Y.Text `markdown`, Y.Map `marks`; Y.Text preferred when
    equivalent so author escapes survive).
  - `server/core/room-manager.ts` — one authority per slug: single-flight
    room load, per-slug serialized queue, per-slug quarantine, per-slug
    epoch fence (stale persist dropped locally, counted, never escalated),
    debounced persist, per-doc shutdown flush.
  - `server/core/sessions.ts` — signed (slug, role, accessEpoch) tokens.
  - `server/core/runtime.ts` — Hocuspocus transport wired to the room
    manager: per-doc auth/epoch check, read-only viewers enforced at the
    server hook, load/store/change/unload hooks that adopt the Hocuspocus
    document as the room document and never escalate across documents.
- `server/collab.ts` (12,476-line legacy god module) is replaced by a thin
  compatibility facade over the core. It contains no authority logic. The
  global admission guard + cohort access-epoch fencing, stale-onStore
  reload/storm breakers, projection repair workers/queues, canonical-sync
  rollback fencing and hot-slug quarantine machinery are deleted, not wrapped.
- Deleted incident mechanism (from the plan): one stale `onStoreDocument`
  could trip a *global* guard that bumped the access epoch of every active
  slug, invalidating unrelated sessions and starving `/`, `/health` and
  `/favicon.ico` on the shared event loop. That class is now structurally
  impossible: there is no cross-document mutable state except bounded,
  non-blocking room caps that reject only the offending room's work.
- Integration: `server/index.ts` / `npm run serve` start the new core via
  the existing `startCollabRuntime*` facade entrypoints; the existing
  editor, `/api/documents/*`, `/share/markdown`, `/d/:slug`, collab-session
  and agent APIs run on it unchanged in shape. `/health` answers from
  in-memory core state only.

## Invariants (enforced in server/core)
1. One authority per document (room Y.Doc); DB markdown/marks are a derived
   projection written only by the room's serialized persist.
2. Per-document isolation — no global guard/quarantine/fence.
3. Serialized per-doc writes; stale (epoch) writes dropped for that slug only.
4. Session tokens carry (slug, role, epoch); drift fences only that session.
5. Reads are side-effect free; seeding happens once, at single-flight load.
6. Health is liveness + counts only, O(1).
7. Passive viewers never publish (server-side read-only).
8. Shutdown flushes each room independently and fails closed per slug.
9. No expensive synchronous work on request/admission paths.

## Commands run and results
- `npm run build` — PASS (vite build + `build:mcp` tsc).
- `npm run test:ci` — PASS (9 test files).
- `npm run test:pr:collab` — PASS. Script updated to:
  `test:collab:contracts` (yjs simulation, hocuspocus contracts, history
  anchors) + new `core-collab-rewrite.test.ts` + the two kept shutdown
  regressions (`collab-shutdown-authority-regression`,
  `collab-shutdown-live-connection-drain-regression`), both passing
  unmodified against the new core.
- `npx tsc --noEmit --skipLibCheck` — the repo has ~1,300 pre-existing
  errors at the frozen commit (rootDir/lib/source-grep test noise); no new
  errors in `server/core/*`, `server/collab.ts` or the new tests beyond the
  pre-existing TS6059 rootDir pattern that all `server/*` files exhibit.
- New tests:
  - `src/tests/core-collab-rewrite.test.ts` — PASS: two live clients
    converge; viewer cannot publish; quarantining a pathological doc does
    not block/fence another doc or health (issue #557 mapped regression);
    stale-epoch persist dropped for the causal doc only; single-flight
    load; persistence across room eviction.
  - `src/tests/core-server-e2e.test.ts` — PASS against a real spawned
    `server/bootstrap.ts`: HTTP create (`/share/markdown`), collab-session
    via HTTP, two WS clients converge, `/health` fast while live, unrelated
    doc creation unaffected, edits persist across a full server restart on
    the same SQLite file.
- Direct observation of the running app: launched `npm run serve` on
  `$PORT`; `GET /health` returned `{"status":"ok",...,"collab":{"enabled":
  true,"state":"ready","wsUrlBase":"ws://localhost:50624"}}`; `GET /`
  200 in ~3ms; `POST /share/markdown` created slug `puda42nk`;
  `GET /api/documents/puda42nk/collab-session` (with client headers)
  returned a core-signed session; `GET /d/puda42nk` 200; a standalone
  two-provider client script converged on a second doc (`rlhwkh69`).
  No browser is available in this sandbox (no Chromium/Playwright
  binaries), so the editor UI itself was exercised through its exact
  HTTP + Hocuspocus protocol paths, not a real browser.
- Existing-test sampling (each run individually): PASS — `marks`,
  `mobile-comment-ux`, `frontmatter`, `edit-ops`, `mutation-coordinator`,
  `share-mark-mutation-failure-recovery`, `agent-edit-v2` (after two core
  fixes: persist must not bump revision; mutation base source is
  `persisted_yjs` unless a client is actually connected),
  `agent-edit-canonical-base`, `agent-edit-collab-propagates`,
  `canonical-mutation-empty-marks-regression`, `external-change`,
  `db-pragmas`, `milkdown-collab-runtime`,
  `collab-hard-reconnect-durable-only-regression`,
  `collab-commenter-durable-replay`. FAIL on the frozen baseline too
  (verified in a clean worktree at HEAD): `marks-route-parity-regression`,
  `mutation-contract-stage-and-ws`, `library-sync-marks-collab-failure-rollback`,
  `state-comment-freshness-regression`, plus the three below.
  (pre-existing, verified in a clean `git worktree` at HEAD):
  `proof-mark-rehydration` (escaped-quote assertion), `server-routes-and-share`,
  `canonical-repair-endpoints`. `npm test` as a whole therefore does not
  pass at the frozen commit either; it stops at `proof-mark-rehydration`.

## Capability inventory
- Kept: document create/read/update/delete, share links + roles
  (viewer/commenter/editor/owner), live multi-client collaboration
  (Hocuspocus/pm-yjs-v1 wire format unchanged), marks/comments/suggestions
  data model, agent ops/edit-v2/state APIs, snapshots, library, dashboard,
  snapshots, health, graceful shutdown with per-doc fail-closed flush,
  session expiry/epoch fencing, quarantine of a single pathological doc.
- Changed: collab authority, persistence scheduling, session signing,
  quarantine/admission, projection derivation — all now in `server/core`.
  Projection (markdown) is derived only during debounced persist and is
  never read back into a live room. Persist no longer bumps `revision`.
- Missing / deliberately removed: global admission guard, stale-onStore
  storm breakers and reload loop, projection repair worker and repair
  queues, canonical-sync rollback fencing, hot-slug denylist quarantine,
  and the legacy `__unsafe*` test-hook surface beyond the hooks kept for
  the shutdown regressions and new core tests.

## Retired tests (named) and what covers them
Retired because they assert the deleted legacy machinery (global guards,
onStore quarantine/reload storms, projection repair, source-grep of legacy
`server/collab.ts` internals) — the behaviors they protected are now
impossible by construction and are covered by `core-collab-rewrite.test.ts`
(isolation, stale-drop locality, single-flight, viewer read-only,
convergence, persistence) and `core-server-e2e.test.ts` (running server,
restart persistence), plus the kept shutdown regressions:
`collab-global-admission-guard.test.ts`,
`collab-global-admission-guard-cross-runtime.test.ts`,
`collab-global-admission-guard-real-path.test.ts`,
`collab-global-admission-guard-thresholds.test.ts`,
`collab-onstore-auto-quarantine.test.ts`,
`collab-onstore-drift-quarantine.test.ts`,
`collab-onstore-stale-overwrite.test.ts`,
`collab-onstore-stale-overwrite-root-cause.test.ts`,
`collab-onstore-invalidated-doc-regression.test.ts`,
`collab-onstore-missing-meta-stale-overwrite.test.ts`,
`collab-onstore-authoritative-baseline-regression.test.ts`,
`collab-onstore-canonical-marks-reconcile-wiring.test.ts`,
`collab-onstore-external-state-reconcile.test.ts`,
`collab-onchange-stale-overwrite.test.ts`,
`collab-stale-onstore-reload-soft-invalidation-wiring.test.ts`,
`collab-projection-repair-worker.test.ts`,
`collab-projection-repair-teardown.test.ts`,
`collab-repair-loop-auto-quarantine.test.ts`,
`collab-corrupt-persisted-yjs-quarantine.test.ts`,
`collab-pathological-fast-quarantine.test.ts`,
`collab-integrity-warning-noise-regression.test.ts`,
`collab-oversized-live-doc-noise-regression.test.ts`,
`collab-ws-oversize-suppression.test.ts`,
`collab-security.test.ts` (source-grep of legacy collab internals),
`collab-runtime-warm-failure-regression.test.ts`,
`collab-session-build-registers-active-lease.test.ts`,
`collab-direct-connection-timeout-regression.test.ts`.
All other existing tests were not retired; the required suites pass and
the sampled non-collab tests above pass. Full `npm test` was already red
at the frozen commit (see pre-existing failures above), so a complete
163-file collab-importing test census was not achievable in this session;
tests in that set that target route/mark/agent behavior on top of the
facade (e.g. `agent-edit-v2`) were verified passing where sampled.

## Limitations and gaps
- No browser available, so Milkdown editor UI behavior (cursor rendering,
  focus, mobile) is verified only via its protocol/HTTP paths.
- `server/canonical-document.ts`, `server/document-engine.ts` and the
  agent/mutation layers remain from the legacy codebase as storage-level
  mutation engines on top of the new core; they no longer own live
  authority, but they were not rewritten.
- The facade keeps legacy response shapes; a few legacy behaviors that
  depended on repair-worker side effects (automatic projection repair,
  repair-queue observability) no longer exist by design.
- Multi-process/replica collaboration (shared Yjs across instances) is
  out of scope, as it was in the legacy design.
- Pre-existing failures at the frozen commit (`proof-mark-rehydration`,
  `server-routes-and-share`, `canonical-repair-endpoints`, and overall
  `npm test`) remain; they fail identically on unmodified HEAD.
