bmad-method 6.2.3-next.8 → 6.3.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 (76) hide show
  1. package/.claude-plugin/marketplace.json +0 -3
  2. package/README.md +8 -9
  3. package/README_CN.md +1 -1
  4. package/README_VN.md +110 -0
  5. package/package.json +1 -1
  6. package/removals.txt +17 -0
  7. package/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/steps/step-13-responsive-accessibility.md +1 -1
  8. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/data/prd-purpose.md +197 -0
  9. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-01-discovery.md +1 -1
  10. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-01b-legacy-conversion.md +1 -1
  11. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-02-review.md +1 -1
  12. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-03-edit.md +1 -1
  13. package/src/bmm-skills/2-plan-workflows/bmad-edit-prd/steps-e/step-e-04-complete.md +1 -3
  14. package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/steps/step-01-document-discovery.md +1 -1
  15. package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/steps/step-02-prd-analysis.md +1 -1
  16. package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/steps/step-03-epic-coverage-validation.md +1 -1
  17. package/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/workflow.md +1 -1
  18. package/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/workflow.md +1 -1
  19. package/src/bmm-skills/4-implementation/bmad-agent-dev/SKILL.md +5 -0
  20. package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/SKILL.md +29 -0
  21. package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/generate-trail.md +38 -0
  22. package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/step-01-orientation.md +105 -0
  23. package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/step-02-walkthrough.md +89 -0
  24. package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/step-03-detail-pass.md +106 -0
  25. package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/step-04-testing.md +74 -0
  26. package/src/bmm-skills/4-implementation/bmad-checkpoint-preview/step-05-wrapup.md +24 -0
  27. package/src/bmm-skills/4-implementation/bmad-code-review/steps/step-01-gather-context.md +38 -15
  28. package/src/bmm-skills/4-implementation/bmad-correct-course/checklist.md +2 -2
  29. package/src/bmm-skills/4-implementation/bmad-correct-course/workflow.md +8 -8
  30. package/src/bmm-skills/4-implementation/bmad-qa-generate-e2e-tests/checklist.md +1 -1
  31. package/src/bmm-skills/4-implementation/bmad-quick-dev/compile-epic-context.md +62 -0
  32. package/src/bmm-skills/4-implementation/bmad-quick-dev/spec-template.md +1 -1
  33. package/src/bmm-skills/4-implementation/bmad-quick-dev/step-01-clarify-and-route.md +33 -6
  34. package/src/bmm-skills/4-implementation/bmad-quick-dev/step-02-plan.md +20 -8
  35. package/src/bmm-skills/4-implementation/bmad-quick-dev/step-03-implement.md +2 -0
  36. package/src/bmm-skills/4-implementation/bmad-quick-dev/step-oneshot.md +16 -4
  37. package/src/bmm-skills/4-implementation/bmad-quick-dev/workflow.md +1 -5
  38. package/src/bmm-skills/4-implementation/bmad-retrospective/workflow.md +134 -134
  39. package/src/bmm-skills/4-implementation/bmad-sprint-planning/sprint-status-template.yaml +1 -1
  40. package/src/bmm-skills/4-implementation/bmad-sprint-planning/workflow.md +3 -3
  41. package/src/bmm-skills/4-implementation/bmad-sprint-status/workflow.md +2 -2
  42. package/src/bmm-skills/module-help.csv +2 -0
  43. package/src/core-skills/bmad-help/SKILL.md +4 -2
  44. package/src/core-skills/bmad-party-mode/SKILL.md +121 -2
  45. package/src/core-skills/module-help.csv +1 -0
  46. package/tools/installer/cli-utils.js +18 -9
  47. package/tools/installer/commands/install.js +1 -1
  48. package/tools/installer/core/existing-install.js +2 -8
  49. package/tools/installer/core/install-paths.js +0 -3
  50. package/tools/installer/core/installer.js +180 -463
  51. package/tools/installer/core/manifest-generator.js +8 -14
  52. package/tools/installer/core/manifest.js +94 -102
  53. package/tools/installer/ide/_config-driven.js +149 -38
  54. package/tools/installer/ide/shared/skill-manifest.js +1 -16
  55. package/tools/installer/install-messages.yaml +19 -26
  56. package/tools/installer/modules/community-manager.js +377 -0
  57. package/tools/installer/modules/custom-module-manager.js +644 -0
  58. package/tools/installer/modules/external-manager.js +65 -49
  59. package/tools/installer/modules/official-modules.js +117 -65
  60. package/tools/installer/modules/plugin-resolver.js +398 -0
  61. package/tools/installer/modules/registry-client.js +66 -0
  62. package/tools/installer/{external-official-modules.yaml → modules/registry-fallback.yaml} +3 -12
  63. package/tools/installer/ui.js +549 -666
  64. package/src/bmm-skills/4-implementation/bmad-agent-qa/SKILL.md +0 -61
  65. package/src/bmm-skills/4-implementation/bmad-agent-qa/bmad-skill-manifest.yaml +0 -11
  66. package/src/bmm-skills/4-implementation/bmad-agent-quick-flow-solo-dev/SKILL.md +0 -53
  67. package/src/bmm-skills/4-implementation/bmad-agent-quick-flow-solo-dev/bmad-skill-manifest.yaml +0 -11
  68. package/src/bmm-skills/4-implementation/bmad-agent-sm/SKILL.md +0 -55
  69. package/src/bmm-skills/4-implementation/bmad-agent-sm/bmad-skill-manifest.yaml +0 -11
  70. package/src/core-skills/bmad-party-mode/steps/step-01-agent-loading.md +0 -138
  71. package/src/core-skills/bmad-party-mode/steps/step-02-discussion-orchestration.md +0 -187
  72. package/src/core-skills/bmad-party-mode/steps/step-03-graceful-exit.md +0 -167
  73. package/src/core-skills/bmad-party-mode/workflow.md +0 -183
  74. package/tools/installer/core/custom-module-cache.js +0 -260
  75. package/tools/installer/custom-handler.js +0 -112
  76. package/tools/installer/modules/custom-modules.js +0 -197
