Skip to content

Run lifecycle

A run is mini-ork's unit of work: a kickoff enters, a recipe walks it through six stages, and a verdict leaves with the evidence that produced it. This page describes that path end to end — what each stage owns, how nodes and edges move work, how a run survives a crash, and what lands on disk.

The lifecycle is deliberately boring: every stage writes durable state before the next stage reads it. That is what makes resume, replay, and audit possible.

The six stages

flowchart LR
    K[kickoff] --> C[classify]
    C --> P[plan]
    P --> E[execute]
    E --> V[verify]
    V -->|pass| R[reflect]
    V -->|fail| E
    R --> I[improve]
    I -.->|next run| C
Stage Owns Writes
Classify Choosing the task class and recipe task_runs.recipe, classification confidence
Plan Decomposing the objective into nodes and edges plan.json, node records
Execute Dispatching nodes to lanes with budgets Node outputs, artifacts, run_events
Verify Running gates and deciding the verdict verifier-*.log, run-verdict.json
Reflect Extracting only what the evidence supports into memory Memory namespaces, learning rows
Improve Scoring proposed changes and non-regression-gating them Candidate and promotion records

Classify

The classifier scores the kickoff against every seeded task_class.yaml and picks the best above threshold. A task class binds a recipe: workflow plus artifact contract. Classification is skippable — passing a recipe name to run forces it — but the decision is always recorded, so a later audit can see whether the wrong recipe was chosen.

Plan

The planner produces a graph of nodes connected by typed edges. A plan is not complete until it names how success is checked: the verifier contract, the artifact contract, and the success check that verification will execute. Plans that fail schema validation are repaired and retried, not silently accepted.

Execute

The executor walks the graph. Ready nodes are routed to lanes by role; each dispatch records its lane, model, transport and cost. Nodes that mutate a workspace run under the isolation policy (worktree, in-place, or per-node sandbox — see Sandboxing).

Failure inside execute is not immediately fatal. Retry edges and max_rounds re-dispatch with correction context, and a rollback node returns the workspace to the last known-good state while preserving it for inspection.

Verify

Verification executes the declared checks. A judge may veto a pass; it can never turn a failed command into a pass. The verdict is one of four values:

Verdict Meaning
PROVEN Every required gate ran and passed
REFUTED At least one required gate ran and failed
UNVERIFIED No gate produced a trustworthy signal
VACUOUS The checks that ran had no discriminating power

VACUOUS is the load-bearing one: a suite that passes without exercising the change is not evidence, and mini-ork says so instead of reporting green.

Reflect

Reflection turns the execution trace into memory — but only entries the evidence supports. A failed run contributes failure modes; a proven run contributes technique. Unverified claims do not enter prompts. See Learning loop.

Improve

Improvement proposes changes to prompts, workflow nodes or code, scores them, and promotes only on measured non-regression. The outer loop and its caps are in The self-improvement loop.

Nodes

Eight node types, each with a distinct contract:

Node type Responsibility Typical lane
planner Decompose the task; emit objective, assumptions, artifact and verifier contracts planner
researcher Gather prior runs and source material into a bounded context pack researcher, lens lanes
implementer Produce the artifact — patch, doc, config, report implementer / worker
reviewer Challenge the artifact against requirements; cannot approve its own work reviewer
verifier Run deterministic probes; binary pass/fail verifier
reflector Extract textual gradients from the trace reflector
publisher Commit, merge, push or finalize — only after gates pass publisher
rollback Revert to last known-good state; preserve the worktree, never destroy rollback

Lanes are roles, not vendors. Several models can serve researcher, and routing picks among them from measured performance (see Learning loop).

Edges

Edges carry semantics the executor enforces:

Edge type Meaning
depends_on Target cannot start until source completes and its output is available
supplies_context_to Source output is injected into target's context pack, even without a hard dependency
verifies Source verifier gates target's continuation
blocks Source failure prevents target from running entirely
retries On failure, target re-runs source with correction context
escalates_to On failure beyond max retries, route to a human gate or escalation inbox

The distinction between depends_on and supplies_context_to is the difference between scheduling and prompting: the first constrains order, the second only enriches context.

Durability: checkpoints, recovery, leases

A run can span hours and dozens of model calls. mini-ork keeps it resumable at two granularities and keeps two processes from racing it.

