@hegemonart/get-design-done 1.19.0 → 1.19.6

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 (62) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +54 -0
  4. package/SKILL.md +10 -4
  5. package/agents/README.md +53 -0
  6. package/agents/a11y-mapper.md +10 -0
  7. package/agents/component-benchmark-harvester.md +11 -0
  8. package/agents/component-benchmark-synthesizer.md +11 -0
  9. package/agents/component-taxonomy-mapper.md +10 -0
  10. package/agents/design-advisor.md +10 -0
  11. package/agents/design-assumptions-analyzer.md +10 -0
  12. package/agents/design-auditor.md +22 -0
  13. package/agents/design-authority-watcher.md +10 -0
  14. package/agents/design-component-generator.md +10 -0
  15. package/agents/design-context-checker-gate.md +10 -0
  16. package/agents/design-context-checker.md +10 -0
  17. package/agents/design-discussant.md +24 -0
  18. package/agents/design-doc-writer.md +12 -0
  19. package/agents/design-executor.md +10 -0
  20. package/agents/design-figma-writer.md +10 -0
  21. package/agents/design-fixer.md +10 -0
  22. package/agents/design-integration-checker-gate.md +10 -0
  23. package/agents/design-integration-checker.md +10 -0
  24. package/agents/design-paper-writer.md +10 -0
  25. package/agents/design-pattern-mapper.md +10 -0
  26. package/agents/design-pencil-writer.md +10 -0
  27. package/agents/design-phase-researcher.md +10 -0
  28. package/agents/design-plan-checker.md +10 -0
  29. package/agents/design-planner.md +10 -0
  30. package/agents/design-reflector.md +20 -0
  31. package/agents/design-research-synthesizer.md +10 -0
  32. package/agents/design-start-writer.md +10 -0
  33. package/agents/design-update-checker.md +10 -0
  34. package/agents/design-verifier-gate.md +10 -0
  35. package/agents/design-verifier.md +11 -0
  36. package/agents/gdd-graphify-sync.md +10 -0
  37. package/agents/gdd-intel-updater.md +10 -0
  38. package/agents/gdd-learnings-extractor.md +10 -0
  39. package/agents/motion-mapper.md +10 -0
  40. package/agents/token-mapper.md +10 -0
  41. package/agents/visual-hierarchy-mapper.md +10 -0
  42. package/hooks/gdd-decision-injector.js +30 -8
  43. package/package.json +18 -2
  44. package/reference/authority-feeds.md +4 -2
  45. package/reference/checklists.md +30 -0
  46. package/reference/component-authoring.md +184 -0
  47. package/reference/emotional-design.md +124 -0
  48. package/reference/first-principles.md +89 -0
  49. package/reference/heuristics.md +70 -0
  50. package/reference/motion-advanced.md +192 -3
  51. package/reference/registry.json +28 -0
  52. package/reference/schemas/insight-line.schema.json +37 -0
  53. package/reference/shared-preamble.md +10 -0
  54. package/scripts/lib/design-search.cjs +206 -0
  55. package/scripts/lib/probe-optional.cjs +29 -0
  56. package/scripts/lib/relevance-counter.cjs +121 -0
  57. package/skills/complete-cycle/SKILL.md +40 -2
  58. package/skills/continue/SKILL.md +23 -0
  59. package/skills/pause/SKILL.md +40 -14
  60. package/skills/recall/SKILL.md +74 -0
  61. package/skills/resume/SKILL.md +34 -16
  62. package/skills/timeline/SKILL.md +65 -0
@@ -349,4 +349,14 @@ You MUST NOT:
349
349
  @.design/intel/dependencies.json (if present)
350
350
  @.design/intel/graph.json (if present)
351
351
 
352
+ ## Record
353
+
354
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
355
+
356
+ ```json
357
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
358
+ ```
359
+
360
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
361
+
352
362
  ## PLANNING COMPLETE
@@ -51,6 +51,16 @@ Write these sections in order. If source data is missing, write the section head
51
51
 
52
52
  Compare `.design/DESIGN-VERIFICATION.md` gaps to `.design/DESIGN-PLAN.md` acceptance criteria. List decisions that deviated from plan, unexpected cost spikes (agent cost > 2× typical), agents that ran > 3× their `typical-duration-seconds`. One bullet per surprise; cite cycle slug and evidence.
53
53
 
