@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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +54 -0
- package/SKILL.md +10 -4
- package/agents/README.md +53 -0
- package/agents/a11y-mapper.md +10 -0
- package/agents/component-benchmark-harvester.md +11 -0
- package/agents/component-benchmark-synthesizer.md +11 -0
- package/agents/component-taxonomy-mapper.md +10 -0
- package/agents/design-advisor.md +10 -0
- package/agents/design-assumptions-analyzer.md +10 -0
- package/agents/design-auditor.md +22 -0
- package/agents/design-authority-watcher.md +10 -0
- package/agents/design-component-generator.md +10 -0
- package/agents/design-context-checker-gate.md +10 -0
- package/agents/design-context-checker.md +10 -0
- package/agents/design-discussant.md +24 -0
- package/agents/design-doc-writer.md +12 -0
- package/agents/design-executor.md +10 -0
- package/agents/design-figma-writer.md +10 -0
- package/agents/design-fixer.md +10 -0
- package/agents/design-integration-checker-gate.md +10 -0
- package/agents/design-integration-checker.md +10 -0
- package/agents/design-paper-writer.md +10 -0
- package/agents/design-pattern-mapper.md +10 -0
- package/agents/design-pencil-writer.md +10 -0
- package/agents/design-phase-researcher.md +10 -0
- package/agents/design-plan-checker.md +10 -0
- package/agents/design-planner.md +10 -0
- package/agents/design-reflector.md +20 -0
- package/agents/design-research-synthesizer.md +10 -0
- package/agents/design-start-writer.md +10 -0
- package/agents/design-update-checker.md +10 -0
- package/agents/design-verifier-gate.md +10 -0
- package/agents/design-verifier.md +11 -0
- package/agents/gdd-graphify-sync.md +10 -0
- package/agents/gdd-intel-updater.md +10 -0
- package/agents/gdd-learnings-extractor.md +10 -0
- package/agents/motion-mapper.md +10 -0
- package/agents/token-mapper.md +10 -0
- package/agents/visual-hierarchy-mapper.md +10 -0
- package/hooks/gdd-decision-injector.js +30 -8
- package/package.json +18 -2
- package/reference/authority-feeds.md +4 -2
- package/reference/checklists.md +30 -0
- package/reference/component-authoring.md +184 -0
- package/reference/emotional-design.md +124 -0
- package/reference/first-principles.md +89 -0
- package/reference/heuristics.md +70 -0
- package/reference/motion-advanced.md +192 -3
- package/reference/registry.json +28 -0
- package/reference/schemas/insight-line.schema.json +37 -0
- package/reference/shared-preamble.md +10 -0
- package/scripts/lib/design-search.cjs +206 -0
- package/scripts/lib/probe-optional.cjs +29 -0
- package/scripts/lib/relevance-counter.cjs +121 -0
- package/skills/complete-cycle/SKILL.md +40 -2
- package/skills/continue/SKILL.md +23 -0
- package/skills/pause/SKILL.md +40 -14
- package/skills/recall/SKILL.md +74 -0
- package/skills/resume/SKILL.md +34 -16
- package/skills/timeline/SKILL.md +65 -0
package/agents/design-planner.md
CHANGED
|
@@ -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
|
package/agents/motion-mapper.md
CHANGED
|
@@ -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
|
package/agents/token-mapper.md
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
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
|
|
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.
|
|
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-
|
|
8
|
-
**Feed count:**
|
|
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
|
|
package/reference/checklists.md
CHANGED
|
@@ -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.
|