@typeonce/effect-machine 0.19.1 → 0.21.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 (54) hide show
  1. package/README.md +90 -14
  2. package/dist/Machine.d.ts +155 -18
  3. package/dist/Machine.d.ts.map +1 -1
  4. package/dist/Machine.js +15 -3
  5. package/dist/Machine.js.map +1 -1
  6. package/dist/internal/machine/atom.d.ts.map +1 -1
  7. package/dist/internal/machine/atom.js +18 -4
  8. package/dist/internal/machine/atom.js.map +1 -1
  9. package/dist/internal/machine/executionPlan.d.ts.map +1 -1
  10. package/dist/internal/machine/executionPlan.js +33 -3
  11. package/dist/internal/machine/executionPlan.js.map +1 -1
  12. package/dist/internal/machine/invocation.d.ts.map +1 -1
  13. package/dist/internal/machine/invocation.js +7 -0
  14. package/dist/internal/machine/invocation.js.map +1 -1
  15. package/dist/internal/machine/machine.d.ts +1 -0
  16. package/dist/internal/machine/machine.d.ts.map +1 -1
  17. package/dist/internal/machine/machine.js +49 -13
  18. package/dist/internal/machine/machine.js.map +1 -1
  19. package/dist/internal/machine/planner.d.ts +11 -2
  20. package/dist/internal/machine/planner.d.ts.map +1 -1
  21. package/dist/internal/machine/planner.js +49 -9
  22. package/dist/internal/machine/planner.js.map +1 -1
  23. package/dist/internal/machine/runtime.d.ts +4 -3
  24. package/dist/internal/machine/runtime.d.ts.map +1 -1
  25. package/dist/internal/machine/runtime.js +12 -1
  26. package/dist/internal/machine/runtime.js.map +1 -1
  27. package/dist/internal/machine/topology.d.ts +9 -1
  28. package/dist/internal/machine/topology.d.ts.map +1 -1
  29. package/dist/internal/machine/topology.js +7 -0
  30. package/dist/internal/machine/topology.js.map +1 -1
  31. package/dist/internal/testing/machine/verification.d.ts.map +1 -1
  32. package/dist/internal/testing/machine/verification.js +15 -3
  33. package/dist/internal/testing/machine/verification.js.map +1 -1
  34. package/dist/testing/MachineTest.d.ts +2 -0
  35. package/dist/testing/MachineTest.d.ts.map +1 -1
  36. package/dist/testing/MachineTest.js.map +1 -1
  37. package/dist/unstable/reactivity/AtomMachine.d.ts +10 -8
  38. package/dist/unstable/reactivity/AtomMachine.d.ts.map +1 -1
  39. package/dist/unstable/reactivity/AtomMachine.js +2 -2
  40. package/dist/unstable/reactivity/AtomMachine.js.map +1 -1
  41. package/docs/agent-guide.md +48 -0
  42. package/docs/effect-atom-react.md +28 -0
  43. package/package.json +1 -1
  44. package/src/Machine.ts +371 -45
  45. package/src/internal/machine/atom.ts +26 -18
  46. package/src/internal/machine/executionPlan.ts +37 -3
  47. package/src/internal/machine/invocation.ts +13 -1
  48. package/src/internal/machine/machine.ts +75 -15
  49. package/src/internal/machine/planner.ts +64 -11
  50. package/src/internal/machine/runtime.ts +48 -19
  51. package/src/internal/machine/topology.ts +18 -1
  52. package/src/internal/testing/machine/verification.ts +16 -3
  53. package/src/testing/MachineTest.ts +2 -0
  54. package/src/unstable/reactivity/AtomMachine.ts +10 -8
package/README.md CHANGED
@@ -420,6 +420,47 @@ choice destinations remain calls such as `to.full.Running()`. Runtime named
420
420
  branch builders remain callable, including `select.unchanged()`, because their
421
421
  result carries the selected branch evidence.
422
422
 
