@harness-engineering/cli 1.6.1 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/agents/personas/planner.yaml +27 -0
  2. package/dist/agents/personas/verifier.yaml +30 -0
  3. package/dist/agents/skills/claude-code/enforce-architecture/SKILL.md +19 -0
  4. package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +274 -0
  5. package/dist/agents/skills/claude-code/harness-accessibility/skill.yaml +51 -0
  6. package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +111 -72
  7. package/dist/agents/skills/claude-code/harness-autopilot/skill.yaml +4 -2
  8. package/dist/agents/skills/claude-code/harness-dependency-health/skill.yaml +1 -1
  9. package/dist/agents/skills/claude-code/harness-design/SKILL.md +265 -0
  10. package/dist/agents/skills/claude-code/harness-design/skill.yaml +53 -0
  11. package/dist/agents/skills/claude-code/harness-design-mobile/SKILL.md +336 -0
  12. package/dist/agents/skills/claude-code/harness-design-mobile/skill.yaml +49 -0
  13. package/dist/agents/skills/claude-code/harness-design-system/SKILL.md +282 -0
  14. package/dist/agents/skills/claude-code/harness-design-system/skill.yaml +50 -0
  15. package/dist/agents/skills/claude-code/harness-design-web/SKILL.md +360 -0
  16. package/dist/agents/skills/claude-code/harness-design-web/skill.yaml +52 -0
  17. package/dist/agents/skills/claude-code/harness-hotspot-detector/skill.yaml +1 -1
  18. package/dist/agents/skills/claude-code/harness-impact-analysis/SKILL.md +16 -0
  19. package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +19 -1
  20. package/dist/agents/skills/claude-code/harness-knowledge-mapper/skill.yaml +1 -1
  21. package/dist/agents/skills/claude-code/harness-onboarding/SKILL.md +19 -1
  22. package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +13 -9
  23. package/dist/agents/skills/claude-code/harness-security-scan/skill.yaml +1 -1
  24. package/dist/agents/skills/claude-code/harness-verify/SKILL.md +26 -0
  25. package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +274 -0
  26. package/dist/agents/skills/gemini-cli/harness-accessibility/skill.yaml +51 -0
  27. package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +111 -72
  28. package/dist/agents/skills/gemini-cli/harness-autopilot/skill.yaml +4 -2
  29. package/dist/agents/skills/gemini-cli/harness-dependency-health/skill.yaml +1 -1
  30. package/dist/agents/skills/gemini-cli/harness-design/SKILL.md +265 -0
  31. package/dist/agents/skills/gemini-cli/harness-design/skill.yaml +53 -0
  32. package/dist/agents/skills/gemini-cli/harness-design-mobile/SKILL.md +336 -0
  33. package/dist/agents/skills/gemini-cli/harness-design-mobile/skill.yaml +49 -0
  34. package/dist/agents/skills/gemini-cli/harness-design-system/SKILL.md +282 -0
  35. package/dist/agents/skills/gemini-cli/harness-design-system/skill.yaml +50 -0
  36. package/dist/agents/skills/gemini-cli/harness-design-web/SKILL.md +360 -0
  37. package/dist/agents/skills/gemini-cli/harness-design-web/skill.yaml +52 -0
  38. package/dist/agents/skills/gemini-cli/harness-hotspot-detector/skill.yaml +1 -1
  39. package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +16 -0
  40. package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/skill.yaml +1 -1
  41. package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +13 -9
  42. package/dist/agents/skills/gemini-cli/harness-security-scan/skill.yaml +1 -1
  43. package/dist/agents/skills/node_modules/.bin/vitest +2 -2
  44. package/dist/agents/skills/shared/design-knowledge/anti-patterns/color.yaml +106 -0
  45. package/dist/agents/skills/shared/design-knowledge/anti-patterns/layout.yaml +109 -0
  46. package/dist/agents/skills/shared/design-knowledge/anti-patterns/motion.yaml +109 -0
  47. package/dist/agents/skills/shared/design-knowledge/anti-patterns/typography.yaml +112 -0
  48. package/dist/agents/skills/shared/design-knowledge/industries/creative.yaml +80 -0
  49. package/dist/agents/skills/shared/design-knowledge/industries/ecommerce.yaml +80 -0
  50. package/dist/agents/skills/shared/design-knowledge/industries/emerging-tech.yaml +83 -0
  51. package/dist/agents/skills/shared/design-knowledge/industries/fintech.yaml +80 -0
  52. package/dist/agents/skills/shared/design-knowledge/industries/healthcare.yaml +80 -0
  53. package/dist/agents/skills/shared/design-knowledge/industries/lifestyle.yaml +80 -0
  54. package/dist/agents/skills/shared/design-knowledge/industries/saas.yaml +80 -0
  55. package/dist/agents/skills/shared/design-knowledge/industries/services.yaml +80 -0
  56. package/dist/agents/skills/shared/design-knowledge/palettes/curated.yaml +234 -0
  57. package/dist/agents/skills/shared/design-knowledge/platform-rules/android.yaml +125 -0
  58. package/dist/agents/skills/shared/design-knowledge/platform-rules/flutter.yaml +144 -0
  59. package/dist/agents/skills/shared/design-knowledge/platform-rules/ios.yaml +106 -0
  60. package/dist/agents/skills/shared/design-knowledge/platform-rules/web.yaml +102 -0
  61. package/dist/agents/skills/shared/design-knowledge/typography/pairings.yaml +274 -0
  62. package/dist/bin/harness.js +3 -2
  63. package/dist/{chunk-3U5VZYR7.js → chunk-4WUGOJQ7.js} +6 -3
  64. package/dist/{chunk-O6NEKDYP.js → chunk-FFIX3QVG.js} +697 -349
  65. package/dist/chunk-GA6GN5J2.js +6150 -0
  66. package/dist/dist-C4J67MPP.js +242 -0
  67. package/dist/dist-N4D4QWFV.js +2809 -0
  68. package/dist/index.d.ts +79 -0
  69. package/dist/index.js +3 -2
  70. package/dist/validate-cross-check-WGXQ7K62.js +7 -0
  71. package/package.json +12 -8
  72. package/dist/validate-cross-check-LNIZ7KGZ.js +0 -6
