@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
@@ -7,7 +7,13 @@
7
7
  import * as Cause from "effect/Cause"
8
8
  import * as Effect from "effect/Effect"
9
9
  import type * as Schema from "effect/Schema"
10
- import type { ActorContext, ActorRef, Enqueue, InitialEvent as MachineInitialEvent, Machine } from "../../Machine.js"
10
+ import type {
11
+ Enqueue,
12
+ InitialEvent as MachineInitialEvent,
13
+ Machine,
14
+ MachineReferences,
15
+ MachineTarget
16
+ } from "../../Machine.js"
11
17
  import { getTargetBuilder, makeCollector, type RuntimeCommand } from "./command.js"
12
18
  import {
13
19
  type ActiveConfiguration,
@@ -16,6 +22,7 @@ import {
16
22
  completeConfigurationEffect,
17
23
  completeConfigurationSync,
18
24
  configurationFromHistoryRecord,
25
+ configurationFromInitialTargetSync,
19
26
  getActiveLeafPathFrom,
20
27
  getActiveLeafPaths,
21
28
  getHistoryRecord,
@@ -38,13 +45,16 @@ import {
38
45
  validateInitialConfiguration
39
46
  } from "./configuration.js"
40
47
  import { InfiniteTransitionError, MachineSchemaDecodeError, StartupError, StoppedError } from "./errors.js"
48
+ import { getStateInitializeValues, makeStateInitializeBuilder } from "./initialization.js"
41
49
  import * as InvocationEvent from "./invocationEvent.js"
42
50
  import { decodeEventSync, decodeInputSync, decodeStateValueSync } from "./protocol.js"
43
51
  import { InitialEventTypeId } from "./symbols.js"
44
52
  import {
45
53
  getNode,
54
+ type InitialTarget as InitialTargetInstruction,
46
55
  isChoiceTarget,
47
56
  isHistoryTarget,
57
+ isInitialTarget,
48
58
  isNoTarget,
49
59
  isSnapshot,
50
60
  isTarget,
@@ -94,35 +104,35 @@ export type TransitionHandler<States extends Machine.StateSchemas, E, R, Context
94
104
  enqueue: Enqueue<any, any>
95
105
  ) => Machine.HandlerResult<States, E, R>
96
106
 
97
- const rootActorScopes = new WeakMap<Machine.Any, ActorContext<any, any>>()
98
- const machineActorScopes = new WeakMap<Machine.Any, ActorContext<any, any>>()
107
+ const rootMachineReferences = new WeakMap<Machine.Any, MachineReferences<any, any>>()
108
+ const scopedMachineReferences = new WeakMap<Machine.Any, MachineReferences<any, any>>()
99
109
 
100
- export const withActorScope = (
110
+ export const withMachineReferences = (
101
111
  machine: Machine.Any,
102
- actorScope: ActorContext<any, any>
112
+ machineReferences: MachineReferences<any, any>
103
113
  ): Machine.Any => {
104
114
  const scoped = Object.create(machine) as Machine.Any
105
- machineActorScopes.set(scoped, { self: actorScope.self, parent: actorScope.parent })
115
+ scopedMachineReferences.set(scoped, { self: machineReferences.self, parent: machineReferences.parent })
106
116
  return scoped
107
117
  }
108
118
 
109
- const getActorContext = (
119
+ const resolveMachineReferences = (
110
120
  machine: Machine.Any,
111
121
  configuration: ActiveConfiguration
112
- ): ActorContext<any, any> => {
113
- const scope = configuration.actorScope
122
+ ): MachineReferences<any, any> => {
123
+ const scope = configuration.machineReferences
114
124
  if (scope !== undefined) return scope
115
- const machineScope = machineActorScopes.get(machine)
125
+ const machineScope = scopedMachineReferences.get(machine)
116
126
  if (machineScope !== undefined) return machineScope
117
- const cached = rootActorScopes.get(machine)
127
+ const cached = rootMachineReferences.get(machine)
118
128
  if (cached !== undefined) return cached
119
- const self: ActorRef<unknown> = {
129
+ const self: MachineTarget<unknown> = {
120
130
  id: machine.id ?? "Machine",
121
131
  sessionId: "Machine.plan",
122
132
  send: () => Effect.fail(new StoppedError())
123
133
  }
124
134
  const root = { self, parent: undefined }
125
- rootActorScopes.set(machine, root)
135
+ rootMachineReferences.set(machine, root)
126
136
  return root
127
137
  }
128
138
 
@@ -224,6 +234,7 @@ const completeHistoryConfiguration = (
224
234
  const commands: Array<RuntimeCommand> = []
225
235
  const raisedEvents: Array<unknown> = []
226
236
  const emittedEvents: Array<unknown> = []
237
+ const transitions: Array<ResolvedChoiceTransition> = []
227
238
 
228
239
  let changed = true
229
240
  while (changed) {
@@ -240,22 +251,62 @@ const completeHistoryConfiguration = (
240
251
  values,
241
252
  outputs: configuration.outputs,
242
253
  history: configuration.history,
243
- actorScope: configuration.actorScope
254
+ machineReferences: configuration.machineReferences
244
255
  } as ActiveConfiguration
256
+ if (child.type === "choice") {
257
+ const choice = resolveChoiceTarget(
258
+ machine,
259
+ current,
260
+ makeChoiceTarget(child.path, path, Object.fromEntries(values)),
261
+ event
262
+ )
263
+ let next = current
264
+ for (const routed of [choice.target, ...choice.additionalTargets]) {
265
+ if (routed === undefined || isHistoryTarget(routed)) {
266
+ throw new Error(`Machine initial choice "${child.path}" must resolve to an active state target`)
267
+ }
268
+ const resolved = isInitialTarget(routed)
269
+ ? resolveInitialTarget(machine, next, routed, event)
270
+ : undefined
271
+ next = normalizeTargetConfigurationSync(
272
+ machine,
273
+ next,
274
+ (resolved?.target ?? routed) as Machine.Snapshot<any> | Machine.Target<any, any>
275
+ )
276
+ if (resolved !== undefined) {
277
+ commands.push(...resolved.commands)
278
+ raisedEvents.push(...resolved.raisedEvents)
279
+ emittedEvents.push(...resolved.emittedEvents)
280
+ transitions.push(...resolved.transitions)
281
+ }
282
+ }
283
+ active.clear()
284
+ values.clear()
285
+ for (const activePath of next.active) active.add(activePath)
286
+ for (const [valuePath, stateValue] of next.values) values.set(valuePath, stateValue)
287
+ commands.push(...choice.commands)
288
+ raisedEvents.push(...choice.raisedEvents)
289
+ emittedEvents.push(...choice.emittedEvents)
290
+ transitions.push(...choice.transitions)
291
+ changed = true
292
+ continue
293
+ }
245
294
  active.add(child.path)
246
295
  if (child.schema !== undefined) {
247
- const initializer = machine.handlers[path]?.initial
296
+ const initializer = machine.handlers[path]?.initialize
248
297
  if (initializer === undefined) {
249
298
  throw new Error(`Machine shallow history requires an initial value implementation for state "${path}"`)
250
299
  }
251
300
  const initialized = collectStateInitializer(machine, initializer, {
252
- ...getActorContext(machine, current),
301
+ ...resolveMachineReferences(machine, current),
253
302
  state: current.values.get(path),
254
303
  containingState: getParentValue(machine, current, path),
255
304
  ancestors: getParentValues(machine, current, path),
256
- event
305
+ event,
306
+ builder: makeStateInitializeBuilder(machine, path)
257
307
  })
258
- values.set(child.path, decodeStateValueSync(machine, child, initialized.value))
308
+ const initializedValues = getStateInitializeValues(path, initialized.value)
309
+ values.set(child.path, decodeStateValueSync(machine, child, initializedValues[child.key]))
259
310
  commands.push(...initialized.commands)
260
311
  raisedEvents.push(...initialized.raisedEvents)
261
312
  emittedEvents.push(...initialized.emittedEvents)
@@ -271,35 +322,36 @@ const completeHistoryConfiguration = (
271
322
  values,
272
323
  outputs: configuration.outputs,
273
324
  history: configuration.history,
274
- actorScope: configuration.actorScope
325
+ machineReferences: configuration.machineReferences
275
326
  } as ActiveConfiguration
276
- const initializer = valuedMissing.length === 0 ? undefined : machine.handlers[path]?.initial
327
+ const initializer = valuedMissing.length === 0 ? undefined : machine.handlers[path]?.initialize
277
328
  if (valuedMissing.length > 0 && initializer === undefined) {
278
329
  throw new Error(`Machine shallow history requires an initial value implementation for state "${path}"`)
279
330
  }
280
331
  const initialized = initializer === undefined ? undefined : collectStateInitializer(machine, initializer, {
281
- ...getActorContext(machine, current),
332
+ ...resolveMachineReferences(machine, current),
282
333
  state: current.values.get(path),
283
334
  containingState: getParentValue(machine, current, path),
284
335
  ancestors: getParentValues(machine, current, path),
285
- event
336
+ event,
337
+ builder: makeStateInitializeBuilder(machine, path)
286
338
  })
287
- if (initialized !== undefined && (typeof initialized.value !== "object" || initialized.value === null)) {
288
- throw new Error(`Machine parallel state initializer for "${path}" must return its region values`)
289
- }
339
+ const initializedValues = initialized === undefined
340
+ ? undefined
341
+ : getStateInitializeValues(path, initialized.value)
290
342
  for (const childPath of missing) {
291
343
  const child = getNode(machine, childPath)
292
344
  active.add(child.path)
293
345
  if (child.schema !== undefined) {
294
346
  if (
295
347
  initialized === undefined ||
296
- !Object.prototype.hasOwnProperty.call(initialized.value as object, child.key)
348
+ initializedValues === undefined || !Object.prototype.hasOwnProperty.call(initializedValues, child.key)
297
349
  ) {
298
350
  throw new Error(`Machine parallel state initializer for "${path}" must return region "${child.key}"`)
299
351
  }
300
352
  values.set(
301
353
  child.path,
302
- decodeStateValueSync(machine, child, (initialized.value as Record<string, unknown>)[child.key])
354
+ decodeStateValueSync(machine, child, initializedValues[child.key])
303
355
  )
304
356
  }
305
357
  }
@@ -322,16 +374,38 @@ const completeHistoryConfiguration = (
322
374
  } as ActiveConfiguration,
323
375
  commands,
324
376
  raisedEvents,
325
- emittedEvents
377
+ emittedEvents,
378
+ transitions
326
379
  }
327
380
  }
328
381
 
329
- const resolveHistoryTarget = (
382
+ export function resolveInitialTarget(
383
+ machine: Machine.Any,
384
+ configuration: ActiveConfiguration,
385
+ target: InitialTargetInstruction,
386
+ event: unknown
387
+ ) {
388
+ const partial = configurationFromInitialTargetSync(machine, configuration, target)
389
+ const completed = completeHistoryConfiguration(machine, partial, event)
390
+ const snapshot = snapshotFromConfigurationAtPath(machine, completed.configuration, target.path)
391
+ return {
392
+ target: makeTarget(target.path as any, snapshot.value as any, {
393
+ snapshot: snapshot as any,
394
+ values: Object.fromEntries(completed.configuration.values) as any
395
+ }),
396
+ commands: completed.commands,
397
+ raisedEvents: completed.raisedEvents,
398
+ emittedEvents: completed.emittedEvents,
399
+ transitions: completed.transitions
400
+ }
401
+ }
402
+
403
+ function resolveHistoryTarget(
330
404
  machine: Machine.Any,
331
405
  configuration: ActiveConfiguration,
332
406
  target: { readonly path: string; readonly parent: string },
333
407
  event: unknown
334
- ) => {
408
+ ) {
335
409
  const node = getNode(machine, target.path)
336
410
  if (node.type !== "history" || node.parent !== target.parent) {
337
411
  throw new Error(`Machine expected history target "${target.path}" to resolve to its declared parent`)
@@ -353,7 +427,7 @@ const resolveHistoryTarget = (
353
427
  commands: completed.commands,
354
428
  raisedEvents: completed.raisedEvents,
355
429
  emittedEvents: completed.emittedEvents,
356
- transitions: []
430
+ transitions: completed.transitions
357
431
  }
358
432
  }
359
433
 
@@ -542,7 +616,7 @@ const makeStateActionContext = <
542
616
  path: string,
543
617
  event: Machine.LifecycleEvent<Events>
544
618
  ): Machine.StateActionContext<States, Events, Emits, StateId> => ({
545
- ...getActorContext(machine, configuration),
619
+ ...resolveMachineReferences(machine, configuration),
546
620
  state: configuration.values.get(path) as Machine.StateByIdentifier<States, StateId>,
547
621
  containingState: getParentValue(machine, configuration, path) as Machine.ParentStateValue<States, StateId>,
548
622
  ancestors: getParentValues(machine, configuration, path) as Machine.ParentStateValues<States, StateId>,
@@ -562,7 +636,7 @@ const makeTransitionContext = <
562
636
  event: Machine.EventByTag<Events, EventTag>,
563
637
  snapshot: Machine.Snapshot<States>
564
638
  ): Machine.HandlerContext<States, Events, Emits, StateId, EventTag, any, any> => ({
565
- ...getActorContext(machine, configuration),
639
+ ...resolveMachineReferences(machine, configuration),
566
640
  state: configuration.values.get(path) as Machine.StateByIdentifier<States, StateId>,
567
641
  containingState: getParentValue(machine, configuration, path) as Machine.ParentStateValue<States, StateId>,
568
642
  ancestors: getParentValues(machine, configuration, path) as Machine.ParentStateValues<States, StateId>,
@@ -584,7 +658,7 @@ const makeDoneContext = <
584
658
  output: unknown,
585
659
  snapshot: Machine.Snapshot<States>
586
660
  ): Machine.DoneContext<States, Events, Emits, StateId> => ({
587
- ...getActorContext(machine, configuration),
661
+ ...resolveMachineReferences(machine, configuration),
588
662
  state: configuration.values.get(path) as Machine.StateByIdentifier<States, StateId>,
589
663
  containingState: getParentValue(machine, configuration, path) as Machine.ParentStateValue<States, StateId>,
590
664
  ancestors: getParentValues(machine, configuration, path) as Machine.ParentStateValues<States, StateId>,
@@ -679,7 +753,7 @@ const selectAlwaysTransitions = <
679
753
  Machine.AlwaysContext<States, Events, Emits, Machine.StateIdentifier<States>>
680
754
  >,
681
755
  context: {
682
- ...getActorContext(machine, configuration),
756
+ ...resolveMachineReferences(machine, configuration),
683
757
  state: configuration.values.get(path) as Machine.StateByIdentifier<
684
758
  States,
685
759
  Machine.StateIdentifier<States>
@@ -867,7 +941,7 @@ const selectInvocationTransition = <
867
941
  if (transition === undefined) return []
868
942
  const snapshot = snapshotFromConfiguration<States>(machine, configuration)
869
943
  const context = {
870
- ...getActorContext(machine, configuration),
944
+ ...resolveMachineReferences(machine, configuration),
871
945
  state: configuration.values.get(event.path),
872
946
  containingState: getParentValue(machine, configuration, event.path),
873
947
  ancestors: getParentValues(machine, configuration, event.path),
@@ -1059,12 +1133,12 @@ interface ResolvedChoiceTransition {
1059
1133
  readonly resolvedTarget: string
1060
1134
  }
1061
1135
 
1062
- const resolveChoiceTarget = (
1136
+ function resolveChoiceTarget(
1063
1137
  machine: Machine.Any,
1064
1138
  configuration: ActiveConfiguration,
1065
1139
  initialTarget: unknown,
1066
1140
  event: unknown
1067
- ) => {
1141
+ ) {
1068
1142
  const pending: Array<unknown> = [initialTarget]
1069
1143
  const resolvedTargets: Array<unknown> = []
1070
1144
  const commands: Array<RuntimeCommand> = []
@@ -1107,10 +1181,10 @@ const resolveChoiceTarget = (
1107
1181
  ]),
1108
1182
  outputs: configuration.outputs,
1109
1183
  history: configuration.history,
1110
- ...(configuration.actorScope === undefined ? {} : { actorScope: configuration.actorScope })
1184
+ ...(configuration.machineReferences === undefined ? {} : { machineReferences: configuration.machineReferences })
1111
1185
  }
1112
1186
  const collected = collectTransition(machine, choice.transition, {
1113
- ...getActorContext(machine, provisional),
1187
+ ...resolveMachineReferences(machine, provisional),
1114
1188
  containingState: getParentValue(machine, provisional, node.path),
1115
1189
  ancestors: getParentValues(machine, provisional, node.path),
1116
1190
  event,
@@ -1135,7 +1209,7 @@ const resolveChoiceTarget = (
1135
1209
  emittedEvents.push(...collected.emittedEvents)
1136
1210
  }
1137
1211
 
1138
- if (!isTarget(current) && !isSnapshot(current) && !isHistoryTarget(current)) {
1212
+ if (!isTarget(current) && !isSnapshot(current) && !isHistoryTarget(current) && !isInitialTarget(current)) {
1139
1213
  throw new Error("Machine choice resolver must return a concrete typed target")
1140
1214
  }
1141
1215
  resolvedTargets.push(current)
@@ -1190,6 +1264,10 @@ const collectEvaluatedTransition = <
1190
1264
  (selection.context as any).event
1191
1265
  )
1192
1266
  const choiceResolvedTarget = choiceResolution?.target ?? unresolvedTarget
1267
+ const initialResolution = choiceResolvedTarget !== undefined && isInitialTarget(choiceResolvedTarget)
1268
+ ? resolveInitialTarget(machine, state, choiceResolvedTarget, (selection.context as any).event)
1269
+ : undefined
1270
+ const routedTarget = initialResolution?.target ?? choiceResolvedTarget
1193
1271
  let historyResolution: {
1194
1272
  readonly target: unknown
1195
1273
  readonly commands: ReadonlyArray<RuntimeCommand>
@@ -1197,50 +1275,64 @@ const collectEvaluatedTransition = <
1197
1275
  readonly emittedEvents: ReadonlyArray<unknown>
1198
1276
  readonly transitions: ReadonlyArray<ResolvedChoiceTransition>
1199
1277
  } | undefined
1200
- const reenteredHistoryTarget = isHistoryTarget(choiceResolvedTarget) && selection.transition.reenter &&
1201
- state.active.has(choiceResolvedTarget.parent)
1202
- ? choiceResolvedTarget
1278
+ const reenteredHistoryTarget = isHistoryTarget(routedTarget) && selection.transition.reenter &&
1279
+ state.active.has(routedTarget.parent)
1280
+ ? routedTarget
1203
1281
  : undefined
1204
- if (choiceResolvedTarget !== undefined && isHistoryTarget(choiceResolvedTarget)) {
1282
+ if (routedTarget !== undefined && isHistoryTarget(routedTarget)) {
1205
1283
  // A reentering transition may exit the history node's own parent. SCXML
1206
1284
  // history observes that same exit, so resolve against a provisional
1207
1285
  // capture rather than an older record (or the default).
1208
1286
  const provisionalBoundary = selection.transition.reenter
1209
1287
  ? getNode(machine, selection.sourcePath).parent
1210
- : getLeastCommonAncestor(machine, stateIdentifier, choiceResolvedTarget.parent)
1288
+ : getLeastCommonAncestor(machine, stateIdentifier, routedTarget.parent)
1211
1289
  const provisionalExitPaths = reenteredHistoryTarget !== undefined
1212
1290
  ? sortExitPaths(
1213
1291
  machine,
1214
- Array.from(state.active).filter((path) => isPathInSubtree(path, choiceResolvedTarget.parent))
1292
+ Array.from(state.active).filter((path) => isPathInSubtree(path, routedTarget.parent))
1215
1293
  )
1216
1294
  : getExitPaths(machine, state, provisionalBoundary)
1217
- const stateAtHistoryResolution = provisionalExitPaths.includes(choiceResolvedTarget.parent)
1295
+ const stateAtHistoryResolution = provisionalExitPaths.includes(routedTarget.parent)
1218
1296
  ? captureHistory(machine, state, state, provisionalExitPaths)
1219
1297
  : state
1220
1298
  historyResolution = resolveHistoryTarget(
1221
1299
  machine,
1222
1300
  stateAtHistoryResolution,
1223
- choiceResolvedTarget,
1301
+ routedTarget,
1224
1302
  (selection.context as any).event
1225
1303
  )
1226
1304
  }
1227
1305
  const target: Machine.Snapshot<States> | Machine.Target<States, Machine.StateIdentifier<States>> | undefined =
1228
1306
  historyResolution === undefined
1229
- ? choiceResolvedTarget as
1307
+ ? routedTarget as
1230
1308
  | Machine.Snapshot<States>
1231
1309
  | Machine.Target<States, Machine.StateIdentifier<States>>
1232
1310
  | undefined
1233
1311
  : historyResolution.target as
1234
1312
  | Machine.Snapshot<States>
1235
1313
  | Machine.Target<States, Machine.StateIdentifier<States>>
1236
- const additionalHistoryActions: Array<RuntimeCommand> = []
1237
- const additionalHistoryRaisedEvents: Array<unknown> = []
1238
- const additionalHistoryEmittedEvents: Array<unknown> = []
1239
- const additionalHistoryChoiceTransitions: Array<ResolvedChoiceTransition> = []
1314
+ const additionalTargetActions: Array<RuntimeCommand> = []
1315
+ const additionalTargetRaisedEvents: Array<unknown> = []
1316
+ const additionalTargetEmittedEvents: Array<unknown> = []
1317
+ const additionalTargetChoiceTransitions: Array<ResolvedChoiceTransition> = []
1240
1318
  const additionalChoiceTargets: Array<
1241
1319
  Machine.Snapshot<States> | Machine.Target<States, Machine.StateIdentifier<States>>
1242
1320
  > = []
1243
1321
  for (const additionalTarget of choiceResolution?.additionalTargets ?? []) {
1322
+ if (isInitialTarget(additionalTarget)) {
1323
+ const resolved = resolveInitialTarget(
1324
+ machine,
1325
+ state,
1326
+ additionalTarget,
1327
+ (selection.context as any).event
1328
+ )
1329
+ additionalChoiceTargets.push(resolved.target as any)
1330
+ additionalTargetActions.push(...resolved.commands)
1331
+ additionalTargetRaisedEvents.push(...resolved.raisedEvents)
1332
+ additionalTargetEmittedEvents.push(...resolved.emittedEvents)
1333
+ additionalTargetChoiceTransitions.push(...resolved.transitions)
1334
+ continue
1335
+ }
1244
1336
  if (!isHistoryTarget(additionalTarget)) {
1245
1337
  additionalChoiceTargets.push(additionalTarget as any)
1246
1338
  continue
@@ -1252,10 +1344,10 @@ const collectEvaluatedTransition = <
1252
1344
  (selection.context as any).event
1253
1345
  )
1254
1346
  additionalChoiceTargets.push(resolved.target as any)
1255
- additionalHistoryActions.push(...resolved.commands)
1256
- additionalHistoryRaisedEvents.push(...resolved.raisedEvents)
1257
- additionalHistoryEmittedEvents.push(...resolved.emittedEvents)
1258
- additionalHistoryChoiceTransitions.push(...resolved.transitions)
1347
+ additionalTargetActions.push(...resolved.commands)
1348
+ additionalTargetRaisedEvents.push(...resolved.raisedEvents)
1349
+ additionalTargetEmittedEvents.push(...resolved.emittedEvents)
1350
+ additionalTargetChoiceTransitions.push(...resolved.transitions)
1259
1351
  }
1260
1352
  const targetPath = target === undefined
1261
1353
  ? undefined
@@ -1282,28 +1374,32 @@ const collectEvaluatedTransition = <
1282
1374
  commands: [
1283
1375
  ...transitionResult.commands,
1284
1376
  ...(choiceResolution?.commands ?? []),
1377
+ ...(initialResolution?.commands ?? []),
1285
1378
  ...(historyResolution?.commands ?? []),
1286
- ...additionalHistoryActions
1379
+ ...additionalTargetActions
1287
1380
  ],
1288
1381
  raisedEvents: [
1289
1382
  ...transitionResult.raisedEvents,
1290
1383
  ...(choiceResolution?.raisedEvents ?? []),
1384
+ ...(initialResolution?.raisedEvents ?? []),
1291
1385
  ...(historyResolution?.raisedEvents ?? []),
1292
- ...additionalHistoryRaisedEvents
1386
+ ...additionalTargetRaisedEvents
1293
1387
  ],
1294
1388
  emittedEvents: [
1295
1389
  ...transitionResult.emittedEvents,
1296
1390
  ...(choiceResolution?.emittedEvents ?? []),
1391
+ ...(initialResolution?.emittedEvents ?? []),
1297
1392
  ...(historyResolution?.emittedEvents ?? []),
1298
- ...additionalHistoryEmittedEvents
1393
+ ...additionalTargetEmittedEvents
1299
1394
  ],
1300
1395
  changed,
1301
1396
  exitPaths: [],
1302
1397
  entryPaths: [],
1303
1398
  choiceTransitions: [
1304
1399
  ...(choiceResolution?.transitions ?? []),
1400
+ ...(initialResolution?.transitions ?? []),
1305
1401
  ...(historyResolution?.transitions ?? []),
1306
- ...additionalHistoryChoiceTransitions
1402
+ ...additionalTargetChoiceTransitions
1307
1403
  ]
1308
1404
  } as EvaluatedTransition<States, Event, E, R, Context>
1309
1405
  }
@@ -1323,20 +1419,23 @@ const collectEvaluatedTransition = <
1323
1419
  commands: [
1324
1420
  ...transitionResult.commands,
1325
1421
  ...(choiceResolution?.commands ?? []),
1422
+ ...(initialResolution?.commands ?? []),
1326
1423
  ...(historyResolution?.commands ?? []),
1327
- ...additionalHistoryActions
1424
+ ...additionalTargetActions
1328
1425
  ],
1329
1426
  raisedEvents: [
1330
1427
  ...transitionResult.raisedEvents,
1331
1428
  ...(choiceResolution?.raisedEvents ?? []),
1429
+ ...(initialResolution?.raisedEvents ?? []),
1332
1430
  ...(historyResolution?.raisedEvents ?? []),
1333
- ...additionalHistoryRaisedEvents
1431
+ ...additionalTargetRaisedEvents
1334
1432
  ],
1335
1433
  emittedEvents: [
1336
1434
  ...transitionResult.emittedEvents,
1337
1435
  ...(choiceResolution?.emittedEvents ?? []),
1436
+ ...(initialResolution?.emittedEvents ?? []),
1338
1437
  ...(historyResolution?.emittedEvents ?? []),
1339
- ...additionalHistoryEmittedEvents
1438
+ ...additionalTargetEmittedEvents
1340
1439
  ],
1341
1440
  changed,
1342
1441
  exitPaths: reenteredHistoryTarget !== undefined
@@ -1353,8 +1452,9 @@ const collectEvaluatedTransition = <
1353
1452
  : getEntryPaths(machine, stateAfterTransition, boundary),
1354
1453
  choiceTransitions: [
1355
1454
  ...(choiceResolution?.transitions ?? []),
1455
+ ...(initialResolution?.transitions ?? []),
1356
1456
  ...(historyResolution?.transitions ?? []),
1357
- ...additionalHistoryChoiceTransitions
1457
+ ...additionalTargetChoiceTransitions
1358
1458
  ]
1359
1459
  } as EvaluatedTransition<States, Event, E, R, Context>
1360
1460
  }
@@ -73,8 +73,7 @@ const acknowledgedPlan = (
73
73
  commands: planned.commands,
74
74
  emittedEvents: planned.emittedEvents,
75
75
  microsteps: planned.microsteps.map((microstep) => {
76
- const { transitions: _, ...evidence } = microstep
77
- return { ...evidence, next: snapshot(microstep.next) }
76
+ return { ...microstep, transitions: microstep.transitions ?? [], next: snapshot(microstep.next) }
78
77
  }),
79
78
  done: planned.done,
80
79
  output: planned.output
@@ -433,6 +432,7 @@ const makeProcessLogic: <
433
432
  ) => {
434
433
  try {
435
434
  const planned = compiledInitial(initialArgs, scope)
435
+ scope.inspectInitial(planned.initialEntryPaths)
436
436
  const result = {
437
437
  state: planned.state as Machine.Snapshot<States>,
438
438
  done: planned.done,
@@ -459,8 +459,9 @@ const makeProcessLogic: <
459
459
  ) =>
460
460
  compiledInitial === undefined
461
461
  ? internalRuntime.provideMachineRuntime(
462
- internalPlanner.planInitial(internalPlanner.withActorScope(machine, scope), ...initialArgs).pipe(
462
+ internalPlanner.planInitial(internalPlanner.withMachineReferences(machine, scope), ...initialArgs).pipe(
463
463
  Effect.flatMap((planned) => {
464
+ scope.inspectInitial(planned.initialEntryPaths, planned.microsteps)
464
465
  const commands = planned.commands.length === 0
465
466
  ? undefined
466
467
  : CommandRuntime.runCommands(planned.commands, scope)
@@ -486,6 +487,7 @@ const makeProcessLogic: <
486
487
  )
487
488
  : Effect.try({ try: () => makeCompiledInitial!(scope), catch: (error) => error as any })
488
489
  return ({
490
+ inspection: { kind: "Machine", definition: machine },
489
491
  execution: {
490
492
  _tag: "Compiled",
491
493
  childless: !hasInvokes,
@@ -540,7 +542,7 @@ const makeProcessLogic: <
540
542
  try {
541
543
  planned = internalPlanner.planConfiguration(
542
544
  machine,
543
- Configuration.withActorScope(
545
+ Configuration.withMachineReferences(
544
546
  configuration ?? Configuration.normalizeConfigurationSync(machine, current),
545
547
  context
546
548
  ),
@@ -651,7 +653,7 @@ const makeProcessLogic: <
651
653
  try {
652
654
  planned = internalPlanner.planConfiguration(
653
655
  machine,
654
- Configuration.withActorScope(
656
+ Configuration.withMachineReferences(
655
657
  configuration ?? Configuration.normalizeConfigurationSync(machine, current),
656
658
  context
657
659
  ),