dropWindow

fun dropWindow(self: ReplicaId, dropped: Set<RgaId>): Pair<Rga<V>, Patch<Rga<V>>>?

Drop dropped from this log — the un-gated history-windowing path (#254), not the causal-stability barrier of compact.

Windowing deliberately forgets position, so unlike compact it may drop a live element and needs no stability gate: reroot-to-HEAD keeps the retained window reachable, and a concurrent Insert(J, after = dropped-I) resurfaces at the window boundary rather than being orphaned.

The drop is recorded in the cheapest sound form. This replica's own dots that form a contiguous run up from compactedBelow[self] + 1 fold into the floor — O(authors), and the reason a windowed log stops growing. Everything else (a foreign author's dots; own dots above the first retained one) keeps an explicit RgaOp.Compact entry, which costs one (RgaId -> RgaId) pair each.

Only self's floor entry is ever raised. Raising a foreign author's would annihilate a dot that author may not have minted yet; this replica, by contrast, can never hold an undelivered dot of its own. (The reason is not that a single-author log is somehow safe — see compactedBelow, where the reorder is shown to bite within one author too.)

The floor's positional reroot degrades to RgaId.HEAD. A floor writes no RgaOp.Compact.positions, so a survivor whose predecessor this call floored away re-roots to HEAD rather than to that predecessor's surviving ancestor, and can overtake older HEAD-anchored records. That is a stated part of this contract, not a defect: see compactedBelow for why it is accepted. Refusing to floor past a dot that still has a surviving successor — the barrier compact uses — would reclaim nothing at all under a drop-oldest window, which is the whole reason this entry point exists.

The floor is reported through causalFloor, not causalDots. A raised floor purges its ops and — unlike RgaOp.Compact — records no id set, so those dots leave causalDots entirely. A consumer folding a delivered frontier must therefore read the two together (a dot is delivered if it is in causalDots or at-or-below causalFloor); reading only the dots would stop the walk at the first swallowed seq, and since the floor is downward-closed that seq is 1, collapsing the author's frontier to 0 — a regression that, once gossiped, would leave compact's condition 3 (delivered.dominates(frontierMax)) permanently unsatisfiable for that author. Quilter reads both (#2127); a consumer that folds its own frontier must do the same.

Return

(newState, delta) — the delta is a minimal Rga, wrapped as a Patch so it cannot be swapped with the state at a destructuring site, that any peer absorbs through piece to perform the same drop — or null if dropped is empty.

Samples

val a = ReplicaId("A")

var log = Rga.empty<String>()
var after = RgaId.HEAD
val ids = (1..5).map { i ->
    val (next, op) = log.insertAfter(replica = a, after = after, value = "entry-$i")
    log = next
    after = op.id
    op.id
}
val peer = log // a peer that still holds all five inserts

// Retain the newest two; drop the rest.
val (windowed, delta) = checkNotNull(log.dropWindow(self = a, dropped = ids.take(3).toSet()))
check(windowed.toList() == listOf("entry-4", "entry-5"))

// This replica's OWN dots fold into a floor — one entry per author, not one per element.
check(windowed.causalFloor()[a] == 3L)
check(windowed.compactOpCount == 0)

// The drop is permanent suppression, not deletion: merging the peer's log back in
// re-purges the dropped entries instead of resurrecting them.
check(windowed.piece(peer).toList() == listOf("entry-4", "entry-5"))

// Any peer performs the same drop by absorbing the returned delta.
check(peer.piece(delta.delta).toList() == listOf("entry-4", "entry-5"))