11f8709286
Introduce the router the core holds when more than one adapter is configured: one HerdrPeerLauncher per peer kind, dispatched by profile (spawn/effectiveCwd/parityOverlay), by pane id (stop, via a spawn-time owner map), and fanned out + combined for the fleet-wide queries (list dedup by pane id, reap/caps union, profiles union). The ctor rejects an empty adapter list and a profile two adapters both claim. Wire it in Bridged.main: partition workerProfiles() by kind (claude-code is the always-present default adapter; opencode is added when any profile opts in) and front both with the composite. This lets BridgeMcp and BridgedApp finally take the PeerLauncher SPI instead of a concrete ClaudeCodeLauncher — the two (ClaudeCodeLauncher) casts in Bridged are gone. list() elements are cast to herdr Agent at the point of the herdr-specific roster view, where that assumption actually lives. Add BridgedConfig.Worker.isClaudeCode()/isOpenCode() kind predicates (the wiring uses isOpenCode; both are unit-tested). Drop the long-dead 'rendezvous' constructor param threaded into BridgeMcp and BridgedApp. 10 CompositePeerLauncherTest cases over two real adapters on one FakeHerdr: profile routing (observed via the started agent's claude-/opencode- name prefix), default resolution, unknown-profile and duplicate-profile rejection, caps union, list dedup, reap sum, and stop teardown. 266 tests green.