bmad-method 6.3.1-next.2 → 6.3.1-next.20

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 (155) hide show
  1. package/package.json +1 -2
  2. package/src/bmm-skills/1-analysis/bmad-agent-analyst/SKILL.md +51 -36
  3. package/src/bmm-skills/1-analysis/bmad-agent-analyst/customize.toml +90 -0
  4. package/src/bmm-skills/1-analysis/bmad-agent-tech-writer/SKILL.md +50 -33
  5. package/src/bmm-skills/1-analysis/bmad-agent-tech-writer/customize.toml +81 -0
  6. package/src/bmm-skills/1-analysis/bmad-document-project/SKILL.md +57 -1
  7. package/src/bmm-skills/1-analysis/bmad-document-project/customize.toml +41 -0
  8. package/src/bmm-skills/1-analysis/bmad-document-project/workflows/deep-dive-instructions.md +1 -0
  9. package/src/bmm-skills/1-analysis/bmad-document-project/workflows/full-scan-instructions.md +1 -0
  10. package/src/bmm-skills/1-analysis/bmad-prfaq/SKILL.md +48 -9
  11. package/src/bmm-skills/1-analysis/bmad-prfaq/customize.toml +41 -0
  12. package/src/bmm-skills/1-analysis/bmad-prfaq/references/verdict.md +4 -0
  13. package/src/bmm-skills/1-analysis/bmad-product-brief/SKILL.md +44 -9
  14. package/src/bmm-skills/1-analysis/bmad-product-brief/customize.toml +47 -0
  15. package/src/bmm-skills/1-analysis/bmad-product-brief/prompts/contextual-discovery.md +8 -7
  16. package/src/bmm-skills/1-analysis/bmad-product-brief/prompts/draft-and-review.md +6 -5
  17. package/src/bmm-skills/1-analysis/bmad-product-brief/prompts/finalize.md +4 -1
  18. package/src/bmm-skills/1-analysis/bmad-product-brief/prompts/guided-elicitation.md +3 -2
  19. package/src/bmm-skills/1-analysis/research/bmad-domain-research/SKILL.md +91 -1
  20. package/src/bmm-skills/1-analysis/research/bmad-domain-research/customize.toml +41 -0
  21. package/src/bmm-skills/1-analysis/research/bmad-domain-research/domain-steps/step-06-research-synthesis.md +6 -0
  22. package/src/bmm-skills/1-analysis/research/bmad-market-research/SKILL.md +91 -1
  23. package/src/bmm-skills/1-analysis/research/bmad-market-research/customize.toml +41 -0
  24. package/src/bmm-skills/1-analysis/research/bmad-market-research/steps/step-06-research-completion.md +6 -0
  25. package/src/bmm-skills/1-analysis/research/bmad-technical-research/SKILL.md +91 -1
  26. package/src/bmm-skills/1-analysis/research/bmad-technical-research/customize.toml +41 -0
  27. package/src/bmm-skills/1-analysis/research/bmad-technical-research/technical-steps/step-06-research-synthesis.md +6 -0
  28. package/src/bmm-skills/2-plan-workflows/bmad-agent-pm/SKILL.md +50 -35
  29. package/src/bmm-skills/2-plan-workflows/bmad-agent-pm/customize.toml +85 -0
  30. package/src/bmm-skills/2-plan-workflows/bmad-agent-ux-designer/SKILL.md +50 -31
  31. package/src/bmm-skills/2-plan-workflows/bmad-agent-ux-designer/customize.toml +60 -0
  32. package/src/bmm-skills/2-plan-workflows/bmad-create-prd/SKILL.md +99 -1
  33. package/src/bmm-skills/2-plan-workflows/bmad-create-prd/customize.toml +41 -0
  34. package/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-08-scoping.md +70 -23
  35. package/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-11-polish.md +1 -1
  36. package/src/bmm-skills/2-plan-workflows/bmad-create-prd/steps-c/step-12-complete.md +6 -0
  37. package/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/SKILL.md +70 -1
  38. package/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/customize.toml +41 -0
  39. package/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/steps/step-14-complete.md +6 -0
  40. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/SKILL.md +97 -1
  41. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/customize.toml +42 -0
  42. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-04-complete.md +2 -0
  43. package/src/bmm-skills/2-plan-workflows/bmad-validate-prd/SKILL.md +99 -1
  44. package/src/bmm-skills/2-plan-workflows/bmad-validate-prd/customize.toml +42 -0
  45. package/src/bmm-skills/2-plan-workflows/bmad-validate-prd/steps-v/step-v-13-report-complete.md +1 -0
  46. package/src/bmm-skills/3-solutioning/bmad-agent-architect/SKILL.md +50 -30
  47. package/src/bmm-skills/3-solutioning/bmad-agent-architect/customize.toml +65 -0
  48. package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/SKILL.md +86 -1
  49. package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/customize.toml +41 -0
  50. package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/steps/step-06-final-assessment.md +6 -0
  51. package/src/bmm-skills/3-solutioning/bmad-create-architecture/SKILL.md +69 -1
  52. package/src/bmm-skills/3-solutioning/bmad-create-architecture/customize.toml +41 -0
  53. package/src/bmm-skills/3-solutioning/bmad-create-architecture/steps/step-08-complete.md +6 -0
  54. package/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/SKILL.md +88 -1
  55. package/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/customize.toml +41 -0
  56. package/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/steps/step-04-final-validation.md +6 -0
  57. package/src/bmm-skills/3-solutioning/bmad-generate-project-context/SKILL.md +76 -1
  58. package/src/bmm-skills/3-solutioning/bmad-generate-project-context/customize.toml +41 -0
  59. package/src/bmm-skills/3-solutioning/bmad-generate-project-context/steps/step-03-complete.md +6 -0
  60. package/src/bmm-skills/4-implementation/bmad-agent-dev/SKILL.md +48 -43
  61. package/src/bmm-skills/4-implementation/bmad-agent-dev/customize.toml +90 -0
  62. package/src/bmm-skills/4-implementation/bmad-correct-course/SKILL.md +296 -1
  63. package/src/bmm-skills/4-implementation/bmad-correct-course/customize.toml +41 -0
  64. package/src/bmm-skills/4-implementation/bmad-create-story/SKILL.md +412 -1
  65. package/src/bmm-skills/4-implementation/bmad-create-story/customize.toml +41 -0
  66. package/src/bmm-skills/4-implementation/bmad-qa-generate-e2e-tests/SKILL.md +171 -1
  67. package/src/bmm-skills/4-implementation/bmad-qa-generate-e2e-tests/customize.toml +41 -0
  68. package/src/bmm-skills/4-implementation/bmad-retrospective/SKILL.md +1507 -1
  69. package/src/bmm-skills/4-implementation/bmad-retrospective/customize.toml +41 -0
  70. package/src/bmm-skills/module.yaml +49 -0
  71. package/src/core-skills/bmad-advanced-elicitation/SKILL.md +7 -1
  72. package/src/core-skills/bmad-customize/SKILL.md +111 -0
  73. package/src/core-skills/bmad-customize/scripts/list_customizable_skills.py +231 -0
  74. package/src/core-skills/bmad-customize/scripts/tests/test_list_customizable_skills.py +249 -0
  75. package/src/core-skills/bmad-distillator/resources/distillate-format-reference.md +1 -1
  76. package/src/core-skills/bmad-party-mode/SKILL.md +13 -10
  77. package/src/core-skills/module-help.csv +1 -0
  78. package/src/core-skills/module.yaml +3 -0
  79. package/src/scripts/resolve_config.py +176 -0
  80. package/src/scripts/resolve_customization.py +230 -0
  81. package/tools/installer/cli-utils.js +0 -137
  82. package/tools/installer/commands/status.js +1 -1
  83. package/tools/installer/commands/uninstall.js +1 -1
  84. package/tools/installer/core/existing-install.js +1 -1
  85. package/tools/installer/core/install-paths.js +12 -6
  86. package/tools/installer/core/installer.js +88 -88
  87. package/tools/installer/core/manifest-generator.js +331 -189
  88. package/tools/installer/core/manifest.js +24 -642
  89. package/tools/installer/file-ops.js +1 -1
  90. package/tools/installer/fs-native.js +116 -0
  91. package/tools/installer/ide/_config-driven.js +1 -1
  92. package/tools/installer/ide/platform-codes.js +1 -1
  93. package/tools/installer/ide/shared/path-utils.js +0 -145
  94. package/tools/installer/ide/shared/skill-manifest.js +1 -1
  95. package/tools/installer/message-loader.js +1 -1
  96. package/tools/installer/modules/community-manager.js +11 -6
  97. package/tools/installer/modules/custom-module-manager.js +1 -28
  98. package/tools/installer/modules/external-manager.js +5 -44
  99. package/tools/installer/modules/official-modules.js +5 -53
  100. package/tools/installer/modules/plugin-resolver.js +1 -1
  101. package/tools/installer/modules/registry-client.js +133 -12
  102. package/tools/installer/modules/version-resolver.js +336 -0
  103. package/tools/installer/project-root.js +55 -1
  104. package/tools/installer/prompts.js +0 -106
  105. package/tools/installer/ui.js +50 -48
  106. package/tools/migrate-custom-module-paths.js +1 -1
  107. package/src/bmm-skills/1-analysis/bmad-agent-analyst/bmad-skill-manifest.yaml +0 -11
  108. package/src/bmm-skills/1-analysis/bmad-agent-tech-writer/bmad-skill-manifest.yaml +0 -11
  109. package/src/bmm-skills/1-analysis/bmad-document-project/workflow.md +0 -25
  110. package/src/bmm-skills/1-analysis/research/bmad-domain-research/workflow.md +0 -51
  111. package/src/bmm-skills/1-analysis/research/bmad-market-research/workflow.md +0 -51
  112. package/src/bmm-skills/1-analysis/research/bmad-technical-research/workflow.md +0 -52
  113. package/src/bmm-skills/2-plan-workflows/bmad-agent-pm/bmad-skill-manifest.yaml +0 -11
  114. package/src/bmm-skills/2-plan-workflows/bmad-agent-ux-designer/bmad-skill-manifest.yaml +0 -11
  115. package/src/bmm-skills/2-plan-workflows/bmad-create-prd/workflow.md +0 -61
  116. package/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/workflow.md +0 -35
  117. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/workflow.md +0 -62
  118. package/src/bmm-skills/2-plan-workflows/bmad-validate-prd/workflow.md +0 -61
  119. package/src/bmm-skills/3-solutioning/bmad-agent-architect/bmad-skill-manifest.yaml +0 -11
  120. package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/workflow.md +0 -47
  121. package/src/bmm-skills/3-solutioning/bmad-create-architecture/workflow.md +0 -32
  122. package/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/workflow.md +0 -51
  123. package/src/bmm-skills/3-solutioning/bmad-generate-project-context/workflow.md +0 -39
  124. package/src/bmm-skills/4-implementation/bmad-agent-dev/bmad-skill-manifest.yaml +0 -11
  125. package/src/bmm-skills/4-implementation/bmad-correct-course/workflow.md +0 -267
  126. package/src/bmm-skills/4-implementation/bmad-create-story/workflow.md +0 -380
  127. package/src/bmm-skills/4-implementation/bmad-qa-generate-e2e-tests/workflow.md +0 -136
  128. package/src/bmm-skills/4-implementation/bmad-retrospective/workflow.md +0 -1479
  129. package/tools/installer/ide/shared/agent-command-generator.js +0 -180
  130. package/tools/installer/ide/shared/bmad-artifacts.js +0 -208
  131. package/tools/installer/ide/shared/module-injections.js +0 -136
  132. package/tools/installer/ide/templates/agent-command-template.md +0 -14
  133. package/tools/installer/ide/templates/combined/antigravity.md +0 -8
  134. package/tools/installer/ide/templates/combined/default-agent.md +0 -15
  135. package/tools/installer/ide/templates/combined/default-task.md +0 -10
  136. package/tools/installer/ide/templates/combined/default-tool.md +0 -10
  137. package/tools/installer/ide/templates/combined/default-workflow.md +0 -6
  138. package/tools/installer/ide/templates/combined/gemini-agent.toml +0 -14
  139. package/tools/installer/ide/templates/combined/gemini-task.toml +0 -11
  140. package/tools/installer/ide/templates/combined/gemini-tool.toml +0 -11
  141. package/tools/installer/ide/templates/combined/gemini-workflow-yaml.toml +0 -16
  142. package/tools/installer/ide/templates/combined/gemini-workflow.toml +0 -14
  143. package/tools/installer/ide/templates/combined/kiro-agent.md +0 -16
  144. package/tools/installer/ide/templates/combined/kiro-task.md +0 -9
  145. package/tools/installer/ide/templates/combined/kiro-tool.md +0 -9
  146. package/tools/installer/ide/templates/combined/kiro-workflow.md +0 -7
  147. package/tools/installer/ide/templates/combined/opencode-agent.md +0 -15
  148. package/tools/installer/ide/templates/combined/opencode-task.md +0 -13
  149. package/tools/installer/ide/templates/combined/opencode-tool.md +0 -13
  150. package/tools/installer/ide/templates/combined/opencode-workflow-yaml.md +0 -16
  151. package/tools/installer/ide/templates/combined/opencode-workflow.md +0 -16
  152. package/tools/installer/ide/templates/combined/rovodev.md +0 -9
  153. package/tools/installer/ide/templates/combined/trae.md +0 -9
  154. package/tools/installer/ide/templates/combined/windsurf-workflow.md +0 -10
  155. package/tools/installer/ide/templates/split/.gitkeep +0 -0
