Simplify agent configurations and fix team bundle builds

Major refactoring to streamline agent configuration structure and improve build reliability:

Agent Configuration Simplification:
- Remove environment sections from all agent YAML files
- Add single 'persona' property to agent configs pointing to persona file
- All agents now use consistent, simplified structure without web/ide environment splits
- Fix dev agent to be available for web environment (was causing team-dev bundle build failure)

Build System Updates:
- Update dependency-resolver.js to use new persona property instead of environments.web.persona_file
- Update bundle-optimizer.js to load personas using agent's persona property
- Remove environment availability checks since all agents are now web-compatible
- Change output directory from dist/web/bundles/ to dist/web/teams/ for clarity

File Organization:
- Move IDE-specific personas (dev.ide.md, devops-pe.ide.md, sm.ide.md) to bmad-core/ide-agents/
- Rename team bundles for clarity:
  - team-full.yml → team-full-app.yml (web application teams)
  - team-planning.yml → team-small-service.yml (backend service teams)
- Remove team-full-ide.yml (IDE teams will be handled separately)

This change ensures all 3 web team bundles build successfully and simplifies future agent maintenance.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Brian Madison
2025-06-06 23:12:58 -05:00
parent f91f49a6d9
commit e3ed97a690
21 changed files with 47 additions and 157 deletions

View File

@@ -118,14 +118,14 @@ class WebBuilder {
}
// Write output files
const outputDir = path.join(this.outputPath, 'bundles');
const outputDir = path.join(this.outputPath, 'teams');
this.ensureDirectory(outputDir);
const outputs = [];
// Default to single_file format if not specified
const outputFormat = bundleConfig.output?.format || 'single_file';
const outputFilename = bundleConfig.output?.filename || bundleConfig.filename || `${bundleConfig.name.toLowerCase().replace(/\s+/g, '-')}-bundle.txt`;
const outputFilename = bundleConfig.output?.filename || bundleConfig.filename || `${bundleConfig.name.toLowerCase().replace(/\s+/g, '-')}.txt`;
if (outputFormat === 'single_file') {
// Create single bundle file
@@ -160,7 +160,7 @@ class WebBuilder {
const outputDir = path.join(this.outputPath, 'agents');
this.ensureDirectory(outputDir);
const agentFile = path.join(outputDir, `${agentId}-agent-bundle.txt`);
const agentFile = path.join(outputDir, `${agentId}.txt`);
fs.writeFileSync(agentFile, optimizedBundle.standaloneContent);
return {
@@ -208,7 +208,7 @@ class WebBuilder {
*/
createOrchestratorFiles(bundle, config) {
const files = [];
const outputDir = path.join(this.outputPath, 'bundles');
const outputDir = path.join(this.outputPath, 'teams');
// Create agent-config.txt
const agentConfigContent = yaml.dump({
@@ -368,7 +368,7 @@ class WebBuilder {
*/
ensureOutputDirectory() {
this.ensureDirectory(this.outputPath);
this.ensureDirectory(path.join(this.outputPath, 'bundles'));
this.ensureDirectory(path.join(this.outputPath, 'teams'));
this.ensureDirectory(path.join(this.outputPath, 'agents'));
}
}

View File

@@ -49,7 +49,7 @@ class BundleOptimizer {
});
// Load and process resources
this.loadResources(optimizedBundle, agentDependencies.bundleResources);
this.loadResources(optimizedBundle, agentDependencies.bundleResources, agentDependencies.agents);
// Create optimized sections for web output
if (bundleConfig.target_environment === 'web') {
@@ -65,7 +65,7 @@ class BundleOptimizer {
/**
* Load resources from core directory
*/
loadResources(bundle, resourceLists) {
loadResources(bundle, resourceLists, agentDeps = []) {
const resourceTypes = ['tasks', 'templates', 'checklists', 'data', 'utils'];
resourceTypes.forEach(type => {
@@ -85,11 +85,13 @@ class BundleOptimizer {
// Load personas for agents
const personaDir = path.join(this.corePath, 'personas');
Object.keys(bundle.agents).forEach(agentId => {
const personaContent = this.loadResourceFile(personaDir, agentId);
agentDeps.forEach(agentDep => {
const agentId = agentDep.agent;
const personaName = agentDep.config.persona || agentId;
const personaContent = this.loadResourceFile(personaDir, personaName);
if (personaContent) {
bundle.resources.personas[agentId] = {
name: agentId,
name: personaName,
content: personaContent,
size: personaContent.length
};
@@ -202,7 +204,9 @@ class BundleOptimizer {
content += `${agent.description}\n\n`;
if (persona) {
content += `## Agent Persona\n\n${persona.content}\n\n`;
content += `==================== START: personas#${agentId} ====================\n`;
content += `${persona.content}\n`;
content += `==================== END: personas#${agentId} ====================\n\n`;
}
// Add required resources inline
@@ -210,9 +214,10 @@ class BundleOptimizer {
resourceTypes.forEach(type => {
const resources = bundle.resources[type];
if (Object.keys(resources).length > 0) {
content += `## ${type.charAt(0).toUpperCase() + type.slice(1)}\n\n`;
Object.entries(resources).forEach(([name, resource]) => {
content += `### ${name}\n\n${resource.content}\n\n`;
content += `==================== START: ${type}#${name} ====================\n`;
content += `${resource.content}\n`;
content += `==================== END: ${type}#${name} ====================\n\n`;
});
}
});

View File

@@ -39,9 +39,6 @@ class DependencyResolver {
if (rawConfig.dependencies) {
config.dependencies = rawConfig.dependencies;
}
if (rawConfig.environments) {
config.environments = rawConfig.environments;
}
// Validate required fields
this.validateAgentConfig(config, agentId);
@@ -66,9 +63,10 @@ class DependencyResolver {
throw new Error(`Agent ID mismatch: expected '${agentId}', got '${config.id}'`);
}
// Ensure environments exist with defaults
if (!config.environments) {
config.environments = { web: {}, ide: {} };
// Ensure persona exists
if (!config.persona) {
// Default to agent id if no persona specified
config.persona = config.id;
}
// Ensure dependencies exist with defaults
@@ -87,11 +85,6 @@ class DependencyResolver {
*/
resolveAgentDependencies(agentId, environment = 'web') {
const config = this.loadAgentConfig(agentId);
// Check if agent is available for this environment
if (environment === 'web' && config.environments.web?.available === false) {
throw new Error(`Agent '${agentId}' is not available for web environment`);
}
const dependencies = {
agent: agentId,