@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,48 @@
|
|
|
1
|
+
name: harness-soundness-review
|
|
2
|
+
version: "1.0.0"
|
|
3
|
+
description: Deep soundness analysis of specs and plans with auto-fix and convergence loop
|
|
4
|
+
cognitive_mode: meticulous-verifier
|
|
5
|
+
triggers:
|
|
6
|
+
- manual
|
|
7
|
+
platforms:
|
|
8
|
+
- claude-code
|
|
9
|
+
- gemini-cli
|
|
10
|
+
tools:
|
|
11
|
+
- Bash
|
|
12
|
+
- Read
|
|
13
|
+
- Write
|
|
14
|
+
- Edit
|
|
15
|
+
- Glob
|
|
16
|
+
- Grep
|
|
17
|
+
cli:
|
|
18
|
+
command: harness skill run harness-soundness-review
|
|
19
|
+
args:
|
|
20
|
+
- name: path
|
|
21
|
+
description: Project root path
|
|
22
|
+
required: false
|
|
23
|
+
- name: mode
|
|
24
|
+
description: Review mode — "spec" for spec soundness or "plan" for plan soundness
|
|
25
|
+
required: true
|
|
26
|
+
mcp:
|
|
27
|
+
tool: run_skill
|
|
28
|
+
input:
|
|
29
|
+
skill: harness-soundness-review
|
|
30
|
+
path: string
|
|
31
|
+
type: rigid
|
|
32
|
+
phases:
|
|
33
|
+
- name: check
|
|
34
|
+
description: Run all checks for the current mode and classify findings
|
|
35
|
+
required: true
|
|
36
|
+
- name: fix
|
|
37
|
+
description: Auto-fix inferrable issues and log changes
|
|
38
|
+
required: true
|
|
39
|
+
- name: converge
|
|
40
|
+
description: Re-run checks, compare issue counts, loop or stop
|
|
41
|
+
required: true
|
|
42
|
+
- name: surface
|
|
43
|
+
description: Present remaining issues to user for resolution
|
|
44
|
+
required: true
|
|
45
|
+
state:
|
|
46
|
+
persistent: false
|
|
47
|
+
files: []
|
|
48
|
+
depends_on: []
|
|
@@ -13,8 +13,23 @@
|
|
|
13
13
|
|
|
14
14
|
## Prerequisites
|
|
15
15
|
|
|
16
|
-
A knowledge graph
|
|
17
|
-
|
|
16
|
+
A knowledge graph at `.harness/graph/` enables full analysis. If no graph exists,
|
|
17
|
+
the skill uses static analysis fallbacks (see Graph Availability section).
|
|
18
|
+
Run `harness scan` to enable graph-enhanced analysis.
|
|
19
|
+
|
|
20
|
+
### Graph Availability
|
|
21
|
+
|
|
22
|
+
Before starting, check if `.harness/graph/graph.json` exists.
|
|
23
|
+
|
|
24
|
+
**If graph exists:** Check staleness — compare `.harness/graph/metadata.json`
|
|
25
|
+
scanTimestamp against `git log -1 --format=%ct` (latest commit timestamp).
|
|
26
|
+
If graph is more than 10 commits behind (`git log --oneline <scanTimestamp>..HEAD | wc -l`),
|
|
27
|
+
run `harness scan` to refresh before proceeding. (Staleness sensitivity: **Medium**)
|
|
28
|
+
|
|
29
|
+
**If graph exists and is fresh (or refreshed):** Use graph tools as primary strategy.
|
|
30
|
+
|
|
31
|
+
**If no graph exists:** Output "Running without graph (run `harness scan` to
|
|
32
|
+
enable full analysis)" and use fallback strategies for all subsequent steps.
|
|
18
33
|
|
|
19
34
|
## Process
|
|
20
35
|
|
|
@@ -43,6 +58,20 @@ For each changed file, use graph traversal to find test files:
|
|
|
43
58
|
|
|
44
59
|
3. **Co-change tests**: Check `co_changes_with` edges for test files that historically change alongside the modified files.
|
|
45
60
|
|
|
61
|
+
#### Fallback (without graph)
|
|
62
|
+
|
|
63
|
+
When no graph is available, use naming conventions, import parsing, and git history:
|
|
64
|
+
|
|
65
|
+
1. **Tier 1 — Filename convention matching**: For each changed file `foo.ts`, search for:
|
|
66
|
+
- `foo.test.ts`, `foo.spec.ts` (same directory)
|
|
67
|
+
- `__tests__/foo.ts`, `__tests__/foo.test.ts`
|
|
68
|
+
- Test files in a parallel `tests/` directory mirroring the source path
|
|
69
|
+
2. **Tier 2 — Import-linked tests**: Parse test files' import statements (grep for `import.*from` in `*.test.*` and `*.spec.*` files). If a test file imports the changed file, it belongs in Tier 2 (if not already in Tier 1).
|
|
70
|
+
3. **Tier 3 — Co-change correlated tests**: Use `git log --format="%H" --name-only` to find test files that frequently change in the same commit as the target file. Files that co-change in >2 commits are co-change correlated.
|
|
71
|
+
4. **Rank**: Tier 1 = direct filename match, Tier 2 = import-linked tests, Tier 3 = co-change correlated tests. Output the same tiered format as the graph version.
|
|
72
|
+
|
|
73
|
+
> Fallback completeness: ~80% — naming conventions and imports catch most mappings; misses dynamic imports and indirect coverage.
|
|
74
|
+
|
|
46
75
|
### Phase 3: PRIORITIZE — Rank and Generate Commands
|
|
47
76
|
|
|
48
77
|
Organize tests into three tiers:
|
|
@@ -85,7 +114,7 @@ npx vitest run tests/services/auth.test.ts tests/types/user.test.ts tests/routes
|
|
|
85
114
|
|
|
86
115
|
## Harness Integration
|
|
87
116
|
|
|
88
|
-
- **`harness scan`** —
|
|
117
|
+
- **`harness scan`** — Recommended before this skill for full graph-enhanced analysis. If graph is missing, skill uses naming convention and import parsing fallbacks.
|
|
89
118
|
- **`harness validate`** — Run after acting on findings to verify project health.
|
|
90
119
|
- **Graph tools** — This skill uses `query_graph`, `get_impact`, and `get_relationships` MCP tools.
|
|
91
120
|
|
|
@@ -95,7 +124,7 @@ npx vitest run tests/services/auth.test.ts tests/types/user.test.ts tests/routes
|
|
|
95
124
|
- Executable run commands generated for quick and full test runs
|
|
96
125
|
- Coverage gaps flagged for changed files with no test coverage
|
|
97
126
|
- Report follows the structured output format
|
|
98
|
-
- All findings are backed by graph query evidence
|
|
127
|
+
- All findings are backed by graph query evidence (with graph) or systematic static analysis (without graph)
|
|
99
128
|
|
|
100
129
|
## Examples
|
|
101
130
|
|
|
@@ -122,8 +151,8 @@ Output:
|
|
|
122
151
|
|
|
123
152
|
## Gates
|
|
124
153
|
|
|
125
|
-
- **
|
|
126
|
-
- **Always include Tier 1.** Direct test coverage is non-negotiable — always recommend running these.
|
|
154
|
+
- **Graph preferred, fallback available.** If no graph exists, use naming conventions, import parsing, and git co-change analysis to identify relevant tests. Do not stop — produce the best test selection possible.
|
|
155
|
+
- **Always include Tier 1.** Direct test coverage is non-negotiable — always recommend running these (whether found via graph or naming conventions).
|
|
127
156
|
|
|
128
157
|
## Escalation
|
|
129
158
|
|
|
@@ -6,9 +6,9 @@ case `uname` in
|
|
|
6
6
|
esac
|
|
7
7
|
|
|
8
8
|
if [ -z "$NODE_PATH" ]; then
|
|
9
|
-
export NODE_PATH="/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.
|
|
9
|
+
export NODE_PATH="/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_yaml@2.8.2/node_modules/vitest/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_yaml@2.8.2/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/node_modules"
|
|
10
10
|
else
|
|
11
|
-
export NODE_PATH="/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.
|
|
11
|
+
export NODE_PATH="/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_yaml@2.8.2/node_modules/vitest/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/vitest@4.0.18_yaml@2.8.2/node_modules:/home/runner/work/harness-engineering/harness-engineering/node_modules/.pnpm/node_modules:$NODE_PATH"
|
|
12
12
|
fi
|
|
13
13
|
if [ -x "$basedir/node" ]; then
|
|
14
14
|
exec "$basedir/node" "$basedir/../vitest/vitest.mjs" "$@"
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
description: "Color anti-patterns — common mistakes that harm accessibility, consistency, and brand integrity"
|
|
2
|
+
|
|
3
|
+
patterns:
|
|
4
|
+
- name: "Hardcoded color values instead of tokens"
|
|
5
|
+
severity: warning
|
|
6
|
+
scope: all
|
|
7
|
+
detect:
|
|
8
|
+
method: "Grep for hex (#xxx, #xxxxxx), rgb(), rgba(), hsl(), hsla() values in component code that are not defined in tokens.json"
|
|
9
|
+
exclude: ["test files", "fixture files", "storybook stories"]
|
|
10
|
+
reason: "Hardcoded colors bypass the design token system, creating inconsistency and making global palette changes impossible without find-and-replace."
|
|
11
|
+
instead: "Reference design tokens: use CSS custom properties (var(--color-primary)), Tailwind classes (text-primary), or platform token bindings."
|
|
12
|
+
strictness:
|
|
13
|
+
permissive: info
|
|
14
|
+
standard: warn
|
|
15
|
+
strict: error
|
|
16
|
+
|
|
17
|
+
- name: "Insufficient contrast ratio (WCAG AA)"
|
|
18
|
+
severity: error
|
|
19
|
+
scope: all
|
|
20
|
+
detect:
|
|
21
|
+
method: "Calculate contrast ratio between foreground text color and background color"
|
|
22
|
+
threshold: "< 4.5:1 for normal text, < 3:1 for large text (18px+ or 14px+ bold)"
|
|
23
|
+
reason: "Low contrast text is unreadable for users with low vision, color blindness, or in bright ambient light. WCAG 2.1 Level AA requires 4.5:1 minimum."
|
|
24
|
+
instead: "Use pre-validated contrast pairs from the palette. Check ratios with a contrast checker before committing."
|
|
25
|
+
strictness:
|
|
26
|
+
permissive: info
|
|
27
|
+
standard: warn
|
|
28
|
+
strict: error
|
|
29
|
+
|
|
30
|
+
- name: "Color as the only differentiator"
|
|
31
|
+
severity: error
|
|
32
|
+
scope: all
|
|
33
|
+
detect:
|
|
34
|
+
method: "Check for status indicators, form validation, or interactive states that rely solely on color change"
|
|
35
|
+
context: "Success/error/warning states, required field indicators, active/inactive toggles"
|
|
36
|
+
reason: "Approximately 8% of men and 0.5% of women have color vision deficiency. Color-only indicators are invisible to them."
|
|
37
|
+
instead: "Combine color with a secondary indicator: icons, text labels, patterns, or border changes. Error states should include both red color AND an error icon/message."
|
|
38
|
+
strictness:
|
|
39
|
+
permissive: info
|
|
40
|
+
standard: warn
|
|
41
|
+
strict: error
|
|
42
|
+
|
|
43
|
+
- name: "Too many colors in a single view"
|
|
44
|
+
severity: warning
|
|
45
|
+
scope: all
|
|
46
|
+
detect:
|
|
47
|
+
method: "Count distinct non-neutral hues in a single screen or component"
|
|
48
|
+
threshold: "> 5 distinct hues (excluding neutrals/grays)"
|
|
49
|
+
reason: "Excessive color variety creates visual noise, weakens brand identity, and makes it harder for users to learn the color semantics of the interface."
|
|
50
|
+
instead: "Limit to 1-2 brand colors + 1 accent + semantic colors (success/warning/error/info). Use neutrals for everything else."
|
|
51
|
+
strictness:
|
|
52
|
+
permissive: info
|
|
53
|
+
standard: warn
|
|
54
|
+
strict: warn
|
|
55
|
+
|
|
56
|
+
- name: "Pure black (#000000) on pure white (#ffffff)"
|
|
57
|
+
severity: info
|
|
58
|
+
scope: web
|
|
59
|
+
detect:
|
|
60
|
+
css_properties: ["color", "background-color"]
|
|
61
|
+
values: ["#000000 on #ffffff", "#000 on #fff"]
|
|
62
|
+
reason: "Maximum contrast (21:1) can cause eye strain during extended reading, especially on bright displays. High contrast also creates harsh vibration at text edges."
|
|
63
|
+
instead: "Use near-black (e.g., #0f172a, #18181b) on near-white (e.g., #fafafa, #f8fafc) for a comfortable reading experience while maintaining excellent contrast ratios."
|
|
64
|
+
strictness:
|
|
65
|
+
permissive: info
|
|
66
|
+
standard: info
|
|
67
|
+
strict: warn
|
|
68
|
+
|
|
69
|
+
- name: "Opacity/alpha for semantic colors"
|
|
70
|
+
severity: warning
|
|
71
|
+
scope: all
|
|
72
|
+
detect:
|
|
73
|
+
method: "Check for rgba() or opacity applied to semantic colors (success, error, warning)"
|
|
74
|
+
context: "Background fills behind status text, badge backgrounds"
|
|
75
|
+
reason: "Transparent semantic colors shift hue depending on what's behind them. A red error badge over a blue card becomes purple, confusing the semantic meaning."
|
|
76
|
+
instead: "Use solid, pre-defined tint colors for semantic backgrounds (e.g., red-50 for error background, green-50 for success) instead of applying opacity to the base color."
|
|
77
|
+
strictness:
|
|
78
|
+
permissive: info
|
|
79
|
+
standard: warn
|
|
80
|
+
strict: warn
|
|
81
|
+
|
|
82
|
+
- name: "Brand colors used for destructive actions"
|
|
83
|
+
severity: warning
|
|
84
|
+
scope: all
|
|
85
|
+
detect:
|
|
86
|
+
method: "Check if primary brand color is applied to delete, remove, or destructive action buttons"
|
|
87
|
+
reason: "Using the brand color for destructive actions creates cognitive dissonance — the color that means 'go/primary' also means 'danger'. Users learn to hesitate on all primary-colored actions."
|
|
88
|
+
instead: "Reserve red (or a distinct danger color) for destructive actions. Primary brand color is for constructive actions only."
|
|
89
|
+
strictness:
|
|
90
|
+
permissive: info
|
|
91
|
+
standard: warn
|
|
92
|
+
strict: warn
|
|
93
|
+
|
|
94
|
+
- name: "Gradient text without fallback"
|
|
95
|
+
severity: info
|
|
96
|
+
scope: web
|
|
97
|
+
detect:
|
|
98
|
+
css_properties: ["background-clip", "-webkit-background-clip"]
|
|
99
|
+
values: ["text"]
|
|
100
|
+
absent: ["color fallback"]
|
|
101
|
+
reason: "Gradient text using background-clip: text has inconsistent browser support and can disappear entirely if the gradient fails to render."
|
|
102
|
+
instead: "Always set a solid color fallback before the gradient declaration. Test in all target browsers."
|
|
103
|
+
strictness:
|
|
104
|
+
permissive: info
|
|
105
|
+
standard: info
|
|
106
|
+
strict: warn
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
description: "Layout anti-patterns — common mistakes in spacing, composition, and responsive design"
|
|
2
|
+
|
|
3
|
+
patterns:
|
|
4
|
+
- name: "Inconsistent spacing values"
|
|
5
|
+
severity: warning
|
|
6
|
+
scope: all
|
|
7
|
+
detect:
|
|
8
|
+
method: "Check for margin/padding values that don't align with the spacing scale defined in tokens.json"
|
|
9
|
+
context: "Custom pixel values like 13px, 7px, 22px that don't match the 4px/8px grid or token scale"
|
|
10
|
+
reason: "Arbitrary spacing values create visual noise. Elements that are 'almost aligned' feel more wrong than elements that are clearly different."
|
|
11
|
+
instead: "Use spacing tokens from the design system scale (e.g., 4, 8, 12, 16, 24, 32, 48, 64). Every spacing value should reference a token."
|
|
12
|
+
strictness:
|
|
13
|
+
permissive: info
|
|
14
|
+
standard: warn
|
|
15
|
+
strict: warn
|
|
16
|
+
|
|
17
|
+
- name: "Content wider than 80ch for reading"
|
|
18
|
+
severity: warning
|
|
19
|
+
scope: web
|
|
20
|
+
detect:
|
|
21
|
+
method: "Check max-width of text content containers"
|
|
22
|
+
threshold: "> 80ch or > 720px without max-width constraint"
|
|
23
|
+
context: "Applies to prose/article content, not dashboards or data tables"
|
|
24
|
+
reason: "Lines longer than 65-80 characters are hard to track from the end of one line to the beginning of the next. Reading speed and comprehension drop significantly."
|
|
25
|
+
instead: "Set max-width: 65ch to 75ch for prose content. Use wider layouts only for data-dense views like dashboards and tables."
|
|
26
|
+
strictness:
|
|
27
|
+
permissive: info
|
|
28
|
+
standard: warn
|
|
29
|
+
strict: warn
|
|
30
|
+
|
|
31
|
+
- name: "Fixed pixel widths on containers"
|
|
32
|
+
severity: warning
|
|
33
|
+
scope: web
|
|
34
|
+
detect:
|
|
35
|
+
css_properties: ["width"]
|
|
36
|
+
values: ["px values on layout containers"]
|
|
37
|
+
exclude: ["max-width", "min-width", "icons", "avatars"]
|
|
38
|
+
reason: "Fixed-width containers break on screen sizes they weren't designed for. A 1200px container is unusable on a 1024px laptop."
|
|
39
|
+
instead: "Use relative units (%, rem, ch) or max-width constraints. Let containers be fluid within min/max bounds."
|
|
40
|
+
strictness:
|
|
41
|
+
permissive: info
|
|
42
|
+
standard: warn
|
|
43
|
+
strict: warn
|
|
44
|
+
|
|
45
|
+
- name: "Missing touch targets on mobile"
|
|
46
|
+
severity: error
|
|
47
|
+
scope: mobile
|
|
48
|
+
detect:
|
|
49
|
+
method: "Check interactive element dimensions"
|
|
50
|
+
threshold: "< 44x44px (iOS) or < 48x48dp (Android)"
|
|
51
|
+
context: "Buttons, links, toggles, checkboxes, and other tappable elements"
|
|
52
|
+
reason: "Small touch targets cause mis-taps, frustration, and accessibility failures. WCAG 2.5.8 requires minimum 24x24 CSS pixels, but platform guidelines recommend 44-48px."
|
|
53
|
+
instead: "Ensure all interactive elements have a minimum tappable area of 44x44px (iOS) or 48x48dp (Android). Use padding to increase hit area without changing visual size."
|
|
54
|
+
strictness:
|
|
55
|
+
permissive: info
|
|
56
|
+
standard: warn
|
|
57
|
+
strict: error
|
|
58
|
+
|
|
59
|
+
- name: "Horizontal scrolling on mobile"
|
|
60
|
+
severity: error
|
|
61
|
+
scope: all
|
|
62
|
+
detect:
|
|
63
|
+
method: "Check for content overflow causing horizontal scroll on viewports < 375px"
|
|
64
|
+
context: "Excludes intentional horizontal scroll components like carousels and code blocks"
|
|
65
|
+
reason: "Unintended horizontal scroll breaks the vertical reading flow and confuses users. It often indicates a layout bug."
|
|
66
|
+
instead: "Use overflow-x: hidden on the body, ensure all images have max-width: 100%, and test layouts at 320px minimum viewport width."
|
|
67
|
+
strictness:
|
|
68
|
+
permissive: info
|
|
69
|
+
standard: warn
|
|
70
|
+
strict: error
|
|
71
|
+
|
|
72
|
+
- name: "Z-index escalation"
|
|
73
|
+
severity: warning
|
|
74
|
+
scope: web
|
|
75
|
+
detect:
|
|
76
|
+
method: "Check for z-index values"
|
|
77
|
+
threshold: "> 100 or more than 10 distinct z-index values in the codebase"
|
|
78
|
+
reason: "Z-index wars create unpredictable stacking. When values escalate to 9999, every new overlay needs 99999, and the system becomes unmaintainable."
|
|
79
|
+
instead: "Define a z-index scale in tokens (e.g., base: 0, dropdown: 10, sticky: 20, modal: 30, toast: 40, tooltip: 50). Never use arbitrary values."
|
|
80
|
+
strictness:
|
|
81
|
+
permissive: info
|
|
82
|
+
standard: warn
|
|
83
|
+
strict: warn
|
|
84
|
+
|
|
85
|
+
- name: "Nested scroll containers"
|
|
86
|
+
severity: warning
|
|
87
|
+
scope: all
|
|
88
|
+
detect:
|
|
89
|
+
method: "Check for scrollable elements inside other scrollable elements"
|
|
90
|
+
context: "Especially problematic when both scroll in the same direction"
|
|
91
|
+
reason: "Nested scrolling creates confusing interaction — users don't know which container will scroll when they swipe. Trackpad momentum makes it worse."
|
|
92
|
+
instead: "Flatten the layout so only one element scrolls at a time. If nested scroll is unavoidable, ensure they scroll in different directions (e.g., vertical page + horizontal carousel)."
|
|
93
|
+
strictness:
|
|
94
|
+
permissive: info
|
|
95
|
+
standard: warn
|
|
96
|
+
strict: warn
|
|
97
|
+
|
|
98
|
+
- name: "Magic number breakpoints"
|
|
99
|
+
severity: info
|
|
100
|
+
scope: web
|
|
101
|
+
detect:
|
|
102
|
+
method: "Check for media query breakpoints that don't match standard device widths or design system breakpoints"
|
|
103
|
+
values: ["arbitrary values like 743px, 1023px, 867px"]
|
|
104
|
+
reason: "Non-standard breakpoints are hard to reason about and don't correspond to real device classes. They suggest the layout was 'fixed' at a specific size rather than designed responsively."
|
|
105
|
+
instead: "Use standard breakpoints (640, 768, 1024, 1280, 1536) or define custom breakpoints in the design system tokens and reuse them consistently."
|
|
106
|
+
strictness:
|
|
107
|
+
permissive: info
|
|
108
|
+
standard: info
|
|
109
|
+
strict: warn
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
description: "Motion and animation anti-patterns — common mistakes in transitions, animations, and interactive feedback"
|
|
2
|
+
|
|
3
|
+
patterns:
|
|
4
|
+
- name: "Animation without prefers-reduced-motion"
|
|
5
|
+
severity: error
|
|
6
|
+
scope: all
|
|
7
|
+
detect:
|
|
8
|
+
method: "Check for CSS animations or transitions without a @media (prefers-reduced-motion: reduce) override"
|
|
9
|
+
context: "Applies to all non-essential animations. Essential animations (progress indicators, loading states) should reduce, not remove."
|
|
10
|
+
reason: "Motion can trigger vestibular disorders, migraines, and seizures. WCAG 2.3.3 requires respecting user motion preferences."
|
|
11
|
+
instead: "Wrap animations in a motion-safe media query or provide a prefers-reduced-motion: reduce override that disables or minimizes the animation."
|
|
12
|
+
strictness:
|
|
13
|
+
permissive: info
|
|
14
|
+
standard: warn
|
|
15
|
+
strict: error
|
|
16
|
+
|
|
17
|
+
- name: "Animations longer than 500ms"
|
|
18
|
+
severity: warning
|
|
19
|
+
scope: all
|
|
20
|
+
detect:
|
|
21
|
+
css_properties: ["animation-duration", "transition-duration"]
|
|
22
|
+
threshold: "> 500ms"
|
|
23
|
+
exclude: ["page transitions", "skeleton loaders", "progress bars"]
|
|
24
|
+
reason: "Long animations feel sluggish and block user interaction. Users perceive delays over 400ms as 'slow'. Interface animations should feel instant and responsive."
|
|
25
|
+
instead: "Keep UI transitions between 150-300ms. Use 200ms as the default. Reserve longer durations (300-500ms) for complex multi-element orchestrations."
|
|
26
|
+
strictness:
|
|
27
|
+
permissive: info
|
|
28
|
+
standard: warn
|
|
29
|
+
strict: warn
|
|
30
|
+
|
|
31
|
+
- name: "Linear easing on UI transitions"
|
|
32
|
+
severity: info
|
|
33
|
+
scope: all
|
|
34
|
+
detect:
|
|
35
|
+
css_properties: ["transition-timing-function", "animation-timing-function"]
|
|
36
|
+
values: ["linear"]
|
|
37
|
+
context: "Flagged for UI element transitions, not progress bars or loading animations"
|
|
38
|
+
reason: "Linear motion feels mechanical and unnatural. Real objects accelerate and decelerate — interfaces should too."
|
|
39
|
+
instead: "Use ease-out for entrances (elements arriving), ease-in for exits (elements leaving), and ease-in-out for state changes. Default: cubic-bezier(0.4, 0, 0.2, 1)."
|
|
40
|
+
strictness:
|
|
41
|
+
permissive: info
|
|
42
|
+
standard: info
|
|
43
|
+
strict: warn
|
|
44
|
+
|
|
45
|
+
- name: "Auto-playing animation loops"
|
|
46
|
+
severity: warning
|
|
47
|
+
scope: all
|
|
48
|
+
detect:
|
|
49
|
+
css_properties: ["animation-iteration-count"]
|
|
50
|
+
values: ["infinite"]
|
|
51
|
+
context: "Excludes loading spinners and progress indicators that are temporary"
|
|
52
|
+
reason: "Infinite animation loops are distracting, increase CPU/GPU usage, and can trigger motion sensitivity issues. They compete with content for attention."
|
|
53
|
+
instead: "Play animations once on entrance, or limit to 3 iterations. If continuous animation is needed, provide a pause control and respect prefers-reduced-motion."
|
|
54
|
+
strictness:
|
|
55
|
+
permissive: info
|
|
56
|
+
standard: warn
|
|
57
|
+
strict: error
|
|
58
|
+
|
|
59
|
+
- name: "Scroll-jacking"
|
|
60
|
+
severity: error
|
|
61
|
+
scope: web
|
|
62
|
+
detect:
|
|
63
|
+
method: "Check for JavaScript that overrides native scroll behavior (custom scroll speed, snap-to-section, parallax scroll hijacking)"
|
|
64
|
+
exclude: ["scroll-snap-type CSS (native)", "smooth-scroll for anchor links"]
|
|
65
|
+
reason: "Overriding native scroll breaks user expectations, disables accessibility features (keyboard scroll, screen reader navigation), and creates motion sickness. It is the single most complained-about UX pattern."
|
|
66
|
+
instead: "Use native CSS scroll-snap for section snapping. For parallax, use CSS transform with will-change, not scroll event listeners. Never change scroll speed or direction."
|
|
67
|
+
strictness:
|
|
68
|
+
permissive: warn
|
|
69
|
+
standard: error
|
|
70
|
+
strict: error
|
|
71
|
+
|
|
72
|
+
- name: "Flash or strobe effects"
|
|
73
|
+
severity: error
|
|
74
|
+
scope: all
|
|
75
|
+
detect:
|
|
76
|
+
method: "Check for elements that flash more than 3 times per second"
|
|
77
|
+
threshold: "> 3 flashes per second"
|
|
78
|
+
reason: "Flashing content can cause seizures in people with photosensitive epilepsy. WCAG 2.3.1 requires no more than 3 flashes per second."
|
|
79
|
+
instead: "Avoid flashing entirely. If attention is needed, use a subtle pulse (opacity 0.8-1.0) at no more than 2 cycles per second."
|
|
80
|
+
strictness:
|
|
81
|
+
permissive: warn
|
|
82
|
+
standard: error
|
|
83
|
+
strict: error
|
|
84
|
+
|
|
85
|
+
- name: "Entrance animations on above-the-fold content"
|
|
86
|
+
severity: warning
|
|
87
|
+
scope: web
|
|
88
|
+
detect:
|
|
89
|
+
method: "Check for fade-in, slide-in, or scale animations on elements visible in the initial viewport"
|
|
90
|
+
context: "Hero sections, navigation, primary CTAs"
|
|
91
|
+
reason: "Animating content that should be immediately visible delays the user's ability to orient and act. It adds perceived load time to an already-loaded page."
|
|
92
|
+
instead: "Show above-the-fold content immediately. Reserve entrance animations for below-the-fold content revealed on scroll (intersection observer pattern)."
|
|
93
|
+
strictness:
|
|
94
|
+
permissive: info
|
|
95
|
+
standard: warn
|
|
96
|
+
strict: warn
|
|
97
|
+
|
|
98
|
+
- name: "Transition on color-scheme change"
|
|
99
|
+
severity: info
|
|
100
|
+
scope: web
|
|
101
|
+
detect:
|
|
102
|
+
method: "Check for transitions applied during dark/light mode toggle that affect all elements"
|
|
103
|
+
context: "Global transition: all on :root or body during theme switch"
|
|
104
|
+
reason: "Transitioning every element's colors during theme change causes a jarring ripple effect and high paint cost. Individual element transitions compound into visual chaos."
|
|
105
|
+
instead: "Apply transition only to background-color and color on specific containers (body, main sections), not globally. Or use instant switch with no transition."
|
|
106
|
+
strictness:
|
|
107
|
+
permissive: info
|
|
108
|
+
standard: info
|
|
109
|
+
strict: info
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
description: "Typography anti-patterns — common mistakes that degrade readability, hierarchy, and brand consistency"
|
|
2
|
+
|
|
3
|
+
patterns:
|
|
4
|
+
- name: "System font in user-facing UI"
|
|
5
|
+
severity: warning
|
|
6
|
+
scope: all
|
|
7
|
+
detect:
|
|
8
|
+
css_properties: ["font-family"]
|
|
9
|
+
values: ["system-ui", "-apple-system", "BlinkMacSystemFont", "Segoe UI", "sans-serif", "serif", "monospace"]
|
|
10
|
+
context: "Only flagged when used as the sole font-family without a branded font preceding it in the stack"
|
|
11
|
+
reason: "System fonts vary across platforms, creating inconsistent brand identity. Users on Windows see Segoe UI while macOS users see SF Pro — the product looks different on every device."
|
|
12
|
+
instead: "Declare a branded font first in the stack with system fonts as fallbacks: `font-family: 'Inter', system-ui, sans-serif`"
|
|
13
|
+
strictness:
|
|
14
|
+
permissive: info
|
|
15
|
+
standard: warn
|
|
16
|
+
strict: warn
|
|
17
|
+
|
|
18
|
+
- name: "More than 3 font families on a single page"
|
|
19
|
+
severity: warning
|
|
20
|
+
scope: all
|
|
21
|
+
detect:
|
|
22
|
+
method: "Count distinct font-family values in rendered page"
|
|
23
|
+
threshold: 3
|
|
24
|
+
reason: "Multiple typefaces create visual noise and weaken typographic hierarchy. Each additional font competes for attention."
|
|
25
|
+
instead: "Use a single font family with weight/size variation for hierarchy, or a deliberate display + body pairing (max 2-3 families including monospace)."
|
|
26
|
+
strictness:
|
|
27
|
+
permissive: info
|
|
28
|
+
standard: warn
|
|
29
|
+
strict: warn
|
|
30
|
+
|
|
31
|
+
- name: "Body text below 14px / 0.875rem"
|
|
32
|
+
severity: error
|
|
33
|
+
scope: all
|
|
34
|
+
detect:
|
|
35
|
+
css_properties: ["font-size"]
|
|
36
|
+
threshold: "< 14px or < 0.875rem"
|
|
37
|
+
context: "Applies to body/paragraph text, not labels or captions"
|
|
38
|
+
reason: "Text below 14px is difficult to read on mobile devices and fails accessibility guidelines for users with low vision."
|
|
39
|
+
instead: "Use 16px (1rem) as the body text baseline. Use 14px only for secondary labels and metadata."
|
|
40
|
+
strictness:
|
|
41
|
+
permissive: info
|
|
42
|
+
standard: warn
|
|
43
|
+
strict: error
|
|
44
|
+
|
|
45
|
+
- name: "Line height below 1.4 for body text"
|
|
46
|
+
severity: warning
|
|
47
|
+
scope: all
|
|
48
|
+
detect:
|
|
49
|
+
css_properties: ["line-height"]
|
|
50
|
+
threshold: "< 1.4"
|
|
51
|
+
context: "Applies to body/paragraph text with font-size >= 14px"
|
|
52
|
+
reason: "Tight line height reduces readability, especially for longer passages. Users with dyslexia or cognitive disabilities are disproportionately affected."
|
|
53
|
+
instead: "Use line-height 1.5-1.6 for body text. Display headings can use tighter spacing (1.1-1.2)."
|
|
54
|
+
strictness:
|
|
55
|
+
permissive: info
|
|
56
|
+
standard: warn
|
|
57
|
+
strict: warn
|
|
58
|
+
|
|
59
|
+
- name: "All-caps body text"
|
|
60
|
+
severity: warning
|
|
61
|
+
scope: all
|
|
62
|
+
detect:
|
|
63
|
+
css_properties: ["text-transform"]
|
|
64
|
+
values: ["uppercase"]
|
|
65
|
+
context: "Flagged when applied to paragraphs or text blocks longer than 50 characters"
|
|
66
|
+
reason: "ALL CAPS reduces reading speed by 10-20% because word shapes become uniform rectangles. Acceptable for short labels and headings, not for body content."
|
|
67
|
+
instead: "Reserve text-transform: uppercase for buttons, labels, and section headers under 30 characters."
|
|
68
|
+
strictness:
|
|
69
|
+
permissive: info
|
|
70
|
+
standard: warn
|
|
71
|
+
strict: warn
|
|
72
|
+
|
|
73
|
+
- name: "Insufficient heading size contrast"
|
|
74
|
+
severity: warning
|
|
75
|
+
scope: all
|
|
76
|
+
detect:
|
|
77
|
+
method: "Compare h1-h6 font sizes — flag when adjacent heading levels differ by less than 20%"
|
|
78
|
+
threshold: "< 1.2x ratio between adjacent levels"
|
|
79
|
+
reason: "When heading sizes are too similar, the visual hierarchy collapses. Users cannot scan the page structure at a glance."
|
|
80
|
+
instead: "Use a consistent type scale ratio (1.2 minor third, 1.25 major third, or 1.333 perfect fourth) to ensure clear size differentiation."
|
|
81
|
+
strictness:
|
|
82
|
+
permissive: info
|
|
83
|
+
standard: warn
|
|
84
|
+
strict: warn
|
|
85
|
+
|
|
86
|
+
- name: "Justified text without hyphenation"
|
|
87
|
+
severity: info
|
|
88
|
+
scope: web
|
|
89
|
+
detect:
|
|
90
|
+
css_properties: ["text-align"]
|
|
91
|
+
values: ["justify"]
|
|
92
|
+
absent: ["hyphens: auto"]
|
|
93
|
+
reason: "Justified text without hyphenation creates uneven word spacing ('rivers of white') that disrupts reading flow, especially in narrow columns."
|
|
94
|
+
instead: "Use text-align: left for most content. If justified text is required, enable CSS hyphens: auto and ensure column width is at least 45 characters."
|
|
95
|
+
strictness:
|
|
96
|
+
permissive: info
|
|
97
|
+
standard: info
|
|
98
|
+
strict: warn
|
|
99
|
+
|
|
100
|
+
- name: "Font weight below 400 for body text"
|
|
101
|
+
severity: warning
|
|
102
|
+
scope: all
|
|
103
|
+
detect:
|
|
104
|
+
css_properties: ["font-weight"]
|
|
105
|
+
threshold: "< 400"
|
|
106
|
+
context: "Applies to body/paragraph text"
|
|
107
|
+
reason: "Light and thin font weights (100-300) reduce legibility on low-resolution screens and for users with vision impairments."
|
|
108
|
+
instead: "Use font-weight 400 (regular) as the minimum for body text. Light weights are acceptable only for large display text (24px+)."
|
|
109
|
+
strictness:
|
|
110
|
+
permissive: info
|
|
111
|
+
standard: warn
|
|
112
|
+
strict: error
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
name: "Creative"
|
|
2
|
+
description: "Expressive, editorial design with bold typography, intentional whitespace, and distinctive visual identity"
|
|
3
|
+
|
|
4
|
+
styles:
|
|
5
|
+
primary: "Editorial layouts with strong typographic hierarchy and intentional use of whitespace as a design element"
|
|
6
|
+
secondary: "Portfolio-driven presentation with immersive imagery, grid-breaking layouts, and art-directed content"
|
|
7
|
+
avoid: ["Generic stock photography that undermines creative credibility", "Template-feeling layouts that contradict the creative message", "Overly uniform grids that feel corporate rather than curated", "Decorative effects without purpose (gratuitous parallax, unnecessary animation)"]
|
|
8
|
+
|
|
9
|
+
palette:
|
|
10
|
+
primary:
|
|
11
|
+
- name: "Charcoal"
|
|
12
|
+
hex: "#1a1a1a"
|
|
13
|
+
usage: "Primary text, editorial headlines, strong contrast backgrounds"
|
|
14
|
+
- name: "Off-Black"
|
|
15
|
+
hex: "#2d2d2d"
|
|
16
|
+
usage: "Secondary surfaces, navigation backgrounds, card overlays"
|
|
17
|
+
- name: "Warm White"
|
|
18
|
+
hex: "#faf8f5"
|
|
19
|
+
usage: "Page backgrounds, content surfaces, breathing space"
|
|
20
|
+
accent:
|
|
21
|
+
- name: "Coral 500"
|
|
22
|
+
hex: "#f97066"
|
|
23
|
+
usage: "Primary accent, CTAs, highlighted portfolio items"
|
|
24
|
+
- name: "Electric Blue"
|
|
25
|
+
hex: "#3b82f6"
|
|
26
|
+
usage: "Links, interactive elements, secondary accent"
|
|
27
|
+
- name: "Saffron"
|
|
28
|
+
hex: "#e8a838"
|
|
29
|
+
usage: "Awards, featured work, premium tier indicators"
|
|
30
|
+
neutral:
|
|
31
|
+
- name: "Stone 800"
|
|
32
|
+
hex: "#292524"
|
|
33
|
+
usage: "Body text, primary readable content"
|
|
34
|
+
- name: "Stone 400"
|
|
35
|
+
hex: "#a8a29e"
|
|
36
|
+
usage: "Captions, metadata, subtle labels"
|
|
37
|
+
- name: "Stone 100"
|
|
38
|
+
hex: "#f5f5f4"
|
|
39
|
+
usage: "Section dividers, subtle background shifts"
|
|
40
|
+
- name: "White"
|
|
41
|
+
hex: "#ffffff"
|
|
42
|
+
usage: "Image framing, overlay text backgrounds, modal surfaces"
|
|
43
|
+
semantic:
|
|
44
|
+
success: "#22c55e"
|
|
45
|
+
warning: "#f59e0b"
|
|
46
|
+
error: "#ef4444"
|
|
47
|
+
info: "#6366f1"
|
|
48
|
+
|
|
49
|
+
typography:
|
|
50
|
+
display:
|
|
51
|
+
families: ["Instrument Serif", "Playfair Display", "Fraunces"]
|
|
52
|
+
weights: [400, 700, 900]
|
|
53
|
+
characteristics: "Expressive serif typefaces with distinctive character for headlines. High contrast between thick and thin strokes creates visual drama at large sizes."
|
|
54
|
+
body:
|
|
55
|
+
families: ["Inter", "Geist", "DM Sans"]
|
|
56
|
+
weights: [400, 500]
|
|
57
|
+
characteristics: "Clean sans-serif paired with serif display creates editorial contrast. Body type should recede, letting display type and imagery lead."
|
|
58
|
+
mono:
|
|
59
|
+
families: ["Geist Mono", "Space Mono"]
|
|
60
|
+
usage: "Code examples in case studies, technical specifications, date stamps on editorial content"
|
|
61
|
+
|
|
62
|
+
anti_patterns:
|
|
63
|
+
- pattern: "Using generic stock photography on a creative portfolio or agency site"
|
|
64
|
+
reason: "Stock imagery directly contradicts the message of original creative work; it signals inauthenticity"
|
|
65
|
+
instead: "Use original photography, custom illustrations, or carefully art-directed imagery that reflects actual creative capability"
|
|
66
|
+
- pattern: "Uniform grid layouts for all content types"
|
|
67
|
+
reason: "Creative sites should demonstrate design range; predictable grids feel template-driven and corporate"
|
|
68
|
+
instead: "Vary layout rhythm with full-bleed images, asymmetric grids, and intentional whitespace; let content dictate layout"
|
|
69
|
+
- pattern: "Autoplay background video on every page"
|
|
70
|
+
reason: "Overuse dilutes impact, increases load time, and creates accessibility issues; it becomes wallpaper rather than storytelling"
|
|
71
|
+
instead: "Use video intentionally for hero moments or case study intros; provide play controls and poster frames"
|
|
72
|
+
- pattern: "Cramming every project into the portfolio with equal weight"
|
|
73
|
+
reason: "Undifferentiated project lists signal lack of editorial judgment; the portfolio itself is a design artifact"
|
|
74
|
+
instead: "Curate 8-12 best projects with clear hierarchy; feature 2-3 as hero case studies with deeper storytelling"
|
|
75
|
+
- pattern: "Tiny body text to appear more 'design-forward'"
|
|
76
|
+
reason: "Sacrificing readability for aesthetics alienates users and fails accessibility standards"
|
|
77
|
+
instead: "Use generous body text (16px+) and let typographic hierarchy, spacing, and weight create sophistication"
|
|
78
|
+
|
|
79
|
+
examples:
|
|
80
|
+
reference_sites: ["pentagram.com", "itsnicethat.com", "awwwards.com", "siteinspire.com", "creativeboom.com"]
|