Senior Engineer Benchmark
Checks

proof-rewrite-integrated

claude-opus-5-5Claude Codehigh effortrun 12 Oct 2026236,827,101 tokens

Instructions ▾

Instructions — what the model was asked

This folder is a frozen copy of the Proof repository, taken at the March 17, 2026 collaboration outage. It is a git repository whose first commit is that frozen state. Its npm dependencies are already installed in node_modules/ and work offline: npm test, npx tsc and npx tsx run from here with no network. Do not try to install or fetch anything.

Before investigating, read AGENTS.md, AGENT_PROMPT.md, benchmark_context/issue-557.md and benchmark_context/local-only-rules.md in full. The task in AGENT_PROMPT.md is quoted below; the “How to work” instructions here extend it from a plan to an integrated implementation and verification. For implementation scope, these instructions supersede any plan-only wording and any repository guidance that requires retaining the legacy architecture. Where a general instruction conflicts, the Benchmark Fixture Override in AGENTS.md wins. Paths in those files that point to another machine mean this folder.

This is a blind, local-only benchmark. Use only the files in this folder and its git history. Do not use web search, external services or any other copy of Proof.

The task, in the owner's words:

The code in this repo is vibecoded slop and it just keeps going down, and there's tons and tons of unrelated issues that are cropping up where it goes down or documents get duplicated, and I'm just tearing my hair out on it. I have a feeling that it's just vibecoded slop. If we started from the beginning, the codebase, especially around the live document collaboration, we would structure it way differently.

So if we wanted to do a clean first-principle structural rewrite where we were not thinking about, okay, what are the implementation services that we keep consistent? How do we do a clean migration? We just started from the beginning as a clean concept. What would we do? How would we structure it? What are the invariants that we would hold to be true throughout the codebase? Make a plan for that.

How to work:

  1. If you have to choose between a greenfield and a brownfield approach, choose GREENFIELD. Greenfield means a clean architecture for the working app, not a standalone prototype. You do not need a production migration or gradual rollout.
  2. Write your plan first and save it in docs/plans/.
  3. Then implement the plan in this folder. The default build and npm run serve must use the new core through the existing editor and APIs. Preserve the app’s intended capabilities, fix the incident failures, and route normal reads and writes through the new core without falling back to the legacy implementation. Actually launch the integrated app and exercise it yourself locally, and write and run automated integration/end-to-end tests against the running client/server paths, including multiple clients, persistence across restart, and the incident regressions or their mapped equivalents wherever the fixture permits. Use a browser if one is available; otherwise exercise the client/server API and collaboration protocol paths with local clients. Writing tests without running them is not verification. Retire an existing test only by naming it and what now covers it, including the regression tests written after past incidents; tests for anything you did not replace stay and still pass. npm run build, npm run test:ci and npm run test:pr:collab pass today and must pass at the end. Do not change .github/workflows; if a script runs a test you retired, update that script and say why in ANSWER.md.
  4. Before you stop, write ANSWER.md in the root of this folder. This file is required: it is your final report, and a chat reply alone is not read. It must contain:
    • the scope you delivered, and where the plan and the new code live
    • every build, typecheck and test command you ran, with its result
    • a capability inventory showing what was kept, changed or is missing, and the regression coverage
    • what you directly observed in the running app versus what remains untested, including any fixture or runtime limitations
    • the limitations and gaps that remain

About this sandbox: the internet is blocked, but you can start servers and connect to them on 127.0.0.1. $PORT holds a free port for this run, and Proof's server uses it. There is no writable /tmp; use $TMPDIR instead, for example APPSIGNAL_LOG_PATH=$TMPDIR npm run serve. This is one non-interactive session: it ends when you end your turn, and anything still running in the background is stopped then, so wait for background work to finish before you end your turn.

7 of 48 checks failed

ANSWER.md the model's output · 28.7 KBdownload

Proof: a clean document core for live collaboration

1. What I delivered

I took the greenfield route and integrated it into the running app.

Plan: docs/plans/2026-10-12-greenfield-document-core-plan.md. It covers:

  • why the system keeps going down and duplicating content (section 1);
  • the clean concept and 11 invariants (section 2);
  • the module layout and data model (section 3);
  • browser changes (section 4), API compatibility (section 5) and verification (section 6);
  • the decisions I made while implementing it (section 6a) and the independent review findings and fixes (section 6b).

