Workflow
workflows/README.md defines it in one sentence:
A workflow is a pre-composed chain of operators: an ordered list of steps, each step a list of branches that run in parallel (at most three), with optional loops back to an earlier step and presets for a branch’s Requirements.
The nine files in workflows/ are references, not the only chains there are: they are the shapes
that came up often enough to be worth writing down.
How the entry uses them
The entry reads the when of every example. A full match is run as written; its presets fill
request.json, and the person is asked only for fields with no default. When the match is partial,
or the business is harder than any when describes, the entry composes its own chain from the
operators’ ## Next tables and routing.json rather than bending a near-miss example into shape,
under the same rules scripts/validate-workflows.mjs enforces on these files:
- every branch names a real operator and presets only fields that operator declares;
- every Requirements field with no Default is preset or listed under the branch’s
asks, so the chain declares which fields the entry takes from the mission scope or asks a person for before that branch starts; - every required Input of a branch is produced by an earlier step;
- branches of one step share no write alias — two operators may not write the same checkout or root
at once, and
frontend.surface.auditfans out by matrix entry because it writes nothing; - a loop goes back to an earlier step and carries
maxRounds; - a chain that writes frontend source under
mode: applyrunsfrontend.surface.auditanduat.verifybetween that write and itsgit.publish; - the chain ends at
git.publish,release.deploy, oruser.
A composed chain that would be useful again becomes a new file, with its when.
Every delivery chain is a long flow
A chain that writes a surface is not finished when the source compiles. Between the write and the
publish stand two proofs nothing else in the tree supplies: frontend.surface.audit, which renders
the surface and keeps the screenshots, and uat.verify, which walks a real person’s journey through
it. quality.verify sits between them and answers a different question — build, lint, types,
coverage — and green gates do not notice that a page reads wrong. Every example that applies frontend
source therefore ends the same way:
frontend.source.apply → workspace.bind (role fe, runtimeNeed consume) → frontend.surface.audit → quality.verify → uat.verify → git.publishThe second workspace.bind is there because the head moved: the surface served, audited and walked
is the one the write just produced. uat.verify needs requestedBy, feature and flow, so every
chain carrying it declares them under asks. backend-feature is the one delivery chain with
neither proof, and its when says why: it writes no surface, and uat.verify requires a
frontend-surface-audit input and a bound fe route.
A chain may also prove a delivery somewhere other than where it was written. staging-uat writes
nothing — its frontend.source.apply runs under mode: dry, so the long-flow law does not reach it —
and it presets env on the audit and the run. That field selects one stack of the installation: its
runtime registry entry, its accounts file, its seed target and its approved reference. An environment
that names no stack under .stacks/ is refused at the gate rather than defaulted, and the chain ends
at user, because two receipts in a person’s hands are the outcome; reaching an environment stays
release’s job.
The file shape
schemaVersion is 9. id equals the file name. when has en and vi. chain is an array of
steps, each an array of
{ operator, requirements?, asks?: [field], fanout?: "matrix", maxParallel?: 1..3 }. loops
is an array of { from, to, when, maxRounds }. ends is user or an operator of the last step.
Branches and the session
Nothing is designed, written or committed outside a session: state.json and
step-1/parallel-1/request/request.json exist, and validate-request is green on them, before any
file outside the session folder is read in order to change it or written. Every source-writing branch
commits on session/<sessionId>; git.publish merges it, and refuses a session branch whose session
carries no source-application receipt and no audit screenshots (SESSION_MISSING). A blocked branch
re-enters as a new step, and a loop counts toward the operator’s own maxRounds.
The nine examples, with their chains rendered step by step, are under Reference → Workflows.