@@ -0,0 +1,360 @@
1
+ # Harness Design Web
2
+
3
+ > 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.
4
+
5
+ ## When to Use
6
+
7
+ - Generating new web components that must conform to the project's design system tokens
8
+ - When `on_new_feature` triggers fire with web UI scope requiring token-bound component generation
9
+ - When `on_commit` triggers fire and new components contain hardcoded design values that should reference tokens
10
+ - Implementing design intent from `design-system/DESIGN.md` into concrete Tailwind classes, CSS custom properties, or CSS-in-JS theme values
11
+ - Converting mockups or wireframes into token-bound component code for React, Vue, or Svelte
12
+ - NOT for generating design tokens themselves (use harness-design-system)
13
+ - NOT for establishing aesthetic direction or anti-patterns (use harness-design)
14
+ - NOT for accessibility auditing (use harness-accessibility)
15
+ - NOT for mobile platform components (use harness-design-mobile)
16
+
17
+ ## Process
18
+
19
+ ### Phase 1: SCAFFOLD — Read Tokens, Detect Framework, Plan Structure
20
+
21
+ 1. **Read design tokens.** Load `design-system/tokens.json` (W3C DTCG format). Extract:
22
+ - Color tokens: primary, secondary, accent, neutral ramps, semantic colors (success, warning, error, info)
23
+ - Typography tokens: heading and body font families, font weights, font sizes, line heights
24
+ - Spacing tokens: spacing scale values (xs through 2xl or equivalent)
25
+ - If `design-system/tokens.json` does not exist, stop and instruct the user to run `harness-design-system` first.
26
+
27
+ 2. **Read design intent.** Load `design-system/DESIGN.md` for:
28
+ - Aesthetic direction (style, tone, differentiator) from harness-design output
29
+ - Anti-patterns to avoid (e.g., "no gradients on data elements," "no decorative borders")
30
+ - Platform-specific web notes (CSS strategy preferences, animation guidelines, responsive behavior)
31
+ - If `design-system/DESIGN.md` does not exist, warn the user and proceed with tokens only. Recommend running `harness-design` for richer output.
32
+
33
+ 3. **Check harness configuration.** Read `harness.config.json` for:
34
+ - `design.strictness` — enforcement level (`strict`, `standard`, `permissive`). Default to `standard`.
35
+ - `design.platforms` — confirm `web` is in the platforms list.
36
+ - `design.tokenPath` — custom token path (default: `design-system/tokens.json`).
37
+
38
+ 4. **Detect web framework.** Scan the project for:
39
+ - **React:** `package.json` contains `react` or `next` dependency, `.tsx`/`.jsx` files exist
40
+ - **Vue:** `package.json` contains `vue` or `nuxt` dependency, `.vue` files exist
41
+ - **Svelte:** `package.json` contains `svelte` or `@sveltejs/kit`, `.svelte` files exist
42
+ - **Vanilla:** No framework detected, output plain HTML/CSS
43
+ - If the user specified `--framework`, use that override.
44
+
45
+ 5. **Detect CSS strategy.** Scan for:
46
+ - **Tailwind:** `tailwind.config.*` exists, `@tailwind` directives in CSS, `class=` with Tailwind utility patterns
47
+ - **CSS Modules:** `.module.css` or `.module.scss` files exist
48
+ - **CSS-in-JS:** `styled-components`, `@emotion/styled`, `stitches` imports detected
49
+ - **Vanilla CSS:** Global `.css`/`.scss` files with no module or utility pattern
50
+ - If the user specified `--cssStrategy`, use that override.
51
+
52
+ 6. **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.
53
+
54
+ 7. **Load anti-pattern definitions.** Read anti-pattern files from `agents/skills/shared/design-knowledge/anti-patterns/`:
55
+ - `typography.yaml` — typographic anti-patterns (too many fonts, inconsistent scales)
56
+ - `color.yaml` — color anti-patterns (hardcoded hex, insufficient contrast)
57
+ - `layout.yaml` — layout anti-patterns (magic numbers, inconsistent spacing)
58
+ - `motion.yaml` — motion anti-patterns (excessive animation, missing reduced-motion)
59
+
60
+ 8. **Build token-to-CSS mapping.** Create a lookup table that maps each token to its CSS representation based on the detected strategy:
61
+ - **Tailwind:** `color.primary.500` maps to `text-primary-500` / `bg-primary-500` (requires `tailwind.config` theme extension)
62
+ - **CSS custom properties:** `color.primary.500` maps to `var(--color-primary-500)`
63
+ - **CSS-in-JS:** `color.primary.500` maps to `theme.color.primary[500]`
64
+
65
+ 9. **Plan component structure.** For the requested component(s), define:
66
+ - Component file path(s) following project conventions
67
+ - Props interface / type definition
68
+ - Which tokens will be consumed (colors, typography, spacing)
69
+ - Responsive behavior (breakpoints, layout changes)
70
+ - Present the scaffold plan to the user before proceeding.
71
+
72
+ ### Phase 2: IMPLEMENT — Generate Token-Bound Components
73
+
74
+ 1. **Generate framework-specific component code.** Based on detected framework:
75
+
76
+ **React (TSX):**
77
+ - Functional component with TypeScript props interface
78
+ - All color values reference tokens (via Tailwind classes, CSS variables, or theme object)
79
+ - All typography values reference tokens (font family, weight, size from token set)
80
+ - All spacing values reference tokens (padding, margin, gap from spacing scale)
81
+ - Export component with display name
82
+
83
+ **Vue (SFC):**
84
+ - Single File Component with `<script setup lang="ts">`
85
+ - Props defined with `defineProps` and TypeScript interface
86
+ - Scoped styles reference CSS custom properties mapped from tokens
87
+ - Template uses token-derived classes or inline styles via CSS variables
88
+
89
+ **Svelte:**
90
+ - Component with TypeScript `<script lang="ts">`
91
+ - Props exported with `export let` declarations
92
+ - Styles reference CSS custom properties mapped from tokens
93
+ - Reactive declarations for computed style values
94
+
95
+ **Vanilla HTML/CSS:**
96
+ - Semantic HTML structure
97
+ - CSS custom properties for all design values
98
+ - No inline styles with hardcoded values
99
+
100
+ 2. **Generate CSS strategy artifacts.** Based on detected CSS strategy:
101
+
102
+ **Tailwind:**
103
+ - Extend `tailwind.config` theme with token values (if not already present)
104
+ - Map tokens to Tailwind utility classes in components
105
+ - Use `@apply` sparingly — prefer utility classes in markup
106
+ - Generate token-to-Tailwind mapping comment block at top of component
107
+
108
+ **CSS Custom Properties:**
109
+ - Generate `:root` declarations for all consumed tokens
110
+ - Components reference `var(--token-name)` exclusively
111
+ - No hardcoded hex, rgb, hsl, or font values in component styles
112
+
113
+ **CSS-in-JS:**
114
+ - Generate theme object from tokens
115
+ - Components consume theme via provider/hook pattern
116
+ - All style values reference theme properties
117
+
118
+ 3. **Apply design intent constraints.** For each generated component:
119
+ - Check against anti-patterns from `design-system/DESIGN.md` and `agents/skills/shared/design-knowledge/anti-patterns/`
120
+ - Enforce style guidelines (e.g., minimal style means no decorative effects)
121
+ - Apply tone-appropriate color usage (e.g., cool tone means no warm accents in neutral UI)
122
+ - Respect platform-specific web notes (animation preferences, responsive behavior)
123
+
124
+ 4. **Add USES_TOKEN annotations.** Insert comments in generated code documenting which tokens are consumed:
125
+ ```
126
+ /* @design-token color.primary.500 — primary action background */
127
+ /* @design-token typography.heading.fontFamily — section heading */
128
+ /* @design-token spacing.md — card internal padding */
129
+ ```
130
+ These annotations enable the knowledge graph to create `USES_TOKEN` edges from this component to the consumed `DesignToken` nodes.
131
+
132
+ ### Phase 3: VERIFY — Check Token Binding and Design Constraints
133
+
134
+ 1. **Scan for hardcoded values.** Use Grep to search generated files for:
135
+ - Hardcoded color values: hex (`#[0-9a-fA-F]{3,8}`), `rgb()`, `hsl()`, named colors
136
+ - Hardcoded font families: `font-family:` declarations not referencing tokens
137
+ - Hardcoded spacing: pixel/rem values in margin/padding/gap not from the token scale
138
+ - Each finding is a violation: the component uses a value not bound to a token.
139
+
140
+ 2. **Verify token coverage.** For every design value in the generated component:
141
+ - Confirm it resolves to a token in `design-system/tokens.json`
142
+ - Confirm the token path is valid (e.g., `color.primary.500` exists in the token tree)
143
+ - Report orphan references (token annotations pointing to non-existent tokens)
144
+
145
+ 3. **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/`:
146
+ - Grep for patterns matching each declared anti-pattern
147
+ - Flag violations with file path, line number, and the specific anti-pattern violated
148
+
149
+ 4. **Query the knowledge graph.** If a graph exists at `.harness/graph/`:
150
+ - Use `DesignIngestor` to verify `DesignToken` nodes exist for all referenced tokens
151
+ - Verify `PLATFORM_BINDING` edges exist for web platform tokens
152
+ - Use `DesignConstraintAdapter` to check for `VIOLATES_DESIGN` edges
153
+ - Report any constraint violations with severity based on `design.strictness`
154
+
155
+ 5. **Assign severity based on `designStrictness`:**
156
+ - `permissive` — all findings are `info`
157
+ - `standard` — hardcoded values and anti-pattern violations are `warn`, accessibility violations are `error`
158
+ - `strict` — hardcoded values are `error` (blocks), anti-pattern violations are `warn`, accessibility violations are `error`
159
+
160
+ 6. **Report verification results.** Present:
161
+
162
+ ```
163
+ WEB-001 [warn] Hardcoded color #3b82f6 — should reference token "color.primary.500"
164
+ File: src/components/Button.tsx:12
165
+ Fix: Replace with Tailwind class "bg-primary-500" or var(--color-primary-500)
166
+
167
+ WEB-002 [info] Anti-pattern: gradient on card background
168
+ File: src/components/MetricCard.tsx:28
169
+ Fix: Use solid background from token "color.neutral.50"
170
+ ```
171
+
172
+ 7. **Run `harness validate`.** After verification, run project-level validation to confirm the new components integrate cleanly.
173
+
174
+ ## Harness Integration
175
+
176
+ - **`harness validate`** — Run after generating components to verify project health. New files must not break existing constraints.
177
+ - **`harness scan`** — Run after component generation to update the knowledge graph with new `USES_TOKEN` edges from generated components to consumed tokens.
178
+ - **`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.
179
+ - **`DesignConstraintAdapter`** (`packages/graph/src/constraints/DesignConstraintAdapter.ts`) — Checks for `VIOLATES_DESIGN` edges during the VERIFY phase. Reports constraint violations at the configured strictness level.
180
+ - **`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.
181
+ - **`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.
182
+ - **`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.
183
+
184
+ **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.
185
+
186
+ ## Success Criteria
187
+
188
+ - Generated components reference design tokens exclusively — no hardcoded color, font, or spacing values
189
+ - Framework detection correctly identifies React, Vue, Svelte, or vanilla projects
190
+ - CSS strategy detection correctly identifies Tailwind, CSS Modules, CSS-in-JS, or vanilla CSS
191
+ - Token-to-CSS mapping produces correct output for each CSS strategy (Tailwind classes, CSS custom properties, theme object references)
192
+ - `@design-token` annotations are present for every consumed token
193
+ - Anti-pattern compliance check catches violations declared in `design-system/DESIGN.md`
194
+ - Verification report uses severity levels matching `design.strictness` configuration
195
+ - `harness validate` passes after component generation
196
+
197
+ ## Examples
198
+
199
+ ### Example: React + Tailwind Button Component
200
+
201
+ **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).
202
+
203
+ **SCAFFOLD output:**
204
+
205
+ ```
206
+ Framework detected: React (Next.js)
207
+ CSS strategy: Tailwind CSS (tailwind.config.ts)
208
+ Tokens loaded: 42 tokens from design-system/tokens.json
209
+ Design intent: Minimal, cool professional (from DESIGN.md)
210
+ Component plan: Button with primary/secondary/ghost variants
211
+ Token consumption: color.primary.*, color.neutral.*, typography.body, spacing.sm/md
212
+ ```
213
+
214
+ **IMPLEMENT output (Button.tsx):**
215
+
216
+ ```tsx
217
+ /* @design-token color.primary.500 — primary variant background */
218
+ /* @design-token color.primary.700 — primary variant hover */
219
+ /* @design-token color.neutral.50 — ghost variant background */
220
+ /* @design-token color.neutral.900 — ghost variant text */
221
+ /* @design-token typography.body.fontFamily — button label */
222
+ /* @design-token typography.body.fontWeight — button label weight */
223
+ /* @design-token spacing.sm — button horizontal padding */
224
+ /* @design-token spacing.xs — button vertical padding */
225
+
226
+ import type { ButtonHTMLAttributes } from 'react';
227
+
228
+ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
229
+ variant?: 'primary' | 'secondary' | 'ghost';
230
+ size?: 'sm' | 'md' | 'lg';
231
+ }
232
+
233
+ export function Button({
234
+ variant = 'primary',
235
+ size = 'md',
236
+ className = '',
237
+ children,
238
+ ...props
239
+ }: ButtonProps) {
240
+ const baseClasses =
241
+ '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';
242
+
243
+ const variantClasses = {
244
+ primary: 'bg-primary-500 text-white hover:bg-primary-700',
245
+ secondary: 'border border-primary-500 text-primary-700 hover:bg-primary-50',
246
+ ghost: 'text-neutral-900 hover:bg-neutral-100',
247
+ };
248
+
249
+ const sizeClasses = {
250
+ sm: 'px-spacing-sm py-spacing-xs text-sm',
251
+ md: 'px-spacing-md py-spacing-sm text-base',
252
+ lg: 'px-spacing-lg py-spacing-md text-lg',
253
+ };
254
+
255
+ return (
256
+ <button
257
+ className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}
258
+ {...props}
259
+ >
260
+ {children}
261
+ </button>
262
+ );
263
+ }
264
+ ```
265
+
266
+ **VERIFY output:**
267
+
268
+ ```
269
+ Verification Results
270
+ --------------------
271
+ Hardcoded values: PASS (0 hardcoded colors, fonts, or spacing)
272
+ Token coverage: PASS (8/8 referenced tokens exist in tokens.json)
273
+ Anti-pattern check: PASS (no gradients, no decorative borders)
274
+ Design constraints: PASS (no VIOLATES_DESIGN edges)
275
+ Harness validate: PASS
276
+ ```
277
+
278
+ ### Example: Vue + CSS Custom Properties Card Component
279
+
280
+ **Context:** E-commerce project. Vue 3 with CSS custom properties. Tokens from harness-design-system.
281
+
282
+ **IMPLEMENT output (ProductCard.vue):**
283
+
284
+ ```vue
285
+ <!-- @design-token color.neutral.50 — card background -->
286
+ <!-- @design-token color.neutral.200 — card border -->
287
+ <!-- @design-token color.neutral.900 — card text -->
288
+ <!-- @design-token typography.heading.fontFamily — product title -->
289
+ <!-- @design-token typography.body.fontFamily — product description -->
290
+ <!-- @design-token spacing.md — card padding -->
291
+ <!-- @design-token spacing.sm — content gap -->
292
+
293
+ <script setup lang="ts">
294
+ interface Props {
295
+ title: string;
296
+ description: string;
297
+ price: string;
298
+ imageUrl: string;
299
+ imageAlt: string;
300
+ }
301
+
302
+ defineProps<Props>();
303
+ </script>
304
+
305
+ <template>
306
+ <article class="product-card">
307
+ <img :src="imageUrl" :alt="imageAlt" class="product-card__image" />
308
+ <div class="product-card__content">
309
+ <h3 class="product-card__title">{{ title }}</h3>
310
+ <p class="product-card__description">{{ description }}</p>
311
+ <span class="product-card__price">{{ price }}</span>
312
+ </div>
313
+ </article>
314
+ </template>
315
+
316
+ <style scoped>
317
+ .product-card {
318
+ background: var(--color-neutral-50);
319
+ border: 1px solid var(--color-neutral-200);
320
+ border-radius: var(--radius-md);
321
+ overflow: hidden;
322
+ }
323
+
324
+ .product-card__content {
325
+ padding: var(--spacing-md);
326
+ display: flex;
327
+ flex-direction: column;
328
+ gap: var(--spacing-sm);
329
+ }
330
+
331
+ .product-card__title {
332
+ font-family: var(--typography-heading-fontFamily);
333
+ font-weight: var(--typography-heading-fontWeight);
334
+ color: var(--color-neutral-900);
335
+ }
336
+
337
+ .product-card__description {
338
+ font-family: var(--typography-body-fontFamily);
339
+ color: var(--color-neutral-700);
340
+ }
341
+ </style>
342
+ ```
343
+
344
+ ## Gates
345
+
346
+ These are hard stops. Violating any gate means the process has broken down.
347
+
348
+ - **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.
349
+ - **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.
350
+ - **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.
351
+ - **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.
352
+ - **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.
353
+
354
+ ## Escalation
355
+
356
+ - **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."
357
+ - **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`."
358
+ - **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.
359
+ - **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."
360
+ - **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.
@@ -0,0 +1,52 @@
1
+ name: harness-design-web
2
+ version: "1.0.0"
3
+ description: Token-bound web component generation with Tailwind/CSS, React/Vue/Svelte patterns, and design constraint verification
4
+ cognitive_mode: meticulous-implementer
5
+ triggers:
6
+ - manual
7
+ - on_new_feature
8
+ - on_commit
9
+ platforms:
10
+ - claude-code
11
+ - gemini-cli
12
+ tools:
13
+ - Bash
14
+ - Read
15
+ - Write
16
+ - Edit
17
+ - Glob
18
+ - Grep
19
+ cli:
20
+ command: harness skill run harness-design-web
21
+ args:
22
+ - name: path
23
+ description: Project root path
24
+ required: false
25
+ - name: framework
26
+ description: Target framework (react, vue, svelte, vanilla)
27
+ required: false
28
+ - name: cssStrategy
29
+ description: CSS strategy (tailwind, css-modules, css-in-js, vanilla)
30
+ required: false
31
+ mcp:
32
+ tool: run_skill
33
+ input:
34
+ skill: harness-design-web
35
+ path: string
36
+ type: rigid
37
+ phases:
38
+ - name: scaffold
39
+ description: Read tokens and design intent, detect framework and CSS strategy, plan component structure
40
+ required: true
41
+ - name: implement
42
+ description: Generate token-bound components with framework-specific patterns
43
+ required: true
44
+ - name: verify
45
+ description: Verify all values reference tokens, no hardcoded colors/fonts/spacing, run design constraints
46
+ required: true
47
+ state:
48
+ persistent: false
49
+ files: []
50
+ depends_on:
51
+ - harness-design-system
52
+ - harness-design
@@ -4,7 +4,7 @@ description: Identify structural risk hotspots via co-change and churn analysis
4
4
  cognitive_mode: analytical-reporter
