FilledByConstruction
The joiner's roster holds a remote by construction, so it would hold one whether or not join() recorded anything. Two in-tree shapes, worth distinguishing because they have different fixes:
a shared roster — both ends read one registry object, so registering the second seam fills both (
InMemoryLoom,ControllableLoom, andGossipSeam, whosepeersdelegates to its base). Splitting the fixture means giving each end its own backend.a seeded roster — the joiner's seam is constructed with the remote's id, so its roster is a constructor literal (
LinkSeam'ssetOf(selfId, remoteId), reached by everyidentified(…)harness). Splitting the fixture is not enough here: the seam would have to learn the id rather than be handed it.
Properties
which of those it is, what fills the roster, and — where the harness folds a genuinely role-split fabric into one process — the tracking URL for splitting it. Free prose on purpose: it is read by a human auditing whether a green joiner assertion meant anything, and the useful answer differs per harness.