Line

You are reading docs for v0.8. See latest (v0.9)

Internals

Workflow narrator

State machines to plain English, scenarios and health checks.

Construct reads the real XState machines in a feature's workflows/ folder and explains them in English, with no LLM and nothing stored. The diagram, the English, the scenarios and the guardrails are all derived from the same source file every time, so they can never disagree with each other or with the code.

Why it matters: a flow described in a document goes stale the day someone edits the code. Here the description is the code, re-read on every request. A product owner can read the English, a tester can lift the scenarios, a reviewer can see the health findings, and an engineer still edits the one source file.

What you get, per machine#

  • In plain English: what each state does, in source order. Identifiers become words (paymentFailed becomes "payment failed", isLowValue becomes "it is low value"), guards become "only if ...", actions become "and then runs notifyCustomer", delays become "After 48 hours", services become "starts issueRefund".
  • 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.

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.

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/.

Limits#

Only machines written as plain object literals are explained (the same limit as the diagram); others say why they cannot be. Parallel regions and history states are treated as ordinary states. Guards and actions are named, not explained: the English says "it is low value", it does not read the function body.

Where the code lives#

packages/engine/workflowNarrator.mjs (English), workflowScenarios.mjs (scenarios and findings), workflowExplain.mjs (one call + text renderers), workflowSource.mjs (path-scoped file access for the CLI); UI in ui/client/features/workflows, endpoint GET /api/workflows/narrative.