@@ -1,112 +0,0 @@
1
- const path = require('node:path');
2
- const fs = require('fs-extra');
3
- const yaml = require('yaml');
4
- const prompts = require('./prompts');
5
- /**
6
- * Handler for custom content (custom.yaml)
7
- * Discovers custom agents and workflows in the project
8
- */
9
- class CustomHandler {
10
- /**
11
- * Find all custom.yaml files in the project
12
- * @param {string} projectRoot - Project root directory
13
- * @returns {Array} List of custom content paths
14
- */
15
- async findCustomContent(projectRoot) {
16
- const customPaths = [];
17
-
18
- // Helper function to recursively scan directories
19
- async function scanDirectory(dir, excludePaths = []) {
20
- try {
21
- const entries = await fs.readdir(dir, { withFileTypes: true });
22
-
23
- for (const entry of entries) {
24
- const fullPath = path.join(dir, entry.name);
25
-
26
- // Skip hidden directories and common exclusions
27
- if (
28
- entry.name.startsWith('.') ||
29
- entry.name === 'node_modules' ||
30
- entry.name === 'dist' ||
31
- entry.name === 'build' ||
32
- entry.name === '.git' ||
33
- entry.name === 'bmad'
34
- ) {
35
- continue;
36
- }
37
-
38
- // Skip excluded paths
39
- if (excludePaths.some((exclude) => fullPath.startsWith(exclude))) {
40
- continue;
41
- }
42
-
43
- if (entry.isDirectory()) {
44
- // Recursively scan subdirectories
45
- await scanDirectory(fullPath, excludePaths);
46
- } else if (entry.name === 'custom.yaml') {
47
- // Found a custom.yaml file
48
- customPaths.push(fullPath);
49
- } else if (
50
- entry.name === 'module.yaml' && // Check if this is a custom module (in root directory)
51
- // Skip if it's in src/modules (those are standard modules)
52
- !fullPath.includes(path.join('src', 'modules'))
53
- ) {
54
- customPaths.push(fullPath);
55
- }
56
- }
57
- } catch {
58
- // Ignore errors (e.g., permission denied)
59
- }
60
- }
61
-
62
- // Scan the entire project, but exclude source directories
63
- await scanDirectory(projectRoot, [path.join(projectRoot, 'src'), path.join(projectRoot, 'tools'), path.join(projectRoot, 'test')]);
64
-
65
- return customPaths;
66
- }
67
-
68
- /**
69
- * Get custom content info from a custom.yaml or module.yaml file
70
- * @param {string} configPath - Path to config file
71
- * @param {string} projectRoot - Project root directory for calculating relative paths
72
- * @returns {Object|null} Custom content info
73
- */
74
- async getCustomInfo(configPath, projectRoot = null) {
75
- try {
76
- const configContent = await fs.readFile(configPath, 'utf8');
77
-
78
- // Try to parse YAML with error handling
79
- let config;
80
- try {
81
- config = yaml.parse(configContent);
82
- } catch (parseError) {
83
- await prompts.log.warn('YAML parse error in ' + configPath + ': ' + parseError.message);
84
- return null;
85
- }
86
-
87
- // Check if this is an module.yaml (module) or custom.yaml (custom content)
88
- const isInstallConfig = configPath.endsWith('module.yaml');
89
- const configDir = path.dirname(configPath);
90
-
91
- // Use provided projectRoot or fall back to process.cwd()
92
- const basePath = projectRoot || process.cwd();
93
- const relativePath = path.relative(basePath, configDir);
94
-
95
- return {
96
- id: config.code || 'unknown-code',
97
- name: config.name,
98
- description: config.description || '',
99
- path: configDir,
100
- relativePath: relativePath,
101
- defaultSelected: config.default_selected === true,
102
- config: config,
103
- isInstallConfig: isInstallConfig, // Track which type this is
104
- };
105
- } catch (error) {
106
- await prompts.log.warn('Failed to read ' + configPath + ': ' + error.message);
107
- return null;
108
- }
109
- }
110
- }
111
-
112
- module.exports = { CustomHandler };
@@ -1,197 +0,0 @@
1
- const path = require('node:path');
2
- const fs = require('fs-extra');
3
- const yaml = require('yaml');
4
- const { CustomHandler } = require('../custom-handler');
5
- const { Manifest } = require('../core/manifest');
6
- const prompts = require('../prompts');
7
-
8
- class CustomModules {
9
- constructor() {
10
- this.paths = new Map();
11
- }
12
-
13
- has(moduleCode) {
14
- return this.paths.has(moduleCode);
15
- }
16
-
17
- get(moduleCode) {
18
- return this.paths.get(moduleCode);
19
- }
20
-
21
- set(moduleId, sourcePath) {
22
- this.paths.set(moduleId, sourcePath);
23
- }
24
-
25
- /**
26
- * Install a custom module from its source path.
27
- * @param {string} moduleName - Module identifier
28
- * @param {string} bmadDir - Target bmad directory
29
- * @param {Function} fileTrackingCallback - Optional callback to track installed files
30
- * @param {Object} options - Install options
31
- * @param {Object} options.moduleConfig - Pre-collected module configuration
32
- * @returns {Object} Install result
33
- */
34
- async install(moduleName, bmadDir, fileTrackingCallback = null, options = {}) {
35
- const sourcePath = this.paths.get(moduleName);
36
- if (!sourcePath) {
37
- throw new Error(`No source path for custom module '${moduleName}'`);
38
- }
39
-
40
- if (!(await fs.pathExists(sourcePath))) {
41
- throw new Error(`Source for custom module '${moduleName}' not found at: ${sourcePath}`);
42
- }
43
-
44
- const targetPath = path.join(bmadDir, moduleName);
45
-
46
- // Read custom.yaml and merge into module config
47
- let moduleConfig = options.moduleConfig ? { ...options.moduleConfig } : {};
48
- const customConfigPath = path.join(sourcePath, 'custom.yaml');
49
- if (await fs.pathExists(customConfigPath)) {
50
- try {
51
- const content = await fs.readFile(customConfigPath, 'utf8');
52
- const customConfig = yaml.parse(content);
53
- if (customConfig) {
54
- moduleConfig = { ...moduleConfig, ...customConfig };
55
- }
56
- } catch (error) {
57
- await prompts.log.warn(`Failed to read custom.yaml for ${moduleName}: ${error.message}`);
58
- }
59
- }
60
-
61
- // Remove existing installation
62
- if (await fs.pathExists(targetPath)) {
63
- await fs.remove(targetPath);
64
- }
65
-
66
- // Copy files with filtering
67
- await this._copyWithFiltering(sourcePath, targetPath, fileTrackingCallback);
68
-
69
- // Add to manifest
70
- const manifest = new Manifest();
71
- const versionInfo = await manifest.getModuleVersionInfo(moduleName, bmadDir, sourcePath);
72
- await manifest.addModule(bmadDir, moduleName, {
73
- version: versionInfo.version,
74
- source: versionInfo.source,
75
- npmPackage: versionInfo.npmPackage,
76
- repoUrl: versionInfo.repoUrl,
77
- });
78
-
79
- return { success: true, module: moduleName, path: targetPath, moduleConfig };
80
- }
81
-
82
- /**
83
- * Copy module files, filtering out install-time-only artifacts.
84
- * @param {string} sourcePath - Source module directory
85
- * @param {string} targetPath - Target module directory
86
- * @param {Function} fileTrackingCallback - Optional callback to track installed files
87
- */
88
- async _copyWithFiltering(sourcePath, targetPath, fileTrackingCallback = null) {
89
- const files = await this._getFileList(sourcePath);
90
-
91
- for (const file of files) {
92
- if (file.startsWith('sub-modules/')) continue;
93
-
94
- const isInSidecar = path
95
- .dirname(file)
96
- .split('/')
97
- .some((dir) => dir.toLowerCase().endsWith('-sidecar'));
98
- if (isInSidecar) continue;
99
-
100
- if (file === 'module.yaml') continue;
101
- if (file === 'config.yaml') continue;
102
-
103
- const sourceFile = path.join(sourcePath, file);
104
- const targetFile = path.join(targetPath, file);
105
-
106
- // Skip web-only agents
107
- if (file.startsWith('agents/') && file.endsWith('.md')) {
108
- const content = await fs.readFile(sourceFile, 'utf8');
109
- if (/<agent[^>]*\slocalskip="true"[^>]*>/.test(content)) {
110
- continue;
111
- }
112
- }
113
-
114
- await fs.ensureDir(path.dirname(targetFile));
115
- await fs.copy(sourceFile, targetFile, { overwrite: true });
116
-
117
- if (fileTrackingCallback) {
118
- fileTrackingCallback(targetFile);
119
- }
120
- }
121
- }
122
-
123
- /**
124
- * Recursively list all files in a directory.
125
- * @param {string} dir - Directory to scan
126
- * @param {string} baseDir - Base directory for relative paths
127
- * @returns {string[]} Relative file paths
128
- */
129
- async _getFileList(dir, baseDir = dir) {
130
- const files = [];
131
- const entries = await fs.readdir(dir, { withFileTypes: true });
132
-
133
- for (const entry of entries) {
134
- const fullPath = path.join(dir, entry.name);
135
- if (entry.isDirectory()) {
136
- files.push(...(await this._getFileList(fullPath, baseDir)));
137
- } else {
138
- files.push(path.relative(baseDir, fullPath));
139
- }
140
- }
141
-
142
- return files;
143
- }
144
-
145
- /**
146
- * Discover custom module source paths from all available sources.
147
- * @param {Object} config - Installation configuration
148
- * @param {Object} paths - InstallPaths instance
149
- * @returns {Map<string, string>} Map of module ID to source path
150
- */
151
- async discoverPaths(config, paths) {
152
- this.paths = new Map();
153
-
154
- if (config._quickUpdate) {
155
- if (config._customModuleSources) {
156
- for (const [moduleId, customInfo] of config._customModuleSources) {
157
- this.paths.set(moduleId, customInfo.sourcePath);
158
- }
159
- }
160
- return this.paths;
161
- }
162
-
163
- // From UI: selectedFiles
164
- if (config.customContent && config.customContent.selected && config.customContent.selectedFiles) {
165
- const customHandler = new CustomHandler();
166
- for (const customFile of config.customContent.selectedFiles) {
167
- const customInfo = await customHandler.getCustomInfo(customFile, paths.projectRoot);
168
- if (customInfo && customInfo.id) {
169
- this.paths.set(customInfo.id, customInfo.path);
170
- }
171
- }
172
- }
173
-
174
- // From UI: sources
175
- if (config.customContent && config.customContent.sources) {
176
- for (const source of config.customContent.sources) {
177
- this.paths.set(source.id, source.path);
178
- }
179
- }
180
-
181
- // From UI: cachedModules
182
- if (config.customContent && config.customContent.cachedModules) {
183
- const selectedCachedIds = config.customContent.selectedCachedModules || [];
184
- const shouldIncludeAll = selectedCachedIds.length === 0 && config.customContent.selected;
185
-
186
- for (const cachedModule of config.customContent.cachedModules) {
187
- if (cachedModule.id && cachedModule.cachePath && (shouldIncludeAll || selectedCachedIds.includes(cachedModule.id))) {
188
- this.paths.set(cachedModule.id, cachedModule.cachePath);
189
- }
190
- }
191
- }
192
-
193
- return this.paths;
194
- }
195
- }
196
-
197
- module.exports = { CustomModules };