# `Squidie`
[🔗](https://github.com/dark-trench/squidie/blob/main/lib/squidie.ex#L2)

Public entrypoint for the Squidie runtime.

The API exposed here stays focused on declarative workflow operations. Host
applications start, inspect, and later control runs through this surface
without needing to work directly with persistence internals.

# `read_option_error`

```elixir
@type read_option_error() ::
  {:invalid_option,
   {:opts, term()}
   | {:option, term()}
   | {:read_model, term()}
   | {:journal_storage, nil}
   | {:run_id, term()}}
```

Structured validation errors returned by the public read-model APIs.

# `start_option_error`

```elixir
@type start_option_error() ::
  {:invalid_option,
   {:opts, term()}
   | {:runtime, term()}
   | {:journal_storage, nil}
   | {:queue, term()}
   | {:now, term()}
   | {:run_id, term()}
   | {:schedule_idempotency_key, term()}}
```

Structured validation errors returned by the public start APIs.

# `apply_signal`

```elixir
@spec apply_signal(
  Squidie.Runtime.Signal.t(),
  keyword()
) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error, Squidie.Config.config_error() | term()}
```

Applies a Squidie-native runtime command signal.

Use the named helpers such as `start/3`, `cancel/2`, `resume/3`,
`approve/3`, `reject/3`, and `replay/2` for ordinary application calls. Use
`apply_signal/2` when an agent, router, webhook, scheduler, or Jido interop
boundary has already normalized a request into a
`Squidie.Runtime.Signal` envelope.

The envelope API applies the same runtime commands for starts, cron starts,
replays, cancellation, and manual decisions while preserving signal metadata,
occurrence time, and idempotency keys in the journal command history.

# `approve`

```elixir
@spec approve(Ecto.UUID.t(), map(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found | :invalid_run_id | Squidie.Config.config_error() | term()}
```

Approves a paused approval step and resumes the run through its success path.

# `cancel`

```elixir
@spec cancel(
  Ecto.UUID.t(),
  keyword()
) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | Squidie.Config.config_error()
     | Squidie.Runtime.Journal.Cancellation.cancel_error()}
```

Requests cancellation for an eligible workflow run.

# `config`

```elixir
@spec config(keyword()) ::
  {:ok, Squidie.Config.t()} | {:error, Squidie.Config.config_error()}
```

Loads Squidie configuration from the application environment with optional
runtime overrides.

# `config!`

```elixir
@spec config!(keyword()) :: Squidie.Config.t()
```

Loads Squidie configuration and raises if required keys are missing.

# `execute_next`

```elixir
@spec execute_next(keyword()) :: Squidie.Runtime.Journal.Executor.execute_result()
```

Executes the next visible workflow attempt through the selected runtime.

The default journal runtime claims one visible Jido journal-backed attempt,
runs its declared step, and appends durable attempt completion or failure
facts. Pass `journal_storage:` only when overriding the inferred Ecto storage
boundary.

# `explain_run`

```elixir
@spec explain_run(
  String.t(),
  keyword()
) ::
  {:ok, Squidie.ReadModel.Explanation.Diagnostic.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | read_option_error()
     | Squidie.Config.config_error()
     | Squidie.ReadModel.Explanation.explanation_error()}
```

Explains the current runtime state of one workflow run.

The result is structured diagnostic data for host apps, CLIs, and dashboards.
Use `inspect_run/2` for the factual run snapshot and `explain_run/2` when an
operator-facing surface needs the reason, evidence, and valid next actions for
the run's current state.

The selected read model comes from host configuration unless overridden. The
read model derives diagnostics from durable journal projections.

# `inspect_run`

```elixir
@spec inspect_run(
  String.t(),
  keyword()
) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | read_option_error()
     | Squidie.Config.config_error()
     | Squidie.ReadModel.Inspection.snapshot_error()}
```

Fetches one workflow run by id.

The selected read model comes from host configuration unless overridden. The
read model rebuilds a projection-backed snapshot from durable journal entries.

# `inspect_run_graph`

```elixir
@spec inspect_run_graph(
  String.t(),
  keyword()
) ::
  {:ok, Squidie.Runs.GraphInspection.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | read_option_error()
     | Squidie.Config.config_error()
     | Squidie.ReadModel.Inspection.snapshot_error()}
```

Fetches one workflow run as graph-oriented inspection data.

The graph projection preserves `inspect_run/2` as the factual run snapshot and
derives nodes and edges from that same durable state. The selected read model
comes from host configuration unless overridden.

# `inspect_run_timeline`

```elixir
@spec inspect_run_timeline(
  String.t(),
  keyword()
) ::
  {:ok, Squidie.ReadModel.Timeline.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | read_option_error()
     | Squidie.Config.config_error()
     | Squidie.ReadModel.Inspection.snapshot_error()}
```

Fetches one workflow run as chronological operator timeline events.

The timeline projection is derived from the same durable read-model snapshot
as `inspect_run/2`. Events carry stable ordering fields and redaction-safe
details so clients do not need to parse raw journal entries.

# `list_runs`

```elixir
@spec list_runs(
  [Squidie.ReadModel.Listing.list_filter()],
  keyword()
) ::
  {:ok, [Squidie.ReadModel.Listing.Summary.t()]}
  | {:error,
     Squidie.Config.config_error() | Squidie.ReadModel.Listing.list_error()}
```

Lists workflow runs with optional filters.

Journal-backed runtime calls return redacted listing summaries. Use
`inspect_run/2` or `inspect_run_graph/2` with a run id when callers need
detailed runtime state for one run.

# `preview_dynamic_work`

```elixir
@spec preview_dynamic_work(String.t(), map() | keyword(), keyword()) ::
  {:ok, Squidie.Runs.DynamicWorkPreview.t()}
  | {:error,
     :not_found
     | Squidie.Config.config_error()
     | read_option_error()
     | Squidie.Runtime.Journal.DynamicWork.dynamic_work_error()
     | term()}
```

Validates bounded dynamic work and returns the graph it would produce.

This is the read-only companion to `record_dynamic_work/3`. It applies the
same validation and normalization rules, but does not append a journal fact.
Use it for UI previews, visual editor validation, and host-side dry runs
before recording dynamic work durably. Pass `:action_registry` to require
every dynamic node action key to be host-allowlisted before previewing.

# `preview_spec`

```elixir
@spec preview_spec(Squidie.Workflow.Spec.t() | map(), map(), keyword()) ::
  {:ok, Squidie.Runs.SpecPreview.t()} | {:error, term()}
```

Previews a runtime-authored workflow spec with a sample payload.

Preview execution resolves runtime-authored action keys through the host-owned
action registry and calls only actions that explicitly opt into dry-run
behavior. It does not create a run, append journal state, schedule dispatch
attempts, or call durable action `run/2` callbacks.

# `preview_spec`

```elixir
@spec preview_spec(Squidie.Workflow.Spec.t() | map(), atom(), map(), keyword()) ::
  {:ok, Squidie.Runs.SpecPreview.t()} | {:error, term()}
```

Previews a runtime-authored workflow spec through a named trigger.

# `record_dynamic_work`

```elixir
@spec record_dynamic_work(String.t(), map() | keyword(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found
     | Squidie.Config.config_error()
     | read_option_error()
     | Squidie.Runtime.Journal.DynamicWork.dynamic_work_error()
     | term()}
```

Records bounded dynamic work for one workflow run.

This API records inspection-only dynamic structure. It does not make dynamic
nodes executable, schedule dispatch attempts, or alter terminal-state
decisions. Use it when host code or a runtime step has already made a bounded
fanout or planning decision and dashboards need durable, validated metadata
about that decision.

The attribute payload must include:

  * `:dynamic_key` - a stable non-empty string for this dynamic work group.
  * `:origin` - a map with `:runnable_key`, `:step`, and positive `:attempt`
    matching a planned runnable in the active run.
  * `:nodes` - one or more dynamic node maps with unique non-empty `:id`
    values that do not collide with declared workflow steps or previously
    recorded dynamic nodes.

Optional `:edges`, `:metadata`, `:reason`, and `:status` values are normalized
and redacted like other journal metadata. Pass `:action_registry` to require
every dynamic node action key to be host-allowlisted before recording. Exact
duplicate records are idempotent while the run remains active. Terminal runs,
stale workflow definitions, invalid origins, node collisions, unknown options,
and write conflicts return structured `{:error, reason}` tuples.

# `reject`

```elixir
@spec reject(Ecto.UUID.t(), map(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found | :invalid_run_id | Squidie.Config.config_error() | term()}
```

Rejects a paused approval step and resumes the run through its rejection path.

# `replay`

```elixir
@spec replay(
  Ecto.UUID.t(),
  keyword()
) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | Squidie.Config.config_error()
     | Squidie.Runtime.Journal.Replay.replay_error()}
  | {:error, {:dispatch_failed, term()}}
```

Creates a new run from a prior run and links it to the original run.

Replays are blocked by default once the source run completed an irreversible
or non-compensatable step. Pass `allow_irreversible: true` only after an
operator has reviewed the side effect and accepted re-execution.

# `resume`

```elixir
@spec resume(Ecto.UUID.t()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found | :invalid_run_id | Squidie.Config.config_error() | term()}
```

Resumes a run that is intentionally paused for manual intervention.

# `resume`

```elixir
@spec resume(
  Ecto.UUID.t(),
  keyword()
) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found | :invalid_run_id | Squidie.Config.config_error() | term()}
@spec resume(Ecto.UUID.t(), map()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found | :invalid_run_id | Squidie.Config.config_error() | term()}
```

Resumes a paused run with either configuration overrides or manual action
attributes.

# `resume`

```elixir
@spec resume(Ecto.UUID.t(), map(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found | :invalid_run_id | Squidie.Config.config_error() | term()}
```

Resumes a paused run with manual action attributes and configuration
overrides.

# `schedule_dynamic_work`

```elixir
@spec schedule_dynamic_work(String.t(), map() | keyword(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found
     | Squidie.Config.config_error()
     | read_option_error()
     | Squidie.Runtime.Journal.DynamicWork.dynamic_work_error()
     | term()}
```

Records bounded dynamic work and schedules each dynamic node as executable work.

This is the executable counterpart to `record_dynamic_work/3`. The dynamic
work fact and the planned runnable intents are appended to the run thread in
one optimistic write, then missing dispatch attempts are scheduled from that
durable plan. Pass `:action_registry`; every dynamic node must include an
approved `:action` key and may include an `:input` map for the scheduled
attempt.

# `start`

```elixir
@spec start(module(), map()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error, Squidie.Config.config_error()}
  | {:error, start_option_error()}
  | {:error, Squidie.Runtime.Journal.Starter.start_error()}
  | {:error, {:dispatch_failed, term()}}
```

Starts a new workflow run through the workflow's default trigger.

Public manual starts load journal runtime defaults from `config :squidie`.
When `journal_storage:` is not passed explicitly, Squidie infers Ecto-backed
journal storage from the configured `:repo`, so host apps must either set
`config :squidie, repo: MyApp.Repo` globally or pass an explicit
`journal_storage:` override from their runtime boundary.

# `start`

```elixir
@spec start(module(), map(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error, Squidie.Config.config_error()}
  | {:error, {:invalid_option, atom()}}
  | {:error, start_option_error()}
  | {:error, Squidie.Runtime.Journal.Starter.start_error()}
  | {:error, {:dispatch_failed, term()}}
@spec start(module(), atom(), map()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error, Squidie.Config.config_error()}
  | {:error, start_option_error()}
  | {:error, Squidie.Runtime.Journal.Starter.start_error()}
  | {:error, {:dispatch_failed, term()}}
```

Starts a new workflow run through the workflow's default trigger with runtime
overrides, or through a named trigger without runtime overrides.

# `start`

```elixir
@spec start(module(), atom(), map(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error, Squidie.Config.config_error()}
  | {:error, {:invalid_option, atom()}}
  | {:error, start_option_error()}
  | {:error, Squidie.Runtime.Journal.Starter.start_error()}
  | {:error, {:dispatch_failed, term()}}
```

Starts a named trigger while applying runtime configuration overrides.

Overrides are intended for host-app test and integration boundaries. Runtime
context injection is kept out of this public API so scheduled starts and other
internal callers can keep their idempotency metadata isolated.

The Jido journal runtime is the default and infers Ecto-backed journal storage
from the configured repo. Pass `journal_storage:` only when a host, test, or
integration boundary needs a non-default storage adapter. Journal execution
supports normal action steps, immediate built-in `:log` steps, built-in
`:wait` steps in transition and dependency workflows, and manual `:pause` or
`:approval` boundaries.

Public manual starts still resolve that default storage through
`config :squidie`, so host apps must keep `:repo` configured globally unless
they pass an explicit `journal_storage:` override.

# `start_child_run`

```elixir
@spec start_child_run(Squidie.Step.Context.t(), module(), map(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error, Squidie.Config.config_error()}
  | {:error, {:invalid_option, atom() | term()}}
  | {:error, Squidie.Runtime.Journal.ChildStarter.start_error()}
```

Starts a child workflow run from a native step context.

Child starts are deterministic for the parent run, parent step, child
workflow, child trigger, and required `:child_key`. Duplicate calls with the
same key return the existing child run and do not duplicate parent lineage.

# `start_child_run`

```elixir
@spec start_child_run(Squidie.Step.Context.t(), module(), atom(), map(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error, Squidie.Config.config_error()}
  | {:error, {:invalid_option, atom() | term()}}
  | {:error, {:invalid_trigger, :expected_atom}}
  | {:error, Squidie.Runtime.Journal.ChildStarter.start_error()}
```

# `start_spec`

```elixir
@spec start_spec(Squidie.Workflow.Spec.t() | map(), map(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error, Squidie.Config.config_error()}
  | {:error, start_option_error()}
  | {:error, Squidie.Runtime.Journal.Starter.start_error()}
  | {:error, {:dispatch_failed, term()}}
```

Starts a runtime-authored workflow spec through its default trigger.

Runtime-authored specs should be validated with a host-owned action registry
before activation. Passing `:action_registry` lets Squidie resolve stable
action keys to approved executable modules at the start boundary.

# `start_spec`

```elixir
@spec start_spec(Squidie.Workflow.Spec.t() | map(), atom(), map(), keyword()) ::
  {:ok, Squidie.ReadModel.Inspection.Snapshot.t()}
  | {:error, Squidie.Config.config_error()}
  | {:error, start_option_error()}
  | {:error, Squidie.Runtime.Journal.Starter.start_error()}
  | {:error, {:dispatch_failed, term()}}
```

Starts a runtime-authored workflow spec through a named trigger.

---

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