Idle recap crashed with `TypeError: undefined is not an object (evaluating
'H.content.filter')` when the reporter's session_stop block-decision extension
poisoned the transcript with eight persisted `session-stop-continuation`
custom entries. The primary block-reason continuation flow was intact — the
custom message correctly renders as a `role: "developer"` LLM message —
but the follow-on idle recap fired 4 minutes later, and the side-channel
provider stream handed back a `done` event whose `message.content` had been
dropped. `runEphemeralTurn`'s sanitize step at
`assistantMessage.content.filter(block => block.type !== "toolCall")` then
tripped the TypeError, propagated as "Idle recap turn failed" in the debug
log while silently muting the session.
- Normalized the provider "done" event's `message.content` to `[]` when
the shape is not an array, so a wrapper stream that drops content surfaces
as an empty recap reply instead of an unrecoverable side-channel crash.
- Guarded `#buildEphemeralSnapshot`'s in-flight-assistant preservation
branch with `Array.isArray(streaming.content)` for the same reason.
- Added a regression test that seeds the reporter's transcript shape (one
real turn, eight persisted `session-stop-continuation` customs carrying a
multi-line block reason with U+2717 glyphs) and drives a recap through a
side stream that returns `content: undefined` on `done`. The test
fails on the pre-fix tree with the exact reporter TypeError and passes
after the guard lands.
Fixes#4323