# What happens in a run

> Running and debugging · https://spoletta.com/docs/engine

When you press Run, the server walks the board. It works out which processes are ready, runs them, in parallel where it can, and records each as a step. A handful of rules decide what runs when. Knowing them is what makes a flow work.

## A run starts with nothing

A run takes no input. It begins at the Start node, with the process the start points at. An object that no process generates exists from the beginning, but **empty**. So whatever a flow works on has to come from inside the flow:

-   a human process that has a person fill it in, the usual first step of a flow started by hand;
-   a Sentry or script process that fetches it, the usual first step of a scheduled flow;
-   an agent that finds it itself, with MCP servers or in the repositories.

> **Watch out:** A first agent that “takes the request” when nothing produces the request gets an empty input. It is the most common authoring mistake.

## Watch a run, step by step

The release notes flow: a person picks the release, an agent drafts the notes, a person approves them or asks for changes, and another agent revises them until they are approved. Step through a run in which the first draft is sent back once. Objects that don't exist yet are faded.

1.  The run begins at **Start**, with **Pick release**. It is a human step, so it waits for a person to fill in Release. Nothing else can run: Release and Notes don't exist yet.
2.  The person filled in **Release**, so it exists. **Draft** takes it, and every object Draft takes without naming a state now exists, so Draft is ready and runs.
3.  Draft hands in **Notes**. **Approve** takes Notes plainly, so it becomes ready and waits for the release manager. Revise and Post wait for states Notes isn't in.
4.  The person sets Notes to **changes requested**, with instructions. A decision starts a **fresh pass** from Notes. Its entering that state triggers **Revise**, which gets the notes and the instructions as a change request.
5.  Revise hands in a new version of **Notes**. Approve takes Notes, so it runs again in this pass: the person reviews the new version.
6.  This time the person sets Notes to **approved**. Another fresh pass, and Notes entering approved triggers **Post**.
7.  Post is done. Nothing is left that can run and nothing failed, so the run ends **Done**. Every step, both versions of Notes and both decisions are kept with it.

## When a process is ready

Once a process succeeds, its outputs exist, and the processes taking them can run. Several ready at once run **in parallel**. What makes a process ready depends on its input links:

| Its input links | It runs |
| --- | --- |
| No state named | once **every** object it takes exists, in any state. |
| An event link (a state, not a condition) | **whenever** the object enters that state, and only then, with whichever of its other inputs exist. Several event links are alternatives: any one triggers it. Its stateless inputs never trigger it on their own. |
| A condition link | counts as an ordinary input for readiness. Once the process is ready the state is checked, and if the object isn't in it, the process is **skipped**. |
| A quorum of n (Needs) | once *n* of its stateless and condition inputs exist and hold their conditions; it is skipped once too few still can. |

A process is also run when the Start points at it, and right after a process with a *next* connection to it succeeds or is skipped.

> **Event links change everything:** With even one event link, a process runs only on its events, from the start, or from a next. So a process that must both write something first and revise it later has to be the board's start, or be split into a writer and a reviser, as Draft and Revise are above. See [Review loops](https://spoletta.com/docs/loops.md).

## Skipping spreads

A skipped process generates nothing. What it would have generated is **settled as absent**, so processes waiting for it go on without it, and are skipped in turn if they would get nothing at all. That makes condition links the way to build branches that rejoin.

1.  **Classify** takes the Ticket and decides what it is. It hands in **Triage** in one of two states.
2.  Triage now exists, in **feature**. Both **Attempt fix** and **Write spec** take it through a condition link, so both are ready at once, and each checks its condition.
3.  Triage isn't a bug, so Attempt fix is **skipped**, and Fix is settled as absent. Write spec's condition holds, so it runs.
4.  Spec exists and Fix never will. **Summarize** takes both, and with every input either there or settled as absent, it runs with what exists.
5.  Summarize is done and the run ends **Done**. A skipped process is not a failure. Without the condition links, Summarize would wait for Fix forever, unless it had a quorum of 1.

Conditions are checked as soon as their process is ready, so put them on an object that only exists once the decision is made, like Triage here. Prefer conditions when a branch is decided once, and events when an object can enter a state many times. See [Branches and decisions](https://spoletta.com/docs/branches.md).

## Passes, loops and rounds

Every process runs **at most once per pass**, so a cycle of agents ends instead of spinning. A **decision**, a person or an agent setting a state, starts a **fresh pass** from that object, so review loops can repeat, as the walkthrough above shows.

-   When a reviewer sends work back, the process taking it in that state gets a **change request**: the reviewed work and the reviewer's instructions. A person's decision always carries their instructions on.
-   An agent reviewer's **rounds** (3 by default) bound the loop. Once it has run that many times, a decision sending the work back to a process that already ran fails it instead, ending that branch or going to its failure handler. A person can loop as long as they like.

## Failure

-   An agent, script or Sentry step fails on an error, a non-zero exit, a reply that doesn't match its contract after it was told so, its timeout, or a stop by a person.
-   **Retries** try it again, each try a step of its own. A stopped step isn't retried.
-   A failure **ends its branch**. The rest of the run goes on, but the run ends failed, unless a failure handler takes it, in which case it can still end done. The handler runs in a fresh pass with what the failed process took, plus *Failure of X* saying what went wrong. See [Handling failure](https://spoletta.com/docs/failures.md).
-   A human step waits as long as it takes; it never times out.

The run ends **done** once nothing is left to run and no failure went unhandled, **failed** if some branch failed unhandled, **terminated** on a duplicate, and **interrupted** when a person stops it.
