clusterClient
Constructs a ClusterClient connected to the relay-room cluster.
Manages the full connect → use → reconnect lifecycle:
Connects to the initial endpoint via loom.
Backs a ManagedRaftTransport with the resulting us.tractat.kuilt.core.Seam.
Constructs a single RaftNode over that transport — it lives for the ClusterClient lifetime, across reconnects.
On transport tear: advances ServerClusterReconnect to the next endpoint, re-joins via loom, and swaps the backing us.tractat.kuilt.core.Seam in the ManagedRaftTransport — the RaftNode is not recreated.
Cross-server resume
A cross-server failover always requires a fresh join (proven by #532): each server's reconnect-window registry is in-memory and per-room-instance, so ResumeResult.WindowClosed is the invariable response. This extension therefore always performs a plain loom.join() on every reconnect — there is no optimistic resume attempt at the Seam level.
Dispatcher injection
The CoroutineScope receiver IS the dispatcher injection point. All background work (reconnect loop, relay coroutines inside ManagedRaftTransport) runs on the caller's dispatcher. No real-clock defaults are introduced.
Parameters
The Loom fabric for connecting to server endpoints.
Endpoint list and rotation policy.
Stable NodeId for this client — must be in ClusterConfig.learners.
Full cluster membership (voters + this learner).
Raft timing and dedup configuration.
How this client obtains its Raft §8 dedup id. ClientIdentity.Auto (default) mints a per-incarnation id; pass ClientIdentity.Durable with a stable ClientId for cross-crash exactly-once.
Injected clock for session resume-token timestamps. Required — no real-clock default (prevents silent virtual-time breakage per the "optional ≠ tuning" policy). Reserved for future session-layer resume; currently unused at the Seam level.