@hegemonart/get-design-done 1.31.0 → 1.32.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 (180) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +75 -0
  4. package/NOTICE +262 -0
  5. package/README.md +13 -1
  6. package/SKILL.md +4 -0
  7. package/agents/design-authority-watcher.md +1 -1
  8. package/agents/perf-analyzer.md +2 -2
  9. package/bin/gdd-mcp +78 -0
  10. package/bin/gdd-sdk +34 -24
  11. package/bin/gdd-state-mcp +78 -0
  12. package/{README.de.md → docs/i18n/README.de.md} +1 -1
  13. package/{README.fr.md → docs/i18n/README.fr.md} +1 -1
  14. package/{README.it.md → docs/i18n/README.it.md} +1 -1
  15. package/{README.ja.md → docs/i18n/README.ja.md} +1 -1
  16. package/{README.ko.md → docs/i18n/README.ko.md} +1 -1
  17. package/{README.zh-CN.md → docs/i18n/README.zh-CN.md} +1 -1
  18. package/hooks/_hook-emit.js +1 -1
  19. package/hooks/budget-enforcer.ts +5 -5
  20. package/hooks/context-exhaustion.ts +2 -2
  21. package/hooks/gdd-precompact-snapshot.js +3 -3
  22. package/hooks/gdd-read-injection-scanner.ts +2 -2
  23. package/hooks/gdd-sessionstart-recap.js +1 -1
  24. package/hooks/gdd-turn-closeout.js +1 -1
  25. package/hooks/hooks.json +9 -0
  26. package/hooks/inject-using-gdd.sh +72 -0
  27. package/hooks/run-hook.cmd +35 -0
  28. package/package.json +20 -9
  29. package/recipes/.gitkeep +0 -0
  30. package/reference/schemas/events.schema.json +63 -1
  31. package/reference/schemas/recipe.schema.json +33 -0
  32. package/scripts/cli/gdd-events.mjs +5 -5
  33. package/scripts/lib/cache/gdd-cache-manager.cjs +1 -1
  34. package/scripts/lib/cli/index.ts +22 -160
  35. package/scripts/lib/connection-probe/index.cjs +1 -1
  36. package/scripts/lib/discuss-parallel-runner/aggregator.ts +1 -1
  37. package/scripts/lib/discuss-parallel-runner/index.ts +1 -1
  38. package/scripts/lib/error-classifier.cjs +24 -227
  39. package/scripts/lib/event-stream/index.ts +25 -193
  40. package/scripts/lib/gdd-errors/index.ts +24 -213
  41. package/scripts/lib/gdd-state/index.ts +23 -161
  42. package/scripts/lib/health-mirror/index.cjs +79 -1
  43. package/scripts/lib/iteration-budget.cjs +23 -199
  44. package/scripts/lib/jittered-backoff.cjs +24 -107
  45. package/scripts/lib/lockfile.cjs +23 -195
  46. package/scripts/lib/logger/index.ts +1 -1
  47. package/scripts/lib/parallelism-engine/concurrency-tuner.cjs +1 -1
  48. package/scripts/lib/perf-analyzer/index.cjs +1 -1
  49. package/scripts/lib/pipeline-runner/index.ts +4 -4
  50. package/scripts/lib/pipeline-runner/state-machine.ts +1 -1
  51. package/scripts/lib/prompt-dedup/index.cjs +1 -1
  52. package/scripts/lib/rate-guard.cjs +2 -2
  53. package/scripts/lib/recipe-loader.cjs +142 -0
  54. package/scripts/lib/session-runner/errors.ts +3 -3
  55. package/scripts/lib/session-runner/index.ts +3 -3
  56. package/scripts/lib/session-runner/transcript.ts +1 -1
  57. package/scripts/lib/tool-scoping/index.ts +1 -1
  58. package/scripts/mcp-servers/gdd-mcp/server.ts +29 -311
  59. package/scripts/mcp-servers/gdd-state/server.ts +28 -282
  60. package/sdk/README.md +45 -0
  61. package/{scripts/lib → sdk}/cli/commands/audit.ts +3 -3
  62. package/{scripts/lib → sdk}/cli/commands/init.ts +3 -3
  63. package/{scripts/lib → sdk}/cli/commands/query.ts +4 -4
  64. package/{scripts/lib → sdk}/cli/commands/run.ts +5 -5
  65. package/{scripts/lib → sdk}/cli/commands/stage.ts +5 -5
  66. package/sdk/cli/index.js +8091 -0
  67. package/sdk/cli/index.ts +172 -0
  68. package/{scripts/lib → sdk}/cli/parse-args.ts +2 -2
  69. package/{scripts/lib/gdd-errors → sdk/errors}/classification.ts +1 -1
  70. package/sdk/errors/index.ts +218 -0
  71. package/{scripts/lib → sdk}/event-stream/emitter.ts +1 -1
  72. package/sdk/event-stream/index.ts +197 -0
  73. package/{scripts/lib → sdk}/event-stream/reader.ts +1 -1
  74. package/{scripts/lib → sdk}/event-stream/types.ts +2 -2
  75. package/{scripts/lib → sdk}/event-stream/writer.ts +1 -1
  76. package/sdk/index.ts +19 -0
  77. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/README.md +3 -3
  78. package/sdk/mcp/gdd-mcp/server.js +1966 -0
  79. package/sdk/mcp/gdd-mcp/server.ts +325 -0
  80. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_cycle_recap.ts +3 -3
  81. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_decisions_list.ts +2 -2
  82. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_events_tail.ts +3 -3
  83. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_health.ts +2 -2
  84. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_intel_get.ts +2 -2
  85. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_learnings_digest.ts +2 -2
  86. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_phase_current.ts +2 -2
  87. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_phases_list.ts +2 -2
  88. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_plans_list.ts +2 -2
  89. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_reflections_latest.ts +2 -2
  90. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_status.ts +3 -3
  91. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/gdd_telemetry_query.ts +3 -3
  92. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/index.ts +2 -2
  93. package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/tools/shared.ts +3 -3
  94. package/sdk/mcp/gdd-state/server.js +2790 -0
  95. package/sdk/mcp/gdd-state/server.ts +294 -0
  96. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/add_blocker.ts +3 -3
  97. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/add_decision.ts +3 -3
  98. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/add_must_have.ts +3 -3
  99. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/checkpoint.ts +2 -2
  100. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/frontmatter_update.ts +2 -2
  101. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/get.ts +3 -3
  102. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/index.ts +1 -1
  103. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/probe_connections.ts +3 -3
  104. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/resolve_blocker.ts +3 -3
  105. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/set_status.ts +2 -2
  106. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/shared.ts +8 -8
  107. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/transition_stage.ts +4 -4
  108. package/{scripts/mcp-servers → sdk/mcp}/gdd-state/tools/update_progress.ts +2 -2
  109. package/sdk/primitives/error-classifier.cjs +232 -0
  110. package/sdk/primitives/iteration-budget.cjs +205 -0
  111. package/sdk/primitives/jittered-backoff.cjs +112 -0
  112. package/sdk/primitives/lockfile.cjs +201 -0
  113. package/{scripts/lib/gdd-state → sdk/state}/gates.ts +1 -1
  114. package/sdk/state/index.ts +167 -0
  115. package/{scripts/lib/gdd-state → sdk/state}/lockfile.ts +1 -1
  116. package/{scripts/lib/gdd-state → sdk/state}/mutator.ts +1 -1
  117. package/{scripts/lib/gdd-state → sdk/state}/parser.ts +1 -1
  118. package/{scripts/lib/gdd-state → sdk/state}/types.ts +4 -4
  119. package/skills/audit/SKILL.md +13 -0
  120. package/skills/brief/SKILL.md +25 -0
  121. package/skills/design/SKILL.md +17 -0
  122. package/skills/discuss/SKILL.md +13 -0
  123. package/skills/explore/SKILL.md +17 -0
  124. package/skills/health/SKILL.md +6 -0
  125. package/skills/plan/SKILL.md +25 -0
  126. package/skills/quality-gate/SKILL.md +2 -2
  127. package/skills/router/SKILL.md +4 -0
  128. package/skills/router/router-pick-emitter.md +78 -0
  129. package/skills/using-gdd/SKILL.md +78 -0
  130. package/skills/verify/SKILL.md +17 -0
  131. package/scripts/aggregate-agent-metrics.ts +0 -282
  132. package/scripts/bootstrap-manifest.txt +0 -3
  133. package/scripts/bootstrap.sh +0 -80
  134. package/scripts/build-distribution-bundles.cjs +0 -549
  135. package/scripts/build-intel.cjs +0 -486
  136. package/scripts/codegen-schema-types.ts +0 -149
  137. package/scripts/detect-stale-refs.cjs +0 -107
  138. package/scripts/e2e/run-headless.ts +0 -514
  139. package/scripts/extract-changelog-section.cjs +0 -58
  140. package/scripts/gsd-cleanup-incubator.cjs +0 -367
  141. package/scripts/injection-patterns.cjs +0 -58
  142. package/scripts/lint-agentskills-spec.cjs +0 -457
  143. package/scripts/release-smoke-test.cjs +0 -200
  144. package/scripts/rollback-release.sh +0 -42
  145. package/scripts/run-injection-scanner-ci.cjs +0 -83
  146. package/scripts/tests/test-authority-rejected-kinds.sh +0 -58
  147. package/scripts/tests/test-authority-watcher-diff.sh +0 -113
  148. package/scripts/tests/test-motion-provenance.sh +0 -64
  149. package/scripts/validate-frontmatter.ts +0 -409
  150. package/scripts/validate-incubator-scope.cjs +0 -133
  151. package/scripts/validate-schemas.ts +0 -401
  152. package/scripts/validate-skill-length.cjs +0 -283
  153. package/scripts/verify-version-sync.cjs +0 -30
  154. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_cycle_recap.schema.json +0 -0
  155. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_decisions_list.schema.json +0 -0
  156. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_events_tail.schema.json +0 -0
  157. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_health.schema.json +0 -0
  158. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_intel_get.schema.json +0 -0
  159. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_learnings_digest.schema.json +0 -0
  160. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_phase_current.schema.json +0 -0
  161. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_phases_list.schema.json +0 -0
  162. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_plans_list.schema.json +0 -0
  163. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_reflections_latest.schema.json +0 -0
  164. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_status.schema.json +0 -0
  165. /package/{scripts/mcp-servers → sdk/mcp}/gdd-mcp/schemas/gdd_telemetry_query.schema.json +0 -0
  166. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/add_blocker.schema.json +0 -0
  167. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/add_decision.schema.json +0 -0
  168. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/add_must_have.schema.json +0 -0
  169. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/checkpoint.schema.json +0 -0
  170. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/frontmatter_update.schema.json +0 -0
  171. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/get.schema.json +0 -0
  172. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/probe_connections.schema.json +0 -0
  173. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/resolve_blocker.schema.json +0 -0
  174. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/set_status.schema.json +0 -0
  175. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/transition_stage.schema.json +0 -0
  176. /package/{scripts/mcp-servers → sdk/mcp}/gdd-state/schemas/update_progress.schema.json +0 -0
  177. /package/{scripts/lib → sdk/primitives}/error-classifier.d.cts +0 -0
  178. /package/{scripts/lib → sdk/primitives}/iteration-budget.d.cts +0 -0
  179. /package/{scripts/lib → sdk/primitives}/jittered-backoff.d.cts +0 -0
  180. /package/{scripts/lib → sdk/primitives}/lockfile.d.cts +0 -0
