Skip to content

fix(terminal): fall back to HTTP output when WS replay is blank - #385

Open
RonenMars wants to merge 1 commit into
mainfrom
fix/terminal-empty-replay-fallback
Open

fix(terminal): fall back to HTTP output when WS replay is blank#385
RonenMars wants to merge 1 commit into
mainfrom
fix/terminal-empty-replay-fallback

Conversation

@RonenMars

Copy link
Copy Markdown
Owner

Problem

Opening a live session that is parked on a question/permission card showed a permanently blank terminal ("Active", prompts counted, but empty body) and repeatedly "failed to load".

The session and server are healthy: the live registry reports ptyAttached: true / waiting_input, and GET /api/sessions/:id/output returns the full 48 KB transcript that renders as 57 lines through the mobile VirtualTerminal.

Root cause

A card-parked session replays only blank ring-buffer rows over the WS terminal_replay.
The terminal_replay handler in useTerminalStream treated any replay as a successful load — it set replayReceivedRef and cleared the 2s HTTP-fallback timer unconditionally.
So a blank replay stranded the terminal empty forever and the richer HTTP /output fallback (which had the full transcript) was never fetched — confirmed in the server logs, where /output was never hit for the affected session.

Fix

Only accept a terminal_replay that carries at least one non-blank line.
An empty replay is ignored, leaving the fallback timer armed so GET /api/sessions/:id/output fills the screen.

Tests

New __tests__/unit/hooks/useTerminalStream.emptyReplay.test.tsx:

  • an empty replay still falls back to HTTP /output (previously failing — reproduces the bug),
  • a non-empty replay is authoritative and does not fall back.

Full useTerminalStream suite green (32 tests); no type errors on the changed files.

Compatibility

Mobile-only, additive behavior change to a client-side fallback path.
No server, API, or WS-contract changes.

A session parked on a question/permission card replays only blank ring-buffer rows over the WS terminal_replay.
The handler treated any replay as a successful load, latching replayReceivedRef and clearing the 2s HTTP fallback timer, so the terminal stayed blank forever even though GET /api/sessions/:id/output still held the full transcript.
Only accept a replay that carries at least one non-blank line; otherwise leave the fallback timer armed so /output fills the screen.
RonenMars added a commit that referenced this pull request Jul 23, 2026
…kip-ci]

Record PRs #385, #386 and #387 as a separate follow-up chain in the land-open-prs runbook.
#385 and #386 target main independently; #387 is stacked on #386 and must be rebased onto main before merging.

[skip-ci]
RonenMars added a commit that referenced this pull request Jul 24, 2026
…kip-ci]

Record PRs #385, #386 and #387 as a separate follow-up chain in the land-open-prs runbook.
#385 and #386 target main independently; #387 is stacked on #386 and must be rebased onto main before merging.

[skip-ci]
RonenMars added a commit that referenced this pull request Jul 26, 2026
…kip-ci]

Record PRs #385, #386 and #387 as a separate follow-up chain in the land-open-prs runbook.
#385 and #386 target main independently; #387 is stacked on #386 and must be rebased onto main before merging.

[skip-ci]
RonenMars added a commit that referenced this pull request Jul 28, 2026
…kip-ci]

Record PRs #385, #386 and #387 as a separate follow-up chain in the land-open-prs runbook.
#385 and #386 target main independently; #387 is stacked on #386 and must be rebased onto main before merging.

[skip-ci]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant