@harness-engineering/cli 1.6.2 → 1.8.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/documentation-maintainer.yaml +3 -1
- package/dist/agents/personas/performance-guardian.yaml +23 -0
- package/dist/agents/personas/planner.yaml +27 -0
- package/dist/agents/personas/verifier.yaml +30 -0
- package/dist/agents/skills/claude-code/align-documentation/SKILL.md +13 -0
- package/dist/agents/skills/claude-code/cleanup-dead-code/SKILL.md +25 -1
- package/dist/agents/skills/claude-code/cleanup-dead-code/skill.yaml +5 -2
- package/dist/agents/skills/claude-code/detect-doc-drift/SKILL.md +12 -0
- package/dist/agents/skills/claude-code/enforce-architecture/SKILL.md +67 -1
- package/dist/agents/skills/claude-code/enforce-architecture/skill.yaml +5 -2
- package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +281 -0
- package/dist/agents/skills/claude-code/harness-accessibility/skill.yaml +51 -0
- package/dist/agents/skills/claude-code/harness-autopilot/SKILL.md +119 -72
- package/dist/agents/skills/claude-code/harness-autopilot/skill.yaml +4 -2
- package/dist/agents/skills/claude-code/harness-brainstorming/SKILL.md +76 -4
- package/dist/agents/skills/claude-code/harness-brainstorming/skill.yaml +2 -0
- package/dist/agents/skills/claude-code/harness-code-review/SKILL.md +487 -234
- package/dist/agents/skills/claude-code/harness-code-review/skill.yaml +15 -2
- package/dist/agents/skills/claude-code/harness-codebase-cleanup/SKILL.md +226 -0
- package/dist/agents/skills/claude-code/harness-codebase-cleanup/skill.yaml +64 -0
- package/dist/agents/skills/claude-code/harness-dependency-health/SKILL.md +35 -6
- 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-docs-pipeline/SKILL.md +460 -0
- package/dist/agents/skills/claude-code/harness-docs-pipeline/skill.yaml +69 -0
- package/dist/agents/skills/claude-code/harness-execution/SKILL.md +73 -8
- package/dist/agents/skills/claude-code/harness-execution/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-hotspot-detector/SKILL.md +32 -6
- package/dist/agents/skills/claude-code/harness-hotspot-detector/skill.yaml +1 -1
- package/dist/agents/skills/claude-code/harness-i18n/SKILL.md +484 -0
- package/dist/agents/skills/claude-code/harness-i18n/skill.yaml +54 -0
- package/dist/agents/skills/claude-code/harness-i18n-process/SKILL.md +388 -0
- package/dist/agents/skills/claude-code/harness-i18n-process/skill.yaml +43 -0
- package/dist/agents/skills/claude-code/harness-i18n-workflow/SKILL.md +512 -0
- package/dist/agents/skills/claude-code/harness-i18n-workflow/skill.yaml +53 -0
- package/dist/agents/skills/claude-code/harness-impact-analysis/SKILL.md +51 -6
- package/dist/agents/skills/claude-code/harness-integrity/SKILL.md +35 -1
- package/dist/agents/skills/claude-code/harness-knowledge-mapper/SKILL.md +46 -5
- 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-perf/SKILL.md +37 -8
- package/dist/agents/skills/claude-code/harness-perf/skill.yaml +3 -0
- package/dist/agents/skills/claude-code/harness-perf-tdd/SKILL.md +17 -4
- package/dist/agents/skills/claude-code/harness-planning/SKILL.md +57 -3
- package/dist/agents/skills/claude-code/harness-planning/skill.yaml +2 -0
- package/dist/agents/skills/claude-code/harness-release-readiness/SKILL.md +29 -9
- package/dist/agents/skills/claude-code/harness-roadmap/SKILL.md +562 -0
- package/dist/agents/skills/claude-code/harness-roadmap/skill.yaml +43 -0
- package/dist/agents/skills/claude-code/harness-security-review/SKILL.md +36 -2
- package/dist/agents/skills/claude-code/harness-security-review/skill.yaml +8 -6
- package/dist/agents/skills/claude-code/harness-security-scan/skill.yaml +1 -1
- package/dist/agents/skills/claude-code/harness-soundness-review/SKILL.md +1267 -0
- package/dist/agents/skills/claude-code/harness-soundness-review/skill.yaml +48 -0
- package/dist/agents/skills/claude-code/harness-test-advisor/SKILL.md +35 -6
- package/dist/agents/skills/claude-code/harness-verification/SKILL.md +66 -0
- package/dist/agents/skills/claude-code/harness-verification/skill.yaml +1 -0
- package/dist/agents/skills/claude-code/harness-verify/SKILL.md +37 -0
- package/dist/agents/skills/claude-code/initialize-harness-project/SKILL.md +15 -1
- package/dist/agents/skills/claude-code/validate-context-engineering/SKILL.md +12 -0
- package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +281 -0
- package/dist/agents/skills/gemini-cli/harness-accessibility/skill.yaml +51 -0
- package/dist/agents/skills/gemini-cli/harness-autopilot/SKILL.md +119 -72
- package/dist/agents/skills/gemini-cli/harness-autopilot/skill.yaml +4 -2
- package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/SKILL.md +226 -0
- package/dist/agents/skills/gemini-cli/harness-codebase-cleanup/skill.yaml +64 -0
- package/dist/agents/skills/gemini-cli/harness-dependency-health/SKILL.md +35 -6
- 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-docs-pipeline/SKILL.md +460 -0
- package/dist/agents/skills/gemini-cli/harness-docs-pipeline/skill.yaml +69 -0
- package/dist/agents/skills/gemini-cli/harness-hotspot-detector/SKILL.md +32 -6
- package/dist/agents/skills/gemini-cli/harness-hotspot-detector/skill.yaml +1 -1
- package/dist/agents/skills/gemini-cli/harness-i18n/SKILL.md +484 -0
- package/dist/agents/skills/gemini-cli/harness-i18n/skill.yaml +54 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-process/SKILL.md +388 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-process/skill.yaml +43 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-workflow/SKILL.md +512 -0
- package/dist/agents/skills/gemini-cli/harness-i18n-workflow/skill.yaml +53 -0
- package/dist/agents/skills/gemini-cli/harness-impact-analysis/SKILL.md +51 -6
- package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/SKILL.md +46 -5
- package/dist/agents/skills/gemini-cli/harness-knowledge-mapper/skill.yaml +1 -1
- package/dist/agents/skills/gemini-cli/harness-perf/SKILL.md +37 -8
- package/dist/agents/skills/gemini-cli/harness-perf/skill.yaml +3 -0
- package/dist/agents/skills/gemini-cli/harness-perf-tdd/SKILL.md +17 -4
- package/dist/agents/skills/gemini-cli/harness-release-readiness/SKILL.md +29 -9
- package/dist/agents/skills/gemini-cli/harness-roadmap/SKILL.md +562 -0
- package/dist/agents/skills/gemini-cli/harness-roadmap/skill.yaml +43 -0
- package/dist/agents/skills/gemini-cli/harness-security-review/skill.yaml +8 -6
- package/dist/agents/skills/gemini-cli/harness-security-scan/skill.yaml +1 -1
- package/dist/agents/skills/gemini-cli/harness-soundness-review/SKILL.md +1267 -0
- package/dist/agents/skills/gemini-cli/harness-soundness-review/skill.yaml +48 -0
- package/dist/agents/skills/gemini-cli/harness-test-advisor/SKILL.md +35 -6
- 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/agents/skills/shared/i18n-knowledge/accessibility/intersection.yaml +142 -0
- package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/encoding.yaml +67 -0
- package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/formatting.yaml +106 -0
- package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/layout.yaml +80 -0
- package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/pluralization.yaml +80 -0
- package/dist/agents/skills/shared/i18n-knowledge/anti-patterns/string-handling.yaml +106 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/android-resources.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/apple-strings.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/backend-patterns.yaml +50 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/flutter-intl.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/i18next.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/react-intl.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/frameworks/vue-i18n.yaml +47 -0
- package/dist/agents/skills/shared/i18n-knowledge/industries/ecommerce.yaml +66 -0
- package/dist/agents/skills/shared/i18n-knowledge/industries/fintech.yaml +66 -0
- package/dist/agents/skills/shared/i18n-knowledge/industries/gaming.yaml +69 -0
- package/dist/agents/skills/shared/i18n-knowledge/industries/healthcare.yaml +66 -0
- package/dist/agents/skills/shared/i18n-knowledge/industries/legal.yaml +66 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/ar.yaml +41 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/de.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/en.yaml +32 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/es.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/fi.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/fr.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/he.yaml +41 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/hi.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/it.yaml +32 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/ja.yaml +38 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/ko.yaml +38 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/nl.yaml +32 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/pl.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/pt.yaml +32 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/ru.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/sv.yaml +32 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/th.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/tr.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hans.yaml +38 -0
- package/dist/agents/skills/shared/i18n-knowledge/locales/zh-Hant.yaml +35 -0
- package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/i18next-mcp.yaml +56 -0
- package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lingo-dev.yaml +56 -0
- package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/lokalise.yaml +60 -0
- package/dist/agents/skills/shared/i18n-knowledge/mcp-interop/tolgee.yaml +60 -0
- package/dist/agents/skills/shared/i18n-knowledge/testing/locale-testing.yaml +107 -0
- package/dist/agents/skills/shared/i18n-knowledge/testing/pseudo-localization.yaml +86 -0
- package/dist/bin/harness.js +64 -4
- package/dist/{chunk-UDWGSL3T.js → chunk-3JWCBVUZ.js} +3 -3
- package/dist/{chunk-IUFFBBYV.js → chunk-LNI4T7R6.js} +179 -61
- package/dist/{chunk-USEYPS7F.js → chunk-SJECMKSS.js} +2250 -40
- package/dist/{dist-4MYPT3OE.js → dist-BDO5GFEM.js} +295 -14
- package/dist/{dist-RBZXXJHG.js → dist-NT3GXHQZ.js} +95 -1
- package/dist/index.d.ts +266 -7
- package/dist/index.js +7 -3
- package/dist/validate-cross-check-2OPGCGGU.js +7 -0
- package/package.json +7 -7
- package/dist/validate-cross-check-CPEPNLOD.js +0 -7
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# Harness Design
|
|
2
|
+
|
|
3
|
+
> Aesthetic direction workflow. Capture design intent, generate DESIGN.md with anti-patterns and platform notes, review components against aesthetic guidelines, and enforce design constraints at configurable strictness levels.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Establishing aesthetic direction for a new or existing project (style, tone, differentiator)
|
|
8
|
+
- When `on_new_feature` triggers fire and the feature has design scope requiring aesthetic guidance
|
|
9
|
+
- Reviewing existing components against declared design intent and anti-patterns
|
|
10
|
+
- Enforcing design constraints via the knowledge graph with configurable strictness
|
|
11
|
+
- Generating or updating `design-system/DESIGN.md` with aesthetic direction, anti-patterns, and platform notes
|
|
12
|
+
- NOT for design token generation or palette selection (use harness-design-system)
|
|
13
|
+
- NOT for accessibility auditing or WCAG compliance (use harness-accessibility)
|
|
14
|
+
- NOT for platform-specific token implementation into CSS/Tailwind/etc. (use harness-design-web/mobile, Phase 5)
|
|
15
|
+
|
|
16
|
+
## Process
|
|
17
|
+
|
|
18
|
+
### Phase 1: INTENT -- Capture Aesthetic Intent
|
|
19
|
+
|
|
20
|
+
1. **Read existing design artifacts.** Search for:
|
|
21
|
+
- `design-system/DESIGN.md` -- existing aesthetic direction documentation (from harness-design-system output)
|
|
22
|
+
- `design-system/tokens.json` -- existing W3C DTCG tokens (palette, typography, spacing defined by harness-design-system)
|
|
23
|
+
- `harness.config.json` -- project configuration for design settings
|
|
24
|
+
|
|
25
|
+
2. **Check harness configuration.** Read `harness.config.json` for:
|
|
26
|
+
- `design.strictness` -- enforcement level (`strict`, `standard`, `permissive`). If not set, default to `standard`.
|
|
27
|
+
- `design.platforms` -- which platforms are enabled (web, mobile)
|
|
28
|
+
- `design.aestheticIntent` -- path to design intent doc (default: `design-system/DESIGN.md`)
|
|
29
|
+
|
|
30
|
+
3. **Load industry profile.** If an industry is specified (via CLI `--industry` arg or config), read the industry profile from `agents/skills/shared/design-knowledge/industries/{industry}.yaml`. Available industries include: `saas`, `fintech`, `healthcare`, `ecommerce`, `creative`, `emerging-tech`, `lifestyle`, `services`. The profile provides sector-specific guidance on:
|
|
31
|
+
- Recommended visual style and tone
|
|
32
|
+
- Industry conventions and user expectations
|
|
33
|
+
- Regulatory or cultural considerations
|
|
34
|
+
- Common anti-patterns for the sector
|
|
35
|
+
|
|
36
|
+
4. **Capture user intent.** Ask the user to define:
|
|
37
|
+
- **Style:** minimal, expressive, corporate, playful, editorial, or custom
|
|
38
|
+
- **Tone:** warm, cool, neutral, bold, muted, or custom
|
|
39
|
+
- **Key differentiator:** what makes this product's visual identity unique
|
|
40
|
+
- **Anti-patterns:** specific design choices to explicitly avoid (e.g., "no gradients on data elements," "no decorative borders on cards")
|
|
41
|
+
|
|
42
|
+
5. **Load shared design knowledge.** Read anti-pattern awareness from `agents/skills/shared/design-knowledge/`:
|
|
43
|
+
- `palettes/curated.yaml` -- curated palettes to understand which aesthetic families are available
|
|
44
|
+
- `typography/pairings.yaml` -- typography pairings to understand which font combinations are recommended
|
|
45
|
+
- Industry-specific anti-pattern guidance from the loaded industry profile
|
|
46
|
+
|
|
47
|
+
6. **Confirm intent before proceeding.** Present a summary of the captured aesthetic intent to the user. This is a hard gate -- no DESIGN.md generation without the user confirming their aesthetic intent.
|
|
48
|
+
|
|
49
|
+
### Phase 2: DIRECTION -- Generate DESIGN.md
|
|
50
|
+
|
|
51
|
+
1. **Generate or update `design-system/DESIGN.md`.** The document must contain the following sections:
|
|
52
|
+
|
|
53
|
+
**Aesthetic Direction:**
|
|
54
|
+
- Style declaration (the chosen style and what it means for this project)
|
|
55
|
+
- Tone description (how the tone manifests in color usage, typography weight, spacing density)
|
|
56
|
+
- Key differentiator (the unique visual identity aspect and how it is expressed)
|
|
57
|
+
|
|
58
|
+
**Anti-Patterns:**
|
|
59
|
+
- Project-specific anti-patterns (from user input in Phase 1)
|
|
60
|
+
- Industry-informed anti-patterns (from the loaded industry profile)
|
|
61
|
+
- Each anti-pattern includes: name, description, example of what NOT to do, and why it conflicts with the declared intent
|
|
62
|
+
|
|
63
|
+
**Platform Notes:**
|
|
64
|
+
- Web-specific guidance (CSS strategy, responsive behavior, animation preferences)
|
|
65
|
+
- Mobile-specific guidance (touch targets, native component usage, platform conventions)
|
|
66
|
+
- Cross-platform consistency rules (which elements must be identical vs. platform-adapted)
|
|
67
|
+
|
|
68
|
+
**Strictness Override:**
|
|
69
|
+
- Current `designStrictness` level and what it means
|
|
70
|
+
- Instructions for changing strictness in `harness.config.json`
|
|
71
|
+
- Behavior differences per level:
|
|
72
|
+
- `permissive` -- all design violations reported as `info` (nothing blocks)
|
|
73
|
+
- `standard` -- anti-pattern and accessibility violations are `warn`, critical violations are `error` (default)
|
|
74
|
+
- `strict` -- accessibility violations are `error` (blocks CI/PR merge), anti-pattern violations are `warn`
|
|
75
|
+
|
|
76
|
+
2. **Populate the knowledge graph.** If a graph exists at `.harness/graph/`:
|
|
77
|
+
- Create an `AestheticIntent` node with properties: style, tone, differentiator, strictness level. Use `DesignIngestor` from `packages/graph/src/ingest/DesignIngestor.ts` for graph ingestion.
|
|
78
|
+
- Create a `DECLARES_INTENT` edge from the project node to the `AestheticIntent` node.
|
|
79
|
+
- This enables downstream skills (harness-accessibility, harness-impact-analysis) to query the declared design intent.
|
|
80
|
+
|
|
81
|
+
3. **Run harness validate.** After generating DESIGN.md, verify the project still passes all constraints. The new file must not break existing validations.
|
|
82
|
+
|
|
83
|
+
### Phase 3: REVIEW -- Review Components Against Design Intent
|
|
84
|
+
|
|
85
|
+
1. **Scan for anti-pattern violations.** Use Grep to search the codebase for patterns that match declared anti-patterns:
|
|
86
|
+
- Hardcoded color values not present in `design-system/tokens.json` (suggests off-brand color usage)
|
|
87
|
+
- Font families flagged as anti-patterns in the design intent (e.g., decorative fonts in a minimal project)
|
|
88
|
+
- Layout patterns on the forbidden list (e.g., excessive drop shadows in a flat design, gradients on data elements)
|
|
89
|
+
- CSS properties or values that contradict the declared style (e.g., rounded corners in a sharp-edge design)
|
|
90
|
+
|
|
91
|
+
2. **Load detection rules from shared design knowledge.** Read from `agents/skills/shared/design-knowledge/`:
|
|
92
|
+
- `anti-patterns/typography.yaml` — font combinations, size, weight, and line-height issues that clash with the declared style
|
|
93
|
+
- `anti-patterns/color.yaml` — hardcoded colors, insufficient contrast, color-only indicators that undermine the declared tone
|
|
94
|
+
- `anti-patterns/layout.yaml` — spacing inconsistencies, missing touch targets, fixed-width containers
|
|
95
|
+
- `anti-patterns/motion.yaml` — missing prefers-reduced-motion, long animations, scroll-jacking
|
|
96
|
+
- `industries/{industry}.yaml` — industry-specific rules from the loaded industry profile
|
|
97
|
+
|
|
98
|
+
3. **Cross-reference with graph constraints.** If a graph exists at `.harness/graph/`:
|
|
99
|
+
- Query for existing `VIOLATES_DESIGN` edges using `DesignConstraintAdapter` from `packages/graph/src/constraints/DesignConstraintAdapter.ts`
|
|
100
|
+
- Compare current findings against previously recorded violations
|
|
101
|
+
- Identify new violations and resolved violations
|
|
102
|
+
|
|
103
|
+
4. **Assign severity based on `designStrictness`:**
|
|
104
|
+
- `permissive` -- all findings are `info` severity
|
|
105
|
+
- `standard` -- anti-pattern violations and accessibility-related findings are `warn`, critical design constraint violations are `error`
|
|
106
|
+
- `strict` -- accessibility violations are `error` (blocks), anti-pattern violations are `warn`
|
|
107
|
+
|
|
108
|
+
5. **Report findings.** Present each finding with:
|
|
109
|
+
- File path and line number
|
|
110
|
+
- Violation description and which anti-pattern or design constraint it violates
|
|
111
|
+
- Severity level (based on current strictness)
|
|
112
|
+
- Suggested remediation
|
|
113
|
+
|
|
114
|
+
### Phase 4: ENFORCE -- Surface and Record Violations
|
|
115
|
+
|
|
116
|
+
1. **Create constraint nodes in the graph.** For each violated design rule, if a graph exists at `.harness/graph/`:
|
|
117
|
+
- Create a `DesignConstraint` node for the rule being violated (if one does not already exist)
|
|
118
|
+
- Create a `VIOLATES_DESIGN` edge from the violating component to the `DesignConstraint` node
|
|
119
|
+
- Use `DesignConstraintAdapter` from `packages/graph/src/constraints/DesignConstraintAdapter.ts` to manage constraint creation and violation recording
|
|
120
|
+
|
|
121
|
+
2. **Format violation output.** Each violation follows a numbered format:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
DESIGN-001 [warn] Anti-pattern: gradient used on data visualization element
|
|
125
|
+
File: src/components/Chart.tsx
|
|
126
|
+
Line: 42
|
|
127
|
+
Constraint: No gradients on data elements
|
|
128
|
+
Intent: Style "minimal" prohibits decorative effects on informational components
|
|
129
|
+
Fix: Replace linear-gradient with solid color from token "neutral.100"
|
|
130
|
+
|
|
131
|
+
DESIGN-002 [error] Off-brand color: hardcoded #ff6b35 not in token set
|
|
132
|
+
File: src/components/Alert.tsx
|
|
133
|
+
Line: 18
|
|
134
|
+
Constraint: All colors must reference design tokens
|
|
135
|
+
Intent: Tone "cool" conflicts with warm orange accent
|
|
136
|
+
Fix: Use token "semantic.warning" (#f59e0b) or add color to tokens.json via harness-design-system
|
|
137
|
+
|
|
138
|
+
DESIGN-003 [info] Typography: decorative font "Playfair Display" used in component
|
|
139
|
+
File: src/components/Hero.tsx
|
|
140
|
+
Line: 8
|
|
141
|
+
Constraint: Heading font must match declared typography pairing
|
|
142
|
+
Intent: Style "minimal" uses Inter for all headings
|
|
143
|
+
Fix: Replace with token "typography.heading.fontFamily"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
3. **Control severity by `designStrictness`:**
|
|
147
|
+
- `permissive` -- all violations output as `info` (DESIGN-001 [info], DESIGN-002 [info], etc.)
|
|
148
|
+
- `standard` -- anti-patterns and a11y = `warn`, off-brand tokens = `error` (default)
|
|
149
|
+
- `strict` -- a11y violations = `error` (blocks CI), anti-patterns = `warn`, off-brand tokens = `error`
|
|
150
|
+
|
|
151
|
+
4. **Run harness validate.** After recording violations in the graph, run validation to ensure the enforcement pass is consistent with the project state.
|
|
152
|
+
|
|
153
|
+
## Harness Integration
|
|
154
|
+
|
|
155
|
+
- **`harness validate`** -- Run after generating DESIGN.md and after enforcement passes. Design violations surface as constraint violations at the configured strictness level.
|
|
156
|
+
- **`harness scan`** -- Run after changes to refresh the knowledge graph. Updated graph enables accurate violation detection and impact analysis.
|
|
157
|
+
- **`DesignIngestor`** (`packages/graph/src/ingest/DesignIngestor.ts`) -- Parses `tokens.json` and `DESIGN.md` to create graph nodes representing the design system. Creates `AestheticIntent` nodes and `DECLARES_INTENT` edges during the DIRECTION phase.
|
|
158
|
+
- **`DesignConstraintAdapter`** (`packages/graph/src/constraints/DesignConstraintAdapter.ts`) -- Manages `DesignConstraint` nodes and `VIOLATES_DESIGN` edges in the graph. Reads `design.strictness` to control violation severity. Used during REVIEW and ENFORCE phases.
|
|
159
|
+
|
|
160
|
+
**Graph naming convention:** This skill uses PascalCase for node types (`AestheticIntent`, `DesignToken`, `DesignConstraint`) and UPPER_SNAKE for edge types (`DECLARES_INTENT`, `VIOLATES_DESIGN`, `USES_TOKEN`, `PLATFORM_BINDING`) as conceptual labels. The graph schema registers these as snake_case identifiers (`aesthetic_intent`, `design_token`, `design_constraint`, `declares_intent`, `violates_design`, `uses_token`, `platform_binding`). The adapter classes (`DesignIngestor`, `DesignConstraintAdapter`) handle the mapping — always use the adapters rather than constructing graph queries with raw type names.
|
|
161
|
+
|
|
162
|
+
- **`harness-design-system`** -- Dependency. This skill reads tokens and design intent generated by harness-design-system. Token-level issues (palette changes, new colors) are resolved by running harness-design-system, not this skill.
|
|
163
|
+
- **`harness-impact-analysis`** -- When design tokens change, impact analysis traces which components consume affected tokens. Use this to determine which components need re-review after token updates.
|
|
164
|
+
|
|
165
|
+
## Success Criteria
|
|
166
|
+
|
|
167
|
+
- `design-system/DESIGN.md` exists with all required sections: Aesthetic Direction, Anti-Patterns, Platform Notes, Strictness Override
|
|
168
|
+
- Anti-patterns are detected in the codebase and reported with file paths, line numbers, and severity
|
|
169
|
+
- `designStrictness` configuration is read from `harness.config.json` and respected in all severity assignments
|
|
170
|
+
- `AestheticIntent` node created in the knowledge graph with style, tone, differentiator, and strictness properties
|
|
171
|
+
- `DECLARES_INTENT` edge connects the project to the aesthetic intent node
|
|
172
|
+
- `DesignConstraint` nodes created for each violated design rule
|
|
173
|
+
- `VIOLATES_DESIGN` edges connect violating components to their constraint nodes
|
|
174
|
+
- Violations output in numbered format (DESIGN-001, DESIGN-002, etc.) with severity matching strictness level
|
|
175
|
+
- `harness validate` passes after DESIGN.md generation and enforcement
|
|
176
|
+
- User confirmed aesthetic intent before DESIGN.md generation (hard gate)
|
|
177
|
+
|
|
178
|
+
## Examples
|
|
179
|
+
|
|
180
|
+
### Example: SaaS Analytics Dashboard Aesthetic Direction
|
|
181
|
+
|
|
182
|
+
**Context:** A SaaS analytics dashboard project. Industry: `saas`. Design tokens already generated by harness-design-system. No existing DESIGN.md aesthetic direction.
|
|
183
|
+
|
|
184
|
+
**INTENT capture:**
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
Industry profile: Loaded (saas) -- recommends professional, data-focused aesthetic
|
|
188
|
+
Style: Minimal
|
|
189
|
+
Tone: Cool, professional
|
|
190
|
+
Differentiator: Dense information display with generous whitespace between sections
|
|
191
|
+
Anti-patterns: No gradients on data elements, no decorative borders on cards,
|
|
192
|
+
no more than 2 font weights per component
|
|
193
|
+
Strictness: standard (from harness.config.json)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**DIRECTION output (DESIGN.md excerpt):**
|
|
197
|
+
|
|
198
|
+
```markdown
|
|
199
|
+
## Aesthetic Direction
|
|
200
|
+
|
|
201
|
+
**Style:** Minimal -- clean lines, flat surfaces, no decorative elements that do not serve
|
|
202
|
+
an informational purpose. Every visual element must earn its place by conveying data or
|
|
203
|
+
guiding the user's eye.
|
|
204
|
+
|
|
205
|
+
**Tone:** Cool, professional -- slate and blue palette dominates. Warm colors reserved
|
|
206
|
+
exclusively for semantic states (warning, error). No warm accents in neutral UI.
|
|
207
|
+
|
|
208
|
+
**Differentiator:** Dense information display with generous whitespace between sections.
|
|
209
|
+
Components are compact internally but breathe externally. Card padding is tight (12px),
|
|
210
|
+
but gaps between cards are generous (24px+).
|
|
211
|
+
|
|
212
|
+
## Anti-Patterns
|
|
213
|
+
|
|
214
|
+
| Pattern | Description | Why It Conflicts |
|
|
215
|
+
| -------------------------- | -------------------------------------------- | ------------------------------------------ |
|
|
216
|
+
| Gradients on data elements | linear-gradient on charts, tables, cards | Minimal style: flat surfaces only |
|
|
217
|
+
| Decorative card borders | border with color on .card elements | Minimal style: borders are structural only |
|
|
218
|
+
| Excess font weights | More than 2 font-weight values per component | Minimal style: typographic restraint |
|
|
219
|
+
|
|
220
|
+
## Strictness Override
|
|
221
|
+
|
|
222
|
+
Current level: **standard**
|
|
223
|
+
|
|
224
|
+
To change, update `harness.config.json`:
|
|
225
|
+
"design": { "strictness": "strict" | "standard" | "permissive" }
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**REVIEW findings:**
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
Found 3 anti-pattern violations in 2 files:
|
|
232
|
+
|
|
233
|
+
DESIGN-001 [warn] Gradient on data element
|
|
234
|
+
File: src/components/RevenueChart.tsx:42
|
|
235
|
+
Constraint: No gradients on data elements
|
|
236
|
+
Fix: Replace linear-gradient(#3b82f6, #1d4ed8) with solid token "primary.500"
|
|
237
|
+
|
|
238
|
+
DESIGN-002 [warn] Decorative border on card
|
|
239
|
+
File: src/components/MetricCard.tsx:15
|
|
240
|
+
Constraint: No decorative borders on cards
|
|
241
|
+
Fix: Remove border-color: #3b82f6, use border-color: transparent or remove border
|
|
242
|
+
|
|
243
|
+
DESIGN-003 [info] Three font weights in one component
|
|
244
|
+
File: src/components/MetricCard.tsx:8
|
|
245
|
+
Constraint: Max 2 font weights per component
|
|
246
|
+
Fix: Consolidate font-weight values to 400 (body) and 600 (heading) only
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
## Gates
|
|
250
|
+
|
|
251
|
+
These are hard stops. Violating any gate means the process has broken down.
|
|
252
|
+
|
|
253
|
+
- **No DESIGN.md generated without the user confirming aesthetic intent.** The INTENT phase must end with explicit user confirmation of style, tone, differentiator, and anti-patterns. Do not generate based on assumptions.
|
|
254
|
+
- **No enforcement without reading tokens from harness-design-system.** The REVIEW and ENFORCE phases require `design-system/tokens.json` to exist. If tokens have not been generated, instruct the user to run harness-design-system first.
|
|
255
|
+
- **Strictness must be read from configuration, not assumed.** Read `design.strictness` from `harness.config.json`. If the key does not exist, default to `standard` and report the default to the user. Never hardcode a strictness level.
|
|
256
|
+
- **No anti-pattern detection without a declared intent.** The REVIEW phase requires an existing DESIGN.md with declared anti-patterns. If no intent has been captured, run the INTENT and DIRECTION phases first.
|
|
257
|
+
- **No graph mutations without validating node types.** When creating `AestheticIntent`, `DesignConstraint`, or `VIOLATES_DESIGN` edges, verify the node and edge types are registered in the graph schema before writing.
|
|
258
|
+
|
|
259
|
+
## Escalation
|
|
260
|
+
|
|
261
|
+
- **When the user cannot articulate a style or tone:** Suggest industry-based defaults from the loaded industry profile. Present 2-3 options with examples: "Based on the saas industry profile, common styles are: (1) Minimal -- clean, data-focused, (2) Corporate -- structured, trustworthy, (3) Expressive -- colorful, engaging. Which resonates most?"
|
|
262
|
+
- **When declared anti-patterns conflict with existing code:** Present a migration path rather than flagging every instance as a violation. Report: "Found 47 instances of gradients on data elements. Recommend a phased migration: (1) Update new components immediately, (2) Schedule legacy component updates over 3 sprints. Set strictness to 'permissive' during migration to avoid blocking CI."
|
|
263
|
+
- **When tokens do not exist yet:** Do not attempt to infer a token set. 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 for aesthetic direction."
|
|
264
|
+
- **When strictness level conflicts with team velocity:** Explain the tradeoffs: "Strict mode blocks PRs on any design violation. If this is slowing the team, consider 'standard' mode which blocks only on critical violations (off-brand colors, accessibility) and warns on anti-patterns."
|
|
265
|
+
- **When the knowledge graph is unavailable:** Skip graph operations in DIRECTION and ENFORCE phases. Log: "Graph not available at `.harness/graph/` -- skipping AestheticIntent node creation and violation recording. Run `harness scan` later to populate." Continue with file-based operations.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: harness-design
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: Aesthetic direction workflow, anti-pattern enforcement, DESIGN.md generation, and strictness configuration
|
|
4
|
+
cognitive_mode: advisory-guide
|
|
5
|
+
triggers:
|
|
6
|
+
- manual
|
|
7
|
+
- on_new_feature
|
|
8
|
+
platforms:
|
|
9
|
+
- claude-code
|
|
10
|
+
- gemini-cli
|
|
11
|
+
tools:
|
|
12
|
+
- Bash
|
|
13
|
+
- Read
|
|
14
|
+
- Write
|
|
15
|
+
- Edit
|
|
16
|
+
- Glob
|
|
17
|
+
- Grep
|
|
18
|
+
cli:
|
|
19
|
+
command: harness skill run harness-design
|
|
20
|
+
args:
|
|
21
|
+
- name: path
|
|
22
|
+
description: Project root path
|
|
23
|
+
required: false
|
|
24
|
+
- name: strictness
|
|
25
|
+
description: Override strictness level (strict, standard, permissive)
|
|
26
|
+
required: false
|
|
27
|
+
- name: industry
|
|
28
|
+
description: Industry vertical for aesthetic recommendations
|
|
29
|
+
required: false
|
|
30
|
+
mcp:
|
|
31
|
+
tool: run_skill
|
|
32
|
+
input:
|
|
33
|
+
skill: harness-design
|
|
34
|
+
path: string
|
|
35
|
+
type: flexible
|
|
36
|
+
phases:
|
|
37
|
+
- name: intent
|
|
38
|
+
description: Capture aesthetic intent, style, tone, and differentiator
|
|
39
|
+
required: true
|
|
40
|
+
- name: direction
|
|
41
|
+
description: Generate DESIGN.md with aesthetic direction, anti-patterns, and platform notes
|
|
42
|
+
required: true
|
|
43
|
+
- name: review
|
|
44
|
+
description: Review existing components against design intent and anti-patterns
|
|
45
|
+
required: false
|
|
46
|
+
- name: enforce
|
|
47
|
+
description: Enforce design constraints via graph, surface violations by strictness level
|
|
48
|
+
required: false
|
|
49
|
+
state:
|
|
50
|
+
persistent: false
|
|
51
|
+
files: []
|
|
52
|
+
depends_on:
|
|
53
|
+
- harness-design-system
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
# Harness Design Mobile
|
|
2
|
+
|
|
3
|
+
> Token-bound mobile component generation. Scaffold from design tokens and aesthetic intent, implement with React Native, SwiftUI, Flutter, or Compose patterns following platform-specific design rules, and verify every value references the token set with native convention compliance.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Generating new mobile components that must conform to the project's design system tokens
|
|
8
|
+
- When `on_new_feature` triggers fire with mobile UI scope requiring token-bound component generation
|
|
9
|
+
- When `on_commit` triggers fire and new mobile components contain hardcoded design values that should reference tokens
|
|
10
|
+
- Implementing design intent from `design-system/DESIGN.md` into platform-native styling (StyleSheet, SwiftUI modifiers, Flutter ThemeData, Compose MaterialTheme)
|
|
11
|
+
- Ensuring components follow platform-specific guidelines (iOS Human Interface Guidelines, Material Design 3, Flutter design patterns)
|
|
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 web platform components (use harness-design-web)
|
|
16
|
+
|
|
17
|
+
## Process
|
|
18
|
+
|
|
19
|
+
### Phase 1: SCAFFOLD — Read Tokens, Detect Platform, 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
|
|
23
|
+
- Typography tokens: heading and body font families, font weights, font sizes, line heights
|
|
24
|
+
- Spacing tokens: spacing scale values
|
|
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)
|
|
29
|
+
- Anti-patterns to avoid
|
|
30
|
+
- Platform-specific mobile notes (touch targets, native component usage, platform conventions)
|
|
31
|
+
- If `design-system/DESIGN.md` does not exist, warn the user and proceed with tokens only.
|
|
32
|
+
|
|
33
|
+
3. **Check harness configuration.** Read `harness.config.json` for:
|
|
34
|
+
- `design.strictness` — enforcement level. Default to `standard`.
|
|
35
|
+
- `design.platforms` — confirm `mobile` is in the platforms list.
|
|
36
|
+
|
|
37
|
+
4. **Detect mobile platform.** Scan the project for:
|
|
38
|
+
- **React Native:** `package.json` contains `react-native` or `expo`, `.tsx` files with `StyleSheet` or `react-native` imports
|
|
39
|
+
- **SwiftUI:** `.swift` files with `import SwiftUI`, `Package.swift` or `.xcodeproj` exists
|
|
40
|
+
- **Flutter:** `pubspec.yaml` exists, `.dart` files with `import 'package:flutter/`
|
|
41
|
+
- **Compose:** `build.gradle.kts` with `compose` dependencies, `.kt` files with `@Composable`
|
|
42
|
+
- If the user specified `--platform`, use that override.
|
|
43
|
+
|
|
44
|
+
5. **Load platform-specific rules.** Based on detected platform, read platform design guidelines from `agents/skills/shared/design-knowledge/platform-rules/`:
|
|
45
|
+
- **iOS (SwiftUI/React Native on iOS):** Read `ios.yaml` — Human Interface Guidelines, safe area insets, navigation bar patterns, tab bar conventions, dynamic type support, SF Symbols integration
|
|
46
|
+
- **Android (Compose/React Native on Android):** Read `android.yaml` — Material Design 3, elevation system, shape system, dynamic color, navigation patterns, edge-to-edge layout
|
|
47
|
+
- **Flutter:** Read `flutter.yaml` — Flutter design patterns, ThemeData structure, widget composition, adaptive layouts, platform channel considerations
|
|
48
|
+
- **React Native cross-platform:** Read both `ios.yaml` and `android.yaml` — platform-specific overrides via `Platform.select`, safe area handling, navigation library patterns
|
|
49
|
+
|
|
50
|
+
6. **Load anti-pattern definitions.** Read anti-pattern files from `agents/skills/shared/design-knowledge/anti-patterns/`:
|
|
51
|
+
- `typography.yaml` — typographic anti-patterns (too many fonts, inconsistent scales)
|
|
52
|
+
- `color.yaml` — color anti-patterns (hardcoded hex, insufficient contrast)
|
|
53
|
+
- `layout.yaml` — layout anti-patterns (magic numbers, inconsistent spacing)
|
|
54
|
+
- `motion.yaml` — motion anti-patterns (excessive animation, missing reduced-motion)
|
|
55
|
+
|
|
56
|
+
7. **Build token-to-platform mapping.** Create a lookup table mapping tokens to platform-native representations:
|
|
57
|
+
- **React Native:** `color.primary.500` maps to `StyleSheet` value or themed constant
|
|
58
|
+
- **SwiftUI:** `color.primary.500` maps to `Color("primary500")` in asset catalog or `Color(hex:)` extension
|
|
59
|
+
- **Flutter:** `color.primary.500` maps to `Theme.of(context).colorScheme.primary` or custom `AppColors.primary500`
|
|
60
|
+
- **Compose:** `color.primary.500` maps to `MaterialTheme.colorScheme.primary` or custom `AppTheme.colors.primary500`
|
|
61
|
+
|
|
62
|
+
8. **Plan component structure.** Define:
|
|
63
|
+
- Component file path(s) following platform conventions
|
|
64
|
+
- Props/parameters interface
|
|
65
|
+
- Which tokens will be consumed
|
|
66
|
+
- Platform-specific considerations (safe areas, touch targets, dynamic type)
|
|
67
|
+
- Present plan to user before proceeding.
|
|
68
|
+
|
|
69
|
+
### Phase 2: IMPLEMENT — Generate Token-Bound Mobile Components
|
|
70
|
+
|
|
71
|
+
1. **Generate platform-specific component code.** Based on detected platform:
|
|
72
|
+
|
|
73
|
+
**React Native (TypeScript):**
|
|
74
|
+
- Functional component with TypeScript props interface
|
|
75
|
+
- All colors via themed StyleSheet or token constants (no hardcoded hex values)
|
|
76
|
+
- Typography via scaled text styles referencing token font families and sizes
|
|
77
|
+
- Spacing via token-derived constants in StyleSheet
|
|
78
|
+
- Platform-specific overrides via `Platform.select` where iOS and Android differ
|
|
79
|
+
- Safe area handling via `useSafeAreaInsets` for edge-to-edge content
|
|
80
|
+
|
|
81
|
+
**SwiftUI:**
|
|
82
|
+
- View struct with typed properties
|
|
83
|
+
- Colors from asset catalog or Color extension referencing tokens
|
|
84
|
+
- Typography via custom `Font` extensions mapping to token values
|
|
85
|
+
- Spacing via token-derived constants
|
|
86
|
+
- Dynamic Type support via `.font(.body)` or custom scaled fonts
|
|
87
|
+
- Safe area respect via `.safeAreaInset` modifiers
|
|
88
|
+
- iOS Human Interface Guidelines compliance (44pt minimum touch targets)
|
|
89
|
+
|
|
90
|
+
**Flutter (Dart):**
|
|
91
|
+
- StatelessWidget or StatefulWidget with typed constructor parameters
|
|
92
|
+
- Colors via `Theme.of(context)` or custom `AppColors` class referencing tokens
|
|
93
|
+
- Typography via `Theme.of(context).textTheme` or custom `AppTypography`
|
|
94
|
+
- Spacing via token-derived constants class
|
|
95
|
+
- Material Design 3 compliance (elevation, shape, dynamic color)
|
|
96
|
+
- Adaptive layout via `LayoutBuilder` or `MediaQuery` for responsive behavior
|
|
97
|
+
|
|
98
|
+
**Compose (Kotlin):**
|
|
99
|
+
- `@Composable` function with typed parameters
|
|
100
|
+
- Colors via `MaterialTheme.colorScheme` or custom theme referencing tokens
|
|
101
|
+
- Typography via `MaterialTheme.typography` or custom type scale
|
|
102
|
+
- Spacing via token-derived `Dp` constants
|
|
103
|
+
- Material Design 3 compliance (Surface, ElevatedCard, shape system)
|
|
104
|
+
- Modifier chains for layout following Compose conventions
|
|
105
|
+
|
|
106
|
+
2. **Apply platform-specific rules:**
|
|
107
|
+
- **Touch targets:** Minimum 44x44pt (iOS) or 48x48dp (Android/Material)
|
|
108
|
+
- **Safe areas:** All platforms handle notch/status bar/navigation bar correctly
|
|
109
|
+
- **Typography scaling:** Support dynamic type (iOS), font scale (Android), and text scale factor (Flutter)
|
|
110
|
+
- **Elevation/shadows:** Platform-appropriate (iOS shadow, Material elevation, Flutter elevation)
|
|
111
|
+
- **Navigation patterns:** Platform-native navigation (UINavigationController, NavHost, Navigator)
|
|
112
|
+
|
|
113
|
+
3. **Add USES_TOKEN annotations.** Insert platform-appropriate comments documenting token consumption:
|
|
114
|
+
```
|
|
115
|
+
// @design-token color.primary.500 — primary action background
|
|
116
|
+
// @design-token typography.heading.fontFamily — section heading
|
|
117
|
+
// @design-token spacing.md — card internal padding
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Phase 3: VERIFY — Check Token Binding and Platform Compliance
|
|
121
|
+
|
|
122
|
+
1. **Scan for hardcoded values.** Search generated files for:
|
|
123
|
+
- Hardcoded color values: hex codes, `UIColor(red:green:blue:)`, `Color(0xFF...)`, `Color(red:green:blue:)`
|
|
124
|
+
- Hardcoded font families: string literals for font names not referencing tokens
|
|
125
|
+
- Hardcoded spacing: raw numeric values in padding/margin not from the token scale
|
|
126
|
+
|
|
127
|
+
2. **Verify token coverage.** For every design value in generated components:
|
|
128
|
+
- Confirm it resolves to a token in `design-system/tokens.json`
|
|
129
|
+
- Confirm the token path is valid
|
|
130
|
+
- Report orphan references
|
|
131
|
+
|
|
132
|
+
3. **Check platform guideline compliance:**
|
|
133
|
+
- **iOS:** Touch targets >= 44pt, safe area respected, dynamic type supported
|
|
134
|
+
- **Android/Material:** Touch targets >= 48dp, edge-to-edge layout, Material 3 components used
|
|
135
|
+
- **Flutter:** ThemeData used consistently, no hardcoded Material values
|
|
136
|
+
- **React Native:** Platform.select used for iOS/Android differences, safe area handled
|
|
137
|
+
|
|
138
|
+
4. **Check anti-pattern compliance.** Cross-reference against `design-system/DESIGN.md` anti-patterns and definitions in `agents/skills/shared/design-knowledge/anti-patterns/`.
|
|
139
|
+
|
|
140
|
+
5. **Query the knowledge graph.** If available at `.harness/graph/`:
|
|
141
|
+
- Verify `DesignToken` nodes exist for all referenced tokens
|
|
142
|
+
- Verify `PLATFORM_BINDING` edges exist for the target mobile platform
|
|
143
|
+
- Check `VIOLATES_DESIGN` edges via `DesignConstraintAdapter`
|
|
144
|
+
|
|
145
|
+
6. **Assign severity based on `designStrictness`:**
|
|
146
|
+
- `permissive` — all findings are `info`
|
|
147
|
+
- `standard` — hardcoded values are `warn`, platform guideline violations are `warn`, accessibility violations are `error`
|
|
148
|
+
- `strict` — hardcoded values are `error` (blocks), platform violations are `warn`, accessibility violations are `error`
|
|
149
|
+
|
|
150
|
+
7. **Report verification results:**
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
MOBILE-001 [warn] Hardcoded color Color(0xFF3B82F6) — should reference token
|
|
154
|
+
File: lib/widgets/action_button.dart:15
|
|
155
|
+
Fix: Use Theme.of(context).colorScheme.primary or AppColors.primary500
|
|
156
|
+
|
|
157
|
+
MOBILE-002 [warn] Touch target 32dp below minimum 48dp (Material Design 3)
|
|
158
|
+
File: lib/widgets/icon_action.dart:22
|
|
159
|
+
Fix: Set minimumSize to Size(48, 48) in ButtonStyle
|
|
160
|
+
|
|
161
|
+
MOBILE-003 [info] Missing dynamic type support
|
|
162
|
+
File: Sources/Views/ProductCard.swift:18
|
|
163
|
+
Fix: Use .font(.body) instead of .font(.system(size: 16))
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
8. **Run `harness validate`.** Confirm new components integrate cleanly.
|
|
167
|
+
|
|
168
|
+
## Harness Integration
|
|
169
|
+
|
|
170
|
+
- **`harness validate`** — Run after generating components to verify project health.
|
|
171
|
+
- **`harness scan`** — Run after component generation to update the knowledge graph with `USES_TOKEN` and `PLATFORM_BINDING` edges.
|
|
172
|
+
- **`DesignIngestor`** (`packages/graph/src/ingest/DesignIngestor.ts`) — Verifies `DesignToken` nodes exist for all tokens referenced by generated components.
|
|
173
|
+
- **`DesignConstraintAdapter`** (`packages/graph/src/constraints/DesignConstraintAdapter.ts`) — Checks for `VIOLATES_DESIGN` edges during VERIFY phase. Reports constraint violations at configured strictness.
|
|
174
|
+
- **`harness-design-system`** — Dependency. Provides `design-system/tokens.json`. If tokens do not exist, instruct user to run harness-design-system first.
|
|
175
|
+
- **`harness-design`** — Dependency. Provides `design-system/DESIGN.md` with aesthetic intent and anti-patterns.
|
|
176
|
+
- **`harness-impact-analysis`** — Traces token changes to affected mobile components via `USES_TOKEN` edges.
|
|
177
|
+
|
|
178
|
+
**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.
|
|
179
|
+
|
|
180
|
+
## Success Criteria
|
|
181
|
+
|
|
182
|
+
- Generated mobile components reference design tokens exclusively — no hardcoded color, font, or spacing values
|
|
183
|
+
- Platform detection correctly identifies React Native, SwiftUI, Flutter, or Compose projects
|
|
184
|
+
- Token-to-platform mapping produces correct output for each mobile platform
|
|
185
|
+
- Platform-specific rules are enforced (touch targets, safe areas, dynamic type, Material 3 compliance)
|
|
186
|
+
- `@design-token` annotations are present for every consumed token
|
|
187
|
+
- Anti-pattern compliance check catches violations from `design-system/DESIGN.md`
|
|
188
|
+
- Verification report uses severity levels matching `design.strictness` configuration
|
|
189
|
+
- `harness validate` passes after component generation
|
|
190
|
+
|
|
191
|
+
## Examples
|
|
192
|
+
|
|
193
|
+
### Example: React Native Card Component
|
|
194
|
+
|
|
195
|
+
**Context:** Fitness app. React Native with Expo. Tokens from harness-design-system. Design intent: expressive, warm tone.
|
|
196
|
+
|
|
197
|
+
**SCAFFOLD output:**
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
Platform detected: React Native (Expo)
|
|
201
|
+
Tokens loaded: 38 tokens from design-system/tokens.json
|
|
202
|
+
Design intent: Expressive, warm (from DESIGN.md)
|
|
203
|
+
Component plan: WorkoutCard with progress indicator
|
|
204
|
+
Token consumption: color.primary.*, color.accent.*, typography.heading, spacing.md/lg
|
|
205
|
+
Platform rules: iOS 44pt touch targets, Android 48dp touch targets, safe area insets
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
**IMPLEMENT output (WorkoutCard.tsx):**
|
|
209
|
+
|
|
210
|
+
```tsx
|
|
211
|
+
// @design-token color.primary.500 — card accent
|
|
212
|
+
// @design-token color.neutral.50 — card background
|
|
213
|
+
// @design-token color.neutral.900 — primary text
|
|
214
|
+
// @design-token typography.heading.fontFamily — workout title
|
|
215
|
+
// @design-token typography.body.fontFamily — workout details
|
|
216
|
+
// @design-token spacing.md — card padding
|
|
217
|
+
// @design-token spacing.sm — content gap
|
|
218
|
+
|
|
219
|
+
import { View, Text, StyleSheet, Platform } from 'react-native';
|
|
220
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
221
|
+
import { tokens } from '@/theme/tokens';
|
|
222
|
+
|
|
223
|
+
interface WorkoutCardProps {
|
|
224
|
+
title: string;
|
|
225
|
+
duration: string;
|
|
226
|
+
progress: number;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
export function WorkoutCard({ title, duration, progress }: WorkoutCardProps) {
|
|
230
|
+
return (
|
|
231
|
+
<View style={styles.card}>
|
|
232
|
+
<Text style={styles.title}>{title}</Text>
|
|
233
|
+
<Text style={styles.detail}>{duration}</Text>
|
|
234
|
+
<View style={styles.progressTrack}>
|
|
235
|
+
<View style={[styles.progressFill, { width: `${progress}%` }]} />
|
|
236
|
+
</View>
|
|
237
|
+
</View>
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const styles = StyleSheet.create({
|
|
242
|
+
card: {
|
|
243
|
+
backgroundColor: tokens.color.neutral[50],
|
|
244
|
+
borderRadius: tokens.radius.md,
|
|
245
|
+
padding: tokens.spacing.md,
|
|
246
|
+
gap: tokens.spacing.sm,
|
|
247
|
+
...Platform.select({
|
|
248
|
+
ios: {
|
|
249
|
+
shadowColor: tokens.color.neutral[900],
|
|
250
|
+
shadowOffset: { width: 0, height: 2 },
|
|
251
|
+
shadowOpacity: 0.08,
|
|
252
|
+
shadowRadius: 8,
|
|
253
|
+
},
|
|
254
|
+
android: {
|
|
255
|
+
elevation: 2,
|
|
256
|
+
},
|
|
257
|
+
}),
|
|
258
|
+
},
|
|
259
|
+
title: {
|
|
260
|
+
fontFamily: tokens.typography.heading.fontFamily,
|
|
261
|
+
fontWeight: tokens.typography.heading.fontWeight,
|
|
262
|
+
fontSize: 18,
|
|
263
|
+
color: tokens.color.neutral[900],
|
|
264
|
+
},
|
|
265
|
+
detail: {
|
|
266
|
+
fontFamily: tokens.typography.body.fontFamily,
|
|
267
|
+
fontSize: 14,
|
|
268
|
+
color: tokens.color.neutral[600],
|
|
269
|
+
},
|
|
270
|
+
progressTrack: {
|
|
271
|
+
height: 6,
|
|
272
|
+
backgroundColor: tokens.color.neutral[200],
|
|
273
|
+
borderRadius: 3,
|
|
274
|
+
},
|
|
275
|
+
progressFill: {
|
|
276
|
+
height: 6,
|
|
277
|
+
backgroundColor: tokens.color.primary[500],
|
|
278
|
+
borderRadius: 3,
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Example: SwiftUI List Item
|
|
284
|
+
|
|
285
|
+
**IMPLEMENT output (WorkoutRow.swift):**
|
|
286
|
+
|
|
287
|
+
```swift
|
|
288
|
+
// @design-token color.primary.500 — accent color
|
|
289
|
+
// @design-token color.neutral.900 — primary text
|
|
290
|
+
// @design-token color.neutral.600 — secondary text
|
|
291
|
+
// @design-token typography.heading.fontWeight — title weight
|
|
292
|
+
// @design-token spacing.sm — content spacing
|
|
293
|
+
|
|
294
|
+
import SwiftUI
|
|
295
|
+
|
|
296
|
+
struct WorkoutRow: View {
|
|
297
|
+
let title: String
|
|
298
|
+
let duration: String
|
|
299
|
+
let progress: Double
|
|
300
|
+
|
|
301
|
+
var body: some View {
|
|
302
|
+
VStack(alignment: .leading, spacing: AppSpacing.sm) {
|
|
303
|
+
Text(title)
|
|
304
|
+
.font(.headline)
|
|
305
|
+
.foregroundColor(AppColors.neutral900)
|
|
306
|
+
|
|
307
|
+
Text(duration)
|
|
308
|
+
.font(.subheadline)
|
|
309
|
+
.foregroundColor(AppColors.neutral600)
|
|
310
|
+
|
|
311
|
+
ProgressView(value: progress)
|
|
312
|
+
.tint(AppColors.primary500)
|
|
313
|
+
}
|
|
314
|
+
.padding(AppSpacing.md)
|
|
315
|
+
.accessibilityElement(children: .combine)
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
## Gates
|
|
321
|
+
|
|
322
|
+
- **No component generation without reading tokens from harness-design-system.** The SCAFFOLD phase requires `design-system/tokens.json`. Do not generate components with hardcoded values as a fallback.
|
|
323
|
+
- **No hardcoded design values in generated output.** Every color, font, and spacing value must reference a token.
|
|
324
|
+
- **No platform-specific code without platform detection.** The SCAFFOLD phase must detect or receive the target mobile platform before generating components.
|
|
325
|
+
- **No generation without scaffold plan confirmation.** Present the component plan to the user first.
|
|
326
|
+
- **No iOS components without 44pt minimum touch targets.** Touch target violations are `error` severity regardless of strictness level.
|
|
327
|
+
- **No Android/Material components without 48dp minimum touch targets.** Same as iOS — touch targets are non-negotiable.
|
|
328
|
+
- **No graph mutations without validating node types.** Verify edge types are registered before writing.
|
|
329
|
+
|
|
330
|
+
## Escalation
|
|
331
|
+
|
|
332
|
+
- **When `design-system/tokens.json` does not exist:** Instruct the user: "Design tokens have not been generated. Run `harness-design-system` first, then re-run `harness-design-mobile`."
|
|
333
|
+
- **When the project targets multiple mobile platforms:** Generate for the primary platform first, then offer to generate platform-adapted variants. React Native projects get both iOS and Android considerations in a single pass.
|
|
334
|
+
- **When tokens are insufficient for the requested component:** Report missing tokens and instruct the user to add them via harness-design-system.
|
|
335
|
+
- **When platform guidelines conflict with design intent:** Present the conflict: "Material Design 3 recommends rounded corners for cards, but your design intent declares 'sharp edges only.' Options: (1) Follow platform guidelines for native feel, (2) Override with design intent for brand consistency."
|
|
336
|
+
- **When the knowledge graph is unavailable:** Skip graph operations. Log: "Graph not available — skipping token node verification and PLATFORM_BINDING edge creation. Run `harness scan` later to populate."
|