New code, which is the only authority for documents in the running app:

Area Files Responsibility
Document core server/core/ (17 files, ~3.6k lines) store.ts (SQLite: append-only Yjs update log + snapshot + derived read model), room.ts / rooms.ts (exactly one in-memory writer per document), sync-server.ts / sync-protocol.ts (Hocuspocus-provider-compatible WebSocket protocol, owned by us), content.ts (markdown ⇄ ProseMirror ⇄ Yjs via structural diffs), projector.ts, marks.ts, blocks.ts, access.ts, budget.ts (event-loop work budget), health.ts, core.ts (facade)
HTTP layer server/http/ (10 files, ~2.4k lines) /api/documents/*, /api/agent/*, /share/markdown, /d/:slug (SPA, JSON, markdown, agent HTML), bridge, library/dashboard, Every auth, /ws routing
Composition server/index.ts (rewired), server/http/app.ts, server/aux-store.ts npm run serve → server/bootstrap.ts → document core. Auth sessions and incident breadcrumbs live in aux-store, not the legacy schema.
Browser src/editor/share-collab-bind-reset.ts, src/editor/index.ts (one method) The browser never re-seeds the shared Y.Doc. Hydration no longer depends on the removed markdown Y.Text.

Removed:

  • 32 legacy authority modules, about 36.8k lines: collab.ts (12.5k lines), routes.ts, agent-routes.ts, canonical-document.ts, document-engine.ts, db.ts, collab-mutation-coordinator.ts, ws.ts, bridge.ts, library.ts, dashboard.ts, snapshot.ts, the mutation-* modules, yjs-volume-maintenance.ts, and others.
  • 6 scripts that only operated on the legacy schema.
  • 204 tests of the removed modules. Each one is listed with what now covers it in docs/plans/2026-10-12-test-retirement-map.md.
  • Nothing in the default build or npm run serve imports the legacy stack, and there is no fallback to it: the files are gone. scripts/typecheck-core.mjs plus a dangling-import scan confirm this.

Housekeeping.

  • All changes are in the working tree and uncommitted. git status shows the deletions plus the new server/core/, server/http/ and src/tests/core-* files.
  • preview.json starts the app with npm run build && npm run serve on port 4000.

The invariants (short form)

  1. One authority: a document's content is its Yjs update log. Markdown, marks JSON, revision and block refs are derived from it and never written back.
  2. One writer per document: browser sync, agent edits, REST PUT, comment ops and library sync all go through that document's single Room, synchronously.
  3. History only grows: a document's lineage is created once and never re-seeded. Whole-document writes are minimal structural diffs (updateYFragment).
  4. Durable before visible: an update is appended to SQLite before it is broadcast or acknowledged. There is no debounced onStore and no "stale persist".
  5. The read model is derived and side-effect free: reads never mutate anything; a projection failure only lags that one document.
  6. Failure is scoped to the document: no global breakers, no cross-document fences, and a corrupt document degrades to read-only on its own.
  7. Bounded event-loop work: size limits plus a per-document and global CPU budget. /health is memory-only and reports event-loop lag.
  8. Access fences per document: only access changes bump the epoch, and doing so closes only that document's sessions.
  9. Idempotent creation: Idempotency-Key on create, and GET /new ignores prefetch and unfurl bots.
  10. Clients write content only through the CRDT: HTTP content writes are preconditioned diffs, and a blind PUT is refused while editors are live.
  11. Boring shutdown: stop accepting, close sockets, flush derived state. There is nothing that could be lost.

How this maps to issue #557 and the duplication reports

  • The outage.

    • Diagnosis (plan §1.4): noteGlobalCollabAdmissionPathology tripped when two stale onStore reloads coincided while four or more documents anywhere in the DB were durably quarantined. Quarantine never expires and the count was a full-table COUNT(*).
    • Once tripped, it bumped the access epoch of every recently active slug and blocked live collab for every pre-existing document (the recorded scoped-slug set is dead code).
    • It then re-tripped with a broader cohort. Meanwhile synchronous SQLite reads and Yjs replays ran on the same event loop that serves / and /health.
    • In the new core the whole mechanism is gone, and the mapped regression test (core-incident-557-regression) applies the same pressure pattern and asserts the properties the issue asks to preserve.
  • Duplication. The structural causes were:

    • clear-and-reinsert writes into the CRDT from several places, including the browser (resetCollabYDocForRebind);
    • re-seeding a document's lineage from the markdown row;
    • replaying buffered client updates into a re-seeded lineage.

    Invariant 3 removes all three. core-store-room includes a negative control showing that the old shape duplicates and the new one does not.

2. Commands I ran and their results

Environment: Node v26.10.0, offline, in a sandbox with no writable /tmp and no browser binary.

Baseline, before any change

Command Result
npm run build ✅ exit 0
npm run test:ci ✅ exit 0 (9 tests)
npm run test:pr:collab ❌ exit 1 in this sandbox: AppSignal tried to log to /tmp. ✅ with APPSIGNAL_LOG_PATH=$TMPDIR
npm test ❌ exit 1: pre-existing failure in proof-mark-rehydration.test.ts. The && chain stops there.
Each of the 140 test files referenced by test, test:server-routes-share, test:pr:collab, test:ci and test:collab:stability-followups, run individually with a 240 s timeout 130 pass, 10 fail (pre-existing): proof-mark-rehydration, mutation-contract-stage-and-ws (hangs), collab-regression-guards-round2, live-viewer-passive-reconnect-wiring, share-new-doc-bootstrap-editability-regression (both need Chromium), share-live-viewer-rest-put-authority-regression, agent-edit-fragment-base-regression, agent-mutations-imply-presence, share-json-repair-readiness-contract-regression, collab-corrupt-persisted-yjs-quarantine
npx tsc -p tsconfig.server.json --noEmit ❌ 256 errors (pre-existing)
npx tsc --noEmit -p tsconfig.json ❌ 1127 errors (pre-existing)

Final

All commands were run from this folder on the final code. Commands with no env prefix were run with no extra environment.

Command Result
npm run build ✅ exit 0 (Vite client build + build:mcp)
npm run test:ci ✅ exit 0 (9/9)
npm run test:pr:collab ✅ exit 0: 14 suites, 68 tests (the 3 unchanged Yjs/Hocuspocus contract suites + npm run test:core, 11 new suites). It now passes without the APPSIGNAL_LOG_PATH workaround, because AppSignal init fails open. On the final code it passed twice as npm run test:pr:collab and once more file-by-file. Four earlier runs during development, before the review fixes, were also green. About 25 s per run.
npm run typecheck:core (scripts/typecheck-core.mjs, strict tsconfig.core.json over server/core, server/http, server/index.ts, src/tests/core-*) ✅ 0 errors in new code. Reports, without gating, 31 pre-existing errors in imported legacy Milkdown schema/parser modules.
npx tsx src/tests/server-routes-and-share.test.ts (98-case legacy route suite, retargeted at the core routers) ✅ 94 passed, 0 failed. Baseline was 96 passed; 2 cases tested deleted legacy guards and were retired, see the retirement map.
Per-file run of all 67 test files referenced by test, test:server-routes-share, test:collab:contracts, test:pr:collab, test:ci, test:core and test:collab:stability-followups 64 pass, 3 fail. The 3 are the same pre-existing failures as baseline: collab-regression-guards-round2 (a client wiring assertion), plus share-new-doc-bootstrap-editability-regression and live-viewer-passive-reconnect-wiring, which both need a Chromium binary.
npm test ❌ exit 1: the && chain stops at the pre-existing collab-regression-guards-round2 failure. Baseline also exited 1, stopping at proof-mark-rehydration, which is now retired.
npm run test:server-routes-share ❌ exit 1: stops at live-viewer-passive-reconnect-wiring (needs Chromium; fails identically at baseline). Every earlier entry in the chain passes.
npx tsc -p tsconfig.server.json --noEmit ❌ 78 errors, down from 256 at baseline. None are in server/core, server/http, server/index.ts or server/aux-store.ts.
npx tsc --noEmit -p tsconfig.json ❌ 512 errors, down from 1127 at baseline. The only ones in new files are the same rootDir TS6059 notices every server-importing test gets under this config.
INCIDENT_DOCS=40 INCIDENT_LOAD_MS=30000 npx tsx src/tests/core-incident-557-regression.test.ts (the test:collab:nightly:matrix configuration) ✅ in 4 runs (the last 2 on the final code): 80 live clients and 620–708 agent edits per run. /health p50 1 ms, p99 169–331 ms, max 192–541 ms; / p99 169–198 ms. 0 probe failures, 0 healthy-document sessions fenced, every acknowledged edit present exactly once.
Manual: npm run serve + scripts/core-live-session-smoke.ts phase 1 → SIGTERM → npm run serve → phase 2 ✅, done twice (before and after the review fixes). Details in §4.

Test suites added (all in test:core, so they run in test:pr:collab):

Suite Tests
core-store-room 8
core-durability-regressions 6
core-work-budget 2
core-sync-protocol (real @hocuspocus/provider) 5
core-shutdown-durability 3
core-security 5
core-api-regressions (ported legacy regressions) 11
core-bridge-library 2
core-review-regressions 7
core-e2e-server (spawned server/bootstrap.ts + real web-client modules) 6
core-incident-557-regression 1

Scripts changed in package.json, and why:

  • test, test:server-routes-share: dropped the 84 retired test files and added npm run test:core. The retired files import modules that no longer exist; what replaces each one is in the retirement map.
  • test:pr:collab: test:collab:contracts && test:core. It replaces collab-shutdown-authority-regression and collab-shutdown-live-connection-drain-regression, which tested the deleted server/collab.ts shutdown. They are replaced by core-shutdown-durability and core-e2e-server (SIGKILL/SIGTERM).
  • test:collab:stability-followups, test:collab:nightly:matrix, test:collab:same-paragraph-race, test:live-viewer:fragment*: repointed at the core suites, since their old targets were retired.
  • Removed test:migration-verify, repair:proof-marks and repair:yjs:audit; their scripts operated only on the deleted legacy schema.
  • Added test:core and typecheck:core.
  • .github/workflows is unchanged.

Independent review

After implementation I had two independent reviews, one of the core and one of the HTTP layer. The reviewers reproduced each finding with throwaway scripts.

  • Core review: 4 high and 4 medium findings.
    • A stale request-time record could seed a room and reopen an access fence.
    • After a projection error, preconditions could pass against stale content and revert live edits.
    • Converting the CRDT could make a read delete schema-unknown elements.
    • A corrupt document's last good read model and history could be destroyed.
    • Medium: retry timer, projection starvation, budget double-charging and starvation, ambiguous accept fallback.
  • HTTP review: 8 findings.
    • Tokenless browser actions on agent routes failed.
    • ownerId spoofing into libraries, with title markup injection.
    • Viewers could write unbounded presence.
    • Create idempotency was shared across callers.
    • Library policy leaked into the room.
    • Some malformed inputs returned 500.
    • Idempotent replay ran before authorization.
    • The bridge silently downgraded invalid tokens.

All of these are fixed and pinned by core-durability-regressions (6 tests) and core-review-regressions (7 tests). The four low-severity items I didn't fix are listed in §5.11. Plan §6b has the full list.

3. Capability inventory

Legend: ✅ kept (same contract, new core) · 🔁 changed (deliberately different) · ⛔ removed / missing.

Capability Status Notes / regression coverage
Create doc: POST /share/markdown, /api/share/markdown, legacy POST /api/documents (warn/disabled modes, auth modes, rate limit, validation codes) ✅ (+ Idempotency-Key) server-routes-and-share, core-store-room, core-e2e-server (idempotent create)
GET /new, /get-started ✅ / 🔁 Prefetch requests and unfurl bots get 204 and create nothing (duplicate-doc source removed). Covered by core-e2e-server.
Share page /d/:slug: SPA with injected config, agent HTML, JSON manifest, text/markdown, token cookie, OG tags, comment-UI mode ✅ server-routes-and-share (retargeted). I fetched the page and the built bundle manually.
Paused/revoked share for non-owners 🔁 Generic "unavailable" page, 200 for HTML (legacy served a stored HTML snapshot), no title or content leak. JSON stays 404/410.
/api/documents/:slug (+ /recovery, /info), open-context, collab-session, collab-refresh ✅ Same shapes the ShareClient parses. Covered by core-e2e-server through the real ShareClient / CollabClient modules.
Live collaboration (Hocuspocus provider protocol, awareness/cursors, read-only roles, token rotation) ✅ (reimplemented server) core-sync-protocol (real provider), core-e2e-server, core-security
Multi-client convergence, offline buffer replay, hard reconnect ✅ core-e2e-server (3 tabs, SIGKILL/SIGTERM restart, offline replay exactly once)
PUT /api/documents/:slug (markdown / marks / title), PUT …/title ✅ / 🔁 A blind markdown PUT is refused with 409 PRECONDITION_REQUIRED while live editors are connected. Marks PUT is a monotonic merge (no lost replies, no resurrection). Covered by core-api-regressions and server-routes-and-share.
Comments, replies, resolve/unresolve, suggestions (insert/delete/replace), accept/reject via /ops, /api/agent/:slug/marks/*, bridge ✅ Anchors are applied server-side in the same transaction as the metadata. Covered by core-api-regressions, core-store-room, core-bridge-library.
Agent state, snapshot, edit, edit/v2 (all 6 ops), rewrite, ops, events/pending, events/ack, idempotent replay, mt1: base tokens ✅ core-api-regressions, core-e2e-server, server-routes-and-share
rewrite.apply with live collaborators 🔁 Allowed: it is a precondition-checked diff, so there's no LIVE_CLIENTS_PRESENT, no barrier, and live sessions are not fenced. Covered by core-api-regressions.
Agent presence/cursors (/presence, implied by mutations with X-Agent-Id, /presence/disconnect) ✅ / 🔁 Reads no longer write presence (legacy GET /state + X-Agent-Id did). The UA-based provisional "AI collaborator" presence was dropped. /presence now needs comment rights (legacy allowed viewers), and its fields are length-capped. Covered by core-api-regressions and core-review-regressions.
Agent API auth (/api/agent/*) 🔁 Same policy as the share routes: an explicit token gives its role (invalid → 401), the owner's Every session is owner, and no token gets the link's default role. Legacy returned 401, which broke accept, resolve and event polling for tokenless share-page users. This grants nothing a tokenless user couldn't already do through /api/documents/*. Covered by core-review-regressions and core-security.
Account ownership and titles 🔁 ownerId: every:<id> on create is honoured only for that authenticated principal; opaque labels are kept. Titles are stored single-line, up to 300 characters. Covered by core-review-regressions.
Access links, pause/resume/revoke/delete ✅ Epoch bump fences only that document. Its sessions are closed with 4205 (reset), so the provider reconnects, gets session-stale and the editor's recovery runs. Covered by core-sync-protocol, core-e2e-server, server-routes-and-share.
Bridge /d/:slug/bridge/* ✅ (server-executed) Legacy forwarding of unknown operations to a connected browser (bridge.request) is not reimplemented: every bridge operation runs on the server. Covered by core-bridge-library.
Every OAuth, library/dashboard, library access link, claim, delete ✅ / 🔁 The library is an ordinary owned (paused) doc whose content the server re-derives on open. It is not continuously synced in the background. Covered by core-bridge-library and server-routes-and-share.
/health 🔁 (stronger) Memory only: starting / ready / degraded / stopping / stopped, event-loop lag, room/session counts, recent incident slugs. Covered by core-shutdown-durability and core-incident-557-regression.
Metrics (/metrics, agent-mutation series used by alerting), bug reports, discovery docs, homepage, static assets ✅ appsignal-prod-alerting and test:ci (unchanged)
Quarantine, repair, clone-from-canonical admin routes; projection repair worker; global admission guard; hot-slug breaker ⛔ by design These routes return 410 RETIRED. The core has no repair state (invariants 1, 5, 6).
Runaway-growth guard (PATHOLOGICAL_GROWTH_BLOCKED), block-explosion integrity quarantine ⛔ by design Replaced by structural impossibility of duplication (invariant 3), preconditions (10), size limits and the work budget (7).
Legacy maintenance (mutation outbox/backfill, legacy mark-tombstone table, http-info incident rows) and their scripts (repair:proof-marks, repair:yjs:audit, test:migration-verify) ⛔ Tables are gone. The core prunes idempotency keys after 24 h and keeps its own mark tombstones, recorded when a mark leaves the CRDT, so stale snapshots can't revive it.
Stored HTML snapshots / CDN snapshot publishing (snapshotUrl) ⛔ / 🔁 snapshotUrl is null. /snapshots/:slug.html renders a share-preview page (title + excerpt) on demand from the read model for active docs; no stored full-HTML snapshot.
Separate-port collab runtime (COLLAB_PORT), PROOF_COLLAB_V2 kill switch 🔁 Collab always runs on the same HTTP server at /ws (the legacy "embedded" mode). COLLAB_PUBLIC_BASE_URL is still honoured for the advertised URL.

Regression coverage for the incident and duplication reports:

  • #557 (outage): core-incident-557-regression. Default run: 12 documents × 2 live clients, agents, access churn, a corrupt document and a 260 KB document. Nightly: 40 × 2 for 30 s.
  • Stale-onStore / quarantine / fencing family: mechanisms removed. Covered by core-store-room, core-sync-protocol, core-shutdown-durability.
  • v2 duplication and replay-into-reseed duplication: core-store-room negative control, plus core-e2e-server (offline replay, fresh-doc joins, restarts).
  • Passive viewers never write: core-e2e-server (viewer edit never persists, revision unchanged), core-sync-protocol.
  • Side-effect-free reads: core-e2e-server, core-api-regressions (reads don't change revision or log head).
  • Stale sessions can't write after access changes: core-sync-protocol, core-e2e-server.
  • Health stays responsive during degradation: core-incident-557-regression.
  • Guard trips scoped to the causal document: core-incident-557-regression asserts that the only incident slug is the corrupt document and that no healthy document's session is closed.

4. What I observed in the running app, and what remains untested

I launched the integrated app myself, twice: once mid-way and once on the final code after the review fixes. The second time it ran with no APPSIGNAL_LOG_PATH. Each time I ran npm run build, then PORT=<free port> DATABASE_PATH=$TMPDIR/…/proof.db npm run serve, and drove it with scripts/core-live-session-smoke.ts. That script uses the real web-client modules (ShareClient, CollabClient and the Hocuspocus provider) plus plain HTTP. What I saw:

  • /health reported ready on the first probe. / returned 200, /favicon.ico 200, and /new returned 302 to /d/<slug>?token=… with the owner cookie set.
  • The share page returned 200 with window.__PROOF_CONFIG__.shareSlug injected, and its built bundle /assets/editor-*.js returned 200 (3.5 MB).
  • Two tabs opened with canEdit:true and converged on each other's edits.
  • An agent read /state, added a comment and a replace suggestion. The comment arrived in tab A through the CRDT, and accepting through the real ShareClient.acceptSuggestion changed the text in tab B.
  • Agent presence ai:planner appeared in tab A's agentPresence map. A title change reached the viewer socket, which saw connected, viewers.updated, document.updated, agent.presence, document.title.updated.
  • Accept: text/markdown returned the clean document. /health showed 1 room and 2 sessions.
  • Restart. I stopped the server with SIGTERM; the log showed [shutdown] complete in 2ms. I then started it again on the same database:
    • every line was present exactly once, the comment survived and the title and revision were intact;
    • a new tab hydrated the full document, comment anchor included;
    • an edit made after the restart persisted.

Extra probes against the final running server:

  • /d/<slug> with Accept: application/json returned the manifest (15 links, mutationReady:true).
  • Tokenless open-context returned an editor session on ws://…/ws?slug=… with pm-yjs-v1.
  • /agent-docs, /.well-known/agent.json and the OG PNG all returned 200.
  • The legacy /api/agent/<slug>/quarantine returned 410.

Exercised automatically against real processes:

  • core-e2e-server spawns server/bootstrap.ts, the exact npm run serve entry point. It runs three simulated browsers on the real client modules plus agents, and kills the server with SIGKILL and SIGTERM mid-session.
  • core-incident-557-regression runs the outage pressure pattern against the spawned server.

Sandbox note. An early smoke-test server, started before I switched to harness-tracked background tasks, could not be signalled from this sandbox ("operation not permitted"). It kept $PORT busy, so my later manual runs used other free ports. It stops when the session ends.

Not exercised:

  • A real browser. There is no Chromium or other browser binary in this sandbox: Playwright's browser cache is absent and no system browser is installed. So the Milkdown editor UI (ProseMirror view, ySyncPlugin binding, cursors plugin, comment UI) was not driven interactively. The browser-side collab/network code (ShareClient, CollabClient, the Hocuspocus provider) did run, in Node with a minimal window shim. Editor typing was simulated by applying updateYFragment diffs to the client's Y.Doc, which is what y-prosemirror's sync plugin does.
  • share-new-doc-bootstrap-editability-regression and live-viewer-passive-reconnect-wiring both need Chromium. They fail here exactly as they did at baseline, and should run against the new server where a browser exists. The two browser changes are small: the client never re-seeds the shared Y.Doc, and hydration ignores the empty markdown Y.Text. Both are unit-tested.
  • Every OAuth against the real provider (offline). The OAuth flows ran against the test suite's mock, and the library against a locally stored, recently verified session.
  • Staging and production scripts (scripts/live-viewer-*, staging-*, prod-*) need remote deployments, which the benchmark forbids.
  • The native macOS app and its local bridge (localhost:9847).

5. Limitations and gaps

  1. One process owns the rooms.
    • Invariant 2 holds per process. The core does not coordinate several server instances writing the same document.
    • If two instances did load one document, the (doc_id, seq) primary key makes the second append fail. That fails closed (the room drops, the client re-sends), so content isn't corrupted, but the system would churn.
    • Scaling out needs slug-sticky routing or a per-document lease in front of the core. Production today ran as a single Railway service.
  2. One operation's cost still scales with document size.
    • The work budget caps throughput, per document and globally, and keeps /health and public routes responsive. Measured /health p99 was 169–331 ms with 80 live clients plus agents.
    • But one parse or serialize of a large document is still synchronous: about 0.5 s for 260 KB, and roughly 2 s near the 1 MB PROOF_MAX_MARKDOWN_BYTES limit.
    • The next step is a worker-thread content engine, so the event loop only ever does O(update) work.
  3. Durability level. synchronous=NORMAL in WAL mode survives a process crash (tested with SIGKILL) but not power loss. PROOF_SQLITE_SYNCHRONOUS=FULL trades throughput for that.
  4. No data migration. As the task allowed, documents in the legacy tables (documents, document_y_updates, …) are not imported, so a database from the old server starts empty under the core. A one-shot importer would be about 100 lines: create a core document with the legacy slug, owner-secret hash and access-token hashes from the legacy markdown and marks.
  5. Agent presence is written to the durable CRDT log. It is small and bounded (50 activity entries), but it is not ephemeral the way awareness is. Moving agent presence to awareness would need a client change in src/editor/index.ts.
  6. Behavior changes callers might notice (all listed in §3):
    • blind PUTs are refused while editors are live;
    • rewrite.apply is allowed with live clients;
    • reads no longer create agent presence;
    • paused shares show a generic page instead of a stored snapshot;
    • snapshotUrl is null;
    • quarantine, repair and clone routes return 410;
    • unknown bridge operations are no longer forwarded to a connected browser;
    • the library is re-derived on open rather than continuously in the background;
    • HTTP markdown writes are capped at 1 MB (PROOF_MAX_MARKDOWN_BYTES). Legacy projection guards tripped at 1.5 M characters.
  7. Browser UI not exercised, because no browser binary is available (§4). The client collab and network modules ran for real in Node, but the editor view did not.
  8. CI path filter. .github/workflows/ci.yml (which I was not allowed to change) triggers test:pr:collab on the legacy filenames. Future PRs that only touch server/core/ or server/http/ won't trigger it. The filter should add ^server/(core|http)/ and ^src/tests/core-.
  9. Typecheck.
    • The repo-wide configs tsconfig.server.json and tsconfig.json failed before this work (256 and 1127 errors) and still fail (78 and 512). None of the remaining errors are in new server code.
    • The new code is gated by npm run typecheck:core (strict, 0 errors). It reports, but doesn't gate, the 31 pre-existing errors in the legacy Milkdown schema and parser modules it imports.
  10. Pre-existing failures left alone.
    • collab-regression-guards-round2 is a client-source wiring assertion that fails identically at baseline. Because the npm test chain is &&-joined, npm test still stops there, as it stopped at the pre-existing proof-mark-rehydration failure before.
    • share-new-doc-bootstrap-editability-regression and live-viewer-passive-reconnect-wiring need Chromium.
  11. Smaller known gaps (from the review; documented rather than fixed):
    • A stale browser snapshot carrying resolved: true can re-resolve a comment that was unresolved after the snapshot was taken. Unresolving itself goes through its own endpoint.
    • A document_too_large degradation does not clear itself after compaction.
    • Room loads, createDocument and /snapshot are measured but not admission-gated by the work budget. They are bounded by the size limits and the create rate limit.
    • An explicit server-side write to a document containing node types unknown to the server schema (e.g. from a newer browser build) removes those nodes. Reads never do; they convert a detached copy.
  12. Some docs still describe legacy mechanisms. AGENTS.md now carries a superseding note, but the older guardrail bullets, CLAUDE.md and the reviewer specs still describe them.