@hegemonart/get-design-done 1.14.7 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +14 -2
  3. package/CHANGELOG.md +84 -0
  4. package/README.md +18 -0
  5. package/SKILL.md +2 -0
  6. package/agents/a11y-mapper.md +25 -0
  7. package/agents/design-auditor.md +92 -8
  8. package/agents/design-context-builder.md +6 -0
  9. package/agents/design-executor.md +5 -2
  10. package/agents/design-pattern-mapper.md +2 -0
  11. package/agents/design-start-writer.md +221 -0
  12. package/agents/design-verifier.md +11 -0
  13. package/agents/motion-mapper.md +45 -0
  14. package/agents/token-mapper.md +36 -0
  15. package/agents/visual-hierarchy-mapper.md +29 -0
  16. package/hooks/first-run-nudge.sh +82 -0
  17. package/hooks/hooks.json +8 -0
  18. package/package.json +14 -2
  19. package/reference/anti-patterns.md +69 -0
  20. package/reference/audit-scoring.md +34 -3
  21. package/reference/brand-voice.md +199 -0
  22. package/reference/checklists.md +30 -3
  23. package/reference/data/google-fonts.csv +51 -0
  24. package/reference/data/palettes.csv +41 -0
  25. package/reference/data/styles.csv +39 -0
  26. package/reference/design-system-guidance.md +177 -0
  27. package/reference/design-systems-catalog.md +151 -0
  28. package/reference/framer-motion-patterns.md +411 -0
  29. package/reference/gestalt.md +219 -0
  30. package/reference/iconography.md +231 -0
  31. package/reference/motion.md +102 -0
  32. package/reference/palette-catalog.md +82 -0
  33. package/reference/performance.md +304 -0
  34. package/reference/registry.json +257 -27
  35. package/reference/review-format.md +2 -2
  36. package/reference/start-interview.md +84 -0
  37. package/reference/style-vocabulary.md +62 -0
  38. package/reference/surfaces.md +114 -0
  39. package/reference/typography.md +80 -0
  40. package/reference/visual-hierarchy-layout.md +306 -0
  41. package/scripts/lib/detect-ui-root.cjs +187 -0
  42. package/scripts/lib/start-findings-engine.cjs +405 -0
  43. package/skills/start/SKILL.md +166 -0
