Review F1: --ws-only is now OPT-IN (HERMES_DESKTOP_WS_ONLY=1). The slim
server has no HTTP routes while the desktop's hermes:api REST plane only
speaks http — shipping it on-by-default made every REST call fail with
'Unsupported Hermes backend URL protocol: ws:'. The descriptor keeps
baseUrl http-only and flags the transport via wsOnlyTransport instead of
overloading baseUrl. Default flips after the REST consumers migrate to
JSON-RPC (#94484 phase 3).
Review F3: entry_ws.run() fails closed on non-loopback hosts — the static
query-token auth is the desktop loopback shortcut, not a posture fit for
network exposure (no gated one-time-ticket auth).
Review F2 (test half): tests/test_tui_gateway_entry_ws.py drives a REAL
websockets-15.0.1 server + sync client through the actual handshake —
valid token accepted (path read from the v15 ServerConnection), missing/
wrong token rejected with 4401, plus the loopback guard both ways.
The desktop app spawns `hermes serve --ws-only` instead of `hermes serve`.
The slim server (tui_gateway/entry_ws.py) uses the bare websockets library
to call handle_ws directly — same dispatch surface, same 158 RPCs, same
events, zero HTTP framework. tui_gateway.server has zero FastAPI imports;
the slim server never touches web_server.py (19.8K lines) at all.
Full backward compat: older runtimes strip --ws-only and fall back to
regular serve (still headless, just through uvicorn).