The PR filtered a foreign tenant root only in hermes_cli.gateway.host_multiplexer_serving; the
seam `gateway run` actually goes through had no cross-tenant path, so tenant B's gateway still
never started: host_attach.decide() answered ATTACH (exit 0, nothing running) on tenant A's
record "serving default", and run._claim_host_gateway_role lost the per-OS-user host lock to A
and refused 75 forever (a race B can never win).
* gateway/host_attach.py: one predicate, launched_by_other_tenant(owner_home, our_home), used by
decide() (foreign owner -> START), by the lock-loss branch of _claim_host_gateway_role (start
beside it, WARNING), by host_multiplexer_serving (replaces its inline copy) and by
host_topology._from_host_record (doctor / cron status / dashboard ladder no longer report a
foreign tenant's process as this tenant's host gateway).
* gateway/host_topology.py + gateway/status.py: HostGatewayTopology carries the launch home, and
multiplexer_liveness_for_profile reads the multiplexer's gateway_state.json from THAT home, so a
named-hosted multiplexer no longer projects a stale standalone record from the default root.
* hermes_cli/gateway_multiplex_mode.py: recorded_standalone_warning_lines gates on gateway_state
+ live PID only; a paused/wedged-heartbeat live gateway still warns.
* docs: `hermes -p X gateway restart` on a parked profile with no live gateway behaves as start.
Tests: one regression per finding (decide()+lock loss; topology home+tenant filter), both red on
the PR head. tests/gateway/test_host_gateway_lock_refusal.py publishes its record from the
process home instead of an arbitrary tmp dir (the home was never consulted before; assertions
unchanged). test_gateway_multiplex_mode case 3 flips to "stale heartbeat + live PID still warns".