5
5
  triggers:
6
6
  - manual
7
- - scheduled
7
+ - on_milestone
8
8
  platforms:
9
9
  - claude-code
10
10
  - gemini-cli
@@ -47,6 +47,17 @@ For each changed file:
47
47
 
48
48
  4. **Test coverage**: Identify test files connected via `imports` edges. Flag changed files with no test coverage.
49
49
 
50
+ 5. **Design token impact**: When the graph contains `DesignToken` nodes, use `query_graph` with `USES_TOKEN` edges to find components that consume changed tokens.
51
+
52
+ ```
53
+ query_graph(rootNodeIds=["designtoken:color.primary"], maxDepth=2, includeEdges=["uses_token"])
54
+ → components: [Button.tsx, Card.tsx, Header.tsx, ...]
55
+ ```
56
+
57
+ If a changed file is `design-system/tokens.json`, identify ALL tokens that changed and trace each to its consuming components. This reveals the full design blast radius of a token change.
58
+
59
+ 6. **Design constraint impact**: When the graph contains `DesignConstraint` nodes, check if changed code introduces new `VIOLATES_DESIGN` edges.
60
+
50
61
  ### Phase 3: ASSESS — Risk Assessment and Report
51
62
 
52
63
  1. **Impact score**: Calculate based on:
@@ -54,6 +65,7 @@ For each changed file:
54
65
  - Number of transitive dependents (weight: 1x)
55
66
  - Whether affected code includes entry points (weight: 5x)
56
67
  - Whether tests exist for the changed code (no tests = higher risk)
68
+ - Whether design tokens are affected (weight: 2x — token changes cascade to all consumers)
57
69
 
58
70
  2. **Risk tiers**:
59
71
  - **Critical** (score > 50): Changes affect entry points or >20 downstream files
@@ -90,6 +102,10 @@ For each changed file:
90
102
  1. src/routes/login.ts — imports auth.ts
91
103
  2. src/middleware/verify.ts — imports auth.ts
92
104
  3. src/routes/signup.ts — imports user.ts (transitive via auth.ts)
105
+
106
+ ### Affected Design Tokens (when tokens change)
107
+ 1. color.primary → used by 12 components
108
+ 2. typography.body → used by 8 components
93
109
  ```
94
110
 
95
111
  ## Harness Integration
@@ -5,7 +5,7 @@ cognitive_mode: constructive-architect
5
5
  triggers:
6
6
  - manual
7
7
  - on_commit
8
- - scheduled
8
+ - on_milestone
9
9
  platforms:
10
10
  - claude-code
11
11
  - gemini-cli
@@ -77,6 +77,8 @@ Run every check below. Record each as **pass**, **warn**, or **fail**:
77
77
  | `homepage` field exists | warn |
78
78
  | `description` field exists | warn |
79
79
  | Build succeeds: run the project's build command | fail |
80
+ | Typecheck passes: run the project's typecheck command (e.g., `pnpm typecheck`) | fail |
81
+ | Tests pass: run the project's test command (e.g., `pnpm test`) | fail |
80
82
  | `pnpm pack --dry-run` produces expected files (no test files, no src if dist exists) | warn |
81
83
 
82
84
  ##### Documentation (root level)
@@ -107,8 +109,8 @@ Run every check below. Record each as **pass**, **warn**, or **fail**:
107
109
  | CI workflow file exists (`.github/workflows/ci.yml` or similar) | fail |
108
110
  | Release/publish workflow file exists | warn |
109
111
  | `test` script exists in root `package.json` | fail |
110
- | `lint` script exists in root `package.json` | warn |
111
- | `typecheck` or `tsc` script exists in root `package.json` | warn |
112
+ | `lint` script exists in root `package.json` | fail |
113
+ | `typecheck` or `tsc` script exists in root `package.json` | fail |
112
114
  | `harness validate` passes (project-level health check) | fail |
113
115
 
114
116
  #### Comprehensive Checks (only with `--comprehensive`)
@@ -267,13 +269,15 @@ After each batch of fixes (or after each individual fix if not batching), run `h
267
269
 
