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¶
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 byrefresh_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 withFenceErrorinstead 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.
Related¶
- Architecture overview — the components around the lifecycle.
- Verification — gates, relations, differential checks.
- Artifact graph — ports and completion contracts.
- Sandboxing — where node work executes.
- Recovery — operator procedures for resume and rewind.