DEV Community

Sherotree
Sherotree

Posted on

Freeze design tokens the agent may not edit — allowlist only

Ask an agent to “tighten spacing on the checkout header” and watch the diff: three lines in the header component… and a surprise edit to --space-3 in the shared tokens file because “4px felt closer.”

That token change ripples through every surface that referenced --space-3. The header looks fine. The settings page quietly compresses. Nobody asked for a design-system RFC.

I’ve started freezing token files by default for agent UI work. The agent may consume tokens. It may edit component files on an allowlist. It may not rewrite the shared scale unless the prompt explicitly opens that door.

What “freeze” means in practice

Three layers, boring on purpose:

  1. Default deny — token / theme modules are read-only for agent sessions
  2. Allowlist — only named component paths may change
  3. Explicit unlock — a human prompt (or a separate PR) is required to touch tokens

Example constraints block:

UI change only. Read-only paths (do not modify):
- src/styles/tokens.css
- src/styles/theme/*.css
- tailwind.config.* / @theme blocks that define the shared scale
- packages/design-tokens/**

Allowlist (edit only these):
- src/features/checkout/CheckoutHeader.tsx
- src/features/checkout/CheckoutHeader.module.css

If the design cannot be achieved without a new token, stop and propose the token
change in plain language — do not edit token files in this PR.
Enter fullscreen mode Exit fullscreen mode

The “stop and propose” line is the escape hatch. Agents that are blocked tend to invent one-off hexes or arbitrary Tailwind values. You want a written proposal, not a silent scale rewrite.

Why agents reach for tokens

Shared tokens look like the “right” abstraction. Models have seen countless posts that say “put spacing in the theme.” So when a one-off gap feels wrong, they “fix the system” instead of the component.

Sometimes a token change is correct — after an RFC, with screenshots, across breakpoints. That work deserves its own PR title and reviewers. Bundling it under “header polish” hides blast radius.

Review gates that catch thawing

In the PR template

## Token / theme files
- [ ] No changes under tokens / theme / design-tokens
- [ ] If a token change is required: link the RFC / design thread and keep it in a separate commit or PR
Enter fullscreen mode Exit fullscreen mode

In CI (lightweight)

  • Fail (or warn loudly) when tokens.css / design-tokens change unless the PR label is tokens / design-system
  • Or require an OWNERS-style approval for those paths

In human review

Open the files changed list first. If a “small UI tweak” touches the scale, send it back before you debate the header padding.

Reject / send back

Reject

  • Edits to shared spacing / color / type scales inside a feature PR
  • Renaming or removing tokens “nobody uses” without a repo-wide grep receipt
  • Adding a new token and using it only once in the same PR without calling that out
  • “Temporary” hardcoded values in the token file to match a mock

Accept

  • Component-only diffs that reference existing tokens
  • A written proposal for a token change, deferred to a follow-up
  • A dedicated tokens PR with before/after on more than one surface
  • Documented allowlist escapes for legacy theme files you already planned to delete

Allowlist patterns that work

Keep the allowlist paths, not vibes:

  • Feature folder for the task (src/features/checkout/**)
  • The specific stories file if Storybook is in scope
  • Explicitly exclude **/tokens*, **/theme*, **/*.config.* that own the scale

Monorepo tip: allow apps/web/... but freeze packages/ui/tokens. Agents love “helpfully” normalizing the package everyone imports.

If you use Tailwind v4 @theme or a JS theme module, freeze those the same way you freeze CSS variables — the file format doesn’t change the blast radius.

Tiny habit

Next agent UI prompt, paste a freeze block: token paths read-only, component paths allowlisted, “propose don’t edit” if the scale is wrong. When the draft still touches tokens.css, don’t negotiate in the diff — restore the freeze and ask for a one-paragraph token proposal instead. Feature PRs should consume the system, not redefine it mid-flight.

Top comments (0)