@@ -0,0 +1,221 @@
1
+ ---
2
+ name: design-start-writer
3
+ description: "Writes .design/START-REPORT.md — 7 fixed sections plus a machine-readable JSON block. Consumes the findings-engine output, interview answers, and detection result from .design/.start-context.json. Never writes STATE.md. Parameter-free: reads the context JSON path from the prompt and emits the report."
4
+ tools: Read, Write, Grep, Glob
5
+ color: green
6
+
7
+ model: haiku
8
+ default-tier: haiku
9
+ tier-rationale: "Formatting + light synthesis over a bounded ~3KB input; Haiku is the correct tier per Phase 10.1 D-14 (Haiku = writers/formatters with fixed schemas)."
10
+
11
+ parallel-safe: always
12
+ typical-duration-seconds: 10
13
+ reads-only: false
14
+ writes:
15
+ - ".design/START-REPORT.md"
16
+
17
+ allowed-read-paths:
18
+ - ".design/.start-context.json"
19
+ - ".design/START-REPORT.md"
20
+ allowed-write-paths:
21
+ - ".design/START-REPORT.md"
22
+ ---
23
+
24
+ ## Role
25
+
26
+ Write `.design/START-REPORT.md` for `/gdd:start`. The report is the single artifact the user sees after a first-run scan. It must feel like GDD understood the project, not like it printed a generic checklist. One best_first_proof, one suggested next command, no ambiguity.
27
+
28
+ ---
29
+
30
+ ## Required Reading
31
+
32
+ - `.design/.start-context.json` — produced by `skills/start/SKILL.md` before spawning this agent. Contains detection result, interview answers, and the findings-engine output.
33
+
34
+ ## Inputs
35
+
36
+ ```json
37
+ {
38
+ "schema_version": "1.0",
39
+ "detected": {
40
+ "kind": "next-app-router | src-components | monorepo-ui-pkg | ...",
41
+ "path": "relative/path/to/components",
42
+ "framework": "next | vite | cra | ...",
43
+ "design_system": "tailwind | css-modules | ...",
44
+ "confidence": 0.85
45
+ },
46
+ "interview": {
47
+ "pain": "free text or empty",
48
+ "target_area": "relative/path",
49
+ "budget": "fast | balanced | thorough",
50
+ "framework_confirmed": true,
51
+ "design_system_confirmed": true,
52
+ "figma_workflow": "figma | canvas | neither | skip"
53
+ },
54
+ "scan": {
55
+ "findings": [{"id":"F1","category":"transition-all","title":"...","file":"...","line":123,"severity":"minor","evidence":"...","visibleDelta":true,"blastRadius":"single-file"}],
56
+ "bestFirstProofId": "F1",
57
+ "partial": false,
58
+ "inspected": {"files": 42, "root": "..."}
59
+ },
60
+ "generated_at": "2026-04-24T01:00:00Z"
61
+ }
62
+ ```
63
+
64
+ ---
65
+
66
+ ## Output contract
67
+
68
+ Write `.design/START-REPORT.md` exactly matching this shape. **All seven H2 sections must be present, in this order, even if empty.** The JSON block at the very end is mandatory.
69
+
70
+ ```markdown
71
+ # GDD First-Run Report
72
+
73
+ > Generated <generated_at> by `/gdd:start`. This report does not start a pipeline cycle — it is a 0→1 proof path. Run the suggested next command to continue.
74
+
75
+ ## What I inspected
76
+
77
+ - **UI root:** `<detected.path>` (`<detected.kind>`, confidence `<detected.confidence>`)
78
+ - **Framework:** `<detected.framework>` — <one-sentence confirmation or override note>
79
+ - **Design system:** `<detected.design_system>` — <one-sentence note>
80
+ - **Files scanned:** `<scan.inspected.files>`
81
+ - **Pain hint:** <`interview.pain` or "none given">
82
+ - **Budget:** `<interview.budget>` <"(timed out — partial scan)" if `scan.partial`>
83
+
84
+ ## Three findings
85
+
86
+ <For each finding F1..F3, emit:>
87
+
88
+ ### <Fn> — <title>
89
+
90
+ **Severity:** `<severity>` · **Evidence:** `<file>:<line>` · **Blast radius:** `<blastRadius>`
91
+
92
+ <one-sentence plain-English rationale pointing at the evidence line>
93
+
94
+ **Fix sketch:** <one-sentence concrete fix — e.g., "Replace `transition` with `transition-transform` on the wrapper.">
95
+
96
+ <End per-finding block>
97
+
98
+ ## Best first proof
99
+
100
+ **Pick:** `<bestFirstProofId>` — <re-state the finding title>
101
+
102
+ <one paragraph: why this one. Cite the rubric condition that tipped the pick — single-file, non-ambiguous, visible delta, no token migration, low blast radius. If `bestFirstProofId` is null, write: "No finding qualified for a single-command fix under the safe-fix rubric — the report recommends the pipeline entry point below instead.">
103
+
104
+ ## Suggested next command
105
+
106
+ ```bash
107
+ <exact command — one of:>
108
+ /gdd:fast "<concrete description of the single fix>"
109
+ /gdd:brief
110
+ /gdd:scan
111
+ ```
112
+
113
+ <one-line rationale: why this command and not the others.>
114
+
115
+ ## Visual Proof Readiness
116
+
117
+ | Surface | Status | Unlock |
118
+ |---------|--------|--------|
119
+ | Preview MCP | <ok \| unconfigured \| unavailable> | <`/gdd:connections preview` or "already configured"> |
120
+ | Storybook | <…> | <…> |
121
+ | Figma | <…> | <`/gdd:connections figma` or "already configured"> |
122
+ | Canvas (.canvas) | <…> | <…> |
123
+
124
+ <one-line note if `interview.figma_workflow` picked a specific surface — nudge toward that one first.>
125
+
126
+ ## Full pipeline path
127
+
128
+ If you want more than a single fix, the full pipeline would do this on this project: `/gdd:brief` to capture the design problem, `/gdd:explore` to inventory your components and interview for context, `/gdd:plan` to decompose the work, `/gdd:design` to execute, and `/gdd:verify` to score the result. The pipeline writes `.design/STATE.md` and runs across a real design cycle.
129
+
130
+ ## Connections / writeback optional
131
+
132
+ If you want to push design decisions back into Figma, paper.design, pencil.dev, or a Claude Design handoff bundle, run `/gdd:connections` to wire up the surfaces. Writeback is never required — the pipeline runs code-first by default.
133
+
134
+ ---
135
+
136
+ ```json
137
+ {
138
+ "schema_version": "1.0",
139
+ "generated_at": "<ISO-8601>",
140
+ "detected": {...copy verbatim from context...},
141
+ "findings": [...copy findings array with id, title, file, line, severity, category, blast_radius...],
142
+ "best_first_proof": "<bestFirstProofId or null>",
143
+ "suggested_command": { "kind": "fast|brief|scan", "text": "<exact command>" },
144
+ "visual_proof_readiness": { "preview": "...", "storybook": "...", "figma": "...", "canvas": "..." }
145
+ }
146
+ ```
147
+ ```
148
+
149
+ ---
150
+
151
+ ## Section-by-section rules
152
+
153
+ ### What I inspected
154
+
155
+ - Always list the six bullets. Mark "(timed out — partial scan)" only when `scan.partial === true`.
156
+ - Never invent fields — only surface what is in the context JSON.
157
+
158
+ ### Three findings
159
+
160
+ - Emit up to three entries. If fewer than three findings exist, emit what exists and add one italic note below: `> Only <N> finding raised — the engine did not hit its cap.`
161
+ - Every finding block includes the evidence file:line. No finding may omit file:line.
162
+ - Fix sketch is one concrete sentence — not a general principle, not a tutorial.
163
+
164
+ ### Best first proof
165
+
166
+ - Reference `bestFirstProofId` exactly. If it is null, write the fallback paragraph.
167
+ - Cite which rubric conditions the winning finding satisfies.
168
+
169
+ ### Suggested next command
170
+
171
+ - If `bestFirstProofId` is non-null → emit `/gdd:fast "<task>"` where `<task>` is a one-line description tied to the finding's fix sketch.
172
+ - If `bestFirstProofId` is null AND there are findings → emit `/gdd:brief` with rationale "the findings need a design decision the rubric cannot make for you."
173
+ - If no findings at all → emit `/gdd:scan` with rationale "this codebase looks healthy at first glance — a full audit confirms."
174
+
175
+ ### Visual Proof Readiness
176
+
177
+ - Always include all four rows. Unknown surfaces default to `unconfigured`.
178
+ - Check `interview.figma_workflow` — if the user picked `figma`, `canvas`, or `neither`, phrase the unlock line to match.
179
+
180
+ ### Full pipeline path
181
+
182
+ - Keep the paragraph short — one sentence of what the pipeline does plus the command sequence. Do not rephrase per run.
183
+
184
+ ### Connections / writeback optional
185
+
186
+ - Keep the paragraph short. Never assert which surface is best; point at `/gdd:connections`.
187
+
188
+ ---
189
+
190
+ ## JSON block
191
+
192
+ The JSON block at the bottom is the contract future `/gdd:fast` / `/gdd:do` invocations will consume. Shape:
193
+
194
+ ```json
195
+ {
196
+ "schema_version": "1.0",
197
+ "generated_at": "ISO-8601",
198
+ "detected": { "root", "kind", "framework", "design_system", "confidence" },
199
+ "findings": [{ "id", "title", "file", "line", "severity", "category", "blast_radius" }],
200
+ "best_first_proof": "F1" | null,
201
+ "suggested_command": { "kind": "fast" | "brief" | "scan", "text": "/gdd:fast \"...\"" },
202
+ "visual_proof_readiness": { "preview", "storybook", "figma", "canvas" }
203
+ }
204
+ ```
205
+
206
+ - Finding IDs stay stable `F1`..`F3`.
207
+ - `text` is always a ready-to-run command, single-line.
208
+ - All string values are JSON-safe — escape embedded quotes.
209
+
210
+ ---
211
+
212
+ ## Do Not
213
+
214
+ - Do not write `.design/STATE.md`, `.design/config.json`, or any source file.
215
+ - Do not invent findings that are not in the context JSON.
216
+ - Do not re-score or re-rank findings — the engine already picked `bestFirstProofId` deterministically.
217
+ - Do not add marketing prose, emojis, or playful copy.
218
+ - Do not emit more than three findings.
219
+ - Do not omit any of the seven H2 sections — even empty, they must exist for downstream regression fixtures.
220
+
221
+ ## START-WRITER COMPLETE
@@ -120,6 +120,11 @@ Anti-Patterns (weight 10%):
120
120
  Motion (weight 5%):
