update

fun update(next: SeamState)

The normal / derived write path — a pump publishing an aggregate (e.g. a rollup of SeamState.Woven/SeamState.Weaving). A no-op once tear has latched, so an in-flight derived write can never overwrite the terminal Torn. Derived rollups publish only recoverable states (SeamState.Woven/SeamState.Weaving); the terminal Torn comes solely from tear.

Why Torn is rejected rather than accepted

Passing a Torn here would publish the terminal state without latching — leaving latched == false, so the very next update overwrites it. That is #1803 rebuilt through the front door of the type that exists to prevent it, and it would be a quieter bug than the one this class replaced, because the seam would look correctly gated. The close decision is tear's alone; a caller holding a Torn it wants published is holding a close decision.

require, not a silent no-op: a caller reaching here with a Torn has a bug in its own routing, and swallowing it would hide the terminal transition instead of publishing it. A self-driven death path should branch on the state and call tear with the reason — see TieredSeam's rollup collector, which does exactly that.

Throws