How a run moves · 5

From idea to launch

This page is the mental model of a whole run (that is: one site being taken from nothing to live), for someone who has never watched one. A site passes through five phases: decide, design, build, test, ship. For each phase it shows who works, what they leave on disk, and what the gate (that is: the program site-step, which runs the checks and decides whether a step is finished) checks before the next phase may begin. The step-by-step tables are on The workflow, step by step; the states a run can be in are on Life-cycle of a run.

Four names for who does the work, because the page uses all four. The agent is the AI assistant working in a Claude Code session; it drives the run. A skill is a written set of instructions the agent follows for one creative step, such as the brief or the review. When the agent follows a skill, we call it that step's actor. When it only runs commands and lets the machine judge, we call it the orchestrator. Same agent, different hats.

Why it matters

An agent can build a website in an afternoon. The same agent will tell you the site is accessible, fast and legal, and it will be wrong about at least one of those. The site still looks finished.

The machine exists so you never have to take that word. Every phase ends in a check that code can run, and the next phase does not open until the check is green. Understanding the phases lets you predict where a run will stop, why, and what the fix is. A refusal (that is: the gate saying no) stops being a mystery.

The mental model in one sentence

The one idea

A site is a sequence of fifteen claims, each proven by a program before the next claim may be made; the agent makes the claims true, and only the gate says they are.

Everything below elaborates that sentence. "Phase" is a reading aid — the machine knows only the fifteen steps in workflow.yaml and which step requires which. Those relationships are the arrows in the pipeline diagram further down. The phases group those steps by what kind of work happens in them.

The gate cycle: how every step closes

Before the phases, the loop that runs inside each one. It is the same for every step, whether the step takes a minute or a day.

The gate cycle: the agent asks site-step next, starts a step, works while two hooks record the ledger and guard deploys, then runs site-step done, which either closes the step or halts the run.
One step, start to finish. Green: the step closes and the next opens. Red: a predicate refused, the run halts, the agent fixes and tries the same step again. Open the diagram at full size.

Four things to notice, because every phase depends on them:

The five phases, named

The diagram below is the whole pipeline with the predicates each step runs. Blue boxes are steps where a skill does creative work. White boxes are steps where the orchestrator (that is: the agent driving the run) runs commands and the machine judges. The pen marks the two steps a human signs. In words: the skill steps are brief, design, scaffold, ux-review, commercial-review, publish-preview, legal-check and publish-live; the two signed steps are commercial-review and legal-check.

The pipeline as a directed graph: preflight, brief, repo, mwg-install, design, scaffold and build in a chain; then security, flows, ux-review and ship-check in parallel; commercial-review; publish-preview; legal-check; publish-live.
Fifteen steps. An arrow means "requires". Open the diagram at full size. The complete picture, which also shows the three places state lives (the machine, the site, the operator), is architecture.svg.
PhaseStepsWhat exists afterwardsWho does the work
1 Decidepreflight, brief, repo, mwg-installbrief.md, a private repo, Modern Web Guidance installed and pinnedthe site-brief skill, then the orchestrator
2 Designdesign, scaffoldtokens.css, declared colour pairs, a project that buildsdesign-system, site-scaffold
3 Buildbuildevery page implemented; the ledger proves guidance came firstthe orchestrator
4 Testsecurity, flows, ux-review, ship-check, commercial-reviewa frozen flow, a review, three ballots, a measurement; the phase ends when commercial-review closesorchestrator, ux-review, commercial-jury, the owner
5 Shippublish-preview, legal-check, publish-livea preview URL, a legal inventory, the live domainsite-publish, legal-check, a legal reviewer

Phase 1 — Decide: preflight, brief, repo, guidance

Claim. Most bad websites are bad because nobody decided what they were for. So the first phase produces a decision, not code: one page, brief.md, that names the single action a visitor should take.

How it goes. The run opens with preflight, which runs the doctor (that is: a check of the machine the build will run on). It confirms Node, Chrome, a logged-in gh (GitHub's command-line tool), a logged-in wrangler (Cloudflare's deploy tool) and a current operator attestation. The attestation is a record, renewed yearly, in which a named person confirms two-factor login on both accounts and a review of the deploy token's permissions. A machine that cannot finish a build is refused before the build starts. Then the site-brief skill interviews you, one question at a time, with a recommended answer. It searches whatever prior material exists before it asks. It pins seven things:

It also records what is out of scope, and whether any AI-generated likeness is involved.

What the gate checks. brief-complete.mjs parses the file: every required field non-empty, and exactly one primary action. Two equal calls to action fail the step, because a page with two equal buttons converts on neither. Then repo asks GitHub, not the agent, whether the site's repository is private. Finally mwg-install copies Modern Web Guidance (that is: Google Chrome's maintained set of current web-platform practice, packaged as a skill the agent searches before building anything) into the site's repo and pins its version in skills-lock.json. The version is read out of the installed skill; the tool refuses to invent one.

So what. When a run stalls in this phase, the fix is a decision, not a file. Ask what the visitor should do. If the answer has an "and" in it, the brief is not done.

