# `SuperPi.Conversation.Machine`
[🔗](https://github.com/oleksandr/super-pi-beam/blob/v0.1.0/lib/super_pi/conversation/machine.ex#L1)

Runtime Conversation Turn Coordinator (`:gen_statem` with `[:handle_event_function, :state_enter]`)
synchronized with durable `Fsmx` tasks (`SuperPi.Durable.TaskEngine`) and the 12-hook
`SuperPi.Extension` pipeline (`REQ-FSM-01`..`REQ-FSM-06`, `09 - Data Flows and Extension Injection Points.md`).

## States
- `:recovering` — Runs `TaskEngine.reconcile_on_open!/1` on startup and transitions to `:idle`.
- `:idle` — Accepts `submit/3` (`:queue`, `:steer`, `:write`) and manual `compact/2`.
- `:preparing_request` — Runs `before_agent_start`, derives context (`Context.derive/1`), runs `before_request` and `before_provider_request`.
- `:streaming_llm` — Streams or invokes the configured `llm_responder` and normalizes events; handles mid-stream `:steer` preemption.
- `:executing_tools` — Runs tool calls one at a time: `before_tool` in the machine, then `wrap_tool` -> `SandboxRunner` -> `after_tool` in a task, so the machine still answers `cancel`, `steer` and `get_state` while a tool runs. Then `after_tools`. A `:steer` lets the running tool finish and skips the rest of the batch.
- `:sleeping_backoff` — Pauses turn execution when provider rate-limits/retries occur (`TaskEngine.sleep_until/3`).
- `:awaiting_children` — A tool result carried the `control` directive `%{"await" => ...}`
  (`delegate_subagent`). The durable task is `waiting` on its child tasks and the machine parks, like
  `:sleeping_backoff`, still answering `cancel`, `get_state` and `compact`. A child that settles wakes
  the task and tells the machine (`{:task_woken, task_id}`, from `TaskEngine`, on any node). A poll
  (`config :super_pi, :await_poll_ms`, default 5 s) covers a lost message. On wake the machine stores
  one user message per child with its summary and goes on at `:preparing_request`. Not a tool result:
  the tool call already has one (the acknowledgement), and a second result for one call id is refused
  by the providers.
- `:compacting` — Runs `before_compact` or default compaction and records `pi.compaction` with `head_entry_id`.
- `:settling_run` — Runs `after_run` verification gate; either loops back to `:preparing_request` (`{:continue, prompt}`) or completes the durable `pi.generation` task and returns to `:idle`.

# `cancel`

Cancels the running turn: stops the LLM request or the running tool (with its OS processes),
records a "cancelled" result for every tool call without a result, marks the durable task
`cancelled`, replies `{:error, :cancelled}` to the waiting submit caller and returns to `:idle`.

The subtree goes with it: the task's live children (subagents, also while the turn is parked in
`:awaiting_children`) are aborted bottom-up by `TaskEngine.cancel_task/2`, which calls
`abort_task!/1` on each, and the machines of those children are cancelled.

# `child_spec`

# `compact`

Runs manual compaction. During a turn the request waits until the conversation is idle, so a
compaction never lands between a tool call and its result. `opts[:timeout]` (default 30 s)
bounds the wait. Returns `{:ok, :noop}`, `{:ok, :cancelled}` or `{:ok, result}`.

# `get_state`

Returns the current `{:state, data}` snapshot of the `:gen_statem`.

# `resume_pending`

Tells the machine that a pending `pi.generation` task was stored for it (a scheduled run, see
`SuperPi.Schedule`). An idle machine starts the task at once. A busy one starts it when its
turn ends. A machine that is still recovering finds the task itself.

# `safe_submit`

`submit/3` for entry points (gateway, RPC): a machine that exits or a call that times out is
`{:error, reason}`, not an exit of the caller.

# `set_extensions`

Updates the active extension pipeline for the conversation machine.

# `start_link`

# `submit`

Submits user input with mode `:queue` (default), `:steer` (preempts active tool batch/stream), or `:write` (passive append).

# `via_tuple`

---

*Consult [api-reference.md](api-reference.md) for complete listing*
