Establishes the canonical Delta-CRDT reference contract so a future native
(Rust/Zig) backend is gate-G1-eligible under ADR-0196 — the ZC-0 'contract
pinning' slice. No Zig code; ZC-1+ remains gated at G2.
- vault/crdt.py: canonical Python reference (ArenaEntry, Delta, LocalArena,
merge_kernel, canonical_bytes, delta_hash). Pure content law — content-
addressed by IEEE-754 bits then provenance; no normalization, no versor
closure, no global Vault writes.
- ZC-0 contract tests (semilattice C-1..C-5; content ordering / signed-zero /
NaN bit-addressing; C-7 no-global-write) — all failable (mutation-checked:
no-dedup breaks C3/C5, arrival-order breaks C1).
- Golden fixture corpus (tests/fixtures/crdt/) regenerated deterministically
from the reference; single source of truth also emits the Rust expected hex.
- core-rs: Delta::canonical_bytes + test_crdt_hash_parity.rs proving Rust
produces byte-identical canonical_bytes to the Python reference.
- ADR-0180 -> Accepted: locked contract, byte layout, obligation map, and the
explicit boundary that no Zig is authorized.
Verification: ZC-0 21 passed, Rust arena+parity 16 passed, architectural
invariants 40 passed, smoke 67 passed. Serving frozen: 7/8 lane SHAs match;
the public_demo miss is a pre-existing wall-clock budget overrun (ADR-0099,
~46-48s > 30s) reproduced identically on clean main — environmental.
Implements ADR-0180 §4.1 item 1: the Delta-CRDT write-accumulation substrate
in core-rs/src/vault.rs.
- ArenaEntry: (versor, provenance) — provenance is part of the content key.
- LocalArena (§2.1): thread-local, share-nothing, lock-free write cache;
snapshot() emits a canonical Delta; non-destructive (flush/GC is the kernel's
concern, safe across the §3.2 eventual-consistency window).
- SemilatticeDelta trait + Delta (§2.2): join is commutative, associative,
idempotent under content-addressed equality (IEEE-754 versor bits +
provenance bytes), never arrival order — per the §2.2 amendment landed today.
- merge_kernel (§2.2): folds deltas into one content-addressed, deduped,
totally ordered set; permutation- and duplicate-invariant — the property
§4.3's hash(Sequential)==hash(Concurrent) rides on.
Pure-CPU only (§1.5.5): no MLX/UMA handshake, no Python binding — those are
downstream (§4.1 item 2; ADR-0181 PR-5). Existing vault recall/reproject paths
untouched; zero eval impact.
10 failable property tests in tests/test_arena.rs (mutation-verified: disabling
the content sort fails 6 of them loudly, per CLAUDE.md §Schema-Defined Proof
Obligations). Also fixes a pre-existing broken doctest in the vault.rs header
(indented math block was parsed as a Rust doctest).
ADR-0020 follow-on (task #35). Two-pronged fix:
1. Kernel: ported ADR-0019 Stage 1 diagonal-metric kernel to
core-rs/src/vault.rs. Per-versor scoring is now 32 multiplies
+ 32 adds via the precomputed Cl(4,1) metric, not the
1024-op full geometric_product the prior path computed.
Bit-identity preserved by serial fold order matching Python.
2. Zero-copy marshalling: replaced Vec<&PyAny> + extract-per-
versor with PyReadonlyArray2<f32> via the numpy Rust crate.
The Rust binding now reads a slice view directly into the
numpy buffer — no Python→Rust copy, no Vec<[f32;32]>
re-chunk. Python caller passes the (N, 32) ndarray as-is
(ascontiguousarray ensures C-contiguous f32).
Result:
N python rust speedup
1k 0.20ms 0.26ms 0.77x (Python wins on fixed overhead)
10k 1.62ms 1.45ms 1.12x
100k 19.22ms 12.93ms 1.49x
1M 251.50ms 131.36ms 1.91x
Parity bit-identical (raw f32 bytes) at every scale across the
parameterised test in tests/test_vault_recall_rust_parity.py.
Both ADR-0020 first-surface gates now pass: parity AND
performance at the scales where Rust is meant to win. Python
remains the default per CLAUDE.md sequencing rule 5;
CORE_BACKEND=rust is now a legitimate opt-in acceleration.
Smoke 27/27, algebra 70/70, runtime 19/19 all green.