@hegemonart/get-design-done 1.27.6 → 1.28.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 (71) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +6 -3
  3. package/CHANGELOG.md +113 -0
  4. package/agents/design-verifier.md +17 -0
  5. package/package.json +5 -4
  6. package/reference/accessibility.md +4 -0
  7. package/reference/audit-scoring.md +14 -0
  8. package/reference/color-theory.md +279 -0
  9. package/reference/composition.md +349 -0
  10. package/reference/contrast-advanced.md +205 -0
  11. package/reference/design-system-guidance.md +2 -0
  12. package/reference/form-patterns.md +2 -0
  13. package/reference/i18n.md +554 -0
  14. package/reference/iconography.md +2 -0
  15. package/reference/motion-interpolate.md +1 -0
  16. package/reference/palette-catalog.md +2 -0
  17. package/reference/proportion-systems.md +267 -0
  18. package/reference/registry.json +42 -0
  19. package/reference/rtl-cjk-cultural.md +2 -0
  20. package/reference/schemas/mcp-gdd-tools.schema.json +381 -0
  21. package/reference/style-vocabulary.md +2 -0
  22. package/reference/typography.md +4 -0
  23. package/reference/visual-hierarchy-layout.md +4 -0
  24. package/scripts/install.cjs +42 -0
  25. package/scripts/lib/gsd-health-mirror/index.cjs +105 -0
  26. package/scripts/lib/gsd-health-mirror/index.d.cts +14 -0
  27. package/scripts/lib/install/mcp-register.cjs +235 -0
  28. package/scripts/lib/install/mcp-register.d.cts +64 -0
  29. package/scripts/lib/intel-store/index.cjs +55 -0
  30. package/scripts/lib/intel-store/index.d.cts +11 -0
  31. package/scripts/lib/mcp-tools-lint/index.cjs +216 -0
  32. package/scripts/lib/mcp-tools-lint/index.d.cts +74 -0
  33. package/scripts/lib/reflections-reader/index.cjs +107 -0
  34. package/scripts/lib/reflections-reader/index.d.cts +18 -0
  35. package/scripts/lib/roadmap-reader/index.cjs +81 -0
  36. package/scripts/lib/roadmap-reader/index.d.cts +13 -0
  37. package/scripts/lib/snapshot-reader/index.cjs +70 -0
  38. package/scripts/lib/snapshot-reader/index.d.cts +28 -0
  39. package/scripts/mcp-servers/gdd-mcp/README.md +66 -0
  40. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_cycle_recap.schema.json +30 -0
  41. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_decisions_list.schema.json +32 -0
  42. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_events_tail.schema.json +22 -0
  43. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_health.schema.json +30 -0
  44. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_intel_get.schema.json +24 -0
  45. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_learnings_digest.schema.json +22 -0
  46. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_phase_current.schema.json +22 -0
  47. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_phases_list.schema.json +31 -0
  48. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_plans_list.schema.json +33 -0
  49. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_reflections_latest.schema.json +21 -0
  50. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_status.schema.json +23 -0
  51. package/scripts/mcp-servers/gdd-mcp/schemas/gdd_telemetry_query.schema.json +23 -0
  52. package/scripts/mcp-servers/gdd-mcp/server.ts +317 -0
  53. package/scripts/mcp-servers/gdd-mcp/tools/gdd_cycle_recap.ts +37 -0
  54. package/scripts/mcp-servers/gdd-mcp/tools/gdd_decisions_list.ts +33 -0
  55. package/scripts/mcp-servers/gdd-mcp/tools/gdd_events_tail.ts +26 -0
  56. package/scripts/mcp-servers/gdd-mcp/tools/gdd_health.ts +19 -0
  57. package/scripts/mcp-servers/gdd-mcp/tools/gdd_intel_get.ts +32 -0
  58. package/scripts/mcp-servers/gdd-mcp/tools/gdd_learnings_digest.ts +23 -0
  59. package/scripts/mcp-servers/gdd-mcp/tools/gdd_phase_current.ts +29 -0
  60. package/scripts/mcp-servers/gdd-mcp/tools/gdd_phases_list.ts +26 -0
  61. package/scripts/mcp-servers/gdd-mcp/tools/gdd_plans_list.ts +39 -0
  62. package/scripts/mcp-servers/gdd-mcp/tools/gdd_reflections_latest.ts +25 -0
  63. package/scripts/mcp-servers/gdd-mcp/tools/gdd_status.ts +31 -0
  64. package/scripts/mcp-servers/gdd-mcp/tools/gdd_telemetry_query.ts +27 -0
  65. package/scripts/mcp-servers/gdd-mcp/tools/index.ts +75 -0
  66. package/scripts/mcp-servers/gdd-mcp/tools/shared.ts +134 -0
  67. package/skills/explore/SKILL.md +31 -0
  68. package/skills/health/SKILL.md +36 -0
  69. package/skills/next/SKILL.md +28 -3
  70. package/skills/progress/SKILL.md +21 -6
  71. package/skills/resume/SKILL.md +26 -1
