@typeonce/effect-machine 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +89 -13
  2. package/dist/Machine.d.ts +396 -127
  3. package/dist/Machine.d.ts.map +1 -1
  4. package/dist/Machine.js +21 -19
  5. package/dist/Machine.js.map +1 -1
  6. package/dist/internal/machine/atom.d.ts +1 -0
  7. package/dist/internal/machine/atom.d.ts.map +1 -1
  8. package/dist/internal/machine/atom.js +23 -0
  9. package/dist/internal/machine/atom.js.map +1 -1
  10. package/dist/internal/machine/cluster.js +2 -2
  11. package/dist/internal/machine/cluster.js.map +1 -1
  12. package/dist/internal/machine/commandRuntime.d.ts.map +1 -1
  13. package/dist/internal/machine/commandRuntime.js +2 -5
  14. package/dist/internal/machine/commandRuntime.js.map +1 -1
  15. package/dist/internal/machine/configuration.d.ts +12 -7
  16. package/dist/internal/machine/configuration.d.ts.map +1 -1
  17. package/dist/internal/machine/configuration.js +9 -5
  18. package/dist/internal/machine/configuration.js.map +1 -1
  19. package/dist/internal/machine/executionPlan.d.ts +4 -3
  20. package/dist/internal/machine/executionPlan.d.ts.map +1 -1
  21. package/dist/internal/machine/executionPlan.js +68 -43
  22. package/dist/internal/machine/executionPlan.js.map +1 -1
  23. package/dist/internal/machine/initialization.d.ts +5 -0
  24. package/dist/internal/machine/initialization.d.ts.map +1 -0
  25. package/dist/internal/machine/initialization.js +61 -0
  26. package/dist/internal/machine/initialization.js.map +1 -0
  27. package/dist/internal/machine/inspectionRuntime.d.ts +25 -0
  28. package/dist/internal/machine/inspectionRuntime.d.ts.map +1 -0
  29. package/dist/internal/machine/inspectionRuntime.js +79 -0
  30. package/dist/internal/machine/inspectionRuntime.js.map +1 -0
  31. package/dist/internal/machine/invocation.d.ts +2 -1
  32. package/dist/internal/machine/invocation.d.ts.map +1 -1
  33. package/dist/internal/machine/invocation.js +18 -11
  34. package/dist/internal/machine/invocation.js.map +1 -1
  35. package/dist/internal/machine/machine.d.ts +1 -2
  36. package/dist/internal/machine/machine.d.ts.map +1 -1
  37. package/dist/internal/machine/machine.js +21 -6
  38. package/dist/internal/machine/machine.js.map +1 -1
  39. package/dist/internal/machine/planner.d.ts +17 -2
  40. package/dist/internal/machine/planner.d.ts.map +1 -1
  41. package/dist/internal/machine/planner.js +137 -64
  42. package/dist/internal/machine/planner.js.map +1 -1
  43. package/dist/internal/machine/process.d.ts.map +1 -1
  44. package/dist/internal/machine/process.js +7 -5
  45. package/dist/internal/machine/process.js.map +1 -1
  46. package/dist/internal/machine/runtime.d.ts +29 -5
  47. package/dist/internal/machine/runtime.d.ts.map +1 -1
  48. package/dist/internal/machine/runtime.js +440 -64
  49. package/dist/internal/machine/runtime.js.map +1 -1
  50. package/dist/internal/machine/symbols.d.ts +2 -0
  51. package/dist/internal/machine/symbols.d.ts.map +1 -1
  52. package/dist/internal/machine/symbols.js +2 -0
  53. package/dist/internal/machine/symbols.js.map +1 -1
  54. package/dist/internal/machine/topology.d.ts +13 -0
  55. package/dist/internal/machine/topology.d.ts.map +1 -1
  56. package/dist/internal/machine/topology.js +9 -0
  57. package/dist/internal/machine/topology.js.map +1 -1
  58. package/dist/internal/testing/machine/finiteModel.d.ts.map +1 -1
  59. package/dist/internal/testing/machine/finiteModel.js +3 -3
  60. package/dist/internal/testing/machine/finiteModel.js.map +1 -1
  61. package/dist/unstable/reactivity/AtomMachine.d.ts +9 -0
  62. package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
  63. package/dist/unstable/reactivity/AtomMachine.js +9 -0
  64. package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
  65. package/docs/agent-guide.md +130 -20
  66. package/package.json +5 -5
  67. package/src/Machine.ts +548 -217
  68. package/src/internal/machine/atom.ts +26 -0
  69. package/src/internal/machine/cluster.ts +2 -2
  70. package/src/internal/machine/commandRuntime.ts +2 -7
  71. package/src/internal/machine/configuration.ts +38 -13
  72. package/src/internal/machine/executionPlan.ts +85 -52
  73. package/src/internal/machine/initialization.ts +73 -0
  74. package/src/internal/machine/inspectionRuntime.ts +102 -0
  75. package/src/internal/machine/invocation.ts +38 -13
  76. package/src/internal/machine/machine.ts +31 -6
  77. package/src/internal/machine/planner.ts +166 -66
  78. package/src/internal/machine/process.ts +7 -5
  79. package/src/internal/machine/runtime.ts +663 -91
  80. package/src/internal/machine/symbols.ts +3 -0
  81. package/src/internal/machine/topology.ts +27 -0
  82. package/src/internal/testing/machine/finiteModel.ts +8 -7
  83. package/src/unstable/reactivity/AtomMachine.ts +12 -0
