@edupia-tutor/spec-driven-docs 0.14.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 (339) hide show
  1. package/bin/build.js +230 -0
  2. package/bin/index.js +598 -0
  3. package/commands/debug.md +830 -0
  4. package/commands/debug.tmpl +257 -0
  5. package/commands/define-product.md +652 -0
  6. package/commands/define-product.tmpl +158 -0
  7. package/commands/dev-gen-test.md +1010 -0
  8. package/commands/dev-gen-test.tmpl +490 -0
  9. package/commands/dev-run-test.md +744 -0
  10. package/commands/dev-run-test.tmpl +224 -0
  11. package/commands/dev-smoke-test.md +711 -0
  12. package/commands/dev-smoke-test.tmpl +217 -0
  13. package/commands/fix-bug.md +744 -0
  14. package/commands/fix-bug.tmpl +171 -0
  15. package/commands/generate-bdd.md +1054 -0
  16. package/commands/generate-bdd.tmpl +534 -0
  17. package/commands/generate-code.md +869 -0
  18. package/commands/generate-code.tmpl +349 -0
  19. package/commands/generate-design-spec.md +958 -0
  20. package/commands/generate-design-spec.tmpl +464 -0
  21. package/commands/generate-prd.md +748 -0
  22. package/commands/generate-prd.tmpl +254 -0
  23. package/commands/generate-spec-manifest.md +658 -0
  24. package/commands/generate-spec-manifest.tmpl +164 -0
  25. package/commands/generate-tech-docs.md +849 -0
  26. package/commands/generate-tech-docs.tmpl +355 -0
  27. package/commands/learn.md +636 -0
  28. package/commands/learn.tmpl +63 -0
  29. package/commands/map-testids.md +575 -0
  30. package/commands/map-testids.tmpl +81 -0
  31. package/commands/propose-scenario.md +623 -0
  32. package/commands/propose-scenario.tmpl +129 -0
  33. package/commands/qc-analyze.md +580 -0
  34. package/commands/qc-analyze.tmpl +86 -0
  35. package/commands/qc-design-test.md +562 -0
  36. package/commands/qc-design-test.tmpl +68 -0
  37. package/commands/qc-plan.md +543 -0
  38. package/commands/qc-plan.tmpl +49 -0
  39. package/commands/qc-report.md +554 -0
  40. package/commands/qc-report.tmpl +60 -0
  41. package/commands/qc-review.md +547 -0
  42. package/commands/qc-review.tmpl +53 -0
  43. package/commands/qc-run-test.md +604 -0
  44. package/commands/qc-run-test.tmpl +84 -0
  45. package/commands/refine-prd.md +772 -0
  46. package/commands/refine-prd.tmpl +140 -0
  47. package/commands/report-bug.md +639 -0
  48. package/commands/report-bug.tmpl +145 -0
  49. package/commands/review-code.md +677 -0
  50. package/commands/review-code.tmpl +104 -0
  51. package/commands/review-context.md +1047 -0
  52. package/commands/review-context.tmpl +415 -0
  53. package/commands/review-tech-docs.md +811 -0
  54. package/commands/review-tech-docs.tmpl +317 -0
  55. package/commands/setup-ai-first.md +545 -0
  56. package/commands/setup-ai-first.tmpl +358 -0
  57. package/commands/sync.md +451 -0
  58. package/commands/sync.tmpl +351 -0
  59. package/commands/update-framework.md +251 -0
  60. package/commands/update-framework.tmpl +151 -0
  61. package/commands/validate-traces.md +842 -0
  62. package/commands/validate-traces.tmpl +348 -0
  63. package/core/FRAMEWORK_VERSION +1 -0
  64. package/core/commands/debug.md +830 -0
  65. package/core/commands/define-product.md +652 -0
  66. package/core/commands/dev-gen-test.md +1010 -0
  67. package/core/commands/dev-run-test.md +744 -0
  68. package/core/commands/dev-smoke-test.md +711 -0
  69. package/core/commands/fix-bug.md +744 -0
  70. package/core/commands/generate-bdd.md +1054 -0
  71. package/core/commands/generate-code.md +869 -0
  72. package/core/commands/generate-design-spec.md +958 -0
  73. package/core/commands/generate-prd.md +748 -0
  74. package/core/commands/generate-spec-manifest.md +658 -0
  75. package/core/commands/generate-tech-docs.md +849 -0
  76. package/core/commands/learn.md +636 -0
  77. package/core/commands/map-testids.md +575 -0
  78. package/core/commands/propose-scenario.md +623 -0
  79. package/core/commands/qc-analyze.md +580 -0
  80. package/core/commands/qc-design-test.md +562 -0
  81. package/core/commands/qc-plan.md +543 -0
  82. package/core/commands/qc-report.md +554 -0
  83. package/core/commands/qc-review.md +547 -0
  84. package/core/commands/qc-run-test.md +604 -0
  85. package/core/commands/refine-prd.md +772 -0
  86. package/core/commands/report-bug.md +639 -0
  87. package/core/commands/review-code.md +677 -0
  88. package/core/commands/review-context.md +1047 -0
  89. package/core/commands/review-tech-docs.md +811 -0
  90. package/core/commands/setup-ai-first.md +545 -0
  91. package/core/commands/sync.md +451 -0
  92. package/core/commands/update-framework.md +251 -0
  93. package/core/commands/validate-traces.md +842 -0
  94. package/core/hooks/data-guard.js +141 -0
  95. package/core/hooks/settings.json +18 -0
  96. package/core/modules/android-compose/module.yaml +13 -0
  97. package/core/modules/android-compose/stack-profile.yaml +57 -0
  98. package/core/modules/angular/architecture-snippets/component-patterns.md +187 -0
  99. package/core/modules/angular/module.yaml +6 -0
  100. package/core/modules/angular/stack-profile.yaml +38 -0
  101. package/core/modules/context-engineering/architecture-snippets/context-design.md +119 -0
  102. package/core/modules/context-engineering/module.yaml +9 -0
  103. package/core/modules/context-engineering/stack-profile.yaml +61 -0
  104. package/core/modules/dotnet/architecture-snippets/clean-arch.md +160 -0
  105. package/core/modules/dotnet/module.yaml +6 -0
  106. package/core/modules/dotnet/stack-profile.yaml +50 -0
  107. package/core/modules/flutter/module.yaml +14 -0
  108. package/core/modules/flutter/stack-profile.yaml +59 -0
  109. package/core/modules/golang/architecture-snippets/domain-layout.md +283 -0
  110. package/core/modules/golang/module.yaml +6 -0
  111. package/core/modules/golang/stack-profile.yaml +40 -0
  112. package/core/modules/ios-swiftui/module.yaml +13 -0
  113. package/core/modules/ios-swiftui/stack-profile.yaml +55 -0
  114. package/core/modules/java-spring/architecture-snippets/layered-arch.md +201 -0
  115. package/core/modules/java-spring/module.yaml +15 -0
  116. package/core/modules/java-spring/stack-profile.yaml +28 -0
  117. package/core/modules/nextjs/architecture-snippets/app-router-patterns.md +269 -0
  118. package/core/modules/nextjs/module.yaml +14 -0
  119. package/core/modules/nextjs/stack-profile.yaml +74 -0
  120. package/core/modules/nuxt/module.yaml +14 -0
  121. package/core/modules/nuxt/stack-profile.yaml +58 -0
  122. package/core/modules/php-laravel/architecture-snippets/service-repository.md +302 -0
  123. package/core/modules/php-laravel/module.yaml +15 -0
  124. package/core/modules/php-laravel/stack-profile.yaml +56 -0
  125. package/core/modules/qc-playwright/stack-profile.yaml +66 -0
  126. package/core/modules/react/architecture-snippets/hooks-query-patterns.md +254 -0
  127. package/core/modules/react/module.yaml +14 -0
  128. package/core/modules/react/stack-profile.yaml +63 -0
  129. package/core/modules/react-native/module.yaml +14 -0
  130. package/core/modules/react-native/stack-profile.yaml +56 -0
  131. package/core/modules/vue/module.yaml +14 -0
  132. package/core/modules/vue/stack-profile.yaml +65 -0
  133. package/core/rules/data-protection.md +80 -0
  134. package/core/rules/workflow.md +44 -0
  135. package/core/skills/code/SKILL.md +770 -0
  136. package/core/skills/debug/SKILL.md +869 -0
  137. package/core/skills/design-spec/SKILL.md +589 -0
  138. package/core/skills/discovery/SKILL.md +554 -0
  139. package/core/skills/prd/SKILL.md +562 -0
  140. package/core/skills/qc/qa-analyst/DOC_GAPS.template.md +63 -0
  141. package/core/skills/qc/qa-analyst/acceptance-criteria.md +60 -0
  142. package/core/skills/qc/qa-analyst/business-rules.md +59 -0
  143. package/core/skills/qc/qa-analyst/data-flow.md +64 -0
  144. package/core/skills/qc/qa-analyst/spec-breakdown.md +61 -0
  145. package/core/skills/qc/qa-designer/e2e/journey.md +41 -0
  146. package/core/skills/qc/qa-designer/exploratory/charter.md +68 -0
  147. package/core/skills/qc/qa-designer/exploratory/explore-to-functional.md +43 -0
  148. package/core/skills/qc/qa-designer/functional/api.md +45 -0
  149. package/core/skills/qc/qa-designer/functional/gui-feature.md +46 -0
  150. package/core/skills/qc/qa-designer/functional/gui-screen.md +52 -0
  151. package/core/skills/qc/qa-designer/integration/api.md +42 -0
  152. package/core/skills/qc/qa-designer/integration/db.md +39 -0
  153. package/core/skills/qc/qa-designer/integration/gui.md +40 -0
  154. package/core/skills/qc/qa-designer/integration/kafka.md +40 -0
  155. package/core/skills/qc/qa-designer/non-functional.md +40 -0
  156. package/core/skills/qc/qa-planner/test-plan.md +120 -0
  157. package/core/skills/qc/qa-reviewer/script/e2e.md +87 -0
  158. package/core/skills/qc/qa-reviewer/script/exploratory.md +45 -0
  159. package/core/skills/qc/qa-reviewer/script/functional.md +101 -0
  160. package/core/skills/qc/qa-reviewer/script/integration.md +91 -0
  161. package/core/skills/qc/qa-reviewer/script/non-functional.md +126 -0
  162. package/core/skills/qc/qa-reviewer/test-case/e2e.md +73 -0
  163. package/core/skills/qc/qa-reviewer/test-case/exploratory.md +43 -0
  164. package/core/skills/qc/qa-reviewer/test-case/functional.md +76 -0
  165. package/core/skills/qc/qa-reviewer/test-case/integration.md +69 -0
  166. package/core/skills/qc/qa-reviewer/test-case/non-functional.md +73 -0
  167. package/core/skills/qc/qa-runner/e2e.md +49 -0
  168. package/core/skills/qc/qa-runner/exploratory/session.md +36 -0
  169. package/core/skills/qc/qa-runner/functional/api.md +35 -0
  170. package/core/skills/qc/qa-runner/functional/gui-feature.md +51 -0
  171. package/core/skills/qc/qa-runner/functional/gui-screen.md +55 -0
  172. package/core/skills/qc/qa-runner/integration.md +47 -0
  173. package/core/skills/qc/qa-runner/non-functional.md +49 -0
  174. package/core/skills/qc/qa-runner/report/report.md +37 -0
  175. package/core/skills/setup-ai-first/SKILL.md +216 -0
  176. package/core/skills/spec/SKILL.md +461 -0
  177. package/core/skills/test/SKILL.md +1297 -0
  178. package/core/steps/capture-lesson.md +79 -0
  179. package/core/steps/context-loader.md +307 -0
  180. package/core/steps/gate.md +87 -0
  181. package/core/steps/report-footer.md +100 -0
  182. package/core/steps/review-fanout.md +138 -0
  183. package/core/steps/spawn-agent.md +124 -0
  184. package/core/steps/trace-mirror.md +26 -0
  185. package/core/templates/architecture.template.md +113 -0
  186. package/core/templates/design-spec.template.md +217 -0
  187. package/core/templates/feature.template +259 -0
  188. package/core/templates/platform-guide.template.md +145 -0
  189. package/core/templates/prd.template.md +327 -0
  190. package/core/templates/product-definition.template.md +168 -0
  191. package/core/templates/project-context.yaml +161 -0
  192. package/docs/01-getting-started/README.md +19 -0
  193. package/docs/01-getting-started/core-concepts.md +102 -0
  194. package/docs/01-getting-started/installation.md +156 -0
  195. package/docs/01-getting-started/quickstart.md +85 -0
  196. package/docs/02-guides/README.md +26 -0
  197. package/docs/02-guides/developer/README.md +46 -0
  198. package/docs/02-guides/developer/bdd-and-trace.md +125 -0
  199. package/docs/02-guides/developer/commands.md +76 -0
  200. package/docs/02-guides/developer/pr-checklist.md +15 -0
  201. package/docs/02-guides/developer/scenarios.md +460 -0
  202. package/docs/02-guides/developer/workflow.md +121 -0
  203. package/docs/02-guides/product-owner/README.md +79 -0
  204. package/docs/02-guides/product-owner/commands.md +30 -0
  205. package/docs/02-guides/product-owner/handoff-checklist.md +42 -0
  206. package/docs/02-guides/product-owner/prd-writing-rules.md +45 -0
  207. package/docs/02-guides/product-owner/scenarios.md +436 -0
  208. package/docs/02-guides/tester/README.md +75 -0
  209. package/docs/02-guides/tester/bug-reporting.md +117 -0
  210. package/docs/02-guides/tester/qc-automation.md +165 -0
  211. package/docs/02-guides/tester/reading-specs.md +79 -0
  212. package/docs/02-guides/tester/scenarios.md +186 -0
  213. package/docs/02-guides/tester/spec-manifest.md +130 -0
  214. package/docs/02-guides/tester/test-checklist.md +31 -0
  215. package/docs/02-guides/tester/workflow.md +77 -0
  216. package/docs/03-concepts/README.md +19 -0
  217. package/docs/03-concepts/architecture.md +248 -0
  218. package/docs/03-concepts/pipeline.md +274 -0
  219. package/docs/03-concepts/traceability.md +149 -0
  220. package/docs/04-operations/README.md +33 -0
  221. package/docs/04-operations/bug-flow.md +362 -0
  222. package/docs/04-operations/publishing.md +137 -0
  223. package/docs/04-operations/sync-and-update.md +522 -0
  224. package/docs/05-reference/README.md +32 -0
  225. package/docs/05-reference/command-cheatsheet.md +147 -0
  226. package/docs/05-reference/commands.md +232 -0
  227. package/docs/05-reference/modules.md +110 -0
  228. package/docs/05-reference/trace-schema.md +153 -0
  229. package/docs/README.md +49 -0
  230. package/hooks/data-guard.js +141 -0
  231. package/hooks/settings.json +18 -0
  232. package/modules/android-compose/module.yaml +13 -0
  233. package/modules/android-compose/stack-profile.yaml +57 -0
  234. package/modules/angular/architecture-snippets/component-patterns.md +187 -0
  235. package/modules/angular/module.yaml +6 -0
  236. package/modules/angular/stack-profile.yaml +38 -0
  237. package/modules/context-engineering/architecture-snippets/context-design.md +119 -0
  238. package/modules/context-engineering/module.yaml +9 -0
  239. package/modules/context-engineering/stack-profile.yaml +61 -0
  240. package/modules/dotnet/architecture-snippets/clean-arch.md +160 -0
  241. package/modules/dotnet/module.yaml +6 -0
  242. package/modules/dotnet/stack-profile.yaml +50 -0
  243. package/modules/flutter/module.yaml +14 -0
  244. package/modules/flutter/stack-profile.yaml +59 -0
  245. package/modules/golang/architecture-snippets/domain-layout.md +283 -0
  246. package/modules/golang/module.yaml +6 -0
  247. package/modules/golang/stack-profile.yaml +40 -0
  248. package/modules/ios-swiftui/module.yaml +13 -0
  249. package/modules/ios-swiftui/stack-profile.yaml +55 -0
  250. package/modules/java-spring/architecture-snippets/layered-arch.md +201 -0
  251. package/modules/java-spring/module.yaml +15 -0
  252. package/modules/java-spring/stack-profile.yaml +28 -0
  253. package/modules/nextjs/architecture-snippets/app-router-patterns.md +269 -0
  254. package/modules/nextjs/module.yaml +14 -0
  255. package/modules/nextjs/stack-profile.yaml +74 -0
  256. package/modules/nuxt/module.yaml +14 -0
  257. package/modules/nuxt/stack-profile.yaml +58 -0
  258. package/modules/php-laravel/architecture-snippets/service-repository.md +302 -0
  259. package/modules/php-laravel/module.yaml +15 -0
  260. package/modules/php-laravel/stack-profile.yaml +56 -0
  261. package/modules/qc-playwright/stack-profile.yaml +66 -0
  262. package/modules/react/architecture-snippets/hooks-query-patterns.md +254 -0
  263. package/modules/react/module.yaml +14 -0
  264. package/modules/react/stack-profile.yaml +63 -0
  265. package/modules/react-native/module.yaml +14 -0
  266. package/modules/react-native/stack-profile.yaml +56 -0
  267. package/modules/vue/module.yaml +14 -0
  268. package/modules/vue/stack-profile.yaml +65 -0
  269. package/package.json +49 -0
  270. package/rules/data-protection.md +80 -0
  271. package/rules/workflow.md +44 -0
  272. package/scripts/init.sh +49 -0
  273. package/scripts/migrate-specs.js +256 -0
  274. package/scripts/upgrade.sh +94 -0
  275. package/skills/code/SKILL.md +770 -0
  276. package/skills/code/SKILL.tmpl +176 -0
  277. package/skills/debug/SKILL.md +869 -0
  278. package/skills/debug/SKILL.tmpl +262 -0
  279. package/skills/design-spec/SKILL.md +589 -0
  280. package/skills/design-spec/SKILL.tmpl +95 -0
  281. package/skills/discovery/SKILL.md +554 -0
  282. package/skills/discovery/SKILL.tmpl +147 -0
  283. package/skills/prd/SKILL.md +562 -0
  284. package/skills/prd/SKILL.tmpl +188 -0
  285. package/skills/qc/qa-analyst/DOC_GAPS.template.md +63 -0
  286. package/skills/qc/qa-analyst/acceptance-criteria.md +60 -0
  287. package/skills/qc/qa-analyst/business-rules.md +59 -0
  288. package/skills/qc/qa-analyst/data-flow.md +64 -0
  289. package/skills/qc/qa-analyst/spec-breakdown.md +61 -0
  290. package/skills/qc/qa-designer/e2e/journey.md +41 -0
  291. package/skills/qc/qa-designer/exploratory/charter.md +68 -0
  292. package/skills/qc/qa-designer/exploratory/explore-to-functional.md +43 -0
  293. package/skills/qc/qa-designer/functional/api.md +45 -0
  294. package/skills/qc/qa-designer/functional/gui-feature.md +46 -0
  295. package/skills/qc/qa-designer/functional/gui-screen.md +52 -0
  296. package/skills/qc/qa-designer/integration/api.md +42 -0
  297. package/skills/qc/qa-designer/integration/db.md +39 -0
  298. package/skills/qc/qa-designer/integration/gui.md +40 -0
  299. package/skills/qc/qa-designer/integration/kafka.md +40 -0
  300. package/skills/qc/qa-designer/non-functional.md +40 -0
  301. package/skills/qc/qa-planner/test-plan.md +120 -0
  302. package/skills/qc/qa-reviewer/script/e2e.md +87 -0
  303. package/skills/qc/qa-reviewer/script/exploratory.md +45 -0
  304. package/skills/qc/qa-reviewer/script/functional.md +101 -0
  305. package/skills/qc/qa-reviewer/script/integration.md +91 -0
  306. package/skills/qc/qa-reviewer/script/non-functional.md +126 -0
  307. package/skills/qc/qa-reviewer/test-case/e2e.md +73 -0
  308. package/skills/qc/qa-reviewer/test-case/exploratory.md +43 -0
  309. package/skills/qc/qa-reviewer/test-case/functional.md +76 -0
  310. package/skills/qc/qa-reviewer/test-case/integration.md +69 -0
  311. package/skills/qc/qa-reviewer/test-case/non-functional.md +73 -0
  312. package/skills/qc/qa-runner/e2e.md +49 -0
  313. package/skills/qc/qa-runner/exploratory/session.md +36 -0
  314. package/skills/qc/qa-runner/functional/api.md +35 -0
  315. package/skills/qc/qa-runner/functional/gui-feature.md +51 -0
  316. package/skills/qc/qa-runner/functional/gui-screen.md +55 -0
  317. package/skills/qc/qa-runner/integration.md +47 -0
  318. package/skills/qc/qa-runner/non-functional.md +49 -0
  319. package/skills/qc/qa-runner/report/report.md +37 -0
  320. package/skills/setup-ai-first/SKILL.md +216 -0
  321. package/skills/setup-ai-first/SKILL.tmpl +116 -0
  322. package/skills/spec/SKILL.md +461 -0
  323. package/skills/spec/SKILL.tmpl +174 -0
  324. package/skills/test/SKILL.md +1297 -0
  325. package/skills/test/SKILL.tmpl +296 -0
  326. package/steps/capture-lesson.md +79 -0
  327. package/steps/context-loader.md +307 -0
  328. package/steps/gate.md +87 -0
  329. package/steps/report-footer.md +100 -0
  330. package/steps/review-fanout.md +138 -0
  331. package/steps/spawn-agent.md +124 -0
  332. package/steps/trace-mirror.md +26 -0
  333. package/templates/architecture.template.md +113 -0
  334. package/templates/design-spec.template.md +217 -0
  335. package/templates/feature.template +259 -0
  336. package/templates/platform-guide.template.md +145 -0
  337. package/templates/prd.template.md +327 -0
  338. package/templates/product-definition.template.md +168 -0
  339. package/templates/project-context.yaml +161 -0
