CodeDocs Vault

Collaboration & the Agent-as-CRDT-Peer

This is OpenKnowledge's quietest but most important idea. An agent's edit is not a suggestion in a side-panel — it is a write into the same CRDT document the human is editing live. The agent is just another collaborator on the wire.


1. The editor stack

The WYSIWYG surface (packages/app/src/editor/) is TipTap / ProseMirror with a patched @handlewithcare/remark-prosemirror bridge so markdown round-trips into rich text and back without corrupting the source. The extension set is broad — slash commands (extensions/slash-command.ts), drag handles and block movers (drag-handle.ts, block-mover.ts), find/replace, heading anchors, footnotes, table controls with frozen headers, @-mentions (composer-mention/), a Callout node, and collaborationCursor for presence. The bridge-id-plugin.ts and source-dirty-observer.ts keep the rich-text view and the markdown source reconciled.

"Editing markdown feels like Notion" is achieved by never showing the user markdown — they edit the ProseMirror tree; the markdown is the serialization, held in a separate CRDT field.


2. Two CRDT fields per document

Each document is a Yjs Y.Doc carrying two synchronized types (packages/server/src/external-change.ts:63-64):

Both are Yjs CRDTs, so concurrent edits — from any number of humans and agents — merge by causal order with no explicit lock or merge step. YAML frontmatter is stripped before TipTap ingestion so config can live in the same file as editable content (packages/core/src/markdown/pipeline.ts).


3. The seam: where an agent's edit enters

  agent (Claude Code)
     │  MCP: write { path, content } / edit { path, find, replace }
     ▼
  ok mcp  (stdio)  ──► connects to collab server as a Yjs client
     │
     ▼
  applies change to Y.Text('source') + Y.XmlFragment('default')
     │
     ▼
  Hocuspocus broadcasts the Yjs update            packages/server/src/server-factory.ts:513-518
     │
     ├──► human's open editor renders it LIVE, agent avatar in presence bar
     └──► persistence commits it to git (07_git_sync_audit.md)

There is no separate "AI changes" code path. The MCP write/edit tools mutate the CRDT layer; from the editor's perspective the agent is a peer that happens to have an agent avatar. This is the inverse of the common "diff review" UX where AI output sits in a staging area — here it lands, and the review happens after, on git history and the activity panel.


4. Reviewing agent work — the safety rails

Because agent edits land live, OK invests in after-the-fact review (the docs are the authority here):


5. The collaboration server

Hocuspocus (server-factory.ts:513-518) runs five orthogonal extensions over the document stream (:545-699): persistence (flush to git on quiescence), liveDerivedIndex (maintain backlink/tag indexes as docs change), principalAuth (validate client token + expected branch), cc1Broadcaster (push file/backlink/graph/tag changes to clients), and serverObserver (track who's focused on what). Adding a concern is adding an extension, not threading a new code path through the sync loop.


What's worth stealing (for Swisscheese)

  1. Agent-as-peer, not agent-as-stage. Letting agent output land in the live document — with strong after review (activity panel, append-only timeline, selective per-agent rollback) — is a different bet than diff-gating everything up front. For multi-agent review it means N reviewers can annotate the same artifact concurrently and you reconcile by CRDT, not by queue.
  2. Selective rollback by author. "Undo everything this agent did in this file" is exactly the control you want when one of five parallel agents goes off the rails.
  3. Append-only restore. Recovery that writes a new version instead of deleting keeps the audit trail intact — a reviewer can always see what was reverted.
  4. Conflict freeze applies to agents too. A frozen-doc invariant that binds humans and MCP writers prevents an agent from blindly overwriting a contested change.
  5. Orthogonal extensions over one stream. Auth, persistence, indexing, presence as separate Hocuspocus extensions is a clean template for layering governance onto a shared-state server.