Clear the durable live-session checkpoint on a terminal SSE error reply

The documented abort flow in reference/live.md (live-poll.mjs --reply <id>
error "...") reset the browser bar to PICKING but left the localStorage
checkpoint written for the GENERATING phase in place. Every reload then
resurrected a dead session the server no longer knew about, and the page
stayed wedged until the user hand-cleared the impeccable-live* keys in
the console (issue #362, diagnosed by @yourcodekitten).

An agent error reply is terminal for the session it names: when the id
matches the current session, run the same markSessionHandled + cleanup
teardown as 'discarded' (cleanup includes clearSession); when it matches
a stored-but-not-current checkpoint (the error raced a reload), drop that
checkpoint too. Errors that name no session keep the existing UI-only
reset, and the accept-cleanup and steer branches are untouched.

Regression guard added to tests/live-browser-regression.test.mjs.

Prepared with AI assistance (Claude Code), directed by @pbakaus.

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-07-25 17:57:29 -07:00
co-authored by Claude Code
parent af78b1e512
commit 21d058e744
2 changed files with 38 additions and 0 deletions
+13
View File
@@ -6499,6 +6499,19 @@
if (maybeCompleteSteer(msg)) break;
console.error('[impeccable] Error:', msg.message);
showToast('Error: ' + msg.message, 5000);
// An agent error reply is terminal for the session it names: tear
// it down exactly like 'discarded' (cleanup includes clearSession),
// or the durable localStorage checkpoint survives and every reload
// resurrects a GENERATING bar for a session the server no longer
// knows about (issue #362).
if (msg.id && msg.id === currentSessionId) {
markSessionHandled();
cleanup();
break;
}
// A stored-but-not-current checkpoint naming the errored session
// (the error raced a reload) must not resurrect either.
if (msg.id && loadSession()?.id === msg.id) clearSession();
hideBar();
renderEditBadge('hidden');
setLiveState('PICKING');