268
270
  These require human judgment and cannot be auto-fixed. List them with guidance:
269
271
 
270
- | Finding | Guidance |
271
- | ------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
272
- | `TODO`/`FIXME` in published source | List each location with file:line. Human must resolve or move to a tracked issue. |
273
- | README missing usage/API sections | Suggest section structure but do not generate content — only the author knows the API. |
274
- | CHANGELOG exists but has no entries (empty or template-only) | Suggest running `git log --oneline <last-tag>..HEAD` to generate entries. Unlike a missing file (auto-fixable above), an empty CHANGELOG needs human-authored content. |
275
- | CI workflow missing | Provide a starter template but flag for human review before committing. |
276
- | Build failure | Show the error output. Do not attempt to fix build issues automatically. |
272
+ | Finding | Guidance |
273
+ | ------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
274
+ | `TODO`/`FIXME` in published source | List each location with file:line. Human must resolve or move to a tracked issue. |
275
+ | README missing usage/API sections | Suggest section structure but do not generate content — only the author knows the API. |
276
+ | CHANGELOG exists but has no entries (empty or template-only) | Suggest running `git log --oneline <last-tag>..HEAD` to generate entries. Unlike a missing file (auto-fixable above), an empty CHANGELOG needs human-authored content. |
277
+ | CI workflow missing | Provide a starter template but flag for human review before committing. |
278
+ | Build failure | Show the error output. Do not attempt to fix build issues automatically. |
279
+ | Typecheck failure | Show the error output with file:line. Common causes: orphaned files with stale imports, missing type declarations, `exactOptionalPropertyTypes` violations. Do not auto-fix — type errors often indicate structural problems. |
280
+ | Test failure | Show the error output with failing test names. Do not attempt to fix test failures automatically — they may indicate real bugs. |
277
281
 