121
121
  Score: [N]/10
122
122
  Evidence: [easing values, reduced-motion presence, duration range]
123
+
124
+ Micro-Polish (qualitative supplement — from DESIGN-AUDIT.md Pillar 7):
125
+ Score: [N]/4 (not weighted into the 0–100 total; reported as supplementary signal)
126
+ Violations flagged: [list BAN/MIFB hits from mapper micro-polish sections]
127
+ Notes: [brief summary — 0 violations = clean; list categories with hits]
123
128
  ```
124
129
 
125
130
  **Weighted total:**
@@ -128,6 +133,8 @@ Score = (Accessibility × 0.25) + (Visual Hierarchy × 0.20) + (Typography × 0.
128
133
  + (Color × 0.15) + (Layout × 0.10) + (Anti-Patterns × 0.10) + (Motion × 0.05)
129
134
  ```
130
135
 
136
+ Note: Micro-Polish is a qualitative supplement (drawn from DESIGN-AUDIT.md Pillar 7) and is reported alongside the weighted total but does not alter the 0–100 score. If Pillar 7 score is 1 or 2 and violations are systemic, flag as a MINOR or MAJOR gap in Phase 5.
137
+
131
138
  **Delta vs baseline:**
132
139
  ```
133
140
  Before: [baseline_score from DESIGN-CONTEXT.md]/100
@@ -149,6 +156,8 @@ Before → After
149
156
  ─────────────────────────────────
150
157
  Total: [baseline]/100 → [new]/100 ([+N] improvement)
151
158
  Grade: [before grade] → [after grade]
159
+ ─────────────────────────────────
160
+ Micro-Polish (suppl.): [N]/4 — [N] violations *(not weighted)*
152
161
  ━━━━━━━━━━━━━━━━━━━━━
153
162
  ```