54
+ After listing standard surprises, apply the **Four Principles Checks** from `reference/emotional-design.md` and `reference/first-principles.md`:
55
+
56
+ **Reducibility check** — Did any executed task add elements that fail the reducibility test (body / attention / memory justification absent)? If DESIGN-PLAN.md tasks added >3 visual elements none of which appear in DESIGN-VERIFICATION.md acceptance criteria, flag as "possible decorative accumulation."
57
+
58
+ **Memory-load check** — Does DESIGN-VERIFICATION.md show any H-06 (Recognition > Recall) gap? If yes, flag: "Memory invariant violation — users may need to remember context between screens." Cite the specific gap.
59
+
60
+ **Peak-End check** — Scan DESIGN-PLAN.md and DESIGN-VERIFICATION.md for evidence of a designed peak moment (a completion screen, a celebration, a distinct success state). If none found, flag: "No peak moment designed — reflective-level experience may score low. Consider adding a designed end state."
61
+
62
+ **Error-redemption check** — Scan DESIGN-VERIFICATION.md for H-09 (Error Recovery) score. If score < 3, flag: "Error-redemption gap — error states do not guide users to resolution. This is a behavioral-level failure that also damages the reflective level (users remember bad endings)."
63
+
54
64
  ### 2. Recurring Decisions
55
65
 
56
66
  Scan STATE.md `<decisions>` block for D-XX codes. Cross-reference `.design/learnings/` files from prior cycles if present. Flag decisions that: (a) appeared in multiple sessions of the same cycle, or (b) appear under the same keyword in learnings from ≥2 prior cycles. These are candidates for `reference/` additions.
@@ -172,4 +182,14 @@ Aggregate per agent across cycles:
172
182
  - Proposals are additive — propose additions, not deletions of existing content, unless the evidence is clear (e.g., wrong frontmatter value).
173
183
  - Maximum 20 proposals per reflection file. If more are warranted, batch the lowest-priority ones into a single summary note at the end.
174
184
 
185
+ ## Record
186
+
187
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
188
+
189
+ ```json
190
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
191
+ ```
192
+
193
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
194
+
175
195
  ## REFLECTION COMPLETE
@@ -163,4 +163,14 @@ Read .design/STATE.md
163
163
 
164
164
  Single file: `.design/DESIGN-CONTEXT.md`.
165
165
 
166
+ ## Record
167
+
168
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
169
+
170
+ ```json
171
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
172
+ ```
173
+
174
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
175
+
166
176
  ## SYNTHESIZE COMPLETE
@@ -219,3 +219,13 @@ The JSON block at the bottom is the contract future `/gdd:fast` / `/gdd:do` invo
219
219
  - Do not omit any of the seven H2 sections — even empty, they must exist for downstream regression fixtures.
220
220
 
221
221
  ## START-WRITER COMPLETE
