diff --git a/docs/chat-session-lifetime.md b/docs/chat-session-lifetime.md index 577d4501..73c92d9d 100644 --- a/docs/chat-session-lifetime.md +++ b/docs/chat-session-lifetime.md @@ -111,6 +111,16 @@ The double-subscription trap does not arise: `releaseSession` unsubscribes and d returning browser either adopts (fresh single subscription) or starts a first turn with no stale listener behind it. `unsub` is a `Set.delete`, so `deleteSession` calling it twice is harmless. +**Verified end to end, 2026-08-10 01:03.** `IDLE_TIMEOUT_MS` was temporarily dropped to 30s (reverted +immediately after), a ticking `run_in_background` job started, and the tab closed. Officer logged +`Session idle timeout reached, releasing binding (agent left running)` thirty seconds later, and the job +ticked straight through it and kept going. That is the exact point at which `deleteSession` used to call +`_claudeKill`. Reopening the tab adopted the session and resumed its output. + +Note the shape of the test: restarting officer does **not** exercise this — the process dies outright and +`releaseSession` never runs, so that only tests `adoptOrphanedSession`, which already worked. The socket +has to close while officer stays up. + ## Step 2 — enumerate live sessions After an officer restart a live session is invisible until a browser reconnects to it _by id_; adoption