System

new-validator

One rule, held by the build

The new-validator skill is a checklist the coding agent follows to turn a rule written in prose into a script the build runs. Once the script is in the chain, breaking the rule stops the build. Below are the steps, then one real validator traced from the files it reads to the result a build sees. The full skill file is on Skills.

The steps

  1. Study the references
    Read the Registries section of CLAUDE.md, then one script of each shape: validate-doc-refs.mjs on its own, the generate-component-md.mjs pair, and validate-rendered-spacing.mjs for built HTML.
  2. Decide the shape
    A validator checks a rule and fails the build. A generator writes a derived file and gets a validator that holds the file to its source. A countable fact usually wants a registry as well.
  3. Decide where it runs
    What the script reads decides the slot. Source files go in the chain that runs before every build. Built HTML goes after the website build. A check against an earlier release needs the git tags. Anything that reads the network runs by hand, in no chain.
  4. Makes the scriptWrite the doc block
    The script opens with its filename, what it guards and why a failure matters, and why it runs where it runs. Any exception lives there or in a named constant beside it, with a reason a stranger could check.
  5. Follow the house conventions
    Collect every error before exiting, and make each one name its fix. Normalise Windows line endings once, on the read. Build paths from the script’s own location and compare them with forward slashes.
  6. For a generator, compare bytes
    The generator exports its assemble function and writes only when run directly. Its validator regenerates in memory and compares with the file on disk, so a hand edit or a stale file fails.
  7. Makes the chain entryWire it in
    Add it to validate-registry in the root package.json, generators ahead of validators. A website check also joins website/package.json. A post-build check joins verify and CI in the same change.
  8. Makes the CLAUDE.md lineClose the loop and prove it fails
    Give the rule its line in CLAUDE.md. Run the script, break the rule on purpose to see the message, restore it, then run the whole chain. A check that cannot be made to fail is not guarding anything.

A hex code, end to end

A hex code like #1A2B3C may live in one file, tokens-primitives.css. Every other tier reaches it through a token, so a theme can swap the value in one place. Two validators hold that line. validate-token-references.mjs fails a semantic token written as a hex instead of a var(). validate-raw-values.mjs reads every stylesheet the package ships and fails a hex in component CSS. Say one is typed into a component’s stylesheet. The next build fails with the file, the line and the value, and says what to do: use the token that owns it, or mark it ds-allow(color) with a reason when it is deliberately off the scale.

1 · In the repowhere a hex may and may not go
2 · The chainroot package.json
3 · What runs the chainevery build starts here
4 · The resultprinted by the script
Primitivestokens-primitives.css · the hex lives here
Semantic tokenstokens-light.css · tokens-dark.css · var() only
Component CSSsrc/components/ · src/chat/ · tokens only
ds-allow(color)a deliberate exception, with its reason
Token referencesscripts/validate-token-references.mjs
Raw valuesscripts/validate-raw-values.mjs
validate-registryprebuild · prestorybook · prebuild-storybook
Website prebuildwebsite/package.json · leaves both out
npm run verifythe local mirror of CI
CI library jobnpm run build
CI Storybook jobnpm run build-storybook
Passone ✓ line with the count checked
Failfile:line · the value · the fix
Build stopsnothing ships
var()a hex herea hex fails it
One file may hold a hex; a hex anywhere else stops the build with the fix named.

Where a hex may live

Each tier has one answer, and a script holds it. A var() fallback is a consumer’s override hook, so the raw values check reads past it.

Where a hex code may live, and what holds each rule
WhereHeld byA hex there
Primitives file
The tier rule itself
Allowed
Semantic token
validate-token-references.mjs
Fails
Component CSS
validate-raw-values.mjs
Fails
Component CSS under ds-allow(color)
validate-raw-values.mjs
Sanctioned
A var() fallback
validate-raw-values.mjs
Sanctioned