@hegemonart/get-design-done 1.57.0 → 1.57.2

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 (123) hide show
  1. package/.claude-plugin/marketplace.json +26 -41
  2. package/.claude-plugin/plugin.json +23 -48
  3. package/CHANGELOG.md +119 -0
  4. package/README.md +166 -511
  5. package/SKILL.md +2 -0
  6. package/agents/README.md +33 -36
  7. package/agents/a11y-mapper.md +3 -3
  8. package/agents/component-benchmark-harvester.md +6 -6
  9. package/agents/component-benchmark-synthesizer.md +3 -3
  10. package/agents/compose-executor.md +3 -3
  11. package/agents/cost-forecaster.md +2 -2
  12. package/agents/design-auditor.md +7 -7
  13. package/agents/design-authority-watcher.md +15 -15
  14. package/agents/design-context-builder.md +4 -4
  15. package/agents/design-context-checker-gate.md +1 -1
  16. package/agents/design-discussant.md +2 -2
  17. package/agents/design-doc-writer.md +1 -1
  18. package/agents/design-executor.md +2 -2
  19. package/agents/design-figma-writer.md +2 -2
  20. package/agents/design-fixer.md +7 -7
  21. package/agents/design-integration-checker-gate.md +1 -1
  22. package/agents/design-integration-checker.md +1 -1
  23. package/agents/design-paper-writer.md +3 -3
  24. package/agents/design-pencil-writer.md +1 -1
  25. package/agents/design-planner.md +21 -0
  26. package/agents/design-reflector.md +39 -39
  27. package/agents/design-research-synthesizer.md +1 -0
  28. package/agents/design-start-writer.md +1 -1
  29. package/agents/design-update-checker.md +5 -5
  30. package/agents/design-verifier-gate.md +1 -1
  31. package/agents/design-verifier.md +52 -48
  32. package/agents/ds-generator.md +2 -2
  33. package/agents/ds-migration-planner.md +4 -4
  34. package/agents/email-executor.md +9 -9
  35. package/agents/experiment-result-ingester.md +3 -3
  36. package/agents/flutter-executor.md +5 -5
  37. package/agents/gdd-graph-refresh.md +3 -3
  38. package/agents/gdd-intel-updater.md +2 -2
  39. package/agents/motion-mapper.md +2 -2
  40. package/agents/motion-verifier.md +4 -4
  41. package/agents/pdf-executor.md +8 -8
  42. package/agents/perf-analyzer.md +17 -17
  43. package/agents/pr-commenter.md +9 -9
  44. package/agents/prototype-gate.md +2 -2
  45. package/agents/quality-gate-runner.md +1 -1
  46. package/agents/rollout-coordinator.md +3 -3
  47. package/agents/swift-executor.md +4 -4
  48. package/agents/ticket-sync-agent.md +6 -6
  49. package/agents/user-research-synthesizer.md +2 -2
  50. package/connections/connections.md +44 -45
  51. package/connections/cursor.md +73 -0
  52. package/connections/preview.md +3 -3
  53. package/dist/claude-code/.claude/skills/cache-manager/SKILL.md +3 -3
  54. package/dist/claude-code/.claude/skills/cache-manager/cache-policy.md +1 -1
  55. package/dist/claude-code/.claude/skills/design/SKILL.md +19 -0
  56. package/dist/claude-code/.claude/skills/explore/SKILL.md +11 -0
  57. package/dist/claude-code/.claude/skills/figma-write/SKILL.md +13 -2
  58. package/dist/claude-code/.claude/skills/paper-write/SKILL.md +54 -0
  59. package/dist/claude-code/.claude/skills/pencil-write/SKILL.md +54 -0
  60. package/dist/claude-code/.claude/skills/report-issue/SKILL.md +2 -2
  61. package/dist/claude-code/.claude/skills/router/SKILL.md +2 -2
  62. package/dist/claude-code/.claude/skills/verify/verify-procedure.md +10 -11
  63. package/dist/claude-code/.claude/skills/warm-cache/SKILL.md +1 -1
  64. package/hooks/budget-enforcer.ts +5 -4
  65. package/hooks/first-run-nudge.cjs +171 -0
  66. package/hooks/gdd-intel-trigger.js +243 -0
  67. package/hooks/gdd-mcp-circuit-breaker.js +62 -7
  68. package/hooks/gdd-precompact-snapshot.js +50 -29
  69. package/hooks/gdd-protected-paths.js +175 -20
  70. package/hooks/gdd-read-injection-scanner.ts +9 -1
  71. package/hooks/gdd-risk-gate.js +110 -8
  72. package/hooks/gdd-sessionstart-recap.js +59 -24
  73. package/hooks/hooks.json +13 -4
  74. package/hooks/inject-using-gdd.cjs +188 -0
  75. package/hooks/update-check.cjs +511 -0
  76. package/package.json +9 -2
  77. package/reference/STATE-TEMPLATE.md +10 -13
  78. package/reference/audit-scoring.md +1 -1
  79. package/reference/cache-tier-doctrine.md +46 -0
  80. package/reference/config-schema.md +9 -9
  81. package/reference/i18n.md +1 -1
  82. package/reference/intel-schema.md +37 -2
  83. package/reference/meta-rules.md +4 -4
  84. package/reference/model-tiers.md +2 -2
  85. package/reference/registry.json +101 -94
  86. package/reference/runtime-models.md +11 -1
  87. package/reference/shared-preamble.md +13 -14
  88. package/reference/skill-graph.md +24 -1
  89. package/scripts/bootstrap.cjs +373 -0
  90. package/scripts/injection-patterns.cjs +58 -0
  91. package/scripts/lib/apply-reflections/incubator-proposals.cjs +57 -26
  92. package/scripts/lib/design-search.cjs +20 -2
  93. package/scripts/lib/install/converters/codex-plugin.cjs +5 -2
  94. package/scripts/lib/install/converters/cursor.cjs +20 -0
  95. package/scripts/lib/issue-reporter/report-flow.cjs +1 -1
  96. package/scripts/lib/manifest/skills.json +80 -13
  97. package/scripts/lib/state/migrate-to-sqlite.cjs +23 -7
  98. package/scripts/lib/state/query-surface.cjs +86 -16
  99. package/scripts/lib/state/render-markdown.cjs +26 -14
  100. package/scripts/lib/state/state-store.cjs +141 -68
  101. package/sdk/cli/commands/stage.ts +17 -0
  102. package/sdk/cli/index.js +21 -1
  103. package/sdk/dashboard/data/_pkg-root.cjs +4 -4
  104. package/sdk/dashboard/data/risk-surface.cjs +54 -19
  105. package/sdk/dashboard/tui/index.cjs +28 -2
  106. package/sdk/mcp/gdd-state/server.js +7 -1
  107. package/sdk/state/index.ts +11 -1
  108. package/skills/cache-manager/SKILL.md +3 -3
  109. package/skills/cache-manager/cache-policy.md +1 -1
  110. package/skills/design/SKILL.md +19 -0
  111. package/skills/explore/SKILL.md +11 -0
  112. package/skills/figma-write/SKILL.md +13 -2
  113. package/skills/paper-write/SKILL.md +54 -0
  114. package/skills/pencil-write/SKILL.md +54 -0
  115. package/skills/report-issue/SKILL.md +2 -2
  116. package/skills/router/SKILL.md +2 -2
  117. package/skills/verify/verify-procedure.md +10 -11
  118. package/skills/warm-cache/SKILL.md +1 -1
  119. package/hooks/first-run-nudge.sh +0 -82
  120. package/hooks/inject-using-gdd.sh +0 -72
  121. package/hooks/update-check.sh +0 -251
  122. package/scripts/lib/audit-aggregator/index.cjs +0 -219
  123. package/scripts/lib/hedge-ensemble.cjs +0 -217
