Background
Deferred from #971 (web terminal session-unknown fast-path).
After a Tower restart, persistent (shellper-backed) terminal sessions are reconnected under a new terminal id, and the old SQLite row is deleted. Both reconnect paths reassign the id:
- startup reconcile:
packages/codev/src/agent-farm/servers/tower-terminals.ts:646 (createSessionRaw → new id) and :669-672 (delete old row, save under new id)
- on-the-fly reconnect:
:832 and :868-872 (deleteTerminalSession(oldId) → new id)
Consequence: a browser (or VSCode) tab still holding the old id's WebSocket URL (/ws/terminal/<oldId>) will get a permanent close — 4404 for the web terminal after #971, or the HTTP 404 upgrade rejection for the VSCode terminal — and correctly gives up. But the old id is permanently dead, so a WS retry to the same URL can never recover it.
Recovery today relies on something re-fetching /api/state (which rehydrates and exposes the successor id) and the dashboard remounting the terminal onto the new wsPath (the Terminal effect is keyed on wsPath). That re-fetch is currently incidental (a user-driven refresh, a focus/poll event) rather than triggered by the give-up itself.
Work
On a permanent terminal close (the classifyUpgradeError(...) === 'permanent' branch added in #971), have the dashboard proactively re-fetch workspace state, resolve the session's successor id, and auto-remount the terminal onto the new wsPath — so a persistent session that came back under a new id self-heals without a manual refresh.
Notes
- The same stale-id gap exists for the VSCode terminal (give-up + reconnect link, but no automatic successor-id remount). Worth considering the analogous affordance there; if folded in, this becomes
area/cross-cutting.
- This is a recovery/UX hardening, not a correctness bug — the
4404/404 give-up is already truthful (the old id really is gone).
Acceptance
- After a Tower restart, an open dashboard terminal tab on a persistent session reconnects to its successor session automatically (no manual page refresh), within a small bounded delay.
Background
Deferred from #971 (web terminal session-unknown fast-path).
After a Tower restart, persistent (shellper-backed) terminal sessions are reconnected under a new terminal id, and the old SQLite row is deleted. Both reconnect paths reassign the id:
packages/codev/src/agent-farm/servers/tower-terminals.ts:646(createSessionRaw→ new id) and:669-672(delete old row, save under new id):832and:868-872(deleteTerminalSession(oldId)→ new id)Consequence: a browser (or VSCode) tab still holding the old id's WebSocket URL (
/ws/terminal/<oldId>) will get a permanent close —4404for the web terminal after #971, or the HTTP404upgrade rejection for the VSCode terminal — and correctly gives up. But the old id is permanently dead, so a WS retry to the same URL can never recover it.Recovery today relies on something re-fetching
/api/state(which rehydrates and exposes the successor id) and the dashboard remounting the terminal onto the newwsPath(theTerminaleffect is keyed onwsPath). That re-fetch is currently incidental (a user-driven refresh, a focus/poll event) rather than triggered by the give-up itself.Work
On a permanent terminal close (the
classifyUpgradeError(...) === 'permanent'branch added in #971), have the dashboard proactively re-fetch workspace state, resolve the session's successor id, and auto-remount the terminal onto the newwsPath— so a persistent session that came back under a new id self-heals without a manual refresh.Notes
area/cross-cutting.4404/404give-up is already truthful (the old id really is gone).Acceptance