@anhth2/spec-driven-dev-plugin 0.5.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 (152) hide show
  1. package/ARCHITECTURE.md +243 -0
  2. package/bin/build.js +230 -0
  3. package/bin/index.js +311 -0
  4. package/commands/debug.md +374 -0
  5. package/commands/debug.tmpl +77 -0
  6. package/commands/define-product.md +451 -0
  7. package/commands/define-product.tmpl +154 -0
  8. package/commands/fix-bug.md +379 -0
  9. package/commands/fix-bug.tmpl +82 -0
  10. package/commands/generate-bdd.md +591 -0
  11. package/commands/generate-bdd.tmpl +294 -0
  12. package/commands/generate-code.md +395 -0
  13. package/commands/generate-code.tmpl +98 -0
  14. package/commands/generate-prd.md +488 -0
  15. package/commands/generate-prd.tmpl +191 -0
  16. package/commands/generate-tech-docs.md +362 -0
  17. package/commands/generate-tech-docs.tmpl +65 -0
  18. package/commands/generate-tests.md +377 -0
  19. package/commands/generate-tests.tmpl +80 -0
  20. package/commands/refine-prd.md +408 -0
  21. package/commands/refine-prd.tmpl +111 -0
  22. package/commands/review-code.md +354 -0
  23. package/commands/review-code.tmpl +57 -0
  24. package/commands/review-context.md +646 -0
  25. package/commands/review-context.tmpl +349 -0
  26. package/commands/review-tech-docs.md +518 -0
  27. package/commands/review-tech-docs.tmpl +221 -0
  28. package/commands/run-tests.md +343 -0
  29. package/commands/run-tests.tmpl +46 -0
  30. package/commands/setup-ai-first.md +278 -0
  31. package/commands/setup-ai-first.tmpl +197 -0
  32. package/commands/smoke-test.md +366 -0
  33. package/commands/smoke-test.tmpl +69 -0
  34. package/commands/validate-traces.md +529 -0
  35. package/commands/validate-traces.tmpl +232 -0
  36. package/core/FRAMEWORK_VERSION +1 -0
  37. package/core/commands/debug.md +374 -0
  38. package/core/commands/define-product.md +451 -0
  39. package/core/commands/fix-bug.md +379 -0
  40. package/core/commands/generate-bdd.md +591 -0
  41. package/core/commands/generate-code.md +395 -0
  42. package/core/commands/generate-prd.md +488 -0
  43. package/core/commands/generate-tech-docs.md +362 -0
  44. package/core/commands/generate-tests.md +377 -0
  45. package/core/commands/refine-prd.md +408 -0
  46. package/core/commands/review-code.md +354 -0
  47. package/core/commands/review-context.md +646 -0
  48. package/core/commands/review-tech-docs.md +518 -0
  49. package/core/commands/run-tests.md +343 -0
  50. package/core/commands/setup-ai-first.md +278 -0
  51. package/core/commands/smoke-test.md +366 -0
  52. package/core/commands/validate-traces.md +529 -0
  53. package/core/hooks/data-guard.js +141 -0
  54. package/core/hooks/settings.json +18 -0
  55. package/core/modules/angular/architecture-snippets/component-patterns.md +187 -0
  56. package/core/modules/angular/module.yaml +6 -0
  57. package/core/modules/angular/stack-profile.yaml +38 -0
  58. package/core/modules/context-engineering/architecture-snippets/context-design.md +119 -0
  59. package/core/modules/context-engineering/module.yaml +9 -0
  60. package/core/modules/context-engineering/stack-profile.yaml +61 -0
  61. package/core/modules/dotnet/architecture-snippets/clean-arch.md +160 -0
  62. package/core/modules/dotnet/module.yaml +6 -0
  63. package/core/modules/dotnet/stack-profile.yaml +50 -0
  64. package/core/modules/golang/architecture-snippets/domain-layout.md +283 -0
  65. package/core/modules/golang/module.yaml +6 -0
  66. package/core/modules/golang/stack-profile.yaml +40 -0
  67. package/core/modules/java-spring/architecture-snippets/layered-arch.md +201 -0
  68. package/core/modules/java-spring/module.yaml +15 -0
  69. package/core/modules/java-spring/stack-profile.yaml +28 -0
  70. package/core/modules/nextjs/architecture-snippets/app-router-patterns.md +269 -0
  71. package/core/modules/nextjs/module.yaml +14 -0
  72. package/core/modules/nextjs/stack-profile.yaml +74 -0
  73. package/core/modules/php-laravel/architecture-snippets/service-repository.md +302 -0
  74. package/core/modules/php-laravel/module.yaml +15 -0
  75. package/core/modules/php-laravel/stack-profile.yaml +56 -0
  76. package/core/modules/react/architecture-snippets/hooks-query-patterns.md +254 -0
  77. package/core/modules/react/module.yaml +14 -0
  78. package/core/modules/react/stack-profile.yaml +63 -0
  79. package/core/rules/data-protection.md +80 -0
  80. package/core/rules/workflow.md +44 -0
  81. package/core/skills/code/SKILL.md +526 -0
  82. package/core/skills/debug/SKILL.md +584 -0
  83. package/core/skills/discovery/SKILL.md +363 -0
  84. package/core/skills/prd/SKILL.md +456 -0
  85. package/core/skills/setup-ai-first/SKILL.md +160 -0
  86. package/core/skills/spec/SKILL.md +361 -0
  87. package/core/skills/test/SKILL.md +862 -0
  88. package/core/steps/context-loader.md +163 -0
  89. package/core/steps/gate.md +81 -0
  90. package/core/steps/report-footer.md +53 -0
  91. package/core/steps/spawn-agent.md +123 -0
  92. package/core/templates/architecture.template.md +113 -0
  93. package/core/templates/feature.template +259 -0
  94. package/core/templates/platform-guide.template.md +145 -0
  95. package/core/templates/prd.template.md +312 -0
  96. package/core/templates/product-definition.template.md +168 -0
  97. package/core/templates/project-context.yaml +78 -0
  98. package/hooks/data-guard.js +141 -0
  99. package/hooks/settings.json +18 -0
  100. package/modules/angular/architecture-snippets/component-patterns.md +187 -0
  101. package/modules/angular/module.yaml +6 -0
  102. package/modules/angular/stack-profile.yaml +38 -0
  103. package/modules/context-engineering/architecture-snippets/context-design.md +119 -0
  104. package/modules/context-engineering/module.yaml +9 -0
  105. package/modules/context-engineering/stack-profile.yaml +61 -0
  106. package/modules/dotnet/architecture-snippets/clean-arch.md +160 -0
  107. package/modules/dotnet/module.yaml +6 -0
  108. package/modules/dotnet/stack-profile.yaml +50 -0
  109. package/modules/golang/architecture-snippets/domain-layout.md +283 -0
  110. package/modules/golang/module.yaml +6 -0
  111. package/modules/golang/stack-profile.yaml +40 -0
  112. package/modules/java-spring/architecture-snippets/layered-arch.md +201 -0
  113. package/modules/java-spring/module.yaml +15 -0
  114. package/modules/java-spring/stack-profile.yaml +28 -0
  115. package/modules/nextjs/architecture-snippets/app-router-patterns.md +269 -0
  116. package/modules/nextjs/module.yaml +14 -0
  117. package/modules/nextjs/stack-profile.yaml +74 -0
  118. package/modules/php-laravel/architecture-snippets/service-repository.md +302 -0
  119. package/modules/php-laravel/module.yaml +15 -0
  120. package/modules/php-laravel/stack-profile.yaml +56 -0
  121. package/modules/react/architecture-snippets/hooks-query-patterns.md +254 -0
  122. package/modules/react/module.yaml +14 -0
  123. package/modules/react/stack-profile.yaml +63 -0
  124. package/package.json +42 -0
  125. package/rules/data-protection.md +80 -0
  126. package/rules/workflow.md +44 -0
  127. package/scripts/init.sh +49 -0
  128. package/scripts/upgrade.sh +94 -0
  129. package/skills/code/SKILL.md +526 -0
  130. package/skills/code/SKILL.tmpl +176 -0
  131. package/skills/debug/SKILL.md +584 -0
  132. package/skills/debug/SKILL.tmpl +262 -0
  133. package/skills/discovery/SKILL.md +363 -0
  134. package/skills/discovery/SKILL.tmpl +147 -0
  135. package/skills/prd/SKILL.md +456 -0
  136. package/skills/prd/SKILL.tmpl +188 -0
  137. package/skills/setup-ai-first/SKILL.md +160 -0
  138. package/skills/setup-ai-first/SKILL.tmpl +107 -0
  139. package/skills/spec/SKILL.md +361 -0
  140. package/skills/spec/SKILL.tmpl +174 -0
  141. package/skills/test/SKILL.md +862 -0
  142. package/skills/test/SKILL.tmpl +296 -0
  143. package/steps/context-loader.md +163 -0
  144. package/steps/gate.md +81 -0
  145. package/steps/report-footer.md +53 -0
  146. package/steps/spawn-agent.md +123 -0
  147. package/templates/architecture.template.md +113 -0
  148. package/templates/feature.template +259 -0
  149. package/templates/platform-guide.template.md +145 -0
  150. package/templates/prd.template.md +312 -0
  151. package/templates/product-definition.template.md +168 -0
  152. package/templates/project-context.yaml +78 -0