154
163
 
@@ -383,6 +392,7 @@ If no `.pen` files: skip silently. Print: `pencil.dev spec diff: no .pen files
383
392
 
384
393
  Collect all failures from Phases 1–4:
385
394
  - Phase 1: category scores still below 7 (despite design pass)
395
+ - Phase 1 (micro-polish supplement): Pillar 7 score of 1 or 2 with systemic violations → MINOR or MAJOR gap
386
396
  - Phase 2: `✗ FAIL` must-haves
387
397
  - Phase 3: NNG scores of 0 or 1 on any heuristic
388
398
  - Phase 4: visual UAT `no` responses
@@ -487,6 +497,7 @@ cosmetics: N
487
497
  | Anti-Patterns | [N]/10 | [N]/10 | [±N] | 10% | [N] |
488
498
  | Motion | [N]/10 | [N]/10 | [±N] | 5% | [N] |
489
499
  | **Total** | **[N]/100** | **[N]/100** | **[±N]** | | |
500
+ | Micro-Polish *(suppl.)* | [N]/4 | [N]/4 | [±N] | — | *(not weighted)* |
490
501
 
491
502
  Grade: [before] → [after]
492
503
 
@@ -94,6 +94,51 @@ generated: [ISO 8601]
94
94
  ## Score
95
95
  Reduced-motion compliance: [Full | Partial | None]
96
96
  Motion consistency: [Consistent | Mixed | Chaotic]
97
+
98
+ ## Micro-motion findings
99
+
100
+ After the standard motion inventory, emit a "Micro-motion findings" section with grep-driven hits:
101
+
102
+ ### Patterns to scan for:
103
+
104
+ 1. **transition:all violations**
105
+ - Grep: `transition:\s*all|transition-property:\s*all`
106
+ - Also Tailwind bare: `className="[^"]*\btransition\b[^-]` (transition class without modifier)
107
+ - Report: file:line, the exact declaration, fix pointer → replace with specific properties
108
+
109
+ 2. **will-change:all violations**
110
+ - Grep: `will-change:\s*all`
111
+ - Report: file:line, the declaration, fix pointer → `will-change: transform`
112
+
113
+ 3. **Keyframe-driven interactive elements**
114
+ - Grep: `animation:.*forwards|@keyframes.*\{` on elements that also have `:hover` or `:active` or `onClick`
115
+ - Report: these should use CSS transitions, not keyframe animations
116
+
117
+ 4. **Missing AnimatePresence initial={false}**
118
+ - Grep: `<AnimatePresence(?![^>]*initial=\{false\})` — AnimatePresence without initial={false}
119
+ - Report: file:line; check if the wrapped component is persistent UI (not route-level transitions)
120
+
121
+ 5. **Icon cross-fade with wrong bounce**
122
+ - Grep: `bounce:\s*[^0]` inside framer-motion spring config near icon-related components
123
+ - Report: bounce must be 0 for icon animations; non-zero bounce creates invasive pop effect
124
+
125
+ 6. **scale-on-press outside canonical range**
126
+ - Grep: `scale.*0\.9[578]|scale.*0\.9[0-4]|whileTap.*scale.*0\.9[578]`
127
+ - Report: file:line; canonical press scale is 0.96 — not 0.95, 0.97, 0.98
128
+
129
+ ### Output format for this section:
130
+ ```
131
+ ## Micro-motion findings
132
+
133
+ | Finding | File | Line | Issue | Fix |
134
+ |---------|------|------|-------|-----|
135
+ | transition:all | src/components/Button.tsx | 23 | `transition: all 200ms` | Replace with `transition: background-color 200ms, color 200ms` |
136
+ | ... | ... | ... | ... | ... |
137
+
138
+ Total: N violations found. (0 = clean)
139
+ ```
140
+
141
+ If no violations found, emit: `## Micro-motion findings — CLEAN (0 violations)`
97
142
  ```
98
143
 
99
144
  ## Constraints
@@ -94,6 +94,42 @@ figma_augmented: [true|false]
94
94
 
95
95
  ## Observations
96
96
  - [Dominant color space, typography scale coherence, grid adherence]
97
+
98
+ ## Micro-polish token findings
99
+
100
+ After the standard token inventory, scan and report:
101
+
102
+ 1. **Tinted image outlines**
103
+ - Grep: `outline-(slate|zinc|neutral|gray|stone|blue|red|green|yellow|purple|orange)-\d+` on `<img>` elements
104
+ - Grep CSS: `img\s*\{[^}]*outline:[^}]*#[0-9a-fA-F]{3,8}`
105
+ - Fix: `outline: 1px solid rgba(0,0,0,0.08)` or `rgba(255,255,255,0.08)` only
106
+
107
+ 2. **Shadow tokens drifting from 3-layer formula**
108
+ - Grep for `box-shadow` values that use a single layer or non-rgba values
109
+ - Flag: shadows that don't follow the 3-layer pattern (0 1px 2px / 0 4px 8px / 0 8px 16px)
110
+ - Report as informational (not hard violation) unless the design system has a shadow token system
111
+
112
+ 3. **Missing root-level font-smoothing**
113
+ - Grep: `-webkit-font-smoothing` and `-moz-osx-font-smoothing`
114
+ - If found NOT on `:root` or `body` → flag as per-element misapplication
115
+ - If not found at all → flag as missing root antialiasing
116
+
117
+ 4. **Missing tabular-nums on dynamic numerals**
118
+ - Grep for elements with className containing: `price`, `counter`, `timer`, `count`, `amount`, `balance`, `total`
119
+ - Check if they have `font-variant-numeric: tabular-nums` or Tailwind `tabular-nums` class
120
+ - Report missing instances
121
+
122
+ ### Output format:
123
+ ```
124
+ ## Micro-polish token findings
125
+
126
+ | Finding | File | Line | Issue | Fix |
127
+ |---------|------|------|-------|-----|
128
+ | tinted-outline | ... | ... | `outline-slate-200` on img | Use `outline: 1px solid rgba(0,0,0,0.08)` |
129
+ | missing-tabular-nums | ... | ... | `.price` element lacks tabular-nums | Add `font-variant-numeric: tabular-nums` |
130
+
131
+ Total: N findings. (0 = clean)
132
+ ```
97
133
  ```
98
134
 
99
135
  ## Constraints
@@ -86,6 +86,35 @@ Scale coherence: [Well-defined | Flat | Inverted | Chaotic]
86
86
 
87
87
  ## Score
88
88
  Overall hierarchy health: [Well-defined | Flat | Inverted]
89
+
90
+ ## Micro-polish hierarchy findings
91
+
92
+ After the standard visual hierarchy map, scan and report:
93
+
94
+ 1. **Same border-radius on nested surfaces**
95
+ - Grep (Tailwind): look for identical `rounded-*` class on a container AND its immediate child within a padded block
96
+ - Grep CSS: `border-radius:\s*[0-9]+` appearing on both parent and child in the same component
97
+ - Fix: apply concentric formula `innerRadius = outerRadius − padding`
98
+
99
+ 2. **Headings without text-wrap:balance**
100
+ - Grep: `<h[1-3]` elements or `.heading`, `.title` elements without `text-wrap: balance` or Tailwind `text-balance`
101
+ - Report: file:line; add `text-wrap: balance` to all headings
102
+
103
+ 3. **Missing text-wrap:pretty on body text**
104
+ - Grep: `<p>`, `.body`, `.description`, `.caption` without `text-wrap: pretty` or `text-pretty`
105
+ - This is an informational finding (enhancement, not violation)
106
+
107
+ ### Output format:
108
+ ```
109
+ ## Micro-polish hierarchy findings
110
+
111
+ | Finding | Severity | File | Description | Fix |
112
+ |---------|----------|------|-------------|-----|
113
+ | same-radius-nested | HIGH | ... | Card (rounded-xl) + inner button (rounded-xl) at 16px padding | inner should be rounded-none (16-16=0) |
114
+ | heading-no-balance | MED | ... | h2 missing text-wrap:balance | Add text-balance class |
115
+
116
+ Total: N findings.
117
+ ```
89
118
  ```
