3.6 KiB
3.6 KiB
ADR-0004: chronogrid_core – Automerge CRDT Integration for Task & Note Registers
- Status: Accepted
- Date: 2026-08-20
- Deciders: Michael Kell
Context & Problem Statement
Task 1.4 requires integrating the Automerge CRDT engine into chronogrid_core so that task and note entities can be modified concurrently by different peers and merged deterministically without centralized coordination. The architecture spec (03-crdt-sync-protocol.md) mandates LWW-Element-Set registers for primitive fields and Hybrid Logical Clocks (HLC) for causal ordering.
Options Considered
- Manual LWW register implementation — track per-field HLC timestamps in a custom data structure and resolve conflicts manually.
- Automerge integration with HLC companion stamps — use Automerge's built-in CRDT merge semantics for structural conflict resolution, augmented with HLC timestamps stored inside each document for causal ordering context.
- Yrs (Yjs Rust port) — alternative CRDT library focused on text collaboration.
Decision Outcome
Chosen Option: Option 2 — Automerge + HLC because:
- Automerge provides battle-tested CRDT merge, fork, save/load, and delta-sync primitives out of the box.
- Storing HLC timestamps as companion fields inside the Automerge document aligns with the spec's requirement for HLC-based LWW conflict resolution while leveraging Automerge's deterministic merge for structural integrity.
- The
automergecrate (v0.5.12) has a stable API withAutoCommit,ReadDoc, andTransactabletraits that map cleanly to our per-entity document model. - Yrs is optimized for text sequences, not key-value LWW registers.
Implementation Details
automerge = "0.5"added tochronogrid_core/Cargo.toml(resolved to v0.5.12).uuid = "1"withv4feature added for entity ID generation.- Schema extension:
crdt_docstable added toschema.sqlwith columnsentity_id TEXT PK,entity_type TEXT,doc_bytes BLOB,updated_at INTEGER, plusidx_crdt_docs_typeindex. - Module structure:
crdt/sub-module withhlc.rs,doc.rs,task.rs,note.rs. - HLC:
Hlcstruct withtick(),update(),Display/FromStr(format:{wall_ms:016}-{counter:08x}-{node_id}), and fullOrdimplementation ensuring lexicographic string order matches logical order. - CrdtDoc: Generic wrapper over
AutoCommitproviding typedput_*/get_*accessors for String, f64, i64, u64, bool scalars at the document root. - TaskCrdt / NoteCrdt: Entity-specific wrappers with field-level setters that automatically advance the HLC and record it in the document.
- Database persistence:
save_crdt_doc(),load_crdt_doc(),delete_crdt_doc()methods onDatabasefor upsert/load/delete of serialized Automerge bytes. - 45 unit tests covering: HLC ordering, tick/update/parse, all scalar types, save/load round-trips, fork/merge conflict resolution, CRDT doc DB persistence, and schema validation.
Consequences & Trade-offs
- Positive: Full offline-first CRDT capability; entities can be forked, edited independently, and merged without data loss. HLC provides deterministic causal ordering for the SQL layer. Zero external network dependencies (local-first mandate satisfied).
- Positive: Automerge's compact binary format minimizes storage overhead for CRDT doc blobs.
- Negative: Automerge 0.5.x adds ~40 transitive dependencies; binary size increases moderately.
- Negative: Each entity requires both a SQL row and a CRDT doc blob, introducing a dual-write pattern that must be kept in sync (future work: transactional wrappers).