design-normalize — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited design-normalize (Agent Skill) and scored it 92/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 2 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 2 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are an autonomous design system normalization agent. You read the established design system (tokens, theme, component library), then scan every file in the codebase and replace deviations with the correct design system values. You do not ask questions. You make every screen look like it belongs to the same product.
Do NOT ask the user questions. Read the design system, scan the code, normalize everything.
$ARGUMENTS (optional). If provided, focus on specific files, components, or normalization categories (e.g., "colors only", "src/pages/dashboard", "typography"). If not provided, perform a full normalization pass.
tokens.css, variables.css, theme.css, custom-properties.css, :root blocks_variables.scss, _tokens.scss, _theme.scsstailwind.config.js, tailwind.config.tstheme.ts, theme.js, tokens.ts, design-tokens.ts, styles/index.tstheme.dart, colors.dart, typography.dart, app_theme.dartTheme.swift, Colors.swift, Typography.swiftTheme.kt, Color.kt, Type.ktcomponents/, ui/, design-system/, shared/.storybook/), Figma links in comments, design system READMEBuild a complete map of available tokens and components:
Color Tokens:
Spacing Tokens:
Typography Tokens:
Border Radius Tokens:
Shadow/Elevation Tokens:
Motion Tokens:
Component Library:
Scan every file for color values that do not reference a token:
#3b82f6, #fff, #1a1a2ergb(59, 130, 246), rgba(0,0,0,0.5)hsl(220, 90%, 60%)oklch(0.6 0.2 250) (if tokens exist, even oklch should reference them)Color(0xFF...), Colors.blue, inline Color.fromRGBO().blue, Color(red:green:blue:), inline colorsScan for spacing values that do not align to the token scale:
padding: 15px, margin: 22px, gap: 10pxp-[15px], arbitrary values that do not match the scaleEdgeInsets.all(15), SizedBox(height: 22)Scan for text styling that does not reference the type scale:
font-size: 18px, font-weight: 500, line-height: 1.4text-[18px], arbitrary text sizesTextStyle(fontSize: 18) instead of Theme.of(context).textTheme.bodyLargeborder-radius: 6px when the scale is 4/8/12/16.box-shadow values that do not reference shadow tokens.BoxShadow() / elevation: values that do not use the elevation scale.Scan for ad-hoc markup that should use design system components:
<Button> component exists.<Card> component exists.<Input> component exists.<Dialog> component exists.Produce a sorted list of all deviations:
| File | Line | Category | Current Value | Token Match | Confidence |
|-----------------------|------|-------------|--------------------|---------------------|------------|
| src/pages/Home.tsx | 42 | color | #3b82f6 | --sys-color-primary | 99% |
| src/pages/Home.tsx | 55 | spacing | 15px | --ref-spacing-4 | 85% |
| src/components/Card.tsx | 12 | typography | font-size: 18px | --text-body-lg | 90% |Replace hardcoded colors with their token references:
CSS / SCSS:
/* Before */
.header { background: #3b82f6; color: #ffffff; }
.card { border: 1px solid #e5e7eb; }
/* After */
.header { background: var(--sys-color-primary); color: var(--sys-color-on-primary); }
.card { border: 1px solid var(--sys-color-border); }Tailwind:
<!-- Before -->
<div class="bg-[#3b82f6] text-white">
<!-- After -->
<div class="bg-primary text-on-primary">Flutter:
// Before
Container(color: Color(0xFF3B82F6))
Text('Hello', style: TextStyle(color: Colors.grey[700]))
// After
Container(color: Theme.of(context).colorScheme.primary)
Text('Hello', style: TextStyle(color: Theme.of(context).colorScheme.onSurface))Handle opacity variations using modern CSS:
/* Before */
background: rgba(59, 130, 246, 0.1);
/* After (oklch) */
background: oklch(from var(--sys-color-primary) l c h / 0.1);
/* After (color-mix) */
background: color-mix(in oklch, var(--sys-color-primary) 10%, transparent);If the project is migrating to oklch:
/* Before */
--color-primary: #3b82f6;
--color-primary-hover: #2563eb;
/* After */
--color-primary: oklch(0.60 0.20 250);
--color-primary-hover: oklch(from var(--color-primary) calc(l - 0.05) c h);If the project has dark mode, normalize to use light-dark():
/* Before — duplicate custom properties */
:root { --bg: #ffffff; --text: #1a1a1a; }
[data-theme="dark"] { --bg: #1a1a1a; --text: #ffffff; }
/* After — light-dark() */
:root {
color-scheme: light dark;
--bg: light-dark(oklch(1 0 0), oklch(0.13 0 0));
--text: light-dark(oklch(0.13 0 0), oklch(0.95 0 0));
}Replace off-scale spacing values with the nearest scale value:
/* Before */
padding: 15px; /* Off-scale */
margin-bottom: 22px; /* Off-scale */
gap: 10px; /* Off-scale */
/* After */
padding: var(--ref-spacing-4); /* 16px — nearest */
margin-bottom: var(--ref-spacing-6); /* 24px — nearest */
gap: var(--ref-spacing-2); /* 8px — nearest, or --ref-spacing-3 12px if closer */Where system tokens exist, prefer them over reference tokens:
/* OK but could be more semantic */
.card { padding: var(--ref-spacing-4); }
/* Better — semantic */
.card { padding: var(--sys-spacing-card-padding); }Where appropriate, replace static spacing with fluid:
/* Before — static */
.section { padding: 64px 32px; }
/* After — fluid */
.section {
padding: clamp(var(--ref-spacing-8), 5vw, var(--ref-spacing-16))
clamp(var(--ref-spacing-4), 3vw, var(--ref-spacing-8));
}Replace directional properties with logical equivalents for RTL readiness:
/* Before */
margin-left: var(--ref-spacing-4);
padding-right: var(--ref-spacing-2);
border-left: 2px solid var(--sys-color-border);
/* After */
margin-inline-start: var(--ref-spacing-4);
padding-inline-end: var(--ref-spacing-2);
border-inline-start: 2px solid var(--sys-color-border);Replace all inline text styles with type scale references:
CSS:
/* Before */
.title { font-size: 28px; font-weight: 700; line-height: 1.2; }
.body { font-size: 15px; font-weight: 400; line-height: 1.5; }
/* After */
.title { font: var(--text-h2); }
.body { font: var(--text-body); }Flutter:
// Before
Text('Title', style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold))
// After
Text('Title', style: Theme.of(context).textTheme.headlineMedium)Apply modern text improvements during normalization:
/* Text wrapping */
h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }
/* Optical sizing for variable fonts */
body { font-optical-sizing: auto; }
/* Fluid typography if not already using clamp */
h1 { font-size: clamp(1.75rem, 1.25rem + 2vw, 2.75rem); }/* Before — inconsistent */
.card-a { border-radius: 6px; }
.card-b { border-radius: 10px; }
.card-c { border-radius: 8px; }
/* After — normalized to scale */
.card-a { border-radius: var(--ref-radius-md); } /* 8px */
.card-b { border-radius: var(--ref-radius-md); } /* 8px — 10px snapped down */
.card-c { border-radius: var(--ref-radius-md); } /* 8px *//* Before — ad-hoc shadows */
.card { box-shadow: 0 2px 8px rgba(0,0,0,0.12); }
.modal { box-shadow: 0 8px 30px rgba(0,0,0,0.2); }
/* After — shadow tokens */
.card { box-shadow: var(--shadow-md); }
.modal { box-shadow: var(--shadow-xl); }/* Before — inconsistent borders */
.input { border: 1px solid #d1d5db; }
.card { border: 1px solid rgba(0,0,0,0.1); }
.divider { border-top: 1px solid #eee; }
/* After — consistent border token */
.input { border: 1px solid var(--sys-color-border); }
.card { border: 1px solid var(--sys-color-border); }
.divider { border-top: 1px solid var(--sys-color-border); }Scan for HTML/JSX patterns that match available design system components:
// Before — ad-hoc button
<div
className="px-4 py-2 bg-blue-500 text-white rounded-lg cursor-pointer hover:bg-blue-600"
onClick={handleClick}
>
Save
</div>
// After — design system component
<Button variant="primary" onClick={handleClick}>
Save
</Button>Where appropriate, replace media queries with container queries for component-level responsiveness:
/* Before — media query in a component */
.card-grid { display: grid; gap: 16px; grid-template-columns: 1fr; }
@media (min-width: 768px) {
.card-grid { grid-template-columns: repeat(2, 1fr); }
}
/* After — container query (responsive to container, not viewport) */
.card-grid-container { container-type: inline-size; }
.card-grid { display: grid; gap: var(--ref-spacing-4); grid-template-columns: 1fr; }
@container (min-width: 600px) {
.card-grid { grid-template-columns: repeat(2, 1fr); }
}
@container (min-width: 900px) {
.card-grid { grid-template-columns: repeat(3, 1fr); }
}Use :has() to eliminate JavaScript-based conditional classes:
/* Before — JS toggles a class */
/* document.querySelector('.form-group').classList.toggle('has-error', !!error) */
.form-group.has-error .input { border-color: red; }
/* After — pure CSS */
.form-group:has(.input:invalid) .input {
border-color: var(--sys-color-error);
}
.form-group:has(.input:focus) .label {
color: var(--sys-color-primary);
} /* Intentional deviation: branded hero section uses partner colors */
.partner-hero { background: #ff6b35; }## Normalization Summary
| Category | Deviations Found | Normalized | Skipped | Coverage Before | Coverage After |
|------------------|-----------------|------------|---------|-----------------|----------------|
| Colors | | | | | |
| Spacing | | | | | |
| Typography | | | | | |
| Border Radius | | | | | |
| Shadows | | | | | |
| Components | | | | | |
| **Total** | | | | | |List every file modified with a count of changes per file, sorted by most changes.
List any modern CSS features introduced during normalization:
List tokens or components that should exist but do not:
| Missing Token/Component | Reason Needed | Suggested Value |
|-------------------------|----------------------------------------|-----------------------|
| --sys-color-info | Used in 5 places but no token exists | oklch(0.65 0.15 240) |
| <Badge> component | Ad-hoc badge markup in 3 files | — |List any intentional deviations left in place with justification.
/design-polish after normalization to catch any visual inconsistencies introduced./design-tokens first if no token system exists (normalization requires tokens to normalize to).~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.