@harness-engineering/cli 2.6.1 → 2.7.1
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/skills/claude-code/align-design-system/SKILL.md +174 -0
- package/dist/agents/skills/claude-code/align-design-system/skill.yaml +57 -0
- package/dist/agents/skills/claude-code/audit-brand-compliance/SKILL.md +189 -0
- package/dist/agents/skills/claude-code/audit-brand-compliance/skill.yaml +50 -0
- package/dist/agents/skills/claude-code/audit-component-anatomy/SKILL.md +181 -0
- package/dist/agents/skills/claude-code/audit-component-anatomy/skill.yaml +51 -0
- package/dist/agents/skills/claude-code/copy-craft/SKILL.md +192 -0
- package/dist/agents/skills/claude-code/copy-craft/skill.yaml +52 -0
- package/dist/agents/skills/claude-code/detect-design-drift/SKILL.md +139 -0
- package/dist/agents/skills/claude-code/detect-design-drift/skill.yaml +50 -0
- package/dist/agents/skills/claude-code/harness-accessibility/SKILL.md +10 -0
- package/dist/agents/skills/claude-code/harness-design-craft/SKILL.md +212 -0
- package/dist/agents/skills/claude-code/harness-design-craft/skill.yaml +57 -0
- package/dist/agents/skills/claude-code/harness-design-pipeline/SKILL.md +266 -0
- package/dist/agents/skills/claude-code/harness-design-pipeline/skill.yaml +70 -0
- package/dist/agents/skills/claude-code/knowledge-craft/SKILL.md +180 -0
- package/dist/agents/skills/claude-code/knowledge-craft/skill.yaml +49 -0
- package/dist/agents/skills/claude-code/naming-craft/SKILL.md +244 -0
- package/dist/agents/skills/claude-code/naming-craft/skill.yaml +51 -0
- package/dist/agents/skills/claude-code/security-craft/SKILL.md +205 -0
- package/dist/agents/skills/claude-code/security-craft/skill.yaml +58 -0
- package/dist/agents/skills/claude-code/spec-craft/SKILL.md +184 -0
- package/dist/agents/skills/claude-code/spec-craft/skill.yaml +55 -0
- package/dist/agents/skills/claude-code/test-craft/SKILL.md +212 -0
- package/dist/agents/skills/claude-code/test-craft/skill.yaml +58 -0
- package/dist/agents/skills/codex/align-design-system/SKILL.md +174 -0
- package/dist/agents/skills/codex/align-design-system/skill.yaml +57 -0
- package/dist/agents/skills/codex/audit-brand-compliance/SKILL.md +189 -0
- package/dist/agents/skills/codex/audit-brand-compliance/skill.yaml +50 -0
- package/dist/agents/skills/codex/audit-component-anatomy/SKILL.md +181 -0
- package/dist/agents/skills/codex/audit-component-anatomy/skill.yaml +51 -0
- package/dist/agents/skills/codex/copy-craft/SKILL.md +192 -0
- package/dist/agents/skills/codex/copy-craft/skill.yaml +52 -0
- package/dist/agents/skills/codex/detect-design-drift/SKILL.md +139 -0
- package/dist/agents/skills/codex/detect-design-drift/skill.yaml +50 -0
- package/dist/agents/skills/codex/harness-accessibility/SKILL.md +10 -0
- package/dist/agents/skills/codex/harness-design-craft/SKILL.md +212 -0
- package/dist/agents/skills/codex/harness-design-craft/skill.yaml +57 -0
- package/dist/agents/skills/codex/harness-design-pipeline/SKILL.md +266 -0
- package/dist/agents/skills/codex/harness-design-pipeline/skill.yaml +70 -0
- package/dist/agents/skills/codex/knowledge-craft/SKILL.md +180 -0
- package/dist/agents/skills/codex/knowledge-craft/skill.yaml +49 -0
- package/dist/agents/skills/codex/naming-craft/SKILL.md +244 -0
- package/dist/agents/skills/codex/naming-craft/skill.yaml +51 -0
- package/dist/agents/skills/codex/security-craft/SKILL.md +205 -0
- package/dist/agents/skills/codex/security-craft/skill.yaml +58 -0
- package/dist/agents/skills/codex/spec-craft/SKILL.md +184 -0
- package/dist/agents/skills/codex/spec-craft/skill.yaml +55 -0
- package/dist/agents/skills/codex/test-craft/SKILL.md +212 -0
- package/dist/agents/skills/codex/test-craft/skill.yaml +58 -0
- package/dist/agents/skills/cursor/align-design-system/SKILL.md +174 -0
- package/dist/agents/skills/cursor/align-design-system/skill.yaml +57 -0
- package/dist/agents/skills/cursor/audit-brand-compliance/SKILL.md +189 -0
- package/dist/agents/skills/cursor/audit-brand-compliance/skill.yaml +50 -0
- package/dist/agents/skills/cursor/audit-component-anatomy/SKILL.md +181 -0
- package/dist/agents/skills/cursor/audit-component-anatomy/skill.yaml +51 -0
- package/dist/agents/skills/cursor/copy-craft/SKILL.md +192 -0
- package/dist/agents/skills/cursor/copy-craft/skill.yaml +52 -0
- package/dist/agents/skills/cursor/detect-design-drift/SKILL.md +139 -0
- package/dist/agents/skills/cursor/detect-design-drift/skill.yaml +50 -0
- package/dist/agents/skills/cursor/harness-accessibility/SKILL.md +10 -0
- package/dist/agents/skills/cursor/harness-design-craft/SKILL.md +212 -0
- package/dist/agents/skills/cursor/harness-design-craft/skill.yaml +57 -0
- package/dist/agents/skills/cursor/harness-design-pipeline/SKILL.md +266 -0
- package/dist/agents/skills/cursor/harness-design-pipeline/skill.yaml +70 -0
- package/dist/agents/skills/cursor/knowledge-craft/SKILL.md +180 -0
- package/dist/agents/skills/cursor/knowledge-craft/skill.yaml +49 -0
- package/dist/agents/skills/cursor/naming-craft/SKILL.md +244 -0
- package/dist/agents/skills/cursor/naming-craft/skill.yaml +51 -0
- package/dist/agents/skills/cursor/security-craft/SKILL.md +205 -0
- package/dist/agents/skills/cursor/security-craft/skill.yaml +58 -0
- package/dist/agents/skills/cursor/spec-craft/SKILL.md +184 -0
- package/dist/agents/skills/cursor/spec-craft/skill.yaml +55 -0
- package/dist/agents/skills/cursor/test-craft/SKILL.md +212 -0
- package/dist/agents/skills/cursor/test-craft/skill.yaml +58 -0
- package/dist/agents/skills/gemini-cli/align-design-system/SKILL.md +174 -0
- package/dist/agents/skills/gemini-cli/align-design-system/skill.yaml +57 -0
- package/dist/agents/skills/gemini-cli/audit-brand-compliance/SKILL.md +189 -0
- package/dist/agents/skills/gemini-cli/audit-brand-compliance/skill.yaml +50 -0
- package/dist/agents/skills/gemini-cli/audit-component-anatomy/SKILL.md +181 -0
- package/dist/agents/skills/gemini-cli/audit-component-anatomy/skill.yaml +51 -0
- package/dist/agents/skills/gemini-cli/copy-craft/SKILL.md +192 -0
- package/dist/agents/skills/gemini-cli/copy-craft/skill.yaml +52 -0
- package/dist/agents/skills/gemini-cli/detect-design-drift/SKILL.md +139 -0
- package/dist/agents/skills/gemini-cli/detect-design-drift/skill.yaml +50 -0
- package/dist/agents/skills/gemini-cli/harness-accessibility/SKILL.md +10 -0
- package/dist/agents/skills/gemini-cli/harness-design-craft/SKILL.md +212 -0
- package/dist/agents/skills/gemini-cli/harness-design-craft/skill.yaml +57 -0
- package/dist/agents/skills/gemini-cli/harness-design-pipeline/SKILL.md +266 -0
- package/dist/agents/skills/gemini-cli/harness-design-pipeline/skill.yaml +70 -0
- package/dist/agents/skills/gemini-cli/knowledge-craft/SKILL.md +180 -0
- package/dist/agents/skills/gemini-cli/knowledge-craft/skill.yaml +49 -0
- package/dist/agents/skills/gemini-cli/naming-craft/SKILL.md +244 -0
- package/dist/agents/skills/gemini-cli/naming-craft/skill.yaml +51 -0
- package/dist/agents/skills/gemini-cli/security-craft/SKILL.md +205 -0
- package/dist/agents/skills/gemini-cli/security-craft/skill.yaml +58 -0
- package/dist/agents/skills/gemini-cli/spec-craft/SKILL.md +184 -0
- package/dist/agents/skills/gemini-cli/spec-craft/skill.yaml +55 -0
- package/dist/agents/skills/gemini-cli/test-craft/SKILL.md +212 -0
- package/dist/agents/skills/gemini-cli/test-craft/skill.yaml +58 -0
- package/dist/{agents-md-2JUQ4FE2.js → agents-md-FKMKH6ZF.js} +4 -4
- package/dist/{analyzer-VY6DJVOU-4AHIJLNS.js → analyzer-H3AHBFSL-KPOPJYRB.js} +8 -8
- package/dist/{architecture-CXAVNB5X.js → architecture-LUR2I67H.js} +6 -6
- package/dist/{assess-project-M626SSPN.js → assess-project-OJWECOP2.js} +2 -1
- package/dist/bin/harness-mcp.js +17 -17
- package/dist/bin/harness.js +27 -27
- package/dist/{check-phase-gate-XMU6LLUQ.js → check-phase-gate-HS5KYLRO.js} +5 -5
- package/dist/{chunk-5XLLIYYL.js → chunk-6UHDQP2N.js} +1 -1
- package/dist/{chunk-I6K43QQS.js → chunk-7AF6C5GE.js} +3 -3
- package/dist/{chunk-372MGNTI.js → chunk-7PLIWP7U.js} +6899 -133
- package/dist/{chunk-VUCGB2KH.js → chunk-B2VAYLYI.js} +1 -1
- package/dist/{chunk-HFOB2MPQ.js → chunk-CZPOPMMI.js} +3 -3
- package/dist/{chunk-43M3RLFQ.js → chunk-FC4JPM6W.js} +2 -2
- package/dist/{chunk-6AX6R3LM.js → chunk-FEKBXX2J.js} +9 -9
- package/dist/{chunk-VTTNIZJL.js → chunk-FXZI6NJ2.js} +131 -6
- package/dist/{chunk-5JNSFYZU.js → chunk-GGSNWH7P.js} +6 -6
- package/dist/{chunk-BCFDGOMA.js → chunk-H2ZJOJ7A.js} +81 -1
- package/dist/{chunk-PFZEADQM.js → chunk-INBTDBV2.js} +79 -2
- package/dist/{chunk-Q6ZR2L6Q.js → chunk-KN3EMDZ5.js} +2 -2
- package/dist/{chunk-JFZOWO7D.js → chunk-LECXPXS3.js} +1 -1
- package/dist/{chunk-CQOMVZDC.js → chunk-LGYXR2KZ.js} +2237 -604
- package/dist/{chunk-QOKMDDBJ.js → chunk-LYIPI2SJ.js} +6 -6
- package/dist/{chunk-L5BCZ5XS.js → chunk-N5NSSLMU.js} +1 -1
- package/dist/{chunk-GWE5LL3R.js → chunk-NIVWM7OW.js} +10 -10
- package/dist/{chunk-24KCOJJG.js → chunk-O2ASYKA6.js} +1 -1
- package/dist/{chunk-K246XQ2L.js → chunk-PTHX545Q.js} +1 -1
- package/dist/{chunk-EPUKTTJZ.js → chunk-RC3OI5NK.js} +5 -1
- package/dist/{chunk-YP7I25SL.js → chunk-RJ2WEES5.js} +1 -1
- package/dist/{chunk-5FDBXUFW.js → chunk-TIH53QXY.js} +1 -1
- package/dist/{chunk-OA6SWTU4.js → chunk-VI4IS55S.js} +11 -8
- package/dist/{chunk-GWF2OILZ.js → chunk-VSIRUZQP.js} +1 -1
- package/dist/{chunk-YYRQCQPZ.js → chunk-WZY5U6NS.js} +178 -109
- package/dist/{chunk-SZEFU6XC.js → chunk-Y4T6ENKQ.js} +9 -9
- package/dist/{chunk-HMW3VKUF.js → chunk-Z3TMCCZB.js} +10 -10
- package/dist/{ci-workflow-3JNDZQYD.js → ci-workflow-MDSTHJOY.js} +4 -4
- package/dist/{dist-OHDQBTSO.js → dist-72ID44UE.js} +3 -3
- package/dist/{dist-QPWXPCPL.js → dist-R3TOOPJ7.js} +1 -1
- package/dist/{docs-5RYMDHN3.js → docs-2RFOJ6XY.js} +6 -6
- package/dist/{engine-GKGT5ULT.js → engine-BSFKOGPN.js} +4 -4
- package/dist/{entropy-DQTAPSSE.js → entropy-3UX6644G.js} +5 -5
- package/dist/{feedback-WH6XPQJS.js → feedback-CVCFYND4.js} +2 -2
- package/dist/{generate-agent-definitions-SZA4QIHN.js → generate-agent-definitions-HZ3XENWO.js} +5 -5
- package/dist/{glob-helper-XE2UGEOV.js → glob-helper-EX4YZKZO.js} +1 -1
- package/dist/{graph-loader-EQBOIHFZ.js → graph-loader-EIFEOUVI.js} +1 -1
- package/dist/index.d.ts +1012 -12
- package/dist/index.js +27 -27
- package/dist/{loader-BNKGM23C.js → loader-6RHWU5FH.js} +4 -4
- package/dist/{mcp-YKKPWUMH.js → mcp-OYR26JDI.js} +17 -17
- package/dist/{performance-54TMJOEU.js → performance-JJMIRXCH.js} +6 -6
- package/dist/{review-pipeline-OTDDVPNY.js → review-pipeline-BHQZIXWZ.js} +4 -4
- package/dist/{runtime-W5THSNAL.js → runtime-DALTAVTN.js} +4 -4
- package/dist/{scan-4PPP6ZXT.js → scan-LYKLM4EQ.js} +1 -1
- package/dist/{security-27HW7CYT.js → security-RMLMYFPB.js} +1 -1
- package/dist/{validate-QRVCD4GP.js → validate-R7DZRDFK.js} +5 -5
- package/dist/{validate-cross-check-BUAGBAPO.js → validate-cross-check-AUUZFNVL.js} +4 -4
- package/package.json +8 -7
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: copy-craft
|
|
2
|
+
version: "0.1.0"
|
|
3
|
+
description: LLM-judgment critique of prose-in-code across six surfaces (error messages, log lines, CLI output, commit subjects, PR descriptions, code comments). Third craft-pipeline ceiling skill; primary domain is error messages (universally bad). Graceful degradation when git/gh prerequisites are absent.
|
|
4
|
+
stability: draft
|
|
5
|
+
cognitive_mode: constructive-architect
|
|
6
|
+
triggers:
|
|
7
|
+
- manual
|
|
8
|
+
- on_pr
|
|
9
|
+
- on_new_feature
|
|
10
|
+
platforms:
|
|
11
|
+
- claude-code
|
|
12
|
+
tools:
|
|
13
|
+
- Bash
|
|
14
|
+
- Read
|
|
15
|
+
- Glob
|
|
16
|
+
- Grep
|
|
17
|
+
cli:
|
|
18
|
+
command: harness copy-craft
|
|
19
|
+
args:
|
|
20
|
+
- name: path
|
|
21
|
+
description: Project root path
|
|
22
|
+
required: false
|
|
23
|
+
- name: files
|
|
24
|
+
description: Optional source file/glob scope
|
|
25
|
+
required: false
|
|
26
|
+
- name: surfaces
|
|
27
|
+
description: Restrict to error/log/cli-output/commit/pr-description/comment
|
|
28
|
+
required: false
|
|
29
|
+
- name: commits-since
|
|
30
|
+
description: Commit window (default 1 month ago)
|
|
31
|
+
required: false
|
|
32
|
+
mcp:
|
|
33
|
+
tool: copy_craft
|
|
34
|
+
input:
|
|
35
|
+
path: string
|
|
36
|
+
type: rigid
|
|
37
|
+
tier: 2
|
|
38
|
+
phases:
|
|
39
|
+
- name: extract
|
|
40
|
+
description: TS Compiler API for source surfaces; git/gh shell-out for commits + PRs
|
|
41
|
+
required: true
|
|
42
|
+
- name: critique
|
|
43
|
+
description: LLM-rubric loop per (item, rubric) where rubric applies to that surface
|
|
44
|
+
required: true
|
|
45
|
+
- name: report
|
|
46
|
+
description: Aggregate findings + per-surface counts + cost telemetry + skipped surfaces
|
|
47
|
+
required: true
|
|
48
|
+
state:
|
|
49
|
+
persistent: false
|
|
50
|
+
depends_on:
|
|
51
|
+
- harness-design-craft
|
|
52
|
+
- naming-craft
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Detect Design Drift
|
|
2
|
+
|
|
3
|
+
> Detect design-system drift — hardcoded values where tokens exist, and raw HTML primitives where registered components exist. The rule-based floor of design-pipeline #1 (detect half). Reports findings; never modifies source. Pairs with a separate align-design-system fixer skill (deferred to a sibling sub-project).
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Reviewing a PR that touches UI code, when you want to catch divergence from the design system before it ships
|
|
8
|
+
- After adding a new design token, to surface places in the codebase that still use the hardcoded equivalent
|
|
9
|
+
- After registering a new primitive (e.g. Button) in DESIGN.md `## Component Registry`, to find existing raw-HTML usages that should adopt it
|
|
10
|
+
- As part of `harness validate` so drift surfaces continuously, not only on demand
|
|
11
|
+
- As one of three verifiers composed by `harness check-design` (alongside audit-component-anatomy and harness-design-craft)
|
|
12
|
+
- NOT for component-anatomy gaps (use audit-component-anatomy)
|
|
13
|
+
- NOT for aesthetic critique (use harness-design-craft)
|
|
14
|
+
- NOT for fixing drift — this skill detects only; the matching fixer (align-design-system) is a separate sub-project
|
|
15
|
+
|
|
16
|
+
## Process
|
|
17
|
+
|
|
18
|
+
### Phase 1: SCAN — Load resolvers + walk files
|
|
19
|
+
|
|
20
|
+
1. **Read project configuration.** Check `harness.config.json` for:
|
|
21
|
+
- `design.strictness` — `strict` / `standard` / `permissive` (default `standard`)
|
|
22
|
+
- `design.audit.driftDetection.enabled` — gate for the verifier (default `true`)
|
|
23
|
+
- `design.audit.driftDetection.rules.{tokenBypass,primitiveAdoption}` — per-rule toggles
|
|
24
|
+
- `design.audit.driftDetection.fastMode.maxFiles` — validate-time scope cap
|
|
25
|
+
|
|
26
|
+
2. **Load resolvers (soft-dependency — silent skip when absent):**
|
|
27
|
+
- `design-system/tokens.json` (W3C DTCG format) — parsed by `loadTokenSet`. Extracts colors, font families, spacing scale, and deprecated token paths. Returns `null` when the file doesn't exist; token-bypass rules then skip silently.
|
|
28
|
+
- `design-system/DESIGN.md` `## Component Registry` — parsed by `loadComponentRegistry`. Maps registered component types (Button/Input/Textarea/Link/Anchor) to their HTML primitive tag. Returns `null` when DESIGN.md or the section is absent; primitive-adoption rules then skip silently.
|
|
29
|
+
|
|
30
|
+
3. **Collect candidate files.** Walk the project root (or honor an explicit `files` arg from the caller). Skip `node_modules`, `dist`, `build`, `coverage`, and any dotfile directory. Honor only these extensions: `.ts`, `.tsx`, `.js`, `.jsx`, `.css`, `.scss`.
|
|
31
|
+
|
|
32
|
+
### Phase 2: APPLY RULES — Two rule families
|
|
33
|
+
|
|
34
|
+
1. **Token bypass rules (DRIFT-T\*) — regex-based detection.** For each file when tokens were loaded:
|
|
35
|
+
- **DRIFT-T001** — Hex color literal (`#abc`, `#aabbcc`, etc.) NOT present in the loaded palette. Case-insensitive palette match. Deduplicated per `line:value`.
|
|
36
|
+
- **DRIFT-T002** — Font-family string literal NOT present in the typography palette. System fallbacks (`sans-serif`, `serif`, `monospace`, `system-ui`, `inherit`) are always allowed.
|
|
37
|
+
- **DRIFT-T003** — Pixel margin/padding/gap/positioning value NOT present in the spacing scale. Skipped entirely when no spacing tokens exist.
|
|
38
|
+
- **DRIFT-T004** — Reference to a token flagged `$deprecated: true` (or `$extensions.harness.deprecated: true`) in tokens.json. Matched in both `'token.path.form'` and CSS-var kebab form (`--token-path-form`).
|
|
39
|
+
|
|
40
|
+
2. **Primitive adoption rules (DRIFT-P\*) — TS Compiler API JSX parsing.** For each `.jsx`/`.tsx` file when the registry was loaded:
|
|
41
|
+
- **DRIFT-P001** — `<button>` JSX where `Button` is registered
|
|
42
|
+
- **DRIFT-P002** — `<input>` JSX where `Input` is registered
|
|
43
|
+
- **DRIFT-P003** — `<a>` JSX where `Link` or `Anchor` is registered
|
|
44
|
+
- **DRIFT-P004** — `<textarea>` JSX where `Textarea` is registered
|
|
45
|
+
- Lowercase JSX = HTML primitive (JSX semantics). Uppercase identifiers are skipped — they're already components. Member expressions (`<Foo.Bar>`) are skipped.
|
|
46
|
+
|
|
47
|
+
### Phase 3: REPORT — Severity, aggregate, persist
|
|
48
|
+
|
|
49
|
+
1. **Severity from `design.strictness`:**
|
|
50
|
+
- `strict` — every finding `error` (CI blocks)
|
|
51
|
+
- `standard` — DRIFT-T001/T002/P001 → `error`; everything else → `warn`
|
|
52
|
+
- `permissive` — everything → `info`
|
|
53
|
+
|
|
54
|
+
2. **Aggregate the run summary.** `bySeverity`, `byCode`, `totalFiles`, `durationMs`. Also report `catalog.rulesApplied` (which rule families fired) and `meta.{tokensLoaded, registryLoaded, mode}` so callers can see what was active.
|
|
55
|
+
|
|
56
|
+
3. **Persist findings to the graph (when composed by check-design).** The check-design orchestrator passes drift findings to `DesignConstraintAdapter.recordFindings()` alongside anatomy and craft findings. Each finding becomes an idempotent `VIOLATES_design` edge keyed by `(file, code, line)` — re-runs do not double-write.
|
|
57
|
+
|
|
58
|
+
## Harness Integration
|
|
59
|
+
|
|
60
|
+
- **`harness validate`** — Fast-mode hook runs the detect-drift verifier. Findings respect `design.strictness`. Failures degrade gracefully: if the verifier throws, validate logs a warning and continues with other checks.
|
|
61
|
+
- **`harness check-design`** — One of three composed verifiers. The orchestrator aggregates findings across audit-anatomy, design-craft, and detect-drift; persists all three to the graph; and surfaces a unified report.
|
|
62
|
+
- **`mcp__harness__detect_drift`** — Programmatic API. Input: `{ path, mode, files?, designStrictness?, rules? }`. Output: `{ findings, summary, catalog, meta }`. Consumed by the design-pipeline orchestrator (sub-project #5).
|
|
63
|
+
- **`DesignConstraintAdapter.recordFindings()`** — Generic graph persistence entry point shipped in PR #390. Drift findings reuse the adapter; no extra graph plumbing.
|
|
64
|
+
- **Future align-design-system skill** — Separate sub-project. Reads the same finding codes (DRIFT-T\*, DRIFT-P\*) and applies fixes. Decoupling detect from align keeps each skill testable in isolation and lets the detect side ship first.
|
|
65
|
+
|
|
66
|
+
## Success Criteria
|
|
67
|
+
|
|
68
|
+
See `docs/changes/design-pipeline/detect-design-drift/proposal.md` for the full 34 success criteria. Highlights:
|
|
69
|
+
|
|
70
|
+
- Zero false positives when tokens.json/DESIGN.md are absent (rules skip silently — no speculative findings)
|
|
71
|
+
- Token-bypass detection runs in < 1s on a 500-file repo (fast-mode budget)
|
|
72
|
+
- Primitive-adoption parses JSX correctly across multi-line / fragmented opening tags (TS Compiler API, not regex)
|
|
73
|
+
- Idempotent graph persistence — re-running produces zero duplicate edges
|
|
74
|
+
- `harness validate` runtime budget < 3s on a 500-file repo with both rule families enabled
|
|
75
|
+
- Both rule families gated independently via config (a project can disable primitive-adoption without disabling token-bypass)
|
|
76
|
+
|
|
77
|
+
## Examples
|
|
78
|
+
|
|
79
|
+
### Example: Hardcoded brand color outside the palette
|
|
80
|
+
|
|
81
|
+
**Input:** `src/Card.tsx` contains `const styles = { color: "#ff0000" };`, and `design-system/tokens.json` defines `color.brand.primary` as `#0066cc` (but no `#ff0000`).
|
|
82
|
+
|
|
83
|
+
**Output:**
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
DRIFT-T001 [error] src/Card.tsx:14 — Hardcoded color "#ff0000" is not in the design token palette
|
|
87
|
+
Fix: Replace "#ff0000" with a token reference (e.g. var(--color-...) or a token-system lookup).
|
|
88
|
+
If the color is intentionally one-off, add it to tokens.json first.
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Severity is `error` under `standard` because brand-color drift is high-impact.
|
|
92
|
+
|
|
93
|
+
### Example: Raw `<button>` where Button is registered
|
|
94
|
+
|
|
95
|
+
**Input:** `src/SaveButton.tsx` contains `<button onClick={...}>Save</button>`, and `design-system/DESIGN.md` `## Component Registry` lists `Button` mapped to `packages/ui/src/Button.tsx`.
|
|
96
|
+
|
|
97
|
+
**Output:**
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
DRIFT-P001 [error] src/SaveButton.tsx:8 — Raw <button> element where the registered component "Button" should be used
|
|
101
|
+
Fix: Import Button from your component library and replace <button> with <Button>.
|
|
102
|
+
If this raw primitive is intentional (e.g. inside the Button component's own implementation),
|
|
103
|
+
add a JSDoc `@allow-raw-primitive` annotation on the file.
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Example: Reference to a deprecated token
|
|
107
|
+
|
|
108
|
+
**Input:** `src/legacy.css` contains `.x { color: var(--color-brand-500); }`, and `tokens.json` flags `color.brand.500` as `$deprecated: true` with `$description: "Use color.brand.primary instead"`.
|
|
109
|
+
|
|
110
|
+
**Output:**
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
DRIFT-T004 [warn] src/legacy.css:3 — Token "color.brand.500" is deprecated and should be migrated
|
|
114
|
+
Fix: Migrate references to "color.brand.500" to the replacement token noted in tokens.json $description,
|
|
115
|
+
or remove the deprecation if the token is still load-bearing.
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Gates
|
|
119
|
+
|
|
120
|
+
- **No findings without resolved inputs.** If `tokens.json` is absent, all T\* rules silently skip. If `DESIGN.md ## Component Registry` is absent, all P\* rules silently skip. Either resolver failing is not a verifier failure — the project simply hasn't opted in.
|
|
121
|
+
- **No autofix.** Findings include codemod-todo descriptions. The matching fixer (align-design-system) is a separate skill.
|
|
122
|
+
- **No usage-side primitive findings beyond the four registered tags.** Other tags (`<select>`, `<details>`, etc.) are not in scope for v1 — even if the project registers a component for them. Subsumption ships in v1.x.
|
|
123
|
+
- **Strictness from config, not assumed.** Read `design.strictness` from `harness.config.json`; default to `standard` if absent.
|
|
124
|
+
|
|
125
|
+
## Escalation
|
|
126
|
+
|
|
127
|
+
- **When token-bypass false positives appear in a third-party-shaped value.** E.g. a vendor color brought in via a CSS variable that legitimately doesn't match the palette. Either add the value to `tokens.json` (preferred — makes the palette authoritative) or scope the file via `design.audit.driftDetection.rules.tokenBypass: false` for a narrow path-overrides block (v1.x).
|
|
128
|
+
- **When primitive-adoption fires inside the Button component's own implementation.** That's a true positive that the rule can't tell apart from the usage form. Two paths: (1) add `@allow-raw-primitive` JSDoc on the file (v1.x — annotation honored by the rule), or (2) extract the raw `<button>` into a private internal component until the annotation lands.
|
|
129
|
+
- **When `harness validate` runtime exceeds 3 seconds.** Set `design.audit.driftDetection.fastMode.maxFiles` to cap the scope. The MCP tool ignores the cap (`fast`/`full` are equivalent in v1 — the cap is validate-side only).
|
|
130
|
+
- **When the graph persistence fails.** Skip graph integration for that run; findings still appear in the report. The graph is a consumer, not a gate.
|
|
131
|
+
- **When a project ships its own design-system convention (not tokens.json, not DESIGN.md registry).** v1 reads only the two declared input formats. Either (1) generate a tokens.json adapter that mirrors the existing convention (one-shot script), or (2) wait for v1.x's pluggable resolver interface.
|
|
132
|
+
|
|
133
|
+
## Status
|
|
134
|
+
|
|
135
|
+
**v1 — in implementation.** See:
|
|
136
|
+
|
|
137
|
+
- Spec: `docs/changes/design-pipeline/detect-design-drift/proposal.md`
|
|
138
|
+
- Roadmap entry: `design-pipeline sub-project #1` (detect half) in `docs/roadmap.md`
|
|
139
|
+
- Sibling: `align-design-system` (fix half — deferred to a separate sub-project)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: detect-design-drift
|
|
2
|
+
version: "0.1.0"
|
|
3
|
+
description: Detect design-system drift — hardcoded values where tokens exist and raw HTML primitives where registered components exist. Reports only; never modifies source. Floor-layer rule-based verifier composed by harness check-design.
|
|
4
|
+
stability: draft
|
|
5
|
+
cognitive_mode: constructive-architect
|
|
6
|
+
triggers:
|
|
7
|
+
- manual
|
|
8
|
+
- on_pr
|
|
9
|
+
- on_new_feature
|
|
10
|
+
platforms:
|
|
11
|
+
- claude-code
|
|
12
|
+
tools:
|
|
13
|
+
- Bash
|
|
14
|
+
- Read
|
|
15
|
+
- Glob
|
|
16
|
+
- Grep
|
|
17
|
+
cli:
|
|
18
|
+
command: harness skill run detect-design-drift
|
|
19
|
+
args:
|
|
20
|
+
- name: path
|
|
21
|
+
description: Project root path
|
|
22
|
+
required: false
|
|
23
|
+
- name: mode
|
|
24
|
+
description: "fast or full (equivalent in v1 — reserved for future scope expansion)"
|
|
25
|
+
required: false
|
|
26
|
+
- name: files
|
|
27
|
+
description: Optional list of files to scope the run
|
|
28
|
+
required: false
|
|
29
|
+
mcp:
|
|
30
|
+
tool: run_skill
|
|
31
|
+
input:
|
|
32
|
+
skill: detect-design-drift
|
|
33
|
+
path: string
|
|
34
|
+
type: rigid
|
|
35
|
+
tier: 2
|
|
36
|
+
phases:
|
|
37
|
+
- name: scan
|
|
38
|
+
description: Load tokens.json and DESIGN.md registry; walk candidate files
|
|
39
|
+
required: true
|
|
40
|
+
- name: apply_rules
|
|
41
|
+
description: Run DRIFT-T* and DRIFT-P* rules per file
|
|
42
|
+
required: true
|
|
43
|
+
- name: report
|
|
44
|
+
description: Aggregate severity, format findings, persist to graph
|
|
45
|
+
required: true
|
|
46
|
+
state:
|
|
47
|
+
persistent: false
|
|
48
|
+
depends_on:
|
|
49
|
+
- audit-component-anatomy
|
|
50
|
+
- harness-design-craft
|
|
@@ -31,6 +31,15 @@
|
|
|
31
31
|
- If `i18n.enabled` is false or absent, scan for `lang`/`dir` as normal (these remain part of the accessibility audit).
|
|
32
32
|
- This deduplication prevents the same finding from appearing in both the accessibility report and the i18n report.
|
|
33
33
|
|
|
34
|
+
2.6. **Check for component-anatomy audit overlap.** Read `harness.config.json` for `design.audit.componentAnatomy.enabled` (default `true` when absent):
|
|
35
|
+
|
|
36
|
+
- If `enabled: true`, **defer** `A11Y-010` (interactive elements without accessible labels) and `A11Y-050` (`<input>`/`<select>`/`<textarea>` without associated `<label>`) findings for components whose identified type is in the anatomy catalog. Load the catalog component-type set via `getCatalogTypes()` from `audit-component-anatomy`'s public export so this skill has zero rule-content duplication.
|
|
37
|
+
- Identify each scanned JSX element's component type using the same 3-layer resolver `audit-component-anatomy` uses: (1) JSDoc `@component-type X` tag, (2) `design-system/DESIGN.md` `## Component Registry` mapping, (3) top-level export-name catalog match.
|
|
38
|
+
- For components in the catalog: `audit-component-anatomy` owns the label-slot finding as `ANAT-D*` (definition-side in v1, `ANAT-U*` in v2). Do not emit `A11Y-010` / `A11Y-050` for them.
|
|
39
|
+
- For raw HTML elements (`<button>`, `<input>`, `<select>`, `<textarea>`) and unidentified components: scan for `A11Y-010` / `A11Y-050` as normal.
|
|
40
|
+
- If `enabled: false` or absent: scan for `A11Y-010` / `A11Y-050` as normal (no deferral).
|
|
41
|
+
- Same i18n-style deduplication pattern as step 2.5 — prevents one root cause from appearing in both the accessibility report and the anatomy report.
|
|
42
|
+
|
|
34
43
|
3. **Scan component files.** Search all files matching `.tsx`, `.jsx`, `.vue`, `.svelte`, `.html` for the following violations:
|
|
35
44
|
|
|
36
45
|
**Images and media:**
|
|
@@ -183,6 +192,7 @@ This phase is optional. It applies fixes only for **mechanical issues** -- viola
|
|
|
183
192
|
- **`harness-impact-analysis`** -- When tokens change (palette update, new colors), impact analysis traces affected components. The accessibility skill uses this to determine which components need re-scanning.
|
|
184
193
|
- **`harness-design-system`** -- Dependency. When contrast failures originate from token definitions (not component code), escalate to harness-design-system to fix at the source.
|
|
185
194
|
- **`harness-i18n` deduplication** -- When `i18n.enabled: true` in config, `lang` and `dir` attribute checks are deferred to the i18n skill. This prevents duplicate findings across the accessibility and i18n reports. When i18n is not enabled, these checks remain part of the accessibility scan.
|
|
195
|
+
- **`audit-component-anatomy` deduplication** -- When `design.audit.componentAnatomy.enabled: true` in config (default), `A11Y-010` and `A11Y-050` are deferred to `audit-component-anatomy` for components in its catalog (Button, Input, Select, Modal, Card, Tabs, etc.). The anatomy audit owns the label-slot finding for those components; this skill still scans raw HTML and unidentified components. Same i18n-style deduplication pattern.
|
|
186
196
|
|
|
187
197
|
## Success Criteria
|
|
188
198
|
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
# Harness Design Craft
|
|
2
|
+
|
|
3
|
+
> LLM-judgment-based design ceiling-raiser. Three branchable phases — CRITIQUE finds what's mediocre, POLISH applies high-craft moves, BENCHMARK scores against curated exemplars. The ceiling counterpart to harness-design (declared-intent enforcement, rule-based) and the design-pipeline floor audits.
|
|
4
|
+
|
|
5
|
+
## When to Use
|
|
6
|
+
|
|
7
|
+
- Reviewing UI for craft elevation opportunities the rule-based skills can't surface ("hierarchy is muddy here," "loading spinner where a content-matched skeleton would fit")
|
|
8
|
+
- After harness-design has captured intent and basic checks pass — go from "consistent" to "stunning"
|
|
9
|
+
- Before launching customer-facing surfaces — visual judgment beyond consistency
|
|
10
|
+
- During design-engineering work — POLISH phase suggests concrete craft moves with before/after sketches
|
|
11
|
+
- For competitive benchmarking — BENCHMARK scores how close you are to Linear / Stripe / Raycast tier
|
|
12
|
+
- When `on_new_feature` fires AND the feature touches design surface
|
|
13
|
+
- NOT for declared-anti-pattern enforcement (use harness-design)
|
|
14
|
+
- NOT for component anatomy completeness (use audit-component-anatomy)
|
|
15
|
+
- NOT for token validation (use harness-design-system)
|
|
16
|
+
- NOT for accessibility (use harness-accessibility)
|
|
17
|
+
- NOT for code generation from scratch (use v0 / bolt.new / Lovable — different tool class)
|
|
18
|
+
|
|
19
|
+
## Process
|
|
20
|
+
|
|
21
|
+
### Argument Resolution
|
|
22
|
+
|
|
23
|
+
- `mode`: `"fast"` (code-only LLM, cheap, default) or `"deep"` (rendered + vision-LLM, ceiling-raising, requires playwright + vision-capable model)
|
|
24
|
+
- `phases`: subset of `critique`, `polish`, `benchmark`. Default: all three, sequenced.
|
|
25
|
+
- `autoCapture`: B' upgrade behavior. `"prompt"` (default — offer to chain to harness-design if preconditions missing), `"auto"` (chain without prompting), `"skip"` (run with generic-craft rubrics, no offer).
|
|
26
|
+
- `files`: optional scoping. Default: all components/pages discovered.
|
|
27
|
+
|
|
28
|
+
### B' Precondition Check (every invocation)
|
|
29
|
+
|
|
30
|
+
Before any phase runs, check four preconditions and offer to fulfill missing ones:
|
|
31
|
+
|
|
32
|
+
| Precondition | Source | If missing |
|
|
33
|
+
| ---------------------------- | ----------------------------------------------- | -------------------------------------------------------------------- |
|
|
34
|
+
| `designMdExists` | `design-system/DESIGN.md` present | Offer to chain to harness-design (INTENT + DIRECTION) |
|
|
35
|
+
| `aestheticIntentDeclared` | DESIGN.md Aesthetic Direction section populated | Offer to chain to harness-design (INTENT) |
|
|
36
|
+
| `tokensExist` | `design-system/tokens.json` present | Note in summary; do not auto-chain (harness-design-system territory) |
|
|
37
|
+
| `componentRegistryPopulated` | DESIGN.md Component Registry section | Note in summary; falls back to export-name resolution |
|
|
38
|
+
|
|
39
|
+
`autoCapture` controls behavior:
|
|
40
|
+
|
|
41
|
+
- `prompt`: emit `upgradeOffer` interaction; pause for user choice
|
|
42
|
+
- `auto`: chain to harness-design transition automatically (for autopilot)
|
|
43
|
+
- `skip`: run with generic-craft rubrics (degrades quality but unblocks first-run)
|
|
44
|
+
|
|
45
|
+
### Phase: CRITIQUE — Find what is craft-mediocre
|
|
46
|
+
|
|
47
|
+
1. **Identify targets.** Discover components (or pages, when scoped to pages) to critique. Apply `files` scoping if provided.
|
|
48
|
+
|
|
49
|
+
2. **Load critique rubrics.** Read from catalog (`catalog/rubrics/`). 10 rubrics in v1 covering: hierarchy clarity, typography craft, motion quality, color confidence, density rhythm, restraint, polish details, copy voice, interaction craft, brand coherence. Filter by `catalog.rubrics` config if set.
|
|
50
|
+
|
|
51
|
+
3. **For each target × each rubric, run an LLM critique pass:**
|
|
52
|
+
- **Fast mode:** pass source code + rubric prompt + AestheticIntent (if present) to text LLM
|
|
53
|
+
- **Deep mode:** render via playwright at three viewports (1440/768/375), pass screenshots + source + rubric prompt + AestheticIntent to vision-capable LLM
|
|
54
|
+
- Parse response into 3-axis finding: `tier` (foundational/polish/aspirational), `impact` (small/medium/large), `confidence` (high/medium/low — essential for honest LLM output)
|
|
55
|
+
|
|
56
|
+
4. **Apply harness-design overlap deferral.** Per `design.craft.enabled = true`, when a CRITIQUE finding matches a declared anti-pattern in DESIGN.md, defer to harness-design (suppress this finding) and increment `meta.deferralsToHarnessDesign`.
|
|
57
|
+
|
|
58
|
+
5. **Compute derived `priority` field** for each finding (tier × impact × confidence-weighted score) for single-axis sorting when needed.
|
|
59
|
+
|
|
60
|
+
### Phase: POLISH — Apply craft pattern library
|
|
61
|
+
|
|
62
|
+
1. **Load polish patterns.** Read from catalog (`catalog/patterns/`). 15 patterns in v1 across 5 categories: motion (3), skeleton (3), typography (3), interaction (3), layout (3). Filter by `catalog.patterns` config if set.
|
|
63
|
+
|
|
64
|
+
2. **For each target × each applicable pattern, evaluate fit:**
|
|
65
|
+
- Match pattern's `applicableTo` criteria (jsx-attribute, css-property, component-type, etc.)
|
|
66
|
+
- LLM judgment: would applying this pattern improve craft here?
|
|
67
|
+
- If yes: produce 3-axis finding with `before` and `after` content (codemod-TODO sketch, not actual edit)
|
|
68
|
+
|
|
69
|
+
3. **No source modification.** POLISH only emits suggestions with before/after sketches. The user applies via codemod tools or by hand.
|
|
70
|
+
|
|
71
|
+
### Phase: BENCHMARK — Score against curated exemplars
|
|
72
|
+
|
|
73
|
+
1. **Load exemplar corpus.** Read from catalog (`catalog/exemplars/`). 50 exemplars in v1 across 5 component types (EmptyState, LoadingState, ErrorState, Modal, Button — 10 each). Filter by `catalog.exemplars` config if set.
|
|
74
|
+
|
|
75
|
+
2. **For each target component, identify matching exemplars** by component-type tag (e.g., target is an EmptyState → load all 10 EmptyState exemplars).
|
|
76
|
+
|
|
77
|
+
3. **For each target × matching exemplars, run an LLM benchmark pass:**
|
|
78
|
+
- **Fast mode:** structural comparison (code/markup/declared anatomy vs exemplar's reference markup) — limited but useful as a first signal
|
|
79
|
+
- **Deep mode:** visual comparison via vision-LLM (target screenshot vs exemplar screenshot/URL)
|
|
80
|
+
- Parse response into 5-dim radar: `philosophicalCoherence`, `hierarchy`, `craftExecution`, `function`, `innovation` — each with score (0-100), confidence, notes
|
|
81
|
+
- Compute weighted `overall` score
|
|
82
|
+
- Emit narrative `gaps` (where the target falls short of the best exemplars and why)
|
|
83
|
+
|
|
84
|
+
4. **Cite exemplars used.** Each `BenchmarkScore` lists `exemplars` (ids) consulted. Increment per-exemplar `citationCount` for measurement.
|
|
85
|
+
|
|
86
|
+
### Phase: REPORT — Format and persist outputs
|
|
87
|
+
|
|
88
|
+
1. **Write to graph:** CRITIQUE/POLISH findings → `VIOLATES_CRAFT` edges via extended `DesignConstraintAdapter`. BENCHMARK scores → `CRAFT_SCORE` nodes attached to component nodes. All carry `runId` for sub-project #4 fixpoint detection. Idempotent.
|
|
89
|
+
|
|
90
|
+
2. **Format markdown report.** Grouped by component, with `CRAFT-*` codes linked to `finding-codes.md` and rubric/pattern/exemplar names linked to their catalog entries. Low-confidence findings visually distinguished (italic or `(low confidence:)` prefix).
|
|
91
|
+
|
|
92
|
+
3. **Emit summary.** Total findings, breakdown by phase, mode (`fast`/`deep`), LLM cost (`llmCalls.{count, costUsd}`), catalog applied, deferrals to harness-design, precondition state.
|
|
93
|
+
|
|
94
|
+
4. **Signal feedback.** Append to running aggregate: when the same finding-shape recurs N≥5 times across audits (config: `design.craft.signal.proposalThreshold`), emit a candidate pattern proposal to `.harness/design-craft/proposals/`.
|
|
95
|
+
|
|
96
|
+
## Harness Integration
|
|
97
|
+
|
|
98
|
+
- **`harness validate`** — Fast-mode CRITIQUE hook (subset of rubrics; opt-in). Findings respect `design.strictness`.
|
|
99
|
+
- **`mcp__harness__design_craft`** — Programmatic API. Consumed by harness check-design verifier (#4) and design-pipeline orchestrator (#5). Phase selector exposed.
|
|
100
|
+
- **`harness-design`** — Soft dependency. B' progressive upgrade chains to it when AestheticIntent missing. Defers declared-anti-pattern findings to it.
|
|
101
|
+
- **`harness-design-system`** — Soft dependency. Token-related polish patterns enriched when tokens exist.
|
|
102
|
+
- **`DesignConstraintAdapter`** — Extended for `CRAFT-*` codes (CRAFT-C* critique, CRAFT-P* polish, CRAFT-B\* benchmark identifiers) + `CRAFT_SCORE` node type.
|
|
103
|
+
- **`packages/intelligence/`** — Wrapped by `llm/provider.ts` for vision-capable LLM calls. May need extension if no vision support today.
|
|
104
|
+
|
|
105
|
+
## Success Criteria
|
|
106
|
+
|
|
107
|
+
See `docs/changes/design-pipeline/design-craft-elevator/proposal.md` for the full 38 success criteria. Highlights:
|
|
108
|
+
|
|
109
|
+
- Three phases independently invocable via `phases` arg
|
|
110
|
+
- 3-axis output for CRITIQUE/POLISH; 5-dim radar for BENCHMARK
|
|
111
|
+
- Confidence is honest (low-confidence findings emitted, not silently dropped)
|
|
112
|
+
- B' detect-and-offer works (preconditions detected, offer payload emitted, chain to harness-design honored)
|
|
113
|
+
- Seed catalog complete (10 rubrics + 15 patterns + 50 exemplars)
|
|
114
|
+
- Growth infrastructure operational (contribution validation, signal loop, usage measurement)
|
|
115
|
+
- Fast-mode ≤ 30s / 50 files; deep-mode ≤ 3min / 10 components
|
|
116
|
+
- LLM cost tracked per audit
|
|
117
|
+
|
|
118
|
+
## Examples
|
|
119
|
+
|
|
120
|
+
### Example: CRITIQUE finds hierarchy muddiness
|
|
121
|
+
|
|
122
|
+
**Input:** A Dashboard.tsx page rendering three CTA buttons, all using the same `variant="primary"`.
|
|
123
|
+
|
|
124
|
+
**Output (3-axis finding):**
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
CRAFT-C001 [foundational | medium | high] Hierarchy muddy: three buttons compete for primary
|
|
128
|
+
File: src/pages/Dashboard.tsx:88
|
|
129
|
+
Rubric: hierarchy-clarity (rubric-hierarchy-clarity)
|
|
130
|
+
Tier: foundational (this is "fix to be not-broken," not polish)
|
|
131
|
+
Impact: medium (users can still complete tasks, but decision fatigue is real)
|
|
132
|
+
Confidence: high (rule is unambiguous; LLM saw the three buttons + their identical styling)
|
|
133
|
+
Priority: derived → 0.78
|
|
134
|
+
Message: Three primary-variant buttons in the same view: "Save", "Export", "Share".
|
|
135
|
+
No visual signal indicates which is the recommended action. Reduce to one
|
|
136
|
+
primary; demote the others to secondary or ghost variant.
|
|
137
|
+
Cite: rubric "hierarchy-clarity" / source: huashu-design#hierarchy
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Example: POLISH suggests spring physics
|
|
141
|
+
|
|
142
|
+
**Input:** A Modal.tsx using `transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1)`.
|
|
143
|
+
|
|
144
|
+
**Output (3-axis finding with before/after):**
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
CRAFT-P001 [polish | medium | high] Spring physics would feel more confident here
|
|
148
|
+
File: src/components/Modal.tsx:42
|
|
149
|
+
Pattern: spring-physics-microinteraction
|
|
150
|
+
Tier: polish (Modal already works; this elevates the feel)
|
|
151
|
+
Impact: medium (users notice modal motion every time)
|
|
152
|
+
Before: transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
153
|
+
After: transition: transform { duration: spring.medium };
|
|
154
|
+
// stiffness:200 damping:25 for modal entries per emil-design-eng#spring-physics
|
|
155
|
+
Fix kind: codemod-todo (POLISH does not modify source; suggestion only)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Example: BENCHMARK against Linear
|
|
159
|
+
|
|
160
|
+
**Input:** A custom EmptyState component for the project's task list.
|
|
161
|
+
|
|
162
|
+
**Output (5-dim radar):**
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
CRAFT-B001 EmptyState component scored against Linear empty list exemplar
|
|
166
|
+
|
|
167
|
+
philosophicalCoherence: 80 [high] "Restraint aligns with declared minimal aesthetic."
|
|
168
|
+
hierarchy: 65 [medium] "Heading and body OK; action button competes
|
|
169
|
+
with secondary 'Learn more' link."
|
|
170
|
+
craftExecution: 55 [medium] "Generic illustration; Linear uses subtle line art
|
|
171
|
+
matching their monochromatic palette. Missing the
|
|
172
|
+
'breathing room' Linear gets via 64px vertical padding."
|
|
173
|
+
function: 85 [high] "Action is clear and verb-led."
|
|
174
|
+
innovation: 50 [low] "Standard 4-part anatomy; not differentiated."
|
|
175
|
+
|
|
176
|
+
Overall: 67 [medium confidence]
|
|
177
|
+
Gaps:
|
|
178
|
+
- "Reduce the empty-state to one CTA — the secondary link adds noise"
|
|
179
|
+
- "Replace stock illustration with a custom line art aligned to brand"
|
|
180
|
+
- "Increase top padding from 32px to 56px+ to match the breathing-room pattern"
|
|
181
|
+
Exemplars cited: exemplar-linear-empty-list
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Gates
|
|
185
|
+
|
|
186
|
+
- **No assertion of "stunning" without LLM judgment.** This skill is LLM-judgment-based; if no LLM provider is configured, halt with explanatory error — do not degrade to rule-based output.
|
|
187
|
+
- **Deep mode requires playwright + vision-capable LLM.** If either is missing, surface to user with the documented fallback path (code-only mode); do not silently degrade.
|
|
188
|
+
- **No autofix.** POLISH emits suggestions only; source files are never modified.
|
|
189
|
+
- **Confidence is honest.** Low-confidence outputs MUST be emitted (with the low-confidence flag) — never silently upgraded.
|
|
190
|
+
- **B' deferral honored.** When `design.craft.enabled = true` and DESIGN.md declares an anti-pattern matching a CRITIQUE finding, defer to harness-design; never double-count.
|
|
191
|
+
|
|
192
|
+
## Escalation
|
|
193
|
+
|
|
194
|
+
- **When deep mode renders fail (component not reachable via URL).** Emit a "render-unreachable" finding for the affected component, fall back to fast mode for that component, continue the audit. Do not abort.
|
|
195
|
+
- **When the vision-LLM rejects the screenshot (size, content, format).** Log the rejection; downgrade that component's run to fast mode; do not abort.
|
|
196
|
+
- **When LLM cost exceeds the configured per-audit budget.** Halt the audit, emit findings collected so far, report the cost overrun. Do not retry. Config: `design.craft.llm.maxCostUsd` (default unset = no cap).
|
|
197
|
+
- **When the catalog is empty or unloadable.** Halt with explanatory error pointing to `agents/skills/shared/design-knowledge/craft-{rubrics,patterns,exemplars}/`. Do not synthesize findings without the catalog.
|
|
198
|
+
- **When B' detect-and-offer produces an offer the user declines.** Run in generic-craft mode (no AestheticIntent context); note the degraded quality in summary. User can re-invoke with `autoCapture: skip` to suppress future offers.
|
|
199
|
+
- **When the same finding-shape recurs across many audits (signal feedback loop).** Auto-export a candidate pattern proposal to `.harness/design-craft/proposals/` after N≥`design.craft.signal.proposalThreshold` recurrences; require human review before promotion to the catalog.
|
|
200
|
+
- **When a graph operation fails.** Skip graph integration for that run; emit findings to the report only. Log a warning that `VIOLATES_CRAFT` edges + `CRAFT_SCORE` nodes were not persisted.
|
|
201
|
+
|
|
202
|
+
## Status
|
|
203
|
+
|
|
204
|
+
**v1 — in implementation.** See:
|
|
205
|
+
|
|
206
|
+
- Spec: `docs/changes/design-pipeline/design-craft-elevator/proposal.md`
|
|
207
|
+
- Plan: `docs/changes/design-pipeline/design-craft-elevator/plans/2026-05-23-design-craft-elevator-plan.md`
|
|
208
|
+
- Finding codes: `docs/changes/design-pipeline/design-craft-elevator/finding-codes.md`
|
|
209
|
+
- Contribution guide: `docs/changes/design-pipeline/design-craft-elevator/contribution.md`
|
|
210
|
+
- Growth trajectory: `docs/changes/design-pipeline/design-craft-elevator/growth-trajectory.md`
|
|
211
|
+
- Roadmap entry: `design-pipeline sub-project #6` in `docs/roadmap.md`
|
|
212
|
+
- Prior-art references: `docs/changes/design-pipeline/REFERENCES.md` tier-1 entries #2, #3, #4 (impeccable, emil-design-eng, huashu-design)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: harness-design-craft
|
|
2
|
+
version: "0.1.0"
|
|
3
|
+
description: LLM-judgment-based design ceiling-raiser. CRITIQUE finds what's mediocre, POLISH applies high-craft moves, BENCHMARK scores against curated exemplars. The ceiling counterpart to rule-based audit skills.
|
|
4
|
+
stability: draft
|
|
5
|
+
cognitive_mode: constructive-architect
|
|
6
|
+
triggers:
|
|
7
|
+
- manual
|
|
8
|
+
- on_new_feature
|
|
9
|
+
platforms:
|
|
10
|
+
- claude-code
|
|
11
|
+
tools:
|
|
12
|
+
- Bash
|
|
13
|
+
- Read
|
|
14
|
+
- Write
|
|
15
|
+
- Edit
|
|
16
|
+
- Glob
|
|
17
|
+
- Grep
|
|
18
|
+
cli:
|
|
19
|
+
command: harness skill run harness-design-craft
|
|
20
|
+
args:
|
|
21
|
+
- name: path
|
|
22
|
+
description: Project root path
|
|
23
|
+
required: false
|
|
24
|
+
- name: mode
|
|
25
|
+
description: "fast (code-only LLM critique) or deep (rendered + vision-LLM)"
|
|
26
|
+
required: false
|
|
27
|
+
- name: phases
|
|
28
|
+
description: "Subset of critique,polish,benchmark (comma-separated). Default: all three."
|
|
29
|
+
required: false
|
|
30
|
+
- name: files
|
|
31
|
+
description: Optional glob/path scoping
|
|
32
|
+
required: false
|
|
33
|
+
- name: autoCapture
|
|
34
|
+
description: "B' upgrade behavior: prompt | auto | skip. Default: prompt."
|
|
35
|
+
required: false
|
|
36
|
+
mcp:
|
|
37
|
+
tool: run_skill
|
|
38
|
+
input:
|
|
39
|
+
skill: harness-design-craft
|
|
40
|
+
path: string
|
|
41
|
+
type: flexible
|
|
42
|
+
tier: 2
|
|
43
|
+
phases:
|
|
44
|
+
- name: critique
|
|
45
|
+
description: LLM-judgment finding what is craft-mediocre (3-axis tier/impact/confidence output)
|
|
46
|
+
required: false
|
|
47
|
+
- name: polish
|
|
48
|
+
description: Apply polish patterns with before/after sketches (3-axis output)
|
|
49
|
+
required: false
|
|
50
|
+
- name: benchmark
|
|
51
|
+
description: Score against curated exemplars (5-dim radar output)
|
|
52
|
+
required: false
|
|
53
|
+
state:
|
|
54
|
+
persistent: false
|
|
55
|
+
depends_on:
|
|
56
|
+
- harness-design
|
|
57
|
+
- harness-design-system
|