@hegemonart/get-design-done 1.28.0 → 1.28.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 +134 -0
- package/SKILL.md +1 -1
- package/hooks/gdd-decision-injector.js +149 -3
- package/package.json +1 -1
- package/reference/adr-format.md +96 -0
- package/reference/architecture-vocabulary.md +102 -0
- package/reference/context-md-format.md +106 -0
- package/reference/heuristics.md +84 -0
- package/reference/registry.json +29 -1
- package/reference/registry.schema.json +1 -1
- package/reference/shared-preamble.md +78 -6
- package/reference/skill-authoring-contract.md +159 -0
- package/scripts/validate-skill-length.cjs +283 -0
- package/skills/add-backlog/SKILL.md +1 -0
- package/skills/analyze-dependencies/SKILL.md +33 -122
- package/skills/apply-reflections/SKILL.md +1 -40
- package/skills/apply-reflections/apply-reflections-procedure.md +68 -0
- package/skills/audit/SKILL.md +3 -1
- package/skills/bandit-status/SKILL.md +31 -66
- package/skills/benchmark/SKILL.md +15 -55
- package/skills/brief/SKILL.md +12 -1
- package/skills/cache-manager/SKILL.md +3 -57
- package/skills/cache-manager/cache-policy.md +126 -0
- package/skills/check-update/SKILL.md +38 -75
- package/skills/compare/SKILL.md +29 -269
- package/skills/compare/compare-rubric.md +171 -0
- package/skills/complete-cycle/SKILL.md +1 -1
- package/skills/connections/SKILL.md +21 -427
- package/skills/connections/connections-onboarding.md +417 -0
- package/skills/continue/SKILL.md +1 -0
- package/skills/darkmode/SKILL.md +32 -287
- package/skills/darkmode/darkmode-audit-procedure.md +258 -0
- package/skills/debug/SKILL.md +11 -8
- package/skills/debug/debug-feedback-loops.md +119 -0
- package/skills/design/SKILL.md +27 -245
- package/skills/design/design-procedure.md +304 -0
- package/skills/discover/SKILL.md +26 -133
- package/skills/discover/discover-procedure.md +204 -0
- package/skills/discuss/SKILL.md +18 -2
- package/skills/explore/SKILL.md +40 -205
- package/skills/explore/explore-procedure.md +267 -0
- package/skills/fast/SKILL.md +1 -0
- package/skills/figma-write/SKILL.md +2 -2
- package/skills/health/SKILL.md +11 -33
- package/skills/health/health-mcp-detection.md +44 -0
- package/skills/health/health-skill-length-report.md +69 -0
- package/skills/help/SKILL.md +1 -0
- package/skills/list-assumptions/SKILL.md +1 -0
- package/skills/map/SKILL.md +8 -31
- package/skills/new-cycle/SKILL.md +3 -1
- package/skills/new-cycle/milestone-completeness-rubric.md +87 -0
- package/skills/next/SKILL.md +1 -0
- package/skills/note/SKILL.md +1 -0
- package/skills/optimize/SKILL.md +21 -44
- package/skills/pause/SKILL.md +1 -0
- package/skills/peer-cli-add/SKILL.md +26 -108
- package/skills/peer-cli-add/peer-cli-protocol.md +161 -0
- package/skills/peer-cli-customize/SKILL.md +22 -42
- package/skills/peers/SKILL.md +33 -57
- package/skills/plan/SKILL.md +33 -220
- package/skills/plan/plan-procedure.md +278 -0
- package/skills/plant-seed/SKILL.md +1 -0
- package/skills/pr-branch/SKILL.md +1 -0
- package/skills/progress/SKILL.md +1 -7
- package/skills/quality-gate/SKILL.md +34 -166
- package/skills/quality-gate/threat-modeling.md +101 -0
- package/skills/quick/SKILL.md +1 -0
- package/skills/reapply-patches/SKILL.md +1 -0
- package/skills/recall/SKILL.md +1 -0
- package/skills/resume/SKILL.md +1 -0
- package/skills/review-backlog/SKILL.md +1 -0
- package/skills/router/SKILL.md +3 -59
- package/skills/router/router-rules.md +84 -0
- package/skills/scan/SKILL.md +36 -675
- package/skills/scan/scan-procedure.md +731 -0
- package/skills/settings/SKILL.md +1 -0
- package/skills/ship/SKILL.md +1 -0
- package/skills/sketch/SKILL.md +1 -1
- package/skills/sketch-wrap-up/SKILL.md +13 -54
- package/skills/spike/SKILL.md +1 -1
- package/skills/spike-wrap-up/SKILL.md +12 -46
- package/skills/start/SKILL.md +13 -112
- package/skills/start/start-procedure.md +115 -0
- package/skills/stats/SKILL.md +1 -0
- package/skills/style/SKILL.md +18 -140
- package/skills/style/style-doc-procedure.md +150 -0
- package/skills/synthesize/SKILL.md +1 -0
- package/skills/timeline/SKILL.md +1 -0
- package/skills/todo/SKILL.md +1 -0
- package/skills/turn-closeout/SKILL.md +36 -56
- package/skills/undo/SKILL.md +1 -0
- package/skills/update/SKILL.md +1 -0
- package/skills/verify/SKILL.md +42 -457
- package/skills/verify/verify-procedure.md +512 -0
- package/skills/warm-cache/SKILL.md +3 -35
- package/skills/zoom-out/SKILL.md +26 -0
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
/**
|
|
4
|
+
* scripts/validate-skill-length.cjs — Phase 28.5 skill-authoring-contract validator.
|
|
5
|
+
*
|
|
6
|
+
* Walks skills/, validates per D-01/D-02/D-09/D-11:
|
|
7
|
+
* - Frontmatter required: name, description
|
|
8
|
+
* - description length: 20 <= len <= 1024 chars (always strict)
|
|
9
|
+
* - description format (--strict-description / STRICT_DESCRIPTION=1):
|
|
10
|
+
* regex `\. Use when .+\.$` (advisory by default per D-02)
|
|
11
|
+
* - SKILL.md lines: >=250 block, >=100 warn (D-01)
|
|
12
|
+
* - disable-model-invocation: only on D-09 whitelist
|
|
13
|
+
*
|
|
14
|
+
* Exit codes:
|
|
15
|
+
* 0 clean (no warnings, no blockers)
|
|
16
|
+
* 1 warnings only (>=100 lines but <250 on at least one skill, no other failures)
|
|
17
|
+
* 2 blockers present (>=250 lines, frontmatter missing/invalid, description out of range, etc.)
|
|
18
|
+
*
|
|
19
|
+
* CLI flags:
|
|
20
|
+
* --quiet Suppress per-skill output, print summary only.
|
|
21
|
+
* --strict-description Enforce `<what>. Use when <triggers>.` regex on description.
|
|
22
|
+
* --json Emit machine-readable JSON instead of human-readable text.
|
|
23
|
+
* --help, -h Print this usage message.
|
|
24
|
+
*
|
|
25
|
+
* Env:
|
|
26
|
+
* STRICT_DESCRIPTION=1 Equivalent to --strict-description.
|
|
27
|
+
* SKILLS_DIR=<path> Override skills directory (default: ./skills relative to cwd).
|
|
28
|
+
*
|
|
29
|
+
* See reference/skill-authoring-contract.md for the full contract.
|
|
30
|
+
*
|
|
31
|
+
* Line counting: counts every line in the file via split on /\r?\n/ and drops a single
|
|
32
|
+
* trailing empty entry — matches `wc -l` semantics. We count ALL lines (including blanks
|
|
33
|
+
* and comments) because that is what consumes agent context. This mirrors the same
|
|
34
|
+
* counting convention used by tests/agent-size-budget.test.cjs.
|
|
35
|
+
*
|
|
36
|
+
* Validator does NOT enforce skill renames (D-05/D-07) — frontmatter.name is checked for
|
|
37
|
+
* presence only, never compared against a canonical-name list. Whitelist key for
|
|
38
|
+
* disable-model-invocation uses the skill folder name (skills/<dir>/SKILL.md), not the
|
|
39
|
+
* frontmatter.name field.
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
const fs = require('fs');
|
|
43
|
+
const path = require('path');
|
|
44
|
+
|
|
45
|
+
const WARN_LINES = 100;
|
|
46
|
+
const BLOCK_LINES = 250;
|
|
47
|
+
const DESC_MIN = 20;
|
|
48
|
+
const DESC_MAX = 1024;
|
|
49
|
+
// Strict-mode regex: trailing ". Use when <something>." sentence.
|
|
50
|
+
// Multiline + non-greedy to tolerate descriptions split across YAML lines.
|
|
51
|
+
const STRICT_RE = /\. Use when .+\.\s*$/m;
|
|
52
|
+
|
|
53
|
+
// D-09 whitelist — skills permitted to set disable-model-invocation: true.
|
|
54
|
+
// Keyed on skill folder name (skills/<folder>/SKILL.md), not frontmatter.name.
|
|
55
|
+
const DISABLE_INVOCATION_WHITELIST = new Set([
|
|
56
|
+
'help', 'stats', 'note', 'add-backlog', 'todo', 'health', 'settings',
|
|
57
|
+
'next', 'pause', 'resume', 'fast', 'quick', 'pr-branch', 'ship',
|
|
58
|
+
'reapply-patches', 'list-assumptions', 'plant-seed', 'review-backlog',
|
|
59
|
+
'cache-manager', 'warm-cache', 'synthesize', 'timeline', 'start',
|
|
60
|
+
'recall', 'continue', 'update', 'undo', 'zoom-out',
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
function parseArgs(argv) {
|
|
64
|
+
const flags = { quiet: false, strict: false, json: false };
|
|
65
|
+
for (const a of argv.slice(2)) {
|
|
66
|
+
if (a === '--quiet') flags.quiet = true;
|
|
67
|
+
else if (a === '--strict-description') flags.strict = true;
|
|
68
|
+
else if (a === '--json') flags.json = true;
|
|
69
|
+
else if (a === '--help' || a === '-h') { printHelp(); process.exit(0); }
|
|
70
|
+
else { process.stderr.write(`unknown flag: ${a}\n`); process.exit(2); }
|
|
71
|
+
}
|
|
72
|
+
if (process.env.STRICT_DESCRIPTION === '1') flags.strict = true;
|
|
73
|
+
return flags;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function printHelp() {
|
|
77
|
+
process.stdout.write([
|
|
78
|
+
'validate-skill-length.cjs — Phase 28.5 skill-authoring-contract validator',
|
|
79
|
+
'',
|
|
80
|
+
'Usage: node scripts/validate-skill-length.cjs [--quiet] [--strict-description] [--json]',
|
|
81
|
+
'',
|
|
82
|
+
'Flags:',
|
|
83
|
+
' --quiet Suppress per-skill output, print summary only.',
|
|
84
|
+
' --strict-description Enforce `<what>. Use when <triggers>.` regex on description.',
|
|
85
|
+
' --json Emit machine-readable JSON.',
|
|
86
|
+
' --help, -h Show this message.',
|
|
87
|
+
'',
|
|
88
|
+
'Env:',
|
|
89
|
+
' STRICT_DESCRIPTION=1 Equivalent to --strict-description.',
|
|
90
|
+
' SKILLS_DIR=<path> Override skills directory (default: ./skills).',
|
|
91
|
+
'',
|
|
92
|
+
'Exit codes: 0=clean, 1=warnings only, 2=blockers present.',
|
|
93
|
+
'',
|
|
94
|
+
'See reference/skill-authoring-contract.md for the full contract.',
|
|
95
|
+
'',
|
|
96
|
+
].join('\n'));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function parseFrontmatter(content) {
|
|
100
|
+
if (!content.startsWith('---\n') && !content.startsWith('---\r\n')) {
|
|
101
|
+
return { ok: false, error: 'missing-frontmatter' };
|
|
102
|
+
}
|
|
103
|
+
// Find the closing `\n---` after the opening one.
|
|
104
|
+
const end = content.indexOf('\n---', 4);
|
|
105
|
+
if (end < 0) return { ok: false, error: 'unterminated-frontmatter' };
|
|
106
|
+
const block = content.slice(4, end);
|
|
107
|
+
const fields = {};
|
|
108
|
+
const lines = block.split(/\r?\n/);
|
|
109
|
+
for (let i = 0; i < lines.length; i++) {
|
|
110
|
+
const line = lines[i];
|
|
111
|
+
const m = line.match(/^([a-zA-Z][a-zA-Z0-9_-]*):\s*(.*)$/);
|
|
112
|
+
if (m) {
|
|
113
|
+
let value = m[2];
|
|
114
|
+
// Strip wrapping quotes (single or double).
|
|
115
|
+
if (value.length >= 2 &&
|
|
116
|
+
((value.startsWith('"') && value.endsWith('"')) ||
|
|
117
|
+
(value.startsWith("'") && value.endsWith("'")))) {
|
|
118
|
+
value = value.slice(1, -1);
|
|
119
|
+
}
|
|
120
|
+
// Multi-line description folding: when description: is followed by empty value,
|
|
121
|
+
// gather continuation lines until the next `key:` line.
|
|
122
|
+
if (m[1] === 'description' && value === '') {
|
|
123
|
+
const parts = [];
|
|
124
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
125
|
+
if (/^[a-zA-Z][a-zA-Z0-9_-]*:/.test(lines[j])) break;
|
|
126
|
+
parts.push(lines[j].trim());
|
|
127
|
+
}
|
|
128
|
+
value = parts.join(' ').trim();
|
|
129
|
+
}
|
|
130
|
+
fields[m[1]] = value;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return { ok: true, fields, bodyStart: end + 4 };
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function countLines(content) {
|
|
137
|
+
if (!content) return 0;
|
|
138
|
+
const lines = content.split(/\r?\n/);
|
|
139
|
+
// wc -l semantics: drop a single trailing empty entry (the newline-terminated final line).
|
|
140
|
+
if (lines[lines.length - 1] === '') lines.pop();
|
|
141
|
+
return lines.length;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function validateSkill(skillName, skillPath, flags) {
|
|
145
|
+
const result = {
|
|
146
|
+
name: skillName,
|
|
147
|
+
path: skillPath,
|
|
148
|
+
lines: 0,
|
|
149
|
+
descriptionLength: 0,
|
|
150
|
+
hasRequiredFields: false,
|
|
151
|
+
level: 'clean',
|
|
152
|
+
errors: [],
|
|
153
|
+
warnings: [],
|
|
154
|
+
reasons: [],
|
|
155
|
+
};
|
|
156
|
+
let content;
|
|
157
|
+
try {
|
|
158
|
+
content = fs.readFileSync(skillPath, 'utf8');
|
|
159
|
+
} catch (e) {
|
|
160
|
+
result.errors.push({ code: 'read-failed', message: e.message });
|
|
161
|
+
result.level = 'block';
|
|
162
|
+
result.reasons.push(`read-failed: ${e.message}`);
|
|
163
|
+
return result;
|
|
164
|
+
}
|
|
165
|
+
result.lines = countLines(content);
|
|
166
|
+
|
|
167
|
+
const fm = parseFrontmatter(content);
|
|
168
|
+
if (!fm.ok) {
|
|
169
|
+
result.errors.push({ code: 'frontmatter', message: fm.error });
|
|
170
|
+
result.reasons.push(`frontmatter: ${fm.error}`);
|
|
171
|
+
result.level = 'block';
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
const hasName = Boolean(fm.fields.name);
|
|
175
|
+
const hasDesc = Boolean(fm.fields.description);
|
|
176
|
+
result.hasRequiredFields = hasName && hasDesc;
|
|
177
|
+
if (!hasName) {
|
|
178
|
+
result.errors.push({ code: 'missing-name', message: 'frontmatter.name required' });
|
|
179
|
+
result.reasons.push('missing-name');
|
|
180
|
+
}
|
|
181
|
+
if (!hasDesc) {
|
|
182
|
+
result.errors.push({ code: 'missing-description', message: 'frontmatter.description required' });
|
|
183
|
+
result.reasons.push('missing-description');
|
|
184
|
+
} else {
|
|
185
|
+
const d = fm.fields.description;
|
|
186
|
+
result.descriptionLength = d.length;
|
|
187
|
+
if (d.length < DESC_MIN) {
|
|
188
|
+
result.errors.push({ code: 'description-too-short', message: `${d.length} chars; require >=${DESC_MIN}` });
|
|
189
|
+
result.reasons.push(`description-too-short: ${d.length}`);
|
|
190
|
+
}
|
|
191
|
+
if (d.length > DESC_MAX) {
|
|
192
|
+
result.errors.push({ code: 'description-too-long', message: `${d.length} chars; require <=${DESC_MAX}` });
|
|
193
|
+
result.reasons.push(`description-too-long: ${d.length}`);
|
|
194
|
+
}
|
|
195
|
+
if (flags.strict && !STRICT_RE.test(d)) {
|
|
196
|
+
result.errors.push({ code: 'description-format', message: 'strict mode: missing ". Use when <triggers>." suffix' });
|
|
197
|
+
result.reasons.push('description-format');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
const dmi = fm.fields['disable-model-invocation'];
|
|
201
|
+
if (dmi !== undefined) {
|
|
202
|
+
if (dmi !== 'true' && dmi !== 'false') {
|
|
203
|
+
// Tolerate quoted "true"/"false" — parseFrontmatter strips quotes.
|
|
204
|
+
// Any other shape (e.g. raw "True", "yes") is a block.
|
|
205
|
+
result.errors.push({ code: 'disable-model-invocation-shape', message: `disable-model-invocation must be the boolean true|false, got "${dmi}"` });
|
|
206
|
+
result.reasons.push(`disable-model-invocation-shape: ${dmi}`);
|
|
207
|
+
} else if (dmi === 'true' && !DISABLE_INVOCATION_WHITELIST.has(skillName)) {
|
|
208
|
+
result.errors.push({ code: 'disable-model-invocation', message: `${skillName} not on D-09 whitelist` });
|
|
209
|
+
result.reasons.push('disable-model-invocation-not-whitelisted');
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (result.lines >= BLOCK_LINES) {
|
|
213
|
+
result.errors.push({ code: 'block-lines', message: `${result.lines} lines; block threshold ${BLOCK_LINES}` });
|
|
214
|
+
result.reasons.push(`block-lines: ${result.lines}`);
|
|
215
|
+
} else if (result.lines >= WARN_LINES) {
|
|
216
|
+
result.warnings.push({ code: 'warn-lines', message: `${result.lines} lines; warn threshold ${WARN_LINES}` });
|
|
217
|
+
result.reasons.push(`warn-lines: ${result.lines}`);
|
|
218
|
+
}
|
|
219
|
+
if (result.errors.length > 0) result.level = 'block';
|
|
220
|
+
else if (result.warnings.length > 0) result.level = 'warn';
|
|
221
|
+
else result.level = 'clean';
|
|
222
|
+
return result;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function walkSkills(skillsDir) {
|
|
226
|
+
if (!fs.existsSync(skillsDir)) return [];
|
|
227
|
+
const out = [];
|
|
228
|
+
for (const entry of fs.readdirSync(skillsDir, { withFileTypes: true })) {
|
|
229
|
+
if (!entry.isDirectory()) continue;
|
|
230
|
+
const skillFile = path.join(skillsDir, entry.name, 'SKILL.md');
|
|
231
|
+
if (fs.existsSync(skillFile)) out.push({ name: entry.name, path: skillFile });
|
|
232
|
+
}
|
|
233
|
+
return out.sort((a, b) => a.name.localeCompare(b.name));
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function main() {
|
|
237
|
+
const flags = parseArgs(process.argv);
|
|
238
|
+
const root = process.cwd();
|
|
239
|
+
const skillsDir = process.env.SKILLS_DIR || path.join(root, 'skills');
|
|
240
|
+
const skills = walkSkills(skillsDir);
|
|
241
|
+
const results = skills.map(s => validateSkill(s.name, s.path, flags));
|
|
242
|
+
|
|
243
|
+
const summary = {
|
|
244
|
+
total: results.length,
|
|
245
|
+
clean: results.filter(r => r.level === 'clean').length,
|
|
246
|
+
warnings: results.filter(r => r.level === 'warn').length,
|
|
247
|
+
blockers: results.filter(r => r.level === 'block').length,
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
if (flags.json) {
|
|
251
|
+
process.stdout.write(JSON.stringify({ summary, skills: results }, null, 2) + '\n');
|
|
252
|
+
} else {
|
|
253
|
+
if (!flags.quiet) {
|
|
254
|
+
for (const r of results) {
|
|
255
|
+
if (r.level === 'clean') continue;
|
|
256
|
+
process.stdout.write(`${r.name} (${r.lines} lines):\n`);
|
|
257
|
+
for (const e of r.errors) process.stdout.write(` BLOCK ${e.code}: ${e.message}\n`);
|
|
258
|
+
for (const w of r.warnings) process.stdout.write(` WARN ${w.code}: ${w.message}\n`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
process.stdout.write(`\nSummary: ${summary.total} skills | ${summary.clean} clean | ${summary.warnings} warn | ${summary.blockers} block\n`);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
if (summary.blockers > 0) process.exit(2);
|
|
265
|
+
if (summary.warnings > 0) process.exit(1);
|
|
266
|
+
process.exit(0);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (require.main === module) main();
|
|
270
|
+
|
|
271
|
+
module.exports = {
|
|
272
|
+
parseFrontmatter,
|
|
273
|
+
countLines,
|
|
274
|
+
validateSkill,
|
|
275
|
+
walkSkills,
|
|
276
|
+
parseArgs,
|
|
277
|
+
DISABLE_INVOCATION_WHITELIST,
|
|
278
|
+
WARN_LINES,
|
|
279
|
+
BLOCK_LINES,
|
|
280
|
+
DESC_MIN,
|
|
281
|
+
DESC_MAX,
|
|
282
|
+
STRICT_RE,
|
|
283
|
+
};
|
|
@@ -6,17 +6,17 @@ tools: Bash, Read, Glob, Grep
|
|
|
6
6
|
|
|
7
7
|
# /gdd:analyze-dependencies
|
|
8
8
|
|
|
9
|
-
**Role:** Surface dependency relationships, token usage spread, component graphs, and decision traceability using
|
|
9
|
+
**Role:** Surface dependency relationships, token usage spread, component graphs, and decision traceability using `.design/intel/`. All queries are O(1) reads against pre-built JSON slices — no file greps. See `./reference/heuristics.md` for the underlying dependency-analysis heuristics (fan-out thresholds, orphan-token criteria, cycle-detection bias).
|
|
10
10
|
|
|
11
|
-
## Pre-flight
|
|
11
|
+
## Pre-flight
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Verify the intel store exists:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
ls .design/intel/files.json 2>/dev/null && echo "ready" || echo "missing"
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
If missing
|
|
19
|
+
If missing, print:
|
|
20
20
|
|
|
21
21
|
```
|
|
22
22
|
Intel store not found. Build it first:
|
|
@@ -26,145 +26,56 @@ Then re-run /gdd:analyze-dependencies.
|
|
|
26
26
|
|
|
27
27
|
## Usage modes
|
|
28
28
|
|
|
29
|
-
`/gdd:analyze-dependencies` — run all four analyses and print a combined report
|
|
30
|
-
`/gdd:analyze-dependencies tokens` — token fan-out only
|
|
31
|
-
`/gdd:analyze-dependencies components` — component call-graph only
|
|
32
|
-
`/gdd:analyze-dependencies decisions` — decision traceability only
|
|
33
|
-
`/gdd:analyze-dependencies circular` — circular dependency detection only
|
|
29
|
+
- `/gdd:analyze-dependencies` — run all four analyses and print a combined report
|
|
30
|
+
- `/gdd:analyze-dependencies tokens` — token fan-out only
|
|
31
|
+
- `/gdd:analyze-dependencies components` — component call-graph only
|
|
32
|
+
- `/gdd:analyze-dependencies decisions` — decision traceability only
|
|
33
|
+
- `/gdd:analyze-dependencies circular` — circular dependency detection only
|
|
34
34
|
|
|
35
35
|
## Analysis 1 — Token fan-out
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
Surfaces tokens referenced in many files + orphans (referenced exactly once).
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
1. Read `.design/intel/tokens.json`; group by `token` value; count distinct `file` values.
|
|
40
|
+
2. Sort descending; print top-20 with token / file count / category columns.
|
|
41
|
+
3. Append orphans list (token + file:line of the single reference).
|
|
40
42
|
|
|
41
|
-
1
|
|
42
|
-
2. Group entries by `token` value
|
|
43
|
-
3. Count distinct `file` values per token
|
|
44
|
-
4. Sort descending by file count
|
|
45
|
-
5. Print top-20 most-referenced tokens:
|
|
46
|
-
|
|
47
|
-
```
|
|
48
|
-
━━━ Token fan-out ━━━
|
|
49
|
-
Token Files Category
|
|
50
|
-
--color-primary 12 color
|
|
51
|
-
--space-4 9 spacing
|
|
52
|
-
--font-size-body 7 typography
|
|
53
|
-
...
|
|
54
|
-
(top 20 shown)
|
|
55
|
-
|
|
56
|
-
Orphaned tokens (referenced in exactly 1 file):
|
|
57
|
-
--shadow-card-hover (skills/design/SKILL.md:44)
|
|
58
|
-
━━━━━━━━━━━━━━━━━━━━━
|
|
59
|
-
```
|
|
43
|
+
Header: `━━━ Token fan-out ━━━` … `(top 20 shown)` … `Orphaned tokens (referenced in exactly 1 file):` … footer rule.
|
|
60
44
|
|
|
61
45
|
## Analysis 2 — Component call-graph
|
|
62
46
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
**Protocol:**
|
|
47
|
+
Surfaces widely-referenced components and the files referencing each.
|
|
66
48
|
|
|
67
|
-
1. Read `.design/intel/components.json`
|
|
68
|
-
2.
|
|
69
|
-
3.
|
|
70
|
-
4. Sort descending by reference count
|
|
71
|
-
5. Print top-20 most-referenced components with their source files:
|
|
49
|
+
1. Read `.design/intel/components.json`; group by `component` name; count distinct `file` values.
|
|
50
|
+
2. Sort descending; print top-20 with component / references / files columns.
|
|
51
|
+
3. If `components <Name>` is passed, print only that component's referencing files (one per line).
|
|
72
52
|
|
|
73
|
-
|
|
74
|
-
━━━ Component call-graph ━━━
|
|
75
|
-
Component References Files
|
|
76
|
-
Button 14 skills/design/SKILL.md, agents/design-executor.md, ...
|
|
77
|
-
Card 9 skills/verify/SKILL.md, reference/heuristics.md, ...
|
|
78
|
-
...
|
|
79
|
-
(top 20 shown)
|
|
80
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
If a specific component name is passed as a second argument (e.g., `/gdd:analyze-dependencies components Button`), show only that component's referencing files, one per line.
|
|
53
|
+
Header: `━━━ Component call-graph ━━━` … footer rule.
|
|
84
54
|
|
|
85
55
|
## Analysis 3 — Decision traceability
|
|
86
56
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
**Protocol:**
|
|
57
|
+
Maps decisions to skill/agent files that cite them.
|
|
90
58
|
|
|
91
|
-
1. Read `.design/intel/decisions.json`
|
|
92
|
-
2. Read `.design/intel/symbols.json`
|
|
93
|
-
3.
|
|
94
|
-
4.
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
grep -r "D-[0-9][0-9]*" .design/intel/decisions.json | head -20
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
5. Cross-reference with which skill/agent files cite that decision ID (look in symbols.json for heading anchors matching decision patterns)
|
|
101
|
-
|
|
102
|
-
6. Print:
|
|
103
|
-
|
|
104
|
-
```
|
|
105
|
-
━━━ Decision traceability ━━━
|
|
106
|
-
D-01 Use Figma MCP for token extraction
|
|
107
|
-
Referenced by: skills/scan/SKILL.md:12, agents/design-executor.md:7
|
|
59
|
+
1. Read `.design/intel/decisions.json` (decision IDs D-01, D-02, …).
|
|
60
|
+
2. Read `.design/intel/symbols.json` for heading anchors; `.design/intel/dependencies.json` for @-reference chains.
|
|
61
|
+
3. For each decision, cross-reference which files cite the ID.
|
|
62
|
+
4. Print per-decision block: `D-NN <description>` then a 6-space-indented `Referenced by: <file:line>, …` line (or `(no explicit references found)`).
|
|
63
|
+
5. Footer: `Total: N decisions tracked, M with file references`.
|
|
108
64
|
|
|
109
|
-
|
|
110
|
-
Referenced by: (no explicit references found)
|
|
111
|
-
|
|
112
|
-
Total: 3 decisions tracked, 2 with file references
|
|
113
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
If `.design/intel/decisions.json` contains no entries (e.g., no DESIGN-CONTEXT.md exists yet), print:
|
|
117
|
-
```
|
|
118
|
-
No decisions indexed. Run node scripts/build-intel.cjs after creating .design/DESIGN-CONTEXT.md.
|
|
119
|
-
```
|
|
65
|
+
Empty-state: `No decisions indexed. Run node scripts/build-intel.cjs after creating .design/DESIGN-CONTEXT.md.`
|
|
120
66
|
|
|
121
67
|
## Analysis 4 — Circular dependency detection
|
|
122
68
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
**Protocol:**
|
|
126
|
-
|
|
127
|
-
1. Read `.design/intel/graph.json`
|
|
128
|
-
2. Build an adjacency map from `edges` array: `{ from -> [to, to, ...] }`
|
|
129
|
-
3. Run depth-first search with path tracking to detect back-edges (cycles)
|
|
130
|
-
4. Algorithm:
|
|
131
|
-
|
|
132
|
-
```
|
|
133
|
-
visited = {}
|
|
134
|
-
path = []
|
|
135
|
-
cycles = []
|
|
136
|
-
|
|
137
|
-
function dfs(node):
|
|
138
|
-
if node in path:
|
|
139
|
-
cycle_start = path.index(node)
|
|
140
|
-
cycles.append(path[cycle_start:] + [node])
|
|
141
|
-
return
|
|
142
|
-
if node in visited: return
|
|
143
|
-
visited.add(node)
|
|
144
|
-
path.append(node)
|
|
145
|
-
for neighbor in adjacency[node]:
|
|
146
|
-
dfs(neighbor)
|
|
147
|
-
path.pop()
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
5. Print detected cycles (or "No circular dependencies detected"):
|
|
151
|
-
|
|
152
|
-
```
|
|
153
|
-
━━━ Circular dependency detection ━━━
|
|
154
|
-
Cycle 1:
|
|
155
|
-
skills/verify/SKILL.md
|
|
156
|
-
-> reference/accessibility.md
|
|
157
|
-
-> skills/verify/SKILL.md <- CYCLE
|
|
158
|
-
|
|
159
|
-
Total cycles: 1
|
|
160
|
-
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
161
|
-
```
|
|
69
|
+
Detects cycles in the `@`-reference graph (File A → File B → File A). DFS with path-tracking detects back-edges; algorithm + adjacency-map shape detailed in `./reference/heuristics.md` §"Dependency-cycle detection".
|
|
162
70
|
|
|
163
|
-
|
|
71
|
+
1. Read `.design/intel/graph.json`; build adjacency map from `edges`.
|
|
72
|
+
2. Run DFS with path-tracking; collect back-edges as cycles.
|
|
73
|
+
3. Print each cycle with the node sequence + `<- CYCLE` marker on the closing node.
|
|
74
|
+
4. Footer: `Total cycles: N` (or `All clear — no circular dependencies detected.`).
|
|
164
75
|
|
|
165
|
-
## Combined report
|
|
76
|
+
## Combined report
|
|
166
77
|
|
|
167
|
-
When run without a mode argument, print all four analyses in sequence separated by blank lines
|
|
78
|
+
When run without a mode argument, print all four analyses in sequence separated by blank lines, prefixed with:
|
|
168
79
|
|
|
169
80
|
```
|
|
170
81
|
━━━ Dependency Analysis ━━━
|
|
@@ -52,46 +52,7 @@ Based on user choice:
|
|
|
52
52
|
|
|
53
53
|
### 4. Apply Logic by Proposal Type
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
1. Extract agent name from Change field (e.g., `agents/design-verifier.md`)
|
|
57
|
-
2. Read the agent file
|
|
58
|
-
3. Find the frontmatter line matching the field being changed
|
|
59
|
-
4. Use Edit tool to update the specific line
|
|
60
|
-
5. Append `**Applied**: <date>` to the proposal in reflections file
|
|
61
|
-
|
|
62
|
-
#### [REFERENCE]
|
|
63
|
-
1. Extract target file path from Change field (e.g., `reference/heuristics.md`)
|
|
64
|
-
2. If file exists: append the drafted text using Edit tool
|
|
65
|
-
3. If file doesn't exist: create it with a minimal header + the drafted text using Write tool
|
|
66
|
-
4. Append `**Applied**: <date>` to proposal in reflections file
|
|
67
|
-
|
|
68
|
-
#### [BUDGET]
|
|
69
|
-
1. Read `.design/budget.json`
|
|
70
|
-
2. Locate the key path from the Change field (e.g., `design-verifier.per_run_cap_usd`)
|
|
71
|
-
3. Update the value
|
|
72
|
-
4. Write updated JSON back to `.design/budget.json`
|
|
73
|
-
5. Append `**Applied**: <date>` to proposal in reflections file
|
|
74
|
-
|
|
75
|
-
#### [QUESTION]
|
|
76
|
-
1. Read `agents/design-discussant.md`
|
|
77
|
-
2. Find the question text specified in the Change field
|
|
78
|
-
3. If pruning: remove the question lines using Edit tool
|
|
79
|
-
4. If rewording: replace the question text using Edit tool
|
|
80
|
-
5. Append `**Applied**: <date>` to proposal in reflections file
|
|
81
|
-
|
|
82
|
-
#### [GLOBAL-SKILL]
|
|
83
|
-
1. Extract target filename from Change field (e.g., `design-color-conventions.md`)
|
|
84
|
-
2. Ensure `~/.claude/gdd/global-skills/` directory exists (create with `mkdir -p` if not)
|
|
85
|
-
3. If target file exists: append new content using Edit tool (add a `---` separator first)
|
|
86
|
-
4. If target file doesn't exist: create with header + content using Write tool:
|
|
87
|
-
```markdown
|
|
88
|
-
# <Topic> Conventions (Global)
|
|
89
|
-
*Promoted from project: <project-name>, cycle: <cycle-slug>*
|
|
90
|
-
|
|
91
|
-
<content>
|
|
92
|
-
```
|
|
93
|
-
5. Print: "Global skill written to ~/.claude/gdd/global-skills/<name>.md — auto-loads in all future gdd sessions"
|
|
94
|
-
6. Append `**Applied**: <date>` to proposal in reflections file
|
|
55
|
+
After the user chooses `a` (apply) or `e` (edit-then-apply), branch on the proposal's bracketed type tag and follow the per-type apply procedure in `./apply-reflections-procedure.md` — one numbered procedure each for `[FRONTMATTER]`, `[REFERENCE]`, `[BUDGET]`, `[QUESTION]`, `[GLOBAL-SKILL]`. All branches end with `**Applied**: <date>` appended to the proposal block in the reflections file.
|
|
95
56
|
|
|
96
57
|
### 5. Summary
|
|
97
58
|
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: apply-reflections-procedure
|
|
3
|
+
type: heuristic
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
phase: 28.5
|
|
6
|
+
tags: [apply-reflections, proposal, frontmatter, reference, budget, question, global-skill]
|
|
7
|
+
last_updated: 2026-05-18
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Apply-Reflections — Per-Type Procedure
|
|
11
|
+
|
|
12
|
+
Extracted from `skills/apply-reflections/SKILL.md` per Phase 28.5 D-10 (extract-then-link,
|
|
13
|
+
never delete content). The orchestrator loop in `apply-reflections` (resolve file → parse →
|
|
14
|
+
review loop → summary) stays in the SKILL. The per-proposal-type apply logic below moves
|
|
15
|
+
here because it is content-class methodology, not workflow.
|
|
16
|
+
|
|
17
|
+
## Apply Logic by Proposal Type
|
|
18
|
+
|
|
19
|
+
After the user chooses `a` (apply) or `e` (edit-then-apply) in the review loop, branch by
|
|
20
|
+
the proposal's bracketed type tag.
|
|
21
|
+
|
|
22
|
+
### [FRONTMATTER]
|
|
23
|
+
|
|
24
|
+
1. Extract agent name from Change field (e.g., `agents/design-verifier.md`)
|
|
25
|
+
2. Read the agent file
|
|
26
|
+
3. Find the frontmatter line matching the field being changed
|
|
27
|
+
4. Use Edit tool to update the specific line
|
|
28
|
+
5. Append `**Applied**: <date>` to the proposal in reflections file
|
|
29
|
+
|
|
30
|
+
### [REFERENCE]
|
|
31
|
+
|
|
32
|
+
1. Extract target file path from Change field (e.g., `reference/heuristics.md`)
|
|
33
|
+
2. If file exists: append the drafted text using Edit tool
|
|
34
|
+
3. If file doesn't exist: create it with a minimal header + the drafted text using Write tool
|
|
35
|
+
4. Append `**Applied**: <date>` to proposal in reflections file
|
|
36
|
+
|
|
37
|
+
### [BUDGET]
|
|
38
|
+
|
|
39
|
+
1. Read `.design/budget.json`
|
|
40
|
+
2. Locate the key path from the Change field (e.g., `design-verifier.per_run_cap_usd`)
|
|
41
|
+
3. Update the value
|
|
42
|
+
4. Write updated JSON back to `.design/budget.json`
|
|
43
|
+
5. Append `**Applied**: <date>` to proposal in reflections file
|
|
44
|
+
|
|
45
|
+
### [QUESTION]
|
|
46
|
+
|
|
47
|
+
1. Read `agents/design-discussant.md`
|
|
48
|
+
2. Find the question text specified in the Change field
|
|
49
|
+
3. If pruning: remove the question lines using Edit tool
|
|
50
|
+
4. If rewording: replace the question text using Edit tool
|
|
51
|
+
5. Append `**Applied**: <date>` to proposal in reflections file
|
|
52
|
+
|
|
53
|
+
### [GLOBAL-SKILL]
|
|
54
|
+
|
|
55
|
+
1. Extract target filename from Change field (e.g., `design-color-conventions.md`)
|
|
56
|
+
2. Ensure `~/.claude/gdd/global-skills/` directory exists (create with `mkdir -p` if not)
|
|
57
|
+
3. If target file exists: append new content using Edit tool (add a `---` separator first)
|
|
58
|
+
4. If target file doesn't exist: create with header + content using Write tool:
|
|
59
|
+
|
|
60
|
+
```markdown
|
|
61
|
+
# <Topic> Conventions (Global)
|
|
62
|
+
*Promoted from project: <project-name>, cycle: <cycle-slug>*
|
|
63
|
+
|
|
64
|
+
<content>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
5. Print: "Global skill written to ~/.claude/gdd/global-skills/<name>.md — auto-loads in all future gdd sessions"
|
|
68
|
+
6. Append `**Applied**: <date>` to proposal in reflections file
|
package/skills/audit/SKILL.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gdd-audit
|
|
3
|
-
description: "Run design audit
|
|
3
|
+
description: "Run a design audit by spawning design-auditor, design-integration-checker, and (optionally) design-verifier + design-reflector agents, then printing a consolidated 6-pillar score summary. Use when the user wants to score the current design, retroactively verify a completed cycle, or quickly re-check after a fix."
|
|
4
4
|
argument-hint: "[--retroactive] [--quick] [--no-reflect]"
|
|
5
5
|
tools: Read, Write, Task, Glob, Bash
|
|
6
6
|
---
|
|
@@ -9,6 +9,8 @@ tools: Read, Write, Task, Glob, Bash
|
|
|
9
9
|
|
|
10
10
|
Wraps the existing `design-auditor`, `design-verifier`, and `design-integration-checker` agents — no new auditor logic here. Parses flags, spawns the right combination, prints summary.
|
|
11
11
|
|
|
12
|
+
For the 6-pillar scoring rubric this skill aggregates, see `../../reference/audit-scoring.md`. For the shared design-quality pillar set that frames the score categories, see `../../reference/shared-preamble.md`.
|
|
13
|
+
|
|
12
14
|
## Modes
|
|
13
15
|
|
|
14
16
|
### Default
|