From 227a8831488b806e4c0a98b4021ff61e46a9b8cf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 7 Nov 2026 06:40:56 +0000 Subject: [PATCH] Version Packages --- .changeset/actionable-type-errors.md | 17 ----- .changeset/agent-docs-in-the-package.md | 7 -- .changeset/changesets-3-and-tinybench-6.md | 3 - .changeset/dependency-baseline-refresh.md | 8 --- .changeset/devtools-dependency-ranges.md | 7 -- .changeset/drop-react-scheduler-peer.md | 7 -- .changeset/homepage-docs-site.md | 5 -- .changeset/machine-test-check.md | 17 ----- .changeset/repository-oxlint.md | 3 - .changeset/runnable-doc-examples.md | 6 -- .changeset/transition-declarations.md | 31 --------- .changeset/typed-execution-plan.md | 5 -- .changeset/typed-planner-transitions.md | 5 -- .changeset/typescript-7-compatibility-lane.md | 3 - packages/devtools/CHANGELOG.md | 59 +++++++++++++++++ packages/devtools/package.json | 2 +- packages/effect-machine-react/CHANGELOG.md | 45 +++++++++++++ packages/effect-machine-react/package.json | 2 +- packages/effect-machine/CHANGELOG.md | 64 +++++++++++++++++++ packages/effect-machine/package.json | 2 +- packages/oxlint-plugin/CHANGELOG.md | 35 ++++++++++ packages/oxlint-plugin/package.json | 2 +- 22 files changed, 207 insertions(+), 128 deletions(-) delete mode 100644 .changeset/actionable-type-errors.md delete mode 100644 .changeset/agent-docs-in-the-package.md delete mode 100644 .changeset/changesets-3-and-tinybench-6.md delete mode 100644 .changeset/dependency-baseline-refresh.md delete mode 100644 .changeset/devtools-dependency-ranges.md delete mode 100644 .changeset/drop-react-scheduler-peer.md delete mode 100644 .changeset/homepage-docs-site.md delete mode 100644 .changeset/machine-test-check.md delete mode 100644 .changeset/repository-oxlint.md delete mode 100644 .changeset/runnable-doc-examples.md delete mode 100644 .changeset/transition-declarations.md delete mode 100644 .changeset/typed-execution-plan.md delete mode 100644 .changeset/typed-planner-transitions.md delete mode 100644 .changeset/typescript-7-compatibility-lane.md diff --git a/.changeset/actionable-type-errors.md b/.changeset/actionable-type-errors.md deleted file mode 100644 index 3d780aad..00000000 --- a/.changeset/actionable-type-errors.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -"@typeonce/effect-machine": minor ---- - -Compile errors for common machine mistakes now name the fix instead of reporting `never`: - -```ts -Pay: { target: "Archivd" } -// Unknown target "Archivd". Declared: Editing, Checkout, Archived - -invoke: { src: "loadd", onDone: { stay: true } } -// Unknown source. Registered: load -``` - -`Machine.handle` reports a misspelled target, source, or owner, a missing `data`, the root or a history state used as a target, and an `on`, `always`, `onDone`, or `invoke` on a final or choice state. - -A transition that targets a state below an inactive valued state, such as `{ target: "Checkout.Paid" }` from outside `Checkout`, used to fail while planning. It is now a compile error: target `"Checkout"` with a `branches` entry and construct the child with `select.target("Checkout", { data, states: { Paid: {} } })`. diff --git a/.changeset/agent-docs-in-the-package.md b/.changeset/agent-docs-in-the-package.md deleted file mode 100644 index 59ed8abb..00000000 --- a/.changeset/agent-docs-in-the-package.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@typeonce/effect-machine": minor ---- - -Ship agent documentation as `AGENTS.md`, `CLAUDE.md`, and `ai-docs/` in the package, replacing `docs/`. - -An agent working in a project can now read documentation matching the installed version from `node_modules/@typeonce/effect-machine/AGENTS.md`. Replace links to `docs/agent-guide.md`, `docs/root-api.md`, `docs/effect-atom-react.md`, and `docs/machine-review.md` with that file, or with the matching section under `ai-docs/src`. diff --git a/.changeset/changesets-3-and-tinybench-6.md b/.changeset/changesets-3-and-tinybench-6.md deleted file mode 100644 index 853d812b..00000000 --- a/.changeset/changesets-3-and-tinybench-6.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - ---- diff --git a/.changeset/dependency-baseline-refresh.md b/.changeset/dependency-baseline-refresh.md deleted file mode 100644 index 98d16740..00000000 --- a/.changeset/dependency-baseline-refresh.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@typeonce/effect-machine-devtools": patch -"@typeonce/oxlint-plugin-effect-machine": patch ---- - -Update the devtools file watcher to chokidar 6. The devtools CLI now requires Node.js 22.22 or newer. - -Build the Oxlint plugin against `@oxlint/plugins` 1.90.0. The plugin still supports `oxlint` `>=1.80.0 <2`. diff --git a/.changeset/devtools-dependency-ranges.md b/.changeset/devtools-dependency-ranges.md deleted file mode 100644 index b4aed118..00000000 --- a/.changeset/devtools-dependency-ranges.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@typeonce/effect-machine-devtools": patch ---- - -Install the devtools CLI without pinning a second exact TypeScript or Vite. - -`@typeonce/effect-machine-devtools` now depends on `typescript` `>=5.9.0 <7.0.0` and `vite` `^8.1.5` instead of exact versions, so a package manager can reuse compatible versions your project already has. No setup changes are required: the CLI still works when your project uses neither, or uses TypeScript 7. diff --git a/.changeset/drop-react-scheduler-peer.md b/.changeset/drop-react-scheduler-peer.md deleted file mode 100644 index e95f96f6..00000000 --- a/.changeset/drop-react-scheduler-peer.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@typeonce/effect-machine-react": patch ---- - -Remove the `scheduler` peer dependency from `@typeonce/effect-machine-react`. - -The package never imports `scheduler`, so upgrading React no longer produces a peer warning from it. The `scheduler` version is now governed only by `react-dom` and `@effect/atom-react`. Remove `scheduler` from your dependencies if you installed it only for this package. diff --git a/.changeset/homepage-docs-site.md b/.changeset/homepage-docs-site.md deleted file mode 100644 index 228974ec..00000000 --- a/.changeset/homepage-docs-site.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@typeonce/effect-machine": patch ---- - -The npm page for `@typeonce/effect-machine` now links to the API reference at https://effect-machine.typeonce.dev. diff --git a/.changeset/machine-test-check.md b/.changeset/machine-test-check.md deleted file mode 100644 index b5b1a65c..00000000 --- a/.changeset/machine-test-check.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -"@typeonce/effect-machine": minor -"@typeonce/effect-machine-devtools": minor ---- - -Add `MachineTest.check`, `MachineTest.analyze`, and the `effect-machine check` command, so a machine can be verified with one call and no browser. - -`check` reports states with no path from the initial state, public events with no handler, nondeterministic planning, planner law violations, invariant failures, and declared branches that were never taken. It derives input and events from the machine's schemas, and each finding from a run includes the events that reproduce it. A report is `"exhaustive"` only when nothing limited exploration; otherwise `limits` says why it is `"bounded"`. - -```ts -const program = Effect.gen(function*() { - const report = yield* MachineTest.check(Checkout) - return report.ok // false when any finding is an error -}) -``` - -From a shell, `effect-machine check src/checkout.ts --json` prints one JSON object and exits with status 1 on any error. diff --git a/.changeset/repository-oxlint.md b/.changeset/repository-oxlint.md deleted file mode 100644 index 853d812b..00000000 --- a/.changeset/repository-oxlint.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - ---- diff --git a/.changeset/runnable-doc-examples.md b/.changeset/runnable-doc-examples.md deleted file mode 100644 index 75b029b5..00000000 --- a/.changeset/runnable-doc-examples.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@typeonce/effect-machine": patch -"@typeonce/effect-machine-react": patch ---- - -Every API example in the published source now has a title, and the core package's examples compile and run against the current API. diff --git a/.changeset/transition-declarations.md b/.changeset/transition-declarations.md deleted file mode 100644 index f384018c..00000000 --- a/.changeset/transition-declarations.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -"@typeonce/effect-machine": minor -"@typeonce/effect-machine-react": minor -"@typeonce/effect-machine-devtools": minor -"@typeonce/oxlint-plugin-effect-machine": minor ---- - -Declare conditional transitions inline, with `branches` next to `resolve`, so one transition can be read and edited alone. The compiler checks one against the other in both directions, and rejects a resolver that does not return a `select` call on every path: - -```ts -Pay: { - branches: [{ target: "Charging" }, { update: "root" }, { stay: true }, { decline: true }], - resolve: ({ event, select }) => { - if (event.amount < 0) return select.decline() - if (event.amount === 0) return select.stay() - return event.preview - ? select.update({ root: { total: event.amount } }) - : select.target("Charging", { data: { amount: event.amount } }) - } -} -``` - -To migrate: move each `make({ branches })` group into its transition and drop its keys and `title`, so `select.key(...)` becomes `select.target(path, ...)`, `select.update({ owner: value })`, `select.history(path)`, `select.initialize({ input })`, or `select.stay()`. Two keys that reached the same destination are now one entry. Remove `declinable: true`, list `{ decline: true }`, and replace the `decline()` context function with `select.decline()`. - -`none` is replaced: `{ none: true }` becomes `{ stay: true }`, `{ none: true, reenter: true }` becomes `{ reenter: true }`, and `{ none: true, resolve }` becomes `{ stay: true, commands }`. Every plain transition accepts `commands: (context, enqueue) => ...`. - -`update` is now a record with one owner, so `data` only ever means the target's value: `{ update: "root", data }` becomes `{ update: { root: data } }`, and `{ target, update: "Owner", data: () => ({ target, update }) }` becomes `{ target, data, update: { Owner: value } }`. Inside a `branches` list, an entry still names its owner as a string, `{ target, update: "Owner" }`, and the value goes in its `select` call. - -`guard` and `decline` now exist only on `on` handlers and `always`. On `onDone`, `onFailure`, `onElement`, `onSnapshot`, and `choice`, which have no other candidate, use `{ stay: true }` or select a destination. A retained transition's `branchKey` and a transition definition's `key` are now the entry as written, such as `target:Paid`, and `title` is removed. - -In the Oxlint plugin, `no-conditional-none-branch` becomes `no-conditional-stay-branch`, and `no-redundant-resolve` is removed because the compiler now rejects what it reported. Resolvers for invocation outcomes and `always` may select `stay` conditionally, because `Machine.can` queries only events. diff --git a/.changeset/typed-execution-plan.md b/.changeset/typed-execution-plan.md deleted file mode 100644 index 6c4b442a..00000000 --- a/.changeset/typed-execution-plan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@typeonce/effect-machine": patch ---- - -Internal: check the compiled execution plan's transition contexts, targets, and commands at compile time instead of through `any` casts. Machine behavior and the public API are unchanged. diff --git a/.changeset/typed-planner-transitions.md b/.changeset/typed-planner-transitions.md deleted file mode 100644 index e641568d..00000000 --- a/.changeset/typed-planner-transitions.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@typeonce/effect-machine": patch ---- - -Internal: check planner target resolution, invocation sources, and runtime child operations at compile time instead of through `any` casts. Machine behavior and the public API are unchanged. diff --git a/.changeset/typescript-7-compatibility-lane.md b/.changeset/typescript-7-compatibility-lane.md deleted file mode 100644 index 853d812b..00000000 --- a/.changeset/typescript-7-compatibility-lane.md +++ /dev/null @@ -1,3 +0,0 @@ ---- - ---- diff --git a/packages/devtools/CHANGELOG.md b/packages/devtools/CHANGELOG.md index eceeeeb0..3158c755 100644 --- a/packages/devtools/CHANGELOG.md +++ b/packages/devtools/CHANGELOG.md @@ -1,5 +1,64 @@ # @typeonce/effect-machine-devtools +## 0.47.0 + +### Minor Changes + +- d1d9137: Add `MachineTest.check`, `MachineTest.analyze`, and the `effect-machine check` command, so a machine can be verified with one call and no browser. + + `check` reports states with no path from the initial state, public events with no handler, nondeterministic planning, planner law violations, invariant failures, and declared branches that were never taken. It derives input and events from the machine's schemas, and each finding from a run includes the events that reproduce it. A report is `"exhaustive"` only when nothing limited exploration; otherwise `limits` says why it is `"bounded"`. + + ```ts + const program = Effect.gen(function*() { + const report = yield* MachineTest.check(Checkout) + return report.ok // false when any finding is an error + }) + ``` + + From a shell, `effect-machine check src/checkout.ts --json` prints one JSON object and exits with status 1 on any error. +- 42e2d90: Declare conditional transitions inline, with `branches` next to `resolve`, so one transition can be read and edited alone. The compiler checks one against the other in both directions, and rejects a resolver that does not return a `select` call on every path: + + ```ts + Pay: { + branches: [{ target: "Charging" }, { update: "root" }, { stay: true }, { decline: true }], + resolve: ({ event, select }) => { + if (event.amount < 0) return select.decline() + if (event.amount === 0) return select.stay() + return event.preview + ? select.update({ root: { total: event.amount } }) + : select.target("Charging", { data: { amount: event.amount } }) + } + } + ``` + + To migrate: move each `make({ branches })` group into its transition and drop its keys and `title`, so `select.key(...)` becomes `select.target(path, ...)`, `select.update({ owner: value })`, `select.history(path)`, `select.initialize({ input })`, or `select.stay()`. Two keys that reached the same destination are now one entry. Remove `declinable: true`, list `{ decline: true }`, and replace the `decline()` context function with `select.decline()`. + + `none` is replaced: `{ none: true }` becomes `{ stay: true }`, `{ none: true, reenter: true }` becomes `{ reenter: true }`, and `{ none: true, resolve }` becomes `{ stay: true, commands }`. Every plain transition accepts `commands: (context, enqueue) => ...`. + + `update` is now a record with one owner, so `data` only ever means the target's value: `{ update: "root", data }` becomes `{ update: { root: data } }`, and `{ target, update: "Owner", data: () => ({ target, update }) }` becomes `{ target, data, update: { Owner: value } }`. Inside a `branches` list, an entry still names its owner as a string, `{ target, update: "Owner" }`, and the value goes in its `select` call. + + `guard` and `decline` now exist only on `on` handlers and `always`. On `onDone`, `onFailure`, `onElement`, `onSnapshot`, and `choice`, which have no other candidate, use `{ stay: true }` or select a destination. A retained transition's `branchKey` and a transition definition's `key` are now the entry as written, such as `target:Paid`, and `title` is removed. + + In the Oxlint plugin, `no-conditional-none-branch` becomes `no-conditional-stay-branch`, and `no-redundant-resolve` is removed because the compiler now rejects what it reported. Resolvers for invocation outcomes and `always` may select `stay` conditionally, because `Machine.can` queries only events. + +### Patch Changes + +- 7d0e987: Update the devtools file watcher to chokidar 6. The devtools CLI now requires Node.js 22.22 or newer. + + Build the Oxlint plugin against `@oxlint/plugins` 1.90.0. The plugin still supports `oxlint` `>=1.80.0 <2`. +- 697c6cb: Install the devtools CLI without pinning a second exact TypeScript or Vite. + + `@typeonce/effect-machine-devtools` now depends on `typescript` `>=5.9.0 <7.0.0` and `vite` `^8.1.5` instead of exact versions, so a package manager can reuse compatible versions your project already has. No setup changes are required: the CLI still works when your project uses neither, or uses TypeScript 7. +- Updated dependencies [67f11cc] +- Updated dependencies [573636b] +- Updated dependencies [b24c367] +- Updated dependencies [d1d9137] +- Updated dependencies [ca51c52] +- Updated dependencies [42e2d90] +- Updated dependencies [104f98a] +- Updated dependencies [7ffcab7] + - @typeonce/effect-machine@0.47.0 + ## 0.46.0 ### Patch Changes diff --git a/packages/devtools/package.json b/packages/devtools/package.json index 67e48207..3f8c06d6 100644 --- a/packages/devtools/package.json +++ b/packages/devtools/package.json @@ -1,6 +1,6 @@ { "name": "@typeonce/effect-machine-devtools", - "version": "0.46.0", + "version": "0.47.0", "description": "Local development tools for Effect Machine", "author": "Sandro Maglione", "repository": { diff --git a/packages/effect-machine-react/CHANGELOG.md b/packages/effect-machine-react/CHANGELOG.md index f1c18338..850e8d3e 100644 --- a/packages/effect-machine-react/CHANGELOG.md +++ b/packages/effect-machine-react/CHANGELOG.md @@ -1,5 +1,50 @@ # @typeonce/effect-machine-react +## 0.47.0 + +### Minor Changes + +- 42e2d90: Declare conditional transitions inline, with `branches` next to `resolve`, so one transition can be read and edited alone. The compiler checks one against the other in both directions, and rejects a resolver that does not return a `select` call on every path: + + ```ts + Pay: { + branches: [{ target: "Charging" }, { update: "root" }, { stay: true }, { decline: true }], + resolve: ({ event, select }) => { + if (event.amount < 0) return select.decline() + if (event.amount === 0) return select.stay() + return event.preview + ? select.update({ root: { total: event.amount } }) + : select.target("Charging", { data: { amount: event.amount } }) + } + } + ``` + + To migrate: move each `make({ branches })` group into its transition and drop its keys and `title`, so `select.key(...)` becomes `select.target(path, ...)`, `select.update({ owner: value })`, `select.history(path)`, `select.initialize({ input })`, or `select.stay()`. Two keys that reached the same destination are now one entry. Remove `declinable: true`, list `{ decline: true }`, and replace the `decline()` context function with `select.decline()`. + + `none` is replaced: `{ none: true }` becomes `{ stay: true }`, `{ none: true, reenter: true }` becomes `{ reenter: true }`, and `{ none: true, resolve }` becomes `{ stay: true, commands }`. Every plain transition accepts `commands: (context, enqueue) => ...`. + + `update` is now a record with one owner, so `data` only ever means the target's value: `{ update: "root", data }` becomes `{ update: { root: data } }`, and `{ target, update: "Owner", data: () => ({ target, update }) }` becomes `{ target, data, update: { Owner: value } }`. Inside a `branches` list, an entry still names its owner as a string, `{ target, update: "Owner" }`, and the value goes in its `select` call. + + `guard` and `decline` now exist only on `on` handlers and `always`. On `onDone`, `onFailure`, `onElement`, `onSnapshot`, and `choice`, which have no other candidate, use `{ stay: true }` or select a destination. A retained transition's `branchKey` and a transition definition's `key` are now the entry as written, such as `target:Paid`, and `title` is removed. + + In the Oxlint plugin, `no-conditional-none-branch` becomes `no-conditional-stay-branch`, and `no-redundant-resolve` is removed because the compiler now rejects what it reported. Resolvers for invocation outcomes and `always` may select `stay` conditionally, because `Machine.can` queries only events. + +### Patch Changes + +- a5e80b3: Remove the `scheduler` peer dependency from `@typeonce/effect-machine-react`. + + The package never imports `scheduler`, so upgrading React no longer produces a peer warning from it. The `scheduler` version is now governed only by `react-dom` and `@effect/atom-react`. Remove `scheduler` from your dependencies if you installed it only for this package. +- ca51c52: Every API example in the published source now has a title, and the core package's examples compile and run against the current API. +- Updated dependencies [67f11cc] +- Updated dependencies [573636b] +- Updated dependencies [b24c367] +- Updated dependencies [d1d9137] +- Updated dependencies [ca51c52] +- Updated dependencies [42e2d90] +- Updated dependencies [104f98a] +- Updated dependencies [7ffcab7] + - @typeonce/effect-machine@0.47.0 + ## 0.46.0 ### Patch Changes diff --git a/packages/effect-machine-react/package.json b/packages/effect-machine-react/package.json index bd54bf59..73aca5a0 100644 --- a/packages/effect-machine-react/package.json +++ b/packages/effect-machine-react/package.json @@ -1,6 +1,6 @@ { "name": "@typeonce/effect-machine-react", - "version": "0.46.0", + "version": "0.47.0", "description": "React ownership hooks for Effect Machine atoms", "author": "Sandro Maglione", "repository": { diff --git a/packages/effect-machine/CHANGELOG.md b/packages/effect-machine/CHANGELOG.md index 9d39b551..3431ad7d 100644 --- a/packages/effect-machine/CHANGELOG.md +++ b/packages/effect-machine/CHANGELOG.md @@ -1,5 +1,69 @@ # @typeonce/effect-machine +## 0.47.0 + +### Minor Changes + +- 67f11cc: Compile errors for common machine mistakes now name the fix instead of reporting `never`: + + ```ts + Pay: { target: "Archivd" } + // Unknown target "Archivd". Declared: Editing, Checkout, Archived + + invoke: { src: "loadd", onDone: { stay: true } } + // Unknown source. Registered: load + ``` + + `Machine.handle` reports a misspelled target, source, or owner, a missing `data`, the root or a history state used as a target, and an `on`, `always`, `onDone`, or `invoke` on a final or choice state. + + A transition that targets a state below an inactive valued state, such as `{ target: "Checkout.Paid" }` from outside `Checkout`, used to fail while planning. It is now a compile error: target `"Checkout"` with a `branches` entry and construct the child with `select.target("Checkout", { data, states: { Paid: {} } })`. +- 573636b: Ship agent documentation as `AGENTS.md`, `CLAUDE.md`, and `ai-docs/` in the package, replacing `docs/`. + + An agent working in a project can now read documentation matching the installed version from `node_modules/@typeonce/effect-machine/AGENTS.md`. Replace links to `docs/agent-guide.md`, `docs/root-api.md`, `docs/effect-atom-react.md`, and `docs/machine-review.md` with that file, or with the matching section under `ai-docs/src`. +- d1d9137: Add `MachineTest.check`, `MachineTest.analyze`, and the `effect-machine check` command, so a machine can be verified with one call and no browser. + + `check` reports states with no path from the initial state, public events with no handler, nondeterministic planning, planner law violations, invariant failures, and declared branches that were never taken. It derives input and events from the machine's schemas, and each finding from a run includes the events that reproduce it. A report is `"exhaustive"` only when nothing limited exploration; otherwise `limits` says why it is `"bounded"`. + + ```ts + const program = Effect.gen(function*() { + const report = yield* MachineTest.check(Checkout) + return report.ok // false when any finding is an error + }) + ``` + + From a shell, `effect-machine check src/checkout.ts --json` prints one JSON object and exits with status 1 on any error. +- 42e2d90: Declare conditional transitions inline, with `branches` next to `resolve`, so one transition can be read and edited alone. The compiler checks one against the other in both directions, and rejects a resolver that does not return a `select` call on every path: + + ```ts + Pay: { + branches: [{ target: "Charging" }, { update: "root" }, { stay: true }, { decline: true }], + resolve: ({ event, select }) => { + if (event.amount < 0) return select.decline() + if (event.amount === 0) return select.stay() + return event.preview + ? select.update({ root: { total: event.amount } }) + : select.target("Charging", { data: { amount: event.amount } }) + } + } + ``` + + To migrate: move each `make({ branches })` group into its transition and drop its keys and `title`, so `select.key(...)` becomes `select.target(path, ...)`, `select.update({ owner: value })`, `select.history(path)`, `select.initialize({ input })`, or `select.stay()`. Two keys that reached the same destination are now one entry. Remove `declinable: true`, list `{ decline: true }`, and replace the `decline()` context function with `select.decline()`. + + `none` is replaced: `{ none: true }` becomes `{ stay: true }`, `{ none: true, reenter: true }` becomes `{ reenter: true }`, and `{ none: true, resolve }` becomes `{ stay: true, commands }`. Every plain transition accepts `commands: (context, enqueue) => ...`. + + `update` is now a record with one owner, so `data` only ever means the target's value: `{ update: "root", data }` becomes `{ update: { root: data } }`, and `{ target, update: "Owner", data: () => ({ target, update }) }` becomes `{ target, data, update: { Owner: value } }`. Inside a `branches` list, an entry still names its owner as a string, `{ target, update: "Owner" }`, and the value goes in its `select` call. + + `guard` and `decline` now exist only on `on` handlers and `always`. On `onDone`, `onFailure`, `onElement`, `onSnapshot`, and `choice`, which have no other candidate, use `{ stay: true }` or select a destination. A retained transition's `branchKey` and a transition definition's `key` are now the entry as written, such as `target:Paid`, and `title` is removed. + + In the Oxlint plugin, `no-conditional-none-branch` becomes `no-conditional-stay-branch`, and `no-redundant-resolve` is removed because the compiler now rejects what it reported. Resolvers for invocation outcomes and `always` may select `stay` conditionally, because `Machine.can` queries only events. + +### Patch Changes + +- b24c367: The npm page for `@typeonce/effect-machine` now links to the API reference at https://effect-machine.typeonce.dev. +- ca51c52: Every API example in the published source now has a title, and the core package's examples compile and run against the current API. +- 104f98a: Internal: check the compiled execution plan's transition contexts, targets, and commands at compile time instead of through `any` casts. Machine behavior and the public API are unchanged. +- 7ffcab7: Internal: check planner target resolution, invocation sources, and runtime child operations at compile time instead of through `any` casts. Machine behavior and the public API are unchanged. + ## 0.46.0 ### Minor Changes diff --git a/packages/effect-machine/package.json b/packages/effect-machine/package.json index 960820a3..99215ad4 100644 --- a/packages/effect-machine/package.json +++ b/packages/effect-machine/package.json @@ -1,6 +1,6 @@ { "name": "@typeonce/effect-machine", - "version": "0.46.0", + "version": "0.47.0", "description": "Schema-first state machines and statecharts for Effect", "author": "Sandro Maglione", "repository": { diff --git a/packages/oxlint-plugin/CHANGELOG.md b/packages/oxlint-plugin/CHANGELOG.md index e1ef5f0c..dbe75311 100644 --- a/packages/oxlint-plugin/CHANGELOG.md +++ b/packages/oxlint-plugin/CHANGELOG.md @@ -1,5 +1,40 @@ # @typeonce/oxlint-plugin-effect-machine +## 0.47.0 + +### Minor Changes + +- 42e2d90: Declare conditional transitions inline, with `branches` next to `resolve`, so one transition can be read and edited alone. The compiler checks one against the other in both directions, and rejects a resolver that does not return a `select` call on every path: + + ```ts + Pay: { + branches: [{ target: "Charging" }, { update: "root" }, { stay: true }, { decline: true }], + resolve: ({ event, select }) => { + if (event.amount < 0) return select.decline() + if (event.amount === 0) return select.stay() + return event.preview + ? select.update({ root: { total: event.amount } }) + : select.target("Charging", { data: { amount: event.amount } }) + } + } + ``` + + To migrate: move each `make({ branches })` group into its transition and drop its keys and `title`, so `select.key(...)` becomes `select.target(path, ...)`, `select.update({ owner: value })`, `select.history(path)`, `select.initialize({ input })`, or `select.stay()`. Two keys that reached the same destination are now one entry. Remove `declinable: true`, list `{ decline: true }`, and replace the `decline()` context function with `select.decline()`. + + `none` is replaced: `{ none: true }` becomes `{ stay: true }`, `{ none: true, reenter: true }` becomes `{ reenter: true }`, and `{ none: true, resolve }` becomes `{ stay: true, commands }`. Every plain transition accepts `commands: (context, enqueue) => ...`. + + `update` is now a record with one owner, so `data` only ever means the target's value: `{ update: "root", data }` becomes `{ update: { root: data } }`, and `{ target, update: "Owner", data: () => ({ target, update }) }` becomes `{ target, data, update: { Owner: value } }`. Inside a `branches` list, an entry still names its owner as a string, `{ target, update: "Owner" }`, and the value goes in its `select` call. + + `guard` and `decline` now exist only on `on` handlers and `always`. On `onDone`, `onFailure`, `onElement`, `onSnapshot`, and `choice`, which have no other candidate, use `{ stay: true }` or select a destination. A retained transition's `branchKey` and a transition definition's `key` are now the entry as written, such as `target:Paid`, and `title` is removed. + + In the Oxlint plugin, `no-conditional-none-branch` becomes `no-conditional-stay-branch`, and `no-redundant-resolve` is removed because the compiler now rejects what it reported. Resolvers for invocation outcomes and `always` may select `stay` conditionally, because `Machine.can` queries only events. + +### Patch Changes + +- 7d0e987: Update the devtools file watcher to chokidar 6. The devtools CLI now requires Node.js 22.22 or newer. + + Build the Oxlint plugin against `@oxlint/plugins` 1.90.0. The plugin still supports `oxlint` `>=1.80.0 <2`. + ## 0.46.0 ## 0.45.1 diff --git a/packages/oxlint-plugin/package.json b/packages/oxlint-plugin/package.json index eeb511c8..c386e325 100644 --- a/packages/oxlint-plugin/package.json +++ b/packages/oxlint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@typeonce/oxlint-plugin-effect-machine", - "version": "0.46.0", + "version": "0.47.0", "description": "Oxlint rules for Effect Machine models", "author": "Sandro Maglione", "repository": {