@hegemonart/get-design-done 1.51.0 → 1.53.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +96 -0
  4. package/README.md +4 -0
  5. package/SKILL.md +2 -0
  6. package/agents/a11y-mapper.md +30 -1
  7. package/agents/component-taxonomy-mapper.md +30 -1
  8. package/agents/design-context-reviewer-gate.md +102 -0
  9. package/agents/design-context-reviewer.md +186 -0
  10. package/agents/design-debt-crawler.md +60 -60
  11. package/agents/design-research-synthesizer.md +27 -1
  12. package/agents/motion-mapper.md +35 -13
  13. package/agents/token-mapper.md +30 -1
  14. package/agents/visual-hierarchy-mapper.md +30 -1
  15. package/dist/claude-code/.claude/skills/context/SKILL.md +137 -0
  16. package/dist/claude-code/.claude/skills/discover/SKILL.md +7 -1
  17. package/dist/claude-code/.claude/skills/explore/SKILL.md +3 -1
  18. package/dist/claude-code/.claude/skills/migrate-context/SKILL.md +123 -0
  19. package/dist/claude-code/.claude/skills/progress/SKILL.md +4 -0
  20. package/package.json +3 -2
  21. package/reference/design-context-schema.md +159 -0
  22. package/reference/design-context-tag-vocab.md +82 -0
  23. package/reference/registry.json +14 -0
  24. package/reference/schemas/design-context.schema.json +130 -0
  25. package/reference/schemas/mcp-gdd-tools.schema.json +34 -1
  26. package/reference/skill-graph.md +3 -1
  27. package/scripts/lib/design-context/extract-a11y.mjs +188 -0
  28. package/scripts/lib/design-context/extract-components.mjs +243 -0
  29. package/scripts/lib/design-context/extract-motion.mjs +248 -0
  30. package/scripts/lib/design-context/extract-tokens.mjs +234 -0
  31. package/scripts/lib/design-context/extract-visual-hierarchy.mjs +178 -0
  32. package/scripts/lib/design-context/integration-map.mjs +251 -0
  33. package/scripts/lib/design-context/merge-fragments.mjs +227 -0
  34. package/scripts/lib/design-context-query.cjs +0 -0
  35. package/scripts/lib/explore-parallel-runner/index.ts +58 -0
  36. package/scripts/lib/explore-parallel-runner/types.ts +58 -0
  37. package/scripts/lib/manifest/skills.json +18 -2
  38. package/scripts/lib/mappers/compute-batches.mjs +625 -0
  39. package/scripts/lib/mappers/graph-adjacency.mjs +129 -0
  40. package/scripts/lib/mappers/incremental-discover.cjs +617 -0
  41. package/scripts/lib/mappers/incremental-discover.d.cts +133 -0
  42. package/scripts/lib/mappers/neighbor-map.mjs +0 -0
  43. package/scripts/lib/mcp-tools-lint/index.cjs +3 -1
  44. package/sdk/cli/index.js +369 -2
  45. package/sdk/fingerprint/classify.cjs +406 -0
  46. package/sdk/fingerprint/index.ts +405 -0
  47. package/sdk/fingerprint/store.cjs +523 -0
  48. package/sdk/index.ts +1 -0
  49. package/sdk/mcp/gdd-mcp/schemas/gdd_context_query.schema.json +60 -0
  50. package/sdk/mcp/gdd-mcp/server.js +474 -158
  51. package/sdk/mcp/gdd-mcp/server.ts +9 -5
  52. package/sdk/mcp/gdd-mcp/tools/gdd_context_query.ts +35 -0
  53. package/sdk/mcp/gdd-mcp/tools/index.ts +18 -13
  54. package/skills/context/SKILL.md +137 -0
  55. package/skills/discover/SKILL.md +7 -1
  56. package/skills/explore/SKILL.md +3 -1
  57. package/skills/migrate-context/SKILL.md +123 -0
  58. package/skills/progress/SKILL.md +4 -0
@@ -10,8 +10,8 @@ var __commonJS = (cb, mod) => function __require() {
10
10
  return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
11
  };
12
12
  var __export = (target, all) => {
13
- for (var name13 in all)
14
- __defProp(target, name13, { get: all[name13], enumerable: true });
13
+ for (var name14 in all)
14
+ __defProp(target, name14, { get: all[name14], enumerable: true });
15
15
  };
16
16
  var __copyProps = (to, from, except, desc) => {
17
17
  if (from && typeof from === "object" || typeof from === "function") {
@@ -31,6 +31,282 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
31
31
  ));
32
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
33
 