package/README.md CHANGED
@@ -10,10 +10,31 @@ cluster adapter.
10
10
  > This is early-release software. Its API may change, and each release targets
11
11
  > one exact Effect beta.
12
12
 
13
+ ## Design principles
14
+
15
+ - **Type-safe by construction:** reject invalid protocols, compositions, and
16
+ capabilities at compile time where possible, and preserve typed Effect
17
+ failures at runtime.
18
+ - **Explicit and opinionated:** give different semantics different names and
19
+ contracts. Builders and inference remove ceremony without making behavior
20
+ depend on ambiguous omissions.
21
+ - **Readable models:** keep schemas, topology, behavior, and effects concise
22
+ enough that a human can understand the complete model from its definition.
23
+ - **Effect-native:** design toward eventual inclusion in Effect core and follow
24
+ its API shape, module boundaries, ownership, and failure conventions.
25
+
26
+ The package is pre-1.0: a clearer or safer long-term API takes priority over
27
+ backward compatibility. Breaking changes use minor releases, compatible fixes
28
+ use patch releases, and compatibility aliases are not added by default.
29
+
30
+ The core machine model remains local. Distributed identity, placement,
31
+ transport, routing, delivery, and remote lifecycle semantics belong to Effect
32
+ Cluster and are exposed only through explicit integration boundaries.
33
+
13
34
  ## Install
14
35
 
15
36
  ```sh
16
- pnpm add @typeonce/effect-machine effect@4.0.0-rc.108
37
+ pnpm add @typeonce/effect-machine effect@4.0.0-rc.109
17
38
  ```
18
39
 
19
40
  `effect` is an exact peer dependency. Install the version above and upgrade it
@@ -136,7 +157,7 @@ data, put it on their compound parent.
136
157
 
137
158
  ### Separate inputs, raised events, and emissions
138
159
 
139
- `events` is the public actor-input protocol. Events raised to the same machine
160
+ `events` is the public machine-input protocol. Events raised to the same machine
140
161
  belong in `internalEvents`. Ephemeral outward notifications have their own
141
162
  `emittedEvents` protocol:
142
163
 
@@ -186,7 +207,7 @@ protocols but cannot expose a finite constructor set; pass a complete event
186
207
  object to `send` or `Machine.plan` for those events.
187
208
 
188
209
  `ref.emissions` is a hot `Stream`: it publishes only notifications produced
189
- after subscription, replays nothing, and completes when the actor terminates.
210
+ after subscription, replays nothing, and completes when the machine terminates.
190
211
  Snapshots remain separate and stateful: `ref.changes` begins with the current
191
212
  lifecycle snapshot and then follows later changes. Use `Machine.prepare` when
192
213
  an observer must be installed before initial-entry actions run:
@@ -206,13 +227,63 @@ const ref = yield * prepared.start
206
227
  not observe startup emissions. Preparation does not retain or replay an
207
228
  emission: the observer is simply subscribed before initialization begins.
208
229
 
230
+ ### Inspect a live machine tree
231
+
232
+ `Machine.prepare(machine).inspection` is the operational counterpart to the
233
+ domain-facing `changes` and `emissions` streams. It observes the prepared root
234
+ and every locally owned child, `Logic` process, Effect, and timer in one total
235
+ publication order:
236
+
237
+ ```ts
238
+ const prepared = yield * Machine.prepare(checkout)
239
+
240
+ yield * prepared.inspection.pipe(
241
+ Stream.runForEach((record) => Console.log(record.sequence, record.subject.id, record._tag)),
242
+ Effect.forkScoped({ startImmediately: true })
243
+ )
244
+
245
+ const checkoutRef = yield * prepared.start
246
+ ```
247
+
248
+ For a handled input, the stream may expose values such as:
249
+
250
+ ```ts
251
+ { _tag: "EventSent", sequence: 2, deliveryId: 0,
252
+ subject: { id: "checkout", sessionId: "machine:0", kind: "Machine" },
253
+ source: undefined, target: { id: "checkout", sessionId: "machine:0" },
254
+ event: CheckoutEvents.Submit(), causedBy: undefined }
255
+
256
+ { _tag: "EventProcessed", sequence: 4, macrostepId: 0,
257
+ deliveryId: 0, handled: true, configurationChanged: true,
258
+ before: { status: "active", state: /* ... */ },
259
+ after: { status: "active", state: /* ... */ }, microsteps: [/* ... */] }
260
+ ```
261
+
262
+ The closed `Machine.Inspection.Event` union also reports creation,
263
+ initialization and startup failure, direct `Logic` state updates, outward
264
+ emissions, Effect/timer activity lifecycles, and termination. Records erase
265
+ unrelated child protocols to `unknown`; application-level observation remains
266
+ typed through each reference's `changes` and `emissions`.
267
+
268
+ The stream is hot, non-replayed, never fails, and completes after the root
269
+ terminates. Subscribe before `prepared.start` to capture initialization. Local
270
+ session ids are unique only inside that prepared ownership tree: `machine:0`
271
+ is the root and later ids identify its descendants. They are intentionally not
272
+ distributed identities. Cluster placement, routing, and correlation continue
273
+ to use Cluster entity, runner, and request identities at the integration
274
+ boundary.
275
+
276
+ `AtomMachine.inspection(machineAtom)` provides the same root-scoped stream and
277
+ starts a fresh atom-backed machine only after its inspection subscription is
278
+ installed.
279
+
209
280
  Invalid event and emission constructions fail the machine with a typed
