mirror of
https://github.com/bmadcode/BMAD-METHOD.git
synced 2025-12-17 09:45:25 +00:00
_cfg -> _config
This commit is contained in:
parent
ac5fa5c23f
commit
ae9851acab
@ -9,7 +9,7 @@ Customize BMad agents without modifying core files. All customizations persist t
|
|||||||
After installation, find agent customization files in:
|
After installation, find agent customization files in:
|
||||||
|
|
||||||
```
|
```
|
||||||
_bmad/_cfg/agents/
|
_bmad/_config/agents/
|
||||||
├── core-bmad-master.customize.yaml
|
├── core-bmad-master.customize.yaml
|
||||||
├── bmm-dev.customize.yaml
|
├── bmm-dev.customize.yaml
|
||||||
├── bmm-pm.customize.yaml
|
├── bmm-pm.customize.yaml
|
||||||
@ -119,7 +119,7 @@ prompts:
|
|||||||
**Example 1: Customize Developer Agent for TDD**
|
**Example 1: Customize Developer Agent for TDD**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# _bmad/_cfg/agents/bmm-dev.customize.yaml
|
# _bmad/_config/agents/bmm-dev.customize.yaml
|
||||||
agent:
|
agent:
|
||||||
metadata:
|
metadata:
|
||||||
name: 'TDD Developer'
|
name: 'TDD Developer'
|
||||||
@ -135,7 +135,7 @@ critical_actions:
|
|||||||
**Example 2: Add Custom Deployment Workflow**
|
**Example 2: Add Custom Deployment Workflow**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# _bmad/_cfg/agents/bmm-dev.customize.yaml
|
# _bmad/_config/agents/bmm-dev.customize.yaml
|
||||||
menu:
|
menu:
|
||||||
- trigger: deploy-staging
|
- trigger: deploy-staging
|
||||||
workflow: '{project-root}/_bmad/deploy-staging.yaml'
|
workflow: '{project-root}/_bmad/deploy-staging.yaml'
|
||||||
@ -148,7 +148,7 @@ menu:
|
|||||||
**Example 3: Multilingual Product Manager**
|
**Example 3: Multilingual Product Manager**
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# _bmad/_cfg/agents/bmm-pm.customize.yaml
|
# _bmad/_config/agents/bmm-pm.customize.yaml
|
||||||
persona:
|
persona:
|
||||||
role: 'Bilingual Product Manager'
|
role: 'Bilingual Product Manager'
|
||||||
identity: 'Expert in US and LATAM markets'
|
identity: 'Expert in US and LATAM markets'
|
||||||
@ -166,15 +166,15 @@ memories:
|
|||||||
|
|
||||||
- **Start Small:** Customize one section at a time and rebuild to test
|
- **Start Small:** Customize one section at a time and rebuild to test
|
||||||
- **Backup:** Copy customization files before major changes
|
- **Backup:** Copy customization files before major changes
|
||||||
- **Update-Safe:** Your customizations in `_cfg/` survive all BMad updates
|
- **Update-Safe:** Your customizations in `_config/` survive all BMad updates
|
||||||
- **Per-Project:** Customization files are per-project, not global
|
- **Per-Project:** Customization files are per-project, not global
|
||||||
- **Version Control:** Consider committing `_cfg/` to share customizations with your team
|
- **Version Control:** Consider committing `_config/` to share customizations with your team
|
||||||
|
|
||||||
## Module vs. Global Config
|
## Module vs. Global Config
|
||||||
|
|
||||||
**Module-Level (Recommended):**
|
**Module-Level (Recommended):**
|
||||||
|
|
||||||
- Customize agents per-project in `_bmad/_cfg/agents/`
|
- Customize agents per-project in `_bmad/_config/agents/`
|
||||||
- Different projects can have different agent behaviors
|
- Different projects can have different agent behaviors
|
||||||
|
|
||||||
**Global Config (Coming Soon):**
|
**Global Config (Coming Soon):**
|
||||||
|
|||||||
@ -28,7 +28,7 @@ BMad Core is a modular AI agent framework with intelligent installation, platfor
|
|||||||
```
|
```
|
||||||
project-root/
|
project-root/
|
||||||
├── _bmad/ # Centralized installation
|
├── _bmad/ # Centralized installation
|
||||||
│ ├── _cfg/ # Configuration
|
│ ├── _config/ # Configuration
|
||||||
│ │ ├── agents/ # Agent configs
|
│ │ ├── agents/ # Agent configs
|
||||||
│ │ └── agent-manifest.csv # Agent manifest
|
│ │ └── agent-manifest.csv # Agent manifest
|
||||||
│ ├── core/ # Core module
|
│ ├── core/ # Core module
|
||||||
@ -265,7 +265,7 @@ Extractable config nodes:
|
|||||||
</agent>
|
</agent>
|
||||||
```
|
```
|
||||||
|
|
||||||
Generated in: `bmad/_cfg/agents/{module}-{agent}.md`
|
Generated in: `bmad/_config/agents/{module}-{agent}.md`
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
@ -290,7 +290,7 @@ bmad status -v # Detailed status
|
|||||||
### Best Practices
|
### Best Practices
|
||||||
|
|
||||||
1. Run from project root
|
1. Run from project root
|
||||||
2. Backup `_bmad/_cfg/` before updates
|
2. Backup `_bmad/_config/` before updates
|
||||||
3. Use interactive mode for guidance
|
3. Use interactive mode for guidance
|
||||||
4. Review generated configs post-install
|
4. Review generated configs post-install
|
||||||
|
|
||||||
|
|||||||
@ -68,7 +68,7 @@ your-project/
|
|||||||
├── bmm/ # BMad Method (software/game dev)
|
├── bmm/ # BMad Method (software/game dev)
|
||||||
├── bmb/ # BMad Builder (create agents/workflows)
|
├── bmb/ # BMad Builder (create agents/workflows)
|
||||||
├── cis/ # Creative Intelligence Suite
|
├── cis/ # Creative Intelligence Suite
|
||||||
└── _cfg/ # Your customizations
|
└── _config/ # Your customizations
|
||||||
└── agents/ # Agent customization files
|
└── agents/ # Agent customization files
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -114,11 +114,11 @@ In v4, you may have modified agent files directly in `_bmad-*` folders.
|
|||||||
|
|
||||||
### v6 Agent Customization
|
### v6 Agent Customization
|
||||||
|
|
||||||
**All customizations** now go in `_bmad/_cfg/agents/` using customize files:
|
**All customizations** now go in `_bmad/_config/agents/` using customize files:
|
||||||
|
|
||||||
**Example: Renaming an agent and changing communication style**
|
**Example: Renaming an agent and changing communication style**
|
||||||
|
|
||||||
File: `_bmad/_cfg/agents/bmm-pm.customize.yaml`
|
File: `_bmad/_config/agents/bmm-pm.customize.yaml`
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# Customize the PM agent
|
# Customize the PM agent
|
||||||
@ -134,7 +134,7 @@ persona:
|
|||||||
**How it works:**
|
**How it works:**
|
||||||
|
|
||||||
- Base agent: `_bmad/bmm/agents/pm.md`
|
- Base agent: `_bmad/bmm/agents/pm.md`
|
||||||
- Customization: `_bmad/_cfg/agents/bmm-pm.customize.yaml`
|
- Customization: `_bmad/_config/agents/bmm-pm.customize.yaml`
|
||||||
- Result: Agent uses your custom name and style, but updates don't overwrite your changes
|
- Result: Agent uses your custom name and style, but updates don't overwrite your changes
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -214,7 +214,7 @@ Since you are migrating an existing project from v4, it's most likely **Level 3
|
|||||||
- [ ] v4 folders backed up to `v4-backup/`
|
- [ ] v4 folders backed up to `v4-backup/`
|
||||||
- [ ] v6 installed to `_bmad/` folder
|
- [ ] v6 installed to `_bmad/` folder
|
||||||
- [ ] `workflow-init` run with correct project level selected
|
- [ ] `workflow-init` run with correct project level selected
|
||||||
- [ ] Agent customizations migrated to `_bmad/_cfg/agents/` if needed
|
- [ ] Agent customizations migrated to `_bmad/_config/agents/` if needed
|
||||||
- [ ] IDE integration working (test by listing agents)
|
- [ ] IDE integration working (test by listing agents)
|
||||||
- [ ] For active development: `sprint-planning` workflow executed
|
- [ ] For active development: `sprint-planning` workflow executed
|
||||||
|
|
||||||
|
|||||||
@ -336,7 +336,7 @@ Agents adapt their menus based on project phase and available workflows.
|
|||||||
|
|
||||||
Customize agents using the [Agent Customization Guide](./agent-customization-guide.md):
|
Customize agents using the [Agent Customization Guide](./agent-customization-guide.md):
|
||||||
|
|
||||||
1. Edit `_bmad/_cfg/agents/<agent>.customize.yaml`
|
1. Edit `_bmad/_config/agents/<agent>.customize.yaml`
|
||||||
2. Rebuild: `npx bmad-method build <agent-name>`
|
2. Rebuild: `npx bmad-method build <agent-name>`
|
||||||
3. Generate bundles: `npm run bundle`
|
3. Generate bundles: `npm run bundle`
|
||||||
|
|
||||||
|
|||||||
@ -24,11 +24,11 @@ agent:
|
|||||||
# Agent menu items
|
# Agent menu items
|
||||||
menu:
|
menu:
|
||||||
- trigger: "list-tasks"
|
- trigger: "list-tasks"
|
||||||
action: "list all tasks from {project-root}/_bmad/_cfg/task-manifest.csv"
|
action: "list all tasks from {project-root}/_bmad/_config/task-manifest.csv"
|
||||||
description: "List Available Tasks"
|
description: "List Available Tasks"
|
||||||
|
|
||||||
- trigger: "list-workflows"
|
- trigger: "list-workflows"
|
||||||
action: "list all workflows from {project-root}/_bmad/_cfg/workflow-manifest.csv"
|
action: "list all workflows from {project-root}/_bmad/_config/workflow-manifest.csv"
|
||||||
description: "List Workflows"
|
description: "List Workflows"
|
||||||
|
|
||||||
- trigger: "party-mode"
|
- trigger: "party-mode"
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<task id="_bmad/core/tasks/advanced-elicitation.xml" name="Advanced Elicitation" standalone="true"
|
<task id="_bmad/core/tasks/advanced-elicitation.xml" name="Advanced Elicitation" standalone="true"
|
||||||
methods="{project-root}/_bmad/core/tasks/advanced-elicitation-methods.csv"
|
methods="{project-root}/_bmad/core/tasks/advanced-elicitation-methods.csv"
|
||||||
agent-party="{project-root}/_bmad/_cfg/agent-manifest.csv">
|
agent-party="{project-root}/_bmad/_config/agent-manifest.csv">
|
||||||
<llm critical="true">
|
<llm critical="true">
|
||||||
<i>MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER</i>
|
<i>MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER</i>
|
||||||
<i>DO NOT skip steps or change the sequence</i>
|
<i>DO NOT skip steps or change the sequence</i>
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
## CONTEXT BOUNDARIES:
|
## CONTEXT BOUNDARIES:
|
||||||
|
|
||||||
- Agent manifest CSV is available at `{project-root}/_bmad/_cfg/agent-manifest.csv`
|
- Agent manifest CSV is available at `{project-root}/_bmad/_config/agent-manifest.csv`
|
||||||
- User configuration from config.yaml is loaded and resolved
|
- User configuration from config.yaml is loaded and resolved
|
||||||
- Party mode is standalone interactive workflow
|
- Party mode is standalone interactive workflow
|
||||||
- All agent data is available for conversation orchestration
|
- All agent data is available for conversation orchestration
|
||||||
@ -37,7 +37,7 @@ Begin agent loading process:
|
|||||||
|
|
||||||
**Agent Manifest Loading:**"
|
**Agent Manifest Loading:**"
|
||||||
|
|
||||||
Load and parse the agent manifest CSV from `{project-root}/_bmad/_cfg/agent-manifest.csv`
|
Load and parse the agent manifest CSV from `{project-root}/_bmad/_config/agent-manifest.csv`
|
||||||
|
|
||||||
### 2. Extract Agent Data
|
### 2. Extract Agent Data
|
||||||
|
|
||||||
|
|||||||
@ -32,12 +32,12 @@ Load config from `{project-root}/_bmad/core/config.yaml` and resolve:
|
|||||||
- `project_name`, `output_folder`, `user_name`
|
- `project_name`, `output_folder`, `user_name`
|
||||||
- `communication_language`, `document_output_language`, `user_skill_level`
|
- `communication_language`, `document_output_language`, `user_skill_level`
|
||||||
- `date` as a system-generated value
|
- `date` as a system-generated value
|
||||||
- Agent manifest path: `{project-root}/_bmad/_cfg/agent-manifest.csv`
|
- Agent manifest path: `{project-root}/_bmad/_config/agent-manifest.csv`
|
||||||
|
|
||||||
### Paths
|
### Paths
|
||||||
|
|
||||||
- `installed_path` = `{project-root}/_bmad/core/workflows/party-mode`
|
- `installed_path` = `{project-root}/_bmad/core/workflows/party-mode`
|
||||||
- `agent_manifest_path` = `{project-root}/_bmad/_cfg/agent-manifest.csv`
|
- `agent_manifest_path` = `{project-root}/_bmad/_config/agent-manifest.csv`
|
||||||
- `standalone_mode` = `true` (party mode is an interactive workflow)
|
- `standalone_mode` = `true` (party mode is an interactive workflow)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@ -132,7 +132,7 @@ Universal attribute for supplementary information.
|
|||||||
menu:
|
menu:
|
||||||
- trigger: team-standup
|
- trigger: team-standup
|
||||||
exec: '{project-root}/_bmad/bmm/tasks/standup.xml'
|
exec: '{project-root}/_bmad/bmm/tasks/standup.xml'
|
||||||
data: '{project-root}/_bmad/_cfg/agent-manifest.csv'
|
data: '{project-root}/_bmad/_config/agent-manifest.csv'
|
||||||
description: 'Run team standup'
|
description: 'Run team standup'
|
||||||
|
|
||||||
- trigger: analyze-metrics
|
- trigger: analyze-metrics
|
||||||
|
|||||||
@ -63,7 +63,7 @@ agent:
|
|||||||
|
|
||||||
- trigger: with-data
|
- trigger: with-data
|
||||||
exec: '{project-root}/_bmad/{module-code}/tasks/{task-name}.xml'
|
exec: '{project-root}/_bmad/{module-code}/tasks/{task-name}.xml'
|
||||||
data: '{project-root}/_bmad/_cfg/agent-manifest.csv'
|
data: '{project-root}/_bmad/_config/agent-manifest.csv'
|
||||||
description: 'Execute task with data file'
|
description: 'Execute task with data file'
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ Combines task execution with template file.
|
|||||||
menu:
|
menu:
|
||||||
- trigger: team-standup
|
- trigger: team-standup
|
||||||
exec: '{project-root}/_bmad/bmm/tasks/standup.xml'
|
exec: '{project-root}/_bmad/bmm/tasks/standup.xml'
|
||||||
data: '{project-root}/_bmad/_cfg/agent-manifest.csv'
|
data: '{project-root}/_bmad/_config/agent-manifest.csv'
|
||||||
description: 'Run team standup with agent roster'
|
description: 'Run team standup with agent roster'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ thisStepFile: '{workflow_path}/steps/step-09-customize.md'
|
|||||||
nextStepFile: '{workflow_path}/steps/step-10-build-tools.md'
|
nextStepFile: '{workflow_path}/steps/step-10-build-tools.md'
|
||||||
workflowFile: '{workflow_path}/workflow.md'
|
workflowFile: '{workflow_path}/workflow.md'
|
||||||
outputFile: '{output_folder}/agent-customization-{project_name}.md'
|
outputFile: '{output_folder}/agent-customization-{project_name}.md'
|
||||||
configOutputFile: '{project-root}/_bmad/_cfg/agents/{target_module}-{agent_filename}.customize.yaml'
|
configOutputFile: '{project-root}/_bmad/_config/agents/{target_module}-{agent_filename}.customize.yaml'
|
||||||
|
|
||||||
# Template References
|
# Template References
|
||||||
customizationTemplate: '{workflow_path}/templates/agent-customization.md'
|
customizationTemplate: '{workflow_path}/templates/agent-customization.md'
|
||||||
|
|||||||
@ -88,4 +88,4 @@ module_output_file: "{project-root}/\_bmad/{target_module}/agents/{agent_filenam
|
|||||||
standalone_output_folder: "{custom_agent_location}/{agent_filename}"
|
standalone_output_folder: "{custom_agent_location}/{agent_filename}"
|
||||||
standalone_output_file: "{standalone_output_folder}/{agent_filename}.agent.yaml"
|
standalone_output_file: "{standalone_output_folder}/{agent_filename}.agent.yaml"
|
||||||
standalone_info_guide: "{standalone_output_folder}/info-and-installation-guide.md"
|
standalone_info_guide: "{standalone_output_folder}/info-and-installation-guide.md"
|
||||||
config_output_file: "{project-root}/\_bmad/\_cfg/agents/{target_module}-{agent_filename}.customize.yaml"
|
config_output_file: "{project-root}/\_bmad/\_config/agents/{target_module}-{agent_filename}.customize.yaml"
|
||||||
|
|||||||
@ -58,7 +58,7 @@ agent:
|
|||||||
- trigger: epic-retrospective
|
- trigger: epic-retrospective
|
||||||
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml"
|
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml"
|
||||||
workflow-install: "{project-root}/_bmad/bmgd/workflows/4-production/retrospective/workflow.yaml"
|
workflow-install: "{project-root}/_bmad/bmgd/workflows/4-production/retrospective/workflow.yaml"
|
||||||
data: "{project-root}/_bmad/_cfg/agent-manifest.csv"
|
data: "{project-root}/_bmad/_config/agent-manifest.csv"
|
||||||
description: (Optional) Facilitate team retrospective after a game development epic is completed
|
description: (Optional) Facilitate team retrospective after a game development epic is completed
|
||||||
|
|
||||||
- trigger: correct-course
|
- trigger: correct-course
|
||||||
|
|||||||
@ -17,7 +17,7 @@ template: false
|
|||||||
instructions: "{installed_path}/instructions.md"
|
instructions: "{installed_path}/instructions.md"
|
||||||
|
|
||||||
required_inputs:
|
required_inputs:
|
||||||
- agent_manifest: "{project-root}/_bmad/_cfg/agent-manifest.csv"
|
- agent_manifest: "{project-root}/_bmad/_config/agent-manifest.csv"
|
||||||
|
|
||||||
# Smart input file references - handles both whole docs and sharded docs
|
# Smart input file references - handles both whole docs and sharded docs
|
||||||
# Priority: Whole document first, then sharded version
|
# Priority: Whole document first, then sharded version
|
||||||
|
|||||||
@ -38,7 +38,7 @@ agent:
|
|||||||
|
|
||||||
- trigger: epic-retrospective
|
- trigger: epic-retrospective
|
||||||
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml"
|
workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml"
|
||||||
data: "{project-root}/_bmad/_cfg/agent-manifest.csv"
|
data: "{project-root}/_bmad/_config/agent-manifest.csv"
|
||||||
description: Facilitate team retrospective after an epic is completed (Optional)
|
description: Facilitate team retrospective after an epic is completed (Optional)
|
||||||
|
|
||||||
- trigger: correct-course
|
- trigger: correct-course
|
||||||
|
|||||||
@ -663,14 +663,14 @@ You can customize any agent's personality without modifying core agent files.
|
|||||||
|
|
||||||
### Location
|
### Location
|
||||||
|
|
||||||
**Customization Directory:** `{project-root}/_bmad/_cfg/agents/`
|
**Customization Directory:** `{project-root}/_bmad/_config/agents/`
|
||||||
|
|
||||||
**Naming Convention:** `{module}-{agent-name}.customize.yaml`
|
**Naming Convention:** `{module}-{agent-name}.customize.yaml`
|
||||||
|
|
||||||
**Examples:**
|
**Examples:**
|
||||||
|
|
||||||
```
|
```
|
||||||
_bmad/_cfg/agents/
|
_bmad/_config/agents/
|
||||||
├── bmm-pm.customize.yaml
|
├── bmm-pm.customize.yaml
|
||||||
├── bmm-dev.customize.yaml
|
├── bmm-dev.customize.yaml
|
||||||
├── cis-storyteller.customize.yaml
|
├── cis-storyteller.customize.yaml
|
||||||
@ -770,9 +770,9 @@ Other agents collaborate with PM's specialized perspective.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Create customization file at:
|
# Create customization file at:
|
||||||
# {project-root}/_bmad/_cfg/agents/{module}-{agent-name}.customize.yaml
|
# {project-root}/_bmad/_config/agents/{module}-{agent-name}.customize.yaml
|
||||||
|
|
||||||
# Example: _bmad/_cfg/agents/bmm-pm.customize.yaml
|
# Example: _bmad/_config/agents/bmm-pm.customize.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
**Step 2: Regenerate Agent Manifest**
|
**Step 2: Regenerate Agent Manifest**
|
||||||
|
|||||||
@ -358,7 +358,7 @@ See [IDE Setup Guides](https://github.com/bmad-code-org/BMAD-METHOD/tree/main/do
|
|||||||
|
|
||||||
### Q: Can I customize agents?
|
### Q: Can I customize agents?
|
||||||
|
|
||||||
**A:** Yes! Agents are installed as markdown files with XML-style content (optimized for LLMs, readable by any model). Create customization files in `_bmad/_cfg/agents/[agent-name].customize.yaml` to override default behaviors while keeping core functionality intact. See agent documentation for customization options.
|
**A:** Yes! Agents are installed as markdown files with XML-style content (optimized for LLMs, readable by any model). Create customization files in `_bmad/_config/agents/[agent-name].customize.yaml` to override default behaviors while keeping core functionality intact. See agent documentation for customization options.
|
||||||
|
|
||||||
**Note:** While source agents in this repo are YAML, they install as `.md` files with XML-style tags - a format any LLM can read and follow.
|
**Note:** While source agents in this repo are YAML, they install as `.md` files with XML-style tags - a format any LLM can read and follow.
|
||||||
|
|
||||||
|
|||||||
@ -27,7 +27,7 @@ Type `/bmad:core:workflows:party-mode` (or `*party-mode` from any agent), and su
|
|||||||
|
|
||||||
**The basics:**
|
**The basics:**
|
||||||
|
|
||||||
1. Party mode reads `_bmad/_cfg/agent-manifest.csv`
|
1. Party mode reads `_bmad/_config/agent-manifest.csv`
|
||||||
2. Loads ALL installed agents (already includes your customizations from install)
|
2. Loads ALL installed agents (already includes your customizations from install)
|
||||||
3. BMad Master orchestrates - picks 2-3 relevant agents per message based on topic
|
3. BMad Master orchestrates - picks 2-3 relevant agents per message based on topic
|
||||||
4. Agents respond in character, can agree/disagree/build on each other's ideas
|
4. Agents respond in character, can agree/disagree/build on each other's ideas
|
||||||
@ -130,7 +130,7 @@ Party mode uses agents from `_bmad/[module]/agents/*.md` - these already include
|
|||||||
|
|
||||||
**To customize agents for party mode:**
|
**To customize agents for party mode:**
|
||||||
|
|
||||||
1. Create customization file: `_bmad/_cfg/agents/bmm-pm.customize.yaml`
|
1. Create customization file: `_bmad/_config/agents/bmm-pm.customize.yaml`
|
||||||
2. Run `npx bmad-method install` to rebuild agents
|
2. Run `npx bmad-method install` to rebuild agents
|
||||||
3. Customizations now active in party mode
|
3. Customizations now active in party mode
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ template: false
|
|||||||
instructions: "{installed_path}/instructions.md"
|
instructions: "{installed_path}/instructions.md"
|
||||||
|
|
||||||
required_inputs:
|
required_inputs:
|
||||||
- agent_manifest: "{project-root}/_bmad/_cfg/agent-manifest.csv"
|
- agent_manifest: "{project-root}/_bmad/_config/agent-manifest.csv"
|
||||||
|
|
||||||
# Smart input file references - handles both whole docs and sharded docs
|
# Smart input file references - handles both whole docs and sharded docs
|
||||||
# Priority: Whole document first, then sharded version
|
# Priority: Whole document first, then sharded version
|
||||||
|
|||||||
@ -99,7 +99,7 @@ async function buildAgent(projectDir, agentName) {
|
|||||||
// Build the standalone agent
|
// Build the standalone agent
|
||||||
console.log(chalk.cyan(` Building standalone agent ${agentName}...`));
|
console.log(chalk.cyan(` Building standalone agent ${agentName}...`));
|
||||||
|
|
||||||
const customizePath = path.join(projectDir, '_bmad', '_cfg', 'agents', `${agentName}.customize.yaml`);
|
const customizePath = path.join(projectDir, '_bmad', '_config', 'agents', `${agentName}.customize.yaml`);
|
||||||
const customizeExists = await fs.pathExists(customizePath);
|
const customizeExists = await fs.pathExists(customizePath);
|
||||||
|
|
||||||
await builder.buildAgent(standaloneYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true });
|
await builder.buildAgent(standaloneYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true });
|
||||||
@ -125,7 +125,7 @@ async function buildAgent(projectDir, agentName) {
|
|||||||
// Build the agent
|
// Build the agent
|
||||||
console.log(chalk.cyan(` Building ${agentName}...`));
|
console.log(chalk.cyan(` Building ${agentName}...`));
|
||||||
|
|
||||||
const customizePath = path.join(projectDir, '.claude', '_cfg', 'agents', `${agentName}.customize.yaml`);
|
const customizePath = path.join(projectDir, '.claude', '_config', 'agents', `${agentName}.customize.yaml`);
|
||||||
const customizeExists = await fs.pathExists(customizePath);
|
const customizeExists = await fs.pathExists(customizePath);
|
||||||
|
|
||||||
await builder.buildAgent(agentYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true });
|
await builder.buildAgent(agentYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true });
|
||||||
@ -177,7 +177,7 @@ async function buildAllAgents(projectDir) {
|
|||||||
|
|
||||||
console.log(chalk.cyan(` Building standalone agent ${agentName}...`));
|
console.log(chalk.cyan(` Building standalone agent ${agentName}...`));
|
||||||
|
|
||||||
const customizePath = path.join(projectDir, '_bmad', '_cfg', 'agents', `${agentName}.customize.yaml`);
|
const customizePath = path.join(projectDir, '_bmad', '_config', 'agents', `${agentName}.customize.yaml`);
|
||||||
const customizeExists = await fs.pathExists(customizePath);
|
const customizeExists = await fs.pathExists(customizePath);
|
||||||
|
|
||||||
await builder.buildAgent(agentYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true });
|
await builder.buildAgent(agentYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true });
|
||||||
@ -213,7 +213,7 @@ async function buildAllAgents(projectDir) {
|
|||||||
|
|
||||||
console.log(chalk.cyan(` Building ${agentName}...`));
|
console.log(chalk.cyan(` Building ${agentName}...`));
|
||||||
|
|
||||||
const customizePath = path.join(projectDir, '.claude', '_cfg', 'agents', `${agentName}.customize.yaml`);
|
const customizePath = path.join(projectDir, '.claude', '_config', 'agents', `${agentName}.customize.yaml`);
|
||||||
const customizeExists = await fs.pathExists(customizePath);
|
const customizeExists = await fs.pathExists(customizePath);
|
||||||
|
|
||||||
await builder.buildAgent(agentYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true });
|
await builder.buildAgent(agentYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true });
|
||||||
|
|||||||
@ -15,7 +15,7 @@ class ConfigCollector {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the bmad installation directory in a project
|
* Find the bmad installation directory in a project
|
||||||
* V6+ installations can use ANY folder name but ALWAYS have _cfg/manifest.yaml
|
* V6+ installations can use ANY folder name but ALWAYS have _config/manifest.yaml
|
||||||
* @param {string} projectDir - Project directory
|
* @param {string} projectDir - Project directory
|
||||||
* @returns {Promise<string>} Path to bmad directory
|
* @returns {Promise<string>} Path to bmad directory
|
||||||
*/
|
*/
|
||||||
@ -26,13 +26,13 @@ class ConfigCollector {
|
|||||||
return path.join(projectDir, 'bmad');
|
return path.join(projectDir, 'bmad');
|
||||||
}
|
}
|
||||||
|
|
||||||
// V6+ strategy: Look for ANY directory with _cfg/manifest.yaml
|
// V6+ strategy: Look for ANY directory with _config/manifest.yaml
|
||||||
// This is the definitive marker of a V6+ installation
|
// This is the definitive marker of a V6+ installation
|
||||||
try {
|
try {
|
||||||
const entries = await fs.readdir(projectDir, { withFileTypes: true });
|
const entries = await fs.readdir(projectDir, { withFileTypes: true });
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
const manifestPath = path.join(projectDir, entry.name, '_cfg', 'manifest.yaml');
|
const manifestPath = path.join(projectDir, entry.name, '_config', 'manifest.yaml');
|
||||||
if (await fs.pathExists(manifestPath)) {
|
if (await fs.pathExists(manifestPath)) {
|
||||||
// Found a V6+ installation
|
// Found a V6+ installation
|
||||||
return path.join(projectDir, entry.name);
|
return path.join(projectDir, entry.name);
|
||||||
@ -59,12 +59,12 @@ class ConfigCollector {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for ANY directory with _cfg/manifest.yaml
|
// Look for ANY directory with _config/manifest.yaml
|
||||||
try {
|
try {
|
||||||
const entries = await fs.readdir(projectDir, { withFileTypes: true });
|
const entries = await fs.readdir(projectDir, { withFileTypes: true });
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
const manifestPath = path.join(projectDir, entry.name, '_cfg', 'manifest.yaml');
|
const manifestPath = path.join(projectDir, entry.name, '_config', 'manifest.yaml');
|
||||||
if (await fs.pathExists(manifestPath)) {
|
if (await fs.pathExists(manifestPath)) {
|
||||||
// Found a V6+ installation, return just the folder name
|
// Found a V6+ installation, return just the folder name
|
||||||
return entry.name;
|
return entry.name;
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* Custom Module Source Cache
|
* Custom Module Source Cache
|
||||||
* Caches custom module sources under _cfg/custom/ to ensure they're never lost
|
* Caches custom module sources under _config/custom/ to ensure they're never lost
|
||||||
* and can be checked into source control
|
* and can be checked into source control
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -11,7 +11,7 @@ const crypto = require('node:crypto');
|
|||||||
class CustomModuleCache {
|
class CustomModuleCache {
|
||||||
constructor(bmadDir) {
|
constructor(bmadDir) {
|
||||||
this.bmadDir = bmadDir;
|
this.bmadDir = bmadDir;
|
||||||
this.customCacheDir = path.join(bmadDir, '_cfg', 'custom');
|
this.customCacheDir = path.join(bmadDir, '_config', 'custom');
|
||||||
this.manifestPath = path.join(this.customCacheDir, 'cache-manifest.yaml');
|
this.manifestPath = path.join(this.customCacheDir, 'cache-manifest.yaml');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -92,7 +92,7 @@ class Detector {
|
|||||||
// Fallback: scan directory for modules (legacy installations without manifest)
|
// Fallback: scan directory for modules (legacy installations without manifest)
|
||||||
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg') {
|
if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config') {
|
||||||
const modulePath = path.join(bmadDir, entry.name);
|
const modulePath = path.join(bmadDir, entry.name);
|
||||||
const moduleConfigPath = path.join(modulePath, 'config.yaml');
|
const moduleConfigPath = path.join(modulePath, 'config.yaml');
|
||||||
|
|
||||||
@ -205,7 +205,7 @@ class Detector {
|
|||||||
/**
|
/**
|
||||||
* Detect legacy BMAD v4 footprints (case-sensitive path checks)
|
* Detect legacy BMAD v4 footprints (case-sensitive path checks)
|
||||||
* V4 used _bmad-method as default folder name
|
* V4 used _bmad-method as default folder name
|
||||||
* V6+ uses configurable folder names and ALWAYS has _cfg/manifest.yaml with installation.version
|
* V6+ uses configurable folder names and ALWAYS has _config/manifest.yaml with installation.version
|
||||||
* @param {string} projectDir - Project directory to check
|
* @param {string} projectDir - Project directory to check
|
||||||
* @returns {{ hasLegacyV4: boolean, offenders: string[] }}
|
* @returns {{ hasLegacyV4: boolean, offenders: string[] }}
|
||||||
*/
|
*/
|
||||||
@ -232,7 +232,7 @@ class Detector {
|
|||||||
|
|
||||||
// Helper: check if a directory is a V6+ installation
|
// Helper: check if a directory is a V6+ installation
|
||||||
const isV6Installation = async (dirPath) => {
|
const isV6Installation = async (dirPath) => {
|
||||||
const manifestPath = path.join(dirPath, '_cfg', 'manifest.yaml');
|
const manifestPath = path.join(dirPath, '_config', 'manifest.yaml');
|
||||||
if (!(await fs.pathExists(manifestPath))) {
|
if (!(await fs.pathExists(manifestPath))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -250,7 +250,7 @@ class Detector {
|
|||||||
const offenders = [];
|
const offenders = [];
|
||||||
|
|
||||||
// Strategy:
|
// Strategy:
|
||||||
// 1. First scan for ANY V6+ installation (_cfg/manifest.yaml)
|
// 1. First scan for ANY V6+ installation (_config/manifest.yaml)
|
||||||
// 2. If V6+ found → don't flag anything (user is already on V6+)
|
// 2. If V6+ found → don't flag anything (user is already on V6+)
|
||||||
// 3. If NO V6+ found → flag folders with "bmad" in name as potential V4 legacy
|
// 3. If NO V6+ found → flag folders with "bmad" in name as potential V4 legacy
|
||||||
|
|
||||||
@ -271,7 +271,7 @@ class Detector {
|
|||||||
continue; // Skip empty folders
|
continue; // Skip empty folders
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it's a V6+ installation by looking for _cfg/manifest.yaml
|
// Check if it's a V6+ installation by looking for _config/manifest.yaml
|
||||||
// This works for ANY folder name (not just bmad-prefixed)
|
// This works for ANY folder name (not just bmad-prefixed)
|
||||||
const isV6 = await isV6Installation(fullPath);
|
const isV6 = await isV6Installation(fullPath);
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ const yaml = require('yaml');
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages IDE configuration persistence
|
* Manages IDE configuration persistence
|
||||||
* Saves and loads IDE-specific configurations to/from bmad/_cfg/ides/
|
* Saves and loads IDE-specific configurations to/from bmad/_config/ides/
|
||||||
*/
|
*/
|
||||||
class IdeConfigManager {
|
class IdeConfigManager {
|
||||||
constructor() {}
|
constructor() {}
|
||||||
@ -15,7 +15,7 @@ class IdeConfigManager {
|
|||||||
* @returns {string} Path to IDE config directory
|
* @returns {string} Path to IDE config directory
|
||||||
*/
|
*/
|
||||||
getIdeConfigDir(bmadDir) {
|
getIdeConfigDir(bmadDir) {
|
||||||
return path.join(bmadDir, '_cfg', 'ides');
|
return path.join(bmadDir, '_config', 'ides');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -38,27 +38,40 @@ class Installer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the bmad installation directory in a project
|
* Find the bmad installation directory in a project
|
||||||
* V6+ installations can use ANY folder name but ALWAYS have _cfg/manifest.yaml
|
* V6+ installations can use ANY folder name but ALWAYS have _config/manifest.yaml
|
||||||
|
* Also checks for legacy _cfg folder for migration
|
||||||
* @param {string} projectDir - Project directory
|
* @param {string} projectDir - Project directory
|
||||||
* @returns {Promise<string>} Path to bmad directory
|
* @returns {Promise<Object>} { bmadDir: string, hasLegacyCfg: boolean }
|
||||||
*/
|
*/
|
||||||
async findBmadDir(projectDir) {
|
async findBmadDir(projectDir) {
|
||||||
// Check if project directory exists
|
// Check if project directory exists
|
||||||
if (!(await fs.pathExists(projectDir))) {
|
if (!(await fs.pathExists(projectDir))) {
|
||||||
// Project doesn't exist yet, return default
|
// Project doesn't exist yet, return default
|
||||||
return path.join(projectDir, '_bmad');
|
return { bmadDir: path.join(projectDir, '_bmad'), hasLegacyCfg: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
// V6+ strategy: Look for ANY directory with _cfg/manifest.yaml
|
// V6+ strategy: Look for ANY directory with _config/manifest.yaml or legacy _cfg/manifest.yaml
|
||||||
// This is the definitive marker of a V6+ installation
|
let bmadDir = null;
|
||||||
|
let hasLegacyCfg = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const entries = await fs.readdir(projectDir, { withFileTypes: true });
|
const entries = await fs.readdir(projectDir, { withFileTypes: true });
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
const manifestPath = path.join(projectDir, entry.name, '_cfg', 'manifest.yaml');
|
const bmadPath = path.join(projectDir, entry.name);
|
||||||
|
|
||||||
|
// Check for current _config folder
|
||||||
|
const manifestPath = path.join(bmadPath, '_config', 'manifest.yaml');
|
||||||
if (await fs.pathExists(manifestPath)) {
|
if (await fs.pathExists(manifestPath)) {
|
||||||
// Found a V6+ installation
|
// Found a V6+ installation with current _config folder
|
||||||
return path.join(projectDir, entry.name);
|
return { bmadDir: bmadPath, hasLegacyCfg: false };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for legacy _cfg folder
|
||||||
|
const legacyManifestPath = path.join(bmadPath, '_cfg', 'manifest.yaml');
|
||||||
|
if (await fs.pathExists(legacyManifestPath)) {
|
||||||
|
bmadDir = bmadPath;
|
||||||
|
hasLegacyCfg = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,9 +79,14 @@ class Installer {
|
|||||||
// Ignore errors, fall through to default
|
// Ignore errors, fall through to default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we found a bmad directory (with or without legacy _cfg)
|
||||||
|
if (bmadDir) {
|
||||||
|
return { bmadDir, hasLegacyCfg };
|
||||||
|
}
|
||||||
|
|
||||||
// No V6+ installation found, return default
|
// No V6+ installation found, return default
|
||||||
// This will be used for new installations
|
// This will be used for new installations
|
||||||
return path.join(projectDir, '_bmad');
|
return { bmadDir: path.join(projectDir, '_bmad'), hasLegacyCfg: false };
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -473,10 +491,13 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
|
|
||||||
let existingBmadDir = null;
|
let existingBmadDir = null;
|
||||||
let existingBmadFolderName = null;
|
let existingBmadFolderName = null;
|
||||||
|
let hasLegacyCfg = false;
|
||||||
|
|
||||||
if (await fs.pathExists(projectDir)) {
|
if (await fs.pathExists(projectDir)) {
|
||||||
existingBmadDir = await this.findBmadDir(projectDir);
|
const result = await this.findBmadDir(projectDir);
|
||||||
|
existingBmadDir = result.bmadDir;
|
||||||
existingBmadFolderName = path.basename(existingBmadDir);
|
existingBmadFolderName = path.basename(existingBmadDir);
|
||||||
|
hasLegacyCfg = result.hasLegacyCfg;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a project directory if it doesn't exist (user already confirmed)
|
// Create a project directory if it doesn't exist (user already confirmed)
|
||||||
@ -501,6 +522,44 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
|
|
||||||
const bmadDir = path.join(projectDir, bmadFolderName);
|
const bmadDir = path.join(projectDir, bmadFolderName);
|
||||||
|
|
||||||
|
// Check for legacy _cfg folder and prompt for rename
|
||||||
|
if (hasLegacyCfg && !config._quickUpdate) {
|
||||||
|
spinner.stop();
|
||||||
|
|
||||||
|
console.log(chalk.yellow('\n⚠️ Legacy configuration folder detected'));
|
||||||
|
console.log(chalk.dim(` Found: ${path.join(bmadDir, '_cfg')}`));
|
||||||
|
console.log(chalk.dim(' The configuration folder has been renamed from "_cfg" to "_config"'));
|
||||||
|
|
||||||
|
const inquirer = require('inquirer');
|
||||||
|
const { shouldRename } = await inquirer.prompt([
|
||||||
|
{
|
||||||
|
type: 'confirm',
|
||||||
|
name: 'shouldRename',
|
||||||
|
message: 'Would you like the installer to rename "_cfg" to "_config" for you?',
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!shouldRename) {
|
||||||
|
console.log(chalk.red('\n❌ Installation cancelled'));
|
||||||
|
console.log(chalk.dim('You must manually rename the "_cfg" folder to "_config" before proceeding.'));
|
||||||
|
return { success: false, cancelled: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the rename
|
||||||
|
spinner.start('Renaming configuration folder...');
|
||||||
|
try {
|
||||||
|
const oldCfgPath = path.join(bmadDir, '_cfg');
|
||||||
|
const newCfgPath = path.join(bmadDir, '_config');
|
||||||
|
await fs.move(oldCfgPath, newCfgPath);
|
||||||
|
spinner.succeed('Configuration folder renamed successfully');
|
||||||
|
} catch (error) {
|
||||||
|
spinner.fail('Failed to rename configuration folder');
|
||||||
|
console.error(chalk.red(`Error: ${error.message}`));
|
||||||
|
return { success: false, error: error.message };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check existing installation
|
// Check existing installation
|
||||||
spinner.text = 'Checking for existing installation...';
|
spinner.text = 'Checking for existing installation...';
|
||||||
const existingInstall = await this.detector.detect(bmadDir);
|
const existingInstall = await this.detector.detect(bmadDir);
|
||||||
@ -834,8 +893,11 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
customInfo = config._customModuleSources.get(moduleName);
|
customInfo = config._customModuleSources.get(moduleName);
|
||||||
isCustomModule = true;
|
isCustomModule = true;
|
||||||
|
|
||||||
// Check if this is a cached module (source path starts with _cfg)
|
// Check if this is a cached module (source path starts with _config)
|
||||||
if (customInfo.sourcePath && (customInfo.sourcePath.startsWith('_cfg') || customInfo.sourcePath.includes('_cfg/custom'))) {
|
if (
|
||||||
|
customInfo.sourcePath &&
|
||||||
|
(customInfo.sourcePath.startsWith('_config') || customInfo.sourcePath.includes('_config/custom'))
|
||||||
|
) {
|
||||||
useCache = true;
|
useCache = true;
|
||||||
// Make sure we have the right path structure
|
// Make sure we have the right path structure
|
||||||
if (!customInfo.path) {
|
if (!customInfo.path) {
|
||||||
@ -939,9 +1001,9 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
if (finalCustomContent && finalCustomContent.cachedModules) {
|
if (finalCustomContent && finalCustomContent.cachedModules) {
|
||||||
sourcePath = finalCustomContent.cachedModules.find((m) => m.id === moduleName)?.relativePath;
|
sourcePath = finalCustomContent.cachedModules.find((m) => m.id === moduleName)?.relativePath;
|
||||||
} else {
|
} else {
|
||||||
// During update, the sourcePath is already cache-relative if it starts with _cfg
|
// During update, the sourcePath is already cache-relative if it starts with _config
|
||||||
sourcePath =
|
sourcePath =
|
||||||
customInfo.sourcePath && customInfo.sourcePath.startsWith('_cfg')
|
customInfo.sourcePath && customInfo.sourcePath.startsWith('_config')
|
||||||
? customInfo.sourcePath
|
? customInfo.sourcePath
|
||||||
: path.relative(bmadDir, customInfo.path || customInfo.sourcePath);
|
: path.relative(bmadDir, customInfo.path || customInfo.sourcePath);
|
||||||
}
|
}
|
||||||
@ -1061,7 +1123,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
// Customize templates are now created in processAgentFiles when building YAML agents
|
// Customize templates are now created in processAgentFiles when building YAML agents
|
||||||
|
|
||||||
// Pre-register manifest files that will be created (except files-manifest.csv to avoid recursion)
|
// Pre-register manifest files that will be created (except files-manifest.csv to avoid recursion)
|
||||||
const cfgDir = path.join(bmadDir, '_cfg');
|
const cfgDir = path.join(bmadDir, '_config');
|
||||||
this.installedFiles.push(
|
this.installedFiles.push(
|
||||||
path.join(cfgDir, 'manifest.yaml'),
|
path.join(cfgDir, 'manifest.yaml'),
|
||||||
path.join(cfgDir, 'workflow-manifest.csv'),
|
path.join(cfgDir, 'workflow-manifest.csv'),
|
||||||
@ -1329,7 +1391,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const projectDir = path.resolve(config.directory);
|
const projectDir = path.resolve(config.directory);
|
||||||
const bmadDir = await this.findBmadDir(projectDir);
|
const { bmadDir } = await this.findBmadDir(projectDir);
|
||||||
const existingInstall = await this.detector.detect(bmadDir);
|
const existingInstall = await this.detector.detect(bmadDir);
|
||||||
|
|
||||||
if (!existingInstall.installed) {
|
if (!existingInstall.installed) {
|
||||||
@ -1414,7 +1476,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
*/
|
*/
|
||||||
async getStatus(directory) {
|
async getStatus(directory) {
|
||||||
const projectDir = path.resolve(directory);
|
const projectDir = path.resolve(directory);
|
||||||
const bmadDir = await this.findBmadDir(projectDir);
|
const { bmadDir } = await this.findBmadDir(projectDir);
|
||||||
return await this.detector.detect(bmadDir);
|
return await this.detector.detect(bmadDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1430,7 +1492,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
*/
|
*/
|
||||||
async uninstall(directory) {
|
async uninstall(directory) {
|
||||||
const projectDir = path.resolve(directory);
|
const projectDir = path.resolve(directory);
|
||||||
const bmadDir = await this.findBmadDir(projectDir);
|
const { bmadDir } = await this.findBmadDir(projectDir);
|
||||||
|
|
||||||
if (await fs.pathExists(bmadDir)) {
|
if (await fs.pathExists(bmadDir)) {
|
||||||
await fs.remove(bmadDir);
|
await fs.remove(bmadDir);
|
||||||
@ -1447,9 +1509,9 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
*/
|
*/
|
||||||
async createDirectoryStructure(bmadDir) {
|
async createDirectoryStructure(bmadDir) {
|
||||||
await fs.ensureDir(bmadDir);
|
await fs.ensureDir(bmadDir);
|
||||||
await fs.ensureDir(path.join(bmadDir, '_cfg'));
|
await fs.ensureDir(path.join(bmadDir, '_config'));
|
||||||
await fs.ensureDir(path.join(bmadDir, '_cfg', 'agents'));
|
await fs.ensureDir(path.join(bmadDir, '_config', 'agents'));
|
||||||
await fs.ensureDir(path.join(bmadDir, '_cfg', 'custom'));
|
await fs.ensureDir(path.join(bmadDir, '_config', 'custom'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1466,7 +1528,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
// Get all installed module directories
|
// Get all installed module directories
|
||||||
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
||||||
const installedModules = entries
|
const installedModules = entries
|
||||||
.filter((entry) => entry.isDirectory() && entry.name !== '_cfg' && entry.name !== 'docs')
|
.filter((entry) => entry.isDirectory() && entry.name !== '_config' && entry.name !== 'docs')
|
||||||
.map((entry) => entry.name);
|
.map((entry) => entry.name);
|
||||||
|
|
||||||
// Generate config.yaml for each installed module
|
// Generate config.yaml for each installed module
|
||||||
@ -1826,9 +1888,9 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
// Determine project directory (parent of bmad/ directory)
|
// Determine project directory (parent of bmad/ directory)
|
||||||
const bmadDir = path.dirname(modulePath);
|
const bmadDir = path.dirname(modulePath);
|
||||||
const projectDir = path.dirname(bmadDir);
|
const projectDir = path.dirname(bmadDir);
|
||||||
const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
|
const cfgAgentsDir = path.join(bmadDir, '_config', 'agents');
|
||||||
|
|
||||||
// Ensure _cfg/agents directory exists
|
// Ensure _config/agents directory exists
|
||||||
await fs.ensureDir(cfgAgentsDir);
|
await fs.ensureDir(cfgAgentsDir);
|
||||||
|
|
||||||
// Get all agent files
|
// Get all agent files
|
||||||
@ -1917,7 +1979,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
*/
|
*/
|
||||||
async buildStandaloneAgents(bmadDir, projectDir) {
|
async buildStandaloneAgents(bmadDir, projectDir) {
|
||||||
const standaloneAgentsPath = path.join(bmadDir, 'agents');
|
const standaloneAgentsPath = path.join(bmadDir, 'agents');
|
||||||
const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
|
const cfgAgentsDir = path.join(bmadDir, '_config', 'agents');
|
||||||
|
|
||||||
// Check if standalone agents directory exists
|
// Check if standalone agents directory exists
|
||||||
if (!(await fs.pathExists(standaloneAgentsPath))) {
|
if (!(await fs.pathExists(standaloneAgentsPath))) {
|
||||||
@ -2018,7 +2080,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
// Determine project directory (parent of bmad/ directory)
|
// Determine project directory (parent of bmad/ directory)
|
||||||
const bmadDir = path.dirname(modulePath);
|
const bmadDir = path.dirname(modulePath);
|
||||||
const projectDir = path.dirname(bmadDir);
|
const projectDir = path.dirname(bmadDir);
|
||||||
const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
|
const cfgAgentsDir = path.join(bmadDir, '_config', 'agents');
|
||||||
const targetAgentsPath = path.join(modulePath, 'agents');
|
const targetAgentsPath = path.join(modulePath, 'agents');
|
||||||
|
|
||||||
// Ensure target directory exists
|
// Ensure target directory exists
|
||||||
@ -2143,7 +2205,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
async compileAgents(config) {
|
async compileAgents(config) {
|
||||||
try {
|
try {
|
||||||
const projectDir = path.resolve(config.directory);
|
const projectDir = path.resolve(config.directory);
|
||||||
const bmadDir = await this.findBmadDir(projectDir);
|
const { bmadDir } = await this.findBmadDir(projectDir);
|
||||||
|
|
||||||
// Check if bmad directory exists
|
// Check if bmad directory exists
|
||||||
if (!(await fs.pathExists(bmadDir))) {
|
if (!(await fs.pathExists(bmadDir))) {
|
||||||
@ -2151,7 +2213,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get installed modules from manifest
|
// Get installed modules from manifest
|
||||||
const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml');
|
const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
|
||||||
let installedModules = [];
|
let installedModules = [];
|
||||||
let manifest = null;
|
let manifest = null;
|
||||||
if (await fs.pathExists(manifestPath)) {
|
if (await fs.pathExists(manifestPath)) {
|
||||||
@ -2181,7 +2243,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
||||||
|
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory() && entry.name !== '_cfg' && entry.name !== 'docs') {
|
if (entry.isDirectory() && entry.name !== '_config' && entry.name !== 'docs') {
|
||||||
const modulePath = path.join(bmadDir, entry.name);
|
const modulePath = path.join(bmadDir, entry.name);
|
||||||
|
|
||||||
// Special handling for standalone agents in bmad/agents/ directory
|
// Special handling for standalone agents in bmad/agents/ directory
|
||||||
@ -2264,7 +2326,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const projectDir = path.resolve(config.directory);
|
const projectDir = path.resolve(config.directory);
|
||||||
const bmadDir = await this.findBmadDir(projectDir);
|
const { bmadDir } = await this.findBmadDir(projectDir);
|
||||||
|
|
||||||
// Check if bmad directory exists
|
// Check if bmad directory exists
|
||||||
if (!(await fs.pathExists(bmadDir))) {
|
if (!(await fs.pathExists(bmadDir))) {
|
||||||
@ -2287,8 +2349,8 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
// Ensure we have an absolute sourcePath
|
// Ensure we have an absolute sourcePath
|
||||||
let absoluteSourcePath = customModule.sourcePath;
|
let absoluteSourcePath = customModule.sourcePath;
|
||||||
|
|
||||||
// Check if sourcePath is a cache-relative path (starts with _cfg/)
|
// Check if sourcePath is a cache-relative path (starts with _config/)
|
||||||
if (absoluteSourcePath && absoluteSourcePath.startsWith('_cfg')) {
|
if (absoluteSourcePath && absoluteSourcePath.startsWith('_config')) {
|
||||||
// Convert cache-relative path to absolute path
|
// Convert cache-relative path to absolute path
|
||||||
absoluteSourcePath = path.join(bmadDir, absoluteSourcePath);
|
absoluteSourcePath = path.join(bmadDir, absoluteSourcePath);
|
||||||
}
|
}
|
||||||
@ -2695,7 +2757,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
* @returns {Array} Array of file entries from files-manifest.csv
|
* @returns {Array} Array of file entries from files-manifest.csv
|
||||||
*/
|
*/
|
||||||
async readFilesManifest(bmadDir) {
|
async readFilesManifest(bmadDir) {
|
||||||
const filesManifestPath = path.join(bmadDir, '_cfg', 'files-manifest.csv');
|
const filesManifestPath = path.join(bmadDir, '_config', 'files-manifest.csv');
|
||||||
if (!(await fs.pathExists(filesManifestPath))) {
|
if (!(await fs.pathExists(filesManifestPath))) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -2798,12 +2860,12 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
const relativePath = path.relative(bmadDir, fullPath);
|
const relativePath = path.relative(bmadDir, fullPath);
|
||||||
const fileName = path.basename(fullPath);
|
const fileName = path.basename(fullPath);
|
||||||
|
|
||||||
// Skip _cfg directory EXCEPT for modified agent customizations
|
// Skip _config directory EXCEPT for modified agent customizations
|
||||||
if (relativePath.startsWith('_cfg/') || relativePath.startsWith('_cfg\\')) {
|
if (relativePath.startsWith('_config/') || relativePath.startsWith('_config\\')) {
|
||||||
// Special handling for .customize.yaml files - only preserve if modified
|
// Special handling for .customize.yaml files - only preserve if modified
|
||||||
if (relativePath.includes('/agents/') && fileName.endsWith('.customize.yaml')) {
|
if (relativePath.includes('/agents/') && fileName.endsWith('.customize.yaml')) {
|
||||||
// Check if the customization file has been modified from manifest
|
// Check if the customization file has been modified from manifest
|
||||||
const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml');
|
const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
|
||||||
if (await fs.pathExists(manifestPath)) {
|
if (await fs.pathExists(manifestPath)) {
|
||||||
const crypto = require('node:crypto');
|
const crypto = require('node:crypto');
|
||||||
const currentContent = await fs.readFile(fullPath, 'utf8');
|
const currentContent = await fs.readFile(fullPath, 'utf8');
|
||||||
@ -2824,7 +2886,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Skip config.yaml files - these are regenerated on each install/update
|
// Skip config.yaml files - these are regenerated on each install/update
|
||||||
// Users should use _cfg/agents/ override files instead
|
// Users should use _config/agents/ override files instead
|
||||||
if (fileName === 'config.yaml') {
|
if (fileName === 'config.yaml') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -2832,8 +2894,8 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
if (!fileInfo) {
|
if (!fileInfo) {
|
||||||
// File not in manifest = custom file
|
// File not in manifest = custom file
|
||||||
// EXCEPT: Agent .md files in module folders are generated files, not custom
|
// EXCEPT: Agent .md files in module folders are generated files, not custom
|
||||||
// Only treat .md files under _cfg/agents/ as custom
|
// Only treat .md files under _config/agents/ as custom
|
||||||
if (!(fileName.endsWith('.md') && relativePath.includes('/agents/') && !relativePath.startsWith('_cfg/'))) {
|
if (!(fileName.endsWith('.md') && relativePath.includes('/agents/') && !relativePath.startsWith('_config/'))) {
|
||||||
customFiles.push(fullPath);
|
customFiles.push(fullPath);
|
||||||
}
|
}
|
||||||
} else if (manifestHasHashes && fileInfo.hash) {
|
} else if (manifestHasHashes && fileInfo.hash) {
|
||||||
@ -2866,7 +2928,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
* @param {Object} userInfo - User information including name and language
|
* @param {Object} userInfo - User information including name and language
|
||||||
*/
|
*/
|
||||||
async createAgentConfigs(bmadDir, userInfo = null) {
|
async createAgentConfigs(bmadDir, userInfo = null) {
|
||||||
const agentConfigDir = path.join(bmadDir, '_cfg', 'agents');
|
const agentConfigDir = path.join(bmadDir, '_config', 'agents');
|
||||||
await fs.ensureDir(agentConfigDir);
|
await fs.ensureDir(agentConfigDir);
|
||||||
|
|
||||||
// Get all agents from all modules
|
// Get all agents from all modules
|
||||||
@ -2876,7 +2938,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
// Check modules for agents (including core)
|
// Check modules for agents (including core)
|
||||||
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory() && entry.name !== '_cfg') {
|
if (entry.isDirectory() && entry.name !== '_config') {
|
||||||
const moduleAgentsPath = path.join(bmadDir, entry.name, 'agents');
|
const moduleAgentsPath = path.join(bmadDir, entry.name, 'agents');
|
||||||
if (await fs.pathExists(moduleAgentsPath)) {
|
if (await fs.pathExists(moduleAgentsPath)) {
|
||||||
const agentFiles = await fs.readdir(moduleAgentsPath);
|
const agentFiles = await fs.readdir(moduleAgentsPath);
|
||||||
@ -2994,7 +3056,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
|
|||||||
* @param {Array} agentDetails - Array of agent details
|
* @param {Array} agentDetails - Array of agent details
|
||||||
*/
|
*/
|
||||||
async generateAgentManifest(bmadDir, agentDetails) {
|
async generateAgentManifest(bmadDir, agentDetails) {
|
||||||
const manifestPath = path.join(bmadDir, '_cfg', 'agent-manifest.csv');
|
const manifestPath = path.join(bmadDir, '_config', 'agent-manifest.csv');
|
||||||
await AgentPartyGenerator.writeAgentParty(manifestPath, agentDetails, { forWeb: false });
|
await AgentPartyGenerator.writeAgentParty(manifestPath, agentDetails, { forWeb: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -28,8 +28,8 @@ class ManifestGenerator {
|
|||||||
* @param {Array} installedFiles - All installed files (optional, for hash tracking)
|
* @param {Array} installedFiles - All installed files (optional, for hash tracking)
|
||||||
*/
|
*/
|
||||||
async generateManifests(bmadDir, selectedModules, installedFiles = [], options = {}) {
|
async generateManifests(bmadDir, selectedModules, installedFiles = [], options = {}) {
|
||||||
// Create _cfg directory if it doesn't exist
|
// Create _config directory if it doesn't exist
|
||||||
const cfgDir = path.join(bmadDir, '_cfg');
|
const cfgDir = path.join(bmadDir, '_config');
|
||||||
await fs.ensureDir(cfgDir);
|
await fs.ensureDir(cfgDir);
|
||||||
|
|
||||||
// Store modules list (all modules including preserved ones)
|
// Store modules list (all modules including preserved ones)
|
||||||
@ -902,7 +902,7 @@ class ManifestGenerator {
|
|||||||
|
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
// Skip if not a directory or is a special directory
|
// Skip if not a directory or is a special directory
|
||||||
if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === '_cfg') {
|
if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === '_config') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,10 +10,10 @@ class Manifest {
|
|||||||
* @param {Array} installedFiles - List of installed files (no longer used, files tracked in files-manifest.csv)
|
* @param {Array} installedFiles - List of installed files (no longer used, files tracked in files-manifest.csv)
|
||||||
*/
|
*/
|
||||||
async create(bmadDir, data, installedFiles = []) {
|
async create(bmadDir, data, installedFiles = []) {
|
||||||
const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml');
|
const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
|
||||||
const yaml = require('yaml');
|
const yaml = require('yaml');
|
||||||
|
|
||||||
// Ensure _cfg directory exists
|
// Ensure _config directory exists
|
||||||
await fs.ensureDir(path.dirname(manifestPath));
|
await fs.ensureDir(path.dirname(manifestPath));
|
||||||
|
|
||||||
// Structure the manifest data
|
// Structure the manifest data
|
||||||
@ -46,7 +46,7 @@ class Manifest {
|
|||||||
* @returns {Object|null} Manifest data or null if not found
|
* @returns {Object|null} Manifest data or null if not found
|
||||||
*/
|
*/
|
||||||
async read(bmadDir) {
|
async read(bmadDir) {
|
||||||
const yamlPath = path.join(bmadDir, '_cfg', 'manifest.yaml');
|
const yamlPath = path.join(bmadDir, '_config', 'manifest.yaml');
|
||||||
const yaml = require('yaml');
|
const yaml = require('yaml');
|
||||||
|
|
||||||
if (await fs.pathExists(yamlPath)) {
|
if (await fs.pathExists(yamlPath)) {
|
||||||
@ -97,7 +97,7 @@ class Manifest {
|
|||||||
ides: manifest.ides || [],
|
ides: manifest.ides || [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml');
|
const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
|
||||||
await fs.ensureDir(path.dirname(manifestPath));
|
await fs.ensureDir(path.dirname(manifestPath));
|
||||||
|
|
||||||
const yamlContent = yaml.stringify(manifestData, {
|
const yamlContent = yaml.stringify(manifestData, {
|
||||||
|
|||||||
@ -306,7 +306,7 @@ class CustomHandler {
|
|||||||
const targetMdPath = path.join(targetDir, `${agentName}.md`);
|
const targetMdPath = path.join(targetDir, `${agentName}.md`);
|
||||||
// Use the actual bmadDir if available (for when installing to temp dir)
|
// Use the actual bmadDir if available (for when installing to temp dir)
|
||||||
const actualBmadDir = config._bmadDir || bmadDir;
|
const actualBmadDir = config._bmadDir || bmadDir;
|
||||||
const customizePath = path.join(actualBmadDir, '_cfg', 'agents', `custom-${agentName}.customize.yaml`);
|
const customizePath = path.join(actualBmadDir, '_config', 'agents', `custom-${agentName}.customize.yaml`);
|
||||||
|
|
||||||
// Read and compile the YAML
|
// Read and compile the YAML
|
||||||
try {
|
try {
|
||||||
|
|||||||
@ -136,7 +136,7 @@ class BaseIdeSetup {
|
|||||||
// Get module agents
|
// Get module agents
|
||||||
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg' && entry.name !== 'agents') {
|
if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config' && entry.name !== 'agents') {
|
||||||
const moduleAgentsPath = path.join(bmadDir, entry.name, 'agents');
|
const moduleAgentsPath = path.join(bmadDir, entry.name, 'agents');
|
||||||
if (await fs.pathExists(moduleAgentsPath)) {
|
if (await fs.pathExists(moduleAgentsPath)) {
|
||||||
const moduleAgents = await this.scanDirectory(moduleAgentsPath, '.md');
|
const moduleAgents = await this.scanDirectory(moduleAgentsPath, '.md');
|
||||||
@ -208,7 +208,7 @@ class BaseIdeSetup {
|
|||||||
// Get module tasks
|
// Get module tasks
|
||||||
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg' && entry.name !== 'agents') {
|
if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config' && entry.name !== 'agents') {
|
||||||
const moduleTasksPath = path.join(bmadDir, entry.name, 'tasks');
|
const moduleTasksPath = path.join(bmadDir, entry.name, 'tasks');
|
||||||
if (await fs.pathExists(moduleTasksPath)) {
|
if (await fs.pathExists(moduleTasksPath)) {
|
||||||
const moduleTasks = await this.scanDirectoryWithStandalone(moduleTasksPath, ['.md', '.xml']);
|
const moduleTasks = await this.scanDirectoryWithStandalone(moduleTasksPath, ['.md', '.xml']);
|
||||||
@ -254,7 +254,7 @@ class BaseIdeSetup {
|
|||||||
// Get module tools
|
// Get module tools
|
||||||
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg' && entry.name !== 'agents') {
|
if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config' && entry.name !== 'agents') {
|
||||||
const moduleToolsPath = path.join(bmadDir, entry.name, 'tools');
|
const moduleToolsPath = path.join(bmadDir, entry.name, 'tools');
|
||||||
if (await fs.pathExists(moduleToolsPath)) {
|
if (await fs.pathExists(moduleToolsPath)) {
|
||||||
const moduleTools = await this.scanDirectoryWithStandalone(moduleToolsPath, ['.md', '.xml']);
|
const moduleTools = await this.scanDirectoryWithStandalone(moduleToolsPath, ['.md', '.xml']);
|
||||||
@ -300,7 +300,7 @@ class BaseIdeSetup {
|
|||||||
// Get module workflows
|
// Get module workflows
|
||||||
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg' && entry.name !== 'agents') {
|
if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config' && entry.name !== 'agents') {
|
||||||
const moduleWorkflowsPath = path.join(bmadDir, entry.name, 'workflows');
|
const moduleWorkflowsPath = path.join(bmadDir, entry.name, 'workflows');
|
||||||
if (await fs.pathExists(moduleWorkflowsPath)) {
|
if (await fs.pathExists(moduleWorkflowsPath)) {
|
||||||
const moduleWorkflows = await this.findWorkflowYamlFiles(moduleWorkflowsPath);
|
const moduleWorkflows = await this.findWorkflowYamlFiles(moduleWorkflowsPath);
|
||||||
@ -635,7 +635,7 @@ class BaseIdeSetup {
|
|||||||
* @param {Object} agent - Agent information
|
* @param {Object} agent - Agent information
|
||||||
*/
|
*/
|
||||||
async createAgentConfig(bmadDir, agent) {
|
async createAgentConfig(bmadDir, agent) {
|
||||||
const agentConfigDir = path.join(bmadDir, '_cfg', 'agents');
|
const agentConfigDir = path.join(bmadDir, '_config', 'agents');
|
||||||
await this.ensureDir(agentConfigDir);
|
await this.ensureDir(agentConfigDir);
|
||||||
|
|
||||||
// Load agent config template
|
// Load agent config template
|
||||||
|
|||||||
@ -85,7 +85,7 @@ Follow all instructions in the ${type} file exactly as written.
|
|||||||
* Load task manifest CSV
|
* Load task manifest CSV
|
||||||
*/
|
*/
|
||||||
async loadTaskManifest(bmadDir) {
|
async loadTaskManifest(bmadDir) {
|
||||||
const manifestPath = path.join(bmadDir, '_cfg', 'task-manifest.csv');
|
const manifestPath = path.join(bmadDir, '_config', 'task-manifest.csv');
|
||||||
|
|
||||||
if (!(await fs.pathExists(manifestPath))) {
|
if (!(await fs.pathExists(manifestPath))) {
|
||||||
return null;
|
return null;
|
||||||
@ -102,7 +102,7 @@ Follow all instructions in the ${type} file exactly as written.
|
|||||||
* Load tool manifest CSV
|
* Load tool manifest CSV
|
||||||
*/
|
*/
|
||||||
async loadToolManifest(bmadDir) {
|
async loadToolManifest(bmadDir) {
|
||||||
const manifestPath = path.join(bmadDir, '_cfg', 'tool-manifest.csv');
|
const manifestPath = path.join(bmadDir, '_config', 'tool-manifest.csv');
|
||||||
|
|
||||||
if (!(await fs.pathExists(manifestPath))) {
|
if (!(await fs.pathExists(manifestPath))) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -224,7 +224,7 @@ When running any workflow:
|
|||||||
}
|
}
|
||||||
|
|
||||||
async loadWorkflowManifest(bmadDir) {
|
async loadWorkflowManifest(bmadDir) {
|
||||||
const manifestPath = path.join(bmadDir, '_cfg', 'workflow-manifest.csv');
|
const manifestPath = path.join(bmadDir, '_config', 'workflow-manifest.csv');
|
||||||
|
|
||||||
if (!(await fs.pathExists(manifestPath))) {
|
if (!(await fs.pathExists(manifestPath))) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@ -242,15 +242,15 @@ class ModuleManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Also check for cached custom modules in _cfg/custom/
|
// Also check for cached custom modules in _config/custom/
|
||||||
if (this.bmadDir) {
|
if (this.bmadDir) {
|
||||||
const customCacheDir = path.join(this.bmadDir, '_cfg', 'custom');
|
const customCacheDir = path.join(this.bmadDir, '_config', 'custom');
|
||||||
if (await fs.pathExists(customCacheDir)) {
|
if (await fs.pathExists(customCacheDir)) {
|
||||||
const cacheEntries = await fs.readdir(customCacheDir, { withFileTypes: true });
|
const cacheEntries = await fs.readdir(customCacheDir, { withFileTypes: true });
|
||||||
for (const entry of cacheEntries) {
|
for (const entry of cacheEntries) {
|
||||||
if (entry.isDirectory()) {
|
if (entry.isDirectory()) {
|
||||||
const cachePath = path.join(customCacheDir, entry.name);
|
const cachePath = path.join(customCacheDir, entry.name);
|
||||||
const moduleInfo = await this.getModuleInfo(cachePath, entry.name, '_cfg/custom');
|
const moduleInfo = await this.getModuleInfo(cachePath, entry.name, '_config/custom');
|
||||||
if (moduleInfo && !modules.some((m) => m.id === moduleInfo.id) && !customModules.some((m) => m.id === moduleInfo.id)) {
|
if (moduleInfo && !modules.some((m) => m.id === moduleInfo.id) && !customModules.some((m) => m.id === moduleInfo.id)) {
|
||||||
moduleInfo.isCustom = true;
|
moduleInfo.isCustom = true;
|
||||||
moduleInfo.fromCache = true;
|
moduleInfo.fromCache = true;
|
||||||
@ -785,7 +785,7 @@ class ModuleManager {
|
|||||||
async compileModuleAgents(sourcePath, targetPath, moduleName, bmadDir) {
|
async compileModuleAgents(sourcePath, targetPath, moduleName, bmadDir) {
|
||||||
const sourceAgentsPath = path.join(sourcePath, 'agents');
|
const sourceAgentsPath = path.join(sourcePath, 'agents');
|
||||||
const targetAgentsPath = path.join(targetPath, 'agents');
|
const targetAgentsPath = path.join(targetPath, 'agents');
|
||||||
const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
|
const cfgAgentsDir = path.join(bmadDir, '_config', 'agents');
|
||||||
|
|
||||||
// Check if agents directory exists in source
|
// Check if agents directory exists in source
|
||||||
if (!(await fs.pathExists(sourceAgentsPath))) {
|
if (!(await fs.pathExists(sourceAgentsPath))) {
|
||||||
@ -827,7 +827,7 @@ class ModuleManager {
|
|||||||
const originalHash = crypto.createHash('sha256').update(customizeContent).digest('hex');
|
const originalHash = crypto.createHash('sha256').update(customizeContent).digest('hex');
|
||||||
|
|
||||||
// Store in main manifest
|
// Store in main manifest
|
||||||
const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml');
|
const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
|
||||||
let manifestData = {};
|
let manifestData = {};
|
||||||
if (await fs.pathExists(manifestPath)) {
|
if (await fs.pathExists(manifestPath)) {
|
||||||
const manifestContent = await fs.readFile(manifestPath, 'utf8');
|
const manifestContent = await fs.readFile(manifestPath, 'utf8');
|
||||||
|
|||||||
@ -29,7 +29,7 @@ const AgentPartyGenerator = {
|
|||||||
let xmlContent = `<!-- Powered by BMAD-CORE™ -->
|
let xmlContent = `<!-- Powered by BMAD-CORE™ -->
|
||||||
<!-- Agent Manifest - Generated during BMAD ${forWeb ? 'bundling' : 'installation'} -->
|
<!-- Agent Manifest - Generated during BMAD ${forWeb ? 'bundling' : 'installation'} -->
|
||||||
<!-- This file contains a summary of all ${forWeb ? 'bundled' : 'installed'} agents for quick reference -->
|
<!-- This file contains a summary of all ${forWeb ? 'bundled' : 'installed'} agents for quick reference -->
|
||||||
<manifest id="bmad/_cfg/agent-manifest.csv" version="1.0" generated="${new Date().toISOString()}">
|
<manifest id="bmad/_config/agent-manifest.csv" version="1.0" generated="${new Date().toISOString()}">
|
||||||
<description>
|
<description>
|
||||||
Complete roster of ${forWeb ? 'bundled' : 'installed'} BMAD agents with summarized personas for efficient multi-agent orchestration.
|
Complete roster of ${forWeb ? 'bundled' : 'installed'} BMAD agents with summarized personas for efficient multi-agent orchestration.
|
||||||
Used by party-mode and other multi-agent coordination features.
|
Used by party-mode and other multi-agent coordination features.
|
||||||
|
|||||||
@ -410,7 +410,7 @@ function detectBmadProject(targetPath) {
|
|||||||
const possibleNames = ['_bmad'];
|
const possibleNames = ['_bmad'];
|
||||||
for (const name of possibleNames) {
|
for (const name of possibleNames) {
|
||||||
const bmadFolder = path.join(checkPath, name);
|
const bmadFolder = path.join(checkPath, name);
|
||||||
const cfgFolder = path.join(bmadFolder, '_cfg');
|
const cfgFolder = path.join(bmadFolder, '_config');
|
||||||
const manifestFile = path.join(cfgFolder, 'agent-manifest.csv');
|
const manifestFile = path.join(cfgFolder, 'agent-manifest.csv');
|
||||||
|
|
||||||
if (fs.existsSync(manifestFile)) {
|
if (fs.existsSync(manifestFile)) {
|
||||||
@ -596,16 +596,16 @@ function addToManifest(manifestFile, agentData) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save agent source YAML to _cfg/custom/agents/ for reinstallation
|
* Save agent source YAML to _config/custom/agents/ for reinstallation
|
||||||
* Stores user answers in a top-level saved_answers section (cleaner than overwriting defaults)
|
* Stores user answers in a top-level saved_answers section (cleaner than overwriting defaults)
|
||||||
* @param {Object} agentInfo - Agent info (path, type, etc.)
|
* @param {Object} agentInfo - Agent info (path, type, etc.)
|
||||||
* @param {string} cfgFolder - Path to _cfg folder
|
* @param {string} cfgFolder - Path to _config folder
|
||||||
* @param {string} agentName - Final agent name (e.g., "fred-commit-poet")
|
* @param {string} agentName - Final agent name (e.g., "fred-commit-poet")
|
||||||
* @param {Object} answers - User answers to save for reinstallation
|
* @param {Object} answers - User answers to save for reinstallation
|
||||||
* @returns {Object} Info about saved source
|
* @returns {Object} Info about saved source
|
||||||
*/
|
*/
|
||||||
function saveAgentSource(agentInfo, cfgFolder, agentName, answers = {}) {
|
function saveAgentSource(agentInfo, cfgFolder, agentName, answers = {}) {
|
||||||
// Save to _cfg/custom/agents/ instead of _cfg/agents/
|
// Save to _config/custom/agents/ instead of _config/agents/
|
||||||
const customAgentsCfgDir = path.join(cfgFolder, 'custom', 'agents');
|
const customAgentsCfgDir = path.join(cfgFolder, 'custom', 'agents');
|
||||||
|
|
||||||
if (!fs.existsSync(customAgentsCfgDir)) {
|
if (!fs.existsSync(customAgentsCfgDir)) {
|
||||||
@ -689,7 +689,7 @@ function saveAgentSource(agentInfo, cfgFolder, agentName, answers = {}) {
|
|||||||
*/
|
*/
|
||||||
async function createIdeSlashCommands(projectRoot, agentName, agentPath, metadata) {
|
async function createIdeSlashCommands(projectRoot, agentName, agentPath, metadata) {
|
||||||
// Read manifest.yaml to get installed IDEs
|
// Read manifest.yaml to get installed IDEs
|
||||||
const manifestPath = path.join(projectRoot, '_bmad', '_cfg', 'manifest.yaml');
|
const manifestPath = path.join(projectRoot, '_bmad', '_config', 'manifest.yaml');
|
||||||
let installedIdes = ['claude-code']; // Default to Claude Code if no manifest
|
let installedIdes = ['claude-code']; // Default to Claude Code if no manifest
|
||||||
|
|
||||||
if (fs.existsSync(manifestPath)) {
|
if (fs.existsSync(manifestPath)) {
|
||||||
|
|||||||
@ -650,11 +650,11 @@ class UI {
|
|||||||
if (stats.isDirectory()) {
|
if (stats.isDirectory()) {
|
||||||
const files = await fs.readdir(directory);
|
const files = await fs.readdir(directory);
|
||||||
if (files.length > 0) {
|
if (files.length > 0) {
|
||||||
// Check for any bmad installation (any folder with _cfg/manifest.yaml)
|
// Check for any bmad installation (any folder with _config/manifest.yaml)
|
||||||
const { Installer } = require('../installers/lib/core/installer');
|
const { Installer } = require('../installers/lib/core/installer');
|
||||||
const installer = new Installer();
|
const installer = new Installer();
|
||||||
const bmadDir = await installer.findBmadDir(directory);
|
const bmadDir = await installer.findBmadDir(directory);
|
||||||
const hasBmadInstall = (await fs.pathExists(bmadDir)) && (await fs.pathExists(path.join(bmadDir, '_cfg', 'manifest.yaml')));
|
const hasBmadInstall = (await fs.pathExists(bmadDir)) && (await fs.pathExists(path.join(bmadDir, '_config', 'manifest.yaml')));
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
chalk.gray(`Directory exists and contains ${files.length} item(s)`) +
|
chalk.gray(`Directory exists and contains ${files.length} item(s)`) +
|
||||||
|
|||||||
@ -525,7 +525,7 @@ class YamlXmlBuilder {
|
|||||||
} else if (bmadIndex !== -1 && pathParts[bmadIndex + 1]) {
|
} else if (bmadIndex !== -1 && pathParts[bmadIndex + 1]) {
|
||||||
// Path contains /bmad/{module}/
|
// Path contains /bmad/{module}/
|
||||||
const potentialModule = pathParts[bmadIndex + 1];
|
const potentialModule = pathParts[bmadIndex + 1];
|
||||||
// Check if it's a known module, not 'agents' or '_cfg'
|
// Check if it's a known module, not 'agents' or '_config'
|
||||||
if (['bmm', 'bmb', 'cis', 'core'].includes(potentialModule)) {
|
if (['bmm', 'bmb', 'cis', 'core'].includes(potentialModule)) {
|
||||||
module = potentialModule;
|
module = potentialModule;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,7 +95,7 @@ async function migrate(directory) {
|
|||||||
console.log(chalk.dim(`Project: ${projectRoot}`));
|
console.log(chalk.dim(`Project: ${projectRoot}`));
|
||||||
console.log(chalk.dim(`BMAD Directory: ${bmadDir}`));
|
console.log(chalk.dim(`BMAD Directory: ${bmadDir}`));
|
||||||
|
|
||||||
const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml');
|
const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml');
|
||||||
|
|
||||||
if (!fs.existsSync(manifestPath)) {
|
if (!fs.existsSync(manifestPath)) {
|
||||||
console.error(chalk.red('✗ No manifest.yaml found'));
|
console.error(chalk.red('✗ No manifest.yaml found'));
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user