90
119
 
91
120
  ## Constraints
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env bash
2
+ # get-design-done — first-run nudge (Phase 14.7)
3
+ # SessionStart hook. Silent-on-failure by policy: exits 0 on every error path.
4
+ # Prints exactly one restrained line pointing at /gdd:start when all gates pass,
5
+ # and nothing otherwise.
6
+
7
+ set -u # intentionally no -e: we want to fall through to exit 0
8
+
9
+ # Silent logger — writes nothing by default. Set GDD_NUDGE_DEBUG=1 to enable stderr.
10
+ log() {
11
+ if [ "${GDD_NUDGE_DEBUG:-0}" = "1" ]; then
12
+ printf '[gdd first-run-nudge] %s\n' "$*" >&2
13
+ fi
14
+ }
15
+
16
+ DESIGN_DIR="$(pwd)/.design"
17
+ STATE="${DESIGN_DIR}/STATE.md"
18
+ CONFIG="${DESIGN_DIR}/config.json"
19
+ DISMISS_FLAG="${HOME:-$USERPROFILE}/.claude/gdd-nudge-dismissed"
20
+
21
+ # Gate 1 — repo already has GDD state, suppress.
22
+ has_design_state() {
23
+ [ -f "${CONFIG}" ] || [ -f "${STATE}" ]
24
+ }
25
+
26
+ # Gate 2 — per-install dismissal flag.
27
+ is_dismissed() {
28
+ [ -f "${DISMISS_FLAG}" ]
29
+ }
30
+
31
+ # Gate 3 — STATE.md stage belongs to an active pipeline window.
32
+ # Inherits the shape used by Phase 13.3 update-check.sh.
33
+ read_state_stage() {
34
+ [ -f "${STATE}" ] || { printf ''; return; }
35
+ grep -E '^stage:' "${STATE}" 2>/dev/null | head -n1 | \
36
+ sed -E 's/^stage:[[:space:]]*"?([^"[:space:]]+)"?.*/\1/'
37
+ }
38
+
39
+ is_active_stage() {
40
+ local s
41
+ s="$(read_state_stage)"
42
+ case "${s}" in
43
+ plan|design|verify|executing|discussing) return 0 ;;
44
+ *) return 1 ;;
45
+ esac
46
+ }
47
+
48
+ # Gate 4 — recent session history has a gdd:* command. We cannot reliably read
49
+ # session history from a hook in all runtimes; when the signal is unavailable,
50
+ # treat it as "unknown → not suppressed". This preserves the nudge's
51
+ # usefulness without creating false suppression.
52
+ has_recent_gdd_command() {
53
+ # Placeholder: no portable transcript path exposed to SessionStart hooks today.
54
+ # Keep the function for future wiring; for now always returns non-zero (unknown).
55
+ return 1
56
+ }
57
+
58
+ # MANDATORY sourcing guard: unit tests source this script to test the helper
59
+ # functions without executing the main flow. Non-negotiable.
60
+ if [ "${BASH_SOURCE[0]}" = "$0" ]; then
61
+ if has_design_state; then
62
+ log "design state present — suppress"
63
+ exit 0
64
+ fi
65
+ if is_dismissed; then
66
+ log "dismissal flag present — suppress"
67
+ exit 0
68
+ fi
69
+ if is_active_stage; then
70
+ log "active stage — suppress"
71
+ exit 0
72
+ fi
73
+ if has_recent_gdd_command; then
74
+ log "recent gdd:* command detected — suppress"
75
+ exit 0
76
+ fi
77
+ # All gates passed — emit the locked one-line nudge.
78
+ printf 'Tip: run /gdd:start to let GDD inspect this codebase and suggest one first fix.\n'
79
+ exit 0
80
+ fi
81
+ # When sourced (BASH_SOURCE != $0), fall through with function definitions loaded
82
+ # and without side effects.
package/hooks/hooks.json CHANGED
@@ -16,6 +16,14 @@
16
16
  "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/update-check.sh\""