@@ -1,24 +1,23 @@
1
- // scripts/lib/apply-reflections/incubator-proposals.cjs — Plan 29-05
1
+ // scripts/lib/apply-reflections/incubator-proposals.cjs
2
2
  //
3
3
  // Incubator-draft proposal class for /gdd:apply-reflections. Consumes drafts
4
- // authored by scripts/lib/incubator-author.cjs (Plan 29-04) at
4
+ // authored by scripts/lib/incubator-author.cjs at
5
5
  // `.design/reflections/incubator/<slug>/` and exposes the 7 actions surfaced
6
6
  // in skills/apply-reflections/SKILL.md.
7
7
  //
8
8
  // Exports: discoverIncubatorDrafts, renderProposal, applyAccept, applyReject,
9
9
  // applyEdit, checkStage1Gate, recordOptIn.
10
10
  //
11
- // Decisions honoured:
12
- // * D-01 — checkStage1Gate is read-only; recordOptIn is the sole writer and
13
- // only fires on explicit user confirmation. No auto-flip ever.
14
- // * D-04 — applyAccept performs the full draft → final-artifact write +
15
- // registry append in one call. No intermediate state.
16
- // * D-05 — applyAccept calls validateScope from
17
- // scripts/validate-incubator-scope.cjs BEFORE any filesystem
18
- // mutation. Failure throws; registry and incubator subdir
19
- // untouched. Non-bypassable.
20
- // * D-12 DRAFT.md is copied verbatim, so the drafter's `delegate_to: null`
21
- // frontmatter survives the promotion.
11
+ // Invariants:
12
+ // * checkStage1Gate is read-only; recordOptIn is the sole state writer and
13
+ // only fires on explicit user confirmation. No auto-flip ever.
14
+ // * applyAccept performs the full draft → final-artifact write + registry
15
+ // append in one call. No intermediate state.
16
+ // * applyAccept calls validateScope from
17
+ // scripts/validate-incubator-scope.cjs BEFORE any filesystem mutation.
18
+ // Failure throws; registry and incubator subdir untouched. Non-bypassable.
19
+ // * DRAFT.md is copied verbatim, so the drafter's `delegate_to: null`
20
+ // frontmatter survives the promotion.
22
21
  //
23
22
  // Style: CommonJS, zero external deps (node:fs / node:path / node:child_process /
24
23
  // node:os only).
@@ -31,13 +30,14 @@ const child_process = require('node:child_process');
31
30
  const os = require('node:os');
32
31
 
33
32
  const { validateScope } = require('../../validate-incubator-scope.cjs');
33
+ const touchesPatternMiner = require('../touches-pattern-miner.cjs');
34
34
 
35
35
  // --- Constants ---
36
36
 
37
37
  const DEFAULT_INCUBATOR_DIR = '.design/reflections/incubator';
