bmad-method 4.17.0 → 4.18.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.
- package/.claude/commands/bmad-master.md +0 -1
- package/CHANGELOG.md +8 -0
- package/{bmad-core → common}/tasks/create-doc.md +2 -2
- package/{expansion-packs/expansion-creator/common-tasks → common/tasks}/execute-checklist.md +2 -6
- package/common/utils/workflow-management.md +69 -0
- package/dist/agents/analyst.txt +2 -2
- package/dist/agents/architect.txt +4 -8
- package/dist/agents/bmad-master.txt +35 -270
- package/dist/agents/bmad-orchestrator.txt +33 -187
- package/dist/agents/dev.txt +2 -6
- package/dist/agents/pm.txt +4 -8
- package/dist/agents/po.txt +2 -6
- package/dist/agents/sm.txt +2 -6
- package/dist/agents/ux-expert.txt +4 -8
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +4 -8
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +2 -6
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +2 -6
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +35 -193
- package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +2 -2
- package/dist/expansion-packs/expansion-creator/agents/bmad-the-creator.txt +5 -5
- package/dist/teams/team-all.txt +35 -193
- package/dist/teams/team-fullstack.txt +35 -193
- package/dist/teams/team-ide-minimal.txt +35 -193
- package/dist/teams/team-no-ui.txt +35 -193
- package/docs/working-in-the-brownfield.md +2 -2
- package/expansion-packs/expansion-creator/tasks/generate-expansion-pack.md +5 -5
- package/package.json +1 -1
- package/tools/builders/web-builder.js +60 -19
- package/tools/installer/config/install.config.yml +0 -85
- package/tools/installer/lib/config-loader.js +57 -30
- package/tools/installer/lib/file-manager.js +1 -0
- package/tools/installer/lib/ide-setup.js +44 -26
- package/tools/installer/lib/installer.js +250 -8
- package/tools/installer/package.json +1 -1
- package/tools/lib/dependency-resolver.js +15 -0
- package/bmad-core/tasks/core-dump.md +0 -74
- package/bmad-core/tasks/execute-checklist.md +0 -97
- package/bmad-core/utils/file-resolution-context.md +0 -10
- package/bmad-core/utils/workflow-management.md +0 -223
- package/expansion-packs/bmad-infrastructure-devops/tasks/create-doc.md +0 -74
- package/expansion-packs/expansion-creator/common-tasks/create-doc.md +0 -74
- package/expansion-packs/expansion-creator/utils/template-format.md +0 -26
- package/expansion-packs/expansion-creator/utils/workflow-management.md +0 -223
- /package/{bmad-core → common}/utils/template-format.md +0 -0
- /package/{bmad-core/utils → tools/md-assets}/web-agent-startup-instructions.md +0 -0
|
@@ -65,8 +65,9 @@ class IdeSetup {
|
|
|
65
65
|
mdcContent += "alwaysApply: false\n";
|
|
66
66
|
mdcContent += "---\n\n";
|
|
67
67
|
mdcContent += `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
|
68
|
-
mdcContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${this.getAgentTitle(
|
|
69
|
-
agentId
|
|
68
|
+
mdcContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${await this.getAgentTitle(
|
|
69
|
+
agentId,
|
|
70
|
+
installDir
|
|
70
71
|
)} agent persona.\n\n`;
|
|
71
72
|
mdcContent += "## Agent Activation\n\n";
|
|
72
73
|
mdcContent +=
|
|
@@ -84,8 +85,9 @@ class IdeSetup {
|
|
|
84
85
|
mdcContent += "## File Reference\n\n";
|
|
85
86
|
mdcContent += `The complete agent definition is available in [.bmad-core/agents/${agentId}.md](mdc:.bmad-core/agents/${agentId}.md).\n\n`;
|
|
86
87
|
mdcContent += "## Usage\n\n";
|
|
87
|
-
mdcContent += `When the user types \`@${agentId}\`, activate this ${this.getAgentTitle(
|
|
88
|
-
agentId
|
|
88
|
+
mdcContent += `When the user types \`@${agentId}\`, activate this ${await this.getAgentTitle(
|
|
89
|
+
agentId,
|
|
90
|
+
installDir
|
|
89
91
|
)} persona and follow all instructions defined in the YML configuration above.\n`;
|
|
90
92
|
|
|
91
93
|
await fileManager.writeFile(mdcPath, mdcContent);
|
|
@@ -150,8 +152,9 @@ class IdeSetup {
|
|
|
150
152
|
|
|
151
153
|
// Create MD content (similar to Cursor but without frontmatter)
|
|
152
154
|
let mdContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
|
153
|
-
mdContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${this.getAgentTitle(
|
|
154
|
-
agentId
|
|
155
|
+
mdContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${await this.getAgentTitle(
|
|
156
|
+
agentId,
|
|
157
|
+
installDir
|
|
155
158
|
)} agent persona.\n\n`;
|
|
156
159
|
mdContent += "## Agent Activation\n\n";
|
|
157
160
|
mdContent +=
|
|
@@ -169,8 +172,9 @@ class IdeSetup {
|
|
|
169
172
|
mdContent += "## File Reference\n\n";
|
|
170
173
|
mdContent += `The complete agent definition is available in [.bmad-core/agents/${agentId}.md](.bmad-core/agents/${agentId}.md).\n\n`;
|
|
171
174
|
mdContent += "## Usage\n\n";
|
|
172
|
-
mdContent += `When the user types \`@${agentId}\`, activate this ${this.getAgentTitle(
|
|
173
|
-
agentId
|
|
175
|
+
mdContent += `When the user types \`@${agentId}\`, activate this ${await this.getAgentTitle(
|
|
176
|
+
agentId,
|
|
177
|
+
installDir
|
|
174
178
|
)} persona and follow all instructions defined in the YML configuration above.\n`;
|
|
175
179
|
|
|
176
180
|
await fileManager.writeFile(mdPath, mdContent);
|
|
@@ -195,20 +199,34 @@ class IdeSetup {
|
|
|
195
199
|
return agentFiles.map((file) => path.basename(file, ".md"));
|
|
196
200
|
}
|
|
197
201
|
|
|
198
|
-
getAgentTitle(agentId) {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
202
|
+
async getAgentTitle(agentId, installDir) {
|
|
203
|
+
// Try to read the actual agent file to get the title
|
|
204
|
+
let agentPath = path.join(installDir, ".bmad-core", "agents", `${agentId}.md`);
|
|
205
|
+
if (!(await fileManager.pathExists(agentPath))) {
|
|
206
|
+
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (await fileManager.pathExists(agentPath)) {
|
|
210
|
+
try {
|
|
211
|
+
const agentContent = await fileManager.readFile(agentPath);
|
|
212
|
+
const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
|
|
213
|
+
|
|
214
|
+
if (yamlMatch) {
|
|
215
|
+
const yaml = yamlMatch[1];
|
|
216
|
+
const titleMatch = yaml.match(/title:\s*(.+)/);
|
|
217
|
+
if (titleMatch) {
|
|
218
|
+
return titleMatch[1].trim();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.warn(`Failed to read agent title for ${agentId}: ${error.message}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Fallback to formatted agent ID
|
|
227
|
+
return agentId.split('-').map(word =>
|
|
228
|
+
word.charAt(0).toUpperCase() + word.slice(1)
|
|
229
|
+
).join(' ');
|
|
212
230
|
}
|
|
213
231
|
|
|
214
232
|
async setupRoo(installDir, selectedAgent) {
|
|
@@ -294,7 +312,7 @@ class IdeSetup {
|
|
|
294
312
|
const whenToUseMatch = yaml.match(/whenToUse:\s*"(.+)"/);
|
|
295
313
|
const roleDefinitionMatch = yaml.match(/roleDefinition:\s*"(.+)"/);
|
|
296
314
|
|
|
297
|
-
const title = titleMatch ? titleMatch[1].trim() : this.getAgentTitle(agentId);
|
|
315
|
+
const title = titleMatch ? titleMatch[1].trim() : await this.getAgentTitle(agentId, installDir);
|
|
298
316
|
const icon = iconMatch ? iconMatch[1].trim() : "🤖";
|
|
299
317
|
const whenToUse = whenToUseMatch ? whenToUseMatch[1].trim() : `Use for ${title} tasks`;
|
|
300
318
|
const roleDefinition = roleDefinitionMatch
|
|
@@ -381,8 +399,8 @@ class IdeSetup {
|
|
|
381
399
|
const mdPath = path.join(clineRulesDir, `${prefix}-${agentId}.md`);
|
|
382
400
|
|
|
383
401
|
// Create MD content for Cline (focused on project standards and role)
|
|
384
|
-
let mdContent = `# ${this.getAgentTitle(agentId)} Agent\n\n`;
|
|
385
|
-
mdContent += `This rule defines the ${this.getAgentTitle(agentId)} persona and project standards.\n\n`;
|
|
402
|
+
let mdContent = `# ${await this.getAgentTitle(agentId, installDir)} Agent\n\n`;
|
|
403
|
+
mdContent += `This rule defines the ${await this.getAgentTitle(agentId, installDir)} persona and project standards.\n\n`;
|
|
386
404
|
mdContent += "## Role Definition\n\n";
|
|
387
405
|
mdContent +=
|
|
388
406
|
"When the user types `@" + agentId + "`, adopt this persona and follow these guidelines:\n\n";
|
|
@@ -402,7 +420,7 @@ class IdeSetup {
|
|
|
402
420
|
mdContent += `- Update relevant project files when making changes\n`;
|
|
403
421
|
mdContent += `- Reference the complete agent definition in [.bmad-core/agents/${agentId}.md](.bmad-core/agents/${agentId}.md)\n\n`;
|
|
404
422
|
mdContent += "## Usage\n\n";
|
|
405
|
-
mdContent += `Type \`@${agentId}\` to activate this ${this.getAgentTitle(agentId)} persona.\n`;
|
|
423
|
+
mdContent += `Type \`@${agentId}\` to activate this ${await this.getAgentTitle(agentId, installDir)} persona.\n`;
|
|
406
424
|
|
|
407
425
|
await fileManager.writeFile(mdPath, mdContent);
|
|
408
426
|
console.log(chalk.green(`✓ Created rule: ${prefix}-${agentId}.md`));
|
|
@@ -225,6 +225,10 @@ class Installer {
|
|
|
225
225
|
const sourceDir = configLoader.getBmadCorePath();
|
|
226
226
|
const bmadCoreDestDir = path.join(installDir, ".bmad-core");
|
|
227
227
|
await fileManager.copyDirectory(sourceDir, bmadCoreDestDir);
|
|
228
|
+
|
|
229
|
+
// Copy common/ items to .bmad-core
|
|
230
|
+
spinner.text = "Copying common utilities...";
|
|
231
|
+
await this.copyCommonItems(installDir, ".bmad-core", spinner);
|
|
228
232
|
|
|
229
233
|
// Get list of all files for manifest
|
|
230
234
|
const glob = require("glob");
|
|
@@ -283,6 +287,11 @@ class Installer {
|
|
|
283
287
|
}
|
|
284
288
|
}
|
|
285
289
|
}
|
|
290
|
+
|
|
291
|
+
// Copy common/ items to .bmad-core
|
|
292
|
+
spinner.text = "Copying common utilities...";
|
|
293
|
+
const commonFiles = await this.copyCommonItems(installDir, ".bmad-core", spinner);
|
|
294
|
+
files.push(...commonFiles);
|
|
286
295
|
} else if (config.installType === "team") {
|
|
287
296
|
// Team installation
|
|
288
297
|
spinner.text = `Installing ${config.team} team...`;
|
|
@@ -313,6 +322,11 @@ class Installer {
|
|
|
313
322
|
}
|
|
314
323
|
}
|
|
315
324
|
}
|
|
325
|
+
|
|
326
|
+
// Copy common/ items to .bmad-core
|
|
327
|
+
spinner.text = "Copying common utilities...";
|
|
328
|
+
const commonFiles = await this.copyCommonItems(installDir, ".bmad-core", spinner);
|
|
329
|
+
files.push(...commonFiles);
|
|
316
330
|
} else if (config.installType === "expansion-only") {
|
|
317
331
|
// Expansion-only installation - create minimal .bmad-core structure
|
|
318
332
|
spinner.text = "Creating minimal .bmad-core structure for expansion packs...";
|
|
@@ -341,6 +355,10 @@ class Installer {
|
|
|
341
355
|
);
|
|
342
356
|
files.push(...copiedFiles.map(f => `.bmad-core/${f}`));
|
|
343
357
|
}
|
|
358
|
+
|
|
359
|
+
// Copy common/ items to .bmad-core
|
|
360
|
+
spinner.text = "Copying common utilities...";
|
|
361
|
+
await this.copyCommonItems(installDir, ".bmad-core", spinner);
|
|
344
362
|
}
|
|
345
363
|
|
|
346
364
|
// Install expansion packs if requested
|
|
@@ -607,8 +625,10 @@ class Installer {
|
|
|
607
625
|
console.log(chalk.green("✓ .bmad-core framework installed with all agents and workflows"));
|
|
608
626
|
|
|
609
627
|
if (config.expansionPacks && config.expansionPacks.length > 0) {
|
|
610
|
-
|
|
611
|
-
|
|
628
|
+
console.log(chalk.green(`✓ Expansion packs installed:`));
|
|
629
|
+
for (const packId of config.expansionPacks) {
|
|
630
|
+
console.log(chalk.green(` - ${packId} → .${packId}/`));
|
|
631
|
+
}
|
|
612
632
|
}
|
|
613
633
|
|
|
614
634
|
if (config.includeWebBundles && config.webBundlesDirectory) {
|
|
@@ -799,7 +819,11 @@ class Installer {
|
|
|
799
819
|
|
|
800
820
|
const expansionPackDir = path.dirname(pack.manifestPath);
|
|
801
821
|
|
|
802
|
-
//
|
|
822
|
+
// Create dedicated dot folder for this expansion pack
|
|
823
|
+
const expansionDotFolder = path.join(installDir, `.${packId}`);
|
|
824
|
+
await fileManager.ensureDirectory(expansionDotFolder);
|
|
825
|
+
|
|
826
|
+
// Define the folders to copy from expansion packs
|
|
803
827
|
const foldersToSync = [
|
|
804
828
|
'agents',
|
|
805
829
|
'agent-teams',
|
|
@@ -824,21 +848,35 @@ class Installer {
|
|
|
824
848
|
nodir: true
|
|
825
849
|
});
|
|
826
850
|
|
|
827
|
-
// Copy each file to the
|
|
851
|
+
// Copy each file to the expansion pack's dot folder
|
|
828
852
|
for (const file of files) {
|
|
829
853
|
const sourcePath = path.join(sourceFolder, file);
|
|
830
|
-
const destPath = path.join(
|
|
854
|
+
const destPath = path.join(expansionDotFolder, folder, file);
|
|
831
855
|
|
|
832
856
|
if (await fileManager.copyFile(sourcePath, destPath)) {
|
|
833
|
-
installedFiles.push(path.join(
|
|
857
|
+
installedFiles.push(path.join(`.${packId}`, folder, file));
|
|
834
858
|
}
|
|
835
859
|
}
|
|
836
860
|
}
|
|
837
861
|
}
|
|
838
862
|
|
|
839
|
-
//
|
|
863
|
+
// Copy manifest to the expansion pack's dot folder
|
|
864
|
+
const manifestDestPath = path.join(expansionDotFolder, 'manifest.yml');
|
|
865
|
+
if (await fileManager.copyFile(pack.manifestPath, manifestDestPath)) {
|
|
866
|
+
installedFiles.push(path.join(`.${packId}`, 'manifest.yml'));
|
|
867
|
+
}
|
|
840
868
|
|
|
841
|
-
|
|
869
|
+
// Copy common/ items to expansion pack folder
|
|
870
|
+
spinner.text = `Copying common utilities to ${packId}...`;
|
|
871
|
+
await this.copyCommonItems(installDir, `.${packId}`, spinner);
|
|
872
|
+
|
|
873
|
+
// Check and resolve core dependencies
|
|
874
|
+
await this.resolveExpansionPackCoreDependencies(installDir, expansionDotFolder, packId, spinner);
|
|
875
|
+
|
|
876
|
+
// Check and resolve core agents referenced by teams
|
|
877
|
+
await this.resolveExpansionPackCoreAgents(installDir, expansionDotFolder, packId, spinner);
|
|
878
|
+
|
|
879
|
+
console.log(chalk.green(`✓ Installed expansion pack: ${pack.name} to ${`.${packId}`}`));
|
|
842
880
|
} catch (error) {
|
|
843
881
|
console.error(chalk.red(`Failed to install expansion pack ${packId}: ${error.message}`));
|
|
844
882
|
}
|
|
@@ -847,6 +885,168 @@ class Installer {
|
|
|
847
885
|
return installedFiles;
|
|
848
886
|
}
|
|
849
887
|
|
|
888
|
+
async resolveExpansionPackCoreDependencies(installDir, expansionDotFolder, packId, spinner) {
|
|
889
|
+
const glob = require('glob');
|
|
890
|
+
const yaml = require('yaml');
|
|
891
|
+
const fs = require('fs').promises;
|
|
892
|
+
|
|
893
|
+
// Find all agent files in the expansion pack
|
|
894
|
+
const agentFiles = glob.sync('agents/*.md', {
|
|
895
|
+
cwd: expansionDotFolder
|
|
896
|
+
});
|
|
897
|
+
|
|
898
|
+
for (const agentFile of agentFiles) {
|
|
899
|
+
const agentPath = path.join(expansionDotFolder, agentFile);
|
|
900
|
+
const agentContent = await fs.readFile(agentPath, 'utf8');
|
|
901
|
+
|
|
902
|
+
// Extract YAML frontmatter to check dependencies
|
|
903
|
+
const yamlMatch = agentContent.match(/```yaml\n([\s\S]*?)```/);
|
|
904
|
+
if (yamlMatch) {
|
|
905
|
+
try {
|
|
906
|
+
const agentConfig = yaml.parse(yamlMatch[1]);
|
|
907
|
+
const dependencies = agentConfig.dependencies || {};
|
|
908
|
+
|
|
909
|
+
// Check for core dependencies (those that don't exist in the expansion pack)
|
|
910
|
+
for (const depType of ['tasks', 'templates', 'checklists', 'workflows', 'utils', 'data']) {
|
|
911
|
+
const deps = dependencies[depType] || [];
|
|
912
|
+
|
|
913
|
+
for (const dep of deps) {
|
|
914
|
+
const depFileName = dep.endsWith('.md') ? dep : `${dep}.md`;
|
|
915
|
+
const expansionDepPath = path.join(expansionDotFolder, depType, depFileName);
|
|
916
|
+
|
|
917
|
+
// Check if dependency exists in expansion pack
|
|
918
|
+
if (!(await fileManager.pathExists(expansionDepPath))) {
|
|
919
|
+
// Try to find it in core
|
|
920
|
+
const coreDepPath = path.join(configLoader.getBmadCorePath(), depType, depFileName);
|
|
921
|
+
|
|
922
|
+
if (await fileManager.pathExists(coreDepPath)) {
|
|
923
|
+
spinner.text = `Copying core dependency ${dep} for ${packId}...`;
|
|
924
|
+
|
|
925
|
+
// Copy from core to expansion pack dot folder
|
|
926
|
+
const destPath = path.join(expansionDotFolder, depType, depFileName);
|
|
927
|
+
await fileManager.copyFile(coreDepPath, destPath);
|
|
928
|
+
|
|
929
|
+
console.log(chalk.dim(` Added core dependency: ${depType}/${depFileName}`));
|
|
930
|
+
} else {
|
|
931
|
+
console.warn(chalk.yellow(` Warning: Dependency ${depType}/${dep} not found in core or expansion pack`));
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
} catch (error) {
|
|
937
|
+
console.warn(chalk.yellow(` Warning: Could not parse agent dependencies: ${error.message}`));
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
async resolveExpansionPackCoreAgents(installDir, expansionDotFolder, packId, spinner) {
|
|
944
|
+
const glob = require('glob');
|
|
945
|
+
const yaml = require('yaml');
|
|
946
|
+
const fs = require('fs').promises;
|
|
947
|
+
|
|
948
|
+
// Find all team files in the expansion pack
|
|
949
|
+
const teamFiles = glob.sync('agent-teams/*.yml', {
|
|
950
|
+
cwd: expansionDotFolder
|
|
951
|
+
});
|
|
952
|
+
|
|
953
|
+
// Also get existing agents in the expansion pack
|
|
954
|
+
const existingAgents = new Set();
|
|
955
|
+
const agentFiles = glob.sync('agents/*.md', {
|
|
956
|
+
cwd: expansionDotFolder
|
|
957
|
+
});
|
|
958
|
+
for (const agentFile of agentFiles) {
|
|
959
|
+
const agentName = path.basename(agentFile, '.md');
|
|
960
|
+
existingAgents.add(agentName);
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// Process each team file
|
|
964
|
+
for (const teamFile of teamFiles) {
|
|
965
|
+
const teamPath = path.join(expansionDotFolder, teamFile);
|
|
966
|
+
const teamContent = await fs.readFile(teamPath, 'utf8');
|
|
967
|
+
|
|
968
|
+
try {
|
|
969
|
+
const teamConfig = yaml.parse(teamContent);
|
|
970
|
+
const agents = teamConfig.agents || [];
|
|
971
|
+
|
|
972
|
+
// Add bmad-orchestrator if not present (required for all teams)
|
|
973
|
+
if (!agents.includes('bmad-orchestrator')) {
|
|
974
|
+
agents.unshift('bmad-orchestrator');
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// Check each agent in the team
|
|
978
|
+
for (const agentId of agents) {
|
|
979
|
+
if (!existingAgents.has(agentId)) {
|
|
980
|
+
// Agent not in expansion pack, try to get from core
|
|
981
|
+
const coreAgentPath = path.join(configLoader.getBmadCorePath(), 'agents', `${agentId}.md`);
|
|
982
|
+
|
|
983
|
+
if (await fileManager.pathExists(coreAgentPath)) {
|
|
984
|
+
spinner.text = `Copying core agent ${agentId} for ${packId}...`;
|
|
985
|
+
|
|
986
|
+
// Copy agent file
|
|
987
|
+
const destPath = path.join(expansionDotFolder, 'agents', `${agentId}.md`);
|
|
988
|
+
await fileManager.copyFile(coreAgentPath, destPath);
|
|
989
|
+
existingAgents.add(agentId);
|
|
990
|
+
|
|
991
|
+
console.log(chalk.dim(` Added core agent: ${agentId}`));
|
|
992
|
+
|
|
993
|
+
// Now resolve this agent's dependencies too
|
|
994
|
+
const agentContent = await fs.readFile(coreAgentPath, 'utf8');
|
|
995
|
+
const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
|
|
996
|
+
|
|
997
|
+
if (yamlMatch) {
|
|
998
|
+
try {
|
|
999
|
+
// Clean up the YAML to handle command descriptions
|
|
1000
|
+
let yamlContent = yamlMatch[1];
|
|
1001
|
+
yamlContent = yamlContent.replace(/^(\s*-)(\s*"[^"]+")(\s*-\s*.*)$/gm, '$1$2');
|
|
1002
|
+
|
|
1003
|
+
const agentConfig = yaml.parse(yamlContent);
|
|
1004
|
+
const dependencies = agentConfig.dependencies || {};
|
|
1005
|
+
|
|
1006
|
+
// Copy all dependencies for this agent
|
|
1007
|
+
for (const depType of ['tasks', 'templates', 'checklists', 'workflows', 'utils', 'data']) {
|
|
1008
|
+
const deps = dependencies[depType] || [];
|
|
1009
|
+
|
|
1010
|
+
for (const dep of deps) {
|
|
1011
|
+
const depFileName = dep.endsWith('.md') || dep.endsWith('.yml') ? dep : `${dep}.md`;
|
|
1012
|
+
const expansionDepPath = path.join(expansionDotFolder, depType, depFileName);
|
|
1013
|
+
|
|
1014
|
+
// Check if dependency exists in expansion pack
|
|
1015
|
+
if (!(await fileManager.pathExists(expansionDepPath))) {
|
|
1016
|
+
// Try to find it in core
|
|
1017
|
+
const coreDepPath = path.join(configLoader.getBmadCorePath(), depType, depFileName);
|
|
1018
|
+
|
|
1019
|
+
if (await fileManager.pathExists(coreDepPath)) {
|
|
1020
|
+
const destDepPath = path.join(expansionDotFolder, depType, depFileName);
|
|
1021
|
+
await fileManager.copyFile(coreDepPath, destDepPath);
|
|
1022
|
+
console.log(chalk.dim(` Added agent dependency: ${depType}/${depFileName}`));
|
|
1023
|
+
} else {
|
|
1024
|
+
// Try common folder
|
|
1025
|
+
const commonDepPath = path.join(this.rootDir, 'common', depType, depFileName);
|
|
1026
|
+
if (await fileManager.pathExists(commonDepPath)) {
|
|
1027
|
+
const destDepPath = path.join(expansionDotFolder, depType, depFileName);
|
|
1028
|
+
await fileManager.copyFile(commonDepPath, destDepPath);
|
|
1029
|
+
console.log(chalk.dim(` Added agent dependency from common: ${depType}/${depFileName}`));
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
} catch (error) {
|
|
1036
|
+
console.warn(chalk.yellow(` Warning: Could not parse agent ${agentId} dependencies: ${error.message}`));
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
} else {
|
|
1040
|
+
console.warn(chalk.yellow(` Warning: Core agent ${agentId} not found for team ${path.basename(teamFile, '.yml')}`));
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
} catch (error) {
|
|
1045
|
+
console.warn(chalk.yellow(` Warning: Could not parse team file ${teamFile}: ${error.message}`));
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
|
|
850
1050
|
getWebBundleInfo(config) {
|
|
851
1051
|
const webBundleType = config.webBundleType || 'all';
|
|
852
1052
|
|
|
@@ -944,6 +1144,48 @@ class Installer {
|
|
|
944
1144
|
}
|
|
945
1145
|
}
|
|
946
1146
|
|
|
1147
|
+
async copyCommonItems(installDir, targetSubdir, spinner) {
|
|
1148
|
+
const glob = require('glob');
|
|
1149
|
+
const fs = require('fs').promises;
|
|
1150
|
+
const sourceBase = path.dirname(path.dirname(path.dirname(path.dirname(__filename)))); // Go up to project root
|
|
1151
|
+
const commonPath = path.join(sourceBase, 'common');
|
|
1152
|
+
const targetPath = path.join(installDir, targetSubdir);
|
|
1153
|
+
const copiedFiles = [];
|
|
1154
|
+
|
|
1155
|
+
// Check if common/ exists
|
|
1156
|
+
if (!(await fileManager.pathExists(commonPath))) {
|
|
1157
|
+
console.warn(chalk.yellow('Warning: common/ folder not found'));
|
|
1158
|
+
return copiedFiles;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
// Copy all items from common/ to target
|
|
1162
|
+
const commonItems = glob.sync('**/*', {
|
|
1163
|
+
cwd: commonPath,
|
|
1164
|
+
nodir: true
|
|
1165
|
+
});
|
|
1166
|
+
|
|
1167
|
+
for (const item of commonItems) {
|
|
1168
|
+
const sourcePath = path.join(commonPath, item);
|
|
1169
|
+
const destPath = path.join(targetPath, item);
|
|
1170
|
+
|
|
1171
|
+
// Read the file content
|
|
1172
|
+
const content = await fs.readFile(sourcePath, 'utf8');
|
|
1173
|
+
|
|
1174
|
+
// Replace {root} with the target subdirectory
|
|
1175
|
+
const updatedContent = content.replace(/\{root\}/g, targetSubdir);
|
|
1176
|
+
|
|
1177
|
+
// Ensure directory exists
|
|
1178
|
+
await fileManager.ensureDirectory(path.dirname(destPath));
|
|
1179
|
+
|
|
1180
|
+
// Write the updated content
|
|
1181
|
+
await fs.writeFile(destPath, updatedContent, 'utf8');
|
|
1182
|
+
copiedFiles.push(path.join(targetSubdir, item));
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
console.log(chalk.dim(` Added ${commonItems.length} common utilities`));
|
|
1186
|
+
return copiedFiles;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
947
1189
|
async findInstallation() {
|
|
948
1190
|
// Look for .bmad-core in current directory or parent directories
|
|
949
1191
|
let currentDir = process.cwd();
|
|
@@ -6,6 +6,7 @@ class DependencyResolver {
|
|
|
6
6
|
constructor(rootDir) {
|
|
7
7
|
this.rootDir = rootDir;
|
|
8
8
|
this.bmadCore = path.join(rootDir, 'bmad-core');
|
|
9
|
+
this.common = path.join(rootDir, 'common');
|
|
9
10
|
this.cache = new Map();
|
|
10
11
|
}
|
|
11
12
|
|
|
@@ -123,6 +124,7 @@ class DependencyResolver {
|
|
|
123
124
|
let content = null;
|
|
124
125
|
let filePath = null;
|
|
125
126
|
|
|
127
|
+
// First try bmad-core
|
|
126
128
|
for (const ext of extensions) {
|
|
127
129
|
try {
|
|
128
130
|
filePath = path.join(this.bmadCore, type, `${id}${ext}`);
|
|
@@ -132,6 +134,19 @@ class DependencyResolver {
|
|
|
132
134
|
// Try next extension
|
|
133
135
|
}
|
|
134
136
|
}
|
|
137
|
+
|
|
138
|
+
// If not found in bmad-core, try common folder
|
|
139
|
+
if (!content) {
|
|
140
|
+
for (const ext of extensions) {
|
|
141
|
+
try {
|
|
142
|
+
filePath = path.join(this.common, type, `${id}${ext}`);
|
|
143
|
+
content = await fs.readFile(filePath, 'utf8');
|
|
144
|
+
break;
|
|
145
|
+
} catch (e) {
|
|
146
|
+
// Try next extension
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
135
150
|
|
|
136
151
|
if (!content) {
|
|
137
152
|
console.warn(`Resource not found: ${type}/${id}`);
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# Core Dump Task
|
|
2
|
-
|
|
3
|
-
## Purpose
|
|
4
|
-
|
|
5
|
-
To create a concise memory recording file (`.ai/core-dump-n.md`) that captures the essential context of the current agent session, enabling seamless continuation of work in future agent sessions. This task ensures persistent context across agent conversations while maintaining minimal token usage for efficient context loading.
|
|
6
|
-
|
|
7
|
-
## Inputs for this Task
|
|
8
|
-
|
|
9
|
-
- Current session conversation history and accomplishments
|
|
10
|
-
- Files created, modified, or deleted during the session
|
|
11
|
-
- Key decisions made and procedures followed
|
|
12
|
-
- Current project state and next logical steps
|
|
13
|
-
- User requests and agent responses that shaped the session
|
|
14
|
-
|
|
15
|
-
## Task Execution Instructions
|
|
16
|
-
|
|
17
|
-
### 0. Check Existing Core Dump
|
|
18
|
-
|
|
19
|
-
Before proceeding, check if `.ai/core-dump.md` already exists:
|
|
20
|
-
|
|
21
|
-
- If file exists, ask user: "Core dump file exists. Should I: 1. Overwrite, 2. Update, 3. Append or 4. Create new?"
|
|
22
|
-
- **Overwrite**: Replace entire file with new content
|
|
23
|
-
- **Update**: Merge new session info with existing content, updating relevant sections
|
|
24
|
-
- **Append**: Add new session as a separate entry while preserving existing content
|
|
25
|
-
- **Create New**: Create a new file, appending the next possible -# to the file, such as core-dump-3.md if 1 and 2 already exist.
|
|
26
|
-
- If file doesn't exist, proceed with creation of `core-dump-1.md`
|
|
27
|
-
|
|
28
|
-
### 1. Analyze Session Context
|
|
29
|
-
|
|
30
|
-
- Review the entire conversation to identify key accomplishments
|
|
31
|
-
- Note any specific tasks, procedures, or workflows that were executed
|
|
32
|
-
- Identify important decisions made or problems solved
|
|
33
|
-
- Capture the user's working style and preferences observed during the session
|
|
34
|
-
|
|
35
|
-
### 2. Document What Was Accomplished
|
|
36
|
-
|
|
37
|
-
- **Primary Actions**: List the main tasks completed concisely
|
|
38
|
-
- **Story Progress**: For story work, use format "Tasks Complete: 1-6, 8. Next Task Pending: 7, 9"
|
|
39
|
-
- **Problem Solving**: Document any challenges encountered and how they were resolved
|
|
40
|
-
- **User Communications**: Summarize key user requests, preferences, and discussion points
|
|
41
|
-
|
|
42
|
-
### 3. Record File System Changes (Concise Format)
|
|
43
|
-
|
|
44
|
-
- **Files Created**: `filename.ext` (brief purpose/size)
|
|
45
|
-
- **Files Modified**: `filename.ext` (what changed)
|
|
46
|
-
- **Files Deleted**: `filename.ext` (why removed)
|
|
47
|
-
- Focus on essential details, avoid verbose descriptions
|
|
48
|
-
|
|
49
|
-
### 4. Capture Current Project State
|
|
50
|
-
|
|
51
|
-
- **Project Progress**: Where the project stands after this session
|
|
52
|
-
- **Current Issues**: Any blockers or problems that need resolution
|
|
53
|
-
- **Next Logical Steps**: What would be the natural next actions to take
|
|
54
|
-
|
|
55
|
-
### 5. Create/Update Core Dump File
|
|
56
|
-
|
|
57
|
-
Based on user's choice from step 0, handle the file accordingly:
|
|
58
|
-
|
|
59
|
-
### 6. Optimize for Minimal Context
|
|
60
|
-
|
|
61
|
-
- Keep descriptions concise but informative
|
|
62
|
-
- Use abbreviated formats where possible (file sizes, task numbers)
|
|
63
|
-
- Focus on actionable information rather than detailed explanations
|
|
64
|
-
- Avoid redundant information that can be found in project documentation
|
|
65
|
-
- Prioritize information that would be lost without this recording
|
|
66
|
-
- Ensure the file can be quickly scanned and understood
|
|
67
|
-
|
|
68
|
-
### 7. Validate Completeness
|
|
69
|
-
|
|
70
|
-
- Verify all significant session activities are captured
|
|
71
|
-
- Ensure a future agent could understand the current state
|
|
72
|
-
- Check that file changes are accurately recorded
|
|
73
|
-
- Confirm next steps are clear and actionable
|
|
74
|
-
- Verify user communication style and preferences are noted
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
# Checklist Validation Task
|
|
2
|
-
|
|
3
|
-
This task provides instructions for validating documentation against checklists. The agent MUST follow these instructions to ensure thorough and systematic validation of documents.
|
|
4
|
-
|
|
5
|
-
## Context
|
|
6
|
-
|
|
7
|
-
The BMAD Method uses various checklists to ensure quality and completeness of different artifacts. Each checklist contains embedded prompts and instructions to guide the LLM through thorough validation and advanced elicitation. The checklists automatically identify their required artifacts and guide the validation process.
|
|
8
|
-
|
|
9
|
-
## Available Checklists
|
|
10
|
-
|
|
11
|
-
If the user asks or does not specify a specific checklist, list the checklists available to the agent persona. If the task is being run not with a specific agent, tell the user to check the bmad-core/checklists folder to select the appropriate one to run.
|
|
12
|
-
|
|
13
|
-
## Instructions
|
|
14
|
-
|
|
15
|
-
1. **Initial Assessment**
|
|
16
|
-
|
|
17
|
-
- If user or the task being run provides a checklist name:
|
|
18
|
-
- Try fuzzy matching (e.g. "architecture checklist" -> "architect-checklist")
|
|
19
|
-
- If multiple matches found, ask user to clarify
|
|
20
|
-
- Load the appropriate checklist from bmad-core/checklists/
|
|
21
|
-
- If no checklist specified:
|
|
22
|
-
- Ask the user which checklist they want to use
|
|
23
|
-
- Present the available options from the files in the checklists folder
|
|
24
|
-
- Confirm if they want to work through the checklist:
|
|
25
|
-
- Section by section (interactive mode - very time consuming)
|
|
26
|
-
- All at once (YOLO mode - recommended for checklists, there will be a summary of sections at the end to discuss)
|
|
27
|
-
|
|
28
|
-
2. **Document and Artifact Gathering**
|
|
29
|
-
|
|
30
|
-
- Each checklist will specify its required documents/artifacts at the beginning
|
|
31
|
-
- Follow the checklist's specific instructions for what to gather, generally a file can be resolved in the docs folder, if not or unsure, halt and ask or confirm with the user.
|
|
32
|
-
|
|
33
|
-
3. **Checklist Processing**
|
|
34
|
-
|
|
35
|
-
If in interactive mode:
|
|
36
|
-
|
|
37
|
-
- Work through each section of the checklist one at a time
|
|
38
|
-
- For each section:
|
|
39
|
-
- Review all items in the section following instructions for that section embedded in the checklist
|
|
40
|
-
- Check each item against the relevant documentation or artifacts as appropriate
|
|
41
|
-
- Present summary of findings for that section, highlighting warnings, errors and non applicable items (rationale for non-applicability).
|
|
42
|
-
- Get user confirmation before proceeding to next section or if any thing major do we need to halt and take corrective action
|
|
43
|
-
|
|
44
|
-
If in YOLO mode:
|
|
45
|
-
|
|
46
|
-
- Process all sections at once
|
|
47
|
-
- Create a comprehensive report of all findings
|
|
48
|
-
- Present the complete analysis to the user
|
|
49
|
-
|
|
50
|
-
4. **Validation Approach**
|
|
51
|
-
|
|
52
|
-
For each checklist item:
|
|
53
|
-
|
|
54
|
-
- Read and understand the requirement
|
|
55
|
-
- Look for evidence in the documentation that satisfies the requirement
|
|
56
|
-
- Consider both explicit mentions and implicit coverage
|
|
57
|
-
- Aside from this, follow all checklist llm instructions
|
|
58
|
-
- Mark items as:
|
|
59
|
-
- ✅ PASS: Requirement clearly met
|
|
60
|
-
- ❌ FAIL: Requirement not met or insufficient coverage
|
|
61
|
-
- ⚠️ PARTIAL: Some aspects covered but needs improvement
|
|
62
|
-
- N/A: Not applicable to this case
|
|
63
|
-
|
|
64
|
-
5. **Section Analysis**
|
|
65
|
-
|
|
66
|
-
For each section:
|
|
67
|
-
|
|
68
|
-
- think step by step to calculate pass rate
|
|
69
|
-
- Identify common themes in failed items
|
|
70
|
-
- Provide specific recommendations for improvement
|
|
71
|
-
- In interactive mode, discuss findings with user
|
|
72
|
-
- Document any user decisions or explanations
|
|
73
|
-
|
|
74
|
-
6. **Final Report**
|
|
75
|
-
|
|
76
|
-
Prepare a summary that includes:
|
|
77
|
-
|
|
78
|
-
- Overall checklist completion status
|
|
79
|
-
- Pass rates by section
|
|
80
|
-
- List of failed items with context
|
|
81
|
-
- Specific recommendations for improvement
|
|
82
|
-
- Any sections or items marked as N/A with justification
|
|
83
|
-
|
|
84
|
-
## Checklist Execution Methodology
|
|
85
|
-
|
|
86
|
-
Each checklist now contains embedded LLM prompts and instructions that will:
|
|
87
|
-
|
|
88
|
-
1. **Guide thorough thinking** - Prompts ensure deep analysis of each section
|
|
89
|
-
2. **Request specific artifacts** - Clear instructions on what documents/access is needed
|
|
90
|
-
3. **Provide contextual guidance** - Section-specific prompts for better validation
|
|
91
|
-
4. **Generate comprehensive reports** - Final summary with detailed findings
|
|
92
|
-
|
|
93
|
-
The LLM will:
|
|
94
|
-
|
|
95
|
-
- Execute the complete checklist validation
|
|
96
|
-
- Present a final report with pass/fail rates and key findings
|
|
97
|
-
- Offer to provide detailed analysis of any section, especially those with warnings or failures
|