34
+ // scripts/lib/design-context-query.cjs
35
+ var require_design_context_query = __commonJS({
36
+ "scripts/lib/design-context-query.cjs"(exports2, module2) {
37
+ "use strict";
38
+ var fs = require("fs");
39
+ var path = require("path");
40
+ var EXPECTED_NODE_TYPES = [
41
+ "token",
42
+ "component",
43
+ "variant",
44
+ "state",
45
+ "motion-fragment",
46
+ "a11y-pattern",
47
+ "screen",
48
+ "layer",
49
+ "pattern",
50
+ "anti-pattern"
51
+ ];
52
+ function load2(graphPath) {
53
+ const raw = fs.readFileSync(graphPath, "utf8");
54
+ return JSON.parse(raw);
55
+ }
56
+ function _nodes(graph) {
57
+ return Array.isArray(graph && graph.nodes) ? graph.nodes : [];
58
+ }
59
+ function _edges(graph) {
60
+ return Array.isArray(graph && graph.edges) ? graph.edges : [];
61
+ }
62
+ function nodes2(graph, opts = {}) {
63
+ const { type, tag } = opts;
64
+ return _nodes(graph).filter((n) => {
65
+ if (type !== void 0 && n.type !== type) return false;
66
+ if (tag !== void 0 && !(Array.isArray(n.tags) && n.tags.includes(tag))) return false;
67
+ return true;
68
+ });
69
+ }
70
+ function edges2(graph, opts = {}) {
71
+ const { type } = opts;
72
+ return _edges(graph).filter((e) => type === void 0 ? true : e.type === type);
73
+ }
74
+ function _adjacency(graph) {
75
+ const adj = /* @__PURE__ */ new Map();
76
+ const ensure = (id) => {
77
+ if (!adj.has(id)) adj.set(id, /* @__PURE__ */ new Set());
78
+ return adj.get(id);
79
+ };
80
+ for (const n of _nodes(graph)) {
81
+ if (n && typeof n.id === "string") ensure(n.id);
82
+ }
83
+ for (const e of _edges(graph)) {
84
+ if (!e || typeof e.source !== "string" || typeof e.target !== "string") continue;
85
+ const dir = e.direction;
86
+ if (dir === "forward" || dir === "bidirectional") ensure(e.source).add(e.target);
87
+ if (dir === "backward" || dir === "bidirectional") ensure(e.target).add(e.source);
88
+ }
89
+ return adj;
90
+ }
91
+ function pathBetween(graph, from, to) {
92
+ const adj = _adjacency(graph);
93
+ if (!adj.has(from) || !adj.has(to)) return null;
94
+ if (from === to) return [from];
95
+ const prev = /* @__PURE__ */ new Map([[from, null]]);
96
+ const queue = [from];
97
+ while (queue.length) {
98
+ const cur = queue.shift();
99
+ for (const next of adj.get(cur) || []) {
100
+ if (prev.has(next)) continue;
101
+ prev.set(next, cur);
102
+ if (next === to) {
103
+ const out = [];
104
+ for (let at = to; at !== null; at = prev.get(at)) out.unshift(at);
105
+ return out;
106
+ }
107
+ queue.push(next);
108
+ }
109
+ }
110
+ return null;
111
+ }
112
+ function consumersOf2(graph, id) {
113
+ const nodeById = new Map(_nodes(graph).filter((n) => n && typeof n.id === "string").map((n) => [n.id, n]));
114
+ const consumerIds = /* @__PURE__ */ new Set();
115
+ for (const e of _edges(graph)) {
116
+ if (!e || typeof e.source !== "string" || typeof e.target !== "string") continue;
117
+ const dir = e.direction;
118
+ if ((dir === "forward" || dir === "bidirectional") && e.target === id) consumerIds.add(e.source);
119
+ if ((dir === "backward" || dir === "bidirectional") && e.source === id) consumerIds.add(e.target);
120
+ }
121
+ consumerIds.delete(id);
122
+ return [...consumerIds].map((cid) => nodeById.get(cid)).filter(Boolean);
123
+ }
124
+ function unreachable2(graph) {
125
+ const incident = /* @__PURE__ */ new Set();
126
+ for (const e of _edges(graph)) {
127
+ if (!e) continue;
128
+ if (typeof e.source === "string") incident.add(e.source);
129
+ if (typeof e.target === "string") incident.add(e.target);
130
+ }
131
+ return _nodes(graph).filter((n) => n && typeof n.id === "string" && !incident.has(n.id)).map((n) => n.id);
132
+ }
133
+ function cycles2(graph) {
134
+ const adj = _adjacency(graph);
135
+ const WHITE = 0;
136
+ const GRAY = 1;
137
+ const BLACK = 2;
138
+ const color = new Map([...adj.keys()].map((id) => [id, WHITE]));
139
+ const stack = [];
140
+ const found = [];
141
+ const seen = /* @__PURE__ */ new Set();
142
+ const canonical = (cyc) => {
143
+ let min = 0;
144
+ for (let i = 1; i < cyc.length; i++) if (cyc[i] < cyc[min]) min = i;
145
+ return cyc.slice(min).concat(cyc.slice(0, min)).join("\0");
146
+ };
147
+ const visit = (node) => {
148
+ color.set(node, GRAY);
149
+ stack.push(node);
150
+ for (const next of adj.get(node) || []) {
151
+ if (color.get(next) === GRAY) {
152
+ const idx = stack.indexOf(next);
153
+ const cyc = stack.slice(idx);
154
+ const key = canonical(cyc);
155
+ if (!seen.has(key)) {
156
+ seen.add(key);
157
+ found.push(cyc.slice());
158
+ }
159
+ } else if (color.get(next) === WHITE) {
160
+ visit(next);
161
+ }
162
+ }
163
+ stack.pop();
164
+ color.set(node, BLACK);
165
+ };
166
+ for (const id of adj.keys()) if (color.get(id) === WHITE) visit(id);
167
+ return found;
168
+ }
169
+ function coverage2(graph) {
170
+ const present = new Set(_nodes(graph).map((n) => n && n.type).filter(Boolean));
171
+ const present_types = EXPECTED_NODE_TYPES.filter((t) => present.has(t));
172
+ const missing_types = EXPECTED_NODE_TYPES.filter((t) => !present.has(t));
173
+ const pct = Math.round(present_types.length / EXPECTED_NODE_TYPES.length * 100);
174
+ return { present_types, missing_types, pct };
175
+ }
176
+ function _parseFlags(argv) {
177
+ const flags = { json: false, file: null };
178
+ const rest = [];
179
+ for (let i = 0; i < argv.length; i++) {
180
+ const a = argv[i];
181
+ if (a === "--json") flags.json = true;
182
+ else if (a === "--file") flags.file = argv[++i];
183
+ else if (a.startsWith("--file=")) flags.file = a.slice("--file=".length);
184
+ else rest.push(a);
185
+ }
186
+ return { flags, rest };
187
+ }
188
+ function _printNodes(list, json, out) {
189
+ if (json) {
190
+ out.write(JSON.stringify(list, null, 2) + "\n");
191
+ return;
192
+ }
193
+ if (!list.length) {
194
+ out.write("(no matching nodes)\n");
195
+ return;
196
+ }
197
+ for (const n of list) out.write(`${n.id} ${n.type} ${n.name}
198
+ `);
199
+ }
200
+ function main(argv, io = {}) {
201
+ const out = io.stdout || process.stdout;
202
+ const err = io.stderr || process.stderr;
203
+ const { flags, rest } = _parseFlags(argv);
204
+ const cmd = rest[0];
205
+ const usage = "usage: design-context-query <nodes|edges|path|consumers-of|unreachable|cycles|coverage> [args] [--file PATH] [--json]";
206
+ if (!cmd) {
207
+ err.write(usage + "\n");
208
+ return 1;
209
+ }
210
+ const file = flags.file || path.join(process.cwd(), ".design", "context-graph.json");
211
+ let graph;
212
+ try {
213
+ graph = load2(file);
214
+ } catch (e) {
215
+ err.write(`design-context-query: cannot load ${file}: ${e.message}
216
+ `);
217
+ return 1;
218
+ }
219
+ switch (cmd) {
220
+ case "nodes": {
221
+ const typeIdx = rest.indexOf("--type");
222
+ const tagIdx = rest.indexOf("--tag");
223
+ const opts = {};
224
+ if (typeIdx !== -1) opts.type = rest[typeIdx + 1];
225
+ if (tagIdx !== -1) opts.tag = rest[tagIdx + 1];
226
+ _printNodes(nodes2(graph, opts), flags.json, out);
227
+ return 0;
228
+ }
229
+ case "edges": {
230
+ const typeIdx = rest.indexOf("--type");
231
+ const opts = {};
232
+ if (typeIdx !== -1) opts.type = rest[typeIdx + 1];
233
+ const list = edges2(graph, opts);
234
+ if (flags.json) out.write(JSON.stringify(list, null, 2) + "\n");
235
+ else if (!list.length) out.write("(no matching edges)\n");
236
+ else for (const e of list) out.write(`${e.source} ${e.type} ${e.target} ${e.direction} ${e.weight}
237
+ `);
238
+ return 0;
239
+ }
240
+ case "path": {
241
+ const [, from, to] = rest;
242
+ if (!from || !to) {
243
+ err.write("usage: path <from-id> <to-id>\n");
244
+ return 1;
245
+ }
246
+ const p = pathBetween(graph, from, to);
247
+ if (flags.json) out.write(JSON.stringify({ from, to, path: p }, null, 2) + "\n");
248
+ else out.write(p ? p.join(" -> ") + "\n" : `(no path from ${from} to ${to})
249
+ `);
250
+ return 0;
251
+ }
252
+ case "consumers-of": {
253
+ const [, id] = rest;
254
+ if (!id) {
255
+ err.write("usage: consumers-of <node-id>\n");
256
+ return 1;
257
+ }
258
+ _printNodes(consumersOf2(graph, id), flags.json, out);
259
+ return 0;
260
+ }
261
+ case "unreachable": {
262
+ const list = unreachable2(graph);
263
+ if (flags.json) out.write(JSON.stringify(list, null, 2) + "\n");
264
+ else out.write(list.length ? list.join("\n") + "\n" : "(no orphan nodes)\n");
265
+ return 0;
266
+ }
267
+ case "cycles": {
268
+ const list = cycles2(graph);
269
+ if (flags.json) out.write(JSON.stringify(list, null, 2) + "\n");
270
+ else if (!list.length) out.write("(no cycles)\n");
271
+ else for (const c of list) out.write(c.join(" -> ") + " -> " + c[0] + "\n");
272
+ return 0;
273
+ }
274
+ case "coverage": {
275
+ const c = coverage2(graph);
276
+ if (flags.json) out.write(JSON.stringify(c, null, 2) + "\n");
277
+ else {
278
+ out.write(`coverage: ${c.pct}% (${c.present_types.length}/${EXPECTED_NODE_TYPES.length} node types)
279
+ `);
280
+ out.write(`present: ${c.present_types.join(", ") || "(none)"}
281
+ `);
282
+ out.write(`missing: ${c.missing_types.join(", ") || "(none)"}
283
+ `);
284
+ }
285
+ return 0;
286
+ }
287
+ default:
288
+ err.write(`design-context-query: unknown command "${cmd}"
289
+ ${usage}
290
+ `);
291
+ return 1;
292
+ }
293
+ }
294
+ if (require.main === module2) process.exit(main(process.argv.slice(2)));
295
+ module2.exports = {
296
+ load: load2,
297
+ nodes: nodes2,
298
+ edges: edges2,
299
+ path: pathBetween,
300
+ consumersOf: consumersOf2,
301
+ unreachable: unreachable2,
302
+ cycles: cycles2,
303
+ coverage: coverage2,
304
+ main,
305
+ EXPECTED_NODE_TYPES
306
+ };
307
+ }
308
+ });
309
+
34
310
  // scripts/lib/snapshot-reader/index.cjs
