Jizoku (jizoku v0.4.0)

Copy Markdown View Source

Public entrypoint for the Jizoku 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.

Summary

Types

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

Structured validation errors returned by the public start APIs.

Functions

Atomically applies a versioned graph mutation and repairs ready dispatches.

Applies a Jizoku-native or recognized Jido runtime command signal.

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

Requests cancellation for an eligible workflow run.

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

Loads Jizoku configuration and raises if required keys are missing.

Continues an eligible run as one fresh, durably linked successor.

Delivers and durably acknowledges pending Jido signals for one workflow run.

Executes the next visible workflow attempt through the selected runtime.

Explains the current runtime state of one workflow run.

Traverses continue-as-new lineage with an explicit read bound.

Fetches one workflow run by id.

Fetches one workflow run as graph-oriented inspection data.

Fetches one workflow run as chronological operator timeline events.

Lists workflow runs with optional filters.

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

Validates a versioned graph mutation against current durable run state.

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

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

Repairs missing graph dispatch markers and ready attempts from durable facts.

Records bounded dynamic work for one workflow run.

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

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

Resumes a run that is intentionally paused for manual intervention.

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

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

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

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

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

Starts a named trigger while applying runtime configuration overrides.

Starts a child workflow run from a native step context.

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

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

Types

read_option_error()

@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()

@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.

Functions

apply_graph_mutation(run_id, attrs, overrides \\ [])

@spec apply_graph_mutation(String.t(), map(), keyword()) ::
  {:ok, Jizoku.GraphMutation.Report.t()} | {:error, term()}

Atomically applies a versioned graph mutation and repairs ready dispatches.

The mutation fact and every new runnable intent commit to the run thread in one optimistic append before any dispatch-thread write. If that commit succeeds but dispatch repair fails, the returned report has status :committed_needs_reconciliation.

apply_signal(signal, overrides \\ [])

Applies a Jizoku-native or recognized Jido 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 already has a Jizoku.Runtime.Signal or recognized Jido.Signal command envelope.

The envelope API applies the same runtime commands for starts, cron starts, replays, cancellation, and manual decisions while preserving signal metadata, occurrence time, identity, source provenance, trace correlation, partition, and idempotency keys in the journal command history. Raw Jido signals must use a supported Jizoku command type. The signal source is audit provenance, not authorization; authenticate and authorize inbound signals before applying them. Domain signals require a host-owned Jizoku.Jido.SignalResolver passed as jido_signal_resolver:. The resolver can return only bounded lifecycle commands and cannot choose runtime storage, queues, or executable modules from signal strings. Domain decisions are durably fenced by partition plus CloudEvents source and ID before target mutation, so exact retries reuse the original resolved command and queue across resolver deployments.

approve(run_id, attrs, overrides \\ [])

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

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

cancel(run_id, overrides \\ [])

Requests cancellation for an eligible workflow run.

config(overrides \\ [])

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

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

config!(overrides \\ [])

@spec config!(keyword()) :: Jizoku.Config.t()

Loads Jizoku configuration and raises if required keys are missing.

continue_as_new(run_id, overrides \\ [])

@spec continue_as_new(
  Ecto.UUID.t(),
  keyword()
) :: {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()} | {:error, term()}

Continues an eligible run as one fresh, durably linked successor.

The host must first activate continuation fences with config :jizoku, continuation_fences: :enabled after every runtime worker has been upgraded to a fence-aware Jizoku release. input: and continuation_key: are required. Only the declared input is carried into the successor; accumulated workflow context is not copied.

Exact retries return the same successor. Reusing a continuation key with different input fails closed.

deliver_jido_signals(run_id, overrides \\ [])

@spec deliver_jido_signals(
  String.t(),
  keyword()
) :: {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()} | {:error, term()}

Delivers and durably acknowledges pending Jido signals for one workflow run.

Dispatch routes are host-owned runtime configuration and are never persisted. Configure :jido_dispatch_routes as a map from the durable route name to a Jido.Signal.Dispatch configuration. Delivery is at-least-once: consumers must deduplicate the stable Jido signal id when a process stops after sending but before recording the acknowledgement.

execute_next(overrides \\ [])

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(run_id, overrides \\ [])

