Root cause (task 01): none of C1-C3 - in Chromium 151 (real mode) a
merely-hidden tab neither stops the stream (frames arrive at full rate;
turn completes) nor fires pagehide on tab switch; C1's double-record
path was proven latent via a synthetic pagehide (trigger is
browser-dependent, e.g. Safari) and C2 (the 120s pre-token guard) was
confirmed to fire while hidden.
- C1: the pagehide partial-persist is correlated with the turn's settle
(leavePartialIndex) - the done/stop settle REPLACES it in place
(identity-guarded rememberBrainTurn in-place mode), so bor.chat.v1
and the auto-saved saved_chats row keep exactly ONE brain turn per
question; a real navigation never runs a settle, so the leave-save
is unchanged.
- C2: the visibility re-arm gives the still-armed pre-token guard a
fresh TURN_TIMEOUT_MS when the tab returns to visible - hidden time
no longer counts toward the 120s guard.
- Phase-48 teardown contract untouched: Stop / tab close / real
navigation still cancel the fetch and stop the model.
- Unit pins: tests/unit/test_frontend_hidden_tab.py (the app.js
mechanisms without a browser).
- E2E pins: tests/e2e/test_hidden_tab_stream.py - synthetic pagehide
mid-stream completes exactly once with one brain turn (localStorage
+ auto-saved row), reload restores one bubble, no-event baseline,
and the fake-clock pre-token guard re-arm (discriminating: fails
with the re-arm disabled).
Convert the two unchecked TODO items into executable phases (Protocol B,
appended after the 72 completed phases):
- 73_hidden_tab_stream (TODO L3): a merely-hidden browser tab must never
stop a generating answer; repro/root-cause decision tree + the pagehide
partial-correlation fix + the hidden-tab E2E pin.
- 74_llm_chat_history (TODO L4, history): client-provided history in
POST /api/chat (stateless, A10) mapped through both the deflected and
grounded agent paths, prior thinking blocks preserved via
reasoning_content, capped oldest-first; mock echo marker + E2E.
- 75_save_doc_full_session (TODO L4, save-as-doc): the Save-as-doc draft
body becomes the full session transcript; edit-out happens in the
existing doc-edit body; multi-turn git-verified E2E.
Owner-confirmed assumptions A1-A7 are recorded as ASSUMPTION lines in the
task files. TODO.md is cleared (items now live in .agents/phases/todo/).