The transcript-as-state framing is useful. I'd add one failure case to the role-sequence test: a timeout after the request was sent but before the assistant reply was persisted. Without an explicit pending or failed state, retrying can duplicate the user turn or leave a successful response missing from local history. Persisting the request/response boundary makes replay useful for recovery as well as debugging.