> ## Documentation Index
> Fetch the complete documentation index at: https://piloop.autoresearch.inc/llms.txt
> Use this file to discover all available pages before exploring further.

# State machines

> The statuses of ideas, runs, agents and candidates, and the paths between them.

Four columns hold a lifecycle: `ideas.status`, `runs.status`, `workers.state` and `candidates.verdict`. A CHECK
constraint fixes the set of values of each one. piloop has no table of allowed transitions: the daemon and the CLI
take the paths below. Anyone with `piloop sql` can set any value, for example to park an idea or to change a verdict.

These are the values, generated from the enums in `piloop/db/models.py`:

| Enum | Column | Values |
| - | - | - |
| `IdeaStatus` | `ideas.status` | `seed`, `proposed`, `ready`, `scheduled`, `done`, `parked`, `rejected` |
| `RunStatus` | `runs.status` | `queued`, `running`, `succeeded`, `failed`, `timed_out` |
| `WorkerState` | `workers.state` | `requested`, `starting`, `running`, `exited`, `killed` |
| `Verdict` | `candidates.verdict` | `pending`, `keep`, `interesting`, `discard`, `crash`, `reference` |

## Idea

```mermaid theme={null}
stateDiagram-v2
    direction LR
    [*] --> seed: idea seed
    [*] --> proposed: idea add, needs approval
    [*] --> ready: idea add
    seed --> proposed: idea develop, needs approval
    seed --> ready: idea develop
    seed --> rejected: research rejects it
    proposed --> ready: a human approves it
    ready --> scheduled: the scheduler queues a run
    ready --> parked: unknown track or no base
    scheduled --> ready: the run failed, attempts are left
    scheduled --> done: commits judged, or no attempts left
    scheduled --> parked: the last attempt did not start
    parked --> ready: set by hand
```

A newer idea that `supersedes` a `seed`, `proposed` or `ready` idea that never ran makes the daemon reject it. You,
the orchestrator and research also park or reject ideas by hand. See [Ideas, seeds and runs](/concepts/ideas-and-runs).

## Run

```mermaid theme={null}
stateDiagram-v2
    direction LR
    [*] --> queued: the scheduler queues it
    queued --> running: the executor starts it
    running --> queued: its agent did not start, relaunch
    running --> succeeded: commits or a finding
    running --> failed: an error, no commit and no finding, or the daemon stopped
    running --> timed_out: the role timeout
    queued --> failed: the campaign or the daemon stopped
```

A run that the daemon stopped is not counted as an attempt. Its idea goes back to `ready`.

## Agent

A `workers` row is an agent process of any role. While it is `requested`, the row is a request to start one.

```mermaid theme={null}
stateDiagram-v2
    direction LR
    [*] --> requested: a trigger, the queue or a person
    requested --> starting: taken, within the caps
    requested --> killed: the campaign stopped
    starting --> running: the runtime started it
    starting --> killed: the start failed
    running --> exited: the agent ended
    running --> killed: timeout, or the daemon stopped
```

## Candidate verdict

```mermaid theme={null}
stateDiagram-v2
    direction LR
    [*] --> pending: a new commit
    [*] --> keep: the baseline
    [*] --> reference: candidate import
    pending --> keep: a significant gain, guardrails hold
    pending --> interesting: a gain that is not significant, a guardrail breached, or a keep to rebase
    pending --> discard: no gain, a guardrail past its floor, or a skipped commit
    pending --> crash: no primary value
    discard --> interesting: a note
```

The daemon sets a verdict once. Anyone may change it later, and should say why in a comment. See
[the verdict](/concepts/verdict).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.