Terminal direct transport: recover from a silently dead
Gap left by the streams/terminal child (PRs #7706/#7707): the 30 s silence watchdog covers only the control-plane relay transport (`apps/web/src/components/ConsolePane.tsx:948-964`, armed only when `relayAcks`). The node-daemon `'direct'` transport (`ConsolePane.tsx:884`, `dialDirect`) has no watchdog, because the daemon does not acknowledge keepalives. The child deferred it because the epic's PRD kept `apps/jaahd` out of scope. On the same broken corporate network that started this epic, a direct terminal can therefore hang silently, with no reconnect and no fallback to the relay. That breaks the epic's "same behaviour on every surface" ask.
Also never run on dev: the epic's terminal AC-6 oracle (kill the terminal socket → it reconnects and accepts input), and the AC-7 image oracle (an attachment image whose first request fails renders after the retry). The child reported having no live session or image record on dev.
Fix (no new surface):
1. In `apps/jaahd`'s console websocket server, answer each client keepalive with the same empty binary ack frame the control-plane relay sends (see the relay ack the client already understands, `ConsolePane.tsx:251-257`).
2. Arm the existing `silenceWatchdog` for the direct transport too. When it fires, close the socket and take the existing direct→relay fallback (`ConsolePane.tsx:876-880`). Gate this on the daemon advertising acks, so an old daemon is never wrongly declared dead.
Acceptance:
- AC-1: a vitest shows a direct socket silent for 30 s closes and falls back to the relay; a jaahd test shows the keepalive is acked.
- AC-2 (dev): open a console terminal on a dev node through the UI (proxied transport) and drop its socket → it reconnects within 15 s and accepts input. Repeat on the direct transport once a dev node runs the new package.
- AC-3 (dev): open a dev task with an image attachment and fail that image's first request in Playwright → the image renders after the automatic retry, with no broken-image icon.
Out of scope: the relay protocol, the read/write choke point in `apps/web/src/net/`, server idempotency, and the stream's 35 s reopen.
Done means:
- AC-1, AC-2 and AC-3 pass, with the evidence (timings, screenshots) in the report.
- `./dc check quick` green, the PR merged via the merge lane, and the Jaah Deploy to dev green.
Outcome
Direct terminal now acks keepalives (jaahd) and falls back to relay after 30s silence; PR #7714 merged 71703ca, quick gate + dev deploy green. AC-2 not run on dev (no openable session); AC-3 blocked by dev image bug, filed draft 12558. Memory: used mem-34625, mem-30597.
Artifacts
Activity
- Ready
- Runner started
- Runner ended (done)