@spec explain_run(
  String.t(),
  keyword()
) ::
  {:ok, Jizoku.ReadModel.Explanation.Diagnostic.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | read_option_error()
     | Jizoku.Config.config_error()
     | Jizoku.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_continuation_chain(run_id, overrides \\ [])

@spec inspect_continuation_chain(
  String.t(),
  keyword()
) :: {:ok, Jizoku.ReadModel.ContinuationChain.t()} | {:error, term()}

Traverses continue-as-new lineage with an explicit read bound.

Traversal follows predecessor links by default and never follows child-run or replay lineage. :max_hops defaults to the host continuation-history policy; :direction accepts :backward or :forward.

inspect_run(run_id, overrides \\ [])

@spec inspect_run(
  String.t(),
  keyword()
) ::
  {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | read_option_error()
     | Jizoku.Config.config_error()
     | Jizoku.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(run_id, overrides \\ [])

@spec inspect_run_graph(
  String.t(),
  keyword()
) ::
  {:ok, Jizoku.Runs.GraphInspection.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | read_option_error()
     | Jizoku.Config.config_error()
     | Jizoku.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(run_id, overrides \\ [])

@spec inspect_run_timeline(
  String.t(),
  keyword()
) ::
  {:ok, Jizoku.ReadModel.Timeline.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | read_option_error()
     | Jizoku.Config.config_error()
     | Jizoku.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(filters \\ [], overrides \\ [])

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(run_id, attrs, overrides \\ [])

@spec preview_dynamic_work(String.t(), map() | keyword(), keyword()) ::
  {:ok, Jizoku.Runs.DynamicWorkPreview.t()}
  | {:error,
     :not_found
     | Jizoku.Config.config_error()
     | read_option_error()
     | Jizoku.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_graph_mutation(run_id, attrs, overrides \\ [])

@spec preview_graph_mutation(String.t(), map(), keyword()) ::
  {:ok, Jizoku.GraphMutation.Preview.t()} | {:error, term()}

Validates a versioned graph mutation against current durable run state.

Preview is read-only. It resolves added actions and validates dependency and lifecycle invariants without appending journal facts or checkpoints.

preview_spec(spec, payload, overrides \\ [])

@spec preview_spec(Jizoku.Workflow.Spec.t() | map(), map(), keyword()) ::
  {:ok, Jizoku.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(spec, trigger_name, payload, overrides)

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

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

reconcile_dynamic_graph(run_id, overrides \\ [])

@spec reconcile_dynamic_graph(
  String.t(),
  keyword()
) :: {:ok, Jizoku.GraphMutation.Reconciliation.t()} | {:error, term()}

Repairs missing graph dispatch markers and ready attempts from durable facts.

Reconciliation never appends graph mutations or invents topology. It is safe to repeat after conflicts, restarts, and partial post-commit scheduling.

record_dynamic_work(run_id, attrs, overrides \\ [])

@spec record_dynamic_work(String.t(), map() | keyword(), keyword()) ::
  {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found
     | Jizoku.Config.config_error()
     | read_option_error()
     | Jizoku.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(run_id, attrs, overrides \\ [])

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

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

replay(run_id, overrides \\ [])

@spec replay(
  Ecto.UUID.t(),
  keyword()
) ::
  {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found
     | :invalid_run_id
     | Jizoku.Config.config_error()
     | Jizoku.Runtime.Journal.Commands.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(run_id)

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

Resumes a run that is intentionally paused for manual intervention.

resume(run_id, overrides)

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

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

resume(run_id, attrs, overrides)

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

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

schedule_dynamic_work(run_id, attrs, overrides \\ [])

@spec schedule_dynamic_work(
  String.t(),
  map() | keyword() | Jido.Instruction.t(),
  keyword()
) ::
  {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()}
  | {:error,
     :not_found
     | Jizoku.Config.config_error()
     | read_option_error()
     | Jizoku.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. A Jido.Instruction is accepted directly when :origin identifies an already applied runnable; Jizoku uses the instruction ID as the durable dynamic-work identity and resolves its action module through the registry.

start(workflow, payload)

@spec start(module(), map()) ::
  {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()}
  | {:error, Jizoku.Config.config_error()}
  | {:error, start_option_error()}
  | {:error, Jizoku.Runtime.Journal.Commands.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 :jizoku. When journal_storage: is not passed explicitly, Jizoku infers Ecto-backed journal storage from the configured :repo, so host apps must either set config :jizoku, repo: MyApp.Repo globally or pass an explicit journal_storage: override from their runtime boundary.

start(workflow, payload, overrides)

@spec start(module(), map(), keyword()) ::
  {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()}
  | {:error, Jizoku.Config.config_error()}
  | {:error, {:invalid_option, atom()}}
  | {:error, start_option_error()}
  | {:error, Jizoku.Runtime.Journal.Commands.Starter.start_error()}
  | {:error, {:dispatch_failed, term()}}
@spec start(module(), atom(), map()) ::
  {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()}
  | {:error, Jizoku.Config.config_error()}
  | {:error, start_option_error()}
  | {:error, Jizoku.Runtime.Journal.Commands.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(workflow, trigger_name, payload, overrides)

@spec start(module(), atom(), map(), keyword()) ::
  {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()}
  | {:error, Jizoku.Config.config_error()}
  | {:error, {:invalid_option, atom()}}
  | {:error, start_option_error()}
  | {:error, Jizoku.Runtime.Journal.Commands.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 :jizoku, so host apps must keep :repo configured globally unless they pass an explicit journal_storage: override.

start_child_run(parent_context, child_workflow, payload, overrides \\ [])

@spec start_child_run(Jizoku.Step.Context.t(), module(), map(), keyword()) ::
  {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()}
  | {:error, Jizoku.Config.config_error()}
  | {:error, {:invalid_option, atom() | term()}}
  | {:error, Jizoku.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(parent_context, child_workflow, child_trigger, payload, overrides)

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

start_spec(spec, payload, overrides \\ [])

@spec start_spec(Jizoku.Workflow.Spec.t() | map(), map(), keyword()) ::
  {:ok, Jizoku.ReadModel.Inspection.Snapshot.t()}
  | {:error, Jizoku.Config.config_error()}
  | {:error, start_option_error()}
  | {:error, Jizoku.Runtime.Journal.Commands.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 Jizoku resolve stable action keys to approved executable modules at the start boundary.

start_spec(spec, trigger_name, payload, overrides)

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

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