222
+
223
+ ## Record
224
+
225
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
226
+
227
+ ```json
228
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
229
+ ```
230
+
231
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
@@ -115,3 +115,13 @@ Last line of your response MUST be:
115
115
  ```
116
116
 
117
117
  The spawning skill greps for this marker to confirm you finished successfully. Emit it even on the "no cache" fallback path.
118
+
119
+ ## Record
120
+
121
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
122
+
123
+ ```json
124
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
125
+ ```
126
+
127
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
@@ -94,4 +94,14 @@ You MAY:
94
94
 
95
95
  Per 10.1-CONTEXT decision **D-21** (Lazy Checker Spawning): "Cheap Haiku gate agents at `agents/*-gate.md` decide whether to spawn full checker. Gate agent: reads DIFF of changed files, applies heuristic (design-system paths touched? copy strings touched? token files touched?), returns `{spawn: true|false, rationale: '...'}`. If false, skip full checker, log as `lazy_skipped: true` in telemetry." This gate is the verifier-specific instance of that pattern — full `design-verifier` is an XL-size spawn and the most expensive single agent in the pipeline, so gating it behind a cheap Haiku diff-scan yields the largest single cost win in Phase 10.1.
96
96
 
97
+ ## Record
98
+
99
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
100
+
101
+ ```json
102
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
103
+ ```
104
+
105
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
106
+
97
107
  ## GATE COMPLETE
@@ -553,6 +553,17 @@ Emit a 2–4 sentence summary paragraph describing results, then:
553
553
  Emit `## GAPS FOUND` heading, then the full structured gap list (BLOCKER first, MAJOR, MINOR, COSMETIC), then on a new line:
554
554
 
555
555
  ```
556
+
557
+ ## Record
558
+
559
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
560
+
561
+ ```json
562
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
563
+ ```
564
+
565
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
566
+
556
567
  ## VERIFICATION COMPLETE
557
568
  ```
558
569
 
@@ -98,3 +98,13 @@ Graphify status: <status line>
98
98
  @.design/intel/files.json (if present)
99
99
 
100
100
  ## GRAPHIFY-SYNC COMPLETE
101
+
102
+ ## Record
103
+
104
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
105
+
106
+ ```json
107
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
108
+ ```
109
+
110
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
@@ -85,4 +85,14 @@ Generated: <timestamp>
85
85
  A slice is stale if its `generated` timestamp is older than the newest `mtime` in `files.json`.
86
86
  The updater does not need to check this manually — `build-intel.cjs` handles mtime comparison.
87
87
 
88
+ ## Record
89
+
90
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
91
+
92
+ ```json
93
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
94
+ ```
95
+
96
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
97
+
88
98
  ## INTEL UPDATE COMPLETE
@@ -82,4 +82,14 @@ For each learning with `Proposed reference update: yes`:
82
82
  @.design/intel/patterns.json (if present)
83
83
  @.design/learnings/LEARNINGS.md (if present)
84
84
 
85
+ ## Record
86
+
87
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
88
+
89
+ ```json
90
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
91
+ ```
92
+
93
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
94
+
85
95
  ## LEARNINGS EXTRACTION COMPLETE
@@ -210,4 +210,14 @@ If no violations found, emit: `## Micro-motion findings — CLEAN (0 violations)
210
210
 
211
211
  No modifications outside `.design/map/`. No git. No agent spawning.
212
212
 
213
+ ## Record
214
+
215
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
216
+
217
+ ```json
218
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
219
+ ```
220
+
221
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
222
+
213
223
  ## MOTION MAP COMPLETE
@@ -144,4 +144,14 @@ Total: N findings. (0 = clean)
144
144
 
145
145
  You MUST NOT modify anything outside `.design/map/`. Do not run git commands or spawn agents.
146
146
 
147
+ ## Record
148
+
149
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
150
+
151
+ ```json
152
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
153
+ ```
154
+
155
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
156
+
147
157
  ## TOKEN MAP COMPLETE
@@ -121,4 +121,14 @@ Total: N findings.
121
121
 
122
122
  No modifications outside `.design/map/`. No git. No agent spawning.
123
123
 
124
+ ## Record
125
+
126
+ At run-end, append one JSONL line to `.design/intel/insights.jsonl`:
127
+
128
+ ```json
129
+ {"ts":"<ISO-8601>","agent":"<name>","cycle":"<cycle from STATE.md>","stage":"<stage from STATE.md>","one_line_insight":"<what was produced or learned>","artifacts_written":["<files written>"]}
130
+ ```
131
+
132
+ Schema: `reference/schemas/insight-line.schema.json`. Use an empty `artifacts_written` array for read-only agents.
133
+
124
134
  ## VISUAL HIERARCHY MAP COMPLETE
@@ -25,6 +25,14 @@ const MIN_BYTES = 1500;
25
25
  const TOP_N = 15;
26
26
  const MATCHER_RE = /[\\/](?:\.design|reference|\.planning)[\\/][^\n]*\.md$/;
27
27
 
28
+ // Phase 19.5: try FTS5 backend first; fall back to grep silently.
29
+ let _designSearch = null;
30
+ try {
31
+ _designSearch = require(path.join(__dirname, '..', 'scripts', 'lib', 'design-search.cjs'));
32
+ } catch { /* not available in this install */ }
33
+
34
+ const BACKEND = _designSearch ? _designSearch.backendName() : null;
35
+
28
36
  function ripgrepAvailable() {
29
37
  try {
30
38
  const r = spawnSync('rg', ['--version'], { encoding: 'utf8', windowsHide: true });
@@ -103,7 +111,7 @@ function sortKeyFor(tag) {
103
111
  return 0;
104
112
  }
105
113
 
106
- function buildRecallBlock(matches, basename) {
114
+ function buildRecallBlock(matches, basename, backendLabel) {
107
115
  if (!matches.length) return null;
108
116
  const uniq = [];
109
117
  const seen = new Set();
@@ -125,10 +133,11 @@ function buildRecallBlock(matches, basename) {
125
133
  const excerpt = m.text.length > 140 ? m.text.slice(0, 137) + '…' : m.text;
126
134
  lines.push(`> - [${tag}] ${excerpt} (${path.relative(process.cwd(), m.file)}:${m.line})`);
127
135
  }
136
+ // backendLabel passed in from main()
128
137
  if (uniq.length > TOP_N) {
129
- lines.push(`> … (${uniq.length - TOP_N} more matches; use \`/gdd:recall <term>\` to expand. Grep backend; FTS5 upgrade in Phase 19.5.)`);
138
+ lines.push(`> … (${uniq.length - TOP_N} more matches; use \`/gdd:recall <term>\` to expand. Backend: ${backendLabel}.)`);
130
139
  } else {
131
- lines.push(`> (${uniq.length} match${uniq.length === 1 ? '' : 'es'} surfaced. Grep backend; FTS5 upgrade in Phase 19.5.)`);
140
+ lines.push(`> (${uniq.length} match${uniq.length === 1 ? '' : 'es'} surfaced. Backend: ${backendLabel}.)`);
132
141
  }
133
142
  lines.push('');
134
143
  return lines.join('\n');
@@ -173,13 +182,26 @@ async function main() {
173
182
  return;
174
183
  }
175
184
 
176
- const useRg = ripgrepAvailable();
177
- const hits = [];
178
- for (const src of sources) {
179
- hits.push(...(useRg ? grepLinesRg(src, terms) : grepLinesNode(src, terms)));
185
+ const useRgGlobal = ripgrepAvailable();
186
+ let hits = [];
187
+ if (BACKEND === 'fts5' && _designSearch) {
188
+ // FTS5 path: single query across all indexed docs
189
+ try {
190
+ const query = terms.join(' OR ');
191
+ hits = _designSearch.search(query, cwd, { limit: TOP_N * 3 });
192
+ } catch { hits = []; }
193
+ if (!hits.length) {
194
+ // FTS5 db may be stale — rebuild silently then retry
195
+ try { _designSearch.reindex(cwd); hits = _designSearch.search(terms.join(' OR '), cwd, { limit: TOP_N * 3 }); } catch { hits = []; }
196
+ }
197
+ } else {
198
+ for (const src of sources) {
199
+ hits.push(...(useRgGlobal ? grepLinesRg(src, terms) : grepLinesNode(src, terms)));
200
+ }
180
201
  }
181
202
 
182
- const block = buildRecallBlock(hits, basename);
203
+ const backendLabel = BACKEND || (useRgGlobal ? 'ripgrep' : 'node-grep');
204
+ const block = buildRecallBlock(hits, basename, backendLabel);
183
205
  if (!block) {
184
206
  process.stdout.write(JSON.stringify({ continue: true }));
185
207
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hegemonart/get-design-done",
3
- "version": "1.19.0",
3
+ "version": "1.19.6",
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",
@@ -82,7 +82,23 @@
82
82
  "information-architecture",
83
83
  "form-patterns",
84
84
  "data-viz",
85
- "platforms"
85
+ "platforms",
86
+ "cross-cycle-memory",
87
+ "fts5",
88
+ "checkpoints",
89
+ "experience-archive",
90
+ "recall",
91
+ "relevance-counter",
92
+ "record-contract",
93
+ "first-principles",
94
+ "emotional-design",
95
+ "component-authoring",
96
+ "disney-12-principles",
97
+ "peak-end-rule",
98
+ "loss-aversion",
99
+ "cognitive-load",
100
+ "doherty-threshold",
101
+ "rams-lens"
86
102
  ],
87
103
  "skills": [
88
104
  "SKILL.md"
@@ -4,8 +4,8 @@
4
4
  >
5
5
  > **Anti-slop thesis:** No Dribbble. No Behance. No LinkedIn. No generic trending aggregators. See `.planning/PROJECT.md` and `.planning/phases/13.2-external-authority-watcher/13.2-CONTEXT.md` §D-08.
6
6
 
7
- **Last reviewed:** 2026-04-19
8
- **Feed count:** 26 (updated each time a feed is added or removed)
7
+ **Last reviewed:** 2026-04-24
8
+ **Feed count:** 28 (updated each time a feed is added or removed)
9
9
 
10
10
  ---
11
11
 
@@ -46,6 +46,8 @@
46
46
  - **[Scott Jehl](https://scottjehl.com/)** — `kind: named-practitioner` · `url: https://scottjehl.com/feed/` · `cadence-hint: monthly` · *Progressive enhancement and web performance; long-form durable analysis.*
47
47
  - **[Heydon Pickering](https://heydonworks.com/)** — `kind: named-practitioner` · `url: https://heydonworks.com/feed.xml` · `cadence-hint: irregular` · *Accessibility-first component design; Inclusive Components author.*
48
48
  - **[Una Kravets](https://una.im/)** — `kind: named-practitioner` · `url: https://una.im/feed.xml` · `cadence-hint: monthly` · *Chrome DevRel on CSS; surfaces and explains new platform capabilities.*
49
+ - **[Don Norman — jnd.org](https://jnd.org/)** — `kind: named-practitioner` · `url: https://jnd.org/feed/` · `cadence-hint: monthly` · *Don Norman's essays on emotional design, affordances, cognitive design, and human-centered AI. Primary source for `reference/emotional-design.md`.*
50
+ - **[Vitsœ — Dieter Rams](https://www.vitsoe.com/gb/about/good-design)** — `kind: named-practitioner` · `url: https://www.vitsoe.com/feed` · `cadence-hint: irregular` · *Canonical source for Rams's 10 Principles of Good Design. Published by Vitsœ, who worked directly with Rams at Braun. Primary source for the Rams Lens in `reference/checklists.md`.*
49
51
 
50
52
  ## User-added Are.na channels (user-extensible)
51
53
 
@@ -162,3 +162,33 @@ Use this checklist after the main design review for pixel-level craft verificati
162
162
  - [ ] No `transition: all` anywhere (see BAN-12 transition-all)
163
163
  - [ ] No `will-change: all` anywhere (see BAN-13 will-change-all)
164
164
  - [ ] `prefers-reduced-motion` respected via `MotionConfig` or `useReducedMotion()`
165
+
166
+ ---
167
+
168
+ ## Rams Lens — 10 Design Questions
169
+
170
+ Dieter Rams's 10 principles of good design (Vitsœ/Braun, 1970s–80s) applied as a self-audit lens. Each question maps to one principle.
171
+
172
+ - [ ] **Innovative** — Does this design solve the problem in a way that was not possible or obvious before?
173
+ - [ ] **Useful** — Does every element serve the primary function? Nothing decorative that doesn't earn its place?
174
+ - [ ] **Aesthetic** — Is the visual appearance the minimum necessary for legibility and emotional resonance?
175
+ - [ ] **Understandable** — Can the user figure out how to use this without reading documentation or a tooltip?
176
+ - [ ] **Unobtrusive** — Does the design stay in the background and let the content or task take focus?
177
+ - [ ] **Honest** — Does the design not imply capabilities, quality, or status that the product doesn't have?
178
+ - [ ] **Long-lasting** — Is this design free of trend-dependent choices (gradients, micro-styles) that will age in 12 months?
179
+ - [ ] **Thorough** — Have edge cases been considered and handled (empty states, error states, loading states, overflow text)?
180
+ - [ ] **Environmentally friendly** — Is the performance footprint minimal? (image sizes, JS bundle, font weight)
181
+ - [ ] **As little design as possible** — If you removed 20% of the design decisions, would the product be worse? If not, remove them.
182
+
183
+ ---
184
+
185
+ ## Sonner / Component-Authoring Lens — 6 Questions
186
+
187
+ Emil Kowalski's component-authoring principles applied as a per-component self-audit. Full reference: `reference/component-authoring.md`.
188
+
189
+ - [ ] **P-01 API surface** — Does this component work correctly in 1 line with zero configuration?
190
+ - [ ] **P-02 Composability** — Does this component compose via slots/children, not via style-configuration props?
191
+ - [ ] **P-03 Defaults** — Are the defaults so sensible that most consumers never need to pass any props?
192
+ - [ ] **P-04 Animation** — Does every animation in this component communicate a state change? No decorative loops?
193
+ - [ ] **P-05 Accessibility** — Does this component have a complete ARIA contract before any visual styling?
194
+ - [ ] **P-06 Edge honesty** — Are known failure modes documented with `// KNOWN:` or `// EDGE:` comments?
@@ -0,0 +1,184 @@
1
+ # Component Authoring Principles
2
+
3
+ Source: Emil Kowalski's work on Sonner, Vaul, and cmdk — synthesised from his published writing and talks. See also: `reference/framer-motion-patterns.md`, `reference/motion-advanced.md`.
4
+
5
+ Use this file when authoring, reviewing, or auditing UI components. The 6 principles apply as a lens during code review and design verification. Each principle has a grep-able audit signal.
6
+
7
+ ---
8
+
9
+ ## The 6 Principles
10
+
11
+ ### P-01: Minimal API Surface
12
+
13
+ > Expose only what the consumer needs. Every prop is a contract you must maintain forever.
14
+
15
+ A component with the right API surface works in 1 line for 80% of cases and 3 lines for 95% of cases. A component that requires 7 props for basic usage has too much surface.
16
+
17
+ **Audit signal:**
18
+ ```bash
19
+ # Count required (non-optional) props in a component interface
20
+ grep -E "^\s+\w+: " src/components/Button.tsx | grep -v "?" | wc -l
21
+ ```
22
+
23
+ **Thresholds:**
24
+ - ≤5 props total: excellent
25
+ - 6–9 props total: acceptable if logically grouped
26
+ - ≥10 props: flag for decomposition
27
+
28
+ **Pattern — variant over prop explosion:**
29
+ ```tsx
30
+ // BAD — prop explosion
31
+ <Button color="blue" size="md" rounded={true} shadow={true} uppercase={false} />
32
+
33
+ // GOOD — variant collapses 5 props to 1
34
+ <Button variant="primary" size="md" />
35
+ ```
36
+
37
+ ---
38
+
39
+ ### P-02: Composability Over Configuration
40
+
41
+ > Components should compose, not configure. Accepting `backgroundColor` or `textColor` is a sign the abstraction boundary is wrong.
42
+
43
+ The right abstraction lets consumers build what they need by combining small pieces, not by passing increasingly specific configuration. Slot-based APIs > configuration-object APIs.
44
+
45
+ **Audit signal:**
46
+ ```bash
47
+ # Configuration props that should be design tokens instead
48
+ grep -rE "(backgroundColor|textColor|borderRadius|fontSize)=" src/components/ --include="*.tsx"
49
+ ```
50
+
51
+ **Pattern — slot composition:**
52
+ ```tsx
53
+ // BAD — too much configuration
54
+ <Card title="Hello" subtitle="World" icon="user" rightContent={<Badge />} />
55
+
56
+ // GOOD — slot composition; parent controls layout
57
+ <Card>
58
+ <Card.Header>
59
+ <Card.Icon><UserIcon /></Card.Icon>
60
+ <Card.Title>Hello</Card.Title>
61
+ <Card.Subtitle>World</Card.Subtitle>
62
+ <Badge />
63
+ </Card.Header>
64
+ </Card>
65
+ ```
66
+
67
+ ---
68
+
69
+ ### P-03: Sensible Defaults
70
+
71
+ > The zero-config case should work and look correct. Options are for exceptions.
72
+
73
+ A component with sensible defaults doesn't require the consumer to know its internals. The defaults encode the design system's opinion about what "normal" looks like.
74
+
75
+ **Audit signal:**
76
+ ```bash
77
+ # Props with no default values (every prop is required = red flag)
78
+ grep -E "^\s+\w+: " src/components/Toast.tsx | grep -v "?" | wc -l
79
+ ```
80
+
81
+ **The Sonner model:** `<Toaster />` with zero props renders a toast system that follows the OS color scheme, positions correctly on all viewports, stacks properly, and auto-dismisses at a sensible duration. All options exist — but the zero-prop case works.
82
+
83
+ **Anti-pattern:** Required props for things with a logical default (e.g., `position` on a modal that should always default to `center`).
84
+
85
+ ---
86
+
87
+ ### P-04: Animation as State Communication
88
+
89
+ > Transitions communicate state change. They are not decoration. An animation that fires without a state change is noise.
90
+
91
+ Every motion in a component should answer: "What did the system just do?" If the animation doesn't have a clear answer, remove it.
92
+
93
+ **Audit signal:**
94
+ ```bash
95
+ # Animations not tied to state change (decorative loops = red flag)
96
+ grep -rE "animate.*loop|animation.*infinite|keyframes.*repeat" src/components/ --include="*.tsx"
97
+ ```
98
+
99
+ **The Sonner model:**
100
+ - Toast enters → communicates: "event occurred"
101
+ - Toast stacks → communicates: "multiple events queued"
102
+ - Toast exits → communicates: "event acknowledged or expired"
103
+ - No animation fires without a state change triggering it
104
+
105
+ **Thresholds:**
106
+ - All animations tied to state: excellent
107
+ - ≤1 decorative animation (e.g., a loading shimmer): acceptable
108
+ - ≥2 decorative animations: flag for review
109
+
110
+ See `reference/motion-advanced.md` for implementation patterns.
111
+
112
+ ---
113
+
114
+ ### P-05: Accessibility Before Visuals
115
+
116
+ > If a component isn't accessible by keyboard and screen reader, it isn't done. Accessibility is not a post-processing step.
117
+
118
+ Build the ARIA contract before the visual. The visual is a rendering of the semantic layer, not the other way around.
119
+
120
+ **Audit signal:**
121
+ ```bash
122
+ # Interactive divs/spans without ARIA role (missing semantic contract)
123
+ grep -rE "<(div|span)[^>]*onClick" src/components/ --include="*.tsx" | grep -v "role="
124
+ ```
125
+
126
+ **Required ARIA contracts by component type:**
127
+
128
+ | Component | Required attributes |
129
+ |---|---|
130
+ | Dialog / Modal | `role="dialog"`, `aria-modal="true"`, `aria-labelledby` |
131
+ | Combobox / Select | `role="combobox"`, `aria-expanded`, `aria-controls` |
132
+ | Menu | `role="menu"`, `role="menuitem"`, keyboard trap |
133
+ | Toast / Alert | `role="status"` (polite) or `role="alert"` (assertive) |
134
+ | Toggle / Switch | `role="switch"`, `aria-checked` |
135
+ | Tabs | `role="tablist"`, `role="tab"`, `role="tabpanel"`, `aria-selected` |
136
+ | Tooltip | `role="tooltip"`, `aria-describedby` on trigger |
137
+
138
+ ---
139
+
140
+ ### P-06: Edge Case Honesty
141
+
142
+ > Document the cases where the component fails. If you know it breaks with strings longer than 30 characters, say so.
143
+
144
+ Undocumented edge cases become production bugs. A component spec that acknowledges failure modes is more trustworthy than one that claims universal correctness.
145
+
146
+ **Audit signal:**
147
+ ```bash
148
+ # Look for documented edge cases
149
+ grep -rE "// KNOWN:|// EDGE:|// LIMIT:" src/components/ --include="*.tsx"
150
+ ```
151
+
152
+ **Template for component edge case documentation:**
153
+ ```tsx
154
+ // KNOWN: Toast title truncates at ~80 chars on 320px viewport; use short titles
155
+ // KNOWN: Stacking > 5 toasts simultaneously is unsupported; excess toasts are queued
156
+ // EDGE: If `duration` is set to Infinity, a visible dismiss button is required
157
+ ```
158
+
159
+ The presence of these comments is a quality signal, not a code smell. It means the author thought about the boundary conditions.
160
+
161
+ ---
162
+
163
+ ## Lens Application in Audits
164
+
165
+ When auditing a component, apply these six principles as a checklist:
166
+
167
+ | Principle | Pass condition | Fail condition |
168
+ |---|---|---|
169
+ | P-01 Minimal API | ≤9 props; zero-config case works | ≥10 props; required props for things with defaults |
170
+ | P-02 Composability | Slot-based composition; no style props | `backgroundColor`/`textColor` props present |
171
+ | P-03 Defaults | Zero-prop case renders correctly | Most props required for basic usage |
172
+ | P-04 Animation | All motion tied to state change | Decorative loops or orphaned animations present |
173
+ | P-05 Accessibility | ARIA contract complete; keyboard navigable | `onClick` on `div`; missing `role`; no keyboard trap |
174
+ | P-06 Edge honesty | Known limits documented with `// KNOWN:` | No documentation of failure modes |
175
+
176
+ ---
177
+
178
+ ## Wiring
179
+
180
+ **design-auditor:** Apply as an optional sub-check within Pillar 7 (Micro-Polish) for component-heavy UIs. Cite principle ID (P-01 through P-06) in findings.
181
+
182
+ **design-discussant:** In `--spec` mode, ask one component-authoring question per component under review: "For [ComponentName]: does the API surface expose only what consumers need, or are there configuration props that reveal implementation details?"
183
+
184
+ **design-verifier:** When verifying component-library phases, include P-01 through P-06 in the must-have checklist as a component quality gate.