1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
//! Phase 1 of the RelayCell backpressure plan — the merge algebra and the
//! `Reactive` read supertype.
//!
//! See `lazily-spec/docs/relaycell-backpressure-analysis.md`:
//!
//! - §4.0 — the reactive primitives. `Reactive<T>` is the read supertype
//! (`get` + `subscribe`); `Source<T>: Reactive<T>` adds `set`/`merge`, so a
//! non-settable reader-kind (a derived Slot) is correctly typed read-only.
//! - §4.3 — `MergePolicy`, the algebra trait. A merge `⊕ : T × T → T` folds
//! accumulated ops; the *properties* it satisfies (associativity always;
//! commutativity/idempotency per transport contract) select which overflow
//! behaviour is sound. `MergeCell<T, M>` generalizes `Cell`
//! (`Cell ≡ MergeCell<KeepLatest>`): a source whose write is a merge.
//!
//! Associativity is the irreducible core (§2) and is *not* a runtime flag — it
//! is a law every policy must satisfy, verified by the property tests in
//! `tests/merge_laws.rs`. The two independent branches — commutativity (the
//! reordering tax) and idempotency (the durability tax) — are surfaced as
//! `const` flags so a relay can validate its (overflow, transport) choice
//! against the algebra at construction (Phase 2+).
use BTreeSet;
use PhantomData;
use Add;
use crateCellCrdt;
/// The coalescence algebra: an associative fold `⊕ : T × T → T`.
///
/// `merge(old, op)` accumulates the operation `op` into the current state
/// `old`. The single non-negotiable requirement is **associativity**
/// (`merge(merge(a, b), c) == merge(a, merge(b, c))`), which licenses the
/// variable flush points a bounded relay uses: regrouping a run of merged ops
/// never changes the converged state (analysis §2). Associativity is enforced
/// by the law-tests, not by a flag.
///
/// The two independent, transport-selected properties are exposed as `const`
/// flags:
///
/// - [`COMMUTATIVE`](MergePolicy::COMMUTATIVE) — needed only when ops may be
/// applied out of order (the *reordering tax*).
/// - [`IDEMPOTENT`](MergePolicy::IDEMPOTENT) — needed only for at-least-once /
/// crash-replay durability (the *durability tax*). For an idempotent `⊕`,
/// re-applying the same op is a no-op — which is exactly the `PartialEq`
/// store-guard one layer up, giving free dedup.
/// Keep-latest (right-zero) band: `old ⊕ op = op`. Associative and idempotent,
/// **not** commutative. This is the merge behind a plain [`Cell`](Source) —
/// `Cell ≡ MergeCell<KeepLatest>` (analysis §4.0). Positional last-writer-wins;
/// distinct from timestamped [`Lww`](crate::LwwRegister) (which is commutative).
;
/// Additive commutative monoid: `old ⊕ op = old + op`. Associative and
/// commutative, **not** idempotent (re-adding double-counts). The
/// unordered-exactly-once tier (analysis §2): a running counter / sum.
;
/// Max semilattice: `old ⊕ op = max(old, op)`. Associative, commutative, and
/// idempotent — the full-CRDT corner for a totally-ordered value.
;
/// Set-union (grow-only) semilattice: `old ⊕ op = old ∪ op`. Associative,
/// commutative, idempotent. The unordered-at-least-once tier (analysis §2).
;
/// Raw FIFO append: `old ⊕ op = old ++ op`. Associative (concatenation is a
/// free semigroup) but **neither** commutative nor idempotent — order and
/// multiplicity are meaning (analysis §2, `protocol.md` §176). A `RawFifo`
/// stream cannot conflate; its only bounded-lossless option is Spill.
;
/// Blanket semilattice policy over any existing [`CellCrdt`] unit — wires the
/// `#lzsync` CRDT registers (`LwwRegister`, `MvRegister`, `PnCounter`) into the
/// merge algebra without reimplementing their join. `merge` folds via
/// [`CellCrdt::merge_from`], which is contractually commutative, associative,
/// and idempotent (a join semilattice), so all three properties hold.
///
/// - `CrdtJoin<LwwRegister<T>>` — timestamped last-writer-wins (commutative,
/// unlike positional [`KeepLatest`]).
/// - `CrdtJoin<PnCounter>` — increment/decrement counter.
/// - `CrdtJoin<MvRegister<T>>` — multi-value (concurrency-retaining) register.
;
// ---------------------------------------------------------------------------
// Cell kernel migration (`#lzcellkernel`)
// ---------------------------------------------------------------------------
//
// The former `MergeCellHandle<T, M>` struct and the vestigial `Reactive<T>` /
// `Source<T>` read/write traits are **deleted**. A "merge cell" is now just a
// `Source<T, M>` with `M != KeepLatest`, and a plain source cell is `Source<T>`
// = `Source<T, KeepLatest>` — the identity `Source ≡ Source<T, KeepLatest>` is a
// default type parameter, not a spec assertion. Write protection lives on the
// inherent `impl<T, M: MergePolicy<T>> Source<T, M>` (see `cell.rs`), so
// `computed.set(…)` fails to compile with no trait in sight.