278
282
  #### Output
279
283
 
@@ -4,7 +4,7 @@ description: Lightweight mechanical security scan for health checks
4
4
  cognitive_mode: meticulous-implementer
5
5
  triggers:
6
6
  - manual
7
- - scheduled
7
+ - on_milestone
8
8
  platforms:
9
9
  - claude-code
10
10
  - gemini-cli
@@ -6,9 +6,9 @@ case `uname` in
6
6
  esac
7
7
 
8
8
  if [ -z "$NODE_PATH" ]; then
9
- export NODE_PATH="/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_@types+node@22.19.15_yaml@2.8.2/node_modules/vitest/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_@types+node@22.19.15_yaml@2.8.2/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/node_modules"
9
+ export NODE_PATH="/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_yaml@2.8.2/node_modules/vitest/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_yaml@2.8.2/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/node_modules"
10
10
  else
11
- export NODE_PATH="/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_@types+node@22.19.15_yaml@2.8.2/node_modules/vitest/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_@types+node@22.19.15_yaml@2.8.2/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/node_modules:$NODE_PATH"
11
+ export NODE_PATH="/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_yaml@2.8.2/node_modules/vitest/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_yaml@2.8.2/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/node_modules:$NODE_PATH"
12
12
  fi
13
13
  if [ -x "$basedir/node" ]; then
