fix(desktop): keep a surfaced terminal outage across focus and remount

Draft
PO
7d ago
+84-8

What & why

Problem

  • A person whose terminal host is offline or unreachable loses the cause in the header each time they focus the window, switch tabs, or wake the laptop. The pane shows "Reconnecting…" with no reason for about 10 more failed dials (tens of seconds with backoff), then the cause comes back.
  • The same reset re-arms the terminal_connect_failed latch, so one continuous outage sends the event again after each focus or tab switch. A few stuck terminals produce most of the events. The failure-to-input ratio in the report measures focus events more than outages.
  • The rise on 24–26 Oct was not a release or relay change. Most of it came from a very small number of terminals that repeated the event many times. Real host-offline and relay-unreachable failures stayed near their normal level.

Changes

  • After an outage is diagnosed in a visible window, a resume (forceReconnect) or a remount on the same endpoint (connect after park) keeps the failure count, the diagnosis and the telemetry latch. The redial still happens at once. If it attaches, attached clears everything as before. If it fails, the cause shows again after the first failure, not after 10 more.
  • Kept as before:
    • A resume before any diagnosis still starts a fresh budget, so failures counted during suspend do not flag an outage (#5135 / #5702).
    • A new endpoint, a terminated session, disconnect() and the manual reconnect() still reset everything.
Event during a diagnosed outageBeforeAfter
Window focus / visibility / wakeCause hidden for ~10 dials, event sent againCause back after 1 failed dial, no new event
Tab switch (park → connect, same terminal)Same as aboveSame as above
Re-point to another terminal / manual retryFull resetFull reset

[!NOTE]
After this change, terminal_connect_failed counts outages more closely. Expect event volume to drop with no change in the number of affected people. Compare people affected, not raw events, against the old baseline.

Agent context

  • Not in scope: the relay close-4404 ("stream expired") loop on one host, which shows as stream-blocked. It needs relay-side logs. Also not in scope: host-offline and relay-unreachable failures that reflect real host or network state. The header already explains those.

How I tested it

  • bun test src/renderer/lib/terminal/ in apps/desktop: all tests pass, including 4 new transport tests (resume before diagnosis, resume during an outage, remount on the same endpoint, remount on a new endpoint). The 2 "keeps the outage" tests fail on main.
  • bunx @biomejs/biome@2.4.2 check on the changed files and bun run typecheck in apps/desktop pass. I did not run the root bun run lint (the full repo script).
  • I did not check this in the running app. There is no session replay for the affected sessions. The header behavior is covered only by the unit tests through lastDiagnosis and the log entries.

Checklist

  • PR title follows conventional commits (type(scope): subject)
  • bun run lint and bun run typecheck pass (CI fails on lint warnings too)
  • "Allow edits from maintainers" is checked on fork PRs
  • I have signed the CLA (the bot asks on your first PR)

Created with PostHog Desktop from this inbox report.

Origin

  • Scout: signals-scout-general
  • First signal: 2026-10-28
  • Inbox report: open
  • Task started by: auto-start, after the report was rated P2 and ready to fix

Summary by cubic

Keeps a diagnosed terminal outage visible and single-report across window focus, tab switches, and wake events, instead of resetting the failure budget and telemetry latch each time.

  • A resume (forceReconnect) or a remount on the same endpoint during a diagnosed outage now keeps the diagnosis, failure count, and telemetry latch; the cause returns after the first failed redial instead of after ~10.
  • Resumes before any diagnosis, new endpoints, terminated sessions, disconnect(), and manual reconnect() still reset everything as before.
  • terminal_connect_failed now tracks outages rather than focus events, so event volume drops with no change in affected people.