38
38
  const DEFAULT_REGISTRY_PATH = 'reference/registry.json';
39
39
  const DEFAULT_GATE_SPEC_PATH = 'reference/capability-gap-stage-gate.md';
40
- const DEFAULT_STATE_PATH = '.planning/STATE.md';
40
+ const DEFAULT_STATE_PATH = '.design/STATE.md';
41
41
  const OPT_IN_HEADING = '## Capability-gap Stage-1 opt-in';
42
42
  const OPT_IN_TOKEN_RE = /Stage-1 opt-in|capability.gap.*opt.in|confirmed_by/i;
43
43
 
@@ -94,7 +94,7 @@ function discoverIncubatorDrafts(options) {
94
94
  const drafts = [];
95
95
  for (const ent of entries) {
96
96
  if (!ent.isDirectory()) continue;
97
- if (ent.name === 'archive') continue; // D-06: archived drafts not surfaced
97
+ if (ent.name === 'archive') continue; // archived drafts not surfaced
98
98
 
99
99
  const slugDir = path.join(incubatorDir, ent.name);
100
100
  const manifestPath = path.join(slugDir, 'manifest.json');
@@ -199,15 +199,15 @@ function renderUnifiedDiff(oldText, newText) {
199
199
  return out.join('\n');
200
200
  }
201
201
 
202
- // --- applyAccept (D-04 + D-05) ---
202
+ // --- applyAccept ---
203
203
 
204
204
  /**
205
- * Promote draft → final artifact + registry entry in one call (D-04).
205
+ * Promote draft → final artifact + registry entry in one call.
206
206
  *
207
- * Order: validateScope (D-05; throws → no writes) → read DRAFT.md →
207
+ * Order: validateScope (throws → no writes) → read DRAFT.md →
208
208
  * [dryRun: return intent] → mkdirp parent → atomic-write target →
209
209
  * append-and-atomic-write registry → fs.rm incubator subdir last
210
- * (so partial failure leaves draft retryable — T-29.05-04).
210
+ * (so partial failure leaves draft retryable).
211
211
  */
212
212
  function applyAccept(draft, options) {
213
213
  const o = options || {};
@@ -217,7 +217,7 @@ function applyAccept(draft, options) {
217
217
  : path.join(repoRoot, o.registryPath || DEFAULT_REGISTRY_PATH);
218
218
  const dryRun = !!o.dryRun;
219
219
 
220
- // Step 1 — D-05 scope guard. THROWS on failure; registry untouched.
220
+ // Step 1 — scope guard. THROWS on failure; registry untouched.
221
221
  validateScope(draft.target_path, { repoRoot });
222
222
 
223
223
  const draftBody = fs.readFileSync(draft.draft_path, 'utf8');
@@ -275,7 +275,7 @@ function appendRegistryEntry(registryPath, kind, entry) {
275
275
  throw new Error(`[incubator-proposals] registry root must be an object: ${registryPath}`);
276
276
  }
277
277
 
278
- // Phase 14.5 self-authoring shape: { agents: [...], skills: [...] }.
278
+ // Self-authoring registry shape: { agents: [...], skills: [...] }.
279
279
  // Initialize missing arrays additively so we never clobber another schema's data.
280
280
  if (kind === 'agent') {
281
281
  if (!Array.isArray(registry.agents)) registry.agents = [];
@@ -356,10 +356,10 @@ function applyEdit(draft, options) {
356
356
  }
357
357
  }
358
358
 
359
- // --- checkStage1Gate (D-01: read-only) ---
359
+ // --- checkStage1Gate (read-only) ---
360
360
 
361
361
  /**
362
- * Read-only Stage-1 gate inspection (D-01).
362
+ * Read-only Stage-1 gate inspection.
363
363
  * thresholdMet = count(registry entries with origin === 'incubator') ≥ K
364
364
  * optInRecorded = state file contains an opt-in token
365
365
  * summary = human-readable one-liner
@@ -404,7 +404,7 @@ function checkStage1Gate(options) {
404
404
  /**
405
405
  * Pull `K` out of capability-gap-stage-gate.md. The doc encodes K as a row
406
406
  * in a markdown table: `| K | 3 | Minimum number of stable clusters... |`.
407
- * If absent or unparseable, fall back to 3 (Phase 29 D-03 default).
407
+ * If absent or unparseable, fall back to 3 (the documented default).
408
408
  */
409
409
  function readK(gateSpecPath) {
410
410
  const src = safeReadFileSync(gateSpecPath);
@@ -415,12 +415,12 @@ function readK(gateSpecPath) {
415
415
  return Number.isFinite(v) && v > 0 ? v : 3;
416
416
  }
417
417
 
418
- // --- recordOptIn (D-01: explicit-only) ---
418
+ // --- recordOptIn (explicit-only) ---
419
419
 
420
420
  /**
421
421
  * Persist the user's explicit Stage-1 opt-in to STATE.md. Idempotent.
422
422
  * IMPORTANT: this is the SOLE state writer in this module. Only invoke after
423
- * explicit user confirmation in the apply-reflections UX (D-01).
423
+ * explicit user confirmation in the apply-reflections UX.
424
424
  */
425
425
  function recordOptIn(options) {
426
426
  const o = options || {};
@@ -442,10 +442,41 @@ function recordOptIn(options) {
442
442
  return { optInRecorded: true, at, confirmedBy };
443
443
  }
444
444
 
445
+ // --- Touches-pattern proposals (Batch D D8 wire) ---
446
+ //
447
+ // Surfaces recurring `Touches:` signatures across archived task files as
448
+ // auto-crystallization proposals alongside the incubator drafts. The miner
449
+ // is opt-in via `proposalsRoot` arg (defaults to the touches-pattern-miner
450
+ // default location); when no archive exists yet, returns an empty list.
451
+
452
+ function discoverTouchesPatternProposals(opts = {}) {
453
+ const cwd = opts.cwd || process.cwd();
454
+ const cycleDir = path.join(cwd, opts.cycleDir || touchesPatternMiner.DEFAULT_CYCLE_DIR);
455
+ if (!fs.existsSync(cycleDir)) return [];
456
+ try {
457
+ const mined = touchesPatternMiner.mine({
458
+ cycleDir,
459
+ minTasks: opts.minTasks,
460
+ minCycles: opts.minCycles,
461
+ });
462
+ if (!Array.isArray(mined) || mined.length === 0) return [];
463
+ return mined.map((pattern, i) => ({
464
+ type: 'touches-pattern',
465
+ id: `touches-pattern-${i + 1}`,
466
+ pattern,
467
+ summary: pattern.signature || pattern.canonical || `Pattern #${i + 1}`,
468
+ }));
469
+ } catch (_err) {
470
+ // Miner is best-effort — never block apply-reflections on its failure.
471
+ return [];
472
+ }
473
+ }
474
+
445
475
  // --- Exports ---
446
476
 
447
477
  module.exports = {
448
478
  discoverIncubatorDrafts,
479
+ discoverTouchesPatternProposals,
449
480
  renderProposal,
450
481
  applyAccept,
451
482
  applyReject,
@@ -124,14 +124,32 @@ function reindex(projectRoot) {
124
124
  db.close();
125
125
  }
126
126
 
127
+ /**
128
+ * Re-wrap each whitespace/OR-delimited term in FTS5 double-quote escaping so
129
+ * that tokens containing `.`, `/`, `-`, or other punctuation that the trigram
130
+ * tokenizer treats as illegal bare-term characters are accepted as quoted
131
+ * phrase queries. This matches the pattern used in instinct-store.cjs.
132
+ *
133
+ * Examples:
134
+ * "heuristics.md OR reference/heuristics.md"
135
+ * -> '"heuristics.md" OR "reference/heuristics.md"'
136
+ * "color tokens"
137
+ * -> '"color" OR "tokens"'
138
+ */
139
+ function _quoteFts5Query(rawQuery) {
140
+ const terms = rawQuery.split(/\s+OR\s+|\s+/).filter(Boolean);
141
+ return terms.map(t => '"' + t.replace(/"/g, '""') + '"').join(' OR ');
142
+ }
143
+
127
144
  function _searchFts5(query, projectRoot, limit) {
128
145
  const dbPath = _dbPath(projectRoot);
129
146
  if (!fs.existsSync(dbPath)) reindex(projectRoot);
130
147
  const db = new Database(dbPath, { readonly: true });
131
148
  try {
149
+ const matchExpr = _quoteFts5Query(query);
132
150
  const rows = db.prepare(
133
151
  `SELECT file, line, text FROM docs WHERE docs MATCH ? ORDER BY rank LIMIT ?`
134
- ).all(query, limit);
152
+ ).all(matchExpr, limit);
135
153
  return rows.map(r => ({ file: r.file, line: r.line, text: r.text }));
136
154
  } finally {
137
155
  db.close();
@@ -203,4 +221,4 @@ function search(query, projectRoot, opts = {}) {
203
221
  return _searchNode(query, projectRoot, limit);
204
222
  }
205
223
 
206
- module.exports = { search, reindex, backendName };
224
+ module.exports = { search, reindex, backendName, _quoteFts5Query };
@@ -306,9 +306,12 @@ function buildManifest(sources) {
306
306
  category,
307
307
  capabilities: ['Read', 'Write'],
308
308
  websiteURL: homepage || '',
309
+ // Codex uses /gdd- prefix uniformly (not /gdd: like Claude Code).
310
+ // Both lines use the same prefix to avoid the documented inconsistency
311
+ // (audit P1 #4 — committed manifest had mixed /gdd: and $gdd-).
309
312
  defaultPrompt: [
310
- 'Run /gdd:brief to start a design cycle.',
311
- 'Use $gdd-explore to audit a screen.',
313
+ 'Run /gdd-brief to start a design cycle.',
314
+ 'Run /gdd-explore to audit a screen.',
312
315
  ],
313
316
  brandColor: '#10A37F',
314
317
  };
@@ -24,6 +24,26 @@
24
24
  *
25
25
  * Pure / side-effect-free: no fs, no env, no path. `convert` is a
26
26
  * deterministic string → string transform.
27
+ *
28
+ * KNOWN LIMITATION — sibling .md files (audit batch H6, 2026-06-04):
29
+ * The Cursor install drops ONLY `skills/<name>/SKILL.md`. Sibling
30
+ * `.md` files living next to SKILL.md (e.g. `discover-procedure.md`,
31
+ * `explore-procedure.md`, `cache-policy.md`) are NOT enumerated by
32
+ * `runtime-artifact-layout.cjs#skillsKind` and therefore NOT installed.
33
+ * Source SKILL.md files reference siblings via relative paths
34
+ * (e.g. `./discover-procedure.md`); on Cursor those links resolve to
35
+ * nothing.
36
+ *
37
+ * This is a systemic limitation of the current `multi-artifact`
38
+ * pipeline, not a Cursor-specific bug — it affects every runtime that
39
+ * uses `skillsKind` (claude global, cursor, codex, copilot, antigravity,
40
+ * windsurf, augment, trae, qwen, codebuddy). Fix requires extending the
41
+ * StagedArtifact contract to emit multiple files per skill (one
42
+ * SKILL.md + N siblings), updating `computeDestPath`, the foreign-file
43
+ * detection in `detectMultiArtifactInstalled`, and the uninstall
44
+ * enumeration in `uninstallMultiArtifact`. Tracked as a follow-up
45
+ * beyond batch H6 scope. See `connections/cursor.md` for user-facing
46
+ * guidance.
27
47
  */
28
48
 
29
49
  const shared = require('./shared.cjs');
@@ -120,7 +120,7 @@ async function runReportFlow(args) {
120
120
  submitted: false,
121
121
  reason: 'disabled',
122
122
  surface: reason, // 'env' | 'config'
123
- message: `/gdd:report-issue is disabled by ${reasonMsg}. Run \`gsd-health\` to see the active disable surface.`,
123
+ message: `/gdd:report-issue is disabled by ${reasonMsg}. Run \`/gdd:health\` to see the active disable surface.`,
124
124
  };
125
125
  }
126
126
 
@@ -18,7 +18,10 @@
18
18
  "name": "apply-reflections",
19
19
  "description": "Review and selectively apply proposals from .design/reflections/<cycle-slug>.md. Diffs each proposal, prompts user to accept/skip/edit, then writes changes.",
20
20
  "argument_hint": "[--cycle <slug>] [--filter <FRONTMATTER|REFERENCE|BUDGET|QUESTION|GLOBAL-SKILL>] [--dry-run]",
21
- "tools": "Read, Write, Edit, Bash, Glob"
21
+ "tools": "Read, Write, Edit, Bash, Glob",
22
+ "composes_with": [
23
+ "audit"
24
+ ]
22
25
  },
23
26
  {
24
27
  "name": "audit",
@@ -50,6 +53,9 @@
50
53
  "description": "Stage 1 of 5 design intake that captures problem statement, audience, constraints, success metrics, and scope into .design/BRIEF.md, and bootstraps .design/STATE.md if missing. Use when starting a new design cycle and before {{command_prefix}}explore. Activates for requests involving capturing a problem statement, defining audience and constraints, or starting a new design brief.",
51
54
  "argument_hint": "[--re-brief to redo intake on existing project]",
52
55
  "tools": "Read, Write, AskUserQuestion, mcp__gdd_state__frontmatter_update, mcp__gdd_state__set_status, mcp__gdd_state__update_progress, mcp__gdd_state__get",
56
+ "composes_with": [
57
+ "explore"
58
+ ],
53
59
  "next_skills": [
54
60
  "explore"
55
61
  ]
@@ -63,7 +69,7 @@
63
69
  },
64
70
  {
65
71
  "name": "cache-manager",
66
- "description": "Maintains .design/cache-manifest.json for Layer B explicit cache per D-08. Computes deterministic SHA-256 input-hash from (agent-path + sorted-input-file-paths + input-content-hashes). On spawn: lookup key → return cached blob if within TTL, else miss. On completion: write result + TTL. Consulted by hooks/budget-enforcer.js before every Agent spawn.",
72
+ "description": "Maintains .design/cache-manifest.json for Layer B explicit cache per D-08. Computes deterministic SHA-256 input-hash from (agent-path + sorted-input-file-paths + input-content-hashes). On spawn: lookup key → return cached blob if within TTL, else miss. On completion: write result + TTL. Consulted by hooks/budget-enforcer.ts before every Agent spawn.",
67
73
  "user_invocable": false,
68
74
  "tools": "Read, Bash, Write",
69
75
  "disable_model_invocation": true
@@ -78,13 +84,19 @@
78
84
  "name": "compare",
79
85
  "description": "Compute the delta between the `DESIGN.md` baseline (from scan) and the `DESIGN-VERIFICATION.md` result (from verify), reporting per-category score delta, anti-pattern delta (resolved vs new), must-have pass/fail change, and design drift (regressions without covering tasks in `DESIGN-PLAN.md`). Use after `verify` to measure whether a design pipeline cycle actually improved the design. Writes `.design/COMPARE-REPORT.md`. Activates for requests involving diffing a design baseline against verification output, or a before-after design delta.",
80
86
  "argument_hint": "",
81
- "user_invocable": true
87
+ "user_invocable": true,
88
+ "composes_with": [
89
+ "verify"
90
+ ]
82
91
  },
83
92
  {
84
93
  "name": "complete-cycle",
85
94
  "description": "Cycle closeout command that marks CYCLES.md entry complete, archives pipeline artifacts to .design/archive/cycle-N/, generates EXPERIENCE.md, rebuilds the search index, and resets STATE.md. Use when a design cycle has shipped and you're ready to start the next one.",
86
95
  "argument_hint": "[<retrospective note>]",
87
- "tools": "Read, Write, Bash, AskUserQuestion"
96
+ "tools": "Read, Write, Bash, AskUserQuestion",
97
+ "composes_with": [
98
+ "audit"
99
+ ]
88
100
  },
89
101
  {
90
102
  "name": "connections",
@@ -112,7 +124,10 @@
112
124
  "name": "darkmode",
113
125
  "description": "Audit a project's dark mode implementation - detects architecture (CSS custom props, Tailwind `dark:` prefix, or JS class toggle), runs architecture-specific contrast / token-override / anti-pattern / meta-property checks, and writes a prioritized fix list to `.design/DARKMODE-AUDIT.md`. Use when the user wants to verify dark mode quality without re-running the full design pipeline. Read-only - no score writeback to `DESIGN.md`. Activates for requests involving auditing dark mode, checking dark-theme contrast, or dark-mode anti-patterns.",
114
126
  "argument_hint": "",
115
- "user_invocable": true
127
+ "user_invocable": true,
128
+ "composes_with": [
129
+ "audit"
130
+ ]
116
131
  },
117
132
  {
118
133
  "name": "debug",
@@ -127,6 +142,11 @@
127
142
  "argument_hint": "[--auto] [--parallel] [--variants N]",
128
143
  "user_invocable": true,
129
144
  "tools": "Read, Write, Bash, Grep, Glob, Task, AskUserQuestion, mcp__gdd_state__get, mcp__gdd_state__transition_stage, mcp__gdd_state__update_progress, mcp__gdd_state__set_status, mcp__gdd_state__add_blocker, mcp__gdd_state__resolve_blocker, mcp__gdd_state__checkpoint",
145
+ "composes_with": [
146
+ "figma-write",
147
+ "paper-write",
148
+ "pencil-write"
149
+ ],
130
150
  "next_skills": [
131
151
  "verify"
132
152
  ]
@@ -136,13 +156,19 @@
136
156
  "frontmatter_name": "discover",
137
157
  "description": "Stage 1.5 of 4 orchestrator that probes Figma / Refero / Pinterest connections, spawns design-context-builder (auto-detect + interview) and (via lazy gate) design-context-checker (6-dimension validator), producing .design/DESIGN-CONTEXT.md. Use after {{command_prefix}}scan when a fast-path context build is wanted instead of the full {{command_prefix}}explore. Activates for requests involving detecting an existing design system, inventorying tokens and components, or onboarding a brownfield repo.",
138
158
  "argument_hint": "[--auto] [--incremental] [--full]",
139
- "user_invocable": true
159
+ "user_invocable": true,
160
+ "composes_with": [
161
+ "explore"
162
+ ]
140
163
  },
141
164
  {
142
165
  "name": "discuss",
143
166
  "description": "Adaptive design interview command that spawns design-discussant in normal / --all / --spec mode to gather decisions via one-question-at-a-time AskUserQuestion, writing D-XX entries to STATE.md <decisions>. Use when locking design decisions outside the main pipeline or backfilling missing context.",
144
167
  "argument_hint": "[topic] [--all] [--spec] [--cycle <name>]",
145
- "tools": "Read, Write, Task"
168
+ "tools": "Read, Write, Task",
169
+ "composes_with": [
170
+ "list-assumptions"
171
+ ]
146
172
  },
147
173
  {
148
174
  "name": "do",
@@ -155,6 +181,11 @@
155
181
  "description": "Stage 2 of 5 - unified exploration merging inventory grep + design interview. Probes 6 connections, scans the codebase, conducts the AskUserQuestion interview, and writes .design/DESIGN.md + DESIGN-DEBT.md + DESIGN-CONTEXT.md. Use after {{command_prefix}}brief to map the existing system and lock decisions before planning. Activates for requests involving researching design direction, gathering references, or exploring visual options.",
156
182
  "argument_hint": "[--skip-interview] [--skip-scan] [--incremental] [--full]",
157
183
  "tools": "Read, Write, Bash, Grep, Glob, Task, AskUserQuestion, mcp__gdd_state__get, mcp__gdd_state__transition_stage, mcp__gdd_state__probe_connections, mcp__gdd_state__update_progress, mcp__gdd_state__set_status, mcp__gdd_state__add_blocker, mcp__gdd_state__checkpoint, mcp__gdd_state__add_decision",
184
+ "composes_with": [
185
+ "discuss",
186
+ "list-assumptions",
187
+ "sketch"
188
+ ],
158
189
  "next_skills": [
159
190
  "plan"
160
191
  ]
@@ -272,13 +303,19 @@
272
303
  "name": "new-cycle",
273
304
  "description": "Start a new design cycle. Creates cycle scope in STATE.md, initializes .design/CYCLES.md entry. Each cycle has its own goal and tracks its own decisions/tasks/pipeline runs.",
274
305
  "argument_hint": "[<goal>]",
275
- "tools": "Read, Write, AskUserQuestion"
306
+ "tools": "Read, Write, AskUserQuestion",
307
+ "composes_with": [
308
+ "brief"
309
+ ]
276
310
  },
277
311
  {
278
312
  "name": "new-project",
279
313
  "description": "Initialize a new get-design-done project. Gathers project context, creates PROJECT.md and STATE.md, initializes first cycle. Run once per project before any pipeline stage.",
280
314
  "argument_hint": "[--name <project-name>]",
281
315
  "tools": "Read, Write, AskUserQuestion, Bash, Glob",
316
+ "composes_with": [
317
+ "brief"
318
+ ],
282
319
  "next_skills": [
283
320
  "brief"
284
321
  ]
@@ -327,6 +364,20 @@
327
364
  "tools": "Read, Write, Bash, Grep, Glob",
328
365
  "registered_in_phase": "56"
329
366
  },
367
+ {
368
+ "name": "paper-write",
369
+ "description": "Push design decisions from `.design/DESIGN-CONTEXT.md` into the active paper.design canvas by dispatching the `design-paper-writer` agent in one of three modes (annotate / tokenize / roundtrip). Use when the user has completed a design pipeline cycle and wants the decisions reflected in their paper.design canvas. Operates proposal->confirm with `--dry-run`.",
370
+ "argument_hint": "<annotate|tokenize|roundtrip> [--dry-run]",
371
+ "user_invocable": true,
372
+ "tools": "Read, Write, Bash, Grep, Glob"
373
+ },
374
+ {
375
+ "name": "pencil-write",
376
+ "description": "Update local `.pen` source files with design decisions from `.design/DESIGN-CONTEXT.md` by dispatching the `design-pencil-writer` agent in one of two modes (annotate / roundtrip). Use when the user has completed a design pipeline cycle and wants the decisions reflected in their `.pen` files. Operates proposal->confirm with `--dry-run`.",
377
+ "argument_hint": "<annotate|roundtrip> [--dry-run]",
378
+ "user_invocable": true,
379
+ "tools": "Read, Write, Bash, Grep, Glob"
380
+ },
330
381
  {
331
382
  "name": "pause",
332
383
  "description": "Write a numbered checkpoint so work can resume in a new session without re-running completed stages.",
@@ -480,7 +531,7 @@
480
531
  },
481
532
  {
482
533
  "name": "router",
483
- "description": "Routes a /gdd command to fast|quick|full path + S|M|L|XL complexity_class and returns {path, complexity_class, model_tier_overrides, resolved_models, estimated_cost_usd, cache_hits}. Deterministic - no model call. Invoked once at command entry before any Agent spawn. Read by hooks/budget-enforcer.js.",
534
+ "description": "Routes a /gdd command to fast|quick|full path + S|M|L|XL complexity_class and returns {path, complexity_class, model_tier_overrides, resolved_models, estimated_cost_usd, cache_hits}. Deterministic - no model call. Invoked once at command entry before any Agent spawn. Read by hooks/budget-enforcer.ts.",
484
535
  "argument_hint": "<intent-string> [<target-artifacts-csv>]",
485
536
  "tools": "Read, Bash, Grep"
486
537
  },
@@ -489,7 +540,10 @@
489
540
  "frontmatter_name": "scan",
490
541
  "description": "Pre-pipeline initializer that maps an existing repo's design system (colors, typography, spacing, components, tokens), runs the anti-pattern audit, scores the 7 weighted categories, and writes DESIGN.md + .design/DESIGN-DEBT.md. Use when starting work in any new or existing repo before {{command_prefix}}discover. Activates for requests involving a fast read-only anti-pattern sweep, a quick design lint, or spotting slop without a full audit.",
491
542
  "argument_hint": "[--quick] [--full]",
492
- "user_invocable": true
543
+ "user_invocable": true,
544
+ "composes_with": [
545
+ "explore"
546
+ ]
493
547
  },
494
548
  {
495
549
  "name": "settings",
@@ -503,13 +557,19 @@
503
557
  "description": "Post-verify PR flow - creates a clean PR branch, invokes code review check, and prepares the PR for merge. Activates for requests involving finishing a cycle, packaging design output, or moving work to a pull request.",
504
558
  "argument_hint": "[--title <PR title>] [--draft]",
505
559
  "tools": "Read, Write, Bash, AskUserQuestion, Task",
506
- "disable_model_invocation": true
560
+ "disable_model_invocation": true,
561
+ "composes_with": [
562
+ "pr-branch"
563
+ ]
507
564
  },
508
565
  {
509
566
  "name": "sketch",
510
567
  "description": "Multi-variant HTML design exploration that creates .design/sketches/<slug>/ with N standalone variants (default 3), browser-openable directly via file:// without a build step. Use when answering 'what could this look like?' before committing to a direction.",
511
568
  "argument_hint": "[topic] [--variants N] [--quick]",
512
- "tools": "Read, Write, AskUserQuestion, Bash"
569
+ "tools": "Read, Write, AskUserQuestion, Bash",
570
+ "composes_with": [
571
+ "sketch-wrap-up"
572
+ ]
513
573
  },
514
574
  {
515
575
  "name": "sketch-wrap-up",
@@ -526,7 +586,10 @@
526
586
  "name": "spike",
527
587
  "description": "Timeboxed feasibility experiment that creates .design/spikes/<slug>/ with HYPOTHESIS.md, success/failure criteria, scratch/ subdirectory, and a default 60-minute timebox. Use when answering 'can this work?' before betting design or implementation effort on a risky approach.",
528
588
  "argument_hint": "[hypothesis] [--timebox <minutes>]",
529
- "tools": "Read, Write, Bash, AskUserQuestion"
589
+ "tools": "Read, Write, Bash, AskUserQuestion",
590
+ "composes_with": [
591
+ "spike-wrap-up"
592
+ ]
530
593
  },
531
594
  {
532
595
  "name": "spike-wrap-up",
@@ -631,6 +694,10 @@
631
694
  "argument_hint": "[--auto] [--post-handoff]",
632
695
  "user_invocable": true,
633
696
  "tools": "mcp__gdd_state__get, mcp__gdd_state__transition_stage, mcp__gdd_state__add_must_have, mcp__gdd_state__add_blocker, mcp__gdd_state__resolve_blocker, mcp__gdd_state__update_progress, mcp__gdd_state__set_status, mcp__gdd_state__checkpoint, mcp__gdd_state__probe_connections",
697
+ "composes_with": [
698
+ "audit",
699
+ "debug"
700
+ ],
634
701
  "next_skills": [
635
702
  "ship"
636
703
  ]
@@ -47,7 +47,7 @@ function findPackageRoot(startDir) {
47
47
  try { pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8')); } catch { pkg = null; }
48
48
  if (pkg) {
49
49
  if (firstWithPkg === null) firstWithPkg = dir;
50
- if (pkg.name === 'get-design-done') return dir;
50
+ if (pkg.name === '@hegemonart/get-design-done') return dir;
51
51
  }
52
52
  const parent = path.dirname(dir);
53
53
  if (parent === dir) break;
@@ -214,19 +214,24 @@ function buildDryRunDiff(ops) {
214
214
  * Migrate .design/STATE.md (and supplementary stores) into the SQLite database.
215
215
  *
216
216
  * @param {object} opts
217
- * @param {string} [opts.projectRoot] - project root dir (defaults to cwd / env)
218
- * @param {boolean} [opts.dryRun=false] - wrap writes in BEGIN/ROLLBACK + print diff
219
- * @param {boolean} [opts.force=false] - same as --migrate-state flag; required to actually write
217
+ * @param {string} [opts.projectRoot] - project root dir (defaults to cwd / env)
218
+ * @param {string} [opts.statePath] - explicit path to STATE.md (overrides projectRoot lookup)
219
+ * @param {boolean} [opts.dryRun=false] - wrap writes in BEGIN/ROLLBACK + print diff
220
+ * @param {boolean} [opts.force=false] - same as --migrate-state flag; required to actually write
221
+ * @param {boolean} [opts.upsertOnly=false] - re-parse markdown and UPSERT without wiping unrelated rows
222
+ * (used by the R8 freshness guard to fold hand-edits into SQLite)
220
223
  * @returns {Promise<{migrated:boolean, tables:object, dryRun:boolean, skipped:boolean, reason:string}>}
221
224
  */
222
225
  async function migrateToSqlite(opts = {}) {
223
- const { dryRun = false, force = false } = opts;
226
+ const { dryRun = false, force = false, upsertOnly = false } = opts;
227
+ // upsertOnly implies force (it's always an internal call, not user-facing opt-in).
228
+ const effectiveForce = force || upsertOnly;
224
229
  const projectRoot = resolveProjectRoot(opts.projectRoot);
225
230
 
226
231
  // Opt-in guard: --migrate-state / force required.
227
232
  // This fires first (before the SQLite probe) so the message is consistent
228
233
  // regardless of whether better-sqlite3 is installed.
229
- if (!force) {
234
+ if (!effectiveForce) {
230
235
  const notice =
231
236
  'Migration is opt-in in v1.57.0. Re-run with --migrate-state to proceed.';
232
237
  return {
@@ -254,7 +259,7 @@ async function migrateToSqlite(opts = {}) {
254
259
  }
255
260
 
256
261
  // Read STATE.md.
257
- const statePath = path.join(projectRoot, '.design', 'STATE.md');
262
+ const statePath = opts.statePath || path.join(projectRoot, '.design', 'STATE.md');
258
263
  if (!fs.existsSync(statePath)) {
259
264
  return {
260
265
  migrated: false,
@@ -440,9 +445,20 @@ async function migrateToSqlite(opts = {}) {
440
445
  );
441
446
  counts.decisions++;
442
447
  ops.push({ action: 'upsert', table: 'decisions', id: d.id, fields: { status: d.status, body_md: d.text, raw_line: rawLine } });
448
+ // BUG-05: populate FTS5 table so queryDecisions returns hits.
449
+ // FTS5 virtual tables do not support ON CONFLICT — use DELETE + INSERT pattern.
450
+ // Guard: if FTS5 tables are absent (no-fts5 build), skip without throwing.
451
+ try {
452
+ db.prepare('DELETE FROM decisions_fts WHERE id = ?').run(d.id);
453
+ db.prepare('INSERT INTO decisions_fts (id, body_md, tags) VALUES (?, ?, ?)').run(d.id, d.text, null);
454
+ } catch { /* FTS5 table absent - skip */ }
443
455
  }
444
456
 
445
457
  // --- blockers ---
458
+ // BUG-02: DELETE existing rows for this cycle_id before re-inserting to prevent duplication.
459
+ // The blockers table uses AUTOINCREMENT PK with no natural-key ON CONFLICT, so
460
+ // re-running migrate without this delete would DUPLICATE every blocker row.
461
+ db.prepare('DELETE FROM blockers WHERE cycle_id = ?').run(cycleId);
446
462
  for (let i = 0; i < blockers.length; i++) {
447
463
  const b = blockers[i];
448
464
  const rawLine = `[${b.stage}] [${b.date}]: ${b.text}`;