architecture, in one page
One Postgres, three layers, two tiers of inference.
data model
The prose document and the claim graph are two views of one transactional source of truth. The relational layer holds documents, revisions, sources, users, and orgs. Apache AGE 1.6.0 holds the graph: typed claim vertices and edges (supports · contradicts · qualifies · depends_on). pgvector 0.8.2 holds embeddings of bibliography passages as 1024-dim vectors with an HNSW index.
All three layers are queryable in one SQL transaction. There is no cross-database sync to manage, no eventual consistency window, no separate vector or graph service to keep healthy.
inference
Two tiers. Haiku 4.5 handles the high-frequency, low-stakes work — running on every paragraph change to detect claims and classify them. Round trip to claim cards in the side-pane: ~200ms.
Sonnet 4.6 handles the low-frequency, high-stakes work — verification (with tool use over the bibliography and Exa web search), pairwise contradiction scanning, reconciliation drafting, the hostile-NYRB-critic, the reverse outline, and the voice-matched co-writer. Sonnet is invoked on demand or on save, never on every keystroke.
CRDT layer
Yjs handles concurrent edit merging. v1 runs in-memory only; the doc’s prose is persisted as plaintext (documents.proseText) for search and the public viewer. v2 wires the WebSocket relay over Cloudflare Durable Objects for live multi-user collab.
eval gate
Every PR runs the Braintrust eval suite. The current gate is type_match ≥ 0.85 on the claim-detector against a 30-paragraph hand-labeled gold set. Drops greater than 0.05 below baseline block merges. Last run: 86.36%. The harness, the dataset, and the scorers are checked in.
decision rationales
Every load-bearing technical choice — Azure over Neon, AGE over Neo4j, Drizzle over Prisma, Tiptap over Slate, Newsreader over Inter, Haiku-Sonnet routing over uniform inference — is logged with its tradeoff and revisit conditions in docs/decisions.md.