bmad-method 6.2.3-next.0 → 6.2.3-next.1

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 (74) hide show
  1. package/package.json +8 -8
  2. package/src/core-skills/bmad-distillator/resources/distillate-format-reference.md +1 -1
  3. package/tools/{cli → installer}/bmad-cli.js +3 -1
  4. package/tools/{cli/lib → installer}/cli-utils.js +3 -4
  5. package/tools/{cli → installer}/commands/install.js +3 -3
  6. package/tools/{cli → installer}/commands/status.js +4 -4
  7. package/tools/{cli → installer}/commands/uninstall.js +5 -5
  8. package/tools/installer/core/config.js +52 -0
  9. package/tools/{cli/installers/lib → installer}/core/custom-module-cache.js +1 -1
  10. package/tools/installer/core/existing-install.js +127 -0
  11. package/tools/installer/core/install-paths.js +129 -0
  12. package/tools/installer/core/installer.js +1790 -0
  13. package/tools/{cli/installers/lib → installer}/core/manifest-generator.js +3 -3
  14. package/tools/{cli/installers/lib → installer}/core/manifest.js +2 -2
  15. package/tools/{cli/installers/lib/custom/handler.js → installer/custom-handler.js} +1 -1
  16. package/tools/{cli/installers/lib → installer}/ide/_config-driven.js +30 -397
  17. package/tools/{cli/installers/lib → installer}/ide/manager.js +1 -53
  18. package/tools/installer/ide/platform-codes.js +37 -0
  19. package/tools/installer/ide/platform-codes.yaml +190 -0
  20. package/tools/{cli/installers/lib → installer}/ide/shared/module-injections.js +1 -1
  21. package/tools/{cli/installers/lib → installer}/message-loader.js +2 -2
  22. package/tools/installer/modules/custom-modules.js +197 -0
  23. package/tools/installer/modules/external-manager.js +323 -0
  24. package/tools/{cli/installers/lib/core/config-collector.js → installer/modules/official-modules.js} +714 -43
  25. package/tools/{cli/lib → installer}/ui.js +65 -299
  26. package/tools/javascript-conventions.md +5 -0
  27. package/tools/bmad-npx-wrapper.js +0 -38
  28. package/tools/cli/installers/lib/core/dependency-resolver.js +0 -743
  29. package/tools/cli/installers/lib/core/detector.js +0 -223
  30. package/tools/cli/installers/lib/core/ide-config-manager.js +0 -157
  31. package/tools/cli/installers/lib/core/installer.js +0 -3002
  32. package/tools/cli/installers/lib/ide/_base-ide.js +0 -657
  33. package/tools/cli/installers/lib/ide/platform-codes.js +0 -100
  34. package/tools/cli/installers/lib/ide/platform-codes.yaml +0 -341
  35. package/tools/cli/installers/lib/modules/external-manager.js +0 -136
  36. package/tools/cli/installers/lib/modules/manager.js +0 -928
  37. package/tools/cli/lib/config.js +0 -213
  38. package/tools/cli/lib/platform-codes.js +0 -116
  39. package/tools/lib/xml-utils.js +0 -13
  40. /package/tools/{cli → installer}/README.md +0 -0
  41. /package/tools/{cli → installer}/external-official-modules.yaml +0 -0
  42. /package/tools/{cli/lib → installer}/file-ops.js +0 -0
  43. /package/tools/{cli/installers/lib → installer}/ide/shared/agent-command-generator.js +0 -0
  44. /package/tools/{cli/installers/lib → installer}/ide/shared/bmad-artifacts.js +0 -0
  45. /package/tools/{cli/installers/lib → installer}/ide/shared/path-utils.js +0 -0
  46. /package/tools/{cli/installers/lib → installer}/ide/shared/skill-manifest.js +0 -0
  47. /package/tools/{cli/installers/lib → installer}/ide/templates/agent-command-template.md +0 -0
  48. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/antigravity.md +0 -0
  49. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-agent.md +0 -0
  50. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-task.md +0 -0
  51. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-tool.md +0 -0
  52. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/default-workflow.md +0 -0
  53. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-agent.toml +0 -0
  54. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-task.toml +0 -0
  55. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-tool.toml +0 -0
  56. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-workflow-yaml.toml +0 -0
  57. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/gemini-workflow.toml +0 -0
  58. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-agent.md +0 -0
  59. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-task.md +0 -0
  60. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-tool.md +0 -0
  61. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/kiro-workflow.md +0 -0
  62. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-agent.md +0 -0
  63. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-task.md +0 -0
  64. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-tool.md +0 -0
  65. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-workflow-yaml.md +0 -0
  66. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/opencode-workflow.md +0 -0
  67. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/rovodev.md +0 -0
  68. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/trae.md +0 -0
  69. /package/tools/{cli/installers/lib → installer}/ide/templates/combined/windsurf-workflow.md +0 -0
  70. /package/tools/{cli/installers/lib → installer}/ide/templates/split/.gitkeep +0 -0
  71. /package/tools/{cli/installers → installer}/install-messages.yaml +0 -0
  72. /package/tools/{cli/lib → installer}/project-root.js +0 -0
  73. /package/tools/{cli/lib → installer}/prompts.js +0 -0
  74. /package/tools/{cli/lib → installer}/yaml-format.js +0 -0