35
311
  var require_snapshot_reader = __commonJS({
36
312
  "scripts/lib/snapshot-reader/index.cjs"(exports2, module2) {
@@ -52,10 +328,10 @@ var require_snapshot_reader = __commonJS({
52
328
  }
53
329
  const entries = await fs.promises.readdir(dir);
54
330
  const candidates = [];
55
- for (const name13 of entries) {
56
- if (!name13.endsWith(".json")) continue;
57
- if (name13 === "last-recap.json") continue;
58
- const full = path.join(dir, name13);
331
+ for (const name14 of entries) {
332
+ if (!name14.endsWith(".json")) continue;
333
+ if (name14 === "last-recap.json") continue;
334
+ const full = path.join(dir, name14);
59
335
  try {
60
336
  const stat = await fs.promises.stat(full);
61
337
  candidates.push({ full, mtime: stat.mtimeMs });
@@ -147,16 +423,16 @@ var require_loader = __commonJS({
147
423
  function reset() {
148
424
  _cache.clear();
149
425
  }
150
- function load(name13, opts) {
426
+ function load2(name14, opts) {
151
427
  const o = opts || {};
152
428
  const dir = o.dir || MANIFEST_DIR;
153
429
  const fallback = Object.prototype.hasOwnProperty.call(o, "fallback") ? o.fallback : {};
154
- const abs = path.join(dir, `${name13}.json`);
430
+ const abs = path.join(dir, `${name14}.json`);
155
431
  let stat;
156
432
  try {
157
433
  stat = fs.statSync(abs);
158
434
  } catch {
159
- if (!o.quiet) process.stderr.write(`manifest: ${name13}.json not found \u2014 using empty fallback (a consumer phase may not have shipped its data yet)
435
+ if (!o.quiet) process.stderr.write(`manifest: ${name14}.json not found \u2014 using empty fallback (a consumer phase may not have shipped its data yet)
160
436
  `);
161
437
  return fallback;
162
438
  }
@@ -167,12 +443,12 @@ var require_loader = __commonJS({
167
443
  _cache.set(abs, { mtimeMs: stat.mtimeMs, data });
168
444
  return data;
169
445
  } catch (e) {
170
- if (!o.quiet) process.stderr.write(`manifest: ${name13}.json parse error (${e.message}) \u2014 using empty fallback
446
+ if (!o.quiet) process.stderr.write(`manifest: ${name14}.json parse error (${e.message}) \u2014 using empty fallback
171
447
  `);
172
448
  return fallback;
173
449
  }
174
450
  }
175
- module2.exports = { load, reset, MANIFEST_DIR };
451
+ module2.exports = { load: load2, reset, MANIFEST_DIR };
176
452
  }
177
453
  });
178
454
 
@@ -300,12 +576,12 @@ var require_health_mirror = __commonJS({
300
576
  try {
301
577
  const body = await fs.promises.readFile(p, "utf8");
302
578
  const parsed = JSON.parse(body);
303
- const name13 = typeof parsed.name === "string" ? parsed.name : "(unknown)";
579
+ const name14 = typeof parsed.name === "string" ? parsed.name : "(unknown)";
304
580
  const version = typeof parsed.version === "string" ? parsed.version : "0.0.0";
305
581
  checks.push({
306
582
  name: "package_json",
307
583
  status: "ok",
308
- detail: name13 + "@" + version
584
+ detail: name14 + "@" + version
309
585
  });
310
586
  } catch (err) {
311
587
  checks.push({
@@ -484,9 +760,9 @@ var require_intel_store = __commonJS({
484
760
  }
485
761
  const entries = fs.readdirSync(dir);
486
762
  const ids = [];
487
- for (const name13 of entries) {
488
- if (!name13.endsWith(".json")) continue;
489
- ids.push(name13.slice(0, -".json".length));
763
+ for (const name14 of entries) {
764
+ if (!name14.endsWith(".json")) continue;
765
+ ids.push(name14.slice(0, -".json".length));
490
766
  }
491
767
  return ids;
492
768
  }
@@ -512,22 +788,22 @@ var require_reflections_reader = __commonJS({
512
788
  async function listReflectionFiles(dir) {
513
789
  const entries = await fs.promises.readdir(dir);
514
790
  const candidates = [];
515
- for (const name13 of entries) {
516
- if (!name13.endsWith(".md")) continue;
517
- const full = path.join(dir, name13);
791
+ for (const name14 of entries) {
792
+ if (!name14.endsWith(".md")) continue;
793
+ const full = path.join(dir, name14);
518
794
  try {
519
795
  const stat = await fs.promises.stat(full);
520
- candidates.push({ name: name13, full, mtime: stat.mtimeMs });
796
+ candidates.push({ name: name14, full, mtime: stat.mtimeMs });
521
797
  } catch {
522
798
  }
523
799
  }
524
800
  candidates.sort((a, b) => b.mtime - a.mtime);
525
801
  return candidates;
526
802
  }
527
- function extractCycle(name13) {
528
- const m = name13.match(/cycle[-_]?[\w.]+/i);
803
+ function extractCycle(name14) {
804
+ const m = name14.match(/cycle[-_]?[\w.]+/i);
529
805
  if (m) return m[0];
530
- return name13.replace(/\.md$/, "");
806
+ return name14.replace(/\.md$/, "");
531
807
  }
532
808
  async function readLatestReflection2(rootDir) {
533
809
  const dir = path.join(rootDir, ".design", "reflections");
@@ -604,12 +880,12 @@ var require_roadmap_reader = __commonJS({
604
880
  let h;
605
881
  while ((h = headingRe.exec(md)) !== null) {
606
882
  const number = h[1];
607
- let name13 = h[2].trim();
608
- name13 = name13.replace(/\s+\([^)]*\)\s*$/g, "").trim();
609
- const inlineVer = name13.match(/\s+—\s+(v\d+\.\d+(?:\.\d+)?)/);
883
+ let name14 = h[2].trim();
884
+ name14 = name14.replace(/\s+\([^)]*\)\s*$/g, "").trim();
885
+ const inlineVer = name14.match(/\s+—\s+(v\d+\.\d+(?:\.\d+)?)/);
610
886
  let version = inlineVer ? inlineVer[1] : "";
611
887
  if (inlineVer) {
612
- name13 = name13.slice(0, inlineVer.index).trim();
888
+ name14 = name14.slice(0, inlineVer.index).trim();
613
889
  }
614
890
  if (version === "") {
615
891
  const after = md.slice(h.index, h.index + 2e3);
@@ -618,7 +894,7 @@ var require_roadmap_reader = __commonJS({
618
894
  }
619
895
  phases.push({
620
896
  number,
621
- name: name13,
897
+ name: name14,
622
898
  version,
623
899
  checkbox_status: statusMap.get(number) ?? "unknown"
624
900
  });
@@ -763,16 +1039,99 @@ function toToolError(err) {
763
1039
  return out;
764
1040
  }
765
1041
 
766
- // sdk/mcp/gdd-mcp/tools/gdd_cycle_recap.ts
767
- var gdd_cycle_recap_exports = {};
768
- __export(gdd_cycle_recap_exports, {
1042
+ // sdk/mcp/gdd-mcp/tools/gdd_context_query.ts
1043
+ var gdd_context_query_exports = {};
1044
+ __export(gdd_context_query_exports, {
769
1045
  handle: () => handle,
770
1046
  name: () => name,
771
1047
  schemaPath: () => schemaPath
772
1048
  });
1049
+ var import_design_context_query = __toESM(require_design_context_query());
773
1050
 
774
- // sdk/state/index.ts
1051
+ // sdk/mcp/gdd-mcp/tools/shared.ts
775
1052
  var import_node_fs = require("node:fs");
1053
+ var import_node_path = require("node:path");
1054
+ function okResponse(data) {
1055
+ return { success: true, data };
1056
+ }
1057
+ function errorResponse(err) {
1058
+ const payload = toToolError(err);
1059
+ if (typeof err === "object" && err !== null && "code" in err && err.code === "directory_not_found") {
1060
+ const error = { ...payload.error, mcp_code: "directory_not_found" };
1061
+ return { success: false, error };
1062
+ }
1063
+ return { success: false, error: payload.error };
1064
+ }
1065
+ function resolveStatePath() {
1066
+ const override = process.env["GDD_STATE_PATH"];
1067
+ if (typeof override === "string" && override.length > 0) {
1068
+ return override;
1069
+ }
1070
+ return (0, import_node_path.join)(resolveProjectRoot(), ".design", "STATE.md");
1071
+ }
1072
+ function resolveTelemetryDir() {
1073
+ return (0, import_node_path.join)(resolveProjectRoot(), ".design", "telemetry");
1074
+ }
1075
+ function resolveProjectRoot(startCwd = process.cwd()) {
1076
+ const override = process.env["GDD_PROJECT_ROOT"];
1077
+ if (typeof override === "string" && override.length > 0) {
1078
+ return (0, import_node_path.resolve)(override);
1079
+ }
1080
+ let dir = (0, import_node_path.resolve)(startCwd);
1081
+ while (true) {
1082
+ if ((0, import_node_fs.existsSync)((0, import_node_path.join)(dir, ".design")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(dir, ".planning")) || (0, import_node_fs.existsSync)((0, import_node_path.join)(dir, ".claude-plugin", "plugin.json"))) {
1083
+ return dir;
1084
+ }
1085
+ const parent = (0, import_node_path.dirname)(dir);
1086
+ if (parent === dir) {
1087
+ throw new Error(
1088
+ `gdd project root not found: walked up to ${dir} from ${startCwd}`
1089
+ );
1090
+ }
1091
+ dir = parent;
1092
+ }
1093
+ }
1094
+
1095
+ // sdk/mcp/gdd-mcp/tools/gdd_context_query.ts
1096
+ var name = "gdd_context_query";
1097
+ var schemaPath = "../schemas/gdd_context_query.schema.json";
1098
+ async function handle(input) {
1099
+ try {
1100
+ const t = input ?? {};
1101
+ let graph = null;
1102
+ const ops = {
1103
+ nodes: () => (0, import_design_context_query.nodes)(graph, { type: t.type, tag: t.tag }),
1104
+ edges: () => (0, import_design_context_query.edges)(graph, { type: t.type }),
1105
+ path: () => (0, import_design_context_query.path)(graph, t.from, t.to),
1106
+ "consumers-of": () => (0, import_design_context_query.consumersOf)(graph, t.id),
1107
+ unreachable: () => (0, import_design_context_query.unreachable)(graph),
1108
+ cycles: () => (0, import_design_context_query.cycles)(graph),
1109
+ coverage: () => (0, import_design_context_query.coverage)(graph)
1110
+ };
1111
+ const fn = t.op ? ops[t.op] : void 0;
1112
+ if (!fn) return errorResponse(new Error("op is required \u2014 one of: " + Object.keys(ops).join(", ")));
1113
+ try {
1114
+ graph = (0, import_design_context_query.load)(resolveProjectRoot() + "/.design/context-graph.json");
1115
+ } catch {
1116
+ graph = null;
1117
+ }
1118
+ if (!graph) return okResponse({ op: t.op, graph_present: false, result: null });
1119
+ return okResponse({ op: t.op, graph_present: true, result: fn() });
1120
+ } catch (err) {
1121
+ return errorResponse(err);
1122
+ }
1123
+ }
1124
+
1125
+ // sdk/mcp/gdd-mcp/tools/gdd_cycle_recap.ts
1126
+ var gdd_cycle_recap_exports = {};
1127
+ __export(gdd_cycle_recap_exports, {
1128
+ handle: () => handle2,
1129
+ name: () => name2,
1130
+ schemaPath: () => schemaPath2
1131
+ });
1132
+
1133
+ // sdk/state/index.ts
1134
+ var import_node_fs2 = require("node:fs");
776
1135
 
777
1136
  // sdk/state/types.ts
778
1137
  function isConnectionStatus(value) {
@@ -843,29 +1202,29 @@ function parse(raw) {
843
1202
  const line = lines[i] ?? "";
844
1203
  const openMatch = line.match(blockOpen);
845
1204
  if (!openMatch) continue;
846
- const name13 = openMatch[1];
847
- if (!BLOCK_ORDER.includes(name13)) {
1205
+ const name14 = openMatch[1];
1206
+ if (!BLOCK_ORDER.includes(name14)) {
848
1207
  continue;
849
1208
  }
850
- if (seen.has(name13)) {
851
- throw new ParseError(`duplicate block <${name13}>`, lineToFileLine(afterFm, normalized, i));
1209
+ if (seen.has(name14)) {
1210
+ throw new ParseError(`duplicate block <${name14}>`, lineToFileLine(afterFm, normalized, i));
852
1211
  }
853
1212
  let close = -1;
854
1213
  for (let j = i + 1; j < lines.length; j++) {
855
1214
  const cm = (lines[j] ?? "").match(blockClose);
856
- if (cm && cm[1] === name13) {
1215
+ if (cm && cm[1] === name14) {
857
1216
  close = j;
858
1217
  break;
859
1218
  }
860
1219
  }
861
1220
  if (close === -1) {
862
1221
  throw new ParseError(
863
- `unterminated block <${name13}> (no </${name13}>)`,
1222
+ `unterminated block <${name14}> (no </${name14}>)`,
864
1223
  lineToFileLine(afterFm, normalized, i)
865
1224
  );
866
1225
  }
867
- blocks.push({ name: name13, openLine: i, closeLine: close });
868
- seen.add(name13);
1226
+ blocks.push({ name: name14, openLine: i, closeLine: close });
1227
+ seen.add(name14);
869
1228
  i = close;
870
1229
  }
871
1230
  let body_preamble;
@@ -1475,66 +1834,20 @@ var GATES = Object.freeze({
1475
1834
 
1476
1835
  // sdk/state/index.ts
1477
1836
  async function read(path) {
1478
- const raw = (0, import_node_fs.readFileSync)(path, "utf8");
1837
+ const raw = (0, import_node_fs2.readFileSync)(path, "utf8");
1479
1838
  return parse(raw).state;
1480
1839
  }
1481
1840
 
1482
1841
  // sdk/mcp/gdd-mcp/tools/gdd_cycle_recap.ts
1483
1842
  var import_snapshot_reader = __toESM(require_snapshot_reader());
1484
-
1485
- // sdk/mcp/gdd-mcp/tools/shared.ts
1486
- var import_node_fs2 = require("node:fs");
1487
- var import_node_path = require("node:path");
1488
- function okResponse(data) {
1489
- return { success: true, data };
1490
- }
1491
- function errorResponse(err) {
1492
- const payload = toToolError(err);
1493
- if (typeof err === "object" && err !== null && "code" in err && err.code === "directory_not_found") {
1494
- const error = { ...payload.error, mcp_code: "directory_not_found" };
1495
- return { success: false, error };
1496
- }
1497
- return { success: false, error: payload.error };
1498
- }
1499
- function resolveStatePath() {
1500
- const override = process.env["GDD_STATE_PATH"];
1501
- if (typeof override === "string" && override.length > 0) {
1502
- return override;
1503
- }
1504
- return (0, import_node_path.join)(resolveProjectRoot(), ".design", "STATE.md");
1505
- }
1506
- function resolveTelemetryDir() {
1507
- return (0, import_node_path.join)(resolveProjectRoot(), ".design", "telemetry");
1508
- }
1509
- function resolveProjectRoot(startCwd = process.cwd()) {
1510
- const override = process.env["GDD_PROJECT_ROOT"];
1511
- if (typeof override === "string" && override.length > 0) {
1512
- return (0, import_node_path.resolve)(override);
1513
- }
1514
- let dir = (0, import_node_path.resolve)(startCwd);
1515
- while (true) {
1516
- if ((0, import_node_fs2.existsSync)((0, import_node_path.join)(dir, ".design")) || (0, import_node_fs2.existsSync)((0, import_node_path.join)(dir, ".planning")) || (0, import_node_fs2.existsSync)((0, import_node_path.join)(dir, ".claude-plugin", "plugin.json"))) {
1517
- return dir;
1518
- }
1519
- const parent = (0, import_node_path.dirname)(dir);
1520
- if (parent === dir) {
1521
- throw new Error(
1522
- `gdd project root not found: walked up to ${dir} from ${startCwd}`
1523
- );
1524
- }
1525
- dir = parent;
1526
- }
1527
- }
1528
-
1529
- // sdk/mcp/gdd-mcp/tools/gdd_cycle_recap.ts
1530
- var name = "gdd_cycle_recap";
1531
- var schemaPath = "../schemas/gdd_cycle_recap.schema.json";
1843
+ var name2 = "gdd_cycle_recap";
1844
+ var schemaPath2 = "../schemas/gdd_cycle_recap.schema.json";
1532
1845
  function snapCount(snap, key, fallback) {
1533
1846
  if (typeof snap[key] === "number") return snap[key];
1534
1847
  const arr = snap[fallback];
1535
1848
  return Array.isArray(arr) ? arr.length : 0;
1536
1849
  }
1537
- async function handle(_input) {
1850
+ async function handle2(_input) {
1538
1851
  try {
1539
1852
  const snap = await (0, import_snapshot_reader.readLatestSnapshot)(resolveProjectRoot());
1540
1853
  const state = await read(resolveStatePath());
@@ -1557,13 +1870,13 @@ async function handle(_input) {
1557
1870
  // sdk/mcp/gdd-mcp/tools/gdd_decisions_list.ts
1558
1871
  var gdd_decisions_list_exports = {};
1559
1872
  __export(gdd_decisions_list_exports, {
1560
- handle: () => handle2,
1561
- name: () => name2,
1562
- schemaPath: () => schemaPath2
1873
+ handle: () => handle3,
1874
+ name: () => name3,
1875
+ schemaPath: () => schemaPath3
1563
1876
  });
1564
- var name2 = "gdd_decisions_list";
1565
- var schemaPath2 = "../schemas/gdd_decisions_list.schema.json";
1566
- async function handle2(input) {
1877
+ var name3 = "gdd_decisions_list";
1878
+ var schemaPath3 = "../schemas/gdd_decisions_list.schema.json";
1879
+ async function handle3(input) {
1567
1880
  try {
1568
1881
  const typed = input ?? {};
1569
1882
  const state = await read(resolveStatePath());
@@ -1580,9 +1893,9 @@ async function handle2(input) {
1580
1893
  // sdk/mcp/gdd-mcp/tools/gdd_events_tail.ts
1581
1894
  var gdd_events_tail_exports = {};
1582
1895
  __export(gdd_events_tail_exports, {
1583
- handle: () => handle3,
1584
- name: () => name3,
1585
- schemaPath: () => schemaPath3
1896
+ handle: () => handle4,
1897
+ name: () => name4,
1898
+ schemaPath: () => schemaPath4
1586
1899
  });
1587
1900
 
1588
1901
  // sdk/event-stream/writer.ts
@@ -1663,9 +1976,9 @@ async function* readEvents(opts = {}) {
1663
1976
  }
1664
1977
 
1665
1978
  // sdk/mcp/gdd-mcp/tools/gdd_events_tail.ts
1666
- var name3 = "gdd_events_tail";
1667
- var schemaPath3 = "../schemas/gdd_events_tail.schema.json";
1668
- async function handle3(input) {
1979
+ var name4 = "gdd_events_tail";
1980
+ var schemaPath4 = "../schemas/gdd_events_tail.schema.json";
1981
+ async function handle4(input) {
1669
1982
  try {
1670
1983
  const typed = input ?? {};
1671
1984
  const limit = typeof typed.limit === "number" && typed.limit > 0 ? typed.limit : 50;
@@ -1685,14 +1998,14 @@ async function handle3(input) {
1685
1998
  // sdk/mcp/gdd-mcp/tools/gdd_health.ts
1686
1999
  var gdd_health_exports = {};
1687
2000
  __export(gdd_health_exports, {
1688
- handle: () => handle4,
1689
- name: () => name4,
1690
- schemaPath: () => schemaPath4
2001
+ handle: () => handle5,
2002
+ name: () => name5,
2003
+ schemaPath: () => schemaPath5
1691
2004
  });
1692
2005
  var import_health_mirror = __toESM(require_health_mirror());
1693
- var name4 = "gdd_health";
1694
- var schemaPath4 = "../schemas/gdd_health.schema.json";
1695
- async function handle4(_input) {
2006
+ var name5 = "gdd_health";
2007
+ var schemaPath5 = "../schemas/gdd_health.schema.json";
2008
+ async function handle5(_input) {
1696
2009
  try {
1697
2010
  const result = await (0, import_health_mirror.getHealthChecks)(resolveProjectRoot());
1698
2011
  return okResponse({ checks: result.checks });
@@ -1704,14 +2017,14 @@ async function handle4(_input) {
1704
2017
  // sdk/mcp/gdd-mcp/tools/gdd_intel_get.ts
1705
2018
  var gdd_intel_get_exports = {};
1706
2019
  __export(gdd_intel_get_exports, {
1707
- handle: () => handle5,
1708
- name: () => name5,
1709
- schemaPath: () => schemaPath5
2020
+ handle: () => handle6,
2021
+ name: () => name6,
2022
+ schemaPath: () => schemaPath6
1710
2023
  });
1711
2024
  var import_intel_store = __toESM(require_intel_store());
1712
- var name5 = "gdd_intel_get";
1713
- var schemaPath5 = "../schemas/gdd_intel_get.schema.json";
1714
- async function handle5(input) {
2025
+ var name6 = "gdd_intel_get";
2026
+ var schemaPath6 = "../schemas/gdd_intel_get.schema.json";
2027
+ async function handle6(input) {
1715
2028
  try {
1716
2029
  const typed = input ?? {};
1717
2030
  if (typeof typed.slice_id !== "string" || typed.slice_id.length === 0) {
@@ -1733,14 +2046,14 @@ async function handle5(input) {
1733
2046
  // sdk/mcp/gdd-mcp/tools/gdd_learnings_digest.ts
1734
2047
  var gdd_learnings_digest_exports = {};
1735
2048
  __export(gdd_learnings_digest_exports, {
1736
- handle: () => handle6,
1737
- name: () => name6,
1738
- schemaPath: () => schemaPath6
2049
+ handle: () => handle7,
2050
+ name: () => name7,
2051
+ schemaPath: () => schemaPath7
1739
2052
  });
1740
2053
  var import_reflections_reader = __toESM(require_reflections_reader());
1741
- var name6 = "gdd_learnings_digest";
1742
- var schemaPath6 = "../schemas/gdd_learnings_digest.schema.json";
1743
- async function handle6(input) {
2054
+ var name7 = "gdd_learnings_digest";
2055
+ var schemaPath7 = "../schemas/gdd_learnings_digest.schema.json";
2056
+ async function handle7(input) {
1744
2057
  try {
1745
2058
  const typed = input ?? {};
1746
2059
  const n = typeof typed.cycles === "number" && typed.cycles > 0 ? typed.cycles : 5;
@@ -1754,13 +2067,13 @@ async function handle6(input) {
1754
2067
  // sdk/mcp/gdd-mcp/tools/gdd_phase_current.ts
1755
2068
  var gdd_phase_current_exports = {};
1756
2069
  __export(gdd_phase_current_exports, {
1757
- handle: () => handle7,
1758
- name: () => name7,
1759
- schemaPath: () => schemaPath7
2070
+ handle: () => handle8,
2071
+ name: () => name8,
2072
+ schemaPath: () => schemaPath8
1760
2073
  });
1761
- var name7 = "gdd_phase_current";
1762
- var schemaPath7 = "../schemas/gdd_phase_current.schema.json";
1763
- async function handle7(_input) {
2074
+ var name8 = "gdd_phase_current";
2075
+ var schemaPath8 = "../schemas/gdd_phase_current.schema.json";
2076
+ async function handle8(_input) {
1764
2077
  try {
1765
2078
  const state = await read(resolveStatePath());
1766
2079
  const p = state.position;
@@ -1778,14 +2091,14 @@ async function handle7(_input) {
1778
2091
  // sdk/mcp/gdd-mcp/tools/gdd_phases_list.ts
1779
2092
  var gdd_phases_list_exports = {};
1780
2093
  __export(gdd_phases_list_exports, {
1781
- handle: () => handle8,
1782
- name: () => name8,
1783
- schemaPath: () => schemaPath8
2094
+ handle: () => handle9,
2095
+ name: () => name9,
2096
+ schemaPath: () => schemaPath9
1784
2097
  });
1785
2098
  var import_roadmap_reader = __toESM(require_roadmap_reader());
1786
- var name8 = "gdd_phases_list";
1787
- var schemaPath8 = "../schemas/gdd_phases_list.schema.json";
1788
- async function handle8(_input) {
2099
+ var name9 = "gdd_phases_list";
2100
+ var schemaPath9 = "../schemas/gdd_phases_list.schema.json";
2101
+ async function handle9(_input) {
1789
2102
  try {
1790
2103
  const md = await (0, import_roadmap_reader.readRoadmapMd)(resolveProjectRoot());
1791
2104
  return okResponse({ phases: (0, import_roadmap_reader.parsePhases)(md) });
@@ -1797,13 +2110,13 @@ async function handle8(_input) {
1797
2110
  // sdk/mcp/gdd-mcp/tools/gdd_plans_list.ts
1798
2111
  var gdd_plans_list_exports = {};
1799
2112
  __export(gdd_plans_list_exports, {
1800
- handle: () => handle9,
1801
- name: () => name9,
1802
- schemaPath: () => schemaPath9
2113
+ handle: () => handle10,
2114
+ name: () => name10,
2115
+ schemaPath: () => schemaPath10
1803
2116
  });
1804
- var name9 = "gdd_plans_list";
1805
- var schemaPath9 = "../schemas/gdd_plans_list.schema.json";
1806
- async function handle9(input) {
2117
+ var name10 = "gdd_plans_list";
2118
+ var schemaPath10 = "../schemas/gdd_plans_list.schema.json";
2119
+ async function handle10(input) {
1807
2120
  try {
1808
2121
  const typed = input ?? {};
1809
2122
  const state = await read(resolveStatePath());
@@ -1824,14 +2137,14 @@ async function handle9(input) {
1824
2137
  // sdk/mcp/gdd-mcp/tools/gdd_reflections_latest.ts
1825
2138
  var gdd_reflections_latest_exports = {};
1826
2139
  __export(gdd_reflections_latest_exports, {
1827
- handle: () => handle10,
1828
- name: () => name10,
1829
- schemaPath: () => schemaPath10
2140
+ handle: () => handle11,
2141
+ name: () => name11,
2142
+ schemaPath: () => schemaPath11
1830
2143
  });
1831
2144
  var import_reflections_reader2 = __toESM(require_reflections_reader());
1832
- var name10 = "gdd_reflections_latest";
1833
- var schemaPath10 = "../schemas/gdd_reflections_latest.schema.json";
1834
- async function handle10(_input) {
2145
+ var name11 = "gdd_reflections_latest";
2146
+ var schemaPath11 = "../schemas/gdd_reflections_latest.schema.json";
2147
+ async function handle11(_input) {
1835
2148
  try {
1836
2149
  const r = await (0, import_reflections_reader2.readLatestReflection)(resolveProjectRoot());
1837
2150
  if (r === null) return okResponse({ cycle: null, path: null, content_excerpt: "" });
@@ -1848,13 +2161,13 @@ async function handle10(_input) {
1848
2161
  // sdk/mcp/gdd-mcp/tools/gdd_status.ts
1849
2162
  var gdd_status_exports = {};
1850
2163
  __export(gdd_status_exports, {
1851
- handle: () => handle11,
1852
- name: () => name11,
1853
- schemaPath: () => schemaPath11
2164
+ handle: () => handle12,
2165
+ name: () => name12,
2166
+ schemaPath: () => schemaPath12
1854
2167
  });
1855
- var name11 = "gdd_status";
1856
- var schemaPath11 = "../schemas/gdd_status.schema.json";
1857
- async function handle11(_input) {
2168
+ var name12 = "gdd_status";
2169
+ var schemaPath12 = "../schemas/gdd_status.schema.json";
2170
+ async function handle12(_input) {
1858
2171
  try {
1859
2172
  const state = await read(resolveStatePath());
1860
2173
  const completed = (state.must_haves ?? []).filter((m) => m.status === "pass");
@@ -1873,13 +2186,13 @@ async function handle11(_input) {
1873
2186
  // sdk/mcp/gdd-mcp/tools/gdd_telemetry_query.ts
1874
2187
  var gdd_telemetry_query_exports = {};
1875
2188
  __export(gdd_telemetry_query_exports, {
1876
- handle: () => handle12,
1877
- name: () => name12,
1878
- schemaPath: () => schemaPath12
2189
+ handle: () => handle13,
2190
+ name: () => name13,
2191
+ schemaPath: () => schemaPath13
1879
2192
  });
1880
- var name12 = "gdd_telemetry_query";
1881
- var schemaPath12 = "../schemas/gdd_telemetry_query.schema.json";
1882
- async function handle12(input) {
2193
+ var name13 = "gdd_telemetry_query";
2194
+ var schemaPath13 = "../schemas/gdd_telemetry_query.schema.json";
2195
+ async function handle13(input) {
1883
2196
  try {
1884
2197
  const typed = input ?? {};
1885
2198
  const limit = typeof typed.limit === "number" && typed.limit > 0 ? typed.limit : 100;
@@ -1900,6 +2213,7 @@ async function handle12(input) {
1900
2213
  // sdk/mcp/gdd-mcp/tools/index.ts
1901
2214
  var TOOL_MODULES = [
1902
2215
  gdd_status_exports,
2216
+ gdd_context_query_exports,
1903
2217
  gdd_cycle_recap_exports,
1904
2218
  gdd_decisions_list_exports,
1905
2219
  gdd_events_tail_exports,
@@ -1913,9 +2227,9 @@ var TOOL_MODULES = [
1913
2227
  gdd_telemetry_query_exports
1914
2228
  ];
1915
2229
  var TOOL_COUNT = TOOL_MODULES.length;
1916
- if (TOOL_COUNT > 12) {
2230
+ if (TOOL_COUNT > 13) {
1917
2231
  throw new Error(
1918
- `gdd-mcp: TOOL_COUNT=${TOOL_COUNT} exceeds the 12-tool cap (D-03). Add tool past 12 requires re-scoping in a new plan.`
2232
+ `gdd-mcp: TOOL_COUNT=${TOOL_COUNT} exceeds the 13-tool cap (D-03, raised from 12 in Phase 52). Adding a tool past 13 requires re-scoping in a new plan.`
1919
2233
  );
1920
2234
  }
1921
2235
 
@@ -1951,6 +2265,7 @@ function loadTools() {
1951
2265
  }
1952
2266
  var TOOL_DESCRIPTIONS = {
1953
2267
  gdd_status: "gdd_status: current cycle phase, branch, last-3 decisions, last-3 completed plans, blocker count.",
2268
+ gdd_context_query: "gdd_context_query: read-only query over the DesignContext graph (.design/context-graph.json) \u2014 op one of nodes/edges/path/consumers-of/unreachable/cycles/coverage; structured no-graph result when absent.",
1954
2269
  gdd_phase_current: "gdd_phase_current: STATE.md <position> block (phase, stage, task_progress, status).",
1955
2270
  gdd_phases_list: "gdd_phases_list: parsed ROADMAP.md overview (phase number, name, target version, shipped/planned).",
1956
2271
  gdd_plans_list: "gdd_plans_list: plans tracked in STATE.md must_haves (optionally filtered by input.phase).",
@@ -1965,6 +2280,7 @@ var TOOL_DESCRIPTIONS = {
1965
2280
  };
1966
2281
  var TOOL_READONLY = {
1967
2282
  gdd_status: true,
2283
+ gdd_context_query: true,
1968
2284
  gdd_phase_current: true,
1969
2285
  gdd_phases_list: true,
1970
2286
  gdd_plans_list: true,