bmad-method 4.23.0 → 4.24.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.
- package/.vscode/settings.json +11 -5
- package/CHANGELOG.md +22 -1
- package/README.md +2 -2
- package/bmad-core/agents/bmad-master.md +15 -2
- package/bmad-core/agents/bmad-orchestrator.md +14 -0
- 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} +5 -0
- package/bmad-core/data/bmad-kb.md +4 -4
- package/bmad-core/tasks/create-brownfield-story.md +355 -0
- package/bmad-core/tasks/create-next-story.md +29 -4
- package/bmad-core/tasks/create-workflow-plan.md +289 -0
- package/bmad-core/tasks/shard-doc.md +3 -3
- package/bmad-core/tasks/update-workflow-plan.md +248 -0
- package/bmad-core/templates/architecture-tmpl.md +1 -1
- package/bmad-core/templates/brownfield-prd-tmpl.md +52 -28
- package/bmad-core/templates/fullstack-architecture-tmpl.md +3 -3
- package/bmad-core/utils/plan-management.md +223 -0
- package/bmad-core/workflows/brownfield-fullstack.yaml +297 -0
- package/bmad-core/workflows/brownfield-service.yaml +187 -0
- package/bmad-core/workflows/{brownfield-ui.yml → brownfield-ui.yaml} +110 -36
- package/bmad-core/workflows/{greenfield-fullstack.yml → greenfield-fullstack.yaml} +110 -36
- package/bmad-core/workflows/{greenfield-service.yml → greenfield-service.yaml} +110 -36
- package/bmad-core/workflows/{greenfield-ui.yml → greenfield-ui.yaml} +110 -36
- package/common/tasks/create-doc.md +21 -1
- 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-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/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 +26 -38
- package/tools/installer/package.json +1 -1
- package/tools/lib/dependency-resolver.js +9 -13
- package/tools/lib/yaml-utils.js +29 -0
- package/tools/update-expansion-version.js +3 -3
- package/tools/yaml-format.js +1 -1
- package/bmad-core/workflows/brownfield-fullstack.yml +0 -112
- package/bmad-core/workflows/brownfield-service.yml +0 -113
- package/dist/agents/analyst.txt +0 -2709
- package/dist/agents/architect.txt +0 -3903
- package/dist/agents/bmad-master.txt +0 -9173
- package/dist/agents/bmad-orchestrator.txt +0 -1257
- package/dist/agents/dev.txt +0 -298
- package/dist/agents/pm.txt +0 -2205
- package/dist/agents/po.txt +0 -1511
- package/dist/agents/qa.txt +0 -262
- package/dist/agents/sm.txt +0 -701
- package/dist/agents/ux-expert.txt +0 -1081
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +0 -2358
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +0 -1584
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +0 -809
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +0 -6672
- package/dist/expansion-packs/bmad-creator-tools/agents/bmad-the-creator.txt +0 -1960
- package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +0 -2053
- package/dist/teams/team-all.txt +0 -10543
- package/dist/teams/team-fullstack.txt +0 -9731
- package/dist/teams/team-ide-minimal.txt +0 -3535
- package/dist/teams/team-no-ui.txt +0 -8619
- /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/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/{config.yml → config.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/expansion-packs/bmad-creator-tools/{config.yml → config.yaml} +0 -0
- /package/expansion-packs/bmad-infrastructure-devops/{config.yml → config.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
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
const fs = require('fs-extra');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const yaml = require('js-yaml');
|
|
4
|
+
const { extractYamlFromAgent } = require('../../lib/yaml-utils');
|
|
4
5
|
|
|
5
6
|
class ConfigLoader {
|
|
6
7
|
constructor() {
|
|
7
|
-
this.configPath = path.join(__dirname, '..', 'config', 'install.config.
|
|
8
|
+
this.configPath = path.join(__dirname, '..', 'config', 'install.config.yaml');
|
|
8
9
|
this.config = null;
|
|
9
10
|
}
|
|
10
11
|
|
|
@@ -41,9 +42,9 @@ class ConfigLoader {
|
|
|
41
42
|
const agentContent = await fs.readFile(agentPath, 'utf8');
|
|
42
43
|
|
|
43
44
|
// Extract YAML block from agent file
|
|
44
|
-
const
|
|
45
|
-
if (
|
|
46
|
-
const yamlContent = yaml.load(
|
|
45
|
+
const yamlContentText = extractYamlFromAgent(agentContent);
|
|
46
|
+
if (yamlContentText) {
|
|
47
|
+
const yamlContent = yaml.load(yamlContentText);
|
|
47
48
|
const agentConfig = yamlContent.agent || {};
|
|
48
49
|
|
|
49
50
|
agents.push({
|
|
@@ -79,10 +80,10 @@ class ConfigLoader {
|
|
|
79
80
|
for (const entry of entries) {
|
|
80
81
|
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
|
81
82
|
const packPath = path.join(expansionPacksDir, entry.name);
|
|
82
|
-
const configPath = path.join(packPath, 'config.
|
|
83
|
+
const configPath = path.join(packPath, 'config.yaml');
|
|
83
84
|
|
|
84
85
|
try {
|
|
85
|
-
// Read config.
|
|
86
|
+
// Read config.yaml
|
|
86
87
|
const configContent = await fs.readFile(configPath, 'utf8');
|
|
87
88
|
const config = yaml.load(configContent);
|
|
88
89
|
|
|
@@ -97,7 +98,7 @@ class ConfigLoader {
|
|
|
97
98
|
dependencies: config.dependencies?.agents || []
|
|
98
99
|
});
|
|
99
100
|
} catch (error) {
|
|
100
|
-
// Fallback if config.
|
|
101
|
+
// Fallback if config.yaml doesn't exist or can't be read
|
|
101
102
|
console.warn(`Failed to read config for expansion pack ${entry.name}: ${error.message}`);
|
|
102
103
|
|
|
103
104
|
// Try to derive info from directory name as fallback
|
|
@@ -180,7 +181,7 @@ class ConfigLoader {
|
|
|
180
181
|
const teams = [];
|
|
181
182
|
|
|
182
183
|
for (const entry of entries) {
|
|
183
|
-
if (entry.isFile() && entry.name.endsWith('.
|
|
184
|
+
if (entry.isFile() && entry.name.endsWith('.yaml')) {
|
|
184
185
|
const teamPath = path.join(teamsDir, entry.name);
|
|
185
186
|
|
|
186
187
|
try {
|
|
@@ -189,7 +190,7 @@ class ConfigLoader {
|
|
|
189
190
|
|
|
190
191
|
if (teamConfig.bundle) {
|
|
191
192
|
teams.push({
|
|
192
|
-
id: path.basename(entry.name, '.
|
|
193
|
+
id: path.basename(entry.name, '.yaml'),
|
|
193
194
|
name: teamConfig.bundle.name || entry.name,
|
|
194
195
|
description: teamConfig.bundle.description || 'Team configuration',
|
|
195
196
|
icon: teamConfig.bundle.icon || '📋'
|
|
@@ -209,7 +210,7 @@ class ConfigLoader {
|
|
|
209
210
|
}
|
|
210
211
|
|
|
211
212
|
getTeamPath(teamId) {
|
|
212
|
-
return path.join(this.getBmadCorePath(), 'agent-teams', `${teamId}.
|
|
213
|
+
return path.join(this.getBmadCorePath(), 'agent-teams', `${teamId}.yaml`);
|
|
213
214
|
}
|
|
214
215
|
|
|
215
216
|
async getTeamDependencies(teamId) {
|
|
@@ -224,7 +225,7 @@ class ConfigLoader {
|
|
|
224
225
|
const depPaths = [];
|
|
225
226
|
|
|
226
227
|
// Add team config file
|
|
227
|
-
depPaths.push(`.bmad-core/agent-teams/${teamId}.
|
|
228
|
+
depPaths.push(`.bmad-core/agent-teams/${teamId}.yaml`);
|
|
228
229
|
|
|
229
230
|
// Add all agents
|
|
230
231
|
for (const agent of teamDeps.agents) {
|
|
@@ -236,7 +237,7 @@ class ConfigLoader {
|
|
|
236
237
|
|
|
237
238
|
// Add all resolved resources
|
|
238
239
|
for (const resource of teamDeps.resources) {
|
|
239
|
-
const filePath = `.bmad-core/${resource.type}/${resource.id}.${resource.type === 'workflows' ? '
|
|
240
|
+
const filePath = `.bmad-core/${resource.type}/${resource.id}.${resource.type === 'workflows' ? 'yaml' : 'md'}`;
|
|
240
241
|
if (!depPaths.includes(filePath)) {
|
|
241
242
|
depPaths.push(filePath);
|
|
242
243
|
}
|
|
@@ -17,7 +17,7 @@ async function initializeModules() {
|
|
|
17
17
|
class FileManager {
|
|
18
18
|
constructor() {
|
|
19
19
|
this.manifestDir = ".bmad-core";
|
|
20
|
-
this.manifestFile = "install-manifest.
|
|
20
|
+
this.manifestFile = "install-manifest.yaml";
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
async copyFile(source, destination) {
|
|
@@ -83,15 +83,15 @@ class FileManager {
|
|
|
83
83
|
this.manifestFile
|
|
84
84
|
);
|
|
85
85
|
|
|
86
|
-
// Read version from core-config.
|
|
87
|
-
const coreConfigPath = path.join(__dirname, "../../../bmad-core/core-config.
|
|
86
|
+
// Read version from core-config.yaml
|
|
87
|
+
const coreConfigPath = path.join(__dirname, "../../../bmad-core/core-config.yaml");
|
|
88
88
|
let coreVersion = "unknown";
|
|
89
89
|
try {
|
|
90
90
|
const coreConfigContent = await fs.readFile(coreConfigPath, "utf8");
|
|
91
91
|
const coreConfig = yaml.load(coreConfigContent);
|
|
92
92
|
coreVersion = coreConfig.version || "unknown";
|
|
93
93
|
} catch (error) {
|
|
94
|
-
console.warn("Could not read version from core-config.
|
|
94
|
+
console.warn("Could not read version from core-config.yaml, using 'unknown'");
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
const manifest = {
|
|
@@ -178,7 +178,7 @@ class FileManager {
|
|
|
178
178
|
const filePath = path.join(installDir, file.path);
|
|
179
179
|
|
|
180
180
|
// Skip checking the manifest file itself - it will always be different due to timestamps
|
|
181
|
-
if (file.path.endsWith('install-manifest.
|
|
181
|
+
if (file.path.endsWith('install-manifest.yaml')) {
|
|
182
182
|
continue;
|
|
183
183
|
}
|
|
184
184
|
|
|
@@ -3,6 +3,7 @@ const fs = require("fs-extra");
|
|
|
3
3
|
const yaml = require("js-yaml");
|
|
4
4
|
const fileManager = require("./file-manager");
|
|
5
5
|
const configLoader = require("./config-loader");
|
|
6
|
+
const { extractYamlFromAgent } = require("../../lib/yaml-utils");
|
|
6
7
|
|
|
7
8
|
// Dynamic import for ES module
|
|
8
9
|
let chalk;
|
|
@@ -27,7 +28,7 @@ class IdeSetup {
|
|
|
27
28
|
if (this.ideAgentConfig) return this.ideAgentConfig;
|
|
28
29
|
|
|
29
30
|
try {
|
|
30
|
-
const configPath = path.join(__dirname, '..', 'config', 'ide-agent-config.
|
|
31
|
+
const configPath = path.join(__dirname, '..', 'config', 'ide-agent-config.yaml');
|
|
31
32
|
const configContent = await fs.readFile(configPath, 'utf8');
|
|
32
33
|
this.ideAgentConfig = yaml.load(configContent);
|
|
33
34
|
return this.ideAgentConfig;
|
|
@@ -98,11 +99,11 @@ class IdeSetup {
|
|
|
98
99
|
mdcContent += "## Agent Activation\n\n";
|
|
99
100
|
mdcContent +=
|
|
100
101
|
"CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n";
|
|
101
|
-
mdcContent += "```
|
|
102
|
+
mdcContent += "```yaml\n";
|
|
102
103
|
// Extract just the YAML content from the agent file
|
|
103
|
-
const
|
|
104
|
-
if (
|
|
105
|
-
mdcContent +=
|
|
104
|
+
const yamlContent = extractYamlFromAgent(agentContent);
|
|
105
|
+
if (yamlContent) {
|
|
106
|
+
mdcContent += yamlContent;
|
|
106
107
|
} else {
|
|
107
108
|
// If no YAML found, include the whole content minus the header
|
|
108
109
|
mdcContent += agentContent.replace(/^#.*$/m, "").trim();
|
|
@@ -180,11 +181,11 @@ class IdeSetup {
|
|
|
180
181
|
mdContent += "## Agent Activation\n\n";
|
|
181
182
|
mdContent +=
|
|
182
183
|
"CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n";
|
|
183
|
-
mdContent += "```
|
|
184
|
+
mdContent += "```yaml\n";
|
|
184
185
|
// Extract just the YAML content from the agent file
|
|
185
|
-
const
|
|
186
|
-
if (
|
|
187
|
-
mdContent +=
|
|
186
|
+
const yamlContent = extractYamlFromAgent(agentContent);
|
|
187
|
+
if (yamlContent) {
|
|
188
|
+
mdContent += yamlContent;
|
|
188
189
|
} else {
|
|
189
190
|
// If no YAML found, include the whole content minus the header
|
|
190
191
|
mdContent += agentContent.replace(/^#.*$/m, "").trim();
|
|
@@ -428,11 +429,11 @@ class IdeSetup {
|
|
|
428
429
|
mdContent += "## Role Definition\n\n";
|
|
429
430
|
mdContent +=
|
|
430
431
|
"When the user types `@" + agentId + "`, adopt this persona and follow these guidelines:\n\n";
|
|
431
|
-
mdContent += "```
|
|
432
|
+
mdContent += "```yaml\n";
|
|
432
433
|
// Extract just the YAML content from the agent file
|
|
433
|
-
const
|
|
434
|
-
if (
|
|
435
|
-
mdContent +=
|
|
434
|
+
const yamlContent = extractYamlFromAgent(agentContent);
|
|
435
|
+
if (yamlContent) {
|
|
436
|
+
mdContent += yamlContent;
|
|
436
437
|
} else {
|
|
437
438
|
// If no YAML found, include the whole content minus the header
|
|
438
439
|
mdContent += agentContent.replace(/^#.*$/m, "").trim();
|
|
@@ -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);
|
|
@@ -757,12 +758,7 @@ class Installer {
|
|
|
757
758
|
const ides = manifest.ides_setup || [];
|
|
758
759
|
if (ides.includes('cursor')) {
|
|
759
760
|
console.log(chalk.yellow.bold("\n⚠️ IMPORTANT: Cursor Custom Modes Update Required"));
|
|
760
|
-
console.log(chalk.yellow("Since agent files have been repaired, you need to
|
|
761
|
-
console.log(chalk.yellow("1. Open Cursor Settings (Cmd/Ctrl + ,)"));
|
|
762
|
-
console.log(chalk.yellow("2. Go to: Features > Cursor Tab > Custom Modes"));
|
|
763
|
-
console.log(chalk.yellow("3. Update each custom mode with the latest agent templates from:"));
|
|
764
|
-
console.log(chalk.yellow(` ${path.join(installDir, '.bmad-core', 'agents')}`));
|
|
765
|
-
console.log(chalk.yellow("4. Copy the full content of each agent file into the corresponding custom mode"));
|
|
761
|
+
console.log(chalk.yellow("Since agent files have been repaired, you need to update any custom agent modes configured in the Cursor custom agent GUI per the Cursor docs."));
|
|
766
762
|
}
|
|
767
763
|
|
|
768
764
|
} catch (error) {
|
|
@@ -861,12 +857,7 @@ class Installer {
|
|
|
861
857
|
// Warning for Cursor custom modes if agents were updated
|
|
862
858
|
if (options.isUpdate && ides.includes('cursor')) {
|
|
863
859
|
console.log(chalk.yellow.bold("\n⚠️ IMPORTANT: Cursor Custom Modes Update Required"));
|
|
864
|
-
console.log(chalk.yellow("Since agents have been updated, you need to
|
|
865
|
-
console.log(chalk.yellow("1. Open Cursor Settings (Cmd/Ctrl + ,)"));
|
|
866
|
-
console.log(chalk.yellow("2. Go to: Features > Cursor Tab > Custom Modes"));
|
|
867
|
-
console.log(chalk.yellow("3. Update each custom mode with the latest agent templates from:"));
|
|
868
|
-
console.log(chalk.yellow(` ${path.join(installDir, '.bmad-core', 'agents')}`));
|
|
869
|
-
console.log(chalk.yellow("4. Copy the full content of each agent file into the corresponding custom mode"));
|
|
860
|
+
console.log(chalk.yellow("Since agents have been updated, you need to update any custom agent modes configured in the Cursor custom agent GUI per the Cursor docs."));
|
|
870
861
|
}
|
|
871
862
|
}
|
|
872
863
|
|
|
@@ -1019,7 +1010,7 @@ class Installer {
|
|
|
1019
1010
|
|
|
1020
1011
|
// Check if expansion pack already exists
|
|
1021
1012
|
let expansionDotFolder = path.join(installDir, `.${packId}`);
|
|
1022
|
-
const existingManifestPath = path.join(expansionDotFolder, 'install-manifest.
|
|
1013
|
+
const existingManifestPath = path.join(expansionDotFolder, 'install-manifest.yaml');
|
|
1023
1014
|
|
|
1024
1015
|
if (await fileManager.pathExists(existingManifestPath)) {
|
|
1025
1016
|
spinner.stop();
|
|
@@ -1161,12 +1152,12 @@ class Installer {
|
|
|
1161
1152
|
}
|
|
1162
1153
|
}
|
|
1163
1154
|
|
|
1164
|
-
// Copy config.
|
|
1165
|
-
const configPath = path.join(expansionPackDir, 'config.
|
|
1155
|
+
// Copy config.yaml
|
|
1156
|
+
const configPath = path.join(expansionPackDir, 'config.yaml');
|
|
1166
1157
|
if (await fileManager.pathExists(configPath)) {
|
|
1167
|
-
const configDestPath = path.join(expansionDotFolder, 'config.
|
|
1158
|
+
const configDestPath = path.join(expansionDotFolder, 'config.yaml');
|
|
1168
1159
|
if (await fileManager.copyFile(configPath, configDestPath)) {
|
|
1169
|
-
installedFiles.push(path.join(`.${packId}`, 'config.
|
|
1160
|
+
installedFiles.push(path.join(`.${packId}`, 'config.yaml'));
|
|
1170
1161
|
}
|
|
1171
1162
|
}
|
|
1172
1163
|
|
|
@@ -1232,10 +1223,10 @@ class Installer {
|
|
|
1232
1223
|
const agentContent = await fs.readFile(agentPath, 'utf8');
|
|
1233
1224
|
|
|
1234
1225
|
// Extract YAML frontmatter to check dependencies
|
|
1235
|
-
const
|
|
1236
|
-
if (
|
|
1226
|
+
const yamlContent = extractYamlFromAgent(agentContent);
|
|
1227
|
+
if (yamlContent) {
|
|
1237
1228
|
try {
|
|
1238
|
-
const agentConfig = yaml.parse(
|
|
1229
|
+
const agentConfig = yaml.parse(yamlContent);
|
|
1239
1230
|
const dependencies = agentConfig.dependencies || {};
|
|
1240
1231
|
|
|
1241
1232
|
// Check for core dependencies (those that don't exist in the expansion pack)
|
|
@@ -1278,7 +1269,7 @@ class Installer {
|
|
|
1278
1269
|
const fs = require('fs').promises;
|
|
1279
1270
|
|
|
1280
1271
|
// Find all team files in the expansion pack
|
|
1281
|
-
const teamFiles = glob.sync('agent-teams/*.
|
|
1272
|
+
const teamFiles = glob.sync('agent-teams/*.yaml', {
|
|
1282
1273
|
cwd: expansionDotFolder
|
|
1283
1274
|
});
|
|
1284
1275
|
|
|
@@ -1324,13 +1315,10 @@ class Installer {
|
|
|
1324
1315
|
|
|
1325
1316
|
// Now resolve this agent's dependencies too
|
|
1326
1317
|
const agentContent = await fs.readFile(coreAgentPath, 'utf8');
|
|
1327
|
-
const
|
|
1318
|
+
const yamlContent = extractYamlFromAgent(agentContent, true);
|
|
1328
1319
|
|
|
1329
|
-
if (
|
|
1320
|
+
if (yamlContent) {
|
|
1330
1321
|
try {
|
|
1331
|
-
// Clean up the YAML to handle command descriptions
|
|
1332
|
-
let yamlContent = yamlMatch[1];
|
|
1333
|
-
yamlContent = yamlContent.replace(/^(\s*-)(\s*"[^"]+")(\s*-\s*.*)$/gm, '$1$2');
|
|
1334
1322
|
|
|
1335
1323
|
const agentConfig = yaml.parse(yamlContent);
|
|
1336
1324
|
const dependencies = agentConfig.dependencies || {};
|
|
@@ -1340,7 +1328,7 @@ class Installer {
|
|
|
1340
1328
|
const deps = dependencies[depType] || [];
|
|
1341
1329
|
|
|
1342
1330
|
for (const dep of deps) {
|
|
1343
|
-
const depFileName = dep.endsWith('.md') || dep.endsWith('.
|
|
1331
|
+
const depFileName = dep.endsWith('.md') || dep.endsWith('.yaml') ? dep : `${dep}.md`;
|
|
1344
1332
|
const expansionDepPath = path.join(expansionDotFolder, depType, depFileName);
|
|
1345
1333
|
|
|
1346
1334
|
// Check if dependency exists in expansion pack
|
|
@@ -1370,7 +1358,7 @@ class Installer {
|
|
|
1370
1358
|
}
|
|
1371
1359
|
}
|
|
1372
1360
|
} else {
|
|
1373
|
-
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')}`));
|
|
1374
1362
|
}
|
|
1375
1363
|
}
|
|
1376
1364
|
}
|
|
@@ -1538,7 +1526,7 @@ class Installer {
|
|
|
1538
1526
|
|
|
1539
1527
|
if (stats) {
|
|
1540
1528
|
// Check if it has a manifest
|
|
1541
|
-
const manifestPath = path.join(folderPath, "install-manifest.
|
|
1529
|
+
const manifestPath = path.join(folderPath, "install-manifest.yaml");
|
|
1542
1530
|
if (await fileManager.pathExists(manifestPath)) {
|
|
1543
1531
|
const manifest = await fileManager.readExpansionPackManifest(installDir, folder.substring(1));
|
|
1544
1532
|
if (manifest) {
|
|
@@ -1549,8 +1537,8 @@ class Installer {
|
|
|
1549
1537
|
};
|
|
1550
1538
|
}
|
|
1551
1539
|
} else {
|
|
1552
|
-
// Check if it has a config.
|
|
1553
|
-
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");
|
|
1554
1542
|
if (await fileManager.pathExists(configPath)) {
|
|
1555
1543
|
expansionPacks[folder.substring(1)] = {
|
|
1556
1544
|
path: folderPath,
|
|
@@ -1589,7 +1577,7 @@ class Installer {
|
|
|
1589
1577
|
|
|
1590
1578
|
for (const file of filesToRestore) {
|
|
1591
1579
|
// Skip the manifest file itself
|
|
1592
|
-
if (file.endsWith('install-manifest.
|
|
1580
|
+
if (file.endsWith('install-manifest.yaml')) continue;
|
|
1593
1581
|
|
|
1594
1582
|
const relativePath = file.replace(`.${packId}/`, '');
|
|
1595
1583
|
const sourcePath = path.join(pack.packPath, relativePath);
|
|
@@ -1655,7 +1643,7 @@ class Installer {
|
|
|
1655
1643
|
|
|
1656
1644
|
while (currentDir !== path.dirname(currentDir)) {
|
|
1657
1645
|
const bmadDir = path.join(currentDir, ".bmad-core");
|
|
1658
|
-
const manifestPath = path.join(bmadDir, "install-manifest.
|
|
1646
|
+
const manifestPath = path.join(bmadDir, "install-manifest.yaml");
|
|
1659
1647
|
|
|
1660
1648
|
if (await fileManager.pathExists(manifestPath)) {
|
|
1661
1649
|
return bmadDir;
|
|
@@ -1666,7 +1654,7 @@ class Installer {
|
|
|
1666
1654
|
|
|
1667
1655
|
// Also check if we're inside a .bmad-core directory
|
|
1668
1656
|
if (path.basename(process.cwd()) === ".bmad-core") {
|
|
1669
|
-
const manifestPath = path.join(process.cwd(), "install-manifest.
|
|
1657
|
+
const manifestPath = path.join(process.cwd(), "install-manifest.yaml");
|
|
1670
1658
|
if (await fileManager.pathExists(manifestPath)) {
|
|
1671
1659
|
return process.cwd();
|
|
1672
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,12 +179,12 @@ 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
|
}
|
|
191
187
|
}
|
|
192
188
|
}
|
|
193
189
|
|
|
194
|
-
module.exports = DependencyResolver;
|
|
190
|
+
module.exports = DependencyResolver;
|
|
@@ -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
|
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
workflow:
|
|
2
|
-
id: brownfield-fullstack
|
|
3
|
-
name: Brownfield Full-Stack Enhancement
|
|
4
|
-
description: >-
|
|
5
|
-
Agent workflow for enhancing existing full-stack applications with new features,
|
|
6
|
-
modernization, or significant changes. Handles existing system analysis and safe integration.
|
|
7
|
-
type: brownfield
|
|
8
|
-
project_types:
|
|
9
|
-
- feature-addition
|
|
10
|
-
- refactoring
|
|
11
|
-
- modernization
|
|
12
|
-
- integration-enhancement
|
|
13
|
-
|
|
14
|
-
sequence:
|
|
15
|
-
- step: project_analysis
|
|
16
|
-
agent: architect
|
|
17
|
-
action: analyze existing project and use task document-project
|
|
18
|
-
creates: multiple documents per the document-project template
|
|
19
|
-
notes: "Review existing documentation, codebase structure, and identify integration points. Document current system understanding before proceeding."
|
|
20
|
-
|
|
21
|
-
- agent: pm
|
|
22
|
-
creates: prd.md
|
|
23
|
-
uses: brownfield-prd-tmpl
|
|
24
|
-
requires: existing_project_analysis
|
|
25
|
-
notes: "Creates comprehensive PRD with existing system analysis and enhancement planning. SAVE OUTPUT: Copy final prd.md to your project's docs/ folder."
|
|
26
|
-
|
|
27
|
-
- agent: architect
|
|
28
|
-
creates: architecture.md
|
|
29
|
-
uses: brownfield-architecture-tmpl
|
|
30
|
-
requires: prd.md
|
|
31
|
-
notes: "Creates architecture with integration strategy and existing system constraints. SAVE OUTPUT: Copy final architecture.md to your project's docs/ folder."
|
|
32
|
-
|
|
33
|
-
- agent: po
|
|
34
|
-
validates: all_artifacts
|
|
35
|
-
uses: po-master-checklist
|
|
36
|
-
notes: "Validates all documents for integration safety and completeness. May require updates to any document."
|
|
37
|
-
|
|
38
|
-
- agent: various
|
|
39
|
-
updates: any_flagged_documents
|
|
40
|
-
condition: po_checklist_issues
|
|
41
|
-
notes: "If PO finds issues, return to relevant agent to fix and re-export updated documents to docs/ folder."
|
|
42
|
-
|
|
43
|
-
- workflow_end:
|
|
44
|
-
action: move_to_ide
|
|
45
|
-
notes: |
|
|
46
|
-
Planning phase complete! Now transition to IDE Development:
|
|
47
|
-
|
|
48
|
-
1. ENSURE DOCUMENTS ARE IN PROJECT:
|
|
49
|
-
- Copy final prd.md to project's docs/prd.md
|
|
50
|
-
- Copy final architecture.md to project's docs/architecture.md
|
|
51
|
-
- All documents must be in the project before proceeding
|
|
52
|
-
|
|
53
|
-
2. SHARD DOCUMENTS (in IDE):
|
|
54
|
-
- Option A: Use PO agent to shard: @po then ask to shard docs/prd.md
|
|
55
|
-
- Option B: Manual: Drag shard-doc task + docs/prd.md into chat
|
|
56
|
-
- This creates docs/prd/ and docs/architecture/ folders with sharded content
|
|
57
|
-
|
|
58
|
-
3. START DEVELOPMENT CYCLE:
|
|
59
|
-
a. SM Agent (New Chat): @sm → *create
|
|
60
|
-
- Creates next story from sharded docs
|
|
61
|
-
- Review and approve story (Draft → Approved)
|
|
62
|
-
|
|
63
|
-
b. Dev Agent (New Chat): @dev
|
|
64
|
-
- Implements approved story
|
|
65
|
-
- Updates File List with all changes
|
|
66
|
-
- Marks story as "Review" when complete
|
|
67
|
-
|
|
68
|
-
c. QA Agent (New Chat): @qa → review-story
|
|
69
|
-
- Senior dev review with refactoring ability
|
|
70
|
-
- Fixes small issues directly
|
|
71
|
-
- Leaves checklist for remaining items
|
|
72
|
-
- Updates story status (Review → Done or stays Review)
|
|
73
|
-
|
|
74
|
-
d. If QA left unchecked items:
|
|
75
|
-
- Dev Agent (New Chat): Address remaining items
|
|
76
|
-
- Return to QA for final approval
|
|
77
|
-
|
|
78
|
-
4. REPEAT: Continue cycle for all epic stories
|
|
79
|
-
|
|
80
|
-
Reference: data#bmad-kb:IDE Development Workflow
|
|
81
|
-
|
|
82
|
-
flow_diagram: |
|
|
83
|
-
```mermaid
|
|
84
|
-
graph TD
|
|
85
|
-
A[Start: Brownfield Enhancement] --> B[analyst: analyze existing project]
|
|
86
|
-
B --> C[pm: prd.md]
|
|
87
|
-
C --> D[architect: architecture.md]
|
|
88
|
-
D --> E[po: validate with po-master-checklist]
|
|
89
|
-
E --> F{PO finds issues?}
|
|
90
|
-
F -->|Yes| G[Return to relevant agent for fixes]
|
|
91
|
-
F -->|No| H[Move to IDE Environment]
|
|
92
|
-
G --> E
|
|
93
|
-
|
|
94
|
-
style H fill:#90EE90
|
|
95
|
-
style C fill:#FFE4B5
|
|
96
|
-
style D fill:#FFE4B5
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
decision_guidance:
|
|
100
|
-
when_to_use:
|
|
101
|
-
- Enhancement requires coordinated stories
|
|
102
|
-
- Architectural changes are needed
|
|
103
|
-
- Significant integration work required
|
|
104
|
-
- Risk assessment and mitigation planning necessary
|
|
105
|
-
- Multiple team members will work on related changes
|
|
106
|
-
|
|
107
|
-
handoff_prompts:
|
|
108
|
-
analyst_to_pm: "Existing project analysis complete. Create comprehensive PRD with integration strategy."
|
|
109
|
-
pm_to_architect: "PRD ready. Save it as docs/prd.md, then create the integration architecture."
|
|
110
|
-
architect_to_po: "Architecture complete. Save it as docs/architecture.md. Please validate all artifacts for integration safety."
|
|
111
|
-
po_issues: "PO found issues with [document]. Please return to [agent] to fix and re-save the updated document."
|
|
112
|
-
complete: "All planning artifacts validated and saved in docs/ folder. Move to IDE environment to begin development."
|