Two parity gaps with the JSONL backend found in review:
- append() now validates serializability and structuredClones the batch
synchronously at call time, BEFORE waiting behind the per-session
chain. A caller that mutates the passed array (or an event inside it)
after the call can no longer corrupt the persisted copy or advance the
cursor past what was written. Matches the JSONL backend.
- load() now computes the last-turn/end cut from the seq+type COLUMNS
only (cutAtLastTurnEnd is generic over {seq,type}); event `data` is
JSON-parsed only for the committed prefix, never for the uncommitted
tail. A malformed `data` in a crash tail is discarded, not treated as
unloadable — only a parse error/gap in the COMMITTED region is
unloadable (the SessionPersistence.load contract). Matches scanLog.
Regression tests for both.