Phase 2 — Design: tokens, pairs, a scaffold that builds

Claim. Colour, type and spacing are decided once, as tokens, before a single page exists. The contrast of those tokens is proven in both colour schemes before anyone may use them.

How it goes. The design-system skill searches Modern Web Guidance first, which the ledger records. It creates one Claude Design project for this site (Claude Design is Anthropic's design tool; the tokens are exported from that project) and writes src/styles/tokens.css. Each colour token uses light-dark(), a CSS function that carries a light and a dark value in one token. Nothing is shared between sites; the guidance is the shared knowledge, not the code. Then it declares which text token meets which background token, through site-context.mjs design, the only writer of site-context.json. A stylesheet does not say which colours ever meet on screen; the declaration does.

What the gate checks. contrast.mjs resolves both themes from the CSS and demands 4.5:1 for every declared pair. The usual allowance of lower contrast for large text does not apply, because a token gets reused at sizes nobody predicted. A coverage rule refuses a declaration that leaves a colour token out, so the cheapest way past the checker is closed. design-project.mjs confirms the recorded project still exists and is editable. Then site-scaffold stands up Astro with TypeScript. It brings a base layout, canonical and Open Graph tags, a JSON-LD stub, sitemap, robots, favicon and a 404 page. The tokens are imported once and the routes declared. The step closes when npm run build exits 0.

So what. The most common halt here is one pair a few tenths short in dark mode. The fix is the token, not the check. Declaring the routes now is what makes phase 3 auditable: the build must produce exactly the declared pages, no more, no fewer.

Phase 3 — Build: pages with guidance in front of them

Claim. The build step is where most refusals happen, and each one is a to-do line. Its exit proves two different things: that current guidance was consulted before every component, and that every route renders clean in a real browser.

How it goes. The orchestrator implements the pages. Before writing a new component, it runs npx modern-web-guidance search for the thing it is about to build. The site-log hook records that search as an mwg_search line, and every file write as a write line. At the end, done build serves dist/ and opens every declared route in headless Chrome. It never uses the dev server, which carries a hot-reload socket and unminified output the live site never has.

What the gate checks. First the ledger claim: for every component on disk, a guidance search must precede its first write. A component the ledger never saw is unproven, and the message names the uninstalled hook as the likely cause. Then ten predicates run on every route:

So what. An empty result is never a pass here. Every route carries proof it really loaded: a status, a complete document, something rendered. A route or scheme that never ran is refused rather than skipped. Treat the FAIL lines as the list, fix, and run done build again.

Phase 4 — Test: four checks in parallel, then a jury

Claim. Once the site builds clean, the pipeline fans out into four independent checks: defences, the critical flow, honesty, speed. It joins again only after three blind scorers and the owner have said the site is worth paying for.

How it goes. The four can run in any order:

Then commercial-review. The commercial-jury skill puts screenshots of every route in front of three blind scorers. They are separate agent sessions, or people, that have not seen the brief or each other's ballots, and they score eleven strategic dimensions from 1 to 5. jury.mjs reads the ballots and checks their shape: three distinct scorer names, the same eleven dimensions on every ballot, whole numbers from 1 to 5. It computes the median per dimension; every median must reach 3. Then the owner signs, by name, with site-step sign commercial-review --by "Name". The skill never fills in a score itself.

So what. This phase separates the floor from the ceiling. Everything mechanical is the floor: fast, accessible, honest. The jury and the owner are the ceiling: would a stranger who lands here understand what the page wants and do it? A 100 Lighthouse score is the entry price, not the product.

Self-check: which of the four parallel checks rests on a judgement rather than a measurement?

Only ux-review, and the judgement is the skill's, not a person's. Even there it is corroborated: the scanner refuses a review that the build contradicts. The other three, security, flows and ship-check, are decided entirely by code. The first human judgement comes after all four, in the owner's sign-off on commercial-review.

Phase 5 — Ship: preview, legal inventory, live

Claim. A deploy is a thing you did. A step closes on what is true afterwards, measured against the live origin. This is where the temptation to loosen a check is strongest, and it is the phase the machine was built for.

How it goes. publish-preview requires ship-check, commercial-review and security; commercial-review in turn required flows and ux-review, so all of phase 4 is behind it. The site-publish skill deploys dist/ to Cloudflare Pages on the preview branch. It then declares three things no predicate can discover: the preview URL; the site's mail posture (that is: a declaration of whether the domain sends mail at all, and from where), because a domain that never sends mail must say so or anyone can spoof it; and licences.json, an entry with source, licence and proof for every licensable asset. Then legal-check runs on that live preview, and publish-live moves the site to its own domain.

What the gate checks.

So what. Edit one caption before launch and publish-live refuses, because the receipt now describes an older build. That is freshness (that is: the rule that a record about a build must be newer than the build) working as designed: run verify-receipt.mjs audit again, then done publish-live. You never edit a predicate to make a deploy pass. Either the site is wrong or the check is wrong. If the check is wrong, the run stops and the check is fixed first, in its own commit, with its own test. It is never edited just to get this deploy through.

After launch: monthly re-verification

Every gate above answers at publish time. The most common way a live site goes wrong afterwards is "verified once, drifted since". tools/reverify.mjs is the answer, and it is deliberately not a step. Run monthly, it repeats the checks that look at the live site, for every site: the domain, DNS, security.txt, the consent behaviour against the real origin. It writes a report under the site's .claude/state/reverify/. Drift is reported in both directions, a pass turning into a fail and a fail turning back into a pass, because a check that flips back and forth hides if only one direction is reported. It refuses nothing, sets no halt and does not advance the run: a drift finding is a report, and the gate belongs to that site's next real step.

Common misconceptions

"The skills run the pipeline."

The skills are prose for seven creative steps. The pipeline is workflow.yaml, read by site-step.mjs. When the two disagree, the YAML wins, because the YAML is what the gate reads.

The gate runs the pipeline.

A skill does a step's work and files its testimony. Whether the step is done is decided by the exit predicates, and only by them.

"A passing step means the site is good."

Fourteen of the fifteen steps prove a floor: fast, accessible, honest, legal elements present. None of them can tell whether a stranger would act on the page.

A passing step means one claim is proven.

"Good" is the ceiling, and it is decided by the jury and the owner in commercial-review, on purpose the one place the verdict is human.

"A halt means something is broken."

Four halts in an ordinary run is normal: a token a shade too light, a missing favicon, a policy that does not name the host. Each is lifted by evidence, not by explanation.

A halt is the machine doing its job.

The refusal prints the reason and the remedy. Fix, rebuild, run the same step again. The one thing a halt never accepts is a more confident report.

"The preview passed security, so the live headers are fine."

Step security reads files on disk, _headers among them. A host can silently drop a declared header, and a file check cannot see that.

Declared and sent are two different checks.

publish-preview fetches the live URL and proves the CSP was sent. That is why both steps exist and why passing one is no evidence for the other.

The same run, seen by phase

The photographer's site from Life-cycle of a run, compressed to the five phases. The full walk lists every command; this view shows where the phases start and end.

  1. Decide, one hour. The doctor passes. The brief interview settles on "book a shoot" as the one action, after the owner first wanted booking and a newsletter. brief-complete.mjs finds one primary action. The repo is private on GitHub; the guidance is pinned.
  2. Design, one hour, one halt. The tokens are written and four pairs declared. The caption colour is 4.1:1 in dark mode; the run halts; the token is darkened; the step closes. The scaffold builds.
  3. Build, two hours, one halt. Two guidance searches precede the gallery and the booking dialog, so the ledger claim holds. console-clean finds a missing favicon on every route. Fixed, closed.
  4. Test, one hour, no halt. Headers declared, dependencies clean. The booking flow freezes and replays green. Thirty-one verdicts filed. Five Lighthouse runs, median 96, spread 3, well inside the limit of 5. Three blind scorers: lowest median 3. The owner signs.
  5. Ship, one hour, two halts. The preview sends noindex and a CSP; twelve photos are in the licence register. legal.mjs finds the privacy policy does not name Cloudflare, which the hosting declaration does. Halt, text fixed, redeployed, re-observed; a reviewer signs. One caption edited before launch makes the receipt stale: audit rerun, then live. Fifteen of fifteen.

Six hours, four halts, none of them a judgement call. The agent never marked anything done; it only made the predicates true.

Reference card

The sentence

A site is a sequence of fifteen claims, each proven by a program before the next claim may be made; the agent makes the claims true, and only the gate says they are.

PhaseEnds whenTypical haltThe fix is
Decidebrief.md names one action; repo private; guidance pinnedtwo primary actionsa decision
Designevery colour pair ≥ 4.5:1 in both themes; npm run build exits 0one pair short in dark modea token
Buildledger proves guidance first; ten predicates green on every routea console error, an axe findingthe page
Testdefences declared, flow replays, review corroborated, median in budget, jury ≥ 3, owner signsa pattern the review missedthe pattern, then a fresh review
Shippreview sends noindex + CSP; legal elements present and signed; domain live, receipt fresh, DNS sanea stale receipt, a policy missing a processorre-audit, or the text

Numbers that matter: 15 steps, 23 predicate programs (listed on the Architecture page), 7 skills, 31 mandatory patterns, 3 blind scorers scoring 11 dimensions to a floor of 3, 5 Lighthouse runs to a median, 4.5:1 contrast in both themes, 2 human sign-offs, 1 monthly re-verify.

Self-check: without looking up, what are the two things the build step proves, and what proves each?

That guidance was consulted before every component — proven from the ledger, never from a claim. And that every declared route renders clean — proven by ten predicates driving a real Chrome over dist/.

Next steps

To watch one of these phases happen, follow Drive a run, which walks the commands with a check after each. To see what every predicate in a phase actually inspects, read the tables on The workflow, step by step. To learn what a specific file or folder in the diagrams is for, Architecture names every one.