Why
#117 surfaces recovered (crashed) turns in the web UI, but the notice is client-side ephemeral — it's built from a live recovered_turn WebSocket event (web/src/hooks/useChat.ts) and disappears on page refresh or session re-open. A user who reloads before re-sending loses the recovered text and the fact that anything was interrupted.
Sketch
- Persist the recovered marker so it re-renders on session restore, either by (a) journaling a lightweight recovered record and replaying it in
mapBackendMessages, or (b) re-emitting recovered_turn on reconnect when the session still has an unresolved recovered turn.
- Keep the one-click Re-send working after restore.
- No change to what data is stored — the recovered text is already session-journal state.
Acceptance
- Kill the process mid-turn, resume, then reload the web UI → the recovered notice and Re-send button are still there.
- No notice when there's nothing to recover.
Good first issue
Self-contained, one hook + one mapper, existing tests to pattern-match against (tests/server/wsHandler.test.ts).
Why
#117 surfaces recovered (crashed) turns in the web UI, but the notice is client-side ephemeral — it's built from a live
recovered_turnWebSocket event (web/src/hooks/useChat.ts) and disappears on page refresh or session re-open. A user who reloads before re-sending loses the recovered text and the fact that anything was interrupted.Sketch
mapBackendMessages, or (b) re-emittingrecovered_turnon reconnect when the session still has an unresolved recovered turn.Acceptance
Good first issue
Self-contained, one hook + one mapper, existing tests to pattern-match against (
tests/server/wsHandler.test.ts).