@@ -0,0 +1,381 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://raw.githubusercontent.com/hegemonart/get-design-done/main/reference/schemas/mcp-gdd-tools.schema.json",
4
+ "title": "McpGddTools",
5
+ "description": "Combined manifest of all gdd-mcp tool input+output schemas (Plan 27.7-02). Individual tool schemas live under scripts/mcp-servers/gdd-mcp/schemas/ and the tool handlers reference them; this combined schema exists so downstream validators and codegen can compile a single surface (D-11).",
6
+ "type": "object",
7
+ "properties": {
8
+ "tools": {
9
+ "type": "object",
10
+ "description": "Per-tool input/output schemas keyed by tool name. Exactly 12 entries (D-03 hard cap).",
11
+ "additionalProperties": false,
12
+ "properties": {
13
+ "gdd_status": {
14
+ "type": "object",
15
+ "additionalProperties": false,
16
+ "required": ["input", "output"],
17
+ "properties": {
18
+ "input": {
19
+ "type": "object",
20
+ "additionalProperties": false,
21
+ "properties": {}
22
+ },
23
+ "output": {
24
+ "type": "object",
25
+ "required": ["phase", "branch", "last_decisions", "last_completed_plans", "blocker_count"],
26
+ "properties": {
27
+ "phase": { "type": ["string", "null"] },
28
+ "branch": { "type": ["string", "null"] },
29
+ "last_decisions": { "type": "array", "items": { "type": "object" } },
30
+ "last_completed_plans": { "type": "array", "items": { "type": "object" } },
31
+ "blocker_count": { "type": "integer", "minimum": 0 }
32
+ }
33
+ }
34
+ }
35
+ },
36
+ "gdd_phase_current": {
37
+ "type": "object",
38
+ "additionalProperties": false,
39
+ "required": ["input", "output"],
40
+ "properties": {
41
+ "input": {
42
+ "type": "object",
43
+ "additionalProperties": false,
44
+ "properties": {}
45
+ },
46
+ "output": {
47
+ "type": "object",
48
+ "required": ["phase", "stage", "task_progress", "status"],
49
+ "properties": {
50
+ "phase": { "type": ["string", "null"] },
51
+ "stage": { "type": ["string", "null"] },
52
+ "task_progress": { "type": ["string", "null"] },
53
+ "status": { "type": ["string", "null"] }
54
+ }
55
+ }
56
+ }
57
+ },
58
+ "gdd_phases_list": {
59
+ "type": "object",
60
+ "additionalProperties": false,
61
+ "required": ["input", "output"],
62
+ "properties": {
63
+ "input": {
64
+ "type": "object",
65
+ "additionalProperties": false,
66
+ "properties": {}
67
+ },
68
+ "output": {
69
+ "type": "object",
70
+ "required": ["phases"],
71
+ "properties": {
72
+ "phases": {
73
+ "type": "array",
74
+ "items": {
75
+ "type": "object",
76
+ "required": ["number", "name", "version", "checkbox_status"],
77
+ "properties": {
78
+ "number": { "type": "string" },
79
+ "name": { "type": "string" },
80
+ "version": { "type": "string" },
81
+ "checkbox_status": { "type": "string", "enum": ["shipped", "planned", "unknown"] }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
88
+ },
89
+ "gdd_plans_list": {
90
+ "type": "object",
91
+ "additionalProperties": false,
92
+ "required": ["input", "output"],
93
+ "properties": {
94
+ "input": {
95
+ "type": "object",
96
+ "additionalProperties": false,
97
+ "properties": {
98
+ "phase": { "type": "string" }
99
+ }
100
+ },
101
+ "output": {
102
+ "type": "object",
103
+ "required": ["phase", "plans"],
104
+ "properties": {
105
+ "phase": { "type": ["string", "null"] },
106
+ "plans": {
107
+ "type": "array",
108
+ "items": {
109
+ "type": "object",
110
+ "required": ["id", "name", "status"],
111
+ "properties": {
112
+ "id": { "type": "string" },
113
+ "name": { "type": "string" },
114
+ "status": { "type": "string" }
115
+ }
116
+ }
117
+ }
118
+ }
119
+ }
120
+ }
121
+ },
122
+ "gdd_decisions_list": {
123
+ "type": "object",
124
+ "additionalProperties": false,
125
+ "required": ["input", "output"],
126
+ "properties": {
127
+ "input": {
128
+ "type": "object",
129
+ "additionalProperties": false,
130
+ "properties": {
131
+ "status": { "type": "string", "enum": ["locked", "tentative"] }
132
+ }
133
+ },
134
+ "output": {
135
+ "type": "object",
136
+ "required": ["decisions"],
137
+ "properties": {
138
+ "decisions": {
139
+ "type": "array",
140
+ "items": {
141
+ "type": "object",
142
+ "required": ["id", "text", "status"],
143
+ "properties": {
144
+ "id": { "type": "string" },
145
+ "text": { "type": "string" },
146
+ "status": { "type": "string" }
147
+ }
148
+ }
149
+ }
150
+ }
151
+ }
152
+ }
153
+ },
154
+ "gdd_intel_get": {
155
+ "type": "object",
156
+ "additionalProperties": false,
157
+ "required": ["input", "output"],
158
+ "properties": {
159
+ "input": {
160
+ "type": "object",
161
+ "additionalProperties": false,
162
+ "required": ["slice_id"],
163
+ "properties": {
164
+ "slice_id": { "type": "string", "minLength": 1 },
165
+ "shape": { "type": "array", "items": { "type": "string" } }
166
+ }
167
+ },
168
+ "output": {
169
+ "type": "object",
170
+ "required": ["slice_id", "data"],
171
+ "properties": {
172
+ "slice_id": { "type": "string" },
173
+ "data": { "type": "object" }
174
+ }
175
+ }
176
+ }
177
+ },
178
+ "gdd_telemetry_query": {
179
+ "type": "object",
180
+ "additionalProperties": false,
181
+ "required": ["input", "output"],
182
+ "properties": {
183
+ "input": {
184
+ "type": "object",
185
+ "additionalProperties": false,
186
+ "properties": {
187
+ "type": { "type": "string" },
188
+ "since": { "type": "string", "format": "date-time" },
189
+ "limit": { "type": "integer", "minimum": 1, "maximum": 10000 }
190
+ }
191
+ },
192
+ "output": {
193
+ "type": "object",
194
+ "required": ["events"],
195
+ "properties": {
196
+ "events": { "type": "array", "items": { "type": "object" } }
197
+ }
198
+ }
199
+ }
200
+ },
201
+ "gdd_cycle_recap": {
202
+ "type": "object",
203
+ "additionalProperties": false,
204
+ "required": ["input", "output"],
205
+ "properties": {
206
+ "input": {
207
+ "type": "object",
208
+ "additionalProperties": false,
209
+ "properties": {
210
+ "since_snapshot": { "type": "string" }
211
+ }
212
+ },
213
+ "output": {
214
+ "type": "object",
215
+ "required": ["since", "diff"],
216
+ "properties": {
217
+ "since": { "type": ["string", "null"] },
218
+ "diff": {
219
+ "type": "object",
220
+ "required": ["state_sections", "decisions_delta", "completed_plans_delta"],
221
+ "properties": {
222
+ "state_sections": { "type": "array", "items": { "type": "string" } },
223
+ "decisions_delta": { "type": "integer" },
224
+ "completed_plans_delta": { "type": "integer" }
225
+ }
226
+ }
227
+ }
228
+ }
229
+ }
230
+ },
231
+ "gdd_reflections_latest": {
232
+ "type": "object",
233
+ "additionalProperties": false,
234
+ "required": ["input", "output"],
235
+ "properties": {
236
+ "input": {
237
+ "type": "object",
238
+ "additionalProperties": false,
239
+ "properties": {}
240
+ },
241
+ "output": {
242
+ "type": "object",
243
+ "required": ["cycle", "path", "content_excerpt"],
244
+ "properties": {
245
+ "cycle": { "type": ["string", "null"] },
246
+ "path": { "type": ["string", "null"] },
247
+ "content_excerpt": { "type": "string", "maxLength": 4096 }
248
+ }
249
+ }
250
+ }
251
+ },
252
+ "gdd_learnings_digest": {
253
+ "type": "object",
254
+ "additionalProperties": false,
255
+ "required": ["input", "output"],
256
+ "properties": {
257
+ "input": {
258
+ "type": "object",
259
+ "additionalProperties": false,
260
+ "properties": {
261
+ "cycles": { "type": "integer", "minimum": 1, "maximum": 50 }
262
+ }
263
+ },
264
+ "output": {
265
+ "type": "object",
266
+ "required": ["digest", "cycles_included"],
267
+ "properties": {
268
+ "digest": { "type": "string", "maxLength": 5120 },
269
+ "cycles_included": { "type": "integer", "minimum": 0 }
270
+ }
271
+ }
272
+ }
273
+ },
274
+ "gdd_events_tail": {
275
+ "type": "object",
276
+ "additionalProperties": false,
277
+ "required": ["input", "output"],
278
+ "properties": {
279
+ "input": {
280
+ "type": "object",
281
+ "additionalProperties": false,
282
+ "properties": {
283
+ "type": { "type": "string" },
284
+ "limit": { "type": "integer", "minimum": 1, "maximum": 10000 }
285
+ }
286
+ },
287
+ "output": {
288
+ "type": "object",
289
+ "required": ["events"],
290
+ "properties": {
291
+ "events": { "type": "array", "items": { "type": "object" } }
292
+ }
293
+ }
294
+ }
295
+ },
296
+ "gdd_health": {
297
+ "type": "object",
298
+ "additionalProperties": false,
299
+ "required": ["input", "output"],
300
+ "properties": {
301
+ "input": {
302
+ "type": "object",
303
+ "additionalProperties": false,
304
+ "properties": {}
305
+ },
306
+ "output": {
307
+ "type": "object",
308
+ "required": ["checks"],
309
+ "properties": {
310
+ "checks": {
311
+ "type": "array",
312
+ "items": {
313
+ "type": "object",
314
+ "required": ["name", "status", "detail"],
315
+ "properties": {
316
+ "name": { "type": "string" },
317
+ "status": { "type": "string", "enum": ["ok", "warn", "fail"] },
318
+ "detail": { "type": "string" }
319
+ }
320
+ }
321
+ }
322
+ }
323
+ }
324
+ }
325
+ }
326
+ }
327
+ }
328
+ },
329
+ "definitions": {
330
+ "ToolSchemaEntry": {
331
+ "type": "object",
332
+ "additionalProperties": false,
333
+ "required": ["input", "output"],
334
+ "properties": {
335
+ "input": {
336
+ "type": "object",
337
+ "description": "JSON Schema fragment describing the tool's input parameters."
338
+ },
339
+ "output": {
340
+ "type": "object",
341
+ "description": "JSON Schema fragment describing the tool's response envelope.",
342
+ "required": ["type"],
343
+ "properties": {
344
+ "type": { "type": "string", "enum": ["object"] }
345
+ }
346
+ }
347
+ }
348
+ },
349
+ "ToolError": {
350
+ "type": "object",
351
+ "additionalProperties": false,
352
+ "required": ["code", "message", "kind"],
353
+ "properties": {
354
+ "code": { "type": "string", "minLength": 1 },
355
+ "message": { "type": "string", "minLength": 1 },
356
+ "kind": {
357
+ "type": "string",
358
+ "enum": ["validation", "state_conflict", "operation_failed", "unknown"]
359
+ },
360
+ "mcp_code": {
361
+ "type": "string",
362
+ "description": "Optional MCP-specific code (e.g. 'directory_not_found') projected by errorResponse() when an underlying NotFoundError carries a `code` property."
363
+ },
364
+ "context": {
365
+ "type": "object",
366
+ "additionalProperties": true
367
+ }
368
+ }
369
+ },
370
+ "ToolResponseEnvelope": {
371
+ "type": "object",
372
+ "additionalProperties": false,
373
+ "required": ["success"],
374
+ "properties": {
375
+ "success": { "type": "boolean" },
376
+ "data": { "type": "object" },
377
+ "error": { "$ref": "#/definitions/ToolError" }
378
+ }
379
+ }
380
+ }
381
+ }
@@ -16,6 +16,8 @@ This catalog gives two categories of agent a shared, unambiguous vocabulary for
16
16
 
17
17
  Style names in this file are preserved verbatim from the UUPM source to maintain ecosystem legibility. Do not rename or abbreviate styles when writing context files or audit reports.
18
18
 
19
+ **See:** [`./proportion-systems.md`](./proportion-systems.md) for the whole-UI proportion system (4pt / 8pt / √2 baseline grids, modular relationships across type / spacing / sizing / radius) that the rows below reference when they call out "8pt spacing grid", "12-column grid", "section-level spacing (120–200px vertical rhythm)", and similar grid-anchored signatures.
20
+
19
21
  ---
20
22
 
21
23
  ## Style Table
@@ -35,6 +35,8 @@ Choose a ratio and base size. Common ratios:
35
35
 
36
36
  Never create a scale ad-hoc. Pick one ratio, generate the scale, use only values in the scale.
37
37
 
38
+ **See:** [`./proportion-systems.md`](./proportion-systems.md) §Modular Relationships for how the type scale ties to spacing / sizing / radius scales — when one ratio drives all four scales the whole UI gains a single rhythm rather than four independently-tuned progressions.
39
+
38
40
  ---
39
41
 
40
42
  ## Line Height
@@ -228,6 +230,8 @@ Always include a non-variable fallback of the same family in the font stack:
228
230
  font-family: 'InterVariable', 'Inter', -apple-system, system-ui, sans-serif;
229
231
  ```
230
232
 
233
+ **See:** [`./i18n.md`](./i18n.md) §Multi-Script Font Stacks for when a multi-script project should ship weighted-static fonts rather than a single variable font (some scripts ship as static-only families; mixing scripts in a single variable file is rarely viable).
234
+
231
235
  ---
232
236
 
233
237
  ## Micro-Typography
@@ -75,6 +75,8 @@ The key discipline is intentionality. Asymmetry that emerges from neglect — un
75
75
 
76
76
  Rhythm in layout means that repetition creates a predictable visual beat that the eye can lock onto and traverse quickly. A card grid has rhythm. A consistent heading-body-space pattern has rhythm. Rhythm is not uniformity — it is the reliable expectation that similar content will appear in similar visual form. Break rhythm only to signal importance: a featured item in a grid that is twice the size says "this one matters."
77
77
 
78
+ **See:** [`./composition.md`](./composition.md) §Visual-Weight Calculus for the `size × contrast × isolation × complexity` formula that quantifies why an asymmetric large/small pairing directs the eye toward the heavier element.
79
+
78
80
  ---
79
81
 
80
82
  ## Compositional Grids
@@ -96,6 +98,8 @@ Grids are not aesthetic choices — they are coordination mechanisms. A grid ali
96
98
 
97
99
  A baseline grid aligns text and element heights to a consistent vertical increment — typically 4px or 8px. Every element's height, padding, and margin should be a multiple of this increment. The baseline grid is what makes a layout feel "settled" rather than arbitrarily positioned, because every vertical decision relates to a shared rhythm. In practice, use 8px as the primary increment and 4px for sub-increments only (e.g., within a component's internal padding).
98
100
 
101
+ **See:** [`./composition.md`](./composition.md) §Golden Ratio and Root Rectangles + §Focal-Point Construction for the pre-Gestalt compositional foundations (φ-grid, root rectangles, rule-of-thirds intersections) that complement the responsive-column / baseline-grid coordinations above.
102
+
99
103
  ---
100
104
 
101
105
  ## Figure-Ground Manipulation
@@ -62,6 +62,8 @@ function helpText() {
62
62
  ' --dry-run Print the diff without writing',
63
63
  ' --config-dir D Override the config directory',
64
64
  ' --no-peer-prompt Suppress the post-install peer-CLI detection nudge',
65
+ ' --register-mcp Register gdd-mcp with detected harnesses (Claude Code, Codex). Opt-in.',
66
+ ' --no-register-mcp Skip MCP registration (default behavior; included for symmetry).',
65
67
  ' --help, -h Show this message',
66
68
  '',
67
69
  'Environment overrides (per-runtime):',
@@ -215,6 +217,46 @@ async function main() {
215
217
  );
216
218
  }
217
219
  }
220
+
221
+ // Phase 27.7 / Plan 27.7-04 — opt-in MCP registration (D-07).
222
+ // Fires only on real install (not uninstall, not dry-run) when the user
223
+ // passes --register-mcp explicitly. Default OFF; --no-register-mcp is a
224
+ // no-op today (reserved for symmetry / when default flips). Idempotent
225
+ // + graceful absent-CLI fallback handled inside registerMcp.
226
+ if (!uninstall && !dryRun && flags.has('--register-mcp')) {
227
+ try {
228
+ const { registerMcp } = require('./lib/install/mcp-register.cjs');
229
+ for (const harness of ['claude', 'codex']) {
230
+ try {
231
+ const result = registerMcp({ harness });
232
+ if (!result.detected) {
233
+ process.stderr.write('[install] ' + result.notice + '\n');
234
+ } else if (result.idempotent_skip) {
235
+ process.stdout.write(
236
+ '[install] gdd-mcp already registered with ' + harness + ' — skipping.\n',
237
+ );
238
+ } else if (result.applied) {
239
+ process.stdout.write(
240
+ '[install] gdd-mcp registered with ' + harness + '.\n',
241
+ );
242
+ } else {
243
+ process.stderr.write(
244
+ '[install] gdd-mcp registration with ' + harness + ' failed: exit ' + result.exit_code + '\n',
245
+ );
246
+ }
247
+ } catch (err) {
248
+ process.stderr.write(
249
+ '[install] gdd-mcp registration error (' + harness + '): ' + (err && err.message ? err.message : err) + '\n',
250
+ );
251
+ }
252
+ }
253
+ } catch (e) {
254
+ // mcp-register lib not present (forward-compat) — silent skip.
255
+ process.stderr.write(
256
+ '[install] mcp-register lib unavailable: ' + (e && e.message ? e.message : e) + '\n',
257
+ );
258
+ }
259
+ }
218
260
  }
219
261
 
220
262
  // v1.27.1 — Plan 27-11: post-install nudge. Detects installed peer CLIs,
@@ -0,0 +1,105 @@
1
+ 'use strict';
2
+ // scripts/lib/gsd-health-mirror/index.cjs — Plan 27.7-02
3
+ //
4
+ // Pure read-only mirror of skills/health/SKILL.md's check surface.
5
+ // NO subprocess spawn — just inspects 4 well-known files/dirs and
6
+ // reports status. Used by the gdd_health MCP tool.
7
+ //
8
+ // Surface:
9
+ // async getHealthChecks(rootDir) → { checks: HealthCheck[] }
10
+ //
11
+ // The 4 checks (in stable order) are:
12
+ // 1. claude_md — CLAUDE.md presence
13
+ // 2. planning_dir — .planning/ presence
14
+ // 3. design_dir — .design/ presence
15
+ // 4. package_json — package.json present AND parseable
16
+
17
+ const fs = require('node:fs');
18
+ const path = require('node:path');
19
+
20
+ function fileExists(p) {
21
+ try {
22
+ return fs.statSync(p).isFile();
23
+ } catch {
24
+ return false;
25
+ }
26
+ }
27
+
28
+ function dirExists(p) {
29
+ try {
30
+ return fs.statSync(p).isDirectory();
31
+ } catch {
32
+ return false;
33
+ }
34
+ }
35
+
36
+ async function getHealthChecks(rootDir) {
37
+ const checks = [];
38
+
39
+ // 1. CLAUDE.md
40
+ {
41
+ const p = path.join(rootDir, 'CLAUDE.md');
42
+ const present = fileExists(p);
43
+ checks.push({
44
+ name: 'claude_md',
45
+ status: present ? 'ok' : 'warn',
46
+ detail: present ? p : 'CLAUDE.md not found at project root',
47
+ });
48
+ }
49
+
50
+ // 2. .planning/
51
+ {
52
+ const p = path.join(rootDir, '.planning');
53
+ const present = dirExists(p);
54
+ checks.push({
55
+ name: 'planning_dir',
56
+ status: present ? 'ok' : 'warn',
57
+ detail: present ? p : '.planning/ not found at project root',
58
+ });
59
+ }
60
+
61
+ // 3. .design/
62
+ {
63
+ const p = path.join(rootDir, '.design');
64
+ const present = dirExists(p);
65
+ checks.push({
66
+ name: 'design_dir',
67
+ status: present ? 'ok' : 'warn',
68
+ detail: present ? p : '.design/ not found at project root',
69
+ });
70
+ }
71
+
72
+ // 4. package.json — present + parseable
73
+ {
74
+ const p = path.join(rootDir, 'package.json');
75
+ if (!fileExists(p)) {
76
+ checks.push({
77
+ name: 'package_json',
78
+ status: 'warn',
79
+ detail: 'package.json not found at project root',
80
+ });
81
+ } else {
82
+ try {
83
+ const body = await fs.promises.readFile(p, 'utf8');
84
+ const parsed = JSON.parse(body);
85
+ const name = typeof parsed.name === 'string' ? parsed.name : '(unknown)';
86
+ const version = typeof parsed.version === 'string' ? parsed.version : '0.0.0';
87
+ checks.push({
88
+ name: 'package_json',
89
+ status: 'ok',
90
+ detail: name + '@' + version,
91
+ });
92
+ } catch (err) {
93
+ checks.push({
94
+ name: 'package_json',
95
+ status: 'fail',
96
+ detail: 'parse error: ' + (err && err.message ? err.message : String(err)),
97
+ });
98
+ }
99
+ }
100
+ }
101
+
102
+ return { checks };
103
+ }
104
+
105
+ module.exports = { getHealthChecks };
@@ -0,0 +1,14 @@
1
+ // scripts/lib/gsd-health-mirror/index.d.cts — TypeScript ambient declarations
2
+ // for the gsd-health-mirror CJS module. Plan 27.7-02.
3
+
4
+ export interface HealthCheck {
5
+ name: string;
6
+ status: 'ok' | 'warn' | 'fail';
7
+ detail: string;
8
+ }
9
+
10
+ export interface HealthChecksResult {
11
+ checks: HealthCheck[];
12
+ }
13
+
14
+ export function getHealthChecks(rootDir: string): Promise<HealthChecksResult>;