24f404f989
memberHerdrSocket splits lead operations from member operations onto two herdr daemons. Three seams still assumed one shared daemon and broke silently when the two clients differ (all three collapse to today's behaviour when they are the same object): 1. ConnectionIdentity's PaneLocator was pinned to the member daemon only, so a lead's own MCP connection (which lives on the LEAD daemon) resolved to terminal == null, breaking fleet_reply/fleet_ask/fleet_whoami for a lead. PaneLocator now searches the lead client first, then the member client. 2. StatusPoller's StatusRefiner was pinned to the member daemon, so refining an UNKNOWN status for a lead target read the wrong daemon's pane content and never left UNKNOWN, wedging status-gated delivery to that lead forever. StatusRefiner gained a refine(target, raw, control) overload and the poller now refines through the same AgentControl the raw status was sampled from. 3. FleetApp was constructed with the raw lead-only herdr client, so /healthz stayed green while the member daemon was down (every spawn then fails invisibly) and GET /sessions silently dropped every member workspace. FleetApp now takes both clients: healthz requires both to answer, sessions merges workspaces from both. Each fix has a test proven to fail without it (verified by reverting the production change and re-running): FleetdConnectionIdentityConstructionTest / FleetdFleetAppConstructionTest assert the actual Fleetd.java wiring (the same technique as FleetdHerdrControlConstructionTest); StatusPollerRoutingTest and the new PaneLocatorTest/FleetAppTwoDaemonTest cases exercise the real production classes end to end rather than a hand-built object graph.