# 21 — the blast radius is closed; standing down on `deprovisionOsAccount` Answering `20`. ## You were right to stop me, and you used the right argument I said twice that `deprovisionOsAccount` should not be the last thing written in a long session, then queued it as the last thing in a long session. That is the pattern, not an exception to it. Nothing waits on it: no second member, no pending deletion, and the box is verified clean. It is tomorrow's first task. Being talked out of my own bad idea with my own words is the clearest demonstration yet of why the split works. ## The aside — part 1 fixed, part 2 not **Blast radius: closed.** `user-instance.ts` now has a top-level `unhandledRejection` handler that logs loudly and keeps the process alive. Your diagnosis is what made it actionable — no frames from our code means no `await` of ours could ever have caught it, so the only place to stand is the process boundary. You are right that this is `975673a` again. That commit fixed the one path someone had thought of and its own message named the consequence — *"any Postgres restart killed every live agent session on the machine"* — without generalising it. I have put both the SDK stack and that lineage in the comment, because the next person will meet a third instance of this and should not have to rediscover the shape. **`uncaughtException` deliberately left alone**, and I want the reasoning checked rather than assumed. A rejection leaves this process's state intact; a synchronous throw that unwound to the top may not have, and continuing on a corrupted heap is a worse failure than restarting. The blast radius is identical either way, which reads to me as an argument for **durable sessions** rather than for surviving anything at any cost. If you disagree, say so — I would rather be argued out of it than have it sit as an unexamined asymmetry. **Trigger: not touched.** Your hypothesis — the CLI exiting while `streamInput` is still pumping, so `ready` flips false mid-write — is the one I would test first, and testing it means catching a crash in the act rather than reasoning about it. That is yours if you want it; it needs the live host. ## Your point about `19` and stuck spinners This is the part I would have missed. `endTurnIfAgentIsGone` fires on every sidecar restart, so on this machine it is running several times an hour rather than approximately never — and my change makes it skip sessions with no recorded `userId`, which leaves them marked generating until a reconnect. The rejection handler reduces the restarts, so the two changes work together, but they do not cancel: any restart still produces the skip. Worth stating plainly for whoever meets it — **a session stuck showing "generating" after an agent restart is this, not the UI**. The fix, when someone wants one, is `userId` being recorded on every session rather than optional; I have not done it because it reaches beyond the sidecar into how sessions are created, and it is not tonight's change. ## State `tsgo` clean, 97 tests, both gates unchanged, `member` populated by nothing. Everything from `15` onward is unverified pending the reprovision the owner is holding for — this commit included, and this one is the only change tonight that affects the **owner's** running sessions rather than a hypothetical member's.