@@ -0,0 +1,243 @@
1
+ # Framework Architecture
2
+
3
+ > **Nguyên tắc**: Nhìn file này để hiểu toàn bộ framework trước khi đọc bất kỳ file chi tiết nào.
4
+
5
+ ---
6
+
7
+ ## Layer Diagram
8
+
9
+ ```
10
+ ╔══════════════════════════════════════════════════════════════════════╗
11
+ ║ SPEC-DRIVEN DEV FRAMEWORK v0.3 ║
12
+ ╚══════════════════════════════════════════════════════════════════════╝
13
+
14
+ ┌──────────────────────────────────────────────────────────────────────┐
15
+ │ LAYER 0 — PROTECTION (luôn chạy trước) │
16
+ │ │
17
+ │ hooks/data-guard.js → PreToolUse hook: chặn đọc file nhạy cảm │
18
+ │ rules/data-protection.md → Quy tắc declarative cho AI agent │
19
+ └──────────────────────────────────────────────────────────────────────┘
20
+ │ safe ↓ blocked → ✋ STOP
21
+ ┌──────────────────────────────────────────────────────────────────────┐
22
+ │ LAYER 1 — ENTRY POINT (user trigger) │
23
+ │ │
24
+ │ commands/*.tmpl skills/*/SKILL.tmpl │
25
+ │ (slash commands) (auto-trigger by description match) │
26
+ │ /generate-bdd detect: "tạo BDD", "sinh feature" │
27
+ │ /generate-code detect: "viết code", "implement" │
28
+ └──────────────────────────────────────────────────────────────────────┘
29
+ │ both built by bin/build.js
30
+ ┌──────────────────────────────────────────────────────────────────────┐
31
+ │ LAYER 2 — SHARED STEPS (DRY, injected) │
32
+ │ │
33
+ │ steps/gate.md → resolve target file + CHECKPOINT │
34
+ │ steps/context-loader.md → load project config + rules │
35
+ │ steps/report-footer.md → standard output format │
36
+ │ │
37
+ │ Injected at build time via {{include:steps/X.md}} │
38
+ │ Source: *.tmpl → Output: *.md (gitignored) │
39
+ └──────────────────────────────────────────────────────────────────────┘
40
+ │ context loaded
41
+ ┌──────────────────────────────────────────────────────────────────────┐
42
+ │ LAYER 3 — PROJECT CONTEXT (read from consumer project) │
43
+ │ │
44
+ │ .agent/project-context.yaml → paths, tech_stack, domains │
45
+ │ CLAUDE.md → architecture, coding standards │
46
+ │ rules/data-protection.md → what AI must never access │
47
+ │ .agent/modules/{stack}/ → stack rules (plug-in, optional) │
48
+ └──────────────────────────────────────────────────────────────────────┘
49
+ │ context-aware
50
+ ┌──────────────────────────────────────────────────────────────────────┐
51
+ │ LAYER 4 — EXECUTION (command logic) │
52
+ │ │
53
+ │ DISCOVERY PRD / BDD CODE / TEST DEBUG │
54
+ │ /define-product /generate-prd /generate-code /fix-bug │
55
+ │ /refine-prd /generate-tests /debug │
56
+ │ /generate-bdd /run-tests /validate- │
57
+ │ /generate-tech-docs /smoke-test traces │
58
+ │ /review-code /setup-ai-first │
59
+ └──────────────────────────────────────────────────────────────────────┘
60
+
61
+ ┌──────────────────────────────────────────────────────────────────────┐
62
+ │ LAYER 5 — OUTPUT (artifacts in consumer proj) │
63
+ │ │
64
+ │ specs/product-definition/ specs/prd/ specs/bdd/ │
65
+ │ tech-docs/ src/ .trace/ .agent/review/ │
66
+ └──────────────────────────────────────────────────────────────────────┘
67
+ ```
68
+
69
+ ---
70
+
71
+ ## Data Flow — Một command chạy như thế nào
72
+
73
+ ```
74
+ User types: /generate-bdd specs/prd/payment/PAY-01.md
75
+
76
+
77
+ [L0] data-guard.js checks tool calls in real-time
78
+ → nếu AI cố đọc .env / *.key → BLOCK + warn
79
+
80
+
81
+ [L1] commands/generate-bdd.md được Claude đọc
82
+ (assembled từ generate-bdd.tmpl + injected steps)
83
+
84
+
85
+ [L2] gate.md → resolve file path từ $ARGUMENTS
86
+ context-loader.md → đọc project-context.yaml, CLAUDE.md,
87
+ rules/data-protection.md,
88
+ modules/{stack}/stack-profile.yaml
89
+
90
+
91
+ [L3] Claude biết: tech_stack, domains, architecture rules,
92
+ sensitive files to avoid, stack-specific patterns
93
+
94
+
95
+ [L4] generate-bdd logic:
96
+ → đọc PRD → extract UC/BR/AC
97
+ → apply BDD rules R1-R10
98
+ → viết specs/bdd/{domain}/{UC-ID}.feature
99
+
100
+
101
+ [L5] Output: specs/bdd/payment/PAY-01-UC1.feature
102
+ ```
103
+
104
+ ---
105
+
106
+ ## Build System
107
+
108
+ ```
109
+ Source (committed to git) Build output (gitignored)
110
+ ────────────────────────── ─────────────────────────
111
+ commands/*.tmpl ──┐
112
+ skills/**/SKILL.tmpl ──┤ node bin/build.js → commands/*.md
113
+ steps/*.md (shared) ──┘ skills/**/SKILL.md
114
+
115
+ Trigger:
116
+ npm run build ← manual
117
+ prepublishOnly hook ← auto before npm publish
118
+ bin/index.js install ← auto when user runs npx
119
+ ```
120
+
121
+ ---
122
+
123
+ ## Module Plug-in System
124
+
125
+ ```
126
+ Available modules (modules/):
127
+ java-spring, angular, react, nextjs,
128
+ dotnet, golang, php-laravel, context-engineering
129
+
130
+ Usage:
131
+ npx @anhth2/spec-driven-dev --module java-spring
132
+ └─ copies modules/java-spring/ → consumer/.agent/modules/java-spring/
133
+
134
+ At runtime, context-loader.md reads:
135
+ .agent/modules/{tech_stack.module}/stack-profile.yaml
136
+ .agent/modules/{tech_stack.module}/architecture-snippets/
137
+ ```
138
+
139
+ ---
140
+
141
+ ## Hook System — Data Protection
142
+
143
+ ```
144
+ Consumer project setup:
145
+ .claude/settings.json ← registers hook (provided as template)
146
+ hooks/data-guard.js ← copied from this package on install
147
+
148
+ Runtime:
149
+ Every tool use (Read, Write, Edit, Bash)
150
+
151
+
152
+ data-guard.js checks:
153
+ .env* / *.key / *.pem / *secret* / *password* / *credential*
154
+ application-prod.* / appsettings.Production.*
155
+
156
+ safe → allow blocked → exit(2) + warn user
157
+ ```
158
+
159
+ ---
160
+
161
+ ## Future — Sub-Agent Pattern (v2 roadmap)
162
+
163
+ Khi một số command quá nặng cho single context window:
164
+
165
+ ```
166
+ Main session (orchestrator — lightweight, chỉ coordinate)
167
+
168
+ ├─ spawn spec-agent ──→ /refine-prd analysis (own context window)
169
+ │ └─ returns: findings.yaml
170
+
171
+ ├─ spawn codegen-agent ──→ /generate-code UC1 (own context window)
172
+ │ └─ returns: src/ changes
173
+
174
+ └─ spawn test-agent ──→ /generate-tests UC1 (own context window)
175
+ └─ returns: test files
176
+
177
+ Benefits:
178
+ - Main session không bị bloat bởi large file reads
179
+ - Mỗi agent focus vào 1 task, ít hallucination hơn
180
+ - Parallel execution cho multiple UCs
181
+
182
+ Implementation path:
183
+ 1. Tạo steps/spawn-agent.md — pattern + handoff payload format
184
+ 2. Tạo commands/orchestrate-feature.tmpl — top-level orchestrator
185
+ 3. Sub-agent commands nhận input qua $ARGUMENTS (JSON payload)
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Directory Map
191
+
192
+ ```
193
+ spec-driven-dev/
194
+ ├── ARCHITECTURE.md ← Đọc đây trước ◀◀◀
195
+ ├── bin/
196
+ │ ├── build.js ← assembles *.tmpl → *.md
197
+ │ └── index.js ← npm installer + hook installer
198
+ ├── commands/
199
+ │ └── *.tmpl ← slash commands (14 commands)
200
+ ├── hooks/
201
+ │ ├── data-guard.js ← PreToolUse sensitive file protection
202
+ │ └── settings.json ← hook registration template
203
+ ├── modules/
204
+ │ └── {stack}/ ← 8 stacks: java-spring, angular, react,
205
+ │ ├── module.yaml nextjs, dotnet, golang, php-laravel,
206
+ │ ├── stack-profile.yaml context-engineering
207
+ │ └── architecture-snippets/
208
+ ├── rules/
209
+ │ ├── data-protection.md ← what AI must NEVER read/write
210
+ │ └── workflow.md ← general AI behavior rules
211
+ ├── skills/
212
+ │ └── {name}/SKILL.tmpl ← Claude plugin skills (7 skills)
213
+ ├── steps/
214
+ │ ├── gate.md ← shared: file resolve + checkpoint
215
+ │ ├── context-loader.md ← shared: load all project context
216
+ │ └── report-footer.md ← shared: standard output format
217
+ └── templates/
218
+ ├── project-context.yaml ← consumer project config template
219
+ ├── architecture.template.md
220
+ └── platform-guide.template.md
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Maintenance Guide
226
+
227
+ | Muốn thay đổi gì | Sửa file nào |
228
+ |------------------|-------------|
229
+ | Logic của 1 command cụ thể | `commands/{name}.tmpl` |
230
+ | Logic của 1 skill cụ thể | `skills/{name}/SKILL.tmpl` |
231
+ | Gate / checkpoint pattern | `steps/gate.md` |
232
+ | Context loading | `steps/context-loader.md` |
233
+ | Report format | `steps/report-footer.md` |
234
+ | Sensitive file patterns | `hooks/data-guard.js` + `rules/data-protection.md` |
235
+ | Stack-specific rules | `modules/{stack}/stack-profile.yaml` |
236
+ | Project setup template | `templates/project-context.yaml` |
237
+ | Build system | `bin/build.js` |
238
+ | Installer | `bin/index.js` |
239
+
240
+ Sau khi sửa bất kỳ `.tmpl` hoặc `steps/*.md`:
241
+ ```bash
242
+ npm run build # regenerate tất cả *.md
243
+ ```
package/bin/build.js ADDED
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * build.js — Assembles templates → .md files
5
+ *
6
+ * Processes:
7
+ * commands/*.tmpl → commands/*.md
8
+ * skills/**\/SKILL.tmpl → skills/**\/SKILL.md
9
+ *
10
+ * Replaces {{include:steps/gate.md}}, {{include:steps/context-loader.md}},
11
+ * and {{include:steps/report-footer.md}} with the actual file contents.
12
+ *
13
+ * Usage: node bin/build.js
14
+ */
15
+
16
+ const fs = require('fs');
17
+ const path = require('path');
18
+
19
+ const ROOT = path.join(__dirname, '..');
20
+ const COMMANDS_DIR = path.join(ROOT, 'commands');
21
+ const SKILLS_DIR = path.join(ROOT, 'skills');
22
+
23
+ // Cache for step file contents
24
+ const stepCache = {};
25
+
26
+ /**
27
+ * Load a step file by name, caching the result.
28
+ * @param {string} stepPath - e.g. "steps/gate.md"
29
+ * @returns {string} file contents
30
+ */
31
+ function loadStep(stepPath) {
32
+ if (stepCache[stepPath]) return stepCache[stepPath];
33
+
34
+ const fullPath = path.join(ROOT, stepPath);
35
+ if (!fs.existsSync(fullPath)) {
36
+ throw new Error(`Step file not found: ${fullPath}`);
37
+ }
38
+ const content = fs.readFileSync(fullPath, 'utf8');
39
+ stepCache[stepPath] = content;
40
+ return content;
41
+ }
42
+
43
+ /**
44
+ * Process a single .tmpl file: resolve all {{include:...}} markers
45
+ * and write the output as a .md file (replacing .tmpl extension with .md).
46
+ *
47
+ * @param {string} tmplFile - full path to the .tmpl file
48
+ * @param {string} label - display label for logging (e.g. "generate-code")
49
+ * @returns {{ label: string, success: boolean, error?: string }}
50
+ */
51
+ function buildTemplate(tmplFile, label) {
52
+ const outFile = tmplFile.replace(/\.tmpl$/, '.md');
53
+
54
+ try {
55
+ let content = fs.readFileSync(tmplFile, 'utf8');
56
+
57
+ // Replace all {{include:...}} markers
58
+ content = content.replace(/\{\{include:([^}]+)\}\}/g, (match, includePath) => {
59
+ const trimmed = includePath.trim();
60
+ return loadStep(trimmed);
61
+ });
62
+
63
+ fs.writeFileSync(outFile, content, 'utf8');
64
+ return { label, success: true };
65
+ } catch (err) {
66
+ return { label, success: false, error: err.message };
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Recursively find all files matching a predicate under a directory.
72
+ * @param {string} dir
73
+ * @param {(filename: string) => boolean} predicate
74
+ * @returns {string[]} absolute paths
75
+ */
76
+ function findFiles(dir, predicate) {
77
+ if (!fs.existsSync(dir)) return [];
78
+ const results = [];
79
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
80
+ const fullPath = path.join(dir, entry.name);
81
+ if (entry.isDirectory()) {
82
+ results.push(...findFiles(fullPath, predicate));
83
+ } else if (predicate(entry.name)) {
84
+ results.push(fullPath);
85
+ }
86
+ }
87
+ return results;
88
+ }
89
+
90
+ // ── Main ──────────────────────────────────────────────────────────────────────
91
+
92
+ let allSucceeded = 0;
93
+ let allFailed = 0;
94
+
95
+ // ── 1. Build commands/*.tmpl → commands/*.md ──────────────────────────────────
96
+
97
+ console.log('');
98
+ console.log('Building commands from templates...');
99
+ console.log('');
100
+
101
+ const commandTmplFiles = fs.readdirSync(COMMANDS_DIR)
102
+ .filter(f => f.endsWith('.tmpl'))
103
+ .map(f => path.join(COMMANDS_DIR, f));
104
+
105
+ if (commandTmplFiles.length === 0) {
106
+ console.log(' (no .tmpl files found in commands/)');
107
+ } else {
108
+ const commandResults = commandTmplFiles.map(f => {
109
+ const basename = path.basename(f, '.tmpl');
110
+ return buildTemplate(f, basename);
111
+ });
112
+
113
+ for (const r of commandResults) {
114
+ if (r.success) {
115
+ console.log(` ✅ ${r.label}.tmpl → ${r.label}.md`);
116
+ allSucceeded++;
117
+ } else {
118
+ console.log(` ❌ ${r.label}.tmpl → FAILED: ${r.error}`);
119
+ allFailed++;
120
+ }
121
+ }
122
+ }
123
+
124
+ // ── 2. Build skills/**/SKILL.tmpl → skills/**/SKILL.md ───────────────────────
125
+
126
+ console.log('');
127
+ console.log('Building skills from templates...');
128
+ console.log('');
129
+
130
+ const skillTmplFiles = findFiles(SKILLS_DIR, name => name === 'SKILL.tmpl');
131
+
132
+ if (skillTmplFiles.length === 0) {
133
+ console.log(' (no SKILL.tmpl files found in skills/)');
134
+ } else {
135
+ const skillResults = skillTmplFiles.map(f => {
136
+ // Use the parent directory name as the label (e.g., "code", "debug")
137
+ const skillName = path.basename(path.dirname(f));
138
+ return buildTemplate(f, `skills/${skillName}/SKILL`);
139
+ });
140
+
141
+ for (const r of skillResults) {
142
+ if (r.success) {
143
+ console.log(` ✅ ${r.label}.tmpl → ${r.label}.md`);
144
+ allSucceeded++;
145
+ } else {
146
+ console.log(` ❌ ${r.label}.tmpl → FAILED: ${r.error}`);
147
+ allFailed++;
148
+ }
149
+ }
150
+ }
151
+
152
+ // ── 3. Populate core/ directory (distributable) ──────────────────────────────
153
+ //
154
+ // core/ mirrors what gets installed into .agent/ in consumer projects.
155
+ // It is gitignored but included in the npm package (via "files" whitelist).
156
+
157
+ const CORE_DIR = path.join(ROOT, 'core');
158
+ const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8'));
159
+ const VERSION = pkg.version;
160
+
161
+ console.log('');
162
+ console.log('Populating core/ (distributable) ...');
163
+ console.log('');
164
+
165
+ // Clean and recreate core/
166
+ if (fs.existsSync(CORE_DIR)) {
167
+ fs.rmSync(CORE_DIR, { recursive: true });
168
+ }
169
+ fs.mkdirSync(CORE_DIR, { recursive: true });
170
+
171
+ /**
172
+ * Recursively copy src → dest, optionally filtering files by name.
173
+ * @param {string} src
174
+ * @param {string} dest
175
+ * @param {((name: string) => boolean) | null} fileFilter null = copy all files
176
+ */
177
+ function copyDirToCore(src, dest, fileFilter) {
178
+ if (!fs.existsSync(src)) return;
179
+ fs.mkdirSync(dest, { recursive: true });
180
+ for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
181
+ const srcPath = path.join(src, entry.name);
182
+ const destPath = path.join(dest, entry.name);
183
+ if (entry.isDirectory()) {
184
+ copyDirToCore(srcPath, destPath, fileFilter);
185
+ } else if (!fileFilter || fileFilter(entry.name)) {
186
+ fs.copyFileSync(srcPath, destPath);
187
+ }
188
+ }
189
+ }
190
+
191
+ const coreMappings = [
192
+ // Built command .md files (not .tmpl sources)
193
+ { src: COMMANDS_DIR, dest: path.join(CORE_DIR, 'commands'), filter: f => f.endsWith('.md') },
194
+ // Step files (gate, context-loader, spawn-agent, report-footer)
195
+ { src: path.join(ROOT, 'steps'), dest: path.join(CORE_DIR, 'steps'), filter: null },
196
+ // Hook scripts
197
+ { src: path.join(ROOT, 'hooks'), dest: path.join(CORE_DIR, 'hooks'), filter: null },
198
+ // Data-protection and workflow rules
199
+ { src: path.join(ROOT, 'rules'), dest: path.join(CORE_DIR, 'rules'), filter: null },
200
+ // PRD / architecture templates
201
+ { src: path.join(ROOT, 'templates'), dest: path.join(CORE_DIR, 'templates'), filter: null },
202
+ // Stack module profiles
203
+ { src: path.join(ROOT, 'modules'), dest: path.join(CORE_DIR, 'modules'), filter: null },
204
+ // Built skill .md files (not .tmpl sources)
205
+ { src: SKILLS_DIR, dest: path.join(CORE_DIR, 'skills'), filter: f => !f.endsWith('.tmpl') },
206
+ ];
207
+
208
+ for (const { src, dest, filter } of coreMappings) {
209
+ copyDirToCore(src, dest, filter);
210
+ const rel = path.relative(ROOT, dest);
211
+ console.log(` ✅ ${rel}/`);
212
+ }
213
+
214
+ // Write FRAMEWORK_VERSION so upgrade.sh can compare installed vs latest
215
+ fs.writeFileSync(path.join(CORE_DIR, 'FRAMEWORK_VERSION'), VERSION + '\n', 'utf8');
216
+ console.log(` ✅ core/FRAMEWORK_VERSION (v${VERSION})`);
217
+
218
+ // ── Summary ───────────────────────────────────────────────────────────────────
219
+
220
+ const total = allSucceeded + allFailed;
221
+ console.log('');
222
+
223
+ if (allFailed === 0) {
224
+ console.log(`Build complete: ${allSucceeded}/${total} templates assembled.`);
225
+ } else {
226
+ console.log(`Build finished with errors: ${allSucceeded}/${total} succeeded.`);
227
+ process.exit(1);
228
+ }
229
+
230
+ console.log('');