A pane's xterm write pipeline can die while its shell keeps running: a
synchronous throw escaping an unguarded write callback wedges WriteBuffer
(issue #2836), and write() on a disposed terminal silently drops its
completion callback (verified against vendored xterm 6.1.0-beta.287 — it
does NOT throw, falsifying the output scheduler's disposed-race catch).
Every recovery path we have (dead-session reconcile #6514/#7002,
hibernation wake #7145, the allDead activation generation bump) gates on
the PTY being dead, so these panes stayed fossils: last frame painted,
every keystroke and byte of output silently dropped, delivery ack credits
leaking, until the user reloaded the window (issue #8104 class).
Detection is probe-certified, mirroring replay-guard.ts:
- a scheduler write whose completion stalls gets an empty probe write; a
probe that never parses certifies the pipeline dead (catches both the
wedged WriteBuffer and the disposed-terminal case) and credits the
queued deliveries so main's in-flight window no longer leaks
- the replay guard's existing wedged release ("pane likely needs
recovery") now actually hands the pane to recovery
- user input rejected by an unbound transport (detached during a
remount/move and never rebound) arms recovery after confirming the PTY
is alive via pty:hasPty
Recovery reuses the proven remount seam: bump the tab's generation so
TerminalPane unmounts, detach() preserves the live PTY, and the remounted
pane builds a fresh xterm that reattaches and replays the daemon
snapshot — no shell restart, capped per tab to prevent remount storms.
The new e2e spec pins both phenotypes end-to-end (wedge → recover,
dispose-under-live-bindings → recover); both fail on main and pass with
the fix, and the same arc was validated live in a pnpm dev instance.