core/docs/zig/crdt-substrate
..
implementation-slices.md
README.md

Zig Guidance — Delta-CRDT Substrate

Status: doctrine / prototype candidate
Component: Delta-CRDT arena, delta, join, merge kernel, content-addressed ordering
Primary governing ADR: ADR-0180

This is the strongest near-term Zig candidate in CORE.

The CRDT substrate is not semantic cognition. It is the mechanical substrate for concurrent modality write accumulation: thread-local arenas emit canonical deltas, and an explicitly mounted merge kernel folds those deltas into a global Vault-visible state without making final recall approximate or arrival-order dependent.


Why this component is suitable for Zig

The CRDT substrate wants properties Zig is good at providing:

  • explicit allocator ownership;
  • small native surface area;
  • deterministic byte-level ordering;
  • stable C ABI;
  • edge-native build story;
  • predictable memory layout;
  • no garbage collector;
  • no hidden runtime;
  • precise caller-owned buffer contracts.

This is not a broad language preference. It is a substrate fit.


Existing contract to preserve

ADR-0180 states that the semilattice claim holds only at the vault/store layer, not at versor_apply, not at field/propagate, and not at trace reduction. The CRDT substrate must shard write accumulation only.

Required law:

ProjectionHead.project       pure signal projection
versor_apply                 non-commutative, do not shard unless serialized
field propagation            not a CRDT merge
vault/store.write            semilattice-eligible write accumulation
recall result ordering       content-addressed, not arrival-addressed

The existing Rust substrate already implements the conceptual shape:

ArenaEntry { versor: [f32; 32], provenance: Vec<u8> }
Delta      { entries: sorted/deduped ArenaEntry list }
LocalArena { thread-local write cache }
merge_kernel(deltas) -> canonical Delta

Zig may challenge this substrate only by preserving the same laws.


What should be in Zig

A Zig CRDT lane should include:

core-zig/src/crdt/entry.zig
core-zig/src/crdt/arena.zig
core-zig/src/crdt/delta.zig
core-zig/src/crdt/merge.zig
core-zig/src/crdt/hash.zig
core-zig/src/crdt/ffi.zig
include/core_crdt.h

ArenaEntry

Should represent one content-addressed write:

versor: [32]f32
provenance: []const u8

The content key is:

raw IEEE-754 f32 bits of all 32 components
+ provenance bytes

The substrate must not compare floats numerically for canonical ordering. It must compare bytes/bits to avoid platform-dependent NaN, -0.0, and +0.0 behavior.

LocalArena

Should be thread-local and share-nothing.

Allowed:

push local entries
snapshot to Delta
clear/drain if explicitly requested by owner
report pending count

Forbidden:

write global Vault
spawn hidden merge thread
normalize entries
repair bad versors
infer epistemic status
call object-store/S3/cloud code

Delta

A Delta must be canonical:

entries sorted by content key
byte-identical duplicates removed
stable independent of insertion order

merge_kernel

The merge kernel must be explicit, not hidden.

Required behavior:

input: list of Deltas
output: one canonical Delta containing their union
law: permutation-invariant
law: duplicate-delta idempotent
law: content-addressed ordering only

Minimum C ABI sketch

typedef struct CoreCrdtArena CoreCrdtArena;
typedef struct CoreCrdtDelta CoreCrdtDelta;

typedef struct CoreCrdtError {
    int code;
    char message[256];
} CoreCrdtError;

CoreCrdtArena* core_crdt_arena_new(void);
void core_crdt_arena_free(CoreCrdtArena* arena);

int core_crdt_arena_push(
    CoreCrdtArena* arena,
    const float versor[32],
    const unsigned char* provenance,
    unsigned long provenance_len,
    CoreCrdtError* err
);

int core_crdt_arena_snapshot(
    const CoreCrdtArena* arena,
    CoreCrdtDelta** out_delta,
    CoreCrdtError* err
);

void core_crdt_delta_free(CoreCrdtDelta* delta);

int core_crdt_delta_join(
    const CoreCrdtDelta* a,
    const CoreCrdtDelta* b,
    CoreCrdtDelta** out_delta,
    CoreCrdtError* err
);

int core_crdt_merge_kernel(
    const CoreCrdtDelta* const* deltas,
    unsigned long delta_count,
    CoreCrdtDelta** out_delta,
    CoreCrdtError* err
);

int core_crdt_delta_hash(
    const CoreCrdtDelta* delta,
    unsigned char out_sha256[32],
    CoreCrdtError* err
);

This is illustrative, not final. The final ABI must be ratified before implementation is considered supported.


What must stay out of Zig

The CRDT substrate must not own:

  • epistemic status promotion;
  • review decisions;
  • teaching proposal admission;
  • pack ratification;
  • semantic normalization;
  • recall scoring policy beyond canonical store order;
  • object-store sync;
  • hidden background execution;
  • modality compilation semantics, except when called as a separate compiler component.

The CRDT substrate is storage-order law, not cognition.


Required proof obligations

C-1 — Commutativity

join(a, b) == join(b, a)

C-2 — Associativity

join(join(a, b), c) == join(a, join(b, c))

C-3 — Idempotence

join(a, a) == a

C-4 — Permutation invariance

merge_kernel([d1, d2, d3]) == merge_kernel(any_permutation([d1, d2, d3]))

C-5 — Duplicate re-ingest is no-op

merge(existing, already_seen_delta) == existing

C-6 — Recall order invariance

Equal-score recall must not depend on wall-clock arrival. The canonical merged order must be content-addressed so tie breaks are replay-stable.

C-7 — No hidden global mutation

Tests must prove that pushing to an arena never mutates the global Vault. Only explicit merge publication may alter the global visible state.


Migration sequence

  1. Keep Rust implementation as incumbent.
  2. Add Python tests that pin CRDT laws against the current behavior.
  3. Add Zig prototype behind CORE_CRDT_BACKEND=zig.
  4. Compare Zig against Rust/Python reference on canonical fixtures.
  5. Add benchmark only after parity passes.
  6. Promote only if Zig wins on ABI, deployment, memory, or performance.

Promotion criteria

Zig should become the preferred CRDT substrate only if it demonstrates:

  • equal or stronger deterministic law coverage;
  • simpler C ABI for modality compilers and edge runtime;
  • explicit allocation lifecycle that is easier to audit than the incumbent;
  • no loss in exact recall behavior;
  • observable merge state;
  • clean failure when absent or stale.

Until then, Zig remains a prototype lane, not a replacement.