causalDots

open fun causalDots(): Set<Dot>

The causal Dots this state has delivered — (author, author-seq) per op.

This is the capability the causal-stability GC of ADR-003 addendum v3 (#262) needs without breaking Quilted's genericity: a Quilter generic over Quilted<S> cannot know about any one CRDT's internal op identities, so the CRDT exposes them here. The replicator folds these dots into a contiguous delivered VersionVector (highest gap-free seq per author) and gossips it.

Only op-based CRDTs whose elements carry per-author dense Dots participate — in this zoo the LogOp-based op-log types Rga and Fugue, and MovableTree, which keeps an equivalent log of its own. For the LogOp-based pair the per-op rule is LogOp's own KDoc, and that is the source of truth for it rather than this paragraph: a LogOp.Insert contributes the dot it mints, a LogOp.Compact contributes every dot it recorded, and a LogOp.Remove contributes nothing — it reuses its target insert's id and mints no dot. Re-emitting a compaction's recorded dots is precisely what keeps the delivered frontier gap-free across GC. Composites (JsonCrdt, LatticeProduct) union what their children report; every other delta-state CRDT in the zoo (GCounter, ORSet, …) does not use this GC path, and the default empty set keeps the capability non-breaking for them — they contribute nothing to any delivered vector.

This is only half the delivered surface. A consumer folding a delivered frontier must read causalDots() ∪ {dots at-or-below causalFloor()} — the union is the contract, not a partition. The two halves are not guaranteed disjoint: Rga.dropWindow's contiguity walk can raise the floor past an own dot a still-retained Compact op already recorded (stepping over an inherited or previously-explicit Compact so the floor doesn't wedge below it), leaving that dot beneath the floor and still re-emitted here. The overlap is harmless — every consumer only ever asks "was this dot delivered," never "which half reported it."