@@ -1,4 +1,4 @@
1
- const fs = require('fs-extra');
1
+ const fs = require('./fs-native');
2
2
  const path = require('node:path');
3
3
  const crypto = require('node:crypto');
4
4
 
@@ -0,0 +1,116 @@
1
+ // Drop-in replacement for fs-extra using native node:fs APIs.
2
+ // Eliminates graceful-fs monkey-patching that causes non-deterministic
3
+ // file loss during multi-module installs on macOS (issue #1779).
4
+ const fsp = require('node:fs/promises');
5
+ const fs = require('node:fs');
6
+ const path = require('node:path');
7
+
8
+ async function pathExists(p) {
9
+ try {
10
+ await fsp.access(p);
11
+ return true;
12
+ } catch {
13
+ return false;
14
+ }
15
+ }
16
+
17
+ async function ensureDir(dir) {
18
+ await fsp.mkdir(dir, { recursive: true });
19
+ }
20
+
21
+ async function remove(p) {
22
+ await fsp.rm(p, { recursive: true, force: true });
23
+ }
24
+
25
+ async function copy(src, dest, options = {}) {
26
+ const filterFn = options.filter;
27
+ const overwrite = options.overwrite !== false;
28
+ const srcStat = await fsp.stat(src);
29
+
30
+ if (srcStat.isFile()) {
31
+ if (filterFn && !(await filterFn(src, dest))) return;
32
+ await fsp.mkdir(path.dirname(dest), { recursive: true });
33
+ if (!overwrite) {
34
+ try {
35
+ await fsp.access(dest);
36
+ if (options.errorOnExist) throw new Error(`${dest} already exists`);
37
+ return;
38
+ } catch (error) {
39
+ if (error.message.includes('already exists')) throw error;
40
+ }
41
+ }
42
+ await fsp.copyFile(src, dest);
43
+ return;
44
+ }
45
+
46
+ if (srcStat.isDirectory()) {
47
+ if (filterFn && !(await filterFn(src, dest))) return;
48
+ await fsp.mkdir(dest, { recursive: true });
49
+ const entries = await fsp.readdir(src, { withFileTypes: true });
50
+ for (const entry of entries) {
51
+ await copy(path.join(src, entry.name), path.join(dest, entry.name), options);
52
+ }
53
+ }
54
+ }
55
+
56
+ async function move(src, dest) {
57
+ try {
58
+ await fsp.rename(src, dest);
59
+ } catch (error) {
60
+ if (error.code === 'EXDEV') {
61
+ await copy(src, dest);
62
+ await fsp.rm(src, { recursive: true, force: true });
63
+ } else {
64
+ throw error;
65
+ }
66
+ }
67
+ }
68
+
69
+ function readJsonSync(p) {
70
+ return JSON.parse(fs.readFileSync(p, 'utf8'));
71
+ }
72
+
73
+ async function writeJson(p, data, options = {}) {
74
+ const spaces = options.spaces ?? 2;
75
+ await fsp.writeFile(p, JSON.stringify(data, null, spaces) + '\n', 'utf8');
76
+ }
77
+
78
+ module.exports = {
79
+ // Native async (node:fs/promises)
80
+ readFile: fsp.readFile,
81
+ writeFile: fsp.writeFile,
82
+ stat: fsp.stat,
83
+ readdir: fsp.readdir,
84
+ access: fsp.access,
85
+ realpath: fsp.realpath,
86
+ rename: fsp.rename,
87
+ rmdir: fsp.rmdir,
88
+ unlink: fsp.unlink,
89
+ chmod: fsp.chmod,
90
+ mkdir: fsp.mkdir,
91
+ mkdtemp: fsp.mkdtemp,
92
+ copyFile: fsp.copyFile,
93
+ rm: fsp.rm,
94
+
95
+ // fs-extra compatible helpers (native implementations)
96
+ pathExists,
97
+ ensureDir,
98
+ remove,
99
+ copy,
100
+ move,
101
+ readJsonSync,
102
+ writeJson,
103
+
104
+ // Sync methods from core node:fs
105
+ existsSync: fs.existsSync.bind(fs),
106
+ readFileSync: fs.readFileSync.bind(fs),
107
+ writeFileSync: fs.writeFileSync.bind(fs),
108
+ statSync: fs.statSync.bind(fs),
109
+ accessSync: fs.accessSync.bind(fs),
110
+ readdirSync: fs.readdirSync.bind(fs),
111
+ createReadStream: fs.createReadStream.bind(fs),
112
+ pathExistsSync: fs.existsSync.bind(fs),
113
+
114
+ // Constants
115
+ constants: fs.constants,
116
+ };
@@ -1,6 +1,6 @@
1
1
  const os = require('node:os');