210
281
  `MachineSchemaDecodeError`; they do not throw from the constructor call.
211
282
 
212
- ### Send explicitly between actors
283
+ ### Send explicitly between machines
213
284
 
214
- `raise` targets the current machine in the same macrostep. `sendTo` targets an
215
- actor mailbox and is processed later. A child declares the subset of parent
285
+ `raise` targets the current machine in the same macrostep. `sendTo` targets a
286
+ machine mailbox and is processed later. A child declares the subset of parent
216
287
  inputs it may send with `parentEvents`:
217
288
 
218
289
  ```ts
@@ -244,15 +315,18 @@ const ParentInputs = Machine.events(Start, ParentEvents)
244
315
  The same child remains isolated and may be started as a root, where `parent` is
245
316
  `undefined`. When `Child` is invoked, the parent definition must accept every
246
317
  event in `parentEvents`; otherwise `.handle(...)` is a compile-time error.
247
- Inside the child, the parent reference accepts only those declared events.
248
- `emit` never sends to the parent: it only publishes on the emitting actor's
318
+ Inside the child, the parent target accepts only those declared events.
319
+ `emit` never sends to the parent: it only publishes on the emitting machine's
249
320
  `emissions` stream.
250
321
 
251
322
  Every handler also receives `self`, which can be targeted with `sendTo` when a
252
323
  later mailbox turn is required. Use `raise` instead for same-macrostep work.
324
+ Both `self` and `parent` are minimal `Machine.MachineTarget<Event>` values. The
325
+ shared `Machine.MachineReferences<InputEvents, ParentEvents>` context keeps
326
+ their input protocols separate without exposing snapshot or lifecycle APIs.
253
327
  Structural state values use distinct names: `containingState` is the immediate
254
328
  valued state in the same statechart, while `ancestors` maps valued ancestor
255
- paths. `parent` always means the owning actor reference.
329
+ paths. `parent` always means the owning machine target.
256
330
 
257
331
  ### Choose the target by scope
258
332
 
@@ -302,7 +376,7 @@ State-scoped work starts on entry and is interrupted on exit:
302
376
  Loading: {
303
377
  invoke: Machine.invoke({
304
378
  id: "save-document",
305
- effect: saveDocument,
379
+ effect: () => saveDocument,
306
380
  onDone: ({ output, target }) => target.full.Saved({ id: output.id }),
307
381
  onFailure: ({ error, target }) => target.full.Failed({ message: String(error) })
308
382
  })
@@ -369,8 +443,10 @@ lookup.
369
443
  `onDone` is required for a non-`never` output, and `onFailure` is required for a
370
444
  non-`never` typed error; each handler is omitted when its channel is `never`.
371
445
  Defects, interruption, and source-construction failures terminate the owning
372
- runtime. `effect: Effect.sleep(...)` is valid, but `after` keeps timers explicit
373
- and makes static durations visible through activity inspection.
446
+ runtime. Effect sources are always factories evaluated when their state is
447
+ entered. Use `effect: () => Effect.sleep(...)` for a generic Effect, while
448
+ `after` keeps timers explicit and makes static durations visible through
449
+ activity inspection.
374
450
 
375
451
  ## Reactivity
376
452
 
@@ -401,7 +477,7 @@ const childEmissions = AtomMachine.childEmissions(counterAtom.child(Worker))
401
477
  ```
402
478
 
403
479
  These streams require the same `AtomRegistry`, follow the currently mounted
404
- actor instance, and do not replay notifications from an earlier subscription
480
+ machine instance, and do not replay notifications from an earlier subscription
405
481
  or child instance.
406
482
 
407
483
  ## Persistence