Harness Design Web
Token-bound web component generation. Scaffold from design tokens and aesthetic intent, implement with Tailwind/CSS and React/Vue/Svelte patterns, and verify every value references the token set — no hardcoded colors, fonts, or spacing.
When to Use
- Generating new web components that must conform to the project's design system tokens
- When
on_new_feature triggers fire with web UI scope requiring token-bound component generation
- When
on_commit triggers fire and new components contain hardcoded design values that should reference tokens
- Implementing design intent from
design-system/DESIGN.md into concrete Tailwind classes, CSS custom properties, or CSS-in-JS theme values
- Converting mockups or wireframes into token-bound component code for React, Vue, or Svelte
- NOT for generating design tokens themselves (use harness-design-system)
- NOT for establishing aesthetic direction or anti-patterns (use harness-design)
- NOT for accessibility auditing (use harness-accessibility)
- NOT for mobile platform components (use harness-design-mobile)
Process
Phase 1: SCAFFOLD — Read Tokens, Detect Framework, Plan Structure
Read design tokens. Load design-system/tokens.json (W3C DTCG format). Extract:
- Color tokens: primary, secondary, accent, neutral ramps, semantic colors (success, warning, error, info)
- Typography tokens: heading and body font families, font weights, font sizes, line heights
- Spacing tokens: spacing scale values (xs through 2xl or equivalent)
- If
design-system/tokens.json does not exist, stop and instruct the user to run harness-design-system first.
Read design intent. Load design-system/DESIGN.md for:
- Aesthetic direction (style, tone, differentiator) from harness-design output
- Anti-patterns to avoid (e.g., "no gradients on data elements," "no decorative borders")
- Platform-specific web notes (CSS strategy preferences, animation guidelines, responsive behavior)
- If
design-system/DESIGN.md does not exist, warn the user and proceed with tokens only. Recommend running harness-design for richer output.
Check harness configuration. Read harness.config.json for:
design.strictness — enforcement level (strict, standard, permissive). Default to standard.
design.platforms — confirm web is in the platforms list.
design.tokenPath — custom token path (default: design-system/tokens.json).
Detect web framework. Scan the project for:
- React:
package.json contains react or next dependency, .tsx/.jsx files exist
- Vue:
package.json contains vue or nuxt dependency, .vue files exist
- Svelte:
package.json contains svelte or @sveltejs/kit, .svelte files exist
- Vanilla: No framework detected, output plain HTML/CSS
- If the user specified
--framework, use that override.
Detect CSS strategy. Scan for:
- Tailwind:
tailwind.config.* exists, @tailwind directives in CSS, class= with Tailwind utility patterns
- CSS Modules:
.module.css or .module.scss files exist
- CSS-in-JS:
styled-components, @emotion/styled, stitches imports detected
- Vanilla CSS: Global
.css/.scss files with no module or utility pattern
- If the user specified
--cssStrategy, use that override.
Load platform-specific web rules. Read agents/skills/shared/design-knowledge/platform-rules/web.yaml for web-specific design rules including responsive breakpoints, browser compatibility considerations, and CSS best practices.
Load anti-pattern definitions. Read anti-pattern files from agents/skills/shared/design-knowledge/anti-patterns/:
typography.yaml — typographic anti-patterns (too many fonts, inconsistent scales)
color.yaml — color anti-patterns (hardcoded hex, insufficient contrast)
layout.yaml — layout anti-patterns (magic numbers, inconsistent spacing)
motion.yaml — motion anti-patterns (excessive animation, missing reduced-motion)
Build token-to-CSS mapping. Create a lookup table that maps each token to its CSS representation based on the detected strategy:
- Tailwind:
color.primary.500 maps to text-primary-500 / bg-primary-500 (requires tailwind.config theme extension)
- CSS custom properties:
color.primary.500 maps to var(--color-primary-500)
- CSS-in-JS:
color.primary.500 maps to theme.color.primary[500]
Plan component structure. For the requested component(s), define:
- Component file path(s) following project conventions
- Props interface / type definition
- Which tokens will be consumed (colors, typography, spacing)
- Responsive behavior (breakpoints, layout changes)
- Present the scaffold plan to the user before proceeding.
Phase 2: IMPLEMENT — Generate Token-Bound Components
Generate framework-specific component code. Based on detected framework:
React (TSX):
- Functional component with TypeScript props interface
- All color values reference tokens (via Tailwind classes, CSS variables, or theme object)
- All typography values reference tokens (font family, weight, size from token set)
- All spacing values reference tokens (padding, margin, gap from spacing scale)
- Export component with display name
Vue (SFC):
- Single File Component with
<script setup lang="ts">
- Props defined with
defineProps and TypeScript interface
- Scoped styles reference CSS custom properties mapped from tokens
- Template uses token-derived classes or inline styles via CSS variables
Svelte:
- Component with TypeScript
<script lang="ts">
- Props exported with
export let declarations
- Styles reference CSS custom properties mapped from tokens
- Reactive declarations for computed style values
Vanilla HTML/CSS:
- Semantic HTML structure
- CSS custom properties for all design values
- No inline styles with hardcoded values
Generate CSS strategy artifacts. Based on detected CSS strategy:
Tailwind:
- Extend
tailwind.config theme with token values (if not already present)
- Map tokens to Tailwind utility classes in components
- Use
@apply sparingly — prefer utility classes in markup
- Generate token-to-Tailwind mapping comment block at top of component
CSS Custom Properties:
- Generate
:root declarations for all consumed tokens
- Components reference
var(--token-name) exclusively
- No hardcoded hex, rgb, hsl, or font values in component styles
CSS-in-JS:
- Generate theme object from tokens
- Components consume theme via provider/hook pattern
- All style values reference theme properties
Apply design intent constraints. For each generated component:
- Check against anti-patterns from
design-system/DESIGN.md and agents/skills/shared/design-knowledge/anti-patterns/
- Enforce style guidelines (e.g., minimal style means no decorative effects)
- Apply tone-appropriate color usage (e.g., cool tone means no warm accents in neutral UI)
- Respect platform-specific web notes (animation preferences, responsive behavior)
Add USES_TOKEN annotations. Insert comments in generated code documenting which tokens are consumed:
/* @design-token color.primary.500 — primary action background */
/* @design-token typography.heading.fontFamily — section heading */
/* @design-token spacing.md — card internal padding */
These annotations enable the knowledge graph to create USES_TOKEN edges from this component to the consumed DesignToken nodes.
Phase 3: VERIFY — Check Token Binding and Design Constraints
Scan for hardcoded values. Use Grep to search generated files for:
- Hardcoded color values: hex (
#[0-9a-fA-F]{3,8}), rgb(), hsl(), named colors
- Hardcoded font families:
font-family: declarations not referencing tokens
- Hardcoded spacing: pixel/rem values in margin/padding/gap not from the token scale
- Each finding is a violation: the component uses a value not bound to a token.
Verify token coverage. For every design value in the generated component:
- Confirm it resolves to a token in
design-system/tokens.json
- Confirm the token path is valid (e.g.,
color.primary.500 exists in the token tree)
- Report orphan references (token annotations pointing to non-existent tokens)
Check anti-pattern compliance. Cross-reference generated code against anti-patterns declared in design-system/DESIGN.md and the anti-pattern definitions in agents/skills/shared/design-knowledge/anti-patterns/:
- Grep for patterns matching each declared anti-pattern
- Flag violations with file path, line number, and the specific anti-pattern violated
Query the knowledge graph. If a graph exists at .harness/graph/:
- Use
DesignIngestor to verify DesignToken nodes exist for all referenced tokens
- Verify
PLATFORM_BINDING edges exist for web platform tokens
- Use
DesignConstraintAdapter to check for VIOLATES_DESIGN edges
- Report any constraint violations with severity based on
design.strictness
Assign severity based on designStrictness:
permissive — all findings are info
standard — hardcoded values and anti-pattern violations are warn, accessibility violations are error
strict — hardcoded values are error (blocks), anti-pattern violations are warn, accessibility violations are error
Report verification results. Present:
WEB-001 [warn] Hardcoded color #3b82f6 — should reference token "color.primary.500"
File: src/components/Button.tsx:12
Fix: Replace with Tailwind class "bg-primary-500" or var(--color-primary-500)
WEB-002 [info] Anti-pattern: gradient on card background
File: src/components/MetricCard.tsx:28
Fix: Use solid background from token "color.neutral.50"
Run harness validate. After verification, run project-level validation to confirm the new components integrate cleanly.
Harness Integration
harness validate — Run after generating components to verify project health. New files must not break existing constraints.
harness scan — Run after component generation to update the knowledge graph with new USES_TOKEN edges from generated components to consumed tokens.
DesignIngestor (packages/graph/src/ingest/DesignIngestor.ts) — Verifies that DesignToken nodes exist for all tokens referenced by generated components. If tokens are missing from the graph, run harness scan to re-ingest.
DesignConstraintAdapter (packages/graph/src/constraints/DesignConstraintAdapter.ts) — Checks for VIOLATES_DESIGN edges during the VERIFY phase. Reports constraint violations at the configured strictness level.
harness-design-system — Dependency. This skill reads tokens generated by harness-design-system. If tokens do not exist, instruct the user to run harness-design-system first.
harness-design — Dependency. This skill reads aesthetic intent from harness-design output (design-system/DESIGN.md). Anti-pattern enforcement and style constraints come from the design intent document.
harness-impact-analysis — When tokens change, impact analysis traces which components consume affected tokens via USES_TOKEN edges. Use this to identify components that need regeneration after token updates.
Graph naming convention: This skill uses PascalCase for node types (DesignToken, DesignConstraint) and UPPER_SNAKE for edge types (USES_TOKEN, PLATFORM_BINDING, VIOLATES_DESIGN) as conceptual labels. The graph schema registers these as snake_case identifiers (design_token, design_constraint, uses_token, platform_binding, violates_design). The adapter classes (DesignIngestor, DesignConstraintAdapter) handle the mapping — always use the adapters rather than constructing graph queries with raw type names.
Success Criteria
- Generated components reference design tokens exclusively — no hardcoded color, font, or spacing values
- Framework detection correctly identifies React, Vue, Svelte, or vanilla projects
- CSS strategy detection correctly identifies Tailwind, CSS Modules, CSS-in-JS, or vanilla CSS
- Token-to-CSS mapping produces correct output for each CSS strategy (Tailwind classes, CSS custom properties, theme object references)
@design-token annotations are present for every consumed token
- Anti-pattern compliance check catches violations declared in
design-system/DESIGN.md
- Verification report uses severity levels matching
design.strictness configuration
harness validate passes after component generation
Examples
Example: React + Tailwind Button Component
Context: SaaS dashboard project. React with Tailwind CSS. Tokens generated by harness-design-system. Design intent established by harness-design (minimal style, cool professional tone).
SCAFFOLD output:
Framework detected: React (Next.js)
CSS strategy: Tailwind CSS (tailwind.config.ts)
Tokens loaded: 42 tokens from design-system/tokens.json
Design intent: Minimal, cool professional (from DESIGN.md)
Component plan: Button with primary/secondary/ghost variants
Token consumption: color.primary.*, color.neutral.*, typography.body, spacing.sm/md
IMPLEMENT output (Button.tsx):
/* @design-token color.primary.500 — primary variant background */
/* @design-token color.primary.700 — primary variant hover */
/* @design-token color.neutral.50 — ghost variant background */
/* @design-token color.neutral.900 — ghost variant text */
/* @design-token typography.body.fontFamily — button label */
/* @design-token typography.body.fontWeight — button label weight */
/* @design-token spacing.sm — button horizontal padding */
/* @design-token spacing.xs — button vertical padding */
import type { ButtonHTMLAttributes } from 'react';
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary' | 'ghost';
size?: 'sm' | 'md' | 'lg';
}
export function Button({
variant = 'primary',
size = 'md',
className = '',
children,
...props
}: ButtonProps) {
const baseClasses =
'inline-flex items-center justify-center font-body font-medium rounded-md transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500';
const variantClasses = {
primary: 'bg-primary-500 text-white hover:bg-primary-700',
secondary: 'border border-primary-500 text-primary-700 hover:bg-primary-50',
ghost: 'text-neutral-900 hover:bg-neutral-100',
};
const sizeClasses = {
sm: 'px-spacing-sm py-spacing-xs text-sm',
md: 'px-spacing-md py-spacing-sm text-base',
lg: 'px-spacing-lg py-spacing-md text-lg',
};
return (
<button
className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}
{...props}
>
{children}
</button>
);
}
VERIFY output:
Verification Results
--------------------
Hardcoded values: PASS (0 hardcoded colors, fonts, or spacing)
Token coverage: PASS (8/8 referenced tokens exist in tokens.json)
Anti-pattern check: PASS (no gradients, no decorative borders)
Design constraints: PASS (no VIOLATES_DESIGN edges)
Harness validate: PASS
Example: Vue + CSS Custom Properties Card Component
Context: E-commerce project. Vue 3 with CSS custom properties. Tokens from harness-design-system.
IMPLEMENT output (ProductCard.vue):
<!-- @design-token color.neutral.50 — card background -->
<!-- @design-token color.neutral.200 — card border -->
<!-- @design-token color.neutral.900 — card text -->
<!-- @design-token typography.heading.fontFamily — product title -->
<!-- @design-token typography.body.fontFamily — product description -->
<!-- @design-token spacing.md — card padding -->
<!-- @design-token spacing.sm — content gap -->
<script setup lang="ts">
interface Props {
title: string;
description: string;
price: string;
imageUrl: string;
imageAlt: string;
}
defineProps<Props>();
</script>
<template>
<article class="product-card">
<img :src="imageUrl" :alt="imageAlt" class="product-card__image" />
<div class="product-card__content">
<h3 class="product-card__title">{{ title }}</h3>
<p class="product-card__description">{{ description }}</p>
<span class="product-card__price">{{ price }}</span>
</div>
</article>
</template>
<style scoped>
.product-card {
background: var(--color-neutral-50);
border: 1px solid var(--color-neutral-200);
border-radius: var(--radius-md);
overflow: hidden;
}
.product-card__content {
padding: var(--spacing-md);
display: flex;
flex-direction: column;
gap: var(--spacing-sm);
}
.product-card__title {
font-family: var(--typography-heading-fontFamily);
font-weight: var(--typography-heading-fontWeight);
color: var(--color-neutral-900);
}
.product-card__description {
font-family: var(--typography-body-fontFamily);
color: var(--color-neutral-700);
}
</style>
Rationalizations to Reject
| Rationalization |
Reality |
| "The tokens file doesn't exist yet, but I know the brand colors — I'll hardcode them as a placeholder and note they should be replaced later." |
Hardcoded values in generated output are the exact problem this skill exists to prevent. There is no placeholder exception. If design-system/tokens.json does not exist, instruct the user to run harness-design-system first and stop. |
| "The framework is obviously React — everything in this project is React. I don't need to run detection." |
Detection also identifies the CSS strategy (Tailwind vs CSS Modules vs CSS-in-JS), which determines how tokens map to code. Skipping detection produces components that may reference non-existent Tailwind classes or wrong theme paths. |
| "The user hasn't confirmed the scaffold plan, but the component structure is straightforward — I'll just generate it." |
The scaffold plan confirmation is a gate. The user must see which tokens will be consumed and what the component structure will be before code is written. Generating first and explaining later inverts the review opportunity. |
| "This component only uses one hardcoded hex value for a shadow — that's not really a design value, so I'll leave it." |
Every color, font, and spacing value must reference a token. Shadows use color tokens. "Not really a design value" is not a category the verification phase recognizes. The VERIFY phase will flag it; the IMPLEMENT phase should not introduce it. |
"The @design-token annotations are just comments — skipping them on a few components won't affect anything." |
These annotations are how harness scan creates USES_TOKEN edges in the knowledge graph. Missing annotations mean harness-impact-analysis cannot trace token changes to affected components. They are structural metadata, not decorative comments. |
Gates
These are hard stops. Violating any gate means the process has broken down.
- No component generation without reading tokens from harness-design-system. The SCAFFOLD phase requires
design-system/tokens.json to exist. If tokens have not been generated, instruct the user to run harness-design-system first. Do not generate components with hardcoded values as a fallback.
- No hardcoded design values in generated output. Every color, font, and spacing value must reference a token. If a needed token does not exist, instruct the user to add it via harness-design-system rather than hardcoding the value.
- No framework-specific code without framework detection. The SCAFFOLD phase must detect or receive the target framework before generating components. Do not guess or default to React.
- No generation without scaffold plan confirmation. The SCAFFOLD phase must present a component plan to the user. Do not generate code without the user confirming the structure and token consumption plan.
- No graph mutations without validating node types. When creating
USES_TOKEN or PLATFORM_BINDING edges, verify the node and edge types are registered in the graph schema before writing.
Escalation
- When
design-system/tokens.json does not exist: Instruct the user: "Design tokens have not been generated. Run harness-design-system first to create design-system/tokens.json, then re-run harness-design-web for token-bound component generation."
- When the project uses an undetected framework: Ask the user to specify via the
--framework CLI argument. Log: "Could not auto-detect web framework. Please specify: harness skill run harness-design-web --framework react|vue|svelte|vanilla."
- When tokens are insufficient for the requested component: Report which tokens are missing: "Component requires a
color.accent.500 token but it does not exist in tokens.json. Run harness-design-system to add the missing token, or choose an existing alternative." Do not hardcode a fallback.
- When anti-patterns conflict with the requested design: Present the conflict: "The requested gradient background violates the 'no gradients on data elements' anti-pattern from DESIGN.md. Options: (1) Remove the gradient and use a solid token color, (2) Update the anti-pattern list via
harness-design if the intent has changed."
- When the knowledge graph is unavailable: Skip graph operations in SCAFFOLD and VERIFY phases. Log: "Graph not available at
.harness/graph/ — skipping token node verification and USES_TOKEN edge creation. Run harness scan later to populate." Continue with file-based operations.
1---2name: harness-design-web3description: Harness Design Web4---5# Harness Design Web67> Token-bound web component generation. Scaffold from design tokens and aesthetic intent, implement with Tailwind/CSS and React/Vue/Svelte patterns, and verify every value references the token set — no hardcoded colors, fonts, or spacing.89## When to Use1011- Generating new web components that must conform to the project's design system tokens12- When `on_new_feature` triggers fire with web UI scope requiring token-bound component generation13- When `on_commit` triggers fire and new components contain hardcoded design values that should reference tokens14- Implementing design intent from `design-system/DESIGN.md` into concrete Tailwind classes, CSS custom properties, or CSS-in-JS theme values15- Converting mockups or wireframes into token-bound component code for React, Vue, or Svelte16- NOT for generating design tokens themselves (use harness-design-system)17- NOT for establishing aesthetic direction or anti-patterns (use harness-design)18- NOT for accessibility auditing (use harness-accessibility)19- NOT for mobile platform components (use harness-design-mobile)2021## Process2223### Phase 1: SCAFFOLD — Read Tokens, Detect Framework, Plan Structure24251. **Read design tokens.** Load `design-system/tokens.json` (W3C DTCG format). Extract:26 - Color tokens: primary, secondary, accent, neutral ramps, semantic colors (success, warning, error, info)27 - Typography tokens: heading and body font families, font weights, font sizes, line heights28 - Spacing tokens: spacing scale values (xs through 2xl or equivalent)29 - If `design-system/tokens.json` does not exist, stop and instruct the user to run `harness-design-system` first.30312. **Read design intent.** Load `design-system/DESIGN.md` for:32 - Aesthetic direction (style, tone, differentiator) from harness-design output33 - Anti-patterns to avoid (e.g., "no gradients on data elements," "no decorative borders")34 - Platform-specific web notes (CSS strategy preferences, animation guidelines, responsive behavior)35 - If `design-system/DESIGN.md` does not exist, warn the user and proceed with tokens only. Recommend running `harness-design` for richer output.36373. **Check harness configuration.** Read `harness.config.json` for:38 - `design.strictness` — enforcement level (`strict`, `standard`, `permissive`). Default to `standard`.39 - `design.platforms` — confirm `web` is in the platforms list.40 - `design.tokenPath` — custom token path (default: `design-system/tokens.json`).41424. **Detect web framework.** Scan the project for:43 - **React:** `package.json` contains `react` or `next` dependency, `.tsx`/`.jsx` files exist44 - **Vue:** `package.json` contains `vue` or `nuxt` dependency, `.vue` files exist45 - **Svelte:** `package.json` contains `svelte` or `@sveltejs/kit`, `.svelte` files exist46 - **Vanilla:** No framework detected, output plain HTML/CSS47 - If the user specified `--framework`, use that override.48495. **Detect CSS strategy.** Scan for:50 - **Tailwind:** `tailwind.config.*` exists, `@tailwind` directives in CSS, `class=` with Tailwind utility patterns51 - **CSS Modules:** `.module.css` or `.module.scss` files exist52 - **CSS-in-JS:** `styled-components`, `@emotion/styled`, `stitches` imports detected53 - **Vanilla CSS:** Global `.css`/`.scss` files with no module or utility pattern54 - If the user specified `--cssStrategy`, use that override.55566. **Load platform-specific web rules.** Read `agents/skills/shared/design-knowledge/platform-rules/web.yaml` for web-specific design rules including responsive breakpoints, browser compatibility considerations, and CSS best practices.57587. **Load anti-pattern definitions.** Read anti-pattern files from `agents/skills/shared/design-knowledge/anti-patterns/`:59 - `typography.yaml` — typographic anti-patterns (too many fonts, inconsistent scales)60 - `color.yaml` — color anti-patterns (hardcoded hex, insufficient contrast)61 - `layout.yaml` — layout anti-patterns (magic numbers, inconsistent spacing)62 - `motion.yaml` — motion anti-patterns (excessive animation, missing reduced-motion)63648. **Build token-to-CSS mapping.** Create a lookup table that maps each token to its CSS representation based on the detected strategy:65 - **Tailwind:** `color.primary.500` maps to `text-primary-500` / `bg-primary-500` (requires `tailwind.config` theme extension)66 - **CSS custom properties:** `color.primary.500` maps to `var(--color-primary-500)`67 - **CSS-in-JS:** `color.primary.500` maps to `theme.color.primary[500]`68699. **Plan component structure.** For the requested component(s), define:70 - Component file path(s) following project conventions71 - Props interface / type definition72 - Which tokens will be consumed (colors, typography, spacing)73 - Responsive behavior (breakpoints, layout changes)74 - Present the scaffold plan to the user before proceeding.7576### Phase 2: IMPLEMENT — Generate Token-Bound Components77781. **Generate framework-specific component code.** Based on detected framework:7980 **React (TSX):**81 - Functional component with TypeScript props interface82 - All color values reference tokens (via Tailwind classes, CSS variables, or theme object)83 - All typography values reference tokens (font family, weight, size from token set)84 - All spacing values reference tokens (padding, margin, gap from spacing scale)85 - Export component with display name8687 **Vue (SFC):**88 - Single File Component with `<script setup lang="ts">`89 - Props defined with `defineProps` and TypeScript interface90 - Scoped styles reference CSS custom properties mapped from tokens91 - Template uses token-derived classes or inline styles via CSS variables9293 **Svelte:**94 - Component with TypeScript `<script lang="ts">`95 - Props exported with `export let` declarations96 - Styles reference CSS custom properties mapped from tokens97 - Reactive declarations for computed style values9899 **Vanilla HTML/CSS:**100 - Semantic HTML structure101 - CSS custom properties for all design values102 - No inline styles with hardcoded values1031042. **Generate CSS strategy artifacts.** Based on detected CSS strategy:105106 **Tailwind:**107 - Extend `tailwind.config` theme with token values (if not already present)108 - Map tokens to Tailwind utility classes in components109 - Use `@apply` sparingly — prefer utility classes in markup110 - Generate token-to-Tailwind mapping comment block at top of component111112 **CSS Custom Properties:**113 - Generate `:root` declarations for all consumed tokens114 - Components reference `var(--token-name)` exclusively115 - No hardcoded hex, rgb, hsl, or font values in component styles116117 **CSS-in-JS:**118 - Generate theme object from tokens119 - Components consume theme via provider/hook pattern120 - All style values reference theme properties1211223. **Apply design intent constraints.** For each generated component:123 - Check against anti-patterns from `design-system/DESIGN.md` and `agents/skills/shared/design-knowledge/anti-patterns/`124 - Enforce style guidelines (e.g., minimal style means no decorative effects)125 - Apply tone-appropriate color usage (e.g., cool tone means no warm accents in neutral UI)126 - Respect platform-specific web notes (animation preferences, responsive behavior)1271284. **Add USES_TOKEN annotations.** Insert comments in generated code documenting which tokens are consumed:129 ```130 /* @design-token color.primary.500 — primary action background */131 /* @design-token typography.heading.fontFamily — section heading */132 /* @design-token spacing.md — card internal padding */133 ```134 These annotations enable the knowledge graph to create `USES_TOKEN` edges from this component to the consumed `DesignToken` nodes.135136### Phase 3: VERIFY — Check Token Binding and Design Constraints1371381. **Scan for hardcoded values.** Use Grep to search generated files for:139 - Hardcoded color values: hex (`#[0-9a-fA-F]{3,8}`), `rgb()`, `hsl()`, named colors140 - Hardcoded font families: `font-family:` declarations not referencing tokens141 - Hardcoded spacing: pixel/rem values in margin/padding/gap not from the token scale142 - Each finding is a violation: the component uses a value not bound to a token.1431442. **Verify token coverage.** For every design value in the generated component:145 - Confirm it resolves to a token in `design-system/tokens.json`146 - Confirm the token path is valid (e.g., `color.primary.500` exists in the token tree)147 - Report orphan references (token annotations pointing to non-existent tokens)1481493. **Check anti-pattern compliance.** Cross-reference generated code against anti-patterns declared in `design-system/DESIGN.md` and the anti-pattern definitions in `agents/skills/shared/design-knowledge/anti-patterns/`:150 - Grep for patterns matching each declared anti-pattern151 - Flag violations with file path, line number, and the specific anti-pattern violated1521534. **Query the knowledge graph.** If a graph exists at `.harness/graph/`:154 - Use `DesignIngestor` to verify `DesignToken` nodes exist for all referenced tokens155 - Verify `PLATFORM_BINDING` edges exist for web platform tokens156 - Use `DesignConstraintAdapter` to check for `VIOLATES_DESIGN` edges157 - Report any constraint violations with severity based on `design.strictness`1581595. **Assign severity based on `designStrictness`:**160 - `permissive` — all findings are `info`161 - `standard` — hardcoded values and anti-pattern violations are `warn`, accessibility violations are `error`162 - `strict` — hardcoded values are `error` (blocks), anti-pattern violations are `warn`, accessibility violations are `error`1631646. **Report verification results.** Present:165166 ```167 WEB-001 [warn] Hardcoded color #3b82f6 — should reference token "color.primary.500"168 File: src/components/Button.tsx:12169 Fix: Replace with Tailwind class "bg-primary-500" or var(--color-primary-500)170171 WEB-002 [info] Anti-pattern: gradient on card background172 File: src/components/MetricCard.tsx:28173 Fix: Use solid background from token "color.neutral.50"174 ```1751767. **Run `harness validate`.** After verification, run project-level validation to confirm the new components integrate cleanly.177178## Harness Integration179180- **`harness validate`** — Run after generating components to verify project health. New files must not break existing constraints.181- **`harness scan`** — Run after component generation to update the knowledge graph with new `USES_TOKEN` edges from generated components to consumed tokens.182- **`DesignIngestor`** (`packages/graph/src/ingest/DesignIngestor.ts`) — Verifies that `DesignToken` nodes exist for all tokens referenced by generated components. If tokens are missing from the graph, run `harness scan` to re-ingest.183- **`DesignConstraintAdapter`** (`packages/graph/src/constraints/DesignConstraintAdapter.ts`) — Checks for `VIOLATES_DESIGN` edges during the VERIFY phase. Reports constraint violations at the configured strictness level.184- **`harness-design-system`** — Dependency. This skill reads tokens generated by harness-design-system. If tokens do not exist, instruct the user to run harness-design-system first.185- **`harness-design`** — Dependency. This skill reads aesthetic intent from harness-design output (`design-system/DESIGN.md`). Anti-pattern enforcement and style constraints come from the design intent document.186- **`harness-impact-analysis`** — When tokens change, impact analysis traces which components consume affected tokens via `USES_TOKEN` edges. Use this to identify components that need regeneration after token updates.187188**Graph naming convention:** This skill uses PascalCase for node types (`DesignToken`, `DesignConstraint`) and UPPER_SNAKE for edge types (`USES_TOKEN`, `PLATFORM_BINDING`, `VIOLATES_DESIGN`) as conceptual labels. The graph schema registers these as snake_case identifiers (`design_token`, `design_constraint`, `uses_token`, `platform_binding`, `violates_design`). The adapter classes (`DesignIngestor`, `DesignConstraintAdapter`) handle the mapping — always use the adapters rather than constructing graph queries with raw type names.189190## Success Criteria191192- Generated components reference design tokens exclusively — no hardcoded color, font, or spacing values193- Framework detection correctly identifies React, Vue, Svelte, or vanilla projects194- CSS strategy detection correctly identifies Tailwind, CSS Modules, CSS-in-JS, or vanilla CSS195- Token-to-CSS mapping produces correct output for each CSS strategy (Tailwind classes, CSS custom properties, theme object references)196- `@design-token` annotations are present for every consumed token197- Anti-pattern compliance check catches violations declared in `design-system/DESIGN.md`198- Verification report uses severity levels matching `design.strictness` configuration199- `harness validate` passes after component generation200201## Examples202203### Example: React + Tailwind Button Component204205**Context:** SaaS dashboard project. React with Tailwind CSS. Tokens generated by harness-design-system. Design intent established by harness-design (minimal style, cool professional tone).206207**SCAFFOLD output:**208209```210Framework detected: React (Next.js)211CSS strategy: Tailwind CSS (tailwind.config.ts)212Tokens loaded: 42 tokens from design-system/tokens.json213Design intent: Minimal, cool professional (from DESIGN.md)214Component plan: Button with primary/secondary/ghost variants215Token consumption: color.primary.*, color.neutral.*, typography.body, spacing.sm/md216```217218**IMPLEMENT output (Button.tsx):**219220```tsx221/* @design-token color.primary.500 — primary variant background */222/* @design-token color.primary.700 — primary variant hover */223/* @design-token color.neutral.50 — ghost variant background */224/* @design-token color.neutral.900 — ghost variant text */225/* @design-token typography.body.fontFamily — button label */226/* @design-token typography.body.fontWeight — button label weight */227/* @design-token spacing.sm — button horizontal padding */228/* @design-token spacing.xs — button vertical padding */229230import type { ButtonHTMLAttributes } from 'react';231232interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {233 variant?: 'primary' | 'secondary' | 'ghost';234 size?: 'sm' | 'md' | 'lg';235}236237export function Button({238 variant = 'primary',239 size = 'md',240 className = '',241 children,242 ...props243}: ButtonProps) {244 const baseClasses =245 'inline-flex items-center justify-center font-body font-medium rounded-md transition-colors focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary-500';246247 const variantClasses = {248 primary: 'bg-primary-500 text-white hover:bg-primary-700',249 secondary: 'border border-primary-500 text-primary-700 hover:bg-primary-50',250 ghost: 'text-neutral-900 hover:bg-neutral-100',251 };252253 const sizeClasses = {254 sm: 'px-spacing-sm py-spacing-xs text-sm',255 md: 'px-spacing-md py-spacing-sm text-base',256 lg: 'px-spacing-lg py-spacing-md text-lg',257 };258259 return (260 <button261 className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}262 {...props}263 >264 {children}265 </button>266 );267}268```269270**VERIFY output:**271272```273Verification Results274--------------------275Hardcoded values: PASS (0 hardcoded colors, fonts, or spacing)276Token coverage: PASS (8/8 referenced tokens exist in tokens.json)277Anti-pattern check: PASS (no gradients, no decorative borders)278Design constraints: PASS (no VIOLATES_DESIGN edges)279Harness validate: PASS280```281282### Example: Vue + CSS Custom Properties Card Component283284**Context:** E-commerce project. Vue 3 with CSS custom properties. Tokens from harness-design-system.285286**IMPLEMENT output (ProductCard.vue):**287288```vue289<!-- @design-token color.neutral.50 — card background -->290<!-- @design-token color.neutral.200 — card border -->291<!-- @design-token color.neutral.900 — card text -->292<!-- @design-token typography.heading.fontFamily — product title -->293<!-- @design-token typography.body.fontFamily — product description -->294<!-- @design-token spacing.md — card padding -->295<!-- @design-token spacing.sm — content gap -->296297<script setup lang="ts">298interface Props {299 title: string;300 description: string;301 price: string;302 imageUrl: string;303 imageAlt: string;304}305306defineProps<Props>();307</script>308309<template>310 <article class="product-card">311 <img :src="imageUrl" :alt="imageAlt" class="product-card__image" />312 <div class="product-card__content">313 <h3 class="product-card__title">{{ title }}</h3>314 <p class="product-card__description">{{ description }}</p>315 <span class="product-card__price">{{ price }}</span>316 </div>317 </article>318</template>319320<style scoped>321.product-card {322 background: var(--color-neutral-50);323 border: 1px solid var(--color-neutral-200);324 border-radius: var(--radius-md);325 overflow: hidden;326}327328.product-card__content {329 padding: var(--spacing-md);330 display: flex;331 flex-direction: column;332 gap: var(--spacing-sm);333}334335.product-card__title {336 font-family: var(--typography-heading-fontFamily);337 font-weight: var(--typography-heading-fontWeight);338 color: var(--color-neutral-900);339}340341.product-card__description {342 font-family: var(--typography-body-fontFamily);343 color: var(--color-neutral-700);344}345</style>346```347348## Rationalizations to Reject349350| Rationalization | Reality |351| ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |352| "The tokens file doesn't exist yet, but I know the brand colors — I'll hardcode them as a placeholder and note they should be replaced later." | Hardcoded values in generated output are the exact problem this skill exists to prevent. There is no placeholder exception. If `design-system/tokens.json` does not exist, instruct the user to run harness-design-system first and stop. |353| "The framework is obviously React — everything in this project is React. I don't need to run detection." | Detection also identifies the CSS strategy (Tailwind vs CSS Modules vs CSS-in-JS), which determines how tokens map to code. Skipping detection produces components that may reference non-existent Tailwind classes or wrong theme paths. |354| "The user hasn't confirmed the scaffold plan, but the component structure is straightforward — I'll just generate it." | The scaffold plan confirmation is a gate. The user must see which tokens will be consumed and what the component structure will be before code is written. Generating first and explaining later inverts the review opportunity. |355| "This component only uses one hardcoded hex value for a shadow — that's not really a design value, so I'll leave it." | Every color, font, and spacing value must reference a token. Shadows use color tokens. "Not really a design value" is not a category the verification phase recognizes. The VERIFY phase will flag it; the IMPLEMENT phase should not introduce it. |356| "The `@design-token` annotations are just comments — skipping them on a few components won't affect anything." | These annotations are how `harness scan` creates `USES_TOKEN` edges in the knowledge graph. Missing annotations mean harness-impact-analysis cannot trace token changes to affected components. They are structural metadata, not decorative comments. |357358## Gates359360These are hard stops. Violating any gate means the process has broken down.361362- **No component generation without reading tokens from harness-design-system.** The SCAFFOLD phase requires `design-system/tokens.json` to exist. If tokens have not been generated, instruct the user to run harness-design-system first. Do not generate components with hardcoded values as a fallback.363- **No hardcoded design values in generated output.** Every color, font, and spacing value must reference a token. If a needed token does not exist, instruct the user to add it via harness-design-system rather than hardcoding the value.364- **No framework-specific code without framework detection.** The SCAFFOLD phase must detect or receive the target framework before generating components. Do not guess or default to React.365- **No generation without scaffold plan confirmation.** The SCAFFOLD phase must present a component plan to the user. Do not generate code without the user confirming the structure and token consumption plan.366- **No graph mutations without validating node types.** When creating `USES_TOKEN` or `PLATFORM_BINDING` edges, verify the node and edge types are registered in the graph schema before writing.367368## Escalation369370- **When `design-system/tokens.json` does not exist:** Instruct the user: "Design tokens have not been generated. Run `harness-design-system` first to create `design-system/tokens.json`, then re-run `harness-design-web` for token-bound component generation."371- **When the project uses an undetected framework:** Ask the user to specify via the `--framework` CLI argument. Log: "Could not auto-detect web framework. Please specify: `harness skill run harness-design-web --framework react|vue|svelte|vanilla`."372- **When tokens are insufficient for the requested component:** Report which tokens are missing: "Component requires a `color.accent.500` token but it does not exist in `tokens.json`. Run `harness-design-system` to add the missing token, or choose an existing alternative." Do not hardcode a fallback.373- **When anti-patterns conflict with the requested design:** Present the conflict: "The requested gradient background violates the 'no gradients on data elements' anti-pattern from DESIGN.md. Options: (1) Remove the gradient and use a solid token color, (2) Update the anti-pattern list via `harness-design` if the intent has changed."374- **When the knowledge graph is unavailable:** Skip graph operations in SCAFFOLD and VERIFY phases. Log: "Graph not available at `.harness/graph/` — skipping token node verification and USES_TOKEN edge creation. Run `harness scan` later to populate." Continue with file-based operations.