2382f50f53
* fix(dashboard): retry stalled events feed reconnects * fix(dashboard): bound the PTY ticket request before the socket exists ChatPage's connect awaits a single-use ticket from `api.buildWsUrl()` before `new WebSocket()`. That request produces no socket, so a rejection or a hang emits no `close` event and never arms PTY_CONNECTING_TIMEOUT_MS (set after the socket is constructed). The tab stranded on "connecting" with `connectInFlightRef` stuck true, which also suppresses the page-resume reconnect path. Give the ticket phase its own deadline and route both failure modes into the existing backoff. A `ticketSuperseded` flag invalidates a late ticket result so a timed-out attempt cannot open a socket behind the replacement it scheduled, and cleanup clears the timer on unmount. `scheduleReconnect` now takes `number | null` so an attempt that died before any socket existed omits the "(code N)" banner suffix instead of inventing one. Same bug class as the events-feed fix in the preceding commit, on the main chat surface. Co-authored-by: Gille <4317663+helix4u@users.noreply.github.com> * test(dashboard): cover the PTY ticket connect deadline Mirrors the events-feed cases in ChatSidebar.test.tsx: a rejected ticket retries, a stalled ticket times out and its late resolution cannot open a superseded socket, and a settled ticket disarms the deadline so PTY_CONNECTING_TIMEOUT_MS remains the only guard on a wedged handshake (NS-591 regression). Both failure cases fail against ChatPage.tsx without the preceding fix. Co-authored-by: Gille <4317663+helix4u@users.noreply.github.com> --------- Co-authored-by: Gille <4317663+helix4u@users.noreply.github.com>