@@ -70,7 +70,8 @@ the deferred constructors preserve that identity after decoding.
7070- Return snapshots or typed target-builder results from transitions. Do not
7171 return raw decoded state values.
7272- Transition and lifecycle callbacks are synchronous. Put asynchronous work in
73- an invoked Effect, actor, or child machine and map its result to an event.
73+ an invoked Effect, logic process, or child machine and handle its lifecycle
74+ with ` onDone ` , ` onFailure ` , and ` onSnapshot ` .
7475- Put data on the narrowest state where it is valid. Put data shared by sibling
7576 phases on their compound parent.
7677- Declare finality only in the state definition. Do not put ` type: "final" ` in
@@ -80,12 +81,12 @@ the deferred constructors preserve that identity after decoding.
8081- ` parents ` keys are full dotted paths.
8182- Invoke lifetimes follow state entry and exit, not the spelling of the target
8283 builder.
83- - Recover expected invoked Effect failures into machine events. Unrecovered
84- child failures terminate the owning machine.
85- - Reuse the exact child descriptor value for ` invokeMachine ` , ` sendTo ` , and
84+ - Handle every typed invoked Effect failure with ` onFailure ` . Defects and
85+ interruption terminate the owning machine.
86+ - Reuse the exact child descriptor value for inline invocation , ` sendTo ` , and
8687 child lookup.
8788- ` events ` is the public input protocol. ` internalEvents ` contains machine-local
88- deliveries such as invoke results and invoked-child emissions. Handlers see
89+ deliveries such as raised events and invoked-child emissions. Handlers see
8990 both; typed public ` send ` and ` Machine.plan ` accept only ` events ` .
9091- Event tags in ` events ` and ` internalEvents ` must be disjoint.
9192- Event tags must also be unique within each protocol list.
@@ -98,13 +99,13 @@ its extra control is required:
9899- Bind a shared Atom runtime once with ` AtomMachine.bind(runtime) ` , then use the
99100 returned ` make ` or ` resume ` . Use ` AtomMachine.make(machine) ` and
100101 ` AtomMachine.resume(machine, snapshot) ` for service-free machines.
101- - Use ` Machine.invokeEffect ` for a typed one-shot Effect and ` Machine. after` for
102- a timer. Use ` Machine.invoke ` with ` Machine.effect ` only for custom child
103- process behavior or snapshot mapping .
102+ - Use one inline ` Machine.invoke ` object: ` effect ` for one-shot work, ` after `
103+ for a timer, ` logic ` for reusable process logic, and ` child ` for a complete
104+ child statechart .
104105- Use ` Machine.child(id, machine) ` for a complete statechart descriptor and
105106 ` Machine.childAddress<Event>(id) ` for a low-level process address. An
106- invocation is addressable only when ` Machine.invoke ` receives that address
107- explicitly.
107+ logic invocation is addressable only when ` Machine.invoke ` receives that
108+ address explicitly.
108109- Use the callback's ` enqueue ` argument for ` raise ` , ` emit ` , ` sendTo ` , and
109110 ` stop ` . These operations record closed actor commands and do not run Effects.
110111
@@ -541,8 +542,8 @@ type AnyHandledEvent = Machine.Machine.Event<typeof definition>
541542
542543` MachineRef .send ` , ` machineAtom .send ` , and ` Machine .plan ` accept decoded public
543544events or constructions returned by ` Machine .events ` . Transition handlers
544- receive only decoded events. Raised events, invoke results, and mapped child
545- events additionally accept constructions from ` Machine .internalEvents ` . The
545+ receive only decoded events. Raised events and child emissions additionally
546+ accept constructions from ` Machine .internalEvents ` . The
546547local planner and runtime intentionally share the complete decoder to support
547548those internal deliveries, so JavaScript or ` any ` can bypass the local public
548549distinction.
@@ -552,45 +553,50 @@ across both configuration lists.
552553
553554## Recoverable state-scoped work
554555
555- Use ` Machine . invokeEffect ` for a one-shot Effect. Its callbacks preserve the
556- typed success and failure channels while mapping both into machine events :
556+ Use an inline ` invoke ` object with an ` effect ` for one-shot work. Lifecycle callbacks
557+ receive the typed Effect channels and can transition directly :
557558
558559` ` ` ts
559- invoke : ({ state }) =>
560- Machine . invokeEffect ({
561- id : " save" ,
562- effect : SaveService . save ( state . draft ),
563- onSuccess : (entry ) => InternalEvents . Saved ({ entry }),
564- onFailure : ( error ) => InternalEvents .SaveFailed ({ message: error .message })
565- })
560+ invoke : {
561+ id : " save " ,
562+ effect : SaveService . save ( draft ) ,
563+ onDone : ({ output, target }) => target . full . Saved ({ entry : output } ),
564+ onFailure : ({ error, target }) =>
565+ target . full .SaveFailed ({ message: error .message })
566+ }
566567` ` `
567568
568569The owning state scopes the child. Owner-driven interruption on state exit is
569- normal cancellation and stale output is ignored. A child Effect that defects
570- or self-interrupts fails the parent. Omit ` onFailure ` only when the Effect error
571- type is ` never ` ; defects and interruption are not mapped.
570+ normal cancellation and stale output is ignored. An Effect that defects or
571+ self-interrupts fails the parent. ` onDone ` is required when the output is not
572+ ` never ` ; ` onFailure ` is required when the typed error is not ` never ` . Handlers
573+ are forbidden when their channel is ` never ` .
574+
575+ The source may also be a function of the owning state's entry context when it
576+ needs ` state ` , ` parent ` , ` parents ` , or the entry ` event ` . Source construction
577+ errors, defects, and interruption are machine failures rather than a second
578+ phase in ` onFailure ` .
572579
573- Successful non-void output is delivered as a parent event. Include every
574- possible mapped result schema in the parent machine's ` internalEvents ` array and
575- add handlers for the relevant tags. Leave defects and interruption fatal;
576- recover only expected typed failures .
580+ ` Machine . invoke ({ ... }) ` is a zero-runtime identity helper for preserving source
581+ channel inference when an invocation is constructed separately. Prefer the
582+ direct object inside a state when a dynamic source needs contextual owner-state
583+ inference .
577584
578- A cancellable timer uses ` Machine . after ` :
585+ A cancellable timer uses the same object :
579586
580587` ` ` ts
581- invoke : Machine .after (" 3 seconds" , InternalEvents .ClearStatus (), {
582- id: " clear-status"
583- })
588+ invoke : {
589+ id: " clear-status" ,
590+ after: " 3 seconds" ,
591+ onDone: ({ target }) => target .full .Clear ()
592+ }
584593` ` `
585594
586- The timer starts on state entry and is interrupted on exit. Supply an explicit
587- id when more than one active timer could deliver the same event tag. Use
588- lower-level ` Machine .invoke ` with ` Machine .effect ` when custom child logic or
589- snapshot mapping is required. In that API, ` id ` is only the invocation's
590- state-local lifecycle key. To communicate with the invocation, create a
591- ` Machine .childAddress <Event >(" worker" )` and pass it as ` address ` ; TypeScript
592- checks the address protocol against the child logic. Lifecycle ids must be
593- unique among simultaneously active invokes owned by the same state.
595+ The timer starts on state entry and is interrupted on exit. Its ` onDone ` is
596+ always required. For reusable process logic, provide ` logic ` , a state-local
597+ lifecycle ` id ` , and a typed ` address ` . TypeScript checks the address protocol
598+ against the logic event protocol. Lifecycle ids and addresses serve different
599+ purposes and must both be explicit.
594600
595601## Invoked child statecharts
596602
@@ -603,11 +609,11 @@ const Editor = Machine.child("editor", EditorMachine)
603609Invoke it from its owning state:
604610
605611``` ts
606- invoke : Machine . invokeMachine ( {
612+ invoke : {
607613 child : Editor ,
608614 input : editorInput ,
609- onDone : ({ output }) => new EditorCompleted ({ output })
610- })
615+ onDone : ({ output , target }) => target . full . EditorDone ({ output })
616+ }
611617```
612618
613619Use ` Editor ` for:
@@ -618,9 +624,9 @@ parentRef.child(Editor)
618624parentAtom .child (Editor )
619625```
620626
621- Child emissions, mapped snapshots, and mapped completion output are delivered as
622- parent events and must be accepted by the parent's ` internalEvents ` list.
623- Invoked child IDs must be unique while simultaneously active.
627+ Child emissions are delivered through the parent's internal protocol.
628+ ` onSnapshot ` , ` onDone ` , and ` onFailure ` are direct parent transitions. Invoked
629+ child IDs must be unique while simultaneously active.
624630
625631Descriptors with the same id and machine identity address the same child, even
626632when independently constructed. The descriptor objects themselves are not
@@ -632,21 +638,18 @@ logic that does not have a complete machine descriptor.
632638### Inspecting state-owned activities
633639
634640Use ` Machine.activityDefinitions(machine) ` to inspect invokes without running
635- them. Static ` Machine.invoke ` , ` Machine.invokeEffect ` , ` Machine.after ` , and
636- ` Machine.invokeMachine ` descriptors expose serializable ownership metadata:
641+ them. Static inline ` Machine.invoke ` definitions expose serializable ownership
642+ metadata:
637643
638644``` ts
639645Machine .activityDefinitions (machine )
640646// [{ source: "Loading", id: "load-timeout", type: "timer",
641- // duration: "10s", event: "LoadTimedOut" }]
647+ // duration: "10s" }]
642648```
643649
644- Effect success/failure mappers are closures and therefore appear as dynamic
645- outcomes. Child machines expose descriptor identity, never their runtime or
646- implementation. A function-valued ` invoke ` factory is represented as a dynamic
647- activity because inspection must not evaluate user code. The existing invoke
648- helpers remain the only execution API; this metadata does not add lifecycle
649- configuration syntax or affect execution.
650+ Child machines expose descriptor identity, never their runtime or
651+ implementation. Function-valued sources and durations are represented as
652+ dynamic because inspection must not evaluate user code.
650653
651654## AtomMachine and React
652655
@@ -755,8 +758,8 @@ Encoding does not preserve:
755758- completion and history records survive but do not retrigger ` onDone ` ;
756759- active-state invokes start once in ordinary ancestor/document order with
757760 ` Machine.InitialEvent ` ;
758- - ` invokeEffect ` restarts, ` invokeMachine ` creates a fresh child from its normal
759- initial state, and ` Machine.after ` restarts its complete duration;
761+ - inline Effects restart, child machines start fresh from their normal initial
762+ state, and timers restart their complete duration;
760763- inactive invokes, spawned children, child snapshots, elapsed timer time, and
761764 prior ` RuntimeSnapshot ` status/errors are not restored;
762765- a final logical snapshot creates an immediately completed ref;
@@ -985,7 +988,7 @@ parents["Route.Ready"]
985988
986989### Child descriptor types are unrelated
987990
988- Use the descriptor exported by the module that configured ` invokeMachine ` .
991+ Use the descriptor exported by the module that configured the child invocation .
989992An independently created descriptor with the same id and machine identity also
990993matches; the same id paired with a different machine remains a distinct child.
991994
@@ -1009,6 +1012,6 @@ The current API does not include:
10091012- declarative first-class guards;
10101013- a complete inspectable graph for arbitrary transition Effects.
10111014
1012- Use ordinary TypeScript conditions for guards and ` Machine.after ` for
1013- state-scoped timers. Do not invent undocumented state-node properties such as
1014- ` guard ` .
1015+ Use ordinary TypeScript conditions for guards and an inline ` Machine.invoke `
1016+ with ` after ` for state-scoped timers. Do not invent undocumented state-node
1017+ properties such as ` guard ` .
0 commit comments