@@ -1,223 +0,0 @@
1
- const path = require('node:path');
2
- const fs = require('fs-extra');
3
- const yaml = require('yaml');
4
- const { Manifest } = require('./manifest');
5
-
6
- class Detector {
7
- /**
8
- * Detect existing BMAD installation
9
- * @param {string} bmadDir - Path to bmad directory
10
- * @returns {Object} Installation status and details
11
- */
12
- async detect(bmadDir) {
13
- const result = {
14
- installed: false,
15
- path: bmadDir,
16
- version: null,
17
- hasCore: false,
18
- modules: [],
19
- ides: [],
20
- customModules: [],
21
- manifest: null,
22
- };
23
-
24
- // Check if bmad directory exists
25
- if (!(await fs.pathExists(bmadDir))) {
26
- return result;
27
- }
28
-
29
- // Check for manifest using the Manifest class
30
- const manifest = new Manifest();
31
- const manifestData = await manifest.read(bmadDir);
32
- if (manifestData) {
33
- result.manifest = manifestData;
34
- result.version = manifestData.version;
35
- result.installed = true;
36
- // Copy custom modules if they exist
37
- if (manifestData.customModules) {
38
- result.customModules = manifestData.customModules;
39
- }
40
- }
41
-
42
- // Check for core
43
- const corePath = path.join(bmadDir, 'core');
44
- if (await fs.pathExists(corePath)) {
45
- result.hasCore = true;
46
-
47
- // Try to get core version from config
48
- const coreConfigPath = path.join(corePath, 'config.yaml');
49
- if (await fs.pathExists(coreConfigPath)) {
50
- try {
51
- const configContent = await fs.readFile(coreConfigPath, 'utf8');
52
- const config = yaml.parse(configContent);
53
- if (!result.version && config.version) {
54
- result.version = config.version;
55
- }
56
- } catch {
57
- // Ignore config read errors
58
- }
59
- }
60
- }
61
-
62
- // Check for modules
63
- // If manifest exists, use it as the source of truth for installed modules
64
- // Otherwise fall back to directory scanning (legacy installations)
65
- if (manifestData && manifestData.modules && manifestData.modules.length > 0) {
66
- // Use manifest module list - these are officially installed modules
67
- for (const moduleId of manifestData.modules) {
68
- const modulePath = path.join(bmadDir, moduleId);
69
- const moduleConfigPath = path.join(modulePath, 'config.yaml');
70
-
71
- const moduleInfo = {
72
- id: moduleId,
73
- path: modulePath,
74
- version: 'unknown',
75
- };
76
-
77
- if (await fs.pathExists(moduleConfigPath)) {
78
- try {
79
- const configContent = await fs.readFile(moduleConfigPath, 'utf8');
80
- const config = yaml.parse(configContent);
81
- moduleInfo.version = config.version || 'unknown';
82
- moduleInfo.name = config.name || moduleId;
83
- moduleInfo.description = config.description;
84
- } catch {
85
- // Ignore config read errors
86
- }
87
- }
88
-
89
- result.modules.push(moduleInfo);
90
- }
91
- } else {
92
- // Fallback: scan directory for modules (legacy installations without manifest)
93
- const entries = await fs.readdir(bmadDir, { withFileTypes: true });
94
- for (const entry of entries) {
95
- if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config') {
96
- const modulePath = path.join(bmadDir, entry.name);
97
- const moduleConfigPath = path.join(modulePath, 'config.yaml');
98
-
99
- // Only treat it as a module if it has a config.yaml
100
- if (await fs.pathExists(moduleConfigPath)) {
101
- const moduleInfo = {
102
- id: entry.name,
103
- path: modulePath,
104
- version: 'unknown',
105
- };
106
-
107
- try {
108
- const configContent = await fs.readFile(moduleConfigPath, 'utf8');
109
- const config = yaml.parse(configContent);
110
- moduleInfo.version = config.version || 'unknown';
111
- moduleInfo.name = config.name || entry.name;
112
- moduleInfo.description = config.description;
113
- } catch {
114
- // Ignore config read errors
115
- }
116
-
117
- result.modules.push(moduleInfo);
118
- }
119
- }
120
- }
121
- }
122
-
123
- // Check for IDE configurations from manifest
124
- if (result.manifest && result.manifest.ides) {
125
- // Filter out any undefined/null values
126
- result.ides = result.manifest.ides.filter((ide) => ide && typeof ide === 'string');
127
- }
128
-
129
- // Mark as installed if we found core or modules
130
- if (result.hasCore || result.modules.length > 0) {
131
- result.installed = true;
132
- }
133
-
134
- return result;
135
- }
136
-
137
- /**
138
- * Detect legacy installation (_bmad-method, .bmm, .cis)
139
- * @param {string} projectDir - Project directory to check
140
- * @returns {Object} Legacy installation details
141
- */
142
- async detectLegacy(projectDir) {
143
- const result = {
144
- hasLegacy: false,
145
- legacyCore: false,
146
- legacyModules: [],
147
- paths: [],
148
- };
149
-
150
- // Check for legacy core (_bmad-method)
151
- const legacyCorePath = path.join(projectDir, '_bmad-method');
152
- if (await fs.pathExists(legacyCorePath)) {
153
- result.hasLegacy = true;
154
- result.legacyCore = true;
155
- result.paths.push(legacyCorePath);
156
- }
157
-
158
- // Check for legacy modules (directories starting with .)
159
- const entries = await fs.readdir(projectDir, { withFileTypes: true });
160
- for (const entry of entries) {
161
- if (
162
- entry.isDirectory() &&
163
- entry.name.startsWith('.') &&
164
- entry.name !== '_bmad-method' &&
165
- !entry.name.startsWith('.git') &&
166
- !entry.name.startsWith('.vscode') &&
167
- !entry.name.startsWith('.idea')
168
- ) {
169
- const modulePath = path.join(projectDir, entry.name);
170
- const moduleManifestPath = path.join(modulePath, 'install-manifest.yaml');
171
-
172
- // Check if it's likely a BMAD module
173
- if ((await fs.pathExists(moduleManifestPath)) || (await fs.pathExists(path.join(modulePath, 'config.yaml')))) {
174
- result.hasLegacy = true;
175
- result.legacyModules.push({
176
- name: entry.name.slice(1), // Remove leading dot
177
- path: modulePath,
178
- });
179
- result.paths.push(modulePath);
180
- }
181
- }
182
- }
183
-
184
- return result;
185
- }
186
-
187
- /**
188
- * Check if migration from legacy is needed
189
- * @param {string} projectDir - Project directory
190
- * @returns {Object} Migration requirements
191
- */
192
- async checkMigrationNeeded(projectDir) {
193
- const bmadDir = path.join(projectDir, 'bmad');
194
- const current = await this.detect(bmadDir);
195
- const legacy = await this.detectLegacy(projectDir);
196
-
197
- return {
198
- needed: legacy.hasLegacy && !current.installed,
199
- canMigrate: legacy.hasLegacy,
200
- legacy: legacy,
201
- current: current,
202
- };
203
- }
204
-
205
- /**
206
- * Detect legacy BMAD v4 .bmad-method folder
207
- * @param {string} projectDir - Project directory to check
208
- * @returns {{ hasLegacyV4: boolean, offenders: string[] }}
209
- */
210
- async detectLegacyV4(projectDir) {
211
- const offenders = [];
212
-
213
- // Check for .bmad-method folder
214
- const bmadMethodPath = path.join(projectDir, '.bmad-method');
215
- if (await fs.pathExists(bmadMethodPath)) {
216
- offenders.push(bmadMethodPath);
217
- }
218
-
219
- return { hasLegacyV4: offenders.length > 0, offenders };
220
- }
221
- }
222
-
223
- module.exports = { Detector };
@@ -1,157 +0,0 @@
1
- const path = require('node:path');
2
- const fs = require('fs-extra');
3
- const yaml = require('yaml');
4
- const prompts = require('../../../lib/prompts');
5
-
6
- /**
7
- * Manages IDE configuration persistence
8
- * Saves and loads IDE-specific configurations to/from bmad/_config/ides/
9
- */
10
- class IdeConfigManager {
11
- constructor() {}
12
-
13
- /**
14
- * Get path to IDE config directory
15
- * @param {string} bmadDir - BMAD installation directory
16
- * @returns {string} Path to IDE config directory
17
- */
18
- getIdeConfigDir(bmadDir) {
19
- return path.join(bmadDir, '_config', 'ides');
20
- }
21
-
22
- /**
23
- * Get path to specific IDE config file
24
- * @param {string} bmadDir - BMAD installation directory
25
- * @param {string} ideName - IDE name (e.g., 'claude-code')
26
- * @returns {string} Path to IDE config file
27
- */
28
- getIdeConfigPath(bmadDir, ideName) {
29
- return path.join(this.getIdeConfigDir(bmadDir), `${ideName}.yaml`);
30
- }
31
-
32
- /**
33
- * Save IDE configuration
34
- * @param {string} bmadDir - BMAD installation directory
35
- * @param {string} ideName - IDE name
36
- * @param {Object} configuration - IDE-specific configuration object
37
- */
38
- async saveIdeConfig(bmadDir, ideName, configuration) {
39
- const configDir = this.getIdeConfigDir(bmadDir);
40
- await fs.ensureDir(configDir);
41
-
42
- const configPath = this.getIdeConfigPath(bmadDir, ideName);
43
- const now = new Date().toISOString();
44
-
45
- // Check if config already exists to preserve configured_date
46
- let configuredDate = now;
47
- if (await fs.pathExists(configPath)) {
48
- try {
49
- const existing = await this.loadIdeConfig(bmadDir, ideName);
50
- if (existing && existing.configured_date) {
51
- configuredDate = existing.configured_date;
52
- }
53
- } catch {
54
- // Ignore errors reading existing config
55
- }
56
- }
57
-
58
- const configData = {
59
- ide: ideName,
60
- configured_date: configuredDate,
61
- last_updated: now,
62
- configuration: configuration || {},
63
- };
64
-
65
- // Clean the config to remove any non-serializable values (like functions)
66
- const cleanConfig = structuredClone(configData);
67
-
68
- const yamlContent = yaml.stringify(cleanConfig, {
69
- indent: 2,
70
- lineWidth: 0,
71
- sortKeys: false,
72
- });
73
-
74
- // Ensure POSIX-compliant final newline
75
- const content = yamlContent.endsWith('\n') ? yamlContent : yamlContent + '\n';
76
- await fs.writeFile(configPath, content, 'utf8');
77
- }
78
-
79
- /**
80
- * Load IDE configuration
81
- * @param {string} bmadDir - BMAD installation directory
82
- * @param {string} ideName - IDE name
83
- * @returns {Object|null} IDE configuration or null if not found
84
- */
85
- async loadIdeConfig(bmadDir, ideName) {
86
- const configPath = this.getIdeConfigPath(bmadDir, ideName);
87
-
88
- if (!(await fs.pathExists(configPath))) {
89
- return null;
90
- }
91
-
92
- try {
93
- const content = await fs.readFile(configPath, 'utf8');
94
- const config = yaml.parse(content);
95
- return config;
96
- } catch (error) {
97
- await prompts.log.warn(`Failed to load IDE config for ${ideName}: ${error.message}`);
98
- return null;
99
- }
100
- }
101
-
102
- /**
103
- * Load all IDE configurations
104
- * @param {string} bmadDir - BMAD installation directory
105
- * @returns {Object} Map of IDE name to configuration
106
- */
107
- async loadAllIdeConfigs(bmadDir) {
108
- const configDir = this.getIdeConfigDir(bmadDir);
109
- const configs = {};
110
-
111
- if (!(await fs.pathExists(configDir))) {
112
- return configs;
113
- }
114
-
115
- try {
116
- const files = await fs.readdir(configDir);
117
- for (const file of files) {
118
- if (file.endsWith('.yaml')) {
119
- const ideName = file.replace('.yaml', '');
120
- const config = await this.loadIdeConfig(bmadDir, ideName);
121
- if (config) {
122
- configs[ideName] = config.configuration;
123
- }
124
- }
125
- }
126
- } catch (error) {
127
- await prompts.log.warn(`Failed to load IDE configs: ${error.message}`);
128
- }
129
-
130
- return configs;
131
- }
132
-
133
- /**
134
- * Check if IDE has saved configuration
135
- * @param {string} bmadDir - BMAD installation directory
136
- * @param {string} ideName - IDE name
137
- * @returns {boolean} True if configuration exists
138
- */
139
- async hasIdeConfig(bmadDir, ideName) {
140
- const configPath = this.getIdeConfigPath(bmadDir, ideName);
141
- return await fs.pathExists(configPath);
142
- }
143
-
144
- /**
145
- * Delete IDE configuration
146
- * @param {string} bmadDir - BMAD installation directory
147
- * @param {string} ideName - IDE name
148
- */
149
- async deleteIdeConfig(bmadDir, ideName) {
150
- const configPath = this.getIdeConfigPath(bmadDir, ideName);
151
- if (await fs.pathExists(configPath)) {
152
- await fs.remove(configPath);
153
- }
154
- }
155
- }
156
-
157
- module.exports = { IdeConfigManager };