package/bin/index.js ADDED
@@ -0,0 +1,598 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+
7
+ const ROOT = path.join(__dirname, '..');
8
+
9
+ const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8'));
10
+ const VERSION = pkg.version;
11
+
12
+ const args = process.argv.slice(2);
13
+ const isMigrateSpecs = args.includes('--migrate-specs');
14
+ const isInit = args.includes('--init');
15
+ const isProject = args.includes('--project');
16
+ const installHooks = args.includes('--hooks');
17
+ const showHelp = args.includes('--help') || args.includes('-h');
18
+
19
+ // --module <name> flag
20
+ const moduleIdx = args.indexOf('--module');
21
+ const moduleName = moduleIdx !== -1 ? args[moduleIdx + 1] : null;
22
+
23
+ // --services backend:java-spring,web-admin:react,app-mobile:flutter
24
+ const servicesIdx = args.indexOf('--services');
25
+ const servicesRaw = servicesIdx !== -1 ? args[servicesIdx + 1] : null;
26
+ const serviceList = servicesRaw
27
+ ? servicesRaw.split(',').map(s => {
28
+ const [name, mod] = s.trim().split(':');
29
+ return { name: name.trim(), module: (mod || '').trim() };
30
+ }).filter(s => s.name)
31
+ : [];
32
+
33
+ const isUmbrella = args.includes('--umbrella');
34
+ const specSourceIdx = args.indexOf('--spec-source');
35
+ const specSource = specSourceIdx !== -1 ? args[specSourceIdx + 1] : null;
36
+
37
+ const AVAILABLE_MODULES = [
38
+ 'java-spring', 'angular', 'react', 'nextjs',
39
+ 'dotnet', 'golang', 'php-laravel', 'context-engineering',
40
+ 'flutter', 'react-native', 'ios-swiftui', 'android-compose',
41
+ ];
42
+
43
+ // Language/framework labels per module (for generated project-context.yaml)
44
+ const MODULE_STACK = {
45
+ 'java-spring': { language: 'Java 17', framework: 'Spring Boot 3.x' },
46
+ 'golang': { language: 'Go', framework: 'Gin / Echo' },
47
+ 'dotnet': { language: 'C#', framework: '.NET / ASP.NET Core' },
48
+ 'php-laravel': { language: 'PHP', framework: 'Laravel' },
49
+ 'context-engineering': { language: 'TypeScript', framework: 'Node.js' },
50
+ 'react': { language: 'TypeScript', framework: 'React' },
51
+ 'nextjs': { language: 'TypeScript', framework: 'Next.js' },
52
+ 'vue': { language: 'TypeScript', framework: 'Vue 3' },
53
+ 'nuxt': { language: 'TypeScript', framework: 'Nuxt 3' },
54
+ 'angular': { language: 'TypeScript', framework: 'Angular' },
55
+ 'flutter': { language: 'Dart', framework: 'Flutter' },
56
+ 'react-native': { language: 'TypeScript', framework: 'React Native / Expo' },
57
+ 'ios-swiftui': { language: 'Swift', framework: 'SwiftUI' },
58
+ 'android-compose': { language: 'Kotlin', framework: 'Jetpack Compose' },
59
+ };
60
+
61
+ if (showHelp) {
62
+ console.log('Usage: npx @edupia-tutor/spec-driven-docs [options]');
63
+ console.log('');
64
+ console.log('Install modes:');
65
+ console.log(' --init Install framework to .agent/ + create shortcuts in .claude/commands/');
66
+ console.log(' Recommended for new projects. Run upgrade.sh to upgrade later.');
67
+ console.log(' --init --umbrella Umbrella repo setup: installs framework at umbrella level only.');
68
+ console.log(' Generates project-context.yaml with services routing.');
69
+ console.log(' Does NOT install into service submodule directories.');
70
+ console.log(' --project Install full commands to ./.claude/commands/ (project-scoped, legacy)');
71
+ console.log(' (no flag) Install full commands to ~/.claude/commands/ (global, legacy)');
72
+ console.log('');
73
+ console.log('Maintenance:');
74
+ console.log(' --migrate-specs Migrate an existing project from the legacy artifact-type-first');
75
+ console.log(' spec layout (specs/prd, specs/bdd, ...) to the feature-package');
76
+ console.log(' layout (specs/{domain}/{prd-slug}/{prd.md,bdd/,tech-docs/,...}).');
77
+ console.log(' DRY-RUN by default; add --apply to execute. Uses git mv when possible.');
78
+ console.log('');
79
+ console.log('Options:');
80
+ console.log(' --module <name> Copy stack module to .agent/modules/<name>/');
81
+ console.log(' --services <list> Monorepo setup: install into each service subfolder in one command.');
82
+ console.log(' Format: name:module,name:module,...');
83
+ console.log(' Example: backend:java-spring,web-admin:react,app-mobile:flutter');
84
+ console.log(' --umbrella Umbrella mode (use with --init). See above.');
85
+ console.log(' --spec-source <path> Path to PO spec submodule (e.g. free-trial-specs).');
86
+ console.log(' Auto-configures prd_dir, design_spec_dir, domain_knowledge_dir.');
87
+ console.log(' --hooks Install data-guard hook to .claude/hooks/ + update .claude/settings.json');
88
+ console.log('');
89
+ console.log('Available modules:');
90
+ AVAILABLE_MODULES.forEach(m => console.log(` ${m}`));
91
+ console.log('');
92
+ console.log('Examples:');
93
+ console.log(' npx @edupia-tutor/spec-driven-docs --init # single-service project');
94
+ console.log(' npx @edupia-tutor/spec-driven-docs --init --module java-spring # with stack module');
95
+ console.log(' npx @edupia-tutor/spec-driven-docs --init \\');
96
+ console.log(' --services backend:java-spring,web-admin:react,app-mobile:flutter # monorepo setup');
97
+ console.log(' npx @edupia-tutor/spec-driven-docs --init --umbrella \\');
98
+ console.log(' --spec-source free-trial-specs \\');
99
+ console.log(' --services mass-product-web:nextjs # umbrella with one FE service');
100
+ console.log(' npx @edupia-tutor/spec-driven-docs --project --hooks # legacy project install');
101
+ process.exit(0);
102
+ }
103
+
104
+ // ── --migrate-specs: migrate a consumer repo to the feature-package layout ──
105
+ // Runs BEFORE the build step — this operates on the user's specs, not the package.
106
+ if (isMigrateSpecs) {
107
+ require(path.join(__dirname, '..', 'scripts', 'migrate-specs.js'));
108
+ return; // migrate-specs.js calls process.exit itself
109
+ }
110
+
111
+ // ── Step 1: Build .tmpl → .md ─────────────────────────────────────────────
112
+ const buildScript = path.join(__dirname, 'build.js');
113
+ if (fs.existsSync(buildScript)) {
114
+ try {
115
+ require(buildScript);
116
+ } catch (err) {
117
+ console.error('Build step failed:', err.message);
118
+ process.exit(1);
119
+ }
120
+ }
121
+
122
+ // ── --init mode: install to .agent/ + create .claude/commands/ shortcuts ─────
123
+ if (isInit) {
124
+ const coreDir = path.join(ROOT, 'core');
125
+
126
+ if (!fs.existsSync(coreDir)) {
127
+ console.error('');
128
+ console.error('❌ core/ directory not found.');
129
+ console.error(' The package may not have been built correctly.');
130
+ process.exit(1);
131
+ }
132
+
133
+ const projectRoot = process.cwd();
134
+ const agentDir = path.join(projectRoot, '.agent');
135
+ const claudeCommandsDir = path.join(projectRoot, '.claude', 'commands');
136
+ const frameworkVersion = fs.readFileSync(path.join(coreDir, 'FRAMEWORK_VERSION'), 'utf8').trim();
137
+
138
+ console.log('');
139
+ console.log('╔══════════════════════════════════════════╗');
140
+ console.log('║ Spec-Driven Docs — Project Init ║');
141
+ console.log(`║ v${frameworkVersion} (Edupia Team) ║`);
142
+ console.log('╚══════════════════════════════════════════╝');
143
+ console.log('');
144
+ console.log(`Target : ${agentDir}`);
145
+ if (moduleName) console.log(`Module : ${moduleName}`);
146
+ console.log('');
147
+
148
+ // 1. Copy core/** → .agent/**
149
+ console.log('Installing framework files to .agent/ ...');
150
+ console.log('');
151
+ copyDirRecursive(coreDir, agentDir);
152
+
153
+ const agentSubdirs = fs.readdirSync(agentDir, { withFileTypes: true })
154
+ .filter(e => e.isDirectory())
155
+ .map(e => e.name);
156
+ for (const sub of agentSubdirs) {
157
+ console.log(` ✅ .agent/${sub}/`);
158
+ }
159
+ console.log(` ✅ .agent/FRAMEWORK_VERSION (v${frameworkVersion})`);
160
+
161
+ // 2. Create .claude/commands/ shortcuts that delegate to .agent/commands/
162
+ console.log('');
163
+ console.log('Creating .claude/commands/ shortcuts ...');
164
+ console.log('');
165
+ fs.mkdirSync(claudeCommandsDir, { recursive: true });
166
+
167
+ const agentCommandsDir = path.join(agentDir, 'commands');
168
+ const commandFiles = fs.readdirSync(agentCommandsDir).filter(f => f.endsWith('.md'));
169
+ const failedShortcuts = [];
170
+
171
+ for (const cmdFile of commandFiles) {
172
+ const cmdName = cmdFile.replace('.md', '');
173
+ const shortcut =
174
+ `# /${cmdName}\n` +
175
+ `\n` +
176
+ `Read the full command definition from \`.agent/commands/${cmdFile}\`` +
177
+ ` and execute it with arguments: $ARGUMENTS\n`;
178
+ try {
179
+ fs.writeFileSync(path.join(claudeCommandsDir, cmdFile), shortcut, 'utf8');
180
+ console.log(` ✅ /${cmdName}`);
181
+ } catch {
182
+ console.log(` ❌ /${cmdName} (failed to write shortcut)`);
183
+ failedShortcuts.push(cmdName);
184
+ }
185
+ }
186
+
187
+ // 3. Install module (optional --module flag)
188
+ if (moduleName) {
189
+ console.log('');
190
+ if (!AVAILABLE_MODULES.includes(moduleName)) {
191
+ console.log(`⚠️ Unknown module: "${moduleName}"`);
192
+ console.log(` Available: ${AVAILABLE_MODULES.join(', ')}`);
193
+ } else {
194
+ const srcModuleDir = path.join(ROOT, 'modules', moduleName);
195
+ const destModuleDir = path.join(agentDir, 'modules', moduleName);
196
+ fs.mkdirSync(destModuleDir, { recursive: true });
197
+ copyDirRecursive(srcModuleDir, destModuleDir);
198
+ console.log(`✅ Module "${moduleName}" installed to: .agent/modules/${moduleName}`);
199
+ }
200
+ }
201
+
202
+ // 4. Install data-guard hook (optional --hooks flag)
203
+ if (installHooks) {
204
+ console.log('');
205
+ installDataGuardHook();
206
+ }
207
+
208
+ // 5-alt. Umbrella mode: generate umbrella project-context.yaml (do NOT install into submodules)
209
+ if (isUmbrella) {
210
+ const rootCtxPath = path.join(agentDir, 'project-context.yaml');
211
+ if (!fs.existsSync(rootCtxPath)) {
212
+ const specSrc = specSource || 'TODO-spec-submodule';
213
+
214
+ let servicesBlock = '';
215
+ if (serviceList.length > 0) {
216
+ servicesBlock = serviceList.map(s => [
217
+ ` ${s.name}:`,
218
+ ` path: "${s.name}"`,
219
+ ` module: "${s.module || 'TODO'}"`,
220
+ ` specs_dir: "${s.name}/specs/bdd"`,
221
+ ].join('\n')).join('\n');
222
+ } else {
223
+ servicesBlock = [
224
+ ` # {domain}:`,
225
+ ` # path: "{service-submodule-dir}"`,
226
+ ` # module: "{stack-module}"`,
227
+ ` # specs_dir: "{service-dir}/specs/bdd"`,
228
+ ].join('\n');
229
+ }
230
+
231
+ const domainsBlock = serviceList.length > 0
232
+ ? serviceList.map(s => ` - "${s.name}"`).join('\n')
233
+ : ` - "TODO"`;
234
+
235
+ const umbrellaYaml = [
236
+ `project:`,
237
+ ` name: "${path.basename(projectRoot)}"`,
238
+ ` description: ""`,
239
+ ``,
240
+ `setup:`,
241
+ ` mode: umbrella`,
242
+ ` spec_source: "${specSrc}"`,
243
+ ``,
244
+ `# Paths auto-derived from spec_source by context-loader.`,
245
+ `# Override here only if your structure differs.`,
246
+ `paths:`,
247
+ ` prd_dir: "${specSrc}/specs/prd"`,
248
+ ` design_spec_dir: "${specSrc}/specs/design-spec"`,
249
+ ` tech_docs_dir: "${specSrc}/specs/tech-docs" # API contract — shared (BE pushes here, FE/App read via /sync)`,
250
+ ` domain_knowledge_dir: "${specSrc}/specs/domain-knowledge"`,
251
+ ` business_dictionary: "${specSrc}/specs/domain-knowledge/business-dictionary.md"`,
252
+ ` core_entities: "${specSrc}/specs/domain-knowledge/core-entities.md"`,
253
+ ` product_definitions_dir: "${specSrc}/specs/product-definition"`,
254
+ ` refinement_dir: ".agent/review"`,
255
+ ` trace_dir: ".trace"`,
256
+ ``,
257
+ `# Domain → service submodule routing.`,
258
+ `# Each key must match @trace.domain in your PRD files.`,
259
+ `services:`,
260
+ servicesBlock,
261
+ ``,
262
+ `tech_stack:`,
263
+ ` language: multi-service`,
264
+ ` module: ""`,
265
+ ``,
266
+ `conventions:`,
267
+ ` ticket_prefix: FEAT`,
268
+ ``,
269
+ `domains:`,
270
+ domainsBlock,
271
+ ``,
272
+ ].join('\n');
273
+
274
+ fs.writeFileSync(rootCtxPath, umbrellaYaml, 'utf8');
275
+ console.log('');
276
+ console.log(' ✅ .agent/project-context.yaml (umbrella mode, generated)');
277
+ if (specSource) console.log(` spec_source : ${specSrc}`);
278
+ if (serviceList.length > 0) console.log(` services : ${serviceList.map(s => s.name).join(', ')}`);
279
+ } else {
280
+ console.log(' ℹ️ .agent/project-context.yaml (already exists — skipped)');
281
+ }
282
+ }
283
+
284
+ // 5. Monorepo: install into each service subfolder
285
+ if (serviceList.length > 0) {
286
+ console.log('');
287
+ console.log(`Setting up ${serviceList.length} service workspace(s)...`);
288
+
289
+ for (const svc of serviceList) {
290
+ const svcDir = path.join(projectRoot, svc.name);
291
+ const svcAgentDir = path.join(svcDir, '.agent');
292
+ const svcClaudeCmds = path.join(svcDir, '.claude', 'commands');
293
+
294
+ console.log('');
295
+ console.log(` ── ${svc.name} (${svc.module || 'no module'}) ──`);
296
+
297
+ // Create service dir if needed
298
+ fs.mkdirSync(svcDir, { recursive: true });
299
+
300
+ // Copy core → service/.agent/
301
+ copyDirRecursive(coreDir, svcAgentDir);
302
+ console.log(` ✅ ${svc.name}/.agent/`);
303
+
304
+ // Install module
305
+ if (svc.module) {
306
+ if (!AVAILABLE_MODULES.includes(svc.module)) {
307
+ console.log(` ⚠️ Unknown module "${svc.module}" — skipped`);
308
+ } else {
309
+ const srcMod = path.join(ROOT, 'modules', svc.module);
310
+ const destMod = path.join(svcAgentDir, 'modules', svc.module);
311
+ if (fs.existsSync(srcMod)) {
312
+ fs.mkdirSync(destMod, { recursive: true });
313
+ copyDirRecursive(srcMod, destMod);
314
+ console.log(` ✅ ${svc.name}/.agent/modules/${svc.module}/`);
315
+ }
316
+ }
317
+ }
318
+
319
+ // Create .claude/commands/ shortcuts
320
+ fs.mkdirSync(svcClaudeCmds, { recursive: true });
321
+ const svcCmdFiles = fs.readdirSync(path.join(svcAgentDir, 'commands')).filter(f => f.endsWith('.md'));
322
+ for (const cmdFile of svcCmdFiles) {
323
+ const cmdName = cmdFile.replace('.md', '');
324
+ const shortcut =
325
+ `# /${cmdName}\n\nRead the full command definition from \`.agent/commands/${cmdFile}\`` +
326
+ ` and execute it with arguments: $ARGUMENTS\n`;
327
+ fs.writeFileSync(path.join(svcClaudeCmds, cmdFile), shortcut, 'utf8');
328
+ }
329
+ console.log(` ✅ ${svc.name}/.claude/commands/ (${svcCmdFiles.length} shortcuts)`);
330
+
331
+ // Generate project-context.yaml (only if not already present)
332
+ const ctxPath = path.join(svcAgentDir, 'project-context.yaml');
333
+ if (!fs.existsSync(ctxPath)) {
334
+ const stack = MODULE_STACK[svc.module] || { language: 'TODO', framework: 'TODO' };
335
+ const yaml = [
336
+ `project:`,
337
+ ` name: ${path.basename(projectRoot)} — ${svc.name}`,
338
+ ``,
339
+ `tech_stack:`,
340
+ ` language: ${stack.language}`,
341
+ ` framework: ${stack.framework}`,
342
+ ` module: ${svc.module || 'TODO'}`,
343
+ ``,
344
+ `conventions:`,
345
+ ` ticket_prefix: FEAT`,
346
+ ``,
347
+ `paths:`,
348
+ ` specs_dir: ../specs/bdd`,
349
+ ` prd_dir: ../specs/prd`,
350
+ ` tech_docs_dir: ../specs/tech-docs`,
351
+ ` domain_knowledge_dir: ../specs/domain-knowledge`,
352
+ ` business_dictionary: ../specs/domain-knowledge/business-dictionary.md`,
353
+ ` core_entities: ../specs/domain-knowledge/core-entities.md`,
354
+ ` refinement_dir: ../specs/.review`,
355
+ ` product_definitions_dir: ../specs/product-definition`,
356
+ ` trace_dir: ../.trace`,
357
+ ``,
358
+ ].join('\n');
359
+ fs.writeFileSync(ctxPath, yaml, 'utf8');
360
+ console.log(` ✅ ${svc.name}/.agent/project-context.yaml (generated)`);
361
+ } else {
362
+ console.log(` ℹ️ ${svc.name}/.agent/project-context.yaml (already exists — skipped)`);
363
+ }
364
+ }
365
+
366
+ // Generate root project-context.yaml for PO/BA (only if not present)
367
+ const rootCtxPath = path.join(agentDir, 'project-context.yaml');
368
+ if (!fs.existsSync(rootCtxPath)) {
369
+ const svcYaml = serviceList.map(s => [
370
+ ` - name: ${s.name}`,
371
+ ` module: ${s.module || 'TODO'}`,
372
+ ` description: ""`,
373
+ ].join('\n')).join('\n');
374
+ const rootYaml = [
375
+ `project:`,
376
+ ` name: ${path.basename(projectRoot)}`,
377
+ ``,
378
+ `tech_stack:`,
379
+ ` language: multi-service`,
380
+ ``,
381
+ `services:`,
382
+ svcYaml,
383
+ ``,
384
+ `conventions:`,
385
+ ` ticket_prefix: FEAT`,
386
+ ``,
387
+ `paths:`,
388
+ ` specs_dir: specs/bdd`,
389
+ ` prd_dir: specs/prd`,
390
+ ` tech_docs_dir: specs/tech-docs`,
391
+ ` domain_knowledge_dir: specs/domain-knowledge`,
392
+ ` business_dictionary: specs/domain-knowledge/business-dictionary.md`,
393
+ ` core_entities: specs/domain-knowledge/core-entities.md`,
394
+ ` refinement_dir: specs/.review`,
395
+ ` product_definitions_dir: specs/product-definition`,
396
+ ` trace_dir: .trace`,
397
+ ``,
398
+ ].join('\n');
399
+ fs.writeFileSync(rootCtxPath, rootYaml, 'utf8');
400
+ console.log('');
401
+ console.log(' ✅ .agent/project-context.yaml (root — PO/BA workspace, generated)');
402
+ }
403
+ }
404
+
405
+ // 6. Summary
406
+ console.log('');
407
+ if (failedShortcuts.length > 0) {
408
+ console.log(`⚠️ ${commandFiles.length - failedShortcuts.length}/${commandFiles.length} shortcuts created.`);
409
+ process.exit(1);
410
+ }
411
+ console.log(`✅ Framework v${frameworkVersion} installed!`);
412
+ console.log('');
413
+ if (isUmbrella) {
414
+ console.log('Umbrella workspace ready:');
415
+ console.log(' Open Claude Code at project root (umbrella)');
416
+ console.log(' Agent reads specs from: ' + (specSource || 'spec_source in project-context.yaml'));
417
+ if (serviceList.length > 0) {
418
+ console.log(' Service submodules configured:');
419
+ serviceList.forEach(s => console.log(` ${s.name} (${s.module || 'no module'})`));
420
+ }
421
+ console.log('');
422
+ console.log('Next steps:');
423
+ console.log(' 1. Review .agent/project-context.yaml — update service paths + domain names');
424
+ console.log(' 2. Run /setup-ai-first in Claude Code');
425
+ console.log(' 3. Commit .agent/ to git');
426
+ console.log('');
427
+ } else
428
+ if (serviceList.length > 0) {
429
+ console.log('Monorepo workspaces ready:');
430
+ console.log(' PO/BA → open Claude Code at project root');
431
+ serviceList.forEach(s => {
432
+ console.log(` ${s.name.padEnd(10)} → open Claude Code at ./${s.name}/`);
433
+ });
434
+ console.log('');
435
+ console.log('Next steps:');
436
+ console.log(' 1. Fill in CLAUDE.md in each service subfolder (architecture + coding standards)');
437
+ console.log(' 2. Fill in .agent/project-context.yaml in each subfolder (review generated values)');
438
+ console.log(' 3. PO/BA: open root in Claude Code and run /setup-ai-first');
439
+ console.log(' 4. Commit everything to git so the whole team has the framework');
440
+ } else {
441
+ console.log('Next steps:');
442
+ console.log(' 1. Open Claude Code and run /setup-ai-first');
443
+ console.log(' 2. Commit .agent/ to git so your whole team has the framework');
444
+ }
445
+ console.log('');
446
+ console.log('To upgrade later: bash scripts/upgrade.sh');
447
+ console.log(' (or: npx @edupia-tutor/spec-driven-docs@latest --init)');
448
+ console.log('');
449
+ process.exit(0);
450
+ }
451
+
452
+ // ── Banner (legacy --project / global modes) ──────────────────────────────
453
+ const targetDir = isProject
454
+ ? path.join(process.cwd(), '.claude', 'commands')
455
+ : path.join(os.homedir(), '.claude', 'commands');
456
+
457
+ const scope = isProject ? 'project' : 'global';
458
+
459
+ console.log('');
460
+ console.log('╔══════════════════════════════════════════╗');
461
+ console.log('║ Spec-Driven Docs — CLI Installer ║');
462
+ console.log(`║ v${VERSION} (Edupia Team) ║`);
463
+ console.log('╚══════════════════════════════════════════╝');
464
+ console.log('');
465
+ console.log(`Scope : ${scope}`);
466
+ console.log(`Target : ${targetDir}`);
467
+ if (moduleName) console.log(`Module : ${moduleName}`);
468
+ if (installHooks) console.log('Hooks : enabled');
469
+ console.log('');
470
+
471
+ // ── Step 2: Install commands ──────────────────────────────────────────────
472
+ fs.mkdirSync(targetDir, { recursive: true });
473
+
474
+ const commandsDir = path.join(ROOT, 'commands');
475
+ const commands = fs.readdirSync(commandsDir).filter(f => f.endsWith('.md'));
476
+ const failed = [];
477
+
478
+ for (const cmd of commands) {
479
+ try {
480
+ fs.copyFileSync(path.join(commandsDir, cmd), path.join(targetDir, cmd));
481
+ console.log(` ✅ ${cmd.replace('.md', '')}`);
482
+ } catch {
483
+ console.log(` ❌ ${cmd.replace('.md', '')} (failed)`);
484
+ failed.push(cmd);
485
+ }
486
+ }
487
+
488
+ console.log('');
489
+
490
+ if (failed.length > 0) {
491
+ console.log(`⚠️ Installed ${commands.length - failed.length}/${commands.length} commands. Failed: ${failed.join(', ')}`);
492
+ process.exit(1);
493
+ }
494
+
495
+ console.log(`✅ Installed ${commands.length}/${commands.length} commands to:`);
496
+ console.log(` ${targetDir}`);
497
+
498
+ // ── Step 3: Install module (optional) ─────────────────────────────────────
499
+ if (moduleName) {
500
+ console.log('');
501
+ if (!AVAILABLE_MODULES.includes(moduleName)) {
502
+ console.log(`⚠️ Unknown module: "${moduleName}"`);
503
+ console.log(` Available: ${AVAILABLE_MODULES.join(', ')}`);
504
+ process.exit(1);
505
+ }
506
+
507
+ const srcModuleDir = path.join(ROOT, 'modules', moduleName);
508
+ const destModuleDir = path.join(process.cwd(), '.agent', 'modules', moduleName);
509
+
510
+ fs.mkdirSync(destModuleDir, { recursive: true });
511
+ copyDirRecursive(srcModuleDir, destModuleDir);
512
+
513
+ console.log(`✅ Module "${moduleName}" installed to:`);
514
+ console.log(` ${destModuleDir}`);
515
+ }
516
+
517
+ // ── Step 4: Install data-guard hook (optional, --hooks flag) ──────────────
518
+ if (installHooks) {
519
+ console.log('');
520
+ installDataGuardHook();
521
+ }
522
+
523
+ // ── Summary ───────────────────────────────────────────────────────────────
524
+ console.log('');
525
+ console.log('Next steps:');
526
+ console.log(' 1. Open your project in Claude Code');
527
+ console.log(' 2. Type /setup-ai-first to initialize the workflow');
528
+ console.log(' 3. Type / to browse all available commands');
529
+ if (!moduleName) {
530
+ console.log('');
531
+ console.log(`Tip: re-run with --module <name> to install a stack profile.`);
532
+ console.log(` Available: ${AVAILABLE_MODULES.join(', ')}`);
533
+ }
534
+ if (!installHooks) {
535
+ console.log('');
536
+ console.log('Tip: re-run with --hooks to install data-guard hook (sensitive file protection).');
537
+ }
538
+ console.log('');
539
+
540
+ // ── Helpers ───────────────────────────────────────────────────────────────
541
+
542
+ function copyDirRecursive(src, dest) {
543
+ fs.mkdirSync(dest, { recursive: true });
544
+ for (const entry of fs.readdirSync(src)) {
545
+ const srcPath = path.join(src, entry);
546
+ const destPath = path.join(dest, entry);
547
+ if (fs.statSync(srcPath).isDirectory()) {
548
+ copyDirRecursive(srcPath, destPath);
549
+ } else {
550
+ fs.copyFileSync(srcPath, destPath);
551
+ }
552
+ }
553
+ }
554
+
555
+ function installDataGuardHook() {
556
+ const projectRoot = process.cwd();
557
+ const hooksDir = path.join(projectRoot, '.claude', 'hooks');
558
+ const settingsPath = path.join(projectRoot, '.claude', 'settings.json');
559
+
560
+ // 1. Copy hook script
561
+ fs.mkdirSync(hooksDir, { recursive: true });
562
+ const srcHook = path.join(ROOT, 'hooks', 'data-guard.js');
563
+ const destHook = path.join(hooksDir, 'data-guard.js');
564
+ fs.copyFileSync(srcHook, destHook);
565
+ console.log(` ✅ Hook copied to: .claude/hooks/data-guard.js`);
566
+
567
+ // 2. Update .claude/settings.json
568
+ let settings = {};
569
+ if (fs.existsSync(settingsPath)) {
570
+ try { settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8')); } catch {}
571
+ }
572
+
573
+ // Merge: add PreToolUse hook if not already present
574
+ if (!settings.hooks) settings.hooks = {};
575
+ if (!settings.hooks.PreToolUse) settings.hooks.PreToolUse = [];
576
+
577
+ const hookEntry = {
578
+ matcher: 'Read|Write|Edit|Bash',
579
+ hooks: [{ type: 'command', command: 'node .claude/hooks/data-guard.js' }],
580
+ };
581
+
582
+ const alreadyRegistered = settings.hooks.PreToolUse.some(
583
+ h => h.hooks && h.hooks.some(hh => hh.command && hh.command.includes('data-guard.js'))
584
+ );
585
+
586
+ if (!alreadyRegistered) {
587
+ settings.hooks.PreToolUse.push(hookEntry);
588
+ fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
589
+ console.log(` ✅ Hook registered in: .claude/settings.json`);
590
+ } else {
591
+ console.log(` ℹ️ Hook already registered in .claude/settings.json`);
592
+ }
593
+
594
+ console.log('');
595
+ console.log(' 🔒 Data guard active — AI will be blocked from reading:');
596
+ console.log(' .env*, *.key, *.pem, *secret*, *password*, *credential*');
597
+ console.log(' application-prod.*, appsettings.Production.json, ...');
598
+ }