GenServer that executes a flow step tree one step at a time.
The runner holds a stack of pending steps plus the current flow
state. On each :advance message it pops the top step, reduces it,
and either pushes continuation steps, schedules a timed wake-up, or
blocks waiting for an external signal/2.
Notifications ({:flow_state, state}, {:flow_done, state},
{:flow_error, reason}) go to the :notify pid supplied at start
time. Listeners typically use handle_info/2 in a LiveView to
re-assign socket state — LiveSvelte pushes the resulting prop diff
to the Svelte component.
When :tag is supplied at start time, every notification is wrapped
as {:caravela_flow, tag, original_msg} so a single listener driving
multiple flows can demultiplex by tag without spawning forwarder
processes.
Summary
Functions
Synchronously read the flow's current state.
Apply a state-mutating function to the running flow.
Start a runner under the caller's supervision tree. args is a map
containing at minimum :step_tree. Optional keys: :state,
:notify.
Functions
Synchronously read the flow's current state.
Apply a state-mutating function to the running flow.
Unblocks WaitUntil, resets Debounce, and broadcasts a
{:flow_state, new_state} notification.
Start a runner under the caller's supervision tree. args is a map
containing at minimum :step_tree. Optional keys: :state,
:notify.