423
+ ### Update an active scope value
424
+
425
+ Use `to.local.update(...)` to replace the value owned by the nearest active
426
+ compound scope without rebuilding its active child. Use
427
+ `to.branch.<path>.update(...)` for a valued compound or parallel ancestor of the
428
+ handler source:
429
+
430
+ ```ts
431
+ Increment: ;
432
+ ;((to) =>
433
+ to.branch.root.session.update(({ ancestors, target }) => target.from({ count: ancestors["root.session"].count + 1 })))
434
+ ```
435
+
436
+ The update keeps the exact active descendants, their values, history records,
437
+ completion outputs, and unrelated parallel regions. It runs no exit or entry
438
+ actions and does not restart state-owned work. Eventless stabilization still
439
+ runs, so an `always` transition can react to the new value.
440
+
441
+ `update` is callable when used directly and is also a static selection for a
442
+ named branch:
443
+
444
+ ```ts
445
+ to.branches({
446
+ changed: { target: to.local.update },
447
+ unchanged: { target: to.none }
448
+ }).resolve(({ select, event }) =>
449
+ event.changed
450
+ ? select.changed.from({ count: event.count })
451
+ : select.unchanged()
452
+ )
453
+ ```
454
+
455
+ The resolver must return `target(value)` or `target.from(input)`. It may return
456
+ `decline()` only with `{ declinable: true }`. Pass `{ reenter: true }` on event
457
+ or invocation transitions when the handler source should exit and enter again.
458
+ Reentry applies to that source, not to the ancestor whose value changed.
459
+
460
+ The selector omits `update` for schema-less scopes, atomic and final states,
461
+ inactive branches, parallel sibling regions, and choice resolvers. Updating a
462
+ parallel sibling requires an event handled by that region.
463
+
423
464
  Use `declinable: true` when a resolver may decide that its transition is not
424
465
  enabled. Only that resolver receives `decline()`, and its return type expands to
425
466
  accept the opaque declined result:
@@ -582,6 +623,46 @@ entered. Use an Effect containing `Effect.sleep(...)` for generic work, while
582
623
  `from.timer(...)` keeps timer intent explicit and makes static durations visible
583
624
  through activity inspection.
584
625
 
626
+ ### Spawn dynamic child machines
627
+
628
+ Use `from.child(...)` when a state owns a fixed child lifecycle. Use the
629
+ `children` context inside an invoked Effect when the machine process owns an
630
+ open set of children that must survive state changes:
631
+
632
+ ```ts
633
+ const Plant = Machine.childFamily(plantMachine)
634
+
635
+ const central = Machine.make({
636
+ events: Machine.events(ResourcesOffered, PlantBroken)
637
+ // ...
638
+ }).handle({
639
+ Commissioning: {
640
+ invoke: (from) =>
641
+ from.effect("commission-wave", ({ children, state }) =>
642
+ Effect.forEach(
643
+ state.plants,
644
+ (input) => children.spawn(Plant(input.id), { input }),
645
+ { discard: true }
646
+ ))
647
+ .onDone((to) => to.full.Operating())
648
+ .onFailure((to) => to.full.CommissioningFailed())
649
+ }
650
+ })
651
+ ```
652
+
653
+ `children.spawn` completes after initialization. The new child remains owned
654
+ by the machine process after the commissioning Effect completes or its state
655
+ exits. `children.sendTo` and `children.stop` address one active child from an
656
+ Effect; transition resolvers use `enqueue.sendTo` and `enqueue.stop` with the
657
+ same descriptor. Duplicate active ids fail with `ChildAlreadyExistsError` and
658
+ do not replace the existing child. Earlier successful spawns remain active if
659
+ a later spawn in the same wave fails.
660
+
661
+ The child machine's declared `Machine.parent(...)` events must be accepted by
662
+ the owner. This is checked at each spawn call even though ids and cardinality
663
+ remain dynamic. `scope.spawn(child, { input })` provides the same descriptor
664
+ form for lower-level process logic, where the process event protocol is known.
665
+
585
666
  ## Reactivity
586
667
 
587
668
  `AtomMachine` runs one lazy machine instance per `AtomRegistry`:
@@ -603,6 +684,15 @@ The bridge exposes `ref`, `snapshot`, `state`, fail-aware `result`, writable
603
684
  equality-aware derivations. React applications using `@effect/atom-react` need
604
685
  a `RegistryProvider`.
605
686
 
687
+ Descriptors reconstructed from a `Machine.childFamily` resolve the same child
688
+ bridge by machine identity and id:
689
+
690
+ ```ts
691
+ const Plant = Machine.childFamily(plantMachine)
692
+ const plantAtom = centralAtom.child(Plant(selectedPlantId))
693
+ const brokenAtom = AtomMachine.matchesChild(plantAtom, "Broken")
694
+ ```
695
+
606
696
  Emissions stay streams rather than becoming retained atom state:
607
697
 
