reconcile

suspend fun reconcile(child: GroupId, timeout: Duration? = null): ControlOutcome

Reconcile the budget stranded on child's RETIRED inbound edge(s) by re-homing everything they carry — net inflow and already-charged service — onto child's live inbound generation, serialized through the log (design §9 #3, §5.4; issue #1665). It removes the permanent LedgerConflict.PersistentNegativeHoldings / LedgerConflict.PerEdgeSafety / ClosureViolation left by a raced advisory-retire followed by a legal reparent.

The move is conserving: it relocates already-minted units through counters that only ever grow (a net decrease expressed as a second, cancelling counter), so mintedTotal is unchanged and the global conservation identity is restored.

This peer computes no magnitudes at all

It opens a quiesce barrier over each of child's RETIRED inbound edges and then proposes a Reconcile carrying only the child. The patch is derived at apply time, on every peer, from the per-peer finals the fence recorded in the log. That is what retires #1669's standing caveat — "not a safety fence: magnitudes are read from this possibly stale view" — rather than carrying it forever: the magnitude is now a deterministic function of the log prefix, so a lagged, deposed or restarted proposer cannot commit a wrong one. The through-service case (spent(s) != 0), carved out and refused since #1669, is un-gated by exactly this.

Applied in two acts — expect to call it twice

The barriers commit here; the acks are separate committed acts that land afterwards. So the first call typically returns ControlConflict.Refused naming the replicas it is waiting on, and the caller retries once pendingAcks is empty. Refusing rather than blocking is the deliberate shape: the fence's completion is as available as the slowest enrolled peer, and a caller that hung on it would be waiting inside a recovery path with no bound.

The readIndex() leader-authority check is kept as a cheap pre-propose courtesy only — with the magnitude derived at apply, a stale or deposed proposer's Reconcile is refused or correctly derived at apply regardless (§6.2 step 4 corollary), so it is no longer load-bearing.

Refusals — ControlConflict.Refused, fail-closed, nothing written. No unique live inbound edge; a RETIRED inbound edge that does not share the live edge's parent (§5.2's telescoping precondition — reparenting across parents stays legal, re-homing a strand across one does not); no RETIRED inbound edge; a barrier not yet open; a barrier still missing acks; nothing left stranded (already reconciled); or a transfer-tangled strand, where a replica's acked finals leave it net-negative on the edge and re-homing faithfully would have to move transfer rows too (out of scope). A refusal leaves the conflicts standing — safe and recoverable — never a silent conservation break.