diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ceb029..66634c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.15.0] - 2026-07-16 + ### Fixed - Wake storms from blocked transactions with fallback-triggering continuations, and phantom analysis-only effect executions: the static-analysis walker had no arm for a terminal erratum — it walked **past** a `waitFor` retry or an `abort` into nodes the real run never reaches. Two defects flowed from that one behaviour. First, if any post-`waitFor` node threw during analysis (the ordinary read-your-own-write fallback shape), the footprint was marked under-approximated — and an under-approximated footprint is incompatible with *everything*, so the blocked transaction could not park quietly: it was woken by every commit in the system and woke every other parked transaction each time it resubmitted, deterministic system-wide churn for as long as it stayed blocked. Second, `delay`/`fromF` thunks positioned after the erratum ran once per attempt — in the analysis pass only — where the documented model says both passes or none. The walker now **stops at the first terminal erratum**, carrying the accumulated footprint out as complete (it is: the run terminates at the same node, and the commit-time coverage gate refines when the passes diverge). A retry-origin stop is re-raised past `handleErrorWith` containment during analysis, mirroring the runtime's retry-is-not-absorbable rule; an error-origin stop keeps the documented recovery-may-resume swallow. The park path additionally refines an under-approximated footprint from the actual log instead of parking on it, closing the storm in the remaining direction (predicate true at analysis, false at run). A parked transaction now parks on exactly its pre-`waitFor` read set — the predicate's dependency set. **The deliberate trade**: a woken transaction whose continuation writes pays one refinement lap before publishing (wakes fire from pre-publish submission sweeps, so no analysis timed before the woken run can see the satisfied predicate); `ErratumStopSpec` pins the lap count in both directions, and the soaks carry the cost within their existing ceilings. The stop also removes a silent Scala 3 hazard for a top-level `abort` followed by a value-binding continuation, which used to throw a `ClassCastException` *inside the analysis pass* and flag the footprint; the same shape inside a `handleErrorWith` can still flag (the error-origin stop is deliberately swallowed there), but the park-path refinement now keeps that bounded — one runs-alone lap — rather than permanent. - Cancelled commits leaking and resurrecting: cancelling the `F` returned by `commit` (a `timeout`, a lost `race`, supervisor shutdown) interrupted only the caller's wait — the transaction itself ran on a detached fiber the cancellation never reached. A parked `waitFor` transaction survived its caller in the retry map indefinitely; a later commit that conflicted with its read set **woke it, re-ran it, and published its writes** into a completion signal nobody held — side effects at unbounded distance from a cancellation that had long since "succeeded" — and every cancelled blocked commit leaked its retry-map entry, wake closure, and bookkeeping. `commit` now installs an `onCancel` finalizer spanning submission and the wait: cancellation **abandons** the transaction — a shared-across-incarnations flag plus a sweep that removes any parked entry (under the retry semaphore) and demotes-and-deregisters a `Scheduled` registration (under the graph semaphore), draining its dependency cascade so queued peers proceed. The flag is re-checked *inside* every semaphore region that could re-enter the transaction — park, resubmission, wake-time fresh incarnations, and the admission gate — closing the race where an in-flight wake closure registers after abandonment completes. The atomic commit window remains uncancelable: a window already executing runs to completion (its writes may publish); cancellation prevents every future window, promptly, without waiting on the in-flight one. The scaladoc on `commit` and a README section state the contract. Pinned by `CancellationSpec` (resurrection, racing cancellation-vs-wake, dependent release, prompt cancel-while-running, timeout composition — three fail against the old runtime) and `AbandonProtocolSpec` (white-box bookkeeping and idempotency). The `execute` pipeline also gained an `onCancel` completing scheduler deregistration, closing the latent wedge where a cancelled execute fiber stranded its dependents forever. @@ -206,7 +208,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Semantic blocking via `waitFor` / retry mechanism - `handleErrorWith` for transaction-level error recovery -[Unreleased]: https://github.com/Entrolution/bengal-stm/compare/v0.13.0...HEAD +[Unreleased]: https://github.com/Entrolution/bengal-stm/compare/v0.15.0...HEAD +[0.15.0]: https://github.com/Entrolution/bengal-stm/compare/v0.14.0...v0.15.0 [0.14.0]: https://github.com/Entrolution/bengal-stm/compare/v0.13.0...v0.14.0 [0.13.0]: https://github.com/Entrolution/bengal-stm/compare/v0.12.0...v0.13.0 [0.12.0]: https://github.com/Entrolution/bengal-stm/compare/v0.11.0...v0.12.0 diff --git a/SECURITY.md b/SECURITY.md index 67efb4f..a74472f 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -21,8 +21,8 @@ Please include the following information in your report: | Version | Supported | | ------- | ------------------ | -| 0.14.x | Yes | -| < 0.14 | No | +| 0.15.x | Yes | +| < 0.15 | No | ## Security Updates