17
17
  }
18
18
  ]
19
+ },
20
+ {
21
+ "hooks": [
22
+ {
23
+ "type": "command",
24
+ "command": "bash \"${CLAUDE_PLUGIN_ROOT}/hooks/first-run-nudge.sh\""
25
+ }
26
+ ]
19
27
  }
20
28
  ],
21
29
  "PreToolUse": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hegemonart/get-design-done",
3
- "version": "1.14.7",
3
+ "version": "1.15.0",
4
4
  "description": "A Claude Code plugin for systematic design improvement",
5
5
  "author": "Hegemon",
6
6
  "homepage": "https://github.com/hegemonart/get-design-done",
@@ -54,7 +54,19 @@
54
54
  "self-improvement",
55
55
  "reflection",
56
56
  "tested",
57
- "ci"
57
+ "ci",
58
+ "iconography",
59
+ "brand-voice",
60
+ "performance-budget",
61
+ "framer-motion",
62
+ "motion-design",
63
+ "micro-polish",
64
+ "surfaces",
65
+ "make-interfaces-feel-better",
66
+ "palette-catalog",
67
+ "style-vocabulary",
68
+ "industry-palettes",
69
+ "ui-style-vocabulary"
58
70
  ],
59
71
  "skills": [
60
72
  "SKILL.md"
@@ -334,3 +334,72 @@ grep -rn "bounce\|elastic" src/ --include="*.css"
334
334
  - [ ] Bounce or elastic easing anywhere?
335
335
 
336
336
  If YES to any → rewrite that element before proceeding.
337
+
338
+ ---
339
+
340
+ ### BAN-10: Same Border-Radius on Nested Surfaces
341
+
342
+ Applying the same `border-radius` to a container and an element inside it (when the element is separated by padding) makes the inner element appear to "float" — the radii should be concentric, not equal.
343
+
344
+ **Grep (Tailwind):**
345
+ ```
346
+ (rounded-\w+)[^"]*"[^>]*>\s*<[^>]*\1
347
+ ```
348
+ **Grep (CSS):** Look for identical `border-radius` values in parent and child selectors within the same component.
349
+
350
+ **Fix:** Apply the concentric formula: `innerRadius = outerRadius − padding`. See `reference/surfaces.md`.
351
+
352
+ Source: jakubkrehel/make-interfaces-feel-better (MIT)
353
+
354
+ ---
355
+
356
+ ### BAN-11: Tinted Image Outline
357
+
358
+ Using a colored outline on images (e.g., `outline-slate-200`, `outline-gray-300`, or a hex-value outline color) competes visually with the image content and creates color contamination.
359
+
360
+ **Grep (Tailwind):**
361
+ ```
362
+ outline-(slate|zinc|neutral|gray|stone|blue|red|green|yellow|purple)-\d+
363
+ ```
364
+ applied to `<img>` elements.
365
+
366
+ **Grep (CSS):**
367
+ ```
368
+ img\s*\{[^}]*outline:\s*[^}]*#[0-9a-fA-F]{3,8}
369
+ ```
370
+
371
+ **Fix:** Use `outline: 1px solid rgba(0,0,0,0.08)` (light) or `outline: 1px solid rgba(255,255,255,0.08)` (dark). Pure black or white at low opacity only. See `reference/surfaces.md`.
372
+
373
+ Source: jakubkrehel/make-interfaces-feel-better (MIT)
374
+
375
+ ---
376
+
377
+ ### BAN-12: `transition: all`
378
+
379
+ `transition: all` animates every animatable CSS property on the element, including layout-triggering properties (width, height, padding, margin). This causes layout recalculation on EVERY transition, creating jank and unexpected visual effects (e.g., a hover transition that also animates the element's size if any dimensions change).
380
+
381
+ **Grep (CSS):**
382
+ ```
383
+ transition:\s*all
384
+ transition-property:\s*all
385
+ ```
386
+ **Grep (Tailwind):** bare `\btransition\b` class (without a modifier like `transition-transform` or `transition-[specific-property]`).
387
+
388
+ **Fix:** Specify the exact properties to animate. For hover effects: `transition: background-color 150ms, color 150ms, opacity 150ms`. For motion: `transition: transform 200ms, opacity 200ms`.
389
+
390
+ Source: jakubkrehel/make-interfaces-feel-better (MIT)
391
+
392
+ ---
393
+
394
+ ### BAN-13: `will-change: all`
395
+
396
+ `will-change: all` promotes every animatable property to its own GPU compositor layer, consuming GPU memory for each property. On complex components this can allocate hundreds of MB of texture memory per instance, causing performance degradation and potential crashes on mobile.
397
+
398
+ **Grep:**
399
+ ```
400
+ will-change:\s*all
401
+ ```
402
+
403
+ **Fix:** Restrict to specific compositing-safe properties: `will-change: transform`, `will-change: opacity`, `will-change: filter`, or `will-change: clip-path`. Remove entirely after animation completes. See `reference/motion.md` will-change section.
404
+
405
+ Source: jakubkrehel/make-interfaces-feel-better (MIT)
@@ -124,7 +124,7 @@ Check for:
124
124
  - Content max-width enforced (prose: 65ch, layout: 1200–1440px)
125
125
  - Mobile breakpoint respected (no horizontal scroll)
126
126
 
127
- ### 6. Anti-Pattern Compliance (Weight: 10%)
127
+ ### 6. Anti-Pattern Compliance (Weight: 5%)
128
128
 
129
129
  Score = 10 − (number of hard-ban violations × 3) − (number of AI-slop tells × 1), minimum 0.
130
130
 
@@ -155,8 +155,9 @@ Score = (Accessibility × 0.25)
155
155
  + (Typography × 0.15)
156
156
  + (Color × 0.15)
157
157
  + (Layout × 0.10)
158
- + (Anti-Patterns × 0.10)
158
+ + (Anti-Patterns × 0.05)
159
159
  + (Motion × 0.05)
160
+ + (Micro-polish × 0.05)
160
161
  ```
161
162
 
162
163
  | Grade | Score | Meaning |
@@ -184,8 +185,9 @@ Baseline score: [N/100]
184
185
  | Typography | /10 | 15% | |
185
186
  | Color | /10 | 15% | |
186
187
  | Layout | /10 | 10% | |
187
- | Anti-Patterns | /10 | 10% | |
188
+ | Anti-Patterns | /10 | 5% | |
188
189
  | Motion | /10 | 5% | |
190
+ | Micro-polish | /10 | 5% | |
189
191
  | **Total** | | | **/100** |
190
192
 
191
193
  ### Findings
@@ -203,3 +205,32 @@ Baseline score: [N/100]
203
205
  | ... | | |
204
206
  | **Total** | /40 | **= NNG Score:** /100 |
205
207
  ```
208
+
209
+ ---
210
+
211
+ <!-- BREAKING: Anti-Pattern Compliance pillar weight changed 10%→5% in v1.15.0; Micro-polish pillar added at 5%. Cross-cycle score comparisons should account for this change. -->
212
+
213
+ ### 8. Micro-polish (Weight: 5%)
214
+
215
+ Text-wrap, font-smoothing, tabular-nums, concentric radius, image outlines, hit areas, canonical press scale, will-change discipline.
216
+
217
+ | Score | Criteria |
218
+ |---|---|
219
+ | 10 | All 14 micro-polish checklist items pass |
220
+ | 7–9 | 2–3 violations found |
221
+ | 4–6 | 7 or more violations, core items failing (press scale, transition:all) |
222
+ | 0–3 | Most items fail or not considered |
223
+
224
+ Check for (see `reference/checklists.md` Micro-Polish Check gate):
225
+ - Headings: `text-wrap: balance`; body/captions: `text-wrap: pretty`
226
+ - Font smoothing at `:root` only
227
+ - Dynamic numbers: `font-variant-numeric: tabular-nums`
228
+ - Nested elements: concentric radius (`innerRadius = outerRadius − padding`)
229
+ - Images: `outline: 1px solid rgba(0,0,0,0.08)` — no tinted outlines
230
+ - Interactive elements <40px: `::after` hit-area extension to 40×40
231
+ - Press feedback: `scale(0.96)` exactly
232
+ - `AnimatePresence` on persistent UI: `initial={false}`
233
+ - Icon cross-fade spring: `bounce: 0`
234
+ - No `transition: all` (BAN-12)
235
+ - No `will-change: all` (BAN-13)
236
+ - `prefers-reduced-motion` respected