consolidateEmbroideries

Returns a Draft where independent DraftStage.Embroider nodes at the same dependency level are fused into a single DraftStage.BatchedEmbroider.

Theory: the minimum number of coordination rounds equals the depth of the coordination dependency DAG, not the count of individual embroideries. Two embroidery nodes are independent when neither is a transitive ancestor of the other — they can be committed in a single consensus round (one BatchedEmbroider) rather than two sequential rounds.

Dependency level: computed bottom-up in topological order. A coordinated node has level 0 when it has no coordinated ancestors; otherwise level 1 + max(levels of its coordinated ancestors). Two nodes at the same level are guaranteed independent (no mutual ancestor path), so fusion is safe.

Graph contraction: for each level with two or more coordinated nodes, the fused set is replaced by a single new DraftStage.BatchedEmbroider node whose predecessors are the union of the fused nodes' predecessors outside the fused set. Successors of the fused nodes are rewired to the new node. All non-coordinated structure and all edges are preserved.

Idempotent: a second call produces the same result as the first — a lone DraftStage.BatchedEmbroider at some level is the only coordinated node at that level and is not fused further.

Result-preserving: the returned Draft is structurally equivalent to the receiver under isEquivalentTo (same sources, same multiset of embroider opIds, same free-op multiset).

Samples

val combined: Draft<Unit> = Warp.shuttle(OpId("source.docs")).embroider(OpId("embroider.rank"))
    .combine(Warp.shuttle(OpId("source.scores")).embroider(OpId("embroider.vote")))

val consolidated = combined.consolidateEmbroideries()

// Two independent embroideries become one BatchedEmbroider — one consensus round.
check(consolidated.nodes.any { it.stage is DraftStage.BatchedEmbroider })
check(consolidated.nodes.count { it.stage.coordinationKind == CoordinationKind.Coordinated } == 1)
// Semantic equivalence: same sources, same embroider multiset, same free-op multiset.
check(combined.isEquivalentTo(consolidated))