Releases: camcima/finita
Releases · camcima/finita
Release list
Release 4.1.0
- Merge pull request #38 from camcima/fix/architecture-review-remediation (1b39bbc)
- test: pin chained-enqueue queue-limit rejection; clarify docs (9afdf94)
- test: cover checkTransitions branch of QueueLimitExceededError (3a92827)
- feat: add onReleaseError diagnostic hook for lock release failures (f6058bc)
- feat: add maxQueueLength back-pressure option (83a425b)
- feat: add onChainedOperationError sink and document completion boundary (0d94ddf)
- feat: add Statemachine.whenIdle() to await full queue drain (14d601b)
- fix: make Statemachine observer attach idempotent (aeba9db)
- fix: keep ProcessBuilder reusable after a failed build (457da0c)
- fix: restrict graph rankdir/direction options to valid values (6607d81)
- fix: freeze State and Transition to match documented immutability (d466c7d)
- fix: validate transition weights and WeightTransition epsilon (98b07b2)
- docs: fix unsafe Redis lock example, document mutex ownership contract (08cd042)
- Merge pull request #31 from camcima/dependabot/github_actions/actions/checkout-7 (01ee42f)
- build(deps): bump actions/checkout from 6 to 7 (b7b45e0)
- Merge pull request #27 from camcima/dependabot/github_actions/codecov/codecov-action-7 (ecbd461)
- build(deps): bump codecov/codecov-action from 6 to 7 (3588652)
- Merge pull request #34 from camcima/ci/codecov-test-results-action (d076565)
- ci(codecov): upload test results via codecov-action (drop deprecated action) (f17bbc0)
- Merge pull request #33 from camcima/ci/codecov-tokenless-oidc (cdbb369)
- ci(codecov): switch to tokenless OIDC upload (bc56248)
Release 4.0.0
- Merge pull request #29 from camcima/fix/code-review-v3.0.1 (b53efe3)
- ci(osv-scanner): filter dev-only undici/esbuild/js-yaml advisories (e7f48e0)
- fix(statemachine): guard every event observer and transition condition against re-entrancy (cb80489)
- build(deps-dev): bump vitest to 3.2.6 to fix GHSA-5xrq-8626-4rwp (8911c05)
- test: close remaining coverage gaps to 100% across all metrics (b71d0fe)
- docs: document ReentrancyError; correct and complete migration notes (c9d0cf7)
- fix(statemachine): surface lock-release failures; guard selector; restore zero-arg callback (129280b)
- fix(statemachine): reject empty initialStateName instead of silently restarting (36272aa)
- docs: update observer/event/builder docs and migration notes for review fixes (1064703)
- refactor(condition): extract CompositeCondition base for And/OrComposite (8ff3365)
- refactor: share isNamed/nameOrString via src/util (ba9178b)
- fix(condition): timeout throws InvalidSubjectError; allocation-free time check (4ab8a8e)
- fix(graph): escape backslashes in DOT/mermaid output; guard event lookup in labels (2f3fd72)
- test(event): replace stale getInvokeArgs assertions with new args-delivery contract (b42f843)
- fix(event): pass invoke args to observers; drop racy invokeArgs field; inline Dispatcher (8bb6581)
- fix(statemachine): validate maxAutomaticHops is a positive integer (e9a4001)
- fix(statemachine): bound automatic loops with maxAutomaticHops instead of first-revisit detection (16cc1b5)
- fix(statemachine): reject (not throw) on re-entrancy; broaden re-entrancy tests (5ad2514)
- fix(statemachine): throw ReentrancyError on re-entrant trigger instead of deadlocking (3655026)
- docs(observer): clarify onEnter ifStateName contract and test intent (847b363)
- test(observer): add pre-fix-failing regression for stale onEnter lock acquisition (0fb4b83)
- fix(observer): onEnter fires only for rest states via enqueue ifStateName guard (726024a)
- test(observer): prove StatefulStatusChanger isolation with two machines; pin precedence (0332853)
- fix(observer): statefulStatusChanger writes to frame.subject; correct factory docs (d72ce2b)
- test(observer): assert frame.subject referential identity; document logger omission (1a65fc2)
- feat(observer): expose subject on TransitionFrame; share one frame per transition (44ae06c)
- fix(statemachine): snapshot observer lists before notifying (eed53a7)
- fix(statemachine): settle caller promise only after mutex release completes (7501123)
- fix(statemachine): kick runner from EnqueueContext.enqueue; single enqueue path (7e84451)
- refactor(builder): capture condition name once; assert padded-condition error code (67b07ff)
- fix(builder): validate state names; unify name rule across state/event/condition (ac7b38d)
- test(builder): assert weight-conflict payload and message (9f6cfb5)
- fix(builder): detect conflicting weights on duplicate transitions, unify identity key (fbd571d)
- fix(selector): make WeightTransition epsilon ties order-independent (44f30d2)
- docs: add code review report for v3.0.1 (39d4459)
Release 3.0.1
v3.0.0 — execution engine rewrite, typed errors, hardened builder
First v3 release. Major rewrite landed across 55 commits in PR #17 plus follow-up fixes.
Highlights
Graph + execution rewrite
- New
ProcessBuilderwith two-phase build: everyTransitiontargets a realStateinstance, even under cycles and self-loops. Statemachineexecution engine rewritten to pump operations through a FIFO queue, separating the active-transition filter from the transition selector and properly modeling lifecycle phases (proposed → before-observers → commit → after-observers → optional auto-chain).- New observer surfaces:
BeforeTransitionObserverandAfterTransitionObserverwithTransitionFrame/ProposedTransitionFrameimmutable payloads.
Typed error hierarchy
- New
FinitaErrorbase class withcodediscriminant. - New typed errors:
ProcessFinalizedError,GraphValidationError,DuplicateTransitionError,StateNotFoundError,StateEventNotFoundError,ProcessNotFoundError,InvalidSubjectError,AmbiguousTransitionError,AutomaticTransitionCycleError. - Stricter input validation: whitespace-padded event names rejected; empty/whitespace condition names rejected.
GraphBuilder.addStatemade idempotent (closes #14).
Packaging and CI
prepublishOnlyhook +engines.noderange tightened (Node ≥20).- CI matrix: Node 20, 22, 24.
- New CI job:
npm pack --dry-runverification gate. - Codecov configured with project floor at 80%, no per-diff patch threshold.
Review-driven bug fixes folded into 3.0.0
runOperationhonors an already-held mutex viaisAcquired()short-circuit. Manual lock management withautoreleaseLock: falsenow composes correctly with non-idempotent mutexes (`pg_try_advisory_lock`, redis `SET NX`).- Builder treats different condition object instances as conflicts regardless of name. Same reference dedups; different references throw
DuplicateTransitionError. - Event observers fire on event resolution, not state change. Self-transitions and false-condition matched events now fire
event.attach()-style observers, matching the documented Observer Lifecycle.
Breaking changes from v2
- API: state machines must be built via
ProcessBuilderand frozen before use. DirectaddState/addTransitionon graphs is gone. - Observers: before/after observers now operate on immutable
TransitionFrame/ProposedTransitionFrame. Event-attached observers fire whenever the event is resolved on the current state. - Conditions: dedup is by object identity, not by name. Two
CallbackCondition("foo", ...)instances with different bodies now throwDuplicateTransitionErrorinstead of silently merging. - Errors: all framework errors now extend
FinitaErrorand carry acodediscriminant. - Validation: whitespace-padded event names and empty/whitespace condition names now throw
GraphValidationErrorat build time.
See `docs/migration/v2-to-v3.md` for the full migration guide.
Quality gates
- 278 tests across 19 files
- Coverage: 98.62% statements, 99.55% functions, 95.57% branches, 98.62% lines
- `pnpm lint`, `pnpm build`, `pnpm format:check`, `npm pack --dry-run` — all clean
- 76.6 kB tarball, 9 files
🤖 Generated with Claude Code