tieredSeam
Bond a local-tier and a peer-tier Seam — two views of the same node onto two disjoint peer sets — into one Seam whose roster is the union of both.
The motivating case (game-overlay slice 6) is a federated per-game seam: the local tier is a room's RoomHubSeam (the members physically connected to this server) and the peer tier is NamedMux(coreMesh).channel(gameId) (the other servers, one hop across the core mesh). A per-game broadcast must reach the local room and cross to the other servers — two transports, two rosters — so this presents them as one seam. The primitive itself knows nothing about rooms, games, or clusters: it is a generic seam composition, beside us.tractat.kuilt.core.composite.CompositeSeam / RoomHubSeam / NamedMux.
Contract
peers is the live union
local.peers ∪ peer.peers, recomputed whenever either tier's roster changes. The two rosters are assumed disjoint; if they overlap, the union simply dedups by PeerId (a shared id resolves to one entry, and sendTo routes it to the local tier — see below).incoming is the merge of both tiers'
incoming. This seam becomes the sole collector of both underlying seams'incoming(started eagerly on scope) and its own incoming is itself single-collection (collect once, per the ADR-034 contract). Callers must not collect either underlying seam'sincomingelsewhere — exactly as NamedMux and RoomHubSeam own the collection of what they wrap.broadcast tees to BOTH tiers (the frame reaches the local room and crosses to the other servers). Each side is best-effort and independent: a failure on one tier never prevents the other from being attempted.
sendTo routes to whichever tier owns the addressed peer —
peer ∈ local.peers→local.sendTo, elsepeer ∈ peer.peers→peer.sendTo, else the peer is absent from the union and PeerNotConnected is thrown, as Seam.sendTo requires of every fabric (#1935). It never fans to both: unicast stays single-addressee across the union, preserving the ADR-005 single-addressee leak boundary. (A shared/overlapping id resolves to the local tier, since it is checked first.)selfId — both tiers are the same node, so
local.selfIdmust equalpeer.selfId; construction throws IllegalArgumentException otherwise.state is the composed lifecycle: Woven while either tier is Woven (the surviving tier carries), Weaving while forming, and Torn — terminal, latched — once both tiers are Torn or close is called. Both-tiers-torn is genuinely terminal here (not a revivable rollup) because this union's incoming is a one-shot merge that completes permanently when both tiers'
incomingcomplete — so reporting a recoverableWeavingwould contradict a terminally-completedincoming. This differs from us.tractat.kuilt.core.composite.CompositeSeam, whose persistent spool survives ply churn, so its all-plies-torn rollup is recoverableWeaving(#1367). close closes both tiers.
Thread safety
Correct under a multi-threaded dispatcher, by real primitives — never single-thread confinement. state runs through a SeamStateGate: the combine state pump publishes via update() (a no-op once torn) and close latches Torn via tear(), so no in-flight pump write can overwrite the terminal state and tear()'s single-shot return subsumes the old close latch. peers is written from a single combine collector, but that write races collapseRoster, so both are guarded by a small reentrantLock with the collapse marker folded into the same critical section — a post-collapse peers emission cannot resurrect the roster. The marker rather than a read of state is load-bearing: Seam.peers requires the collapse to be published before the Torn latch, so mid-close there is an instant at which the roster is collapsed and state is not yet terminal. incoming flows through a bounded Spool.
Parameters
required parent scope for the union/incoming pumps — no real-dispatcher default (a default would silently decouple the pumps from a test's virtual clock). The internal coroutines run on a child of this scope so close cancels them without tearing the caller's scope.
governs the merged inbound Spool's capacity/overflow. Defaults to DeliveryPolicy.Reliable (bounded, backpressured, lossless).