Conditions during normal operation. Derived from the sentence's verbs and time-bearing nouns. Expect 8–15.
A practical guide to running Stateful on your project. Written for whoever you are on the team: designer, engineer, PM, or a hybrid. No visual-design background assumed.
The output is a state map: an explicit understanding of every condition your system can be in, scoped, with the in-scope active states' re-entry behaviour written down. Do it on a whiteboard, or hand the legwork to an agent.
in, out-with-implication, or out. The middle category captures states you're not designing this iteration but that constrain in-scope work through copy, naming, or data model.The method runs on a system sentence, and a sentence works best where states are dense. That altitude is a feature or a surface, not a whole product. A sentence for an entire app ("a bookstore-and-reader app is…") abstracts so hard it generates nothing. The two worked examples in the source repository (password reset, medication tracker) are at feature scale, not app scale, and that's deliberate.
For a whole product, the practical shape is two things:
The cross-cutting inventory is a shared vocabulary the
feature-level maps inherit from, not a separate map with its own
re-entry specifications. If a cross-cutting condition is
in scope for a feature, its re-entry specification
lives with the feature that renders it.
Write one sentence about what the system is as an object that exists over time, not what it does for the user.
A feature-framed sentence (a meeting invite helps people schedule a time to meet) generates no states because helps schedule is an activity, not a condition. A structural sentence generates states from its verbs and time-bearing nouns.
Test for done Three to five distinct states fall out of the nouns and verbs. Then read the sentence to a colleague unfamiliar with the product; if they can name three distinct conditions without prompting, you're done.
Raw material If a draft stalls, answer five questions about the system before rewriting: what exists when nobody is looking, and what windows or deadlines govern it (time); what gets created and what can happen to it before it ends (lifecycle); whether the process leaves the product and comes back (channels); what may have changed between start and finish (completion differences); where it shows itself beyond the primary screen (surfaces). The answers are ingredients for the sentence, not the sentence. On an existing codebase the same questions are answered from structural evidence: schedulers and expiries, status enums, outbound senders, session handling, routes and templates.
Common slips Feature-framing leaks in (helps the user). Flow-framing leaks in (first X, then Y). The sentence reads well but yields nothing.
When an agent drafts the sentence it presents the sentence with a line or two on why it works, and waits for you to confirm or adjust before any states are listed or written down. The sentence anchors everything downstream; it is yours to sign off, same as triage.
List states across four categories. Each category has its own line of questioning.
Conditions during normal operation. Derived from the sentence's verbs and time-bearing nouns. Expect 8–15.
Design work is a rendered rejection at the moment of action: link expired, password fails policy, server error.
Design work is a re-entry specification on return: tab closed, app backgrounded, time passed, device switched.
States of the system presenting itself on a surface: email HTML, watch complication, screen reader, push notification.
Coverage check Before you stop, run the list against the sentence: every structural term (each underlined verb and time-bearing noun) generates at least one active state; every active state has an explicit answer, or an explicit none, to the failure question and the interruption questions; every surface you listed maps to at least one surface state. A term that generates nothing is either decorative — rewrite the sentence — or hiding states you haven't found yet.
When a category yields a thin list, the following elicitation patterns help. Use them in this order on new work, in any order on existing work.
From the system sentence, underline verbs and time-bearing nouns. Each verb has a before, during, just-after. Each time-bearing noun has within, before, after.
→ Active states.For each active state, push past generic failures (validation error) to second-order ones (link already used, password matches old).
→ Failure states.For each active state, what happens if the user closes the tab, backgrounds the app, drops the network?
→ Interruption states.What's true of this state fifteen minutes from now? Two hours? A day? A week?
→ Interruption states (and sometimes failure states).List every surface the system reaches the user on. For each, identify which active states render on it.
→ Surface states.For harder cases: incident archaeology, multi-actor read, UI inversion, the "and then what?" drill.
Triage each state into one of three scope tags. Engineering and product input is high-value here.
Designed in this iteration.
Not designed now, but has consequences for in-scope work. Annotate each with a one-line note describing the implication.
Not designed, no current implication. Documented so it's not rediscovered later.
Test for done Every state has a tag. No state is unmarked.
Triage is your call, even when a tool drafts it. An agent recommends a scope per state with a one-line rationale and then stops; it doesn't commit scope autonomously, and it doesn't move on to step 4 until you have triaged. Automation proposes, you dispose.
For each in-scope active state, write specifications for behaviour under re-entry: the state entered from a context other than the canonical one.
What does the user see if they return after time has passed?
What does the user see if they arrive from a notification, deep link, or different device?
What does the user see if they arrive without the preceding state having been shown?
What does the user see if the underlying data has changed since they last saw this state?
What does the user see if they arrive during or after a failure in the system?
Re-entry conditions compose. A state re-entered after time has passed and on a different device and after a data change is one specification that must remain coherent under all three, not three independent ones.
Common slips Treating re-entry as a single "returning user" variant. Treating it as copy work. Omitting Q4 (data changed) and Q5 (prior failure) — the most commonly skipped and the most production-incident-producing.
You now have a state map: every state, scoped, with re-entry specifications on the in-scope active ones. What you do with it is your choice.
state-map.json mirror.
Optional. For teams that want machine validation, codegen, or a
contract with downstream tooling.
The method produces understanding. What you deliver from that understanding is a separate decision.
STATEFUL.md STATEFUL.md is a small markdown file the skills (and
any practitioner) produce and update in the working directory. It's
the persistent working memory of the method on a project.
# Stateful working memory
Last updated: <date>
## System sentence
<one sentence, structural>
## Surface(s) in scope
- `<path>`: <one-line description>
## State list
<summary of category counts>
## Triage
In: <n> · Out-with-implication: <n> · Out: <n>
## Re-entry specs
- <state-id>: <count> applicable variants
Optional. Its value compounds across sessions: the second time you run a skill in the same project, the agent has context.
Two annotations that pay off on cross-functional projects and existing-product audits.
Which layers must change to implement or remediate this state?
fe Frontend. Surface, presentation, client-side state. be Backend. Service, business logic, computation. dm Data-model. Schema, persistence, history. inf Infrastructure. OS, push delivery, network, device. The source of a rejection. Independent of how the failure renders.
user-input User-input. What the user provided. Coach to a valid configuration. system System. Internal error or bug. We're on it, plus retry. external External. Dependency failed. Name the dependency. policy Policy. Deliberate business rule. Explain without apologising. A medication tracker walked through all four steps, with layers and cause annotated. 52 states, 45 in-scope.