newLoomPair
Provide a fresh host/joiner Loom pair per test.
.firsthosts via host(pattern) (weave(Rendezvous.New(pattern))).secondjoins via join(joinTag()) (weave(Rendezvous.Existing(joinTag()))) In-process radio fabrics return the SAME instance twice: (loom, loom). Role-split fabrics return DISTINCT host/joiner Looms wired to reach each other.
Scope-aware variant used by every runTest-based test below. Stateless fabrics ignore testScope — the default delegates to the no-arg newLoomPair.
Started/stateful seam implementations override this to start their background work (inbound loops, timers, view managers) on testScope.backgroundScope, whose coroutines are cancelled before runTest's terminal time-advance. Starting such a seam on the test's structured scope would either block the test (structured- concurrency join) or spin its terminal advanceUntilIdle on a re-arming timer; the backgroundScope is the only correct home. A seam started here may also read virtual time from testScope.testScheduler.