bmad-method 4.24.0 → 4.24.2
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.
- package/.vscode/settings.json +11 -5
- package/CHANGELOG.md +17 -1
- package/README.md +1 -1
- package/bmad-core/agents/bmad-master.md +1 -1
- package/bmad-core/agents/dev.md +2 -2
- package/bmad-core/agents/pm.md +1 -1
- package/bmad-core/agents/po.md +1 -1
- package/bmad-core/{core-config.yml → core-config.yaml} +1 -1
- package/bmad-core/data/bmad-kb.md +4 -4
- package/bmad-core/tasks/create-brownfield-story.md +1 -1
- package/bmad-core/tasks/create-next-story.md +4 -4
- package/bmad-core/tasks/shard-doc.md +3 -3
- package/bmad-core/tasks/update-workflow-plan.md +1 -1
- package/bmad-core/templates/architecture-tmpl.md +1 -1
- package/bmad-core/templates/fullstack-architecture-tmpl.md +3 -3
- package/bmad-core/utils/plan-management.md +1 -1
- package/common/tasks/create-doc.md +1 -1
- package/dist/agents/analyst.txt +5 -5
- package/dist/agents/architect.txt +5 -5
- package/dist/agents/bmad-master.txt +18 -18
- package/dist/agents/bmad-orchestrator.txt +7 -7
- package/dist/agents/dev.txt +1 -1
- package/dist/agents/pm.txt +4 -4
- package/dist/agents/po.txt +3 -3
- package/dist/agents/sm.txt +4 -4
- package/dist/agents/ux-expert.txt +1 -1
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +1 -1
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +3 -3
- package/dist/expansion-packs/bmad-creator-tools/agents/bmad-the-creator.txt +10 -10
- package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +2 -2
- package/dist/teams/team-all.txt +19 -19
- package/dist/teams/team-fullstack.txt +14 -14
- package/dist/teams/team-ide-minimal.txt +15 -15
- package/dist/teams/team-no-ui.txt +14 -14
- package/docs/agentic-tools/roo-code-guide.md +1 -1
- package/docs/core-architecture.md +12 -12
- package/docs/user-guide.md +6 -6
- package/expansion-packs/bmad-2d-phaser-game-dev/{config.yml → config.yaml} +1 -1
- package/expansion-packs/bmad-creator-tools/{config.yml → config.yaml} +1 -1
- package/expansion-packs/bmad-creator-tools/tasks/generate-expansion-pack.md +9 -9
- package/expansion-packs/bmad-creator-tools/templates/agent-teams-tmpl.md +1 -1
- package/expansion-packs/bmad-creator-tools/templates/agent-tmpl.md +1 -1
- package/expansion-packs/bmad-infrastructure-devops/README.md +3 -3
- package/expansion-packs/bmad-infrastructure-devops/{config.yml → config.yaml} +1 -1
- package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.md +0 -0
- package/package.json +1 -1
- package/tools/builders/web-builder.js +19 -20
- package/tools/bump-all-versions.js +2 -2
- package/tools/bump-core-version.js +1 -1
- package/tools/bump-expansion-version.js +1 -1
- package/tools/installer/README.md +1 -1
- package/tools/installer/bin/bmad.js +2 -2
- package/tools/installer/lib/config-loader.js +13 -12
- package/tools/installer/lib/file-manager.js +5 -5
- package/tools/installer/lib/ide-setup.js +14 -13
- package/tools/installer/lib/installer.js +24 -26
- package/tools/installer/package.json +1 -1
- package/tools/lib/dependency-resolver.js +8 -12
- package/tools/lib/yaml-utils.js +29 -0
- package/tools/update-expansion-version.js +3 -3
- package/tools/yaml-format.js +1 -1
- /package/.github/{FUNDING.yml → FUNDING.yaml} +0 -0
- /package/.github/workflows/{release.yml → release.yaml} +0 -0
- /package/bmad-core/agent-teams/{team-all.yml → team-all.yaml} +0 -0
- /package/bmad-core/agent-teams/{team-fullstack.yml → team-fullstack.yaml} +0 -0
- /package/bmad-core/agent-teams/{team-ide-minimal.yml → team-ide-minimal.yaml} +0 -0
- /package/bmad-core/agent-teams/{team-no-ui.yml → team-no-ui.yaml} +0 -0
- /package/bmad-core/workflows/{brownfield-fullstack.yml → brownfield-fullstack.yaml} +0 -0
- /package/bmad-core/workflows/{brownfield-service.yml → brownfield-service.yaml} +0 -0
- /package/bmad-core/workflows/{brownfield-ui.yml → brownfield-ui.yaml} +0 -0
- /package/bmad-core/workflows/{greenfield-fullstack.yml → greenfield-fullstack.yaml} +0 -0
- /package/bmad-core/workflows/{greenfield-service.yml → greenfield-service.yaml} +0 -0
- /package/bmad-core/workflows/{greenfield-ui.yml → greenfield-ui.yaml} +0 -0
- /package/expansion-packs/bmad-2d-phaser-game-dev/agent-teams/{phaser-2d-nodejs-game-team.yml → phaser-2d-nodejs-game-team.yaml} +0 -0
- /package/expansion-packs/bmad-2d-phaser-game-dev/workflows/{game-dev-greenfield.yml → game-dev-greenfield.yaml} +0 -0
- /package/expansion-packs/bmad-2d-phaser-game-dev/workflows/{game-prototype.yml → game-prototype.yaml} +0 -0
- /package/tools/installer/config/{ide-agent-config.yml → ide-agent-config.yaml} +0 -0
- /package/tools/installer/config/{install.config.yml → install.config.yaml} +0 -0
|
@@ -2,6 +2,7 @@ const path = require("node:path");
|
|
|
2
2
|
const fileManager = require("./file-manager");
|
|
3
3
|
const configLoader = require("./config-loader");
|
|
4
4
|
const ideSetup = require("./ide-setup");
|
|
5
|
+
const { extractYamlFromAgent } = require("../../lib/yaml-utils");
|
|
5
6
|
|
|
6
7
|
// Dynamic imports for ES modules
|
|
7
8
|
let chalk, ora, inquirer;
|
|
@@ -19,13 +20,13 @@ class Installer {
|
|
|
19
20
|
async getCoreVersion() {
|
|
20
21
|
const yaml = require("js-yaml");
|
|
21
22
|
const fs = require("fs-extra");
|
|
22
|
-
const coreConfigPath = path.join(__dirname, "../../../bmad-core/core-config.
|
|
23
|
+
const coreConfigPath = path.join(__dirname, "../../../bmad-core/core-config.yaml");
|
|
23
24
|
try {
|
|
24
25
|
const coreConfigContent = await fs.readFile(coreConfigPath, "utf8");
|
|
25
26
|
const coreConfig = yaml.load(coreConfigContent);
|
|
26
27
|
return coreConfig.version || "unknown";
|
|
27
28
|
} catch (error) {
|
|
28
|
-
console.warn("Could not read version from core-config.
|
|
29
|
+
console.warn("Could not read version from core-config.yaml, using 'unknown'");
|
|
29
30
|
return "unknown";
|
|
30
31
|
}
|
|
31
32
|
}
|
|
@@ -185,7 +186,7 @@ class Installer {
|
|
|
185
186
|
|
|
186
187
|
// Check for V4 installation (has .bmad-core with manifest)
|
|
187
188
|
const bmadCorePath = path.join(installDir, ".bmad-core");
|
|
188
|
-
const manifestPath = path.join(bmadCorePath, "install-manifest.
|
|
189
|
+
const manifestPath = path.join(bmadCorePath, "install-manifest.yaml");
|
|
189
190
|
|
|
190
191
|
if (await fileManager.pathExists(manifestPath)) {
|
|
191
192
|
state.type = "v4_existing";
|
|
@@ -713,7 +714,7 @@ class Installer {
|
|
|
713
714
|
|
|
714
715
|
for (const file of filesToRestore) {
|
|
715
716
|
// Skip the manifest file itself
|
|
716
|
-
if (file.endsWith('install-manifest.
|
|
717
|
+
if (file.endsWith('install-manifest.yaml')) continue;
|
|
717
718
|
|
|
718
719
|
const relativePath = file.replace('.bmad-core/', '');
|
|
719
720
|
const destPath = path.join(installDir, file);
|
|
@@ -1009,7 +1010,7 @@ class Installer {
|
|
|
1009
1010
|
|
|
1010
1011
|
// Check if expansion pack already exists
|
|
1011
1012
|
let expansionDotFolder = path.join(installDir, `.${packId}`);
|
|
1012
|
-
const existingManifestPath = path.join(expansionDotFolder, 'install-manifest.
|
|
1013
|
+
const existingManifestPath = path.join(expansionDotFolder, 'install-manifest.yaml');
|
|
1013
1014
|
|
|
1014
1015
|
if (await fileManager.pathExists(existingManifestPath)) {
|
|
1015
1016
|
spinner.stop();
|
|
@@ -1151,12 +1152,12 @@ class Installer {
|
|
|
1151
1152
|
}
|
|
1152
1153
|
}
|
|
1153
1154
|
|
|
1154
|
-
// Copy config.
|
|
1155
|
-
const configPath = path.join(expansionPackDir, 'config.
|
|
1155
|
+
// Copy config.yaml
|
|
1156
|
+
const configPath = path.join(expansionPackDir, 'config.yaml');
|
|
1156
1157
|
if (await fileManager.pathExists(configPath)) {
|
|
1157
|
-
const configDestPath = path.join(expansionDotFolder, 'config.
|
|
1158
|
+
const configDestPath = path.join(expansionDotFolder, 'config.yaml');
|
|
1158
1159
|
if (await fileManager.copyFile(configPath, configDestPath)) {
|
|
1159
|
-
installedFiles.push(path.join(`.${packId}`, 'config.
|
|
1160
|
+
installedFiles.push(path.join(`.${packId}`, 'config.yaml'));
|
|
1160
1161
|
}
|
|
1161
1162
|
}
|
|
1162
1163
|
|
|
@@ -1222,10 +1223,10 @@ class Installer {
|
|
|
1222
1223
|
const agentContent = await fs.readFile(agentPath, 'utf8');
|
|
1223
1224
|
|
|
1224
1225
|
// Extract YAML frontmatter to check dependencies
|
|
1225
|
-
const
|
|
1226
|
-
if (
|
|
1226
|
+
const yamlContent = extractYamlFromAgent(agentContent);
|
|
1227
|
+
if (yamlContent) {
|
|
1227
1228
|
try {
|
|
1228
|
-
const agentConfig = yaml.parse(
|
|
1229
|
+
const agentConfig = yaml.parse(yamlContent);
|
|
1229
1230
|
const dependencies = agentConfig.dependencies || {};
|
|
1230
1231
|
|
|
1231
1232
|
// Check for core dependencies (those that don't exist in the expansion pack)
|
|
@@ -1268,7 +1269,7 @@ class Installer {
|
|
|
1268
1269
|
const fs = require('fs').promises;
|
|
1269
1270
|
|
|
1270
1271
|
// Find all team files in the expansion pack
|
|
1271
|
-
const teamFiles = glob.sync('agent-teams/*.
|
|
1272
|
+
const teamFiles = glob.sync('agent-teams/*.yaml', {
|
|
1272
1273
|
cwd: expansionDotFolder
|
|
1273
1274
|
});
|
|
1274
1275
|
|
|
@@ -1314,13 +1315,10 @@ class Installer {
|
|
|
1314
1315
|
|
|
1315
1316
|
// Now resolve this agent's dependencies too
|
|
1316
1317
|
const agentContent = await fs.readFile(coreAgentPath, 'utf8');
|
|
1317
|
-
const
|
|
1318
|
+
const yamlContent = extractYamlFromAgent(agentContent, true);
|
|
1318
1319
|
|
|
1319
|
-
if (
|
|
1320
|
+
if (yamlContent) {
|
|
1320
1321
|
try {
|
|
1321
|
-
// Clean up the YAML to handle command descriptions
|
|
1322
|
-
let yamlContent = yamlMatch[1];
|
|
1323
|
-
yamlContent = yamlContent.replace(/^(\s*-)(\s*"[^"]+")(\s*-\s*.*)$/gm, '$1$2');
|
|
1324
1322
|
|
|
1325
1323
|
const agentConfig = yaml.parse(yamlContent);
|
|
1326
1324
|
const dependencies = agentConfig.dependencies || {};
|
|
@@ -1330,7 +1328,7 @@ class Installer {
|
|
|
1330
1328
|
const deps = dependencies[depType] || [];
|
|
1331
1329
|
|
|
1332
1330
|
for (const dep of deps) {
|
|
1333
|
-
const depFileName = dep.endsWith('.md') || dep.endsWith('.
|
|
1331
|
+
const depFileName = dep.endsWith('.md') || dep.endsWith('.yaml') ? dep : `${dep}.md`;
|
|
1334
1332
|
const expansionDepPath = path.join(expansionDotFolder, depType, depFileName);
|
|
1335
1333
|
|
|
1336
1334
|
// Check if dependency exists in expansion pack
|
|
@@ -1360,7 +1358,7 @@ class Installer {
|
|
|
1360
1358
|
}
|
|
1361
1359
|
}
|
|
1362
1360
|
} else {
|
|
1363
|
-
console.warn(chalk.yellow(` Warning: Core agent ${agentId} not found for team ${path.basename(teamFile, '.
|
|
1361
|
+
console.warn(chalk.yellow(` Warning: Core agent ${agentId} not found for team ${path.basename(teamFile, '.yaml')}`));
|
|
1364
1362
|
}
|
|
1365
1363
|
}
|
|
1366
1364
|
}
|
|
@@ -1528,7 +1526,7 @@ class Installer {
|
|
|
1528
1526
|
|
|
1529
1527
|
if (stats) {
|
|
1530
1528
|
// Check if it has a manifest
|
|
1531
|
-
const manifestPath = path.join(folderPath, "install-manifest.
|
|
1529
|
+
const manifestPath = path.join(folderPath, "install-manifest.yaml");
|
|
1532
1530
|
if (await fileManager.pathExists(manifestPath)) {
|
|
1533
1531
|
const manifest = await fileManager.readExpansionPackManifest(installDir, folder.substring(1));
|
|
1534
1532
|
if (manifest) {
|
|
@@ -1539,8 +1537,8 @@ class Installer {
|
|
|
1539
1537
|
};
|
|
1540
1538
|
}
|
|
1541
1539
|
} else {
|
|
1542
|
-
// Check if it has a config.
|
|
1543
|
-
const configPath = path.join(folderPath, "config.
|
|
1540
|
+
// Check if it has a config.yaml (expansion pack without manifest)
|
|
1541
|
+
const configPath = path.join(folderPath, "config.yaml");
|
|
1544
1542
|
if (await fileManager.pathExists(configPath)) {
|
|
1545
1543
|
expansionPacks[folder.substring(1)] = {
|
|
1546
1544
|
path: folderPath,
|
|
@@ -1579,7 +1577,7 @@ class Installer {
|
|
|
1579
1577
|
|
|
1580
1578
|
for (const file of filesToRestore) {
|
|
1581
1579
|
// Skip the manifest file itself
|
|
1582
|
-
if (file.endsWith('install-manifest.
|
|
1580
|
+
if (file.endsWith('install-manifest.yaml')) continue;
|
|
1583
1581
|
|
|
1584
1582
|
const relativePath = file.replace(`.${packId}/`, '');
|
|
1585
1583
|
const sourcePath = path.join(pack.packPath, relativePath);
|
|
@@ -1645,7 +1643,7 @@ class Installer {
|
|
|
1645
1643
|
|
|
1646
1644
|
while (currentDir !== path.dirname(currentDir)) {
|
|
1647
1645
|
const bmadDir = path.join(currentDir, ".bmad-core");
|
|
1648
|
-
const manifestPath = path.join(bmadDir, "install-manifest.
|
|
1646
|
+
const manifestPath = path.join(bmadDir, "install-manifest.yaml");
|
|
1649
1647
|
|
|
1650
1648
|
if (await fileManager.pathExists(manifestPath)) {
|
|
1651
1649
|
return bmadDir;
|
|
@@ -1656,7 +1654,7 @@ class Installer {
|
|
|
1656
1654
|
|
|
1657
1655
|
// Also check if we're inside a .bmad-core directory
|
|
1658
1656
|
if (path.basename(process.cwd()) === ".bmad-core") {
|
|
1659
|
-
const manifestPath = path.join(process.cwd(), "install-manifest.
|
|
1657
|
+
const manifestPath = path.join(process.cwd(), "install-manifest.yaml");
|
|
1660
1658
|
if (await fileManager.pathExists(manifestPath)) {
|
|
1661
1659
|
return process.cwd();
|
|
1662
1660
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const fs = require('fs').promises;
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const yaml = require('js-yaml');
|
|
4
|
+
const { extractYamlFromAgent } = require('./yaml-utils');
|
|
4
5
|
|
|
5
6
|
class DependencyResolver {
|
|
6
7
|
constructor(rootDir) {
|
|
@@ -14,17 +15,12 @@ class DependencyResolver {
|
|
|
14
15
|
const agentPath = path.join(this.bmadCore, 'agents', `${agentId}.md`);
|
|
15
16
|
const agentContent = await fs.readFile(agentPath, 'utf8');
|
|
16
17
|
|
|
17
|
-
// Extract YAML from markdown content
|
|
18
|
-
const
|
|
19
|
-
if (!
|
|
18
|
+
// Extract YAML from markdown content with command cleaning
|
|
19
|
+
const yamlContent = extractYamlFromAgent(agentContent, true);
|
|
20
|
+
if (!yamlContent) {
|
|
20
21
|
throw new Error(`No YAML configuration found in agent ${agentId}`);
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
// Clean up the YAML to handle command descriptions after dashes
|
|
24
|
-
let yamlContent = yamlMatch[1];
|
|
25
|
-
// Fix commands section: convert "- command - description" to just "- command"
|
|
26
|
-
yamlContent = yamlContent.replace(/^(\s*-)(\s*"[^"]+")(\s*-\s*.*)$/gm, '$1$2');
|
|
27
|
-
|
|
28
24
|
const agentConfig = yaml.load(yamlContent);
|
|
29
25
|
|
|
30
26
|
const dependencies = {
|
|
@@ -53,7 +49,7 @@ class DependencyResolver {
|
|
|
53
49
|
}
|
|
54
50
|
|
|
55
51
|
async resolveTeamDependencies(teamId) {
|
|
56
|
-
const teamPath = path.join(this.bmadCore, 'agent-teams', `${teamId}.
|
|
52
|
+
const teamPath = path.join(this.bmadCore, 'agent-teams', `${teamId}.yaml`);
|
|
57
53
|
const teamContent = await fs.readFile(teamPath, 'utf8');
|
|
58
54
|
const teamConfig = yaml.load(teamContent);
|
|
59
55
|
|
|
@@ -120,7 +116,7 @@ class DependencyResolver {
|
|
|
120
116
|
}
|
|
121
117
|
|
|
122
118
|
try {
|
|
123
|
-
const extensions = ['.md', '.
|
|
119
|
+
const extensions = ['.md', '.yaml'];
|
|
124
120
|
let content = null;
|
|
125
121
|
let filePath = null;
|
|
126
122
|
|
|
@@ -183,8 +179,8 @@ class DependencyResolver {
|
|
|
183
179
|
try {
|
|
184
180
|
const files = await fs.readdir(path.join(this.bmadCore, 'agent-teams'));
|
|
185
181
|
return files
|
|
186
|
-
.filter(f => f.endsWith('.
|
|
187
|
-
.map(f => f.replace('.
|
|
182
|
+
.filter(f => f.endsWith('.yaml'))
|
|
183
|
+
.map(f => f.replace('.yaml', ''));
|
|
188
184
|
} catch (error) {
|
|
189
185
|
return [];
|
|
190
186
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for YAML extraction from agent files
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Extract YAML content from agent markdown files
|
|
7
|
+
* @param {string} agentContent - The full content of the agent file
|
|
8
|
+
* @param {boolean} cleanCommands - Whether to clean command descriptions (default: false)
|
|
9
|
+
* @returns {string|null} - The extracted YAML content or null if not found
|
|
10
|
+
*/
|
|
11
|
+
function extractYamlFromAgent(agentContent, cleanCommands = false) {
|
|
12
|
+
// Remove carriage returns and match YAML block
|
|
13
|
+
const yamlMatch = agentContent.replace(/\r/g, "").match(/```ya?ml\n([\s\S]*?)\n```/);
|
|
14
|
+
if (!yamlMatch) return null;
|
|
15
|
+
|
|
16
|
+
let yamlContent = yamlMatch[1].trim();
|
|
17
|
+
|
|
18
|
+
// Clean up command descriptions if requested
|
|
19
|
+
// Converts "- command - description" to just "- command"
|
|
20
|
+
if (cleanCommands) {
|
|
21
|
+
yamlContent = yamlContent.replace(/^(\s*-)(\s*"[^"]+")(\s*-\s*.*)$/gm, '$1$2');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return yamlContent;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
extractYamlFromAgent
|
|
29
|
+
};
|
|
@@ -22,8 +22,8 @@ if (!/^\d+\.\d+\.\d+$/.test(newVersion)) {
|
|
|
22
22
|
|
|
23
23
|
async function updateVersion() {
|
|
24
24
|
try {
|
|
25
|
-
// Update in config.
|
|
26
|
-
const configPath = path.join(__dirname, '..', 'expansion-packs', packId, 'config.
|
|
25
|
+
// Update in config.yaml
|
|
26
|
+
const configPath = path.join(__dirname, '..', 'expansion-packs', packId, 'config.yaml');
|
|
27
27
|
|
|
28
28
|
if (!fs.existsSync(configPath)) {
|
|
29
29
|
console.error(`Error: Expansion pack '${packId}' not found`);
|
|
@@ -39,7 +39,7 @@ async function updateVersion() {
|
|
|
39
39
|
const updatedYaml = yaml.dump(config, { indent: 2 });
|
|
40
40
|
fs.writeFileSync(configPath, updatedYaml);
|
|
41
41
|
|
|
42
|
-
console.log(`✓ Updated ${packId}/config.
|
|
42
|
+
console.log(`✓ Updated ${packId}/config.yaml: ${oldVersion} → ${newVersion}`);
|
|
43
43
|
console.log(`\n✓ Successfully updated ${packId} to version ${newVersion}`);
|
|
44
44
|
console.log('\nNext steps:');
|
|
45
45
|
console.log('1. Test the changes');
|
package/tools/yaml-format.js
CHANGED
|
@@ -197,7 +197,7 @@ async function main() {
|
|
|
197
197
|
let changed = false;
|
|
198
198
|
if (ext === '.md') {
|
|
199
199
|
changed = await processMarkdownFile(filePath);
|
|
200
|
-
} else if (ext === '.
|
|
200
|
+
} else if (ext === '.yaml' || ext === '.yml' || basename.includes('roomodes') || basename.includes('.yaml') || basename.includes('.yml')) {
|
|
201
201
|
// Handle YAML files and special cases like .roomodes
|
|
202
202
|
changed = await processYamlFile(filePath);
|
|
203
203
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|