Construct
Explain workflows in English
Turn state machines into readable steps and test scenarios.
Construct reads the real XState machines in a feature's workflows/ folder and explains them in plain English, with every start-to-end scenario and any problems it can spot. Nothing is stored, so the explanation cannot go stale.
Use it#
CLI (read-only):
construct research workflow <feature> [<file>] [--format prose|md|json|scenarios] [--dir <path>]
<file> is relative to features/<feature>/workflows/; leave it out to explain every workflow file.
--format json prints pure JSON that can be piped.
UI: the Workflows screen shows the same three panels ("In plain English", "Scenarios", "Health") under each diagram. They refresh on load, on "Re-read from source" and right after a confirmed visual edit.
Guardrails: construct validate reports WORKFLOW-002 (unreachable state) and WORKFLOW-003 (non-final
state with no way out) as warnings for workflow files it can read. Set them to error or off under
rules: in architecture.yml.
What you get, per machine#
- In plain English: what each state does, in source order. Identifiers become words (
paymentFailedbecomes "payment failed",isLowValuebecomes "it is low value"), guards become "only if ...", actions become "and then runsnotifyCustomer", delays become "After 48 hours", services become "startsissueRefund". - Scenarios: every distinct route from the start to an end state as Given/When/Then, happy path first (the shortest route to the first end state). Loops are shown once as "this part can repeat"; output is capped at 25 scenarios. Each scenario also has a machine-readable form (event sequence, steps, end state).
- Health: unreachable states, dead ends, no end state, conditional transitions with no fallback, two unguarded transitions on one event, and targets that do not exist.
Real output#
construct research workflow shop CheckoutWorkflow.tsx, for a workflow generated by
construct create workflow Checkout --feature shop --from fixtures/workflow-graphs/checkout.json:
Checkout
The "checkout" flow has 3 steps. It starts in *idle* and can end in *done*.
Idle
- This flow starts in *idle*.
- When "submit" happens, the flow moves to *submitting*.
Submitting
- When "success" happens, the flow moves to *done*.
- When "failure" happens, the flow moves to *idle* — only if it has error.
Done
- *done* is an end state — the flow stops there.
Scenarios
Happy path
Route: idle → submitting → done
Given the flow starts in *idle*
When "submit" happens
Then the flow moves to *submitting*
And when "success" happens
Then the flow moves to *done*
And the flow ends — *done* is an end state
Note: from *submitting* the flow can go back to *idle* when "failure" happens (only if it has error), so this part can repeat.
Health
- [no-fallback] In *submitting*, "failure" only applies under a condition (it has error) and there is no fallback, so if none holds, nothing happens.
A richer example (guards, a 48 hour timeout, a retry loop, two end states) is
fixtures/workflow-graphs/refund-request.ts; its exact expected output is in
fixtures/workflow-graphs/golden/.