Record the renderer-reattach correction and its phone checks

The port notes carry the third correction of this round: the data
plane assumed a renderer that attaches once and lives forever, which no
foreground service can make true of Android's separate WebView renderer
process. Phase 11 gains the two checks a phone can run — close and
reopen a connection, and a backgrounded shell surviving its renderer
being killed, banner and all.
This commit is contained in:
2026-08-09 10:54:45 +02:00
parent aaff81272a
commit 3f5979d639
2 changed files with 64 additions and 0 deletions
+33
View File
@@ -1745,6 +1745,39 @@ is a terminal that answers the buttons and ignores the keyboard: it reads as the
Worth doing on the software keyboard too, where the same fault shows as the keyboard closing on the first
tap of an arrow key.
### 11.11 Closing a connection and opening a new one both take you somewhere real
Open a shell, close its tab, then open a different one from HOSTS.
**Pass:** the new terminal renders and takes input straight away — no stuck "Connecting…" status, no blank
pane that never receives the prompt.
**Failure means:** `TerminalDataPlane` refused the page's reattach. The renderer's `WebSocket` does not
survive a tab going from one to zero and back to one on every device, and a host that answers a second valid
upgrade with `409 Conflict` instead of taking the socket over leaves every terminal after the first
permanently unreachable — see the correction in `docs/android-port.md`'s terminal section.
### 11.12 A backgrounded shell survives its renderer being killed · **needs several minutes, or developer tooling**
With a shell open and something worth reading in its scrollback, background the app (home button, not back)
for several minutes — long enough for Android to consider reclaiming it — then return. If the device exposes
it, forcing a stop of the WebView renderer process from Developer Options while backgrounded is the more
reliable way to trigger the same thing on demand rather than waiting on the OS's own judgement. Either way,
type something once you are back.
**Pass:** one of two honest outcomes, both good. Either the pane is exactly as it was — the renderer process
survived, so nothing needed to happen — or the pane is empty but for a dim line reading `── the view
reconnected; earlier output stayed on the host ──`, meaning the page reloaded and reattached. In both cases
what is typed now reaches the shell, and the shell is still the same one — not a new tab, not a reconnect
sheet, no "Connecting…" status stuck on screen.
**Failure means:** if the status stays stuck or nothing typed arrives, the renderer's socket did not retry
itself — see `terminal.js`'s `connect()` and its backoff. If the pane came back empty with **no** banner, a
session that survived a reload is being shown as though its scrollback had too, which is not true and is
worse than saying nothing: the banner exists so this is never silently wrong. If typing does nothing but the
banner is there, the session's credit window was not reset on reattach and the shell is frozen behind it —
see `TerminalWorkspace.ReplayAfterAttachAsync`.
---
## Phase 12 — Shared vaults: the operations that span two accounts