Two ledgers

Ledger Key Granularity Used for
checkpoints (run_id, step_id) Lifecycle steps (classify, plan, each stage boundary) Lifecycle replay
node_checkpoints (run_id, node_id) Individual DAG nodes, with input/output hashes Durable-DAG resume

Checkpoint semantics are LangGraph-style: a step recorded as succeeded is skipped on resume, with its persisted outputs intact; a step recorded as failed or errored is re-dispatched. node_checkpoints win over lifecycle checkpoints when both exist for a node, because they carry the hash that proves the reuse is honest: if the node's inputs changed, the old checkpoint does not apply and the node re-runs.

Resume protocol

mini-ork run --resume <run-id>
mini-ork run --resume <run-id> --checkpoint-id <id>

Before doing anything, resume prints one [mini-ork-resume] line stating what will be skipped and what will be re-dispatched. An unknown run id is a hard error — there is no silent fresh start, because a silent fresh start would double-spend and could overwrite evidence.

Single-writer lease

One process owns a run at a time. mini_ork/stores/lease.py implements a lease with a fencing token:

  • default TTL DEFAULT_LEASE_TTL_S = 900 (15 minutes), extended by refresh_lease() while the holder lives;
  • the holder identifies itself with a minted owner token;
  • every write path calls fence_or_reject() — if the token is no longer the current holder, the write fails with FenceError instead of landing.

The fence matters after a pause or a network partition: the old holder may wake up believing it still owns the run. Without fencing it would write over the new holder's work. With fencing, its next write is rejected and the new holder's state stands.

request_recovery() adds a bounded recovery budget (DEFAULT_BUDGET_USD = 5.00) for re-dispatch after a failure, with can_dispatch() gating the projected cost and mark_dispatched() / close_recovery() recording the outcome.

Artifacts and the run directory

A run writes its evidence into .mini-ork/runs/<run-id>/:

.mini-ork/runs/<run-id>/
  plan.json              decomposed plan: nodes, edges, contracts
  nodes/<node-id>/       prompt, output, logs, artifacts per node
  workspace/
    manifests/           hash-verified artifact manifests
    inputs/              artifacts visible to downstream nodes
    system/              framework-only artifacts
    scratch/             disposable node scratch space
  verifier-*.log         raw output of every gate
  run-verdict.json       final verdict, reasons, evidence pointers
  .nodes/                per-node sandbox handles (when isolation is on)

The artifact graph decides what a downstream node may see: declared consumer-visible ports only, hash-verified before use. A missing or altered artifact is a completion failure, not a warning. See Artifact graph for ports, transforms and completion contracts.

State database

The important metadata mirrors into $MINI_ORK_DB:

Table Holds
task_runs One row per run: recipe, status, verdict, timestamps
run_events Ordered event stream (node start/end, retries, gates)
model_costs Per-call spend at list price
artifact_records Artifact content hash and verification linkage
checkpoints / node_checkpoints Resume ledgers
learning_record, conductor_decisions Learning-loop writeback
sqlite3 .mini-ork/state.db \
  'SELECT id, recipe, status, verdict FROM task_runs ORDER BY created_at DESC LIMIT 5;'

The run directory holds the bytes; the database holds the queryable history. Both are needed: the directory for evidence, the database for fleet-level views and learning.

Completion

A run completes when its nodes are done and its artifact contract is satisfied. Completion is artifact-based, not "the last node returned": an implementer that produces no contracted artifact fails completion even if it exits 0. Per-kind completion contracts define what each artifact shape must contain (implementer-summary.json, plan.json, *.diff / *.patch), so a malformed artifact cannot pass by being non-empty.

Publish is a separate, gated step. The publisher runs only after every gate passes, and its delivery strategy (commit, merge, push, bundle) is declared by the recipe — not inferred.

Lifecycle across processes

The same lifecycle runs whether it was started from the CLI, the scheduler, the Python SDK, or the web app. Those are all front doors onto the same executor: mini_ork.cli.execute walks the graph, the lease protects it, checkpoints make it resumable, and the verdict is written once.

This is why a failed run can be triaged, recovered, or promoted to a fix epic without special cases — each of those reads the same durable state the run itself wrote. See Failure triage.