Reference

Command reference

Every command, run from your site-machine clone, with the line that tells you it worked. <site-dir> is always the site's directory. Exit codes are uniform: 0 accepted, 1 refused, 2 usage or spec error.

The gate

node tools/site-step.mjs status <site-dir>
node tools/site-step.mjs next   <site-dir>
node tools/site-step.mjs start  <site-dir> <step> [--actor <name>]
node tools/site-step.mjs done   <site-dir> <step> [--note "…"] [--evidence <path>]
node tools/site-step.mjs block  <site-dir> <step> --blocker <id> --reason "<20+ chars>" [--evidence <path>]
node tools/site-step.mjs sign   <site-dir> <step> --by "<name>" [--note "…"]
CommandSuccess prints
statusOne line per step (OK, BLK, ... or blank), then N done · N blocked · N in progress · N open (of 15).
next<step> [<actor>] per ready step — or the HALTED — block.
startstarted <step> [<actor>]
done ok <label>: <detail> per predicate, then closed <step>. On refusal: cannot close <step>: N exit predicate(s) failed and the halt block on stderr.
blockblocked <step> — <blocker>
sign<step> signed by <name> (<role>) and a reminder to run done.

Preflight and attestation

node tools/doctor.mjs [<site-dir>]
node tools/attest.mjs record --by "<name>" --two-factor --token-scopes "<what was reviewed>"
node tools/attest.mjs show

Doctor: five ok lines and preflight ok — 5/5 checks passed (preflight.json written). Attest: attested — <name>, <date> (expires in a year; preflight will re-ask).

Declarations

node tools/site-context.mjs init     <site-dir> [--profile site|app] [--client] [--ai-feature] [--ai-chatbot]
node tools/site-context.mjs design   <site-dir> --project-id <id> --pair "--text-body on --surface-page"   # text token on background token, as named in tokens.css
node tools/site-context.mjs routes   <site-dir> / /about /impressum /404
node tools/site-context.mjs mail     <site-dir> --sends true|false
node tools/site-context.mjs urls     <site-dir> --live https://example.de --preview https://x.pages.dev/
node tools/site-context.mjs hosting  <site-dir> --processor <name> --outside-eu true|false
node tools/site-context.mjs show     <site-dir>

Also verify, processor, bfsg, legal, edge, jurisdiction. This is the only writer of site-context.json; edit the file by hand and the next predicate that reads it may refuse the shape.

Evidence writers

node tools/mwg-install.mjs install <site-dir>
node tools/mwg-install.mjs verify  <site-dir>
node tools/measure.mjs <site-dir> <url> [--runs N]
node tools/jury.mjs dimensions
node tools/jury.mjs record <site-dir> ballots.json
node tools/publish.mjs probe <site-dir> [--step publish-preview]
node scripts/verify-receipt.mjs audit <site-dir> <url>
node scripts/verify-receipt.mjs check <site-dir>
node scripts/verify-receipt.mjs waive <site-dir> "why"
node tools/reverify.mjs --sites-root <dir> [--site <name>]
CommandSuccess prints
mwg-install install ok modern-web-guidance <version> installed at .agents/skills/modern-web-guidance and the lock line with a tree hash.
mwg-install verifymodern-web-guidance is installed and matches its lock
measure the floor holds — median <n>, spread <n> across 5 runs. Needs an existing run-state.json and something serving the URL.
jury recordPer-dimension medians, then the jury holds — all 11 dimension(s) at or above 3, median of 3 scorers. A malformed filing writes nothing.
publish probePer-route ok, then PASS — N route(s) at <url> — all of: x-robots-tag: noindex | content-security-policy: default-src.
verify-receipt auditA scorecard and PASS — receipt written. Safe to claim done.
verify-receipt checkNothing; exit 0.

Dry-running a predicate

Any predicate runs by hand and writes no state. Useful while fixing, before the next done:

node tools/predicates/contrast.mjs <site-dir>
node tools/predicates/ux-review.mjs <site-dir>
node tools/predicates/security.mjs <site-dir>

Developing the machine

npm run verify        # tsc --noEmit + node --test (63 files)
npm test
npm run typecheck

CI runs on Ubuntu without Chrome, gh or wrangler, so the browser predicates skip themselves there. CI green is not the same as a first run being green — run the doctor on a real machine.

Common misconceptions

"The skills enforce the order."

Skills are prose; an agent can read them out of order or not at all.

The gate enforces the order.

workflow.yaml is read by site-step.mjs, and done re-checks prerequisites every time. Tests pin the skill prose to the code, not the other way round.

"Signing off closes the step."

A person approved it, so it is done.

Signing records a person; done closes.

The signature is one predicate. The jury medians or the legal checks still have to pass in the same done.

"No ledger records means nothing went wrong."

An empty log is a clean log.

No records means unproven.

Components on disk that the ledger never saw written are violations. The likeliest cause is a session without the hooks, and the message says so.

"A passing predicate means the site is secure / compliant."

security.mjs said all defences are in place.

A passing predicate means what it printed.

"Declared, not proven live"; "required elements present". The live header check and the human reviewer exist because the file check cannot see further.

"The jury's aggregate score is what counts."

File a record saying the average was 4.

The ballots count.

Medians are computed from three distinct scorers' ballots on the identical rubric. An asserted aggregate is never read.

"Editing a file re-opens the steps after it."

Status will show what needs redoing.

Nothing re-opens by itself.

Freshness bites when a step is run again: ux-review, the jury and the receipt refuse if older than the newest source file. publish-live re-checks the receipt for you; the others you re-run.

Reference card

The site machine on one screen

Model: a gate — steps in a fixed order, each closed only by code verifying evidence on disk; the writer never certifies.

Parts: workflow.yaml (15 steps) · site-step.mjs (the gate) · 23 predicates · 7 actor skills · 2 hooks (log, guard) · the ledger · the receipt.

Loop: next → do the step → done. Refusal = halt; lifted only by succeeding on the same step. Escape only via a validated blocker with evidence.

State: in the site root and <site>/.claude/state/; operator state in ~/.local/state/site-machine/; nothing in the plugin.

Numbers: perf ≥ 0.90 · a11y 1.0 · LCP ≤ 2.5 s · CLS ≤ 0.1 · TBT ≤ 200 ms · ≤ 150 kB script · contrast 4.5:1 both schemes · 5 Lighthouse runs, spread ≤ 5 · jury 3 scorers, 11 dimensions, median ≥ 3 · receipt valid 24 h · 31 mandatory patterns · attestation yearly.

Rules of thumb: restart after installing · never open the plugin repo as the project when building · ${MACHINE} is YAML-only · a predicate says what it saw, never "secure" or "compliant".