14
14
  exec "$basedir/node" "$basedir/../vitest/vitest.mjs" "$@"
@@ -0,0 +1,106 @@
1
+ description: "Color anti-patterns — common mistakes that harm accessibility, consistency, and brand integrity"
2
+
3
+ patterns:
4
+ - name: "Hardcoded color values instead of tokens"
5
+ severity: warning
6
+ scope: all
7
+ detect:
8
+ method: "Grep for hex (#xxx, #xxxxxx), rgb(), rgba(), hsl(), hsla() values in component code that are not defined in tokens.json"
9
+ exclude: ["test files", "fixture files", "storybook stories"]
10
+ reason: "Hardcoded colors bypass the design token system, creating inconsistency and making global palette changes impossible without find-and-replace."
11
+ instead: "Reference design tokens: use CSS custom properties (var(--color-primary)), Tailwind classes (text-primary), or platform token bindings."
12
+ strictness:
13
+ permissive: info
14
+ standard: warn
15
+ strict: error
16
+
17
+ - name: "Insufficient contrast ratio (WCAG AA)"
18
+ severity: error
19
+ scope: all
20
+ detect:
21
+ method: "Calculate contrast ratio between foreground text color and background color"
22
+ threshold: "< 4.5:1 for normal text, < 3:1 for large text (18px+ or 14px+ bold)"
23
+ reason: "Low contrast text is unreadable for users with low vision, color blindness, or in bright ambient light. WCAG 2.1 Level AA requires 4.5:1 minimum."
24
+ instead: "Use pre-validated contrast pairs from the palette. Check ratios with a contrast checker before committing."
25
+ strictness:
26
+ permissive: info
27
+ standard: warn
28
+ strict: error
29
+
30
+ - name: "Color as the only differentiator"
31
+ severity: error
32
+ scope: all
33
+ detect:
34
+ method: "Check for status indicators, form validation, or interactive states that rely solely on color change"
35
+ context: "Success/error/warning states, required field indicators, active/inactive toggles"
36
+ reason: "Approximately 8% of men and 0.5% of women have color vision deficiency. Color-only indicators are invisible to them."
37
+ instead: "Combine color with a secondary indicator: icons, text labels, patterns, or border changes. Error states should include both red color AND an error icon/message."
38
+ strictness:
39
+ permissive: info
40
+ standard: warn
41
+ strict: error
42
+
43
+ - name: "Too many colors in a single view"
44
+ severity: warning
45
+ scope: all
46
+ detect:
47
+ method: "Count distinct non-neutral hues in a single screen or component"
48
+ threshold: "> 5 distinct hues (excluding neutrals/grays)"
49
+ reason: "Excessive color variety creates visual noise, weakens brand identity, and makes it harder for users to learn the color semantics of the interface."
50
+ instead: "Limit to 1-2 brand colors + 1 accent + semantic colors (success/warning/error/info). Use neutrals for everything else."
51
+ strictness:
52
+ permissive: info
53
+ standard: warn
54
+ strict: warn
55
+
56
+ - name: "Pure black (#000000) on pure white (#ffffff)"
57
+ severity: info
58
+ scope: web
59
+ detect:
60
+ css_properties: ["color", "background-color"]
61
+ values: ["#000000 on #ffffff", "#000 on #fff"]
62
+ reason: "Maximum contrast (21:1) can cause eye strain during extended reading, especially on bright displays. High contrast also creates harsh vibration at text edges."
63
+ instead: "Use near-black (e.g., #0f172a, #18181b) on near-white (e.g., #fafafa, #f8fafc) for a comfortable reading experience while maintaining excellent contrast ratios."
64
+ strictness:
65
+ permissive: info
66
+ standard: info
67
+ strict: warn
68
+
69
+ - name: "Opacity/alpha for semantic colors"
70
+ severity: warning
71
+ scope: all
72
+ detect:
73
+ method: "Check for rgba() or opacity applied to semantic colors (success, error, warning)"
74
+ context: "Background fills behind status text, badge backgrounds"
75
+ reason: "Transparent semantic colors shift hue depending on what's behind them. A red error badge over a blue card becomes purple, confusing the semantic meaning."
76
+ instead: "Use solid, pre-defined tint colors for semantic backgrounds (e.g., red-50 for error background, green-50 for success) instead of applying opacity to the base color."
77
+ strictness:
78
+ permissive: info
79
+ standard: warn
80
+ strict: warn
81
+
82
+ - name: "Brand colors used for destructive actions"
83
+ severity: warning
84
+ scope: all
85
+ detect:
86
+ method: "Check if primary brand color is applied to delete, remove, or destructive action buttons"
87
+ reason: "Using the brand color for destructive actions creates cognitive dissonance — the color that means 'go/primary' also means 'danger'. Users learn to hesitate on all primary-colored actions."
88
+ instead: "Reserve red (or a distinct danger color) for destructive actions. Primary brand color is for constructive actions only."
89
+ strictness:
90
+ permissive: info
91
+ standard: warn
92
+ strict: warn
93
+
94
+ - name: "Gradient text without fallback"
95
+ severity: info
96
+ scope: web
97
+ detect:
98
+ css_properties: ["background-clip", "-webkit-background-clip"]
99
+ values: ["text"]
100
+ absent: ["color fallback"]
101
+ reason: "Gradient text using background-clip: text has inconsistent browser support and can disappear entirely if the gradient fails to render."
102
+ instead: "Always set a solid color fallback before the gradient declaration. Test in all target browsers."
103
+ strictness:
104
+ permissive: info
105
+ standard: info
106
+ strict: warn