@@ -0,0 +1,1966 @@
1
+ #!/usr/bin/env -S node --experimental-strip-types
2
+ "use strict";
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __commonJS = (cb, mod) => function __require() {
10
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name13 in all)
14
+ __defProp(target, name13, { get: all[name13], enumerable: true });
15
+ };
16
+ var __copyProps = (to, from, except, desc) => {
17
+ if (from && typeof from === "object" || typeof from === "function") {
18
+ for (let key of __getOwnPropNames(from))
19
+ if (!__hasOwnProp.call(to, key) && key !== except)
20
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ }
22
+ return to;
23
+ };
24
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
25
+ // If the importer is in node compatibility mode or this is not an ESM
26
+ // file that has been converted to a CommonJS file using a Babel-
27
+ // compatible transform (i.e. "__esModule" has not been set), then set
28
+ // "default" to the CommonJS "module.exports" for node compatibility.
29
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
30
+ mod
31
+ ));
32
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
33
+
34
+ // scripts/lib/snapshot-reader/index.cjs
35
+ var require_snapshot_reader = __commonJS({
36
+ "scripts/lib/snapshot-reader/index.cjs"(exports2, module2) {
37
+ "use strict";
38
+ var fs = require("node:fs");
39
+ var path = require("node:path");
40
+ var SnapshotNotFoundError = class extends Error {
41
+ constructor(dir) {
42
+ super("source directory not found: " + dir);
43
+ this.name = "SnapshotNotFoundError";
44
+ this.code = "directory_not_found";
45
+ this.dir = dir;
46
+ }
47
+ };
48
+ async function readLatestSnapshot2(rootDir) {
49
+ const dir = path.join(rootDir, ".design", "snapshots");
50
+ if (!fs.existsSync(dir)) {
51
+ throw new SnapshotNotFoundError(dir);
52
+ }
53
+ const entries = await fs.promises.readdir(dir);
54
+ 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);
59
+ try {
60
+ const stat = await fs.promises.stat(full);
61
+ candidates.push({ full, mtime: stat.mtimeMs });
62
+ } catch {
63
+ }
64
+ }
65
+ if (candidates.length === 0) return null;
66
+ candidates.sort((a, b) => b.mtime - a.mtime);
67
+ const winner = candidates[0];
68
+ const body = await fs.promises.readFile(winner.full, "utf8");
69
+ let snapshot;
70
+ try {
71
+ snapshot = JSON.parse(body);
72
+ } catch (err) {
73
+ throw new Error(
74
+ "snapshot parse failed: " + winner.full + ": " + (err && err.message ? err.message : String(err))
75
+ );
76
+ }
77
+ const since = typeof snapshot.timestamp === "string" && snapshot.timestamp.length > 0 ? snapshot.timestamp : new Date(winner.mtime).toISOString();
78
+ return { since, snapshot };
79
+ }
80
+ module2.exports = { readLatestSnapshot: readLatestSnapshot2, SnapshotNotFoundError };
81
+ }
82
+ });
83
+
84
+ // scripts/lib/issue-reporter/kill-switch.cjs
85
+ var require_kill_switch = __commonJS({
86
+ "scripts/lib/issue-reporter/kill-switch.cjs"(exports2, module2) {
87
+ "use strict";
88
+ var fs = require("node:fs");
89
+ var path = require("node:path");
90
+ var ENV_KEY = "GDD_DISABLE_ISSUE_REPORTER";
91
+ var CONFIG_RELATIVE_PATH = path.join(".design", "config.json");
92
+ var CONFIG_FLAG_KEY = "issue_reporter";
93
+ function readConfigFlag(cwd) {
94
+ const configPath = path.join(cwd, CONFIG_RELATIVE_PATH);
95
+ let raw;
96
+ try {
97
+ raw = fs.readFileSync(configPath, "utf8");
98
+ } catch {
99
+ return null;
100
+ }
101
+ let parsed;
102
+ try {
103
+ parsed = JSON.parse(raw);
104
+ } catch {
105
+ return null;
106
+ }
107
+ if (parsed == null || typeof parsed !== "object") {
108
+ return null;
109
+ }
110
+ const value = parsed[CONFIG_FLAG_KEY];
111
+ if (typeof value === "boolean") {
112
+ return value;
113
+ }
114
+ return null;
115
+ }
116
+ function isDisabled(opts) {
117
+ const o = opts || {};
118
+ const cwd = o.cwd || process.cwd();
119
+ const env = o.env || process.env;
120
+ if (env[ENV_KEY] === "1") return true;
121
+ if (readConfigFlag(cwd) === false) return true;
122
+ return false;
123
+ }
124
+ function getDisableReason(opts) {
125
+ const o = opts || {};
126
+ const cwd = o.cwd || process.cwd();
127
+ const env = o.env || process.env;
128
+ if (env[ENV_KEY] === "1") return "env";
129
+ if (readConfigFlag(cwd) === false) return "config";
130
+ return null;
131
+ }
132
+ module2.exports = {
133
+ isDisabled,
134
+ getDisableReason
135
+ };
136
+ }
137
+ });
138
+
139
+ // scripts/lib/health-mirror/index.cjs
140
+ var require_health_mirror = __commonJS({
141
+ "scripts/lib/health-mirror/index.cjs"(exports2, module2) {
142
+ "use strict";
143
+ var fs = require("node:fs");
144
+ var path = require("node:path");
145
+ var { getDisableReason } = require_kill_switch();
146
+ function fileExists(p) {
147
+ try {
148
+ return fs.statSync(p).isFile();
149
+ } catch {
150
+ return false;
151
+ }
152
+ }
153
+ function dirExists(p) {
154
+ try {
155
+ return fs.statSync(p).isDirectory();
156
+ } catch {
157
+ return false;
158
+ }
159
+ }
160
+ async function getHealthChecks2(rootDir) {
161
+ const checks = [];
162
+ {
163
+ const p = path.join(rootDir, "CLAUDE.md");
164
+ const present = fileExists(p);
165
+ checks.push({
166
+ name: "claude_md",
167
+ status: present ? "ok" : "warn",
168
+ detail: present ? p : "CLAUDE.md not found at project root"
169
+ });
170
+ }
171
+ {
172
+ const p = path.join(rootDir, ".planning");
173
+ const present = dirExists(p);
174
+ checks.push({
175
+ name: "planning_dir",
176
+ status: present ? "ok" : "warn",
177
+ detail: present ? p : ".planning/ not found at project root"
178
+ });
179
+ }
180
+ {
181
+ const p = path.join(rootDir, ".design");
182
+ const present = dirExists(p);
183
+ checks.push({
184
+ name: "design_dir",
185
+ status: present ? "ok" : "warn",
186
+ detail: present ? p : ".design/ not found at project root"
187
+ });
188
+ }
189
+ {
190
+ const p = path.join(rootDir, "package.json");
191
+ if (!fileExists(p)) {
192
+ checks.push({
193
+ name: "package_json",
194
+ status: "warn",
195
+ detail: "package.json not found at project root"
196
+ });
197
+ } else {
198
+ try {
199
+ const body = await fs.promises.readFile(p, "utf8");
200
+ const parsed = JSON.parse(body);
201
+ const name13 = typeof parsed.name === "string" ? parsed.name : "(unknown)";
202
+ const version = typeof parsed.version === "string" ? parsed.version : "0.0.0";
203
+ checks.push({
204
+ name: "package_json",
205
+ status: "ok",
206
+ detail: name13 + "@" + version
207
+ });
208
+ } catch (err) {
209
+ checks.push({
210
+ name: "package_json",
211
+ status: "fail",
212
+ detail: "parse error: " + (err && err.message ? err.message : String(err))
213
+ });
214
+ }
215
+ }
216
+ }
217
+ {
218
+ let reason = null;
219
+ try {
220
+ reason = getDisableReason({ cwd: rootDir, env: process.env });
221
+ } catch {
222
+ reason = null;
223
+ }
224
+ let detail;
225
+ if (reason === "env") {
226
+ detail = "issue reporter: disabled by env (GDD_DISABLE_ISSUE_REPORTER=1)";
227
+ } else if (reason === "config") {
228
+ detail = "issue reporter: disabled by config (.design/config.json: issue_reporter=false)";
229
+ } else {
230
+ detail = "issue reporter: enabled";
231
+ }
232
+ checks.push({
233
+ name: "issue_reporter",
234
+ status: "ok",
235
+ detail
236
+ });
237
+ }
238
+ {
239
+ const tokenSet = !!(process.env.FIGMA_TOKEN || process.env.FIGMA_PERSONAL_ACCESS_TOKEN);
240
+ let detail;
241
+ let status;
242
+ if (!tokenSet) {
243
+ detail = "figma extract: token missing";
244
+ status = "warn";
245
+ } else if (figmaVariablesBlockedLocally(rootDir)) {
246
+ detail = "figma extract: plugin sync needed for variables (Free tier detected)";
247
+ status = "warn";
248
+ } else {
249
+ detail = "figma extract: ready (token set)";
250
+ status = "ok";
251
+ }
252
+ checks.push({ name: "figma_extract", status, detail });
253
+ }
254
+ {
255
+ const skillPresent = fileExists(
256
+ path.join(rootDir, "skills", "using-gdd", "SKILL.md")
257
+ );
258
+ const hookWired = skillPresent && sessionStartWiresInject(rootDir);
259
+ let detail;
260
+ let status;
261
+ if (!skillPresent) {
262
+ detail = "skill-discipline: missing using-gdd";
263
+ status = "warn";
264
+ } else if (!hookWired) {
265
+ detail = "skill-discipline: hook not wired";
266
+ status = "warn";
267
+ } else {
268
+ detail = "skill-discipline: ready";
269
+ status = "ok";
270
+ }
271
+ checks.push({ name: "skill_discipline", status, detail });
272
+ }
273
+ return { checks };
274
+ }
275
+ function sessionStartWiresInject(rootDir) {
276
+ try {
277
+ const p = path.join(rootDir, "hooks", "hooks.json");
278
+ let hooks;
279
+ try {
280
+ hooks = JSON.parse(fs.readFileSync(p, "utf8"));
281
+ } catch {
282
+ return false;
283
+ }
284
+ const sessionStart = hooks && hooks.hooks && Array.isArray(hooks.hooks.SessionStart) ? hooks.hooks.SessionStart : [];
285
+ for (const entry of sessionStart) {
286
+ const inner = entry && Array.isArray(entry.hooks) ? entry.hooks : [];
287
+ for (const h of inner) {
288
+ if (h && typeof h.command === "string" && /inject-using-gdd/.test(h.command)) {
289
+ return true;
290
+ }
291
+ }
292
+ }
293
+ return false;
294
+ } catch {
295
+ return false;
296
+ }
297
+ }
298
+ function figmaVariablesBlockedLocally(rootDir) {
299
+ try {
300
+ const rawRoot = path.join(rootDir, ".figma-extract-cache", "raw");
301
+ let entries;
302
+ try {
303
+ entries = fs.readdirSync(rawRoot, { withFileTypes: true });
304
+ } catch {
305
+ return false;
306
+ }
307
+ for (const ent of entries) {
308
+ if (!ent.isDirectory()) continue;
309
+ const metaPath = path.join(rawRoot, ent.name, "_meta.json");
310
+ let meta;
311
+ try {
312
+ meta = JSON.parse(fs.readFileSync(metaPath, "utf8"));
313
+ } catch {
314
+ continue;
315
+ }
316
+ const totals = meta && Array.isArray(meta.totals) ? meta.totals : [];
317
+ const blocked = totals.some(
318
+ (t) => t && t.name === "variables" && t.skipped === true && typeof t.reason === "string" && /403/.test(t.reason)
319
+ );
320
+ if (blocked) return true;
321
+ }
322
+ return false;
323
+ } catch {
324
+ return false;
325
+ }
326
+ }
327
+ module2.exports = { getHealthChecks: getHealthChecks2 };
328
+ }
329
+ });
330
+
331
+ // scripts/lib/intel-store/index.cjs
332
+ var require_intel_store = __commonJS({
333
+ "scripts/lib/intel-store/index.cjs"(exports2, module2) {
334
+ "use strict";
335
+ var fs = require("node:fs");
336
+ var path = require("node:path");
337
+ var IntelNotFoundError = class extends Error {
338
+ constructor(dir) {
339
+ super("source directory not found: " + dir);
340
+ this.name = "IntelNotFoundError";
341
+ this.code = "directory_not_found";
342
+ this.dir = dir;
343
+ }
344
+ };
345
+ async function readSlice2(rootDir, sliceId) {
346
+ const dir = path.join(rootDir, ".design", "intel");
347
+ if (!fs.existsSync(dir)) {
348
+ throw new IntelNotFoundError(dir);
349
+ }
350
+ const file = path.join(dir, sliceId + ".json");
351
+ if (!fs.existsSync(file)) return null;
352
+ const body = await fs.promises.readFile(file, "utf8");
353
+ return JSON.parse(body);
354
+ }
355
+ function listSlices(rootDir) {
356
+ const dir = path.join(rootDir, ".design", "intel");
357
+ if (!fs.existsSync(dir)) {
358
+ throw new IntelNotFoundError(dir);
359
+ }
360
+ const entries = fs.readdirSync(dir);
361
+ const ids = [];
362
+ for (const name13 of entries) {
363
+ if (!name13.endsWith(".json")) continue;
364
+ ids.push(name13.slice(0, -".json".length));
365
+ }
366
+ return ids;
367
+ }
368
+ module2.exports = { readSlice: readSlice2, listSlices, IntelNotFoundError };
369
+ }
370
+ });
371
+
372
+ // scripts/lib/reflections-reader/index.cjs
373
+ var require_reflections_reader = __commonJS({
374
+ "scripts/lib/reflections-reader/index.cjs"(exports2, module2) {
375
+ "use strict";
376
+ var fs = require("node:fs");
377
+ var path = require("node:path");
378
+ var DIGEST_CAP_BYTES = 5120;
379
+ var ReflectionsNotFoundError = class extends Error {
380
+ constructor(dir) {
381
+ super("source directory not found: " + dir);
382
+ this.name = "ReflectionsNotFoundError";
383
+ this.code = "directory_not_found";
384
+ this.dir = dir;
385
+ }
386
+ };
387
+ async function listReflectionFiles(dir) {
388
+ const entries = await fs.promises.readdir(dir);
389
+ const candidates = [];
390
+ for (const name13 of entries) {
391
+ if (!name13.endsWith(".md")) continue;
392
+ const full = path.join(dir, name13);
393
+ try {
394
+ const stat = await fs.promises.stat(full);
395
+ candidates.push({ name: name13, full, mtime: stat.mtimeMs });
396
+ } catch {
397
+ }
398
+ }
399
+ candidates.sort((a, b) => b.mtime - a.mtime);
400
+ return candidates;
401
+ }
402
+ function extractCycle(name13) {
403
+ const m = name13.match(/cycle[-_]?[\w.]+/i);
404
+ if (m) return m[0];
405
+ return name13.replace(/\.md$/, "");
406
+ }
407
+ async function readLatestReflection2(rootDir) {
408
+ const dir = path.join(rootDir, ".design", "reflections");
409
+ if (!fs.existsSync(dir)) {
410
+ throw new ReflectionsNotFoundError(dir);
411
+ }
412
+ const files = await listReflectionFiles(dir);
413
+ if (files.length === 0) return null;
414
+ const f = files[0];
415
+ const content = await fs.promises.readFile(f.full, "utf8");
416
+ return { cycle: extractCycle(f.name), path: f.full, content };
417
+ }
418
+ async function readNReflections2(rootDir, n) {
419
+ const dir = path.join(rootDir, ".design", "reflections");
420
+ if (!fs.existsSync(dir)) {
421
+ throw new ReflectionsNotFoundError(dir);
422
+ }
423
+ const files = await listReflectionFiles(dir);
424
+ const take = Math.max(0, Math.min(n, files.length));
425
+ const out = [];
426
+ for (let i = 0; i < take; i++) {
427
+ const f = files[i];
428
+ const content = await fs.promises.readFile(f.full, "utf8");
429
+ out.push({ cycle: extractCycle(f.name), path: f.full, content });
430
+ }
431
+ return out;
432
+ }
433
+ function digestReflections2(reflections) {
434
+ const parts = [];
435
+ for (const r of reflections) {
436
+ let body = r.content;
437
+ if (body.startsWith("---")) {
438
+ const closing = body.indexOf("\n---", 3);
439
+ if (closing !== -1) body = body.slice(closing + 4).trim();
440
+ }
441
+ const excerpt = body.slice(0, 300).trim();
442
+ parts.push("[" + r.cycle + "] " + excerpt);
443
+ }
444
+ let joined = parts.join("\n---\n");
445
+ if (joined.length > DIGEST_CAP_BYTES) {
446
+ joined = joined.slice(0, DIGEST_CAP_BYTES);
447
+ }
448
+ return joined;
449
+ }
450
+ module2.exports = {
451
+ readLatestReflection: readLatestReflection2,
452
+ readNReflections: readNReflections2,
453
+ digestReflections: digestReflections2,
454
+ ReflectionsNotFoundError
455
+ };
456
+ }
457
+ });
458
+
459
+ // scripts/lib/roadmap-reader/index.cjs
460
+ var require_roadmap_reader = __commonJS({
461
+ "scripts/lib/roadmap-reader/index.cjs"(exports2, module2) {
462
+ "use strict";
463
+ var fs = require("node:fs");
464
+ var path = require("node:path");
465
+ async function readRoadmapMd2(rootDir) {
466
+ const p = path.join(rootDir, ".planning", "ROADMAP.md");
467
+ return fs.promises.readFile(p, "utf8");
468
+ }
469
+ function parsePhases2(md) {
470
+ const statusMap = /* @__PURE__ */ new Map();
471
+ const overviewRe = /^-\s+\[([x\s])\]\s+\[Phase\s+(\S+?)\]/gm;
472
+ let mm;
473
+ while ((mm = overviewRe.exec(md)) !== null) {
474
+ const checked = mm[1] === "x";
475
+ statusMap.set(mm[2], checked ? "shipped" : "planned");
476
+ }
477
+ const headingRe = /^###\s+Phase\s+(\S+?):\s+([^\n]+?)$/gm;
478
+ const phases = [];
479
+ let h;
480
+ while ((h = headingRe.exec(md)) !== null) {
481
+ const number = h[1];
482
+ let name13 = h[2].trim();
483
+ name13 = name13.replace(/\s+\([^)]*\)\s*$/g, "").trim();
484
+ const inlineVer = name13.match(/\s+—\s+(v\d+\.\d+(?:\.\d+)?)/);
485
+ let version = inlineVer ? inlineVer[1] : "";
486
+ if (inlineVer) {
487
+ name13 = name13.slice(0, inlineVer.index).trim();
488
+ }
489
+ if (version === "") {
490
+ const after = md.slice(h.index, h.index + 2e3);
491
+ const v = after.match(/\*\*Target version\*\*:\s*(v\d+\.\d+(?:\.\d+)?)/);
492
+ if (v) version = v[1];
493
+ }
494
+ phases.push({
495
+ number,
496
+ name: name13,
497
+ version,
498
+ checkbox_status: statusMap.get(number) ?? "unknown"
499
+ });
500
+ }
501
+ return phases;
502
+ }
503
+ module2.exports = { readRoadmapMd: readRoadmapMd2, parsePhases: parsePhases2 };
504
+ }
505
+ });
506
+
507
+ // sdk/mcp/gdd-mcp/server.ts
508
+ var server_exports = {};
509
+ __export(server_exports, {
510
+ SERVER_NAME: () => SERVER_NAME,
511
+ SERVER_VERSION: () => SERVER_VERSION,
512
+ TOOL_DESCRIPTIONS: () => TOOL_DESCRIPTIONS,
513
+ TOOL_READONLY: () => TOOL_READONLY,
514
+ buildServer: () => buildServer,
515
+ runStdio: () => runStdio
516
+ });
517
+ module.exports = __toCommonJS(server_exports);
518
+ var import_node_fs5 = require("node:fs");
519
+ var import_node_path4 = require("node:path");
520
+ var import_server = require("@modelcontextprotocol/sdk/server/index.js");
521
+ var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
522
+ var import_types6 = require("@modelcontextprotocol/sdk/types.js");
523
+
524
+ // sdk/errors/index.ts
525
+ var GDDError = class extends Error {
526
+ code;
527
+ context;
528
+ constructor(message, code, context = {}) {
529
+ super(message);
530
+ this.code = code;
531
+ this.context = Object.freeze({ ...context });
532
+ this.name = new.target.name;
533
+ }
534
+ /**
535
+ * Serialize to a plain object safe for JSON.stringify. Round-trips
536
+ * through JSON without loss of `name`, `kind`, `code`, `message`, or
537
+ * `context`. Does NOT include the stack trace — MCP tool handlers do
538
+ * not forward stacks to the model.
539
+ */
540
+ toJSON() {
541
+ return {
542
+ name: this.name,
543
+ kind: this.kind,
544
+ code: this.code,
545
+ message: this.message,
546
+ context: this.context
547
+ };
548
+ }
549
+ };
550
+ var ValidationError = class extends GDDError {
551
+ kind = "validation";
552
+ constructor(message, code = "VALIDATION", context) {
553
+ super(message, code, context);
554
+ }
555
+ };
556
+ var StateConflictError = class extends GDDError {
557
+ kind = "state_conflict";
558
+ constructor(message, code = "STATE_CONFLICT", context) {
559
+ super(message, code, context);
560
+ }
561
+ };
562
+ var OperationFailedError = class extends GDDError {
563
+ kind = "operation_failed";
564
+ constructor(message, code = "OPERATION_FAILED", context) {
565
+ super(message, code, context);
566
+ }
567
+ };
568
+ var ParseError = class extends ValidationError {
569
+ line;
570
+ constructor(message, line, context) {
571
+ super(
572
+ `STATE.md parse error at line ${line}: ${message}`,
573
+ "PARSE_ERROR",
574
+ { ...context, line }
575
+ );
576
+ this.line = line;
577
+ }
578
+ };
579
+
580
+ // sdk/errors/classification.ts
581
+ function classify(err) {
582
+ if (err instanceof ValidationError) {
583
+ return {
584
+ kind: "validation",
585
+ shouldThrow: true,
586
+ retryable: false,
587
+ code: err.code,
588
+ message: err.message
589
+ };
590
+ }
591
+ if (err instanceof StateConflictError) {
592
+ return {
593
+ kind: "state_conflict",
594
+ shouldThrow: true,
595
+ retryable: true,
596
+ code: err.code,
597
+ message: err.message
598
+ };
599
+ }
600
+ if (err instanceof OperationFailedError) {
601
+ return {
602
+ kind: "operation_failed",
603
+ shouldThrow: false,
604
+ retryable: false,
605
+ code: err.code,
606
+ message: err.message
607
+ };
608
+ }
609
+ if (err instanceof Error) {
610
+ return {
611
+ kind: "unknown",
612
+ shouldThrow: true,
613
+ retryable: false,
614
+ code: "UNKNOWN",
615
+ message: err.message
616
+ };
617
+ }
618
+ return {
619
+ kind: "unknown",
620
+ shouldThrow: true,
621
+ retryable: false,
622
+ code: "UNKNOWN",
623
+ message: String(err)
624
+ };
625
+ }
626
+ function toToolError(err) {
627
+ const c = classify(err);
628
+ const out = {
629
+ error: {
630
+ code: c.code,
631
+ message: c.message,
632
+ kind: c.kind
633
+ }
634
+ };
635
+ if (err instanceof GDDError) {
636
+ out.error.context = err.context;
637
+ }
638
+ return out;
639
+ }
640
+
641
+ // sdk/mcp/gdd-mcp/tools/gdd_cycle_recap.ts
642
+ var gdd_cycle_recap_exports = {};
643
+ __export(gdd_cycle_recap_exports, {
644
+ handle: () => handle,
645
+ name: () => name,
646
+ schemaPath: () => schemaPath
647
+ });
648
+
649
+ // sdk/state/index.ts
650
+ var import_node_fs = require("node:fs");
651
+
652
+ // sdk/state/types.ts
653
+ function isConnectionStatus(value) {
654
+ return value === "available" || value === "unavailable" || value === "not_configured";
655
+ }
656
+ function isDecisionStatus(value) {
657
+ return value === "locked" || value === "tentative";
658
+ }
659
+ function isMustHaveStatus(value) {
660
+ return value === "pending" || value === "pass" || value === "fail";
661
+ }
662
+ function isSpikeVerdict(value) {
663
+ return value === "yes" || value === "no" || value === "partial";
664
+ }
665
+ function isPrototypingEntryStatus(value) {
666
+ return value === "resolved";
667
+ }
668
+ function isQualityGateStatus(value) {
669
+ return value === "pass" || value === "fail" || value === "timeout" || value === "skipped";
670
+ }
671
+
672
+ // sdk/state/parser.ts
673
+ var BLOCK_ORDER = [
674
+ "position",
675
+ "decisions",
676
+ "must_haves",
677
+ "prototyping",
678
+ "quality_gate",
679
+ "connections",
680
+ "blockers",
681
+ "parallelism_decision",
682
+ "todos",
683
+ "timestamps"
684
+ ];
685
+ var EMPTY_RAW_BODIES = {
686
+ position: null,
687
+ decisions: null,
688
+ must_haves: null,
689
+ prototyping: null,
690
+ quality_gate: null,
691
+ connections: null,
692
+ blockers: null,
693
+ parallelism_decision: null,
694
+ todos: null,
695
+ timestamps: null
696
+ };
697
+ function parse(raw) {
698
+ const line_ending = raw.includes("\r\n") ? "\r\n" : "\n";
699
+ const normalized = line_ending === "\r\n" ? raw.replace(/\r\n/g, "\n") : raw;
700
+ const trailing_newline = normalized.endsWith("\n");
701
+ if (!normalized.startsWith("---\n")) {
702
+ throw new ParseError('file must begin with "---" frontmatter fence', 1);
703
+ }
704
+ const fmEnd = normalized.indexOf("\n---\n", 4);
705
+ if (fmEnd === -1) {
706
+ throw new ParseError('unterminated frontmatter (missing closing "---")', 1);
707
+ }
708
+ const fmText = normalized.slice(4, fmEnd);
709
+ const frontmatter = parseFrontmatter(fmText);
710
+ const afterFm = fmEnd + 5;
711
+ const body = normalized.slice(afterFm);
712
+ const lines = body.split("\n");
713
+ const blocks = [];
714
+ const seen = /* @__PURE__ */ new Set();
715
+ const blockOpen = /^<([a-z_]+)>\s*$/;
716
+ const blockClose = /^<\/([a-z_]+)>\s*$/;
717
+ for (let i = 0; i < lines.length; i++) {
718
+ const line = lines[i] ?? "";
719
+ const openMatch = line.match(blockOpen);
720
+ if (!openMatch) continue;
721
+ const name13 = openMatch[1];
722
+ if (!BLOCK_ORDER.includes(name13)) {
723
+ continue;
724
+ }
725
+ if (seen.has(name13)) {
726
+ throw new ParseError(`duplicate block <${name13}>`, lineToFileLine(afterFm, normalized, i));
727
+ }
728
+ let close = -1;
729
+ for (let j = i + 1; j < lines.length; j++) {
730
+ const cm = (lines[j] ?? "").match(blockClose);
731
+ if (cm && cm[1] === name13) {
732
+ close = j;
733
+ break;
734
+ }
735
+ }
736
+ if (close === -1) {
737
+ throw new ParseError(
738
+ `unterminated block <${name13}> (no </${name13}>)`,
739
+ lineToFileLine(afterFm, normalized, i)
740
+ );
741
+ }
742
+ blocks.push({ name: name13, openLine: i, closeLine: close });
743
+ seen.add(name13);
744
+ i = close;
745
+ }
746
+ let body_preamble;
747
+ let body_trailer;
748
+ const block_gaps = {
749
+ position: "",
750
+ decisions: "",
751
+ must_haves: "",
752
+ prototyping: "",
753
+ quality_gate: "",
754
+ connections: "",
755
+ blockers: "",
756
+ parallelism_decision: "",
757
+ todos: "",
758
+ timestamps: ""
759
+ };
760
+ if (blocks.length === 0) {
761
+ body_preamble = body;
762
+ body_trailer = "";
763
+ } else {
764
+ const firstBlock = blocks[0];
765
+ const lastBlock = blocks[blocks.length - 1];
766
+ if (firstBlock === void 0 || lastBlock === void 0) {
767
+ throw new ParseError("internal: block index inconsistency", 1);
768
+ }
769
+ body_preamble = lines.slice(0, firstBlock.openLine).join("\n");
770
+ if (firstBlock.openLine > 0) body_preamble += "\n";
771
+ body_trailer = lines.slice(lastBlock.closeLine + 1).join("\n");
772
+ for (let bi = 0; bi < blocks.length; bi++) {
773
+ const cur = blocks[bi];
774
+ if (cur === void 0) continue;
775
+ if (bi === 0) {
776
+ block_gaps[cur.name] = body_preamble;
777
+ } else {
778
+ const prev = blocks[bi - 1];
779
+ if (prev === void 0) continue;
780
+ const gapLines = lines.slice(prev.closeLine + 1, cur.openLine);
781
+ let gap = gapLines.join("\n");
782
+ if (cur.openLine > prev.closeLine + 1) gap += "\n";
783
+ block_gaps[cur.name] = gap;
784
+ }
785
+ }
786
+ }
787
+ const raw_bodies = { ...EMPTY_RAW_BODIES };
788
+ let position = null;
789
+ let decisions = [];
790
+ let must_haves = [];
791
+ let connections = {};
792
+ let blockers = [];
793
+ let parallelism_decision = null;
794
+ let todos = null;
795
+ let prototyping = null;
796
+ let quality_gate = null;
797
+ let timestamps = {};
798
+ for (const blk of blocks) {
799
+ const rawBody = lines.slice(blk.openLine + 1, blk.closeLine).join("\n");
800
+ raw_bodies[blk.name] = rawBody;
801
+ const fileLineOfBody = lineToFileLine(afterFm, normalized, blk.openLine + 1);
802
+ switch (blk.name) {
803
+ case "position":
804
+ position = parsePositionBody(rawBody, fileLineOfBody);
805
+ break;
806
+ case "decisions":
807
+ decisions = parseDecisionsBody(rawBody, fileLineOfBody);
808
+ break;
809
+ case "must_haves":
810
+ must_haves = parseMustHavesBody(rawBody, fileLineOfBody);
811
+ break;
812
+ case "prototyping":
813
+ prototyping = parsePrototypingBody(rawBody, fileLineOfBody);
814
+ break;
815
+ case "quality_gate":
816
+ quality_gate = parseQualityGateBody(rawBody, fileLineOfBody);
817
+ break;
818
+ case "connections":
819
+ connections = parseConnectionsBody(rawBody, fileLineOfBody);
820
+ break;
821
+ case "blockers":
822
+ blockers = parseBlockersBody(rawBody, fileLineOfBody);
823
+ break;
824
+ case "parallelism_decision":
825
+ parallelism_decision = rawBody;
826
+ break;
827
+ case "todos":
828
+ todos = rawBody;
829
+ break;
830
+ case "timestamps":
831
+ timestamps = parseTimestampsBody(rawBody, fileLineOfBody);
832
+ break;
833
+ default: {
834
+ const _exhaustive = blk.name;
835
+ void _exhaustive;
836
+ }
837
+ }
838
+ }
839
+ if (position === null) {
840
+ throw new ParseError(
841
+ "missing required <position> block (run scan to initialize STATE.md)",
842
+ 1
843
+ );
844
+ }
845
+ const state = {
846
+ frontmatter,
847
+ position,
848
+ decisions,
849
+ must_haves,
850
+ connections,
851
+ blockers,
852
+ parallelism_decision,
853
+ todos,
854
+ prototyping,
855
+ quality_gate,
856
+ timestamps,
857
+ body_preamble,
858
+ body_trailer
859
+ };
860
+ return {
861
+ state,
862
+ raw_bodies,
863
+ raw_frontmatter: fmText,
864
+ block_gaps,
865
+ line_ending,
866
+ trailing_newline
867
+ };
868
+ }
869
+ function lineToFileLine(bodyStartOffset, normalized, bodyLineIdx) {
870
+ const prefix = normalized.slice(0, bodyStartOffset);
871
+ const prefixLines = prefix.split("\n").length - 1;
872
+ return prefixLines + bodyLineIdx + 1;
873
+ }
874
+ function parseFrontmatter(raw) {
875
+ const out = {};
876
+ const lines = raw.split("\n");
877
+ for (const line of lines) {
878
+ const trimmed = line.trim();
879
+ if (trimmed === "" || trimmed.startsWith("#")) continue;
880
+ const idx = line.indexOf(":");
881
+ if (idx === -1) continue;
882
+ const key = line.slice(0, idx).trim();
883
+ let value = line.slice(idx + 1).trim();
884
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
885
+ value = value.slice(1, -1);
886
+ }
887
+ if (key === "wave") {
888
+ const n = Number(value);
889
+ out[key] = Number.isFinite(n) ? n : value;
890
+ } else {
891
+ out[key] = value;
892
+ }
893
+ }
894
+ const fm = {
895
+ pipeline_state_version: String(out["pipeline_state_version"] ?? "1.0"),
896
+ stage: String(out["stage"] ?? ""),
897
+ cycle: String(out["cycle"] ?? ""),
898
+ wave: typeof out["wave"] === "number" ? out["wave"] : 1,
899
+ started_at: String(out["started_at"] ?? ""),
900
+ last_checkpoint: String(out["last_checkpoint"] ?? "")
901
+ };
902
+ for (const [k, v] of Object.entries(out)) {
903
+ if (!(k in fm)) fm[k] = v;
904
+ }
905
+ return fm;
906
+ }
907
+ function parsePositionBody(body, startLine) {
908
+ const fields = {};
909
+ const lines = body.split("\n");
910
+ for (let i = 0; i < lines.length; i++) {
911
+ const line = lines[i] ?? "";
912
+ const trimmed = line.trim();
913
+ if (trimmed === "" || trimmed.startsWith("<!--")) continue;
914
+ const idx = line.indexOf(":");
915
+ if (idx === -1) continue;
916
+ const key = line.slice(0, idx).trim();
917
+ let value = line.slice(idx + 1).trim();
918
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
919
+ value = value.slice(1, -1);
920
+ }
921
+ fields[key] = value;
922
+ }
923
+ const stage = fields["stage"] ?? "";
924
+ const waveRaw = fields["wave"] ?? "1";
925
+ const waveNum = Number(waveRaw);
926
+ if (!Number.isFinite(waveNum)) {
927
+ throw new ParseError(`<position> wave not numeric: ${waveRaw}`, startLine);
928
+ }
929
+ return {
930
+ stage,
931
+ wave: waveNum,
932
+ task_progress: fields["task_progress"] ?? "0/0",
933
+ status: fields["status"] ?? "initialized",
934
+ handoff_source: fields["handoff_source"] ?? "",
935
+ handoff_path: fields["handoff_path"] ?? "",
936
+ skipped_stages: fields["skipped_stages"] ?? ""
937
+ };
938
+ }
939
+ function parseDecisionsBody(body, startLine) {
940
+ const out = [];
941
+ const lines = body.split("\n");
942
+ const re = /^(D-\d+):\s*(.*?)\s*\((locked|tentative)\)\s*$/;
943
+ for (let i = 0; i < lines.length; i++) {
944
+ const line = (lines[i] ?? "").trim();
945
+ if (line === "" || line.startsWith("<!--")) continue;
946
+ const m = line.match(re);
947
+ if (!m) {
948
+ continue;
949
+ }
950
+ const id = m[1] ?? "";
951
+ const text = m[2] ?? "";
952
+ const status = m[3];
953
+ if (!isDecisionStatus(status)) {
954
+ throw new ParseError(
955
+ `<decisions> invalid status for ${id}: ${status}`,
956
+ startLine + i
957
+ );
958
+ }
959
+ out.push({ id, text, status });
960
+ }
961
+ return out;
962
+ }
963
+ function parseMustHavesBody(body, startLine) {
964
+ const out = [];
965
+ const lines = body.split("\n");
966
+ const re = /^(M-\d+):\s*(.*?)\s*\|\s*status:\s*(pending|pass|fail)\s*$/;
967
+ for (let i = 0; i < lines.length; i++) {
968
+ const line = (lines[i] ?? "").trim();
969
+ if (line === "" || line.startsWith("<!--")) continue;
970
+ const m = line.match(re);
971
+ if (!m) continue;
972
+ const id = m[1] ?? "";
973
+ const text = m[2] ?? "";
974
+ const status = m[3];
975
+ if (!isMustHaveStatus(status)) {
976
+ throw new ParseError(
977
+ `<must_haves> invalid status for ${id}: ${status}`,
978
+ startLine + i
979
+ );
980
+ }
981
+ out.push({ id, text, status });
982
+ }
983
+ return out;
984
+ }
985
+ function parseConnectionsBody(body, startLine) {
986
+ const out = {};
987
+ const lines = body.split("\n");
988
+ for (let i = 0; i < lines.length; i++) {
989
+ const line = lines[i] ?? "";
990
+ const trimmed = line.trim();
991
+ if (trimmed === "" || trimmed.startsWith("<!--")) continue;
992
+ const idx = line.indexOf(":");
993
+ if (idx === -1) continue;
994
+ const key = line.slice(0, idx).trim();
995
+ const value = line.slice(idx + 1).trim();
996
+ if (!isConnectionStatus(value)) {
997
+ throw new ParseError(
998
+ `<connections> invalid status for ${key}: ${value}`,
999
+ startLine + i
1000
+ );
1001
+ }
1002
+ out[key] = value;
1003
+ }
1004
+ return out;
1005
+ }
1006
+ function parseBlockersBody(body, startLine) {
1007
+ const out = [];
1008
+ const lines = body.split("\n");
1009
+ const re = /^\[([^\]]+)\]\s*\[([^\]]+)\]:\s*(.*)$/;
1010
+ for (let i = 0; i < lines.length; i++) {
1011
+ const line = (lines[i] ?? "").trim();
1012
+ if (line === "" || line.startsWith("<!--")) continue;
1013
+ const m = line.match(re);
1014
+ if (!m) {
1015
+ throw new ParseError(
1016
+ `<blockers> malformed line: "${line}"`,
1017
+ startLine + i
1018
+ );
1019
+ }
1020
+ out.push({ stage: m[1] ?? "", date: m[2] ?? "", text: m[3] ?? "" });
1021
+ }
1022
+ return out;
1023
+ }
1024
+ function parsePrototypingBody(body, startLine) {
1025
+ const sketches = [];
1026
+ const spikes = [];
1027
+ const skipped = [];
1028
+ const lines = body.split("\n");
1029
+ const selfClose = /^<([a-z_]+)(\s+[^>]*?)?\s*\/>\s*$/;
1030
+ for (let i = 0; i < lines.length; i++) {
1031
+ const line = (lines[i] ?? "").trim();
1032
+ if (line === "" || line.startsWith("<!--")) continue;
1033
+ const m = line.match(selfClose);
1034
+ if (!m) {
1035
+ continue;
1036
+ }
1037
+ const tag = m[1] ?? "";
1038
+ const attrs = parsePrototypingAttrs(m[2] ?? "");
1039
+ const fileLine = startLine + i;
1040
+ if (tag === "sketch") {
1041
+ sketches.push(buildSketchEntry(attrs, fileLine));
1042
+ } else if (tag === "spike") {
1043
+ spikes.push(buildSpikeEntry(attrs, fileLine));
1044
+ } else if (tag === "skipped") {
1045
+ skipped.push(buildSkippedEntry(attrs, fileLine));
1046
+ }
1047
+ }
1048
+ return { sketches, spikes, skipped };
1049
+ }
1050
+ function parsePrototypingAttrs(span) {
1051
+ const out = {};
1052
+ const re = /([a-zA-Z_][\w-]*)\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s/>]+))/g;
1053
+ let m;
1054
+ while ((m = re.exec(span)) !== null) {
1055
+ const key = m[1] ?? "";
1056
+ const value = (m[2] !== void 0 ? m[2] : void 0) ?? (m[3] !== void 0 ? m[3] : void 0) ?? m[4] ?? "";
1057
+ if (key !== "") out[key] = value;
1058
+ }
1059
+ return out;
1060
+ }
1061
+ function buildSketchEntry(attrs, fileLine) {
1062
+ const slug = attrs["slug"];
1063
+ const cycle = attrs["cycle"];
1064
+ const decision = attrs["decision"];
1065
+ const status = attrs["status"] ?? "resolved";
1066
+ if (slug === void 0) {
1067
+ throw new ParseError("<sketch/> missing required attribute slug", fileLine);
1068
+ }
1069
+ if (cycle === void 0) {
1070
+ throw new ParseError("<sketch/> missing required attribute cycle", fileLine);
1071
+ }
1072
+ if (decision === void 0) {
1073
+ throw new ParseError(
1074
+ "<sketch/> missing required attribute decision",
1075
+ fileLine
1076
+ );
1077
+ }
1078
+ if (!isPrototypingEntryStatus(status)) {
1079
+ throw new ParseError(
1080
+ `<sketch/> invalid status: ${status}`,
1081
+ fileLine
1082
+ );
1083
+ }
1084
+ return {
1085
+ slug,
1086
+ cycle,
1087
+ decision,
1088
+ status,
1089
+ extra_attrs: extractExtraAttrs(attrs, ["slug", "cycle", "decision", "status"])
1090
+ };
1091
+ }
1092
+ function buildSpikeEntry(attrs, fileLine) {
1093
+ const slug = attrs["slug"];
1094
+ const cycle = attrs["cycle"];
1095
+ const decision = attrs["decision"];
1096
+ const verdict = attrs["verdict"];
1097
+ const status = attrs["status"] ?? "resolved";
1098
+ if (slug === void 0) {
1099
+ throw new ParseError("<spike/> missing required attribute slug", fileLine);
1100
+ }
1101
+ if (cycle === void 0) {
1102
+ throw new ParseError("<spike/> missing required attribute cycle", fileLine);
1103
+ }
1104
+ if (decision === void 0) {
1105
+ throw new ParseError(
1106
+ "<spike/> missing required attribute decision",
1107
+ fileLine
1108
+ );
1109
+ }
1110
+ if (verdict === void 0) {
1111
+ throw new ParseError(
1112
+ "<spike/> missing required attribute verdict",
1113
+ fileLine
1114
+ );
1115
+ }
1116
+ if (!isSpikeVerdict(verdict)) {
1117
+ throw new ParseError(
1118
+ `<spike/> invalid verdict: ${verdict}`,
1119
+ fileLine
1120
+ );
1121
+ }
1122
+ if (!isPrototypingEntryStatus(status)) {
1123
+ throw new ParseError(
1124
+ `<spike/> invalid status: ${status}`,
1125
+ fileLine
1126
+ );
1127
+ }
1128
+ return {
1129
+ slug,
1130
+ cycle,
1131
+ decision,
1132
+ verdict,
1133
+ status,
1134
+ extra_attrs: extractExtraAttrs(attrs, [
1135
+ "slug",
1136
+ "cycle",
1137
+ "decision",
1138
+ "verdict",
1139
+ "status"
1140
+ ])
1141
+ };
1142
+ }
1143
+ function buildSkippedEntry(attrs, fileLine) {
1144
+ const at = attrs["at"];
1145
+ const cycle = attrs["cycle"];
1146
+ const reason = attrs["reason"];
1147
+ if (at === void 0) {
1148
+ throw new ParseError("<skipped/> missing required attribute at", fileLine);
1149
+ }
1150
+ if (cycle === void 0) {
1151
+ throw new ParseError(
1152
+ "<skipped/> missing required attribute cycle",
1153
+ fileLine
1154
+ );
1155
+ }
1156
+ if (reason === void 0) {
1157
+ throw new ParseError(
1158
+ "<skipped/> missing required attribute reason",
1159
+ fileLine
1160
+ );
1161
+ }
1162
+ return {
1163
+ at,
1164
+ cycle,
1165
+ reason,
1166
+ extra_attrs: extractExtraAttrs(attrs, ["at", "cycle", "reason"])
1167
+ };
1168
+ }
1169
+ function extractExtraAttrs(all, known) {
1170
+ const out = {};
1171
+ for (const [k, v] of Object.entries(all)) {
1172
+ if (!known.includes(k)) out[k] = v;
1173
+ }
1174
+ return out;
1175
+ }
1176
+ function parseQualityGateBody(body, startLine) {
1177
+ let run = null;
1178
+ const lines = body.split("\n");
1179
+ const selfClose = /^<([a-z_]+)(\s+[^>]*?)?\s*\/>\s*$/;
1180
+ for (let i = 0; i < lines.length; i++) {
1181
+ const line = (lines[i] ?? "").trim();
1182
+ if (line === "" || line.startsWith("<!--")) continue;
1183
+ const m = line.match(selfClose);
1184
+ if (!m) {
1185
+ continue;
1186
+ }
1187
+ const tag = m[1] ?? "";
1188
+ if (tag !== "run") continue;
1189
+ const attrs = parsePrototypingAttrs(m[2] ?? "");
1190
+ run = buildQualityGateRun(attrs, startLine + i);
1191
+ }
1192
+ return { run };
1193
+ }
1194
+ function buildQualityGateRun(attrs, fileLine) {
1195
+ const started_at = attrs["started_at"];
1196
+ const completed_at = attrs["completed_at"];
1197
+ const status = attrs["status"];
1198
+ const iterationRaw = attrs["iteration"];
1199
+ const commands_run = attrs["commands_run"];
1200
+ if (started_at === void 0) {
1201
+ throw new ParseError(
1202
+ "<quality_gate> <run/> missing required attribute started_at",
1203
+ fileLine
1204
+ );
1205
+ }
1206
+ if (completed_at === void 0) {
1207
+ throw new ParseError(
1208
+ "<quality_gate> <run/> missing required attribute completed_at",
1209
+ fileLine
1210
+ );
1211
+ }
1212
+ if (status === void 0) {
1213
+ throw new ParseError(
1214
+ "<quality_gate> <run/> missing required attribute status",
1215
+ fileLine
1216
+ );
1217
+ }
1218
+ if (!isQualityGateStatus(status)) {
1219
+ throw new ParseError(
1220
+ `<quality_gate> <run/> invalid status: ${status}`,
1221
+ fileLine
1222
+ );
1223
+ }
1224
+ if (iterationRaw === void 0) {
1225
+ throw new ParseError(
1226
+ "<quality_gate> <run/> missing required attribute iteration",
1227
+ fileLine
1228
+ );
1229
+ }
1230
+ const iteration = Number(iterationRaw);
1231
+ if (!Number.isFinite(iteration) || !Number.isInteger(iteration) || iteration < 0) {
1232
+ throw new ParseError(
1233
+ `<quality_gate> <run/> iteration not a non-negative integer: ${iterationRaw}`,
1234
+ fileLine
1235
+ );
1236
+ }
1237
+ if (commands_run === void 0) {
1238
+ throw new ParseError(
1239
+ "<quality_gate> <run/> missing required attribute commands_run",
1240
+ fileLine
1241
+ );
1242
+ }
1243
+ return {
1244
+ started_at,
1245
+ completed_at,
1246
+ status,
1247
+ iteration,
1248
+ commands_run,
1249
+ extra_attrs: extractExtraAttrs(attrs, [
1250
+ "started_at",
1251
+ "completed_at",
1252
+ "status",
1253
+ "iteration",
1254
+ "commands_run"
1255
+ ])
1256
+ };
1257
+ }
1258
+ function parseTimestampsBody(body, _startLine) {
1259
+ const out = {};
1260
+ const lines = body.split("\n");
1261
+ for (const line of lines) {
1262
+ const trimmed = line.trim();
1263
+ if (trimmed === "" || trimmed.startsWith("<!--")) continue;
1264
+ const idx = line.indexOf(":");
1265
+ if (idx === -1) continue;
1266
+ const key = line.slice(0, idx).trim();
1267
+ const value = line.slice(idx + 1).trim();
1268
+ out[key] = value;
1269
+ }
1270
+ return out;
1271
+ }
1272
+
1273
+ // sdk/state/gates.ts
1274
+ var DESIGN_KEYWORDS = ["component", "token", "style", "copy", "layout"];
1275
+ function stageParity(state, expected) {
1276
+ if (!state.position || typeof state.position.stage !== "string") {
1277
+ return "position block missing or malformed";
1278
+ }
1279
+ if (!state.frontmatter || typeof state.frontmatter.stage !== "string") {
1280
+ return "frontmatter stage missing or malformed";
1281
+ }
1282
+ if (state.position.stage !== expected) {
1283
+ return `position.stage is "${state.position.stage}" \u2014 expected "${expected}"`;
1284
+ }
1285
+ if (state.frontmatter.stage !== expected) {
1286
+ return `frontmatter.stage is "${state.frontmatter.stage}" \u2014 expected "${expected}"`;
1287
+ }
1288
+ return null;
1289
+ }
1290
+ var briefToExplore = (s) => {
1291
+ const blockers = [];
1292
+ const parity = stageParity(s, "brief");
1293
+ if (parity) blockers.push(parity);
1294
+ return { pass: blockers.length === 0, blockers };
1295
+ };
1296
+ var exploreToPlan = (s) => {
1297
+ const blockers = [];
1298
+ const parity = stageParity(s, "explore");
1299
+ if (parity) blockers.push(parity);
1300
+ const connKeys = Object.keys(s.connections ?? {});
1301
+ if (connKeys.length === 0) {
1302
+ blockers.push(
1303
+ "connections map is empty \u2014 run the explore-stage probe before advancing"
1304
+ );
1305
+ }
1306
+ return { pass: blockers.length === 0, blockers };
1307
+ };
1308
+ var planToDesign = (s) => {
1309
+ const blockers = [];
1310
+ const parity = stageParity(s, "plan");
1311
+ if (parity) blockers.push(parity);
1312
+ if ((s.must_haves ?? []).length === 0) {
1313
+ blockers.push("must_haves is empty \u2014 discover stage must land at least M-01");
1314
+ }
1315
+ const hasLocked = (s.decisions ?? []).some((d) => d.status === "locked");
1316
+ if (!hasLocked) {
1317
+ blockers.push("no locked decision in <decisions> \u2014 at least one must be locked");
1318
+ }
1319
+ const failing = (s.must_haves ?? []).filter((m) => m.status === "fail");
1320
+ for (const mh of failing) {
1321
+ const reconciled = (s.decisions ?? []).some((d) => d.text.includes(mh.id));
1322
+ if (!reconciled) {
1323
+ blockers.push(`${mh.id} marked fail without a decision to reconcile`);
1324
+ }
1325
+ }
1326
+ return { pass: blockers.length === 0, blockers };
1327
+ };
1328
+ var designToVerify = (s) => {
1329
+ const blockers = [];
1330
+ const parity = stageParity(s, "design");
1331
+ if (parity) blockers.push(parity);
1332
+ const pending = (s.must_haves ?? []).filter((m) => m.status === "pending");
1333
+ for (const mh of pending) {
1334
+ const lower = mh.text.toLowerCase();
1335
+ const hit = DESIGN_KEYWORDS.find((kw) => lower.includes(kw));
1336
+ if (hit) {
1337
+ blockers.push(
1338
+ `${mh.id} is pending and mentions "${hit}" \u2014 resolve in design before verify`
1339
+ );
1340
+ }
1341
+ }
1342
+ return { pass: blockers.length === 0, blockers };
1343
+ };
1344
+ var GATES = Object.freeze({
1345
+ briefToExplore,
1346
+ exploreToPlan,
1347
+ planToDesign,
1348
+ designToVerify
1349
+ });
1350
+
1351
+ // sdk/state/index.ts
1352
+ async function read(path) {
1353
+ const raw = (0, import_node_fs.readFileSync)(path, "utf8");
1354
+ return parse(raw).state;
1355
+ }
1356
+
1357
+ // sdk/mcp/gdd-mcp/tools/gdd_cycle_recap.ts
1358
+ var import_snapshot_reader = __toESM(require_snapshot_reader());
1359
+
1360
+ // sdk/mcp/gdd-mcp/tools/shared.ts
1361
+ var import_node_fs2 = require("node:fs");
1362
+ var import_node_path = require("node:path");
1363
+ function okResponse(data) {
1364
+ return { success: true, data };
1365
+ }
1366
+ function errorResponse(err) {
1367
+ const payload = toToolError(err);
1368
+ if (typeof err === "object" && err !== null && "code" in err && err.code === "directory_not_found") {
1369
+ const error = { ...payload.error, mcp_code: "directory_not_found" };
1370
+ return { success: false, error };
1371
+ }
1372
+ return { success: false, error: payload.error };
1373
+ }
1374
+ function resolveStatePath() {
1375
+ const override = process.env["GDD_STATE_PATH"];
1376
+ if (typeof override === "string" && override.length > 0) {
1377
+ return override;
1378
+ }
1379
+ return (0, import_node_path.join)(resolveProjectRoot(), ".design", "STATE.md");
1380
+ }
1381
+ function resolveTelemetryDir() {
1382
+ return (0, import_node_path.join)(resolveProjectRoot(), ".design", "telemetry");
1383
+ }
1384
+ function resolveProjectRoot(startCwd = process.cwd()) {
1385
+ const override = process.env["GDD_PROJECT_ROOT"];
1386
+ if (typeof override === "string" && override.length > 0) {
1387
+ return (0, import_node_path.resolve)(override);
1388
+ }
1389
+ let dir = (0, import_node_path.resolve)(startCwd);
1390
+ while (true) {
1391
+ 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"))) {
1392
+ return dir;
1393
+ }
1394
+ const parent = (0, import_node_path.dirname)(dir);
1395
+ if (parent === dir) {
1396
+ throw new Error(
1397
+ `gdd project root not found: walked up to ${dir} from ${startCwd}`
1398
+ );
1399
+ }
1400
+ dir = parent;
1401
+ }
1402
+ }
1403
+
1404
+ // sdk/mcp/gdd-mcp/tools/gdd_cycle_recap.ts
1405
+ var name = "gdd_cycle_recap";
1406
+ var schemaPath = "../schemas/gdd_cycle_recap.schema.json";
1407
+ function snapCount(snap, key, fallback) {
1408
+ if (typeof snap[key] === "number") return snap[key];
1409
+ const arr = snap[fallback];
1410
+ return Array.isArray(arr) ? arr.length : 0;
1411
+ }
1412
+ async function handle(_input) {
1413
+ try {
1414
+ const snap = await (0, import_snapshot_reader.readLatestSnapshot)(resolveProjectRoot());
1415
+ const state = await read(resolveStatePath());
1416
+ if (snap === null) return okResponse({ since: null, diff: { state_sections: [], decisions_delta: 0, completed_plans_delta: 0 } });
1417
+ const decisionsNow = (state.decisions ?? []).length;
1418
+ const completedNow = (state.must_haves ?? []).filter((m) => m.status === "pass").length;
1419
+ return okResponse({
1420
+ since: snap.since,
1421
+ diff: {
1422
+ state_sections: Object.keys(state),
1423
+ decisions_delta: decisionsNow - snapCount(snap.snapshot, "decisions_count", "last_n_decisions"),
1424
+ completed_plans_delta: completedNow - snapCount(snap.snapshot, "completed_plans_count", "_unused")
1425
+ }
1426
+ });
1427
+ } catch (err) {
1428
+ return errorResponse(err);
1429
+ }
1430
+ }
1431
+
1432
+ // sdk/mcp/gdd-mcp/tools/gdd_decisions_list.ts
1433
+ var gdd_decisions_list_exports = {};
1434
+ __export(gdd_decisions_list_exports, {
1435
+ handle: () => handle2,
1436
+ name: () => name2,
1437
+ schemaPath: () => schemaPath2
1438
+ });
1439
+ var name2 = "gdd_decisions_list";
1440
+ var schemaPath2 = "../schemas/gdd_decisions_list.schema.json";
1441
+ async function handle2(input) {
1442
+ try {
1443
+ const typed = input ?? {};
1444
+ const state = await read(resolveStatePath());
1445
+ let decisions = state.decisions ?? [];
1446
+ if (typeof typed.status === "string" && typed.status.length > 0) {
1447
+ decisions = decisions.filter((d) => d.status === typed.status);
1448
+ }
1449
+ return okResponse({ decisions });
1450
+ } catch (err) {
1451
+ return errorResponse(err);
1452
+ }
1453
+ }
1454
+
1455
+ // sdk/mcp/gdd-mcp/tools/gdd_events_tail.ts
1456
+ var gdd_events_tail_exports = {};
1457
+ __export(gdd_events_tail_exports, {
1458
+ handle: () => handle3,
1459
+ name: () => name3,
1460
+ schemaPath: () => schemaPath3
1461
+ });
1462
+
1463
+ // sdk/event-stream/writer.ts
1464
+ var import_node_fs3 = require("node:fs");
1465
+ var import_node_path2 = require("node:path");
1466
+ var import_node_module = require("node:module");
1467
+ function _findRepoRoot() {
1468
+ let dir = process.cwd();
1469
+ for (let i = 0; i < 8; i++) {
1470
+ if ((0, import_node_fs3.existsSync)((0, import_node_path2.join)(dir, "package.json"))) return dir;
1471
+ const parent = (0, import_node_path2.dirname)(dir);
1472
+ if (parent === dir) break;
1473
+ dir = parent;
1474
+ }
1475
+ return process.cwd();
1476
+ }
1477
+ var _redact;
1478
+ try {
1479
+ const _root = _findRepoRoot();
1480
+ const _candidate = (0, import_node_path2.resolve)(_root, "scripts/lib/redact.cjs");
1481
+ if ((0, import_node_fs3.existsSync)(_candidate)) {
1482
+ const _redactRequire = (0, import_node_module.createRequire)((0, import_node_path2.join)(_root, "package.json"));
1483
+ const _mod = _redactRequire(_candidate);
1484
+ _redact = _mod.redact;
1485
+ } else {
1486
+ const _altRoot = (0, import_node_path2.resolve)(_root, "..", "..");
1487
+ const _altCandidate = (0, import_node_path2.resolve)(_altRoot, "scripts/lib/redact.cjs");
1488
+ if ((0, import_node_fs3.existsSync)(_altCandidate)) {
1489
+ const _altRequire = (0, import_node_module.createRequire)((0, import_node_path2.join)(_altRoot, "package.json"));
1490
+ const _altMod = _altRequire(_altCandidate);
1491
+ _redact = _altMod.redact;
1492
+ } else {
1493
+ _redact = (v) => v;
1494
+ }
1495
+ }
1496
+ } catch {
1497
+ _redact = (v) => v;
1498
+ }
1499
+ var DEFAULT_EVENTS_PATH = ".design/telemetry/events.jsonl";
1500
+ var DEFAULT_MAX_LINE_BYTES = 64 * 1024;
1501
+
1502
+ // sdk/event-stream/reader.ts
1503
+ var import_node_fs4 = require("node:fs");
1504
+ var import_node_path3 = require("node:path");
1505
+ var import_node_readline = require("node:readline");
1506
+ function resolveReadPath(opts) {
1507
+ const raw = opts.path ?? DEFAULT_EVENTS_PATH;
1508
+ if ((0, import_node_path3.isAbsolute)(raw)) return raw;
1509
+ return (0, import_node_path3.resolve)(opts.baseDir ?? process.cwd(), raw);
1510
+ }
1511
+ async function* readEvents(opts = {}) {
1512
+ const path = resolveReadPath(opts);
1513
+ if (!(0, import_node_fs4.existsSync)(path)) return;
1514
+ const stream = (0, import_node_fs4.createReadStream)(path, { encoding: "utf8" });
1515
+ const rl = (0, import_node_readline.createInterface)({ input: stream, crlfDelay: Infinity });
1516
+ const typeRe = opts.type instanceof RegExp ? opts.type : null;
1517
+ const typeStr = typeof opts.type === "string" ? opts.type : null;
1518
+ try {
1519
+ for await (const line of rl) {
1520
+ if (line.trim() === "") continue;
1521
+ let ev;
1522
+ try {
1523
+ ev = JSON.parse(line);
1524
+ } catch {
1525
+ continue;
1526
+ }
1527
+ if (typeStr !== null && ev.type !== typeStr) continue;
1528
+ if (typeRe !== null && !typeRe.test(ev.type)) continue;
1529
+ if (opts.predicate && !opts.predicate(ev)) continue;
1530
+ if (opts.since !== void 0 && ev.timestamp < opts.since) continue;
1531
+ if (opts.until !== void 0 && ev.timestamp > opts.until) continue;
1532
+ yield ev;
1533
+ }
1534
+ } finally {
1535
+ rl.close();
1536
+ stream.close();
1537
+ }
1538
+ }
1539
+
1540
+ // sdk/mcp/gdd-mcp/tools/gdd_events_tail.ts
1541
+ var name3 = "gdd_events_tail";
1542
+ var schemaPath3 = "../schemas/gdd_events_tail.schema.json";
1543
+ async function handle3(input) {
1544
+ try {
1545
+ const typed = input ?? {};
1546
+ const limit = typeof typed.limit === "number" && typed.limit > 0 ? typed.limit : 50;
1547
+ const ring = [];
1548
+ const opts = { path: resolveTelemetryDir() + "/events.jsonl" };
1549
+ if (typeof typed.type === "string" && typed.type.length > 0) opts.type = typed.type;
1550
+ for await (const ev of readEvents(opts)) {
1551
+ ring.push(ev);
1552
+ if (ring.length > limit) ring.shift();
1553
+ }
1554
+ return okResponse({ events: ring });
1555
+ } catch (err) {
1556
+ return errorResponse(err);
1557
+ }
1558
+ }
1559
+
1560
+ // sdk/mcp/gdd-mcp/tools/gdd_health.ts
1561
+ var gdd_health_exports = {};
1562
+ __export(gdd_health_exports, {
1563
+ handle: () => handle4,
1564
+ name: () => name4,
1565
+ schemaPath: () => schemaPath4
1566
+ });
1567
+ var import_health_mirror = __toESM(require_health_mirror());
1568
+ var name4 = "gdd_health";
1569
+ var schemaPath4 = "../schemas/gdd_health.schema.json";
1570
+ async function handle4(_input) {
1571
+ try {
1572
+ const result = await (0, import_health_mirror.getHealthChecks)(resolveProjectRoot());
1573
+ return okResponse({ checks: result.checks });
1574
+ } catch (err) {
1575
+ return errorResponse(err);
1576
+ }
1577
+ }
1578
+
1579
+ // sdk/mcp/gdd-mcp/tools/gdd_intel_get.ts
1580
+ var gdd_intel_get_exports = {};
1581
+ __export(gdd_intel_get_exports, {
1582
+ handle: () => handle5,
1583
+ name: () => name5,
1584
+ schemaPath: () => schemaPath5
1585
+ });
1586
+ var import_intel_store = __toESM(require_intel_store());
1587
+ var name5 = "gdd_intel_get";
1588
+ var schemaPath5 = "../schemas/gdd_intel_get.schema.json";
1589
+ async function handle5(input) {
1590
+ try {
1591
+ const typed = input ?? {};
1592
+ if (typeof typed.slice_id !== "string" || typed.slice_id.length === 0) {
1593
+ return errorResponse(new Error("slice_id is required"));
1594
+ }
1595
+ const data = await (0, import_intel_store.readSlice)(resolveProjectRoot(), typed.slice_id);
1596
+ if (data === null) return errorResponse(new Error("slice not found: " + typed.slice_id));
1597
+ if (Array.isArray(typed.shape) && typed.shape.length > 0 && typeof data === "object" && data !== null) {
1598
+ const projected = {};
1599
+ for (const k of typed.shape) if (k in data) projected[k] = data[k];
1600
+ return okResponse({ slice_id: typed.slice_id, data: projected });
1601
+ }
1602
+ return okResponse({ slice_id: typed.slice_id, data });
1603
+ } catch (err) {
1604
+ return errorResponse(err);
1605
+ }
1606
+ }
1607
+
1608
+ // sdk/mcp/gdd-mcp/tools/gdd_learnings_digest.ts
1609
+ var gdd_learnings_digest_exports = {};
1610
+ __export(gdd_learnings_digest_exports, {
1611
+ handle: () => handle6,
1612
+ name: () => name6,
1613
+ schemaPath: () => schemaPath6
1614
+ });
1615
+ var import_reflections_reader = __toESM(require_reflections_reader());
1616
+ var name6 = "gdd_learnings_digest";
1617
+ var schemaPath6 = "../schemas/gdd_learnings_digest.schema.json";
1618
+ async function handle6(input) {
1619
+ try {
1620
+ const typed = input ?? {};
1621
+ const n = typeof typed.cycles === "number" && typed.cycles > 0 ? typed.cycles : 5;
1622
+ const refls = await (0, import_reflections_reader.readNReflections)(resolveProjectRoot(), n);
1623
+ return okResponse({ digest: (0, import_reflections_reader.digestReflections)(refls), cycles_included: refls.length });
1624
+ } catch (err) {
1625
+ return errorResponse(err);
1626
+ }
1627
+ }
1628
+
1629
+ // sdk/mcp/gdd-mcp/tools/gdd_phase_current.ts
1630
+ var gdd_phase_current_exports = {};
1631
+ __export(gdd_phase_current_exports, {
1632
+ handle: () => handle7,
1633
+ name: () => name7,
1634
+ schemaPath: () => schemaPath7
1635
+ });
1636
+ var name7 = "gdd_phase_current";
1637
+ var schemaPath7 = "../schemas/gdd_phase_current.schema.json";
1638
+ async function handle7(_input) {
1639
+ try {
1640
+ const state = await read(resolveStatePath());
1641
+ const p = state.position;
1642
+ return okResponse({
1643
+ phase: state.frontmatter.cycle ?? null,
1644
+ stage: p?.stage ?? null,
1645
+ task_progress: p?.task_progress ?? null,
1646
+ status: p?.status ?? null
1647
+ });
1648
+ } catch (err) {
1649
+ return errorResponse(err);
1650
+ }
1651
+ }
1652
+
1653
+ // sdk/mcp/gdd-mcp/tools/gdd_phases_list.ts
1654
+ var gdd_phases_list_exports = {};
1655
+ __export(gdd_phases_list_exports, {
1656
+ handle: () => handle8,
1657
+ name: () => name8,
1658
+ schemaPath: () => schemaPath8
1659
+ });
1660
+ var import_roadmap_reader = __toESM(require_roadmap_reader());
1661
+ var name8 = "gdd_phases_list";
1662
+ var schemaPath8 = "../schemas/gdd_phases_list.schema.json";
1663
+ async function handle8(_input) {
1664
+ try {
1665
+ const md = await (0, import_roadmap_reader.readRoadmapMd)(resolveProjectRoot());
1666
+ return okResponse({ phases: (0, import_roadmap_reader.parsePhases)(md) });
1667
+ } catch (err) {
1668
+ return errorResponse(err);
1669
+ }
1670
+ }
1671
+
1672
+ // sdk/mcp/gdd-mcp/tools/gdd_plans_list.ts
1673
+ var gdd_plans_list_exports = {};
1674
+ __export(gdd_plans_list_exports, {
1675
+ handle: () => handle9,
1676
+ name: () => name9,
1677
+ schemaPath: () => schemaPath9
1678
+ });
1679
+ var name9 = "gdd_plans_list";
1680
+ var schemaPath9 = "../schemas/gdd_plans_list.schema.json";
1681
+ async function handle9(input) {
1682
+ try {
1683
+ const typed = input ?? {};
1684
+ const state = await read(resolveStatePath());
1685
+ const plans = (state.must_haves ?? []).map((m) => ({
1686
+ id: m.id,
1687
+ name: m.text,
1688
+ status: m.status
1689
+ }));
1690
+ return okResponse({
1691
+ phase: typed.phase ?? state.frontmatter.cycle ?? null,
1692
+ plans
1693
+ });
1694
+ } catch (err) {
1695
+ return errorResponse(err);
1696
+ }
1697
+ }
1698
+
1699
+ // sdk/mcp/gdd-mcp/tools/gdd_reflections_latest.ts
1700
+ var gdd_reflections_latest_exports = {};
1701
+ __export(gdd_reflections_latest_exports, {
1702
+ handle: () => handle10,
1703
+ name: () => name10,
1704
+ schemaPath: () => schemaPath10
1705
+ });
1706
+ var import_reflections_reader2 = __toESM(require_reflections_reader());
1707
+ var name10 = "gdd_reflections_latest";
1708
+ var schemaPath10 = "../schemas/gdd_reflections_latest.schema.json";
1709
+ async function handle10(_input) {
1710
+ try {
1711
+ const r = await (0, import_reflections_reader2.readLatestReflection)(resolveProjectRoot());
1712
+ if (r === null) return okResponse({ cycle: null, path: null, content_excerpt: "" });
1713
+ return okResponse({
1714
+ cycle: r.cycle,
1715
+ path: r.path,
1716
+ content_excerpt: r.content.slice(0, 4096)
1717
+ });
1718
+ } catch (err) {
1719
+ return errorResponse(err);
1720
+ }
1721
+ }
1722
+
1723
+ // sdk/mcp/gdd-mcp/tools/gdd_status.ts
1724
+ var gdd_status_exports = {};
1725
+ __export(gdd_status_exports, {
1726
+ handle: () => handle11,
1727
+ name: () => name11,
1728
+ schemaPath: () => schemaPath11
1729
+ });
1730
+ var name11 = "gdd_status";
1731
+ var schemaPath11 = "../schemas/gdd_status.schema.json";
1732
+ async function handle11(_input) {
1733
+ try {
1734
+ const state = await read(resolveStatePath());
1735
+ const completed = (state.must_haves ?? []).filter((m) => m.status === "pass");
1736
+ return okResponse({
1737
+ phase: state.frontmatter.cycle ?? null,
1738
+ branch: process.env["GIT_BRANCH"] ?? null,
1739
+ last_decisions: (state.decisions ?? []).slice(-3),
1740
+ last_completed_plans: completed.slice(-3),
1741
+ blocker_count: (state.blockers ?? []).length
1742
+ });
1743
+ } catch (err) {
1744
+ return errorResponse(err);
1745
+ }
1746
+ }
1747
+
1748
+ // sdk/mcp/gdd-mcp/tools/gdd_telemetry_query.ts
1749
+ var gdd_telemetry_query_exports = {};
1750
+ __export(gdd_telemetry_query_exports, {
1751
+ handle: () => handle12,
1752
+ name: () => name12,
1753
+ schemaPath: () => schemaPath12
1754
+ });
1755
+ var name12 = "gdd_telemetry_query";
1756
+ var schemaPath12 = "../schemas/gdd_telemetry_query.schema.json";
1757
+ async function handle12(input) {
1758
+ try {
1759
+ const typed = input ?? {};
1760
+ const limit = typeof typed.limit === "number" && typed.limit > 0 ? typed.limit : 100;
1761
+ const events = [];
1762
+ const opts = { path: resolveTelemetryDir() + "/events.jsonl" };
1763
+ if (typeof typed.type === "string" && typed.type.length > 0) opts.type = typed.type;
1764
+ if (typeof typed.since === "string" && typed.since.length > 0) opts.since = typed.since;
1765
+ for await (const ev of readEvents(opts)) {
1766
+ events.push(ev);
1767
+ if (events.length >= limit) break;
1768
+ }
1769
+ return okResponse({ events });
1770
+ } catch (err) {
1771
+ return errorResponse(err);
1772
+ }
1773
+ }
1774
+
1775
+ // sdk/mcp/gdd-mcp/tools/index.ts
1776
+ var TOOL_MODULES = [
1777
+ gdd_status_exports,
1778
+ gdd_cycle_recap_exports,
1779
+ gdd_decisions_list_exports,
1780
+ gdd_events_tail_exports,
1781
+ gdd_health_exports,
1782
+ gdd_intel_get_exports,
1783
+ gdd_learnings_digest_exports,
1784
+ gdd_phase_current_exports,
1785
+ gdd_phases_list_exports,
1786
+ gdd_plans_list_exports,
1787
+ gdd_reflections_latest_exports,
1788
+ gdd_telemetry_query_exports
1789
+ ];
1790
+ var TOOL_COUNT = TOOL_MODULES.length;
1791
+ if (TOOL_COUNT > 12) {
1792
+ throw new Error(
1793
+ `gdd-mcp: TOOL_COUNT=${TOOL_COUNT} exceeds the 12-tool cap (D-03). Add tool past 12 requires re-scoping in a new plan.`
1794
+ );
1795
+ }
1796
+
1797
+ // sdk/mcp/gdd-mcp/server.ts
1798
+ var SERVER_NAME = "gdd-mcp";
1799
+ var SERVER_VERSION = "1.27.7";
1800
+ function here() {
1801
+ const expectedRel = (0, import_node_path4.join)("sdk", "mcp", "gdd-mcp");
1802
+ const entry = process.argv[1];
1803
+ if (typeof entry === "string" && entry.length > 0) {
1804
+ const entryDir = (0, import_node_path4.dirname)((0, import_node_path4.resolve)(entry));
1805
+ if ((0, import_node_fs5.existsSync)((0, import_node_path4.join)(entryDir, "tools", "index.ts"))) {
1806
+ return entryDir;
1807
+ }
1808
+ }
1809
+ const candidate = (0, import_node_path4.resolve)(process.cwd(), expectedRel);
1810
+ if ((0, import_node_fs5.existsSync)((0, import_node_path4.join)(candidate, "tools", "index.ts"))) {
1811
+ return candidate;
1812
+ }
1813
+ return candidate;
1814
+ }
1815
+ function loadTools() {
1816
+ const baseDir = here();
1817
+ return TOOL_MODULES.map((m) => {
1818
+ const absPath = (0, import_node_path4.join)(baseDir, "tools", m.schemaPath);
1819
+ const raw = (0, import_node_fs5.readFileSync)(absPath, "utf8");
1820
+ const parsed = JSON.parse(raw);
1821
+ const rawInput = parsed.properties?.input;
1822
+ const inputSchema = rawInput !== void 0 && typeof rawInput === "object" ? rawInput : { type: "object" };
1823
+ if (!("type" in inputSchema)) inputSchema["type"] = "object";
1824
+ return { ...m, inputSchema };
1825
+ });
1826
+ }
1827
+ var TOOL_DESCRIPTIONS = {
1828
+ gdd_status: "gdd_status: current cycle phase, branch, last-3 decisions, last-3 completed plans, blocker count.",
1829
+ gdd_phase_current: "gdd_phase_current: STATE.md <position> block (phase, stage, task_progress, status).",
1830
+ gdd_phases_list: "gdd_phases_list: parsed ROADMAP.md overview (phase number, name, target version, shipped/planned).",
1831
+ gdd_plans_list: "gdd_plans_list: plans tracked in STATE.md must_haves (optionally filtered by input.phase).",
1832
+ gdd_decisions_list: "gdd_decisions_list: decisions from STATE.md (optionally filtered by input.status).",
1833
+ gdd_intel_get: "gdd_intel_get: read a slice from .design/intel/ (input.slice_id required); directory_not_found if absent.",
1834
+ gdd_telemetry_query: "gdd_telemetry_query: typed reader over .design/telemetry/*.jsonl with type/since/limit filters.",
1835
+ gdd_cycle_recap: "gdd_cycle_recap: diff current STATE against latest .design/snapshots/ snapshot; directory_not_found if absent.",
1836
+ gdd_reflections_latest: "gdd_reflections_latest: newest .design/reflections/ file (excerpt <= 4 KB); directory_not_found if absent.",
1837
+ gdd_learnings_digest: "gdd_learnings_digest: aggregate last N reflections into a compact digest (<= 5 KB).",
1838
+ gdd_events_tail: "gdd_events_tail: last-N events from .design/telemetry/events.jsonl with optional type filter.",
1839
+ gdd_health: "gdd_health: read-only mirror of gdd-health SKILL \u2014 4 checks (CLAUDE.md, .planning/, .design/, package.json)."
1840
+ };
1841
+ var TOOL_READONLY = {
1842
+ gdd_status: true,
1843
+ gdd_phase_current: true,
1844
+ gdd_phases_list: true,
1845
+ gdd_plans_list: true,
1846
+ gdd_decisions_list: true,
1847
+ gdd_intel_get: true,
1848
+ gdd_telemetry_query: true,
1849
+ gdd_cycle_recap: true,
1850
+ gdd_reflections_latest: true,
1851
+ gdd_learnings_digest: true,
1852
+ gdd_events_tail: true,
1853
+ gdd_health: true
1854
+ };
1855
+ function buildServer() {
1856
+ const tools = loadTools();
1857
+ const byName = /* @__PURE__ */ new Map();
1858
+ for (const t of tools) byName.set(t.name, t);
1859
+ const server = new import_server.Server(
1860
+ { name: SERVER_NAME, version: SERVER_VERSION },
1861
+ {
1862
+ capabilities: { tools: {} }
1863
+ }
1864
+ );
1865
+ server.setRequestHandler(import_types6.ListToolsRequestSchema, async () => {
1866
+ return {
1867
+ tools: tools.map((t) => {
1868
+ const description = TOOL_DESCRIPTIONS[t.name] ?? t.name;
1869
+ const readOnly = TOOL_READONLY[t.name] ?? true;
1870
+ return {
1871
+ name: t.name,
1872
+ description,
1873
+ inputSchema: t.inputSchema,
1874
+ annotations: {
1875
+ readOnlyHint: readOnly,
1876
+ destructiveHint: !readOnly,
1877
+ idempotentHint: false
1878
+ }
1879
+ };
1880
+ })
1881
+ };
1882
+ });
1883
+ server.setRequestHandler(import_types6.CallToolRequestSchema, async (req) => {
1884
+ const { name: toolName, arguments: args } = req.params;
1885
+ const tool = byName.get(toolName);
1886
+ if (tool === void 0) {
1887
+ const payload = toToolError(
1888
+ new Error(`unknown tool: ${toolName}`)
1889
+ );
1890
+ return {
1891
+ isError: true,
1892
+ content: [
1893
+ {
1894
+ type: "text",
1895
+ text: JSON.stringify({ success: false, error: payload.error })
1896
+ }
1897
+ ],
1898
+ structuredContent: { success: false, error: payload.error }
1899
+ };
1900
+ }
1901
+ let response;
1902
+ try {
1903
+ response = await tool.handle(args ?? {});
1904
+ } catch (err) {
1905
+ const payload = toToolError(err);
1906
+ response = { success: false, error: payload.error };
1907
+ }
1908
+ const text = JSON.stringify(response);
1909
+ if (response.success === true) {
1910
+ return {
1911
+ content: [{ type: "text", text }],
1912
+ structuredContent: response
1913
+ };
1914
+ }
1915
+ return {
1916
+ isError: true,
1917
+ content: [{ type: "text", text }],
1918
+ structuredContent: response
1919
+ };
1920
+ });
1921
+ return server;
1922
+ }
1923
+ async function runStdio() {
1924
+ const server = buildServer();
1925
+ const transport = new import_stdio.StdioServerTransport();
1926
+ const shutdown = async (signal) => {
1927
+ if (SHUTTING_DOWN) return;
1928
+ SHUTTING_DOWN = true;
1929
+ try {
1930
+ await server.close();
1931
+ } catch {
1932
+ }
1933
+ process.exit(signal === "SIGTERM" ? 0 : 0);
1934
+ };
1935
+ process.on("SIGINT", () => {
1936
+ void shutdown("SIGINT");
1937
+ });
1938
+ process.on("SIGTERM", () => {
1939
+ void shutdown("SIGTERM");
1940
+ });
1941
+ await server.connect(transport);
1942
+ }
1943
+ var SHUTTING_DOWN = false;
1944
+ function isMain() {
1945
+ const entry = process.argv[1];
1946
+ if (typeof entry !== "string" || entry.length === 0) return false;
1947
+ return /sdk\/mcp\/gdd-mcp\/server\.(ts|js|cjs|mjs)$/.test(
1948
+ entry.replace(/\\/g, "/")
1949
+ );
1950
+ }
1951
+ if (isMain()) {
1952
+ runStdio().catch((err) => {
1953
+ const msg = err instanceof Error ? err.message : String(err);
1954
+ console.error(`[gdd-mcp] fatal: ${msg}`);
1955
+ process.exit(1);
1956
+ });
1957
+ }
1958
+ // Annotate the CommonJS export names for ESM import in node:
1959
+ 0 && (module.exports = {
1960
+ SERVER_NAME,
1961
+ SERVER_VERSION,
1962
+ TOOL_DESCRIPTIONS,
1963
+ TOOL_READONLY,
1964
+ buildServer,
1965
+ runStdio
1966
+ });