# States and rules

> The OPM language · https://spoletta.com/docs/states

A state is one situation an object can be in: `draft`, `approved`, `changes requested`, `bug`. In Spoletta states do the routing: they decide which process runs next.

*Diagram: Classify decides Ticket is a bug, so the process waiting for bug runs. Links leave from a state's pill.*

## Adding states

Right-click an object and choose **Add state**, then type its name. Each state shows as a pill on the object. Double-click a pill to rename it; its **×** deletes it along with its links. During a run the state the object is in is highlighted, and its subtitle reads *In state bug*.

## What a state on a link means

A link that names a state does one of two things, depending on its direction:

-   **Into a state** (a process yields the object in that state): the process generates the object in it. *“Draft” yields “Notes” as “draft”.*
-   **Out of a state** (a process takes the object in that state): the process waits for the object to be in it, as an event or as a condition. See [Event and condition](https://spoletta.com/docs/procedural-links.md#event-and-condition).

Who can decide a state:

| Who | How |
| --- | --- |
| An AI agent | Its link to the object lists the states it may choose between. The agent picks one and can add instructions for whoever takes the object next. |
| A person | A human process's link lists the states to decide between. The person presses one, with optional instructions. |
| A rule | A state's rule says when the object is in it. Scripts, Sentry steps and anything generating the object in no state are routed by rules. |

## Rules

A state can have a **rule** saying when an object is in it, set under **State rules** in the object's settings. When a step generates the object *in no state*, it comes out in the **first** of its states, in order, whose rule holds. If none holds, it comes out in no state.

Rule syntax:

```rule
confidence >= 0.8 and kind == "bug"
status != 200
author.email contains "@acme.com"
data contains "urgent"
```

-   Comparisons are joined by `and`, and all of them must hold.
-   Operators: `==`, `!=`, `<`, `<=`, `>`, `>=` and `contains` (text in text, or an item in a list).
-   The left side is a field path, with dots into parts. An object without attributes holds its value under `data`.
-   The right side is a JSON value; anything that isn't JSON is a string.

*Diagram: A script can't decide a state, but its output still routes: Health comes out slow because ms > 2000 holds.*

OPL:

```text
Health can be down, slow or fine.
Health is down when status != 200.
Health is slow when ms > 2000.
Health is fine when ms <= 2000.
```

> **Order and catch-alls:** Order states from most to least specific: the first match wins. A state without a rule never matches, so a last rule-less state is not a catch-all. Give a catch-all a rule that always holds for that object.
