fix(agent-chat): keep reconnecting state neutral

Merged
TE
10d ago
+226-29

Why

During daemon startup and socket recovery, the agent pane showed the last handshake error in the red host-error card even though cmux was retrying automatically. That made an ordinary reconnect look like a terminal failure.

Leo: “when a chat is loading, Remove that red error box thing it's way scarier than it looks, just let it show it's reconnecting it's not red”.

Change

  • Render automatic daemon/socket recovery as a neutral Reconnecting… status with the shared spinner and no stale error text.
  • Keep a Restart acpmux action available when the host reports another daemon owns the socket.
  • Keep non-retryable handshake failures, deleted chats, and not-found chats as terminal alerts.
  • Show connecting/offline remote chat placeholders as the same neutral spinner state.
  • Add the reconnecting gallery variant and regression tests for neutral versus terminal states.

The Swift retry-state work in #25219 is untouched. The handshake reply adds details.reconnecting only for an update handoff (daemonRestarting), so a missing binary, stopped daemon, unsupported machine or untrusted folder keeps its actionable error and Retry. Transport failures use the existing typed retryability or lost-link code. No timer or retry policy is added.

Verification

  • bun test src/agent-session/acpmux/HostError.test.tsx src/agent-session/acpmux/ChatUnavailableState.test.tsx src/agent-session/acpmux/hostRetry.test.ts (12 passed)
  • bunx vp check --no-fmt --no-lint (2,857 files, no type errors)
  • python3 scripts/cmux-next/prepush-gate.py (no new violations)
  • Native regression added: AcpmuxRefusedRestartTests.onlyAnUpdateHandoffIsAReconnectingHandshake (hosted run pending)
  • Gallery: agent-pane.host-error / reconnecting

The package-wide check reaches pre-existing base failures before completing: the raw font-size ratchet in SendScrollSetting.gallery.tsx, two existing App.tsx hook warnings, and stale generated protocol methods. No changed line adds those failures.

Gallery evidence (Linux Chromium, same harness)

The Linux pool's gallery advisory could not complete on this head, so these real gallery renders were captured from the exact head and base with the supported Chromium gallery harness on gcp-agent-lane-1 (Node 22 + Bun, fixed 520px component width). The reconnect pair compares the base retrying card with the neutral reconnecting state; the refusal pair confirms the terminal restart/refusal card remains actionable.

StateBefore (feat-cmux-next base)After (PR head)
Reconnecting, darkbefore reconnecting darkafter reconnecting dark
Reconnecting, lightbefore reconnecting lightafter reconnecting light
Terminal refusal, darkbefore refusal darkafter refusal dark
Terminal refusal, lightbefore refusal lightafter refusal light

Final head: f7b39c8a16bb02b7d7b70d93b3912b5d5154ac3a. Both GitHub base updates were reproduced by git merge-tree with no conflict resolutions; only unrelated draft-settle code intersects App.tsx. The reconnect feature and gallery renderers remain unchanged. Exact-head fleet Release compile passed in run 40515039939. Independent Astra reviewed the final merge delta.

Review (Codex gpt-6-astra xhigh): SHIP at f7b39c8a16bb02b7d7b70d93b3912b5d5154ac3a

Changelog

Fixed - Recovering agent chats show a neutral Reconnecting spinner while terminal refusals keep their instructions and actions.

Agent session: agent session