← All updates

0.3.9

Sealed message ids never re-open

A consumer-reported production defect, fixed at the root: the Claude Agent SDK splits one API message across multiple assistant frames (a thinking block arrives as its own frame, the tool_use block as a second frame with the same message.id). The facet’s per-frame open/seal re-opened an id the consumer had already sealed — and reduce() correctly refuses a sealed attach target, parking the fold and discarding the rest of the turn.

Now the message lifecycle is keyed on the SDK’s own message.id with a deferred seal: one message.start/message.end pair per id, block indices continuing across frames, the close riding the next fold-binding frame. A defensive path handles the pathological orderings (:cont: derived carriers — sealed ids are never re-opened, ever).

And so this class of bug can’t return: corpus-wide INV-MSG fold gates now run in CI — every cassette, every facet, folded through the normative Reducer, asserting no re-opens and no parking.