PersistenceError:
    | { cause: unknown; key: string; kind: "parse" }
    | {
        cause: unknown;
        expectedVersion: number;
        key: string;
        kind: "migrate-threw";
        storedVersion: number;
    }
    | {
        expectedVersion: number;
        key: string;
        kind: "migrate-missing";
        storedVersion: number;
    }
    | { cause: unknown; key: string; kind: "serialise" }
    | { cause: unknown; key: string; kind: "quota" }

Discriminated union of failure modes surfaced by the persistence layer. Every error branch in loadInitial and the write path constructs one of these and dispatches it through PersistedInputOptions.onError. The default handler is a single console.warn so existing consumers remain audible during rollout.

Designed for switch (err.kind) exhaustiveness per the SPEC §17.4 commitment that every discriminated union is a tagged union with an exhaustiveness check the type system can enforce. The schema-evolution failure mode is split across two tags — migrate-threw (the caller supplied migrate and it threw, carries cause) and migrate-missing (the caller never supplied a migrate, no cause) — because the previous shape encoded those two distinct semantic states as the presence/absence of an optional cause?: unknown, the §17.4 anti-pattern of an "X may or may not have Y" optional that is a state machine in disguise. With the split, switch (err.kind) narrows correctly and no consumer body needs a runtime presence check on cause to know which mode fired (#370).