modeling-state-machineslisted
Install: claude install-skill yutna/functional-design-skills
# Modeling State Machines
## Overview
Most domain entities have a lifecycle: a quote is drafted, sent,
accepted, or expires; a shipment is pending, dispatched, delivered. The
usual representation is one record with a status field and a scattering
of optional fields, which permits every combination of status and data
and forces every function to check.
Model the lifecycle as a choice type instead: one case per state, each
carrying exactly the data that exists in that state, and one function per
legal transition. Illegal states disappear, and so do illegal
transitions.
## When to use
- A record has a `status`, `state`, `stage` or `phase` field
- Functions begin by branching on that field
- Optional fields are meaningful only in some states
- The business describes something as being "in" a state
- A bug allowed an entity to skip a step, or to go backwards
Not for: a value with no lifecycle, or a workflow's internal steps, which
are [designing-workflow-pipelines](../designing-workflow-pipelines/SKILL.md).
## Core rules
1. **One case per state.** Named as the business names it.
2. **Each case carries only its own data.** A tracking number belongs to
the shipped and delivered cases, not to the type.
3. **One function per transition**, taking the specific source state, not
the whole union.
4. **Transitions return the target state**, or a `Result` when the
transition can be refused.
5. **Make illegal transitions unwriteable.** If `deliver` takes a
`Shipped`, noth