608
698
  ```ts
@@ -679,20 +769,6 @@ import { MachineTest } from "@typeonce/effect-machine/testing"
679
769
 
680
770
  Each ESM entrypoint is independent and tree-shakeable.
681
771
 
682
- ## Examples
683
-
684
- Every package directly under [`examples/`](./examples) has its own lockfile and
685
- `check` script.
686
-
687
- | Example | What it demonstrates |
688
- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
689
- | [Playground](./examples/playground) | Five focused React examples: atomic turnstile commands, state-scoped traffic-light timers, hierarchical microwave safety, a resource-owned media player, and a worker-hosted machine synchronized across tabs |
690
- | [Pokémon](./examples/pokemon) | Compound workflow states, invoked child machines, typed emissions, Atom reactivity, and a live Effect service |
691
- | [Platformer](./examples/platformer) | Nested parallel statecharts, typed deep history, raised events, state-scoped timers, deterministic model tests, and a playable SVG adapter |
692
-
693
- The playground is the shortest path from one concept to working code. The
694
- standalone examples show larger composition and ownership boundaries.
695
-
696
772
  ## Reference and development
697
773
 
698
774
  - [API reference](https://effect-machine.typeonce.dev)
package/dist/Machine.d.ts CHANGED
@@ -1258,7 +1258,8 @@ export declare namespace Logic {
1258
1258
  * @category models
1259
1259
  * @since 0.4.0
1260
1260
  */
1261
- interface Spawn {
1261
+ interface Spawn<OwnerEvent = unknown> {
1262
+ <const Child extends ChildMachine.Any>(child: Child & ChildMachine.Executable<Child> & ChildMachine.ParentCompatibility<Child, OwnerEvent>, ...options: ChildMachine.SpawnArgs<Child>): Effect.Effect<ChildMachine.Ref<Child>, ChildAlreadyExistsError | ChildMachine.StartError<Child>, ChildMachine.StartRequirements<Child>>;
1262
1263
  <ChildState, ChildEvent, ChildError, ChildRequirements, ChildOutput, ChildInitialError = never>(logic: Logic<ChildState, ChildEvent, ChildError, ChildRequirements, ChildOutput, ChildInitialError>): Effect.Effect<MachineRef<ChildState, ChildEvent, ChildError, ChildOutput>, ChildInitialError, Exclude<ChildRequirements, Scope.Scope>>;
1263
1264
  <ChildState, ChildEvent, ChildError, ChildRequirements, ChildOutput, Options extends SpawnOptions, ChildInitialError = never>(logic: Logic<ChildState, ChildEvent, ChildError, ChildRequirements, ChildOutput, ChildInitialError>, options: Options & ChildAddress.OptionsCompatibility<Options, ChildEvent>): Effect.Effect<MachineRef<ChildState, ChildEvent, ChildError, ChildOutput>, SpawnIdError<Options> | ChildInitialError, Exclude<ChildRequirements, Scope.Scope>>;
1264
1265
  }
@@ -1274,7 +1275,7 @@ export declare namespace Logic {
1274
1275
  /** Address of the owning process, when one exists. */
1275
1276
  readonly parent: Address<unknown> | undefined;
1276
1277
  /** Starts a child process owned by this scope. */
1277
- readonly spawn: Spawn;
1278
+ readonly spawn: Spawn<Event>;
1278
1279
  /** Sends an event to a machine target or typed parent-local child address. */
1279
1280
  readonly sendTo: {
1280
1281
  <TargetEvent>(target: MachineTarget<TargetEvent>, event: TargetEvent): Effect.Effect<void, StoppedError>;
@@ -1302,6 +1303,7 @@ export declare namespace Logic {
1302
1303
  }
1303
1304
  declare const ChildAddressTypeId = "~effect/Machine/ChildAddress";
1304
1305
  declare const ChildAddressCompatibilityErrorTypeId = "~effect/Machine/ChildAddressCompatibilityError";
1306
+ declare const ChildParentCompatibilityErrorTypeId = "~effect/Machine/ChildParentCompatibilityError";
1305
1307
  declare const ChildMachineTypeId = "~effect/Machine/ChildMachine";
1306
1308
  type InvokeLifecycleId = string & {
1307
1309
  readonly [ChildAddressTypeId]?: never;
@@ -1342,6 +1344,68 @@ export declare namespace ChildMachine {
1342
1344
  * @since 0.4.0
1343
1345
  */
1344
1346
  type Any = ChildMachine<string, Machine.Any>;
1347
+ /**
1348
+ * Bound constructor for an open family of child descriptors that share one
1349
+ * machine definition.
1350
+ *
1351
+ * @category models
1352
+ * @since 0.20.0
1353
+ */
1354
+ interface Family<M extends Machine.Any> {
1355
+ <const Id extends string>(id: Id): ChildMachine<Id, M>;
1356
+ }
1357
+ /**
1358
+ * Ensures a child machine's declared owner protocol is accepted by the
1359
+ * process that will own it.
1360
+ *
1361
+ * @category utility types
1362
+ * @since 0.20.0
1363
+ */
1364
+ type ParentCompatibility<Child extends Any, OwnerEvent> = Child extends ChildMachine<string, infer M> ? Machine.Any extends M ? {
1365
+ readonly [ChildParentCompatibilityErrorTypeId]: {
1366
+ readonly child: unknown;
1367
+ readonly owner: OwnerEvent;
1368
+ };
1369
+ } : [Machine.EventOf<Machine.ParentEvents<M>>] extends [OwnerEvent] ? unknown : {
1370
+ readonly [ChildParentCompatibilityErrorTypeId]: {
1371
+ readonly child: Machine.EventOf<Machine.ParentEvents<M>>;
1372
+ readonly owner: OwnerEvent;
1373
+ };
1374
+ } : never;
1375
+ /**
1376
+ * Ensures the selected child machine has complete handlers and outputs.
1377
+ *
1378
+ * @category utility types
1379
+ * @since 0.20.0
1380
+ */
1381
+ type Executable<Child extends Any> = Child["machine"] extends EnsureExecutable<Machine.States<Child["machine"]>, Machine.UnhandledStates<Child["machine"]>, Machine.OutputStates<Child["machine"]>> ? unknown : never;
1382
+ /**
1383
+ * Startup arguments accepted while spawning a child machine.
1384
+ *
1385
+ * @category utility types
1386
+ * @since 0.20.0
1387
+ */
1388
+ type SpawnArgs<Child extends Any> = Machine.InputSchema<Child["machine"]> extends typeof Schema.Void ? [
1389
+ options?: {
1390
+ readonly input?: never;
1391
+ }
1392
+ ] : [options: {
1393
+ readonly input: Machine.Input<Child["machine"]>;
1394
+ }];
1395
+ /**
1396
+ * Typed failures that may occur before a spawned child becomes active.
1397
+ *
1398
+ * @category utility types
1399
+ * @since 0.20.0
1400
+ */
1401
+ type StartError<Child extends Any> = Child extends ChildMachine<string, infer M> ? Machine.InitialError<M> | Machine.Error<M> | ActionError<Machine.InitialServices<M> | Machine.Services<M>> | InfiniteTransitionError | MachineSchemaDecodeError | StartupError | StoppedError : never;
1402
+ /**
1403
+ * Services needed to initialize a spawned child machine.
1404
+ *
1405
+ * @category utility types
1406
+ * @since 0.20.0
1407
+ */
1408
+ type StartRequirements<Child extends Any> = Child extends ChildMachine<string, infer M> ? Exclude<ExcludeCompatibleRuntime<Exclude<ExecutionServices<Machine.InitialServices<M> | Machine.Services<M>>, MachineRuntimeRequirement>, Machine.Event<M>, Machine.Emit<M>>, Scope.Scope> : never;
1345
1409
  /**
1346
1410
  * Running machine reference selected by a child descriptor.
1347
1411
  *
@@ -1357,6 +1421,21 @@ export declare namespace ChildMachine {
1357
1421
  */
1358
1422
  type Event<Child> = Child extends ChildMachine<string, infer M> ? Machine.EventInput<Machine.InputEvent<M>> : never;
1359
1423
  }
1424
+ /**
1425
+ * Effectful operations for child machines owned directly by the current
1426
+ * machine process.
1427
+ *
1428
+ * @category models
1429
+ * @since 0.20.0
1430
+ */
1431
+ export interface ChildOwner<OwnerEvent> {
1432
+ /** Starts a process-owned child and returns once initialization succeeds. */
1433
+ readonly spawn: <const Child extends ChildMachine.Any>(child: Child & ChildMachine.Executable<Child> & ChildMachine.ParentCompatibility<Child, OwnerEvent>, ...options: ChildMachine.SpawnArgs<Child>) => Effect.Effect<ChildMachine.Ref<Child>, ChildAlreadyExistsError | ChildMachine.StartError<Child>, ChildMachine.StartRequirements<Child>>;
1434
+ /** Sends an event to one active child. Missing children are ignored. */
1435
+ readonly sendTo: <Child extends ChildMachine.Any>(child: Child, event: ChildMachine.Event<Child>) => Effect.Effect<void, StoppedError>;
1436
+ /** Stops one active child. Missing children are ignored. */
1437
+ readonly stop: <Child extends ChildMachine.Any>(child: Child) => Effect.Effect<void>;
1438
+ }
1360
1439
  /**
1361
1440
  * Parent-local address for a child process that can receive events.
1362
1441
  *
@@ -2155,9 +2234,10 @@ export declare namespace Machine {
2155
2234
  *
2156
2235
  * **Details**
2157
2236
  *
2158
- * Every branch exposes its selected target without executing its resolver.
2159
- * A compound local or branch target covers its descendants;
2160
- * `undefined` identifies an explicitly targetless branch.
2237
+ * Every branch exposes its static selection without executing its resolver.
2238
+ * A compound local or branch target covers its descendants. An `update`
2239
+ * selection keeps `target` undefined and records its value owner in
2240
+ * `selection.path`; `none` identifies an explicitly targetless branch.
2161
2241
  *
2162
2242
  * @category models
2163
2243
  * @since 0.4.0
@@ -2762,6 +2842,20 @@ export declare namespace Machine {
2762
2842
  readonly [AncestorStateId in ValuedStateIdentifier<States>]: StateByIdentifier<States, AncestorStateId>;
2763
2843
  }>;
2764
2844
  }
2845
+ /**
2846
+ * Opaque instruction that replaces one active compound or parallel state's
2847
+ * value without changing its active descendants.
2848
+ *
2849
+ * @category models
2850
+ * @since 0.21.0
2851
+ */
2852
+ interface StateUpdate<States extends StateSchemas, StateId extends ValuedStateIdentifier<States>> {
2853
+ readonly [Topology.StateUpdateTypeId]: typeof Topology.StateUpdateTypeId;
2854
+ readonly path: StateId;
2855
+ readonly value: StateByIdentifier<States, StateId>;
2856
+ }
2857
+ /** @internal */
2858
+ type StateUpdateBuilder<States extends StateSchemas, StateId extends ValuedStateIdentifier<States>> = ((value: StateByIdentifier<States, StateId>) => StateUpdate<States, StateId>) & FromMethod<readonly [input: SchemaByIdentifier<States, StateId>["~type.make.in"]], StateUpdate<States, StateId>>;
2765
2859
  /**
2766
2860
  * Opaque result returned by an explicitly targetless transition.
2767
2861
  *
@@ -2966,6 +3060,20 @@ export declare namespace Machine {
2966
3060
  type SelectionNode<AllStates extends StateSchemas, Node, Path extends string, Scope extends "local" | "branch", Builder> = Node extends ChoiceStateNodeConfig ? SelectionMethod<Builder, Path, "choice"> : Node extends {
2967
3061
  readonly states: infer Children extends StateSchemas;
2968
3062
  } ? SelectionMethod<Builder, Path> & InitialSelectionMethod<Builder, Path> & SelectionTreeWithPrefix<AllStates, Children, Path, Scope, Builder> : SelectionMethod<Builder, Path>;
3063
+ /** @internal */
3064
+ type StateUpdateSelectionForNode<AllStates extends StateSchemas, Node, Path extends string> = Node extends {
3065
+ readonly states: StateSchemas;
3066
+ } ? NodeSchema<Node> extends never ? {} : {
3067
+ readonly update: SelectionValue<StateUpdateBuilder<AllStates, Extract<Path, ValuedStateIdentifier<AllStates>>>, Path, "update">;
3068
+ } : {};
3069
+ /** @internal */
3070
+ type BranchUpdateSelectionPath<AllStates extends StateSchemas, Node, Path extends string, Rest extends string> = StateUpdateSelectionForNode<AllStates, Node, Path> & (Node extends {
3071
+ readonly states: infer Children extends StateSchemas;
3072
+ } ? Rest extends `${infer Head}.${infer Tail}` ? Head extends keyof Children ? {
3073
+ readonly [Key in Head]: BranchUpdateSelectionPath<AllStates, Children[Head], JoinPath<Path, Head>, Tail>;
3074
+ } : {} : Rest extends keyof Children ? {
3075
+ readonly [Key in Rest]: StateUpdateSelectionForNode<AllStates, Children[Rest], JoinPath<Path, Rest>>;
3076
+ } : {} : {});
2969
3077
  type FullSelectionNode<AllStates extends StateSchemas, Node, Path extends StateIdentifier<AllStates>, Builder> = Node extends {
2970
3078
  readonly states: StateSchemas;
2971
3079
  } ? SelectionMethod<Builder, Path> & InitialSelectionMethod<Builder, Path> : SelectionMethod<Builder, Path>;
@@ -2973,11 +3081,13 @@ export declare namespace Machine {
2973
3081
  readonly [Key in Extract<ActiveStateKey<States>, keyof FullTargetBuilder<States>>]: FullSelectionNode<States, States[Key], Extract<Key, StateIdentifier<States>>, FullTargetBuilder<States>[Key]>;
2974
3082
  };
2975
3083
  type BranchTargetSelector<States extends StateSchemas, Source extends StateNodeIdentifier<States>, Root extends string = Source extends `${infer Head}.${string}` ? Head : Source> = Root extends ActiveStateKey<States> ? Root extends keyof BranchTargetBuilder<States, Source> ? {
2976
- readonly [Key in Root]: SelectionNode<States, States[Key], Key, "branch", BranchTargetBuilder<States, Source>[Key]>;
3084
+ readonly [Key in Root]: SelectionNode<States, States[Key], Key, "branch", BranchTargetBuilder<States, Source>[Key]> & (Source extends ChoiceIdentifier<States> ? {} : Source extends `${Key}.${infer Rest}` ? BranchUpdateSelectionPath<States, States[Key], Key, Rest> : StateUpdateSelectionForNode<States, States[Key], Key>);
2977
3085
  } : {} : {};
2978
- type LocalTargetSelector<States extends StateSchemas, Source extends StateNodeIdentifier<States>> = NearestCompoundScope<States, Source> extends infer Scope extends StateIdentifier<States> ? ChildrenOf<States, Scope> extends infer Children extends StateSchemas ? LocalTargetBuilder<States, Source> extends infer Builder ? SelectionTreeWithPrefix<States, Children, Scope, "local", Builder> & ("with" extends keyof Builder ? {
3086
+ type LocalTargetSelector<States extends StateSchemas, Source extends StateNodeIdentifier<States>> = NearestCompoundScope<States, Source> extends infer Scope ? [Scope] extends [never] ? {} : Scope extends StateIdentifier<States> ? ChildrenOf<States, Scope> extends infer Children extends StateSchemas ? LocalTargetBuilder<States, Source> extends infer Builder ? SelectionTreeWithPrefix<States, Children, Scope, "local", Builder> & ("with" extends keyof Builder ? {
2979
3087
  readonly with: SelectionValue<Builder["with"], Scope>;
2980
- } : {}) : {} : {} : {};
3088
+ } : {}) & (Source extends ChoiceIdentifier<States> ? {} : Scope extends ValuedStateIdentifier<States> ? {
3089
+ readonly update: SelectionValue<StateUpdateBuilder<States, Scope>, Scope, "update">;
3090
+ } : {}) : {} : {} : {} : {};
2981
3091
  type HistorySelectionTree<AllStates extends StateSchemas, States extends StateSchemas, Prefix extends string, Builder> = {
2982
3092
  readonly [Key in Extract<HistoryContainingKey<States>, keyof Builder>]: States[Key] extends HistoryStateNodeConfig ? SelectionValue<Builder[Key], JoinPath<Prefix, Key>, "history"> : States[Key] extends {
2983
3093
  readonly states: infer Children extends StateSchemas;
@@ -2995,9 +3105,9 @@ export declare namespace Machine {
2995
3105
  interface TargetSelector<States extends StateSchemas, Source extends StateNodeIdentifier<States>> {
2996
3106
  /** Handles the trigger without selecting a destination. */
2997
3107
  readonly none: SelectionValue<TargetBuilder<States, Source>["none"], never, "none">;
2998
- /** Selects a destination inside the nearest active compound scope. */
3108
+ /** Selects a destination or updates the nearest active compound scope. */
2999
3109
  readonly local: LocalTargetSelector<States, Source>;
3000
- /** Selects a destination elsewhere under the currently active root. */
3110
+ /** Selects a destination or updates a valued active ancestor under the current root. */
3001
3111
  readonly branch: BranchTargetSelector<States, Source>;
3002
3112
  /** Selects a complete destination under any top-level state. */
3003
3113
  readonly full: FullTargetSelector<States>;
@@ -3060,6 +3170,8 @@ export declare namespace Machine {
3060
3170
  * @since 0.4.0
3061
3171
  */
3062
3172
  type InvokeContext<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateIdentifier<States>, InputEvents extends ReadonlyArray<TaggedSchema> = Events, ParentEvents extends ReadonlyArray<TaggedSchema> = readonly []> = MachineReferences<InputEvents, ParentEvents> & {
3173
+ /** Process-owned child operations for dynamic child machine lifecycles. */
3174
+ readonly children: ChildOwner<EventOf<InputEvents>>;
3063
3175
  /** Value owned by the state that owns this invocation. */
3064
3176
  readonly state: StateByIdentifier<States, StateId>;
3065
3177
  /** Value owned by the nearest schema-backed ancestor, when one exists. */
@@ -3284,14 +3396,14 @@ export declare namespace Machine {
3284
3396
  * **Details**
3285
3397
  *
3286
3398
  * Handlers return snapshots for complete state replacement, target builder
3287
- * results for path-safe partial transitions, or `target.none()` for an
3288
- * explicitly targetless transition. Raw decoded state values and `void` are
3289
- * not accepted at transition boundaries.
3399
+ * results for path-safe partial transitions, state-value updates, or
3400
+ * `target.none()` for an explicitly targetless transition. Raw decoded state
3401
+ * values and `void` are not accepted at transition boundaries.
3290
3402
  *
3291
3403
  * @category utility types
3292
3404
  * @since 0.4.0
3293
3405
  */
3294
- type HandlerResult<States extends StateSchemas, E, R> = Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>> | StateConstruction<Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>>> | NoTarget;
3406
+ type HandlerResult<States extends StateSchemas, E, R> = Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>> | StateUpdate<States, ValuedStateIdentifier<States>> | StateConstruction<Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>> | StateUpdate<States, ValuedStateIdentifier<States>>> | NoTarget;
3295
3407
  /** A choice resolver must always select a typed target synchronously. */
3296
3408
  type ChoiceResult<States extends StateSchemas, E, R> = Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>> | StateConstruction<Snapshot<States> | Target<States, StateIdentifier<States>> | HistoryTarget<States, HistoryIdentifier<States>> | ChoiceTarget<States, ChoiceIdentifier<States>>>;
3297
3409
  /**
@@ -3552,6 +3664,10 @@ export declare namespace Machine {
3552
3664
  }
3553
3665
  type TransitionResolver<Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, Context, Selection> = (context: TransitionResolveContext<Context, Selection>, enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>) => SelectionKind<Selection> extends "none" ? undefined : SelectedTargetResult<Selection> | undefined;
3554
3666
  type DeclinableTransitionResolver<Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, Context, Selection> = (context: TransitionResolveContext<Context, Selection> & DeclineCapability, enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>) => (SelectionKind<Selection> extends "none" ? undefined : SelectedTargetResult<Selection> | undefined) | Declined;
3667
+ /** @internal */
3668
+ type StateUpdateResolver<Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, Context, Selection> = (context: TransitionResolveContext<Context, Selection>, enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>) => SelectedTargetResult<Selection>;
3669
+ /** @internal */
3670
+ type DeclinableStateUpdateResolver<Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, Context, Selection> = (context: TransitionResolveContext<Context, Selection> & DeclineCapability, enqueue: Enqueue<EventOf<Events>, EmitOf<Emits>>) => SelectedTargetResult<Selection> | Declined;
3555
3671
  /** One named destination declared by a branching transition. */
3556
3672
  interface TransitionBranchInput<Selection extends TargetSelection<any, any, any> = TargetSelection<any, any, any>> {
3557
3673
  /** Exact topology destination available to the branching resolver. */
@@ -3644,6 +3760,16 @@ export declare namespace Machine {
3644
3760
  /** Reenters the source using the selected target's default construction. */
3645
3761
  readonly reenter: () => BuiltTransition<States, Events, Emits, StateId, Context, Reenter, SelectionKind<Selection> extends "none" ? undefined : SelectedTargetResult<Selection> | undefined, "required">;
3646
3762
  } : {} : {});
3763
+ /** @internal */
3764
+ interface StateUpdateTransitionRequired<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateNodeIdentifier<States>, Context, Reenter extends boolean, Selection extends TargetSelection<any, any, "update">> {
3765
+ (resolve: StateUpdateResolver<Events, Emits, Context, Selection>, options?: TransitionRequiredOptions<Reenter>): BuiltTransition<States, Events, Emits, StateId, Context, Reenter, SelectedTargetResult<Selection>, "required">;
3766
+ }
3767
+ /** @internal */
3768
+ interface StateUpdateTransitionDeclinable<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateNodeIdentifier<States>, Context, Reenter extends boolean, Selection extends TargetSelection<any, any, "update">> {
3769
+ (resolve: DeclinableStateUpdateResolver<Events, Emits, Context, Selection>, options: TransitionDeclinableOptions<Reenter>): BuiltTransition<States, Events, Emits, StateId, Context, Reenter, SelectedTargetResult<Selection> | Declined, "declinable">;
3770
+ }
3771
+ /** @internal */
3772
+ type StateUpdateTransition<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateNodeIdentifier<States>, Context, Reenter extends boolean, Acceptance extends TransitionAcceptance, Selection extends TargetSelection<any, any, "update">> = Selection & StateUpdateTransitionRequired<States, Events, Emits, StateId, Context, Reenter, Selection> & ("declinable" extends Acceptance ? StateUpdateTransitionDeclinable<States, Events, Emits, StateId, Context, Reenter, Selection> : {});
3647
3773
  /** @internal Type evidence retained by a machine initial-entry declaration. */
3648
3774
  interface InitialBuilderEvidence<out Selection> {
3649
3775
  readonly [InitialBuilderTypeId]: Types.Covariant<Selection>;
@@ -3667,7 +3793,7 @@ export declare namespace Machine {
3667
3793
  type InitialSelector<States extends StateSchemas, Input = void> = InitialSelectorNode<Input, InitialTargetSelector<States>>;
3668
3794
  /** Target-first initial-entry declaration accepted by {@link make}. */
3669
3795
  type InitialBuilderInput<States extends StateSchemas, Input> = (to: InitialSelector<States, Input>) => InitialBuilderEvidence<TargetSelection<any, any, any>>;
3670
- type TransitionSelectorNode<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateNodeIdentifier<States>, Context, Reenter extends boolean, Acceptance extends TransitionAcceptance, Node> = Node extends (...args: infer Args) => infer Selection ? Selection extends TargetSelection<any, any, any> ? ((...args: Args) => TransitionTarget<States, Events, Emits, StateId, Context, Reenter, Acceptance, Selection>) & {
3796
+ type TransitionSelectorNode<States extends StateSchemas, Events extends ReadonlyArray<TaggedSchema>, Emits extends ReadonlyArray<TaggedSchema>, StateId extends StateNodeIdentifier<States>, Context, Reenter extends boolean, Acceptance extends TransitionAcceptance, Node> = Node extends TargetSelection<any, any, "update"> ? StateUpdateTransition<States, Events, Emits, StateId, Context, Reenter, Acceptance, Node> : Node extends (...args: infer Args) => infer Selection ? Selection extends TargetSelection<any, any, any> ? ((...args: Args) => TransitionTarget<States, Events, Emits, StateId, Context, Reenter, Acceptance, Selection>) & {
3671
3797
  readonly [Key in keyof Node]: TransitionSelectorNode<States, Events, Emits, StateId, Context, Reenter, Acceptance, Node[Key]>;
3672
3798
  } : never : Node extends TargetSelection<any, any, any> ? TransitionTarget<States, Events, Emits, StateId, Context, Reenter, Acceptance, Node> : {
3673
3799
  readonly [Key in keyof Node]: TransitionSelectorNode<States, Events, Emits, StateId, Context, Reenter, Acceptance, Node[Key]>;
@@ -4827,9 +4953,10 @@ export declare const initialDefinition: <M extends Machine.Any>(machine: M) => M
4827
4953
  *
4828
4954
  * Event handlers retain their handler-key order within each source state and
4829
4955
  * are followed by eventless and completion handlers. This function does not
4830
- * execute resolvers. Every direct, named, and targetless branch exposes the
4831
- * destination selected by its required static `target` declaration, while
4832
- * `acceptance` reports whether the resolver may decline the transition.
4956
+ * execute resolvers. Every branch exposes its static selection. State updates
4957
+ * retain the updated owner in `selection.path` while leaving `target`
4958
+ * undefined because they do not change topology. `acceptance` reports whether
4959
+ * the resolver may decline the transition.
4833
4960
  *
4834
4961
  * @category getters
4835
4962
  * @since 0.4.0
@@ -4989,6 +5116,16 @@ export declare const logic: <State, Event = never, Output = void, Error = never,
4989
5116
  * @since 0.4.0
4990
5117
  */
4991
5118
  export declare const child: <const Id extends string, M extends Machine.Any>(id: Id, machine: M) => ChildMachine<Id, M>;
5119
+ /**
5120
+ * Binds one machine definition to an open family of runtime child ids.
5121
+ *
5122
+ * Descriptors created by the returned function are interchangeable with
5123
+ * {@link child} descriptors for the same id and machine definition.
5124
+ *
5125
+ * @category constructors
5126
+ * @since 0.20.0
5127
+ */
5128
+ export declare const childFamily: <M extends Machine.Any>(machine: M) => ChildMachine.Family<M>;
4992
5129
  /**
4993
5130
  * Creates a typed parent-local address for lower-level child process logic.
4994
5131
  *