@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.
- package/dist/agents/personas/planner.yaml +27 -0
- package/dist/agents/personas/verifier.yaml +30 -0
- package/dist/agents/skills/claude-code/enforce-architecture/SKILL.md +19 -0
- package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +274 -0
- package/dist/agents/skills/claude-code/harness-accessibility/skill.yaml +51 -0
- package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +111 -72
- package/dist/agents/skills/claude-code/harness-autopilot/skill.yaml +4 -2
- package/dist/agents/skills/claude-code/harness-dependency-health/skill.yaml +1 -1
- package/dist/agents/skills/claude-code/harness-design/SKILL.md +265 -0
- package/dist/agents/skills/claude-code/harness-design/skill.yaml +53 -0
- package/dist/agents/skills/claude-code/harness-design-mobile/SKILL.md +336 -0
- package/dist/agents/skills/claude-code/harness-design-mobile/skill.yaml +49 -0
- package/dist/agents/skills/claude-code/harness-design-system/SKILL.md +282 -0
- package/dist/agents/skills/claude-code/harness-design-system/skill.yaml +50 -0
- package/dist/agents/skills/claude-code/harness-design-web/SKILL.md +360 -0
- package/dist/agents/skills/claude-code/harness-design-web/skill.yaml +52 -0
- package/dist/agents/skills/claude-code/harness-hotspot-detector/skill.yaml +1 -1
- package/dist/agents/skills/claude-code/harness-impact-analysis/SKILL.md +16 -0
- package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +19 -1
- package/dist/agents/skills/claude-code/harness-knowledge-mapper/skill.yaml +1 -1
- package/dist/agents/skills/claude-code/harness-onboarding/SKILL.md +19 -1
- package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +13 -9
- package/dist/agents/skills/claude-code/harness-security-scan/skill.yaml +1 -1
- package/dist/agents/skills/claude-code/harness-verify/SKILL.md +26 -0
- package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +274 -0
- package/dist/agents/skills/gemini-cli/harness-accessibility/skill.yaml +51 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +111 -72
- package/dist/agents/skills/gemini-cli/harness-autopilot/skill.yaml +4 -2
- package/dist/agents/skills/gemini-cli/harness-dependency-health/skill.yaml +1 -1
- package/dist/agents/skills/gemini-cli/harness-design/SKILL.md +265 -0
- package/dist/agents/skills/gemini-cli/harness-design/skill.yaml +53 -0
- package/dist/agents/skills/gemini-cli/harness-design-mobile/SKILL.md +336 -0
- package/dist/agents/skills/gemini-cli/harness-design-mobile/skill.yaml +49 -0
- package/dist/agents/skills/gemini-cli/harness-design-system/SKILL.md +282 -0
- package/dist/agents/skills/gemini-cli/harness-design-system/skill.yaml +50 -0
- package/dist/agents/skills/gemini-cli/harness-design-web/SKILL.md +360 -0
- package/dist/agents/skills/gemini-cli/harness-design-web/skill.yaml +52 -0
- package/dist/agents/skills/gemini-cli/harness-hotspot-detector/skill.yaml +1 -1
- package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +16 -0
- package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/skill.yaml +1 -1
- package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +13 -9
- package/dist/agents/skills/gemini-cli/harness-security-scan/skill.yaml +1 -1
- package/dist/agents/skills/node_modules/.bin/vitest +2 -2
- package/dist/agents/skills/shared/design-knowledge/anti-patterns/color.yaml +106 -0
- package/dist/agents/skills/shared/design-knowledge/anti-patterns/layout.yaml +109 -0
- package/dist/agents/skills/shared/design-knowledge/anti-patterns/motion.yaml +109 -0
- package/dist/agents/skills/shared/design-knowledge/anti-patterns/typography.yaml +112 -0
- package/dist/agents/skills/shared/design-knowledge/industries/creative.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/ecommerce.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/emerging-tech.yaml +83 -0
- package/dist/agents/skills/shared/design-knowledge/industries/fintech.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/healthcare.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/lifestyle.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/saas.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/industries/services.yaml +80 -0
- package/dist/agents/skills/shared/design-knowledge/palettes/curated.yaml +234 -0
- package/dist/agents/skills/shared/design-knowledge/platform-rules/android.yaml +125 -0
- package/dist/agents/skills/shared/design-knowledge/platform-rules/flutter.yaml +144 -0
- package/dist/agents/skills/shared/design-knowledge/platform-rules/ios.yaml +106 -0
- package/dist/agents/skills/shared/design-knowledge/platform-rules/web.yaml +102 -0
- package/dist/agents/skills/shared/design-knowledge/typography/pairings.yaml +274 -0
- package/dist/bin/harness.js +3 -2
- package/dist/{chunk-3U5VZYR7.js → chunk-4WUGOJQ7.js} +6 -3
- package/dist/{chunk-O6NEKDYP.js → chunk-FFIX3QVG.js} +697 -349
- package/dist/chunk-GA6GN5J2.js +6150 -0
- package/dist/dist-C4J67MPP.js +242 -0
- package/dist/dist-N4D4QWFV.js +2809 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +3 -2
- package/dist/validate-cross-check-WGXQ7K62.js +7 -0
- package/package.json +12 -8
- 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
|
|
@@ -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
|
|
@@ -41,6 +41,19 @@ Run the built-in security scanner as a mechanical check between verification and
|
|
|
41
41
|
3. **Error-severity security findings are blocking** — they cause the overall integrity check to FAIL, same as a test failure.
|
|
42
42
|
4. Warning/info findings are included in the report but do not block.
|
|
43
43
|
|
|
44
|
+
### Phase 1.7: DESIGN HEALTH (conditional)
|
|
45
|
+
|
|
46
|
+
When the project has `design` configured in `harness.config.json`:
|
|
47
|
+
|
|
48
|
+
1. Run `harness-design` in review mode to check existing components against design intent and anti-patterns.
|
|
49
|
+
2. Run `harness-accessibility` in scan+evaluate mode to check WCAG compliance.
|
|
50
|
+
3. Combine findings into a design health summary:
|
|
51
|
+
- Error count (blocking, based on strictness)
|
|
52
|
+
- Warning count (non-blocking)
|
|
53
|
+
- Info count (advisory)
|
|
54
|
+
4. **Error-severity design findings are blocking** in `strict` mode only. In `standard` and `permissive` modes, design findings do not block.
|
|
55
|
+
5. If no `design` block exists, skip this phase entirely.
|
|
56
|
+
|
|
44
57
|
### Phase 2: REVIEW
|
|
45
58
|
|
|
46
59
|
Run change-type-aware AI review using `harness-code-review`.
|
|
@@ -61,6 +74,7 @@ Integrity Check: [PASS/FAIL]
|
|
|
61
74
|
- Lint: [PASS/FAIL/SKIPPED]
|
|
62
75
|
- Types: [PASS/FAIL/SKIPPED]
|
|
63
76
|
- Security: [PASS/WARN/FAIL] ([count] errors, [count] warnings)
|
|
77
|
+
- Design: [PASS/WARN/FAIL/SKIPPED] ([count] errors, [count] warnings)
|
|
64
78
|
- Review: [PASS/FAIL] ([count] suggestions, [count] blocking)
|
|
65
79
|
|
|
66
80
|
Overall: [PASS/FAIL]
|
|
@@ -68,7 +82,7 @@ Overall: [PASS/FAIL]
|
|
|
68
82
|
|
|
69
83
|
Rules:
|
|
70
84
|
|
|
71
|
-
- Overall `PASS` requires: all non-skipped mechanical checks pass AND zero blocking review findings.
|
|
85
|
+
- Overall `PASS` requires: all non-skipped mechanical checks pass AND zero blocking review findings AND zero blocking design findings (strict mode only).
|
|
72
86
|
- Any mechanical failure OR any blocking review finding means `FAIL`.
|
|
73
87
|
- On FAIL, include a summary section listing each failure reason.
|
|
74
88
|
- Non-blocking review suggestions are noted but do not cause FAIL.
|
|
@@ -84,6 +98,8 @@ Rules:
|
|
|
84
98
|
- Follows Principle 7 — deterministic checks always run first
|
|
85
99
|
- Consumes change-type detection from harness-code-review for per-type checklists
|
|
86
100
|
- Output can be written to `.harness/integrity-report.md` for CI integration
|
|
101
|
+
- Invokes `harness-design` and `harness-accessibility` for design health when `design` config exists
|
|
102
|
+
- Design strictness from config controls whether design findings block the overall result
|
|
87
103
|
|
|
88
104
|
## Success Criteria
|
|
89
105
|
|
|
@@ -102,6 +118,7 @@ Integrity Check: PASS
|
|
|
102
118
|
- Lint: PASS (0 warnings)
|
|
103
119
|
- Types: PASS
|
|
104
120
|
- Security: PASS (0 errors, 0 warnings)
|
|
121
|
+
- Design: PASS (0 errors, 0 warnings)
|
|
105
122
|
- Review: 1 suggestion (0 blocking)
|
|
106
123
|
```
|
|
107
124
|
|
|
@@ -114,6 +131,7 @@ Integrity Check: FAIL
|
|
|
114
131
|
- Types: PASS
|
|
115
132
|
- Security: FAIL (1 error, 0 warnings)
|
|
116
133
|
- [SEC-INJ-002] src/auth/login.ts:42 — SQL query built with string concatenation
|
|
134
|
+
- Design: WARN (0 errors, 2 warnings)
|
|
117
135
|
- Review: 3 findings (1 blocking)
|
|
118
136
|
|
|
119
137
|
Blocking: [SEC-INJ-002] SQL injection — user input passed directly to query without parameterization.
|
|
@@ -66,7 +66,17 @@
|
|
|
66
66
|
- Linting rules that encode architectural decisions
|
|
67
67
|
- Any constraints documented in `AGENTS.md` that are not yet automated
|
|
68
68
|
|
|
69
|
-
5. **Map the
|
|
69
|
+
5. **Map the design system** (when present). Look for:
|
|
70
|
+
- `design-system/tokens.json` — W3C DTCG design tokens (colors, typography, spacing)
|
|
71
|
+
- `design-system/DESIGN.md` — Aesthetic intent, anti-patterns, platform notes
|
|
72
|
+
- `harness.config.json` `design` block — strictness level, enabled platforms, token path
|
|
73
|
+
- Active design skills — check if `harness-design-system`, `harness-accessibility`, `harness-design`, `harness-design-web`, `harness-design-mobile` are available
|
|
74
|
+
- Design constraint violations — run a quick `harness-accessibility` scan to surface any existing issues
|
|
75
|
+
- Token coverage — how many components reference tokens vs. hardcoded values
|
|
76
|
+
|
|
77
|
+
If no design system exists, note this as a potential improvement area.
|
|
78
|
+
|
|
79
|
+
6. **Map the concerns.** Identify areas that need attention:
|
|
70
80
|
- Are there TODOs or FIXMEs in the code?
|
|
71
81
|
- Does `harness validate` pass cleanly, or are there warnings?
|
|
72
82
|
- Are there known blockers in `.harness/state.json`?
|
|
@@ -137,6 +147,14 @@ Graph queries produce a complete architecture map in seconds, including transiti
|
|
|
137
147
|
- <convention 1>
|
|
138
148
|
- <convention 2>
|
|
139
149
|
|
|
150
|
+
## Design System
|
|
151
|
+
|
|
152
|
+
- **Tokens:** [present/absent] ([token count] tokens in [group count] groups)
|
|
153
|
+
- **Aesthetic Intent:** [present/absent] (style: [style], strictness: [level])
|
|
154
|
+
- **Platforms:** [web, mobile, or none configured]
|
|
155
|
+
- **Accessibility:** [baseline scan result — e.g., "3 warnings, 0 errors"]
|
|
156
|
+
- **Design Skills:** [list of available design skills]
|
|
157
|
+
|
|
140
158
|
## Harness Status
|
|
141
159
|
|
|
142
160
|
- Adoption level: <level>
|
|
@@ -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` |
|
|
111
|
-
| `typecheck` or `tsc` script exists in root `package.json` |
|
|
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
|
|