2
2
  const path = require('node:path');
3
- const fs = require('fs-extra');
3
+ const fs = require('../fs-native');
4
4
  const yaml = require('yaml');
5
5
  const prompts = require('../prompts');
6
6
  const csv = require('csv-parse/sync');
@@ -1,4 +1,4 @@
1
- const fs = require('fs-extra');
1
+ const fs = require('../fs-native');
2
2
  const path = require('node:path');
3
3
  const yaml = require('yaml');
4
4
 
@@ -15,8 +15,6 @@
15
15
  * - standalone/agents/fred.md → bmad-agent-standalone-fred.md
16
16
  */
17
17
 
18
- // Type segments - agents are included in naming, others are filtered out
19
- const TYPE_SEGMENTS = ['workflows', 'tasks', 'tools'];
20
18
  const AGENT_SEGMENT = 'agents';
21
19
 
22
20
  // BMAD installation folder name - centralized constant for all installers
@@ -194,125 +192,6 @@ function parseDashName(filename) {
194
192
  };
195
193
  }
196
194
 
197
- // ============================================================================
198
- // LEGACY FUNCTIONS (underscore format) - kept for backward compatibility
199
- // ============================================================================
200
-
201
- /**
202
- * Convert hierarchical path to flat underscore-separated name (LEGACY)
203
- * @deprecated Use toDashName instead
204
- */
205
- function toUnderscoreName(module, type, name) {
206
- const isAgent = type === AGENT_SEGMENT;
207
- if (module === 'core') {
208
- return isAgent ? `bmad_agent_${name}.md` : `bmad_${name}.md`;
209
- }
210
- if (module === 'standalone') {
211
- return isAgent ? `bmad_agent_standalone_${name}.md` : `bmad_standalone_${name}.md`;
212
- }
213
- return isAgent ? `bmad_${module}_agent_${name}.md` : `bmad_${module}_${name}.md`;
214
- }
215
-
216
- /**
217
- * Convert relative path to flat underscore-separated name (LEGACY)
218
- * @deprecated Use toDashPath instead
219
- */
220
- function toUnderscorePath(relativePath) {
221
- // Strip common file extensions (same as toDashPath for consistency)
222
- const withoutExt = relativePath.replace(/\.(md|yaml|yml|json|xml|toml)$/i, '');
223
- const parts = withoutExt.split(/[/\\]/);
224
-
225
- const module = parts[0];
226
- const type = parts[1];
227
- const name = parts.slice(2).join('_');
228
-
229
- return toUnderscoreName(module, type, name);
230
- }
231
-
232
- /**
233
- * Create custom agent underscore name (LEGACY)
234
- * @deprecated Use customAgentDashName instead
235
- */
236
- function customAgentUnderscoreName(agentName) {
237
- return `bmad_custom_${agentName}.md`;
238
- }
239
-
240
- /**
241
- * Check if a filename uses underscore format (LEGACY)
242
- * @deprecated Use isDashFormat instead
243
- */
244
- function isUnderscoreFormat(filename) {
245
- return filename.startsWith('bmad_') && filename.includes('_');
246
- }
247
-
248
- /**
249
- * Extract parts from an underscore-formatted filename (LEGACY)
250
- * @deprecated Use parseDashName instead
251
- */
252
- function parseUnderscoreName(filename) {
253
- const withoutExt = filename.replace('.md', '');
254
- const parts = withoutExt.split('_');
255
-
256
- if (parts.length < 2 || parts[0] !== 'bmad') {
257
- return null;
258
- }
259
-
260
- const agentIndex = parts.indexOf('agent');
261
-
262
- if (agentIndex !== -1) {
263
- if (agentIndex === 1) {
264
- // bmad_agent_... - check for standalone
265
- if (parts.length >= 4 && parts[2] === 'standalone') {
266
- return {
267
- prefix: parts[0],
268
- module: 'standalone',
269
- type: 'agents',
270
- name: parts.slice(3).join('_'),
271
- };
272
- }
273
- return {
274
- prefix: parts[0],
275
- module: 'core',
276
- type: 'agents',
277
- name: parts.slice(agentIndex + 1).join('_'),
278
- };
279
- } else {
280
- return {
281
- prefix: parts[0],
282
- module: parts[1],
283
- type: 'agents',
284
- name: parts.slice(agentIndex + 1).join('_'),
285
- };
286
- }
287
- }
288
-
289
- if (parts.length === 2) {
290
- return {
291
- prefix: parts[0],
292
- module: 'core',
293
- type: 'workflows',
294
- name: parts[1],
295
- };
296
- }
297
-
298
- // Check for standalone non-agent: bmad_standalone_name
299
- if (parts[1] === 'standalone') {
300
- return {
301
- prefix: parts[0],
302
- module: 'standalone',
303
- type: 'workflows',
304
- name: parts.slice(2).join('_'),
305
- };
306
- }
307
-
308
- return {
309
- prefix: parts[0],
310
- module: parts[1],
311
- type: 'workflows',
312
- name: parts.slice(2).join('_'),
313
- };
314
- }
315
-
316
195
  /**
317
196
  * Resolve the skill name for an artifact.
318
197
  * Prefers canonicalId from a bmad-skill-manifest.yaml sidecar when available,
@@ -328,37 +207,13 @@ function resolveSkillName(artifact) {
328
207
  return toDashPath(artifact.relativePath);
329
208
  }
330
209
 
331
- // Backward compatibility aliases (colon format was same as underscore)
332
- const toColonName = toUnderscoreName;
333
- const toColonPath = toUnderscorePath;
334
- const customAgentColonName = customAgentUnderscoreName;
335
- const isColonFormat = isUnderscoreFormat;
336
- const parseColonName = parseUnderscoreName;
337
-
338
210
  module.exports = {
339
- // New standard (dash-based)
340
211
  toDashName,
341
212
  toDashPath,
342
213
  resolveSkillName,
343
214
  customAgentDashName,
344
215
  isDashFormat,
345
216
  parseDashName,
346
-
347
- // Legacy (underscore-based) - kept for backward compatibility
348
- toUnderscoreName,
349
- toUnderscorePath,
350
- customAgentUnderscoreName,
351
- isUnderscoreFormat,
352
- parseUnderscoreName,
353
-
354
- // Backward compatibility aliases
355
- toColonName,
356
- toColonPath,
357
- customAgentColonName,
358
- isColonFormat,
359
- parseColonName,
360
-
361
- TYPE_SEGMENTS,
362
217
  AGENT_SEGMENT,
363
218
  BMAD_FOLDER_NAME,
364
219
  };
@@ -1,5 +1,5 @@
1
1
  const path = require('node:path');
2
- const fs = require('fs-extra');
2
+ const fs = require('../../fs-native');
3
3
  const yaml = require('yaml');
4
4
 
5
5
  /**
@@ -1,4 +1,4 @@
1
- const fs = require('fs-extra');
1
+ const fs = require('./fs-native');
2
2
  const path = require('node:path');
3
3
  const yaml = require('yaml');
4
4
  const prompts = require('./prompts');
@@ -1,13 +1,13 @@
1
- const fs = require('fs-extra');
1
+ const fs = require('../fs-native');
2
2
  const os = require('node:os');
3
3
  const path = require('node:path');
4
4
  const { execSync } = require('node:child_process');
5
5
  const prompts = require('../prompts');
6
6
  const { RegistryClient } = require('./registry-client');
7
7
 
8
- const MARKETPLACE_BASE = 'https://raw.githubusercontent.com/bmad-code-org/bmad-plugins-marketplace/main';
9
- const COMMUNITY_INDEX_URL = `${MARKETPLACE_BASE}/registry/community-index.yaml`;
10
- const CATEGORIES_URL = `${MARKETPLACE_BASE}/categories.yaml`;
8
+ const MARKETPLACE_OWNER = 'bmad-code-org';
9
+ const MARKETPLACE_REPO = 'bmad-plugins-marketplace';
10
+ const MARKETPLACE_REF = 'main';
11
11
 
12
12
  /**
13
13
  * Manages community modules from the BMad marketplace registry.
@@ -33,7 +33,12 @@ class CommunityModuleManager {
33
33
  if (this._cachedIndex) return this._cachedIndex;
34
34
 
35
35
  try {
36
- const config = await this._client.fetchYaml(COMMUNITY_INDEX_URL);
36
+ const config = await this._client.fetchGitHubYaml(
37
+ MARKETPLACE_OWNER,
38
+ MARKETPLACE_REPO,
39
+ 'registry/community-index.yaml',
40
+ MARKETPLACE_REF,
41
+ );
37
42
  if (config?.modules?.length) {
38
43
  this._cachedIndex = config;
39
44
  return config;
@@ -54,7 +59,7 @@ class CommunityModuleManager {
54
59
  if (this._cachedCategories) return this._cachedCategories;
55
60
 
56
61
  try {
57
- const config = await this._client.fetchYaml(CATEGORIES_URL);
62
+ const config = await this._client.fetchGitHubYaml(MARKETPLACE_OWNER, MARKETPLACE_REPO, 'categories.yaml', MARKETPLACE_REF);
58
63
  if (config?.categories) {
59
64
  this._cachedCategories = config;
60
65
  return config;
@@ -1,4 +1,4 @@
1
- const fs = require('fs-extra');
1
+ const fs = require('../fs-native');
2
2
  const os = require('node:os');
3
3
  const path = require('node:path');
4
4
  const { execSync } = require('node:child_process');
@@ -155,33 +155,6 @@ class CustomModuleManager {
155
155
  };
156
156
  }
157
157
 
158
- /**
159
- * @deprecated Use parseSource() instead. Kept for backward compatibility.
160
- * Parse and validate a GitHub repository URL.
161
- * @param {string} url - GitHub URL to validate
162
- * @returns {Object} { owner, repo, isValid, error }
163
- */
164
- validateGitHubUrl(url) {
165
- if (!url || typeof url !== 'string') {
166
- return { owner: null, repo: null, isValid: false, error: 'URL is required' };
167
- }
168
- const trimmed = url.trim();
169
-
170
- // HTTPS format: https://github.com/owner/repo[.git] (strict, no trailing path)
171
- const httpsMatch = trimmed.match(/^https?:\/\/github\.com\/([^/]+)\/([^/.]+?)(?:\.git)?$/);
172
- if (httpsMatch) {
173
- return { owner: httpsMatch[1], repo: httpsMatch[2], isValid: true, error: null };
174
- }
175
-
176
- // SSH format: git@github.com:owner/repo[.git]
177
- const sshMatch = trimmed.match(/^git@github\.com:([^/]+)\/([^/.]+?)(?:\.git)?$/);
178
- if (sshMatch) {
179
- return { owner: sshMatch[1], repo: sshMatch[2], isValid: true, error: null };
180
- }
181
-
182
- return { owner: null, repo: null, isValid: false, error: 'Not a valid GitHub URL (expected https://github.com/owner/repo)' };
183
- }
184
-
185
158
  // ─── Marketplace JSON ─────────────────────────────────────────────────────
186
159
 
187
160
  /**
@@ -1,4 +1,4 @@
1
- const fs = require('fs-extra');
1
+ const fs = require('../fs-native');
2
2
  const os = require('node:os');
3
3
  const path = require('node:path');
4
4
  const { execSync } = require('node:child_process');
@@ -6,7 +6,9 @@ const yaml = require('yaml');
6
6
  const prompts = require('../prompts');
7
7
  const { RegistryClient } = require('./registry-client');
8
8
 
9
- const REGISTRY_RAW_URL = 'https://raw.githubusercontent.com/bmad-code-org/bmad-plugins-marketplace/main/registry/official.yaml';
9
+ const MARKETPLACE_OWNER = 'bmad-code-org';
10
+ const MARKETPLACE_REPO = 'bmad-plugins-marketplace';
11
+ const MARKETPLACE_REF = 'main';
10
12
  const FALLBACK_CONFIG_PATH = path.join(__dirname, 'registry-fallback.yaml');
11
13
 
12
14
  /**
@@ -33,8 +35,7 @@ class ExternalModuleManager {
33
35
 
34
36
  // Try remote registry first
35
37
  try {
36
- const content = await this._client.fetch(REGISTRY_RAW_URL);
37
- const config = yaml.parse(content);
38
+ const config = await this._client.fetchGitHubYaml(MARKETPLACE_OWNER, MARKETPLACE_REPO, 'registry/official.yaml', MARKETPLACE_REF);
38
39
  if (config?.modules?.length) {
39
40
  this.cachedModules = config;
40
41
  return config;
@@ -109,46 +110,6 @@ class ExternalModuleManager {
109
110
  return modules.find((m) => m.code === code) || null;
110
111
  }
111
112
 
112
- /**
113
- * Get module info by key
114
- * @param {string} key - The module key (e.g., 'bmad-creative-intelligence-suite')
115
- * @returns {Object|null} Module info or null if not found
116
- */
117
- async getModuleByKey(key) {
118
- const modules = await this.listAvailable();
119
- return modules.find((m) => m.key === key) || null;
120
- }
121
-
122
- /**
123
- * Check if a module code exists in external modules
124
- * @param {string} code - The module code to check
125
- * @returns {boolean} True if the module exists
126
- */
127
- async hasModule(code) {
128
- const module = await this.getModuleByCode(code);
129
- return module !== null;
130
- }
131
-
132
- /**
133
- * Get the URL for a module by code
134
- * @param {string} code - The module code
135
- * @returns {string|null} The URL or null if not found
136
- */
137
- async getModuleUrl(code) {
138
- const module = await this.getModuleByCode(code);
139
- return module ? module.url : null;
140
- }
141
-
142
- /**
143
- * Get the module definition path for a module by code
144
- * @param {string} code - The module code
145
- * @returns {string|null} The module definition path or null if not found
146
- */
147
- async getModuleDefinition(code) {
148
- const module = await this.getModuleByCode(code);
149
- return module ? module.moduleDefinition : null;
150
- }
151
-
152
113
  /**
153
114
  * Get the cache directory for external modules
154
115
  * @returns {string} Path to the external modules cache directory
@@ -1,5 +1,5 @@
1
1
  const path = require('node:path');
2
- const fs = require('fs-extra');
2
+ const fs = require('../fs-native');
3
3
  const yaml = require('yaml');
4
4
  const prompts = require('../prompts');
5
5
  const { getProjectRoot, getSourcePath, getModulePath } = require('../project-root');
@@ -12,6 +12,8 @@ class OfficialModules {
12
12
  // Config collection state (merged from ConfigCollector)
13
13
  this.collectedConfig = {};
14
14
  this._existingConfig = null;
15
+ // Tracked during interactive config collection so {directory_name}
16
+ // placeholder defaults can be resolved in buildQuestion().
15
17
  this.currentProjectDir = null;
16
18
  }
17
19
 
@@ -500,32 +502,6 @@ class OfficialModules {
500
502
  }
501
503
  }
502
504
 
503
- /**
504
- * Find all .md agent files recursively in a directory
505
- * @param {string} dir - Directory to search
506
- * @returns {Array} List of .md agent file paths
507
- */
508
- async findAgentMdFiles(dir) {
509
- const agentFiles = [];
510
-
511
- async function searchDirectory(searchDir) {
512
- const entries = await fs.readdir(searchDir, { withFileTypes: true });
513
-
514
- for (const entry of entries) {
515
- const fullPath = path.join(searchDir, entry.name);
516
-
517
- if (entry.isFile() && entry.name.endsWith('.md')) {
518
- agentFiles.push(fullPath);
519
- } else if (entry.isDirectory()) {
520
- await searchDirectory(fullPath);
521
- }
522
- }
523
- }
524
-
525
- await searchDirectory(dir);
526
- return agentFiles;
527
- }
528
-
529
505
  /**
530
506
  * Create directories declared in module.yaml's `directories` key
531
507
  * This replaces the security-risky module installer pattern with declarative config
@@ -699,29 +675,6 @@ class OfficialModules {
699
675
  return { createdDirs, movedDirs, createdWdsFolders };
700
676
  }
701
677
 
702
- /**
703
- * Private: Process module configuration
704
- * @param {string} modulePath - Path to installed module
705
- * @param {string} moduleName - Module name
706
- */
707
- async processModuleConfig(modulePath, moduleName) {
708
- const configPath = path.join(modulePath, 'config.yaml');
709
-
710
- if (await fs.pathExists(configPath)) {
711
- try {
712
- let configContent = await fs.readFile(configPath, 'utf8');
713
-
714
- // Replace path placeholders
715
- configContent = configContent.replaceAll('{project-root}', `bmad/${moduleName}`);
716
- configContent = configContent.replaceAll('{module}', moduleName);
717
-
718
- await fs.writeFile(configPath, configContent, 'utf8');
719
- } catch (error) {
720
- await prompts.log.warn(`Failed to process module config: ${error.message}`);
721
- }
722
- }
723
- }
724
-
725
678
  /**
726
679
  * Private: Sync module files (preserving user modifications)
727
680
  * @param {string} sourcePath - Source module path
@@ -867,10 +820,10 @@ class OfficialModules {
867
820
  let foundAny = false;
868
821
  const entries = await fs.readdir(bmadDir, { withFileTypes: true });
869
822
 
823
+ const nonModuleDirs = new Set(['_config', '_memory', 'memory', 'docs', 'scripts', 'custom']);
870
824
  for (const entry of entries) {
871
825
  if (entry.isDirectory()) {
872
- // Skip the _config directory - it's for system use
873
- if (entry.name === '_config' || entry.name === '_memory') {
826
+ if (nonModuleDirs.has(entry.name)) {
874
827
  continue;
875
828
  }
876
829
 
@@ -1091,7 +1044,6 @@ class OfficialModules {
1091
1044
  */
1092
1045
  async collectModuleConfigQuick(moduleName, projectDir, silentMode = true) {
1093
1046
  this.currentProjectDir = projectDir;
1094
-
1095
1047
  // Load existing config if not already loaded
1096
1048
  if (!this._existingConfig) {
1097
1049
  await this.loadExistingConfig(projectDir);
@@ -1,4 +1,4 @@
1
- const fs = require('fs-extra');
1
+ const fs = require('../fs-native');
2
2
  const path = require('node:path');
3
3
  const yaml = require('yaml');
4
4