Merge branch 'bmad-code-org:main' into kiro-cli-installer

This commit is contained in:
Philip Louw 2025-11-27 07:50:10 +02:00 committed by GitHub
commit 31fff7af6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 1587 additions and 1929 deletions

54
package-lock.json generated
View File

@ -1023,9 +1023,9 @@
}
},
"node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"version": "3.14.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -1329,9 +1329,9 @@
}
},
"node_modules/@jest/reporters/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"dev": true,
"license": "ISC",
"dependencies": {
@ -2618,9 +2618,9 @@
}
},
"node_modules/c8/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"dev": true,
"license": "ISC",
"dependencies": {
@ -4103,14 +4103,14 @@
}
},
"node_modules/glob": {
"version": "11.0.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.3.tgz",
"integrity": "sha512-2Nim7dha1KVkaiF4q6Dj+ngPPMdfvLJEOpZk/jKiUAkqKebpGAWQXAq9z1xu9HKu5lWfqw/FASuccEjyznjPaA==",
"license": "ISC",
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz",
"integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==",
"license": "BlueOak-1.0.0",
"dependencies": {
"foreground-child": "^3.3.1",
"jackspeak": "^4.1.1",
"minimatch": "^10.0.3",
"minimatch": "^10.1.1",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
@ -4139,10 +4139,10 @@
}
},
"node_modules/glob/node_modules/minimatch": {
"version": "10.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz",
"integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==",
"license": "ISC",
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz",
"integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/brace-expansion": "^5.0.0"
},
@ -4808,9 +4808,9 @@
}
},
"node_modules/jest-config/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"dev": true,
"license": "ISC",
"dependencies": {
@ -5181,9 +5181,9 @@
}
},
"node_modules/jest-runtime/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"version": "10.5.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
"integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
"dev": true,
"license": "ISC",
"dependencies": {
@ -5413,9 +5413,9 @@
"license": "MIT"
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
"integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1"

View File

@ -1 +0,0 @@
# BMad Method Master Knowledge Base Index

View File

@ -1,30 +0,0 @@
# Technical Decisions Log
_Auto-updated during discovery and planning sessions - you can also add information here yourself_
## Purpose
This document captures technical decisions, preferences, and constraints discovered during project discussions. It serves as input for architecture.md and solution design documents.
## Confirmed Decisions
<!-- Technical choices explicitly confirmed by the team/user -->
## Preferences
<!-- Non-binding preferences mentioned during discussions -->
## Constraints
<!-- Hard requirements from infrastructure, compliance, or integration needs -->
## To Investigate
<!-- Technical questions that need research or architect input -->
## Notes
- This file is automatically updated when technical information is mentioned
- Decisions here are inputs, not final architecture
- Final technical decisions belong in architecture.md
- Implementation details belong in solutions/\*.md and story context or dev notes.

View File

@ -18,21 +18,25 @@ agent:
- Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`
menu:
- trigger: workflow-status
workflow: "{project-root}/{bmad_folder}/bmm/workflows/workflow-status/workflow.yaml"
description: Get workflow status or initialize a workflow if not already done (optional)
- trigger: brainstorm-project
workflow: "{project-root}/{bmad_folder}/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml"
description: Guided Brainstorming scoped to product development ideation and problem discovery
description: Guided Brainstorming session with final report (optional)
- trigger: research
workflow: "{project-root}/{bmad_folder}/bmm/workflows/1-analysis/research/workflow.yaml"
description: Guided Research scoped to market and competitive analysis of a product or feature
description: Guided Research scoped to market and competitive analysis (optional)
- trigger: product-brief
workflow: "{project-root}/{bmad_folder}/bmm/workflows/1-analysis/product-brief/workflow.yaml"
description: Create a Product Brief, a great input to then drive a PRD
description: Create a Product Brief (recommended input for PRD)
- trigger: document-project
workflow: "{project-root}/{bmad_folder}/bmm/workflows/document-project/workflow.yaml"
description: Generate comprehensive documentation of an existing codebase, including architecture, data flows, and API contracts, and other details to aid project understanding.
description: Document your existing project (optional, but recommended for existing brownfield project efforts)
- trigger: party-mode
workflow: "{project-root}/{bmad_folder}/core/workflows/party-mode/workflow.yaml"

View File

@ -18,25 +18,29 @@ agent:
- Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`
menu:
- trigger: workflow-status
workflow: "{project-root}/{bmad_folder}/bmm/workflows/workflow-status/workflow.yaml"
description: Get workflow status or initialize a workflow if not already done (optional)
- trigger: create-architecture
workflow: "{project-root}/{bmad_folder}/bmm/workflows/3-solutioning/architecture/workflow.yaml"
description: Produce a Scale Adaptive Architecture
description: Create an Architecture Document to Guide Development of a PRD (required for BMad Method projects)
- trigger: validate-architecture
validate-workflow: "{project-root}/{bmad_folder}/bmm/workflows/3-solutioning/architecture/workflow.yaml"
description: Validate Architecture Document
description: Validate Architecture Document (Recommended, use another LLM and fresh context for best results)
- trigger: implementation-readiness
workflow: "{project-root}/{bmad_folder}/bmm/workflows/3-solutioning/implementation-readiness/workflow.yaml"
description: Validate implementation readiness - PRD, UX, Architecture, Epics aligned
description: Validate PRD, UX, Architecture, Epics and stories aligned (Optional but recommended before development)
- trigger: create-excalidraw-diagram
workflow: "{project-root}/{bmad_folder}/bmm/workflows/diagrams/create-diagram/workflow.yaml"
description: Create system architecture or technical diagram (Excalidraw)
description: Create system architecture or technical diagram (Excalidraw) (Use any time you need a diagram)
- trigger: create-excalidraw-dataflow
workflow: "{project-root}/{bmad_folder}/bmm/workflows/diagrams/create-dataflow/workflow.yaml"
description: Create data flow diagram (Excalidraw)
description: Create data flow diagram (Excalidraw) (Use any time you need a diagram)
- trigger: party-mode
workflow: "{project-root}/{bmad_folder}/core/workflows/party-mode/workflow.yaml"

View File

@ -39,10 +39,6 @@ agent:
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/dev-story/workflow.yaml"
description: "Execute Dev Story workflow (full BMM path with sprint-status)"
- trigger: story-done
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/story-done/workflow.yaml"
description: "Mark story done after DoD complete"
- trigger: code-review
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/code-review/workflow.yaml"
description: "Perform a thorough clean context QA code review on a story flagged Ready for Review"
description: "Perform a thorough clean context code review (Highly Recommended, use fresh context and different LLM)"

View File

@ -19,21 +19,25 @@ agent:
- Find if this exists, if it does, always treat it as the bible I plan and execute against: `**/project-context.md`
menu:
- trigger: workflow-status
workflow: "{project-root}/{bmad_folder}/bmm/workflows/workflow-status/workflow.yaml"
description: Get workflow status or initialize a workflow if not already done (optional)
- trigger: create-prd
workflow: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/prd/workflow.yaml"
description: Create Product Requirements Document (PRD)
description: Create Product Requirements Document (PRD) (Required for BMad Method flow)
- trigger: validate-prd
validate-workflow: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/prd/workflow.yaml"
description: Validate PRD
description: Validate PRD (Highly Recommended, use fresh context and different LLM for best results)
- trigger: create-epics-and-stories
workflow: "{project-root}/{bmad_folder}/bmm/workflows/3-solutioning/create-epics-and-stories/workflow.yaml"
description: Create Epics and User Stories from PRD (Its recommended to not do this until the architecture is complete)
description: Create Epics and User Stories from PRD (Required for BMad Method flow AFTER the Architecture is completed)
- trigger: correct-course
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/correct-course/workflow.yaml"
description: Course Correction Analysis
description: Course Correction Analysis (optional during implementation when things go off track)
ide-only: true
- trigger: party-mode

View File

@ -21,15 +21,15 @@ agent:
menu:
- trigger: create-tech-spec
workflow: "{project-root}/{bmad_folder}/bmm/workflows/bmad-quick-flow/create-tech-spec/workflow.yaml"
description: Architect a technical spec with implementation-ready stories
description: Architect a technical spec with implementation-ready stories (Required first step)
- trigger: quick-dev
workflow: "{project-root}/{bmad_folder}/bmm/workflows/bmad-quick-flow/quick-dev/workflow.yaml"
description: Ship features from spec or direct instructions - no handoffs
description: Implement the tech spec end-to-end solo (Core of Quick Flow)
- trigger: code-review
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/code-review/workflow.yaml"
description: Review code for quality, patterns, and acceptance criteria
description: Review code and improve it (Highly Recommended, use fresh context and different LLM for best results)
- trigger: party-mode
workflow: "{project-root}/{bmad_folder}/core/workflows/party-mode/workflow.yaml"

View File

@ -26,24 +26,24 @@ agent:
menu:
- trigger: sprint-planning
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/sprint-planning/workflow.yaml"
description: Generate or update sprint-status.yaml from epic files
description: Generate or re-generate sprint-status.yaml from epic files (Required after Epics+Stories are created)
- trigger: create-story
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/create-story/workflow.yaml"
description: Create a Draft Story
description: Create a Draft Story (Required to prepare stories for development)
- trigger: validate-create-story
validate-workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/create-story/workflow.yaml"
description: (Optional) Validate Story Draft with Independent Review
description: Validate Story Draft (Highly Recommended, use fresh context and different LLM for best results)
- trigger: epic-retrospective
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/retrospective/workflow.yaml"
data: "{project-root}/{bmad_folder}/_cfg/agent-manifest.csv"
description: (Optional) Facilitate team retrospective after an epic is completed
description: Facilitate team retrospective after an epic is completed (Optional)
- trigger: correct-course
workflow: "{project-root}/{bmad_folder}/bmm/workflows/4-implementation/correct-course/workflow.yaml"
description: (Optional) Execute correct-course task
description: Execute correct-course task (When implementation is off-track)
- trigger: party-mode
workflow: "{project-root}/{bmad_folder}/core/workflows/party-mode/workflow.yaml"

View File

@ -25,7 +25,7 @@ agent:
menu:
- trigger: create-ux-design
workflow: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml"
description: Conduct Design Thinking Workshop to Define the User Specification with PRD as input
description: Generate a UX Design and UI Plan from a PRD (Recommended before creating Architecture)
- trigger: validate-design
validate-workflow: "{project-root}/{bmad_folder}/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml"

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

@ -3,7 +3,7 @@
<critical>The workflow execution engine is governed by: {project-root}/{bmad_folder}/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: workflow-init/workflow.yaml</critical>
<critical>Communicate in {communication_language} with {user_name}</critical>
<critical>This workflow handles BOTH new projects AND legacy projects being migrated to BMad Method</critical>
<critical>This workflow handles BOTH new projects AND legacy projects following the BMad Method</critical>
<workflow>
@ -12,7 +12,7 @@
<action>Perform comprehensive scan for existing work:
- BMM artifacts: PRD, tech-spec, epics, architecture, UX, brief, research, brainstorm
- BMM artifacts: PRD, epics, architecture, UX, brief, research, brainstorm
- Implementation: stories, sprint-status, workflow-status
- Codebase: source directories, package files, git repo
- Check both {output_folder} and {sprint_artifacts} locations
@ -53,31 +53,31 @@ Happy building! 🚀</output>
<ask>How would you like to proceed?
a) **Continue** - Work with existing artifacts
b) **Archive & Start Fresh** - Move old work to archive
c) **Express Setup** - I know exactly what I need
d) **Guided Setup** - Walk me through options
1. **Continue** - Work with existing artifacts
2. **Archive & Start Fresh** - Move old work to archive
3. **Express Setup** - I know exactly what I need
4. **Guided Setup** - Walk me through options
Choice [a/b/c/d]:</ask>
Choice [1-4]</ask>
<check if="choice == a">
<check if="choice == 1">
<action>Set continuing_existing = true</action>
<action>Store found artifacts</action>
<action>Continue to step 7 (detect track from artifacts)</action>
</check>
<check if="choice == b">
<check if="choice == 2">
<ask>Archive existing work? (y/n)</ask>
<action if="y">Move artifacts to {output_folder}/archive/</action>
<output>Ready for fresh start!</output>
<action>Continue to step 3</action>
</check>
<check if="choice == c">
<check if="choice == 3">
<action>Jump to step 3 (express path)</action>
</check>
<check if="choice == d">
<check if="choice == 4">
<action>Continue to step 4 (guided path)</action>
</check>
</check>
@ -85,16 +85,16 @@ Choice [a/b/c/d]:</ask>
<check if="state == CLEAN">
<ask>Setup approach:
a) **Express** - I know what I need
b) **Guided** - Show me the options
1. **Express** - I know what I need
2. **Guided** - Show me the options
Choice [a/b]:</ask>
Choice [1 or 2]:</ask>
<check if="choice == a">
<check if="choice == 1">
<action>Continue to step 3 (express)</action>
</check>
<check if="choice == b">
<check if="choice == 2">
<action>Continue to step 4 (guided)</action>
</check>
</check>
@ -102,20 +102,22 @@ Choice [a/b]:</ask>
<step n="3" goal="Express setup path">
<ask>Is this for:
1) **New project** (greenfield)
2) **Existing codebase** (brownfield)
1. **New project** (greenfield)
2. **Existing codebase** (brownfield)
Choice [1/2]:</ask>
<action>Set field_type based on choice</action>
<ask>Planning approach:
1. **Quick Flow** - Minimal planning, fast to code
2. **BMad Method** - Full planning for complex projects
3. **Enterprise Method** - Extended planning with security/DevOps
1. **BMad Method** - Full planning for complex projects
2. **Enterprise Method** - Extended planning with security/DevOps
Choice [1/2/3]:</ask>
<action>Map to selected_track: quick-flow/method/enterprise</action>
Choice [1/2]:</ask>
<action>Map to selected_track: method/enterprise</action>
<output>🚀 **For Quick Flow (minimal planning, straight to code):**
Load the **quick-flow-solo-dev** agent instead - use Quick Flow agent for faster development</output>
<template-output>field_type</template-output>
<template-output>selected_track</template-output>
@ -135,8 +137,8 @@ Choice [1/2/3]:</ask>
<check if="field_type unclear AND codebase exists">
<ask>I see existing code. Are you:
1) **Modifying** existing codebase (brownfield)
2) **Starting fresh** - code is just scaffold (greenfield)
1. **Modifying** existing codebase (brownfield)
2. **Starting fresh** - code is just scaffold (greenfield)
Choice [1/2]:</ask>
<action>Set field_type based on answer</action>
@ -165,44 +167,60 @@ Continue with software workflows? (y/n)</output>
</step>
<step n="5" goal="Guided setup - select track">
<output>Based on your project, here are your planning options:
<output>Based on your project, here are your BMad Method planning options:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
**1. Quick Flow** 🚀
- Minimal planning, straight to code
- Best for: Simple features, bug fixes
- Risk: Potential rework if complexity emerges
**2. BMad Method** 🎯 {{#if recommended}}(RECOMMENDED){{/if}}
**1. BMad Method** 🎯 {{#if recommended}}(RECOMMENDED){{/if}}
- Full planning: PRD + UX + Architecture
- Best for: Products, platforms, complex features
- Benefit: AI agents have complete context for better results
**3. Enterprise Method** 🏢
**2. Enterprise Method** 🏢
- Extended: Method + Security + DevOps + Testing
- Best for: Enterprise, compliance, mission-critical
- Benefit: Comprehensive planning for complex systems
**🚀 For Quick Flow (minimal planning, straight to code):**
Load the **quick-flow-solo-dev** agent instead - use Quick Flow agent for faster development
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{{#if brownfield}}
💡 Architecture creates focused solution design from your codebase, keeping AI agents on track.
{{/if}}</output>
<ask>Which approach fits best?
<ask>Which BMad Method approach fits best?
1. Quick Flow
2. BMad Method {{#if recommended}}(recommended){{/if}}
3. Enterprise Method
4. Help me decide
1. BMad Method {{#if recommended}}(recommended){{/if}}
2. Enterprise Method
3. Help me decide
4. Switch to Quick Flow (use quick-flow-solo-dev agent)
Choice [1/2/3/4]:</ask>
<check if="choice == 4">
<output>🚀 **Switching to Quick Flow!**
Load the **quick-flow-solo-dev** agent instead:
- Start a new chat
- Load the quick-flow-solo-dev agent
- Use Quick Flow for minimal planning and faster development
Quick Flow is perfect for:
- Simple features and bug fixes
- Rapid prototyping
- When you want to get straight to code
Happy coding! 🚀</output>
<action>Exit workflow</action>
</check>
<check if="choice == 3">
<ask>What concerns you about choosing?</ask>
<action>Provide tailored guidance based on concerns</action>
<action>Loop back to choice</action>
@ -215,7 +233,7 @@ Choice [1/2/3/4]:</ask>
<step n="6" goal="Discovery workflows selection (unified)">
<action>Determine available discovery workflows based on:
- field_type (greenfield gets product-brief option)
- selected_track (quick-flow skips product-brief)
- selected_track (method/enterprise options)
</action>
<check if="field_type == greenfield AND selected_track in [method, enterprise]">
@ -229,7 +247,7 @@ Choice [1/2/3/4]:</ask>
Enter numbers (e.g., "1,3" or "all" or "none"): </ask>
</check>
<check if="field_type == brownfield OR selected_track == quick-flow">
<check if="field_type == brownfield AND selected_track in [method, enterprise]">
<output>Optional discovery workflows:</output>
<ask>Include any of these?
@ -250,7 +268,7 @@ Enter numbers (e.g., "1,2" or "none"): </ask>
<template-output>research_requested</template-output>
<template-output>product_brief_requested</template-output>
<check if="brownfield AND selected_track != quick-flow">
<check if="brownfield">
<output>💡 **Note:** For brownfield projects, run document-project workflow first to analyze your codebase.</output>
</check>
</step>
@ -258,18 +276,18 @@ Enter numbers (e.g., "1,2" or "none"): </ask>
<step n="7" goal="Detect track from artifacts" if="continuing_existing OR migrating_legacy">
<action>Analyze artifacts to detect track:
- Has PRD → BMad Method
- Has tech-spec only → Quick Flow
- Has Security/DevOps → Enterprise Method
- Has tech-spec only → Suggest switching to quick-flow-solo-dev agent
</action>
<output>Detected: **{{detected_track}}** based on {{found_artifacts}}</output>
<ask>Correct? (y/n)</ask>
<ask if="n">Which track instead?
<ask if="n">Which BMad Method track instead?
1. Quick Flow
2. BMad Method
3. Enterprise Method
1. BMad Method
2. Enterprise Method
3. Switch to Quick Flow (use quick-flow-solo-dev agent)
Choice:</ask>
@ -298,11 +316,8 @@ Choice:</ask>
{{#if brownfield}}Prerequisites: document-project{{/if}}
{{#if has_discovery}}Discovery: {{list_selected_discovery}}{{/if}}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{{workflow_path_summary}}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</output>
</output>
<ask>Create workflow tracking file? (y/n)</ask>
@ -326,9 +341,6 @@ To check progress: /bmad:bmm:workflows:workflow-status
Happy building! 🚀</output>
</check>
<check if="n">
<output>No problem! Run workflow-init again when ready.</output>
</check>
</step>
</workflow>

View File

@ -37,12 +37,19 @@
<action>Search {output_folder}/ for file: bmm-workflow-status.yaml</action>
<check if="no status file found">
<output>No workflow status found. To get started:
<output>No workflow status found.</output>
<ask>Would you like to run Workflow Init now? (y/n)</ask>
Load analyst agent and run: `workflow-init`
<check if="response == y OR response == yes">
<action>Launching workflow-init to set up your project tracking...</action>
<invoke-workflow path="{project-root}/{bmad_folder}/bmm/workflows/workflow-status/init/workflow.yaml"></invoke-workflow>
<action>Exit workflow and let workflow-init take over</action>
</check>
This will guide you through project setup and create your workflow path.</output>
<action>Exit workflow</action>
<check if="else">
<output>No workflow status file. Run workflow-init when ready to enable progress tracking.</output>
<action>Exit workflow</action>
</check>
</check>
<check if="status file found">

View File

@ -1,67 +0,0 @@
# BMad Quick Flow - Brownfield
# Fast spec-driven development for existing codebases (1-10 stories typically)
method_name: "BMad Quick Flow"
track: "quick-flow"
field_type: "brownfield"
description: "Spec-driven development for brownfield projects - streamlined path with codebase context"
phases:
- prerequisite: true
name: "Documentation"
conditional: "if_undocumented"
note: "NOT a phase - prerequisite for brownfield without docs"
workflows:
- id: "document-project"
required: true
agent: "analyst"
command: "document-project"
output: "Comprehensive project documentation"
purpose: "Generate codebase context for spec engineering"
- phase: 0
name: "Discovery (Optional)"
optional: true
note: "User-selected during workflow-init"
workflows:
- id: "brainstorm-project"
optional: true
agent: "analyst"
command: "brainstorm-project"
included_by: "user_choice"
- id: "research"
optional: true
agent: "analyst"
command: "research"
included_by: "user_choice"
- phase: 1
name: "Spec Engineering"
required: true
workflows:
- id: "create-tech-spec"
required: true
agent: "quick-flow-solo-dev"
command: "create-tech-spec"
output: "Technical Specification with implementation-ready stories"
note: "Stories include codebase context from document-project"
- phase: 2
name: "Implementation"
required: true
note: "Barry executes all stories, optional code-review after each"
workflows:
- id: "dev-spec"
required: true
repeat: true
agent: "quick-flow-solo-dev"
command: "dev-spec"
note: "Execute stories from spec - Barry is the one-man powerhouse"
- id: "code-review"
optional: true
repeat: true
agent: "quick-flow-solo-dev"
command: "code-review"
note: "Review completed story implementation"

View File

@ -1,56 +0,0 @@
# BMad Quick Flow - Greenfield
# Fast spec-driven development path (1-10 stories typically)
method_name: "BMad Quick Flow"
track: "quick-flow"
field_type: "greenfield"
description: "Spec-driven development for greenfield projects - streamlined path without sprint overhead"
phases:
- phase: 0
name: "Discovery (Optional)"
optional: true
note: "User-selected during workflow-init"
workflows:
- id: "brainstorm-project"
optional: true
agent: "analyst"
command: "brainstorm-project"
included_by: "user_choice"
- id: "research"
optional: true
agent: "analyst"
command: "research"
included_by: "user_choice"
note: "Can have multiple research workflows"
- phase: 1
name: "Spec Engineering"
required: true
workflows:
- id: "create-tech-spec"
required: true
agent: "quick-flow-solo-dev"
command: "create-tech-spec"
output: "Technical Specification with implementation-ready stories"
note: "Stories contain all context for execution"
- phase: 2
name: "Implementation"
required: true
note: "Barry executes all stories, optional code-review after each"
workflows:
- id: "dev-spec"
required: true
repeat: true
agent: "quick-flow-solo-dev"
command: "dev-spec"
note: "Execute stories from spec - Barry is the one-man powerhouse"
- id: "code-review"
optional: true
repeat: true
agent: "quick-flow-solo-dev"
command: "code-review"
note: "Review completed story implementation"

View File

@ -0,0 +1,141 @@
const chalk = require('chalk');
const nodePath = require('node:path');
const { Installer } = require('../installers/lib/core/installer');
module.exports = {
command: 'cleanup',
description: 'Clean up obsolete files from BMAD installation',
options: [
['-d, --dry-run', 'Show what would be deleted without actually deleting'],
['-a, --auto-delete', 'Automatically delete non-retained files without prompts'],
['-l, --list-retained', 'List currently retained files'],
['-c, --clear-retained', 'Clear retained files list'],
],
action: async (options) => {
try {
// Create installer and let it find the BMAD directory
const installer = new Installer();
const bmadDir = await installer.findBmadDir(process.cwd());
if (!bmadDir) {
console.error(chalk.red('❌ BMAD installation not found'));
process.exit(1);
}
const retentionPath = nodePath.join(bmadDir, '_cfg', 'user-retained-files.yaml');
// Handle list-retained option
if (options.listRetained) {
const fs = require('fs-extra');
const yaml = require('js-yaml');
if (await fs.pathExists(retentionPath)) {
const retentionContent = await fs.readFile(retentionPath, 'utf8');
const retentionData = yaml.load(retentionContent) || { retainedFiles: [] };
if (retentionData.retainedFiles.length > 0) {
console.log(chalk.cyan('\n📋 Retained Files:\n'));
for (const file of retentionData.retainedFiles) {
console.log(chalk.dim(` - ${file}`));
}
console.log();
} else {
console.log(chalk.yellow('\n✨ No retained files found\n'));
}
} else {
console.log(chalk.yellow('\n✨ No retained files found\n'));
}
return;
}
// Handle clear-retained option
if (options.clearRetained) {
const fs = require('fs-extra');
if (await fs.pathExists(retentionPath)) {
await fs.remove(retentionPath);
console.log(chalk.green('\n✅ Cleared retained files list\n'));
} else {
console.log(chalk.yellow('\n✨ No retained files list to clear\n'));
}
return;
}
// Handle cleanup operations
if (options.dryRun) {
console.log(chalk.cyan('\n🔍 Legacy File Scan (Dry Run)\n'));
const legacyFiles = await installer.scanForLegacyFiles(bmadDir);
const allLegacyFiles = [
...legacyFiles.backup,
...legacyFiles.documentation,
...legacyFiles.deprecated_task,
...legacyFiles.unknown,
];
if (allLegacyFiles.length === 0) {
console.log(chalk.green('✨ No legacy files found\n'));
return;
}
// Group files by category
const categories = [];
if (legacyFiles.backup.length > 0) {
categories.push({ name: 'Backup Files (.bak)', files: legacyFiles.backup });
}
if (legacyFiles.documentation.length > 0) {
categories.push({ name: 'Documentation', files: legacyFiles.documentation });
}
if (legacyFiles.deprecated_task.length > 0) {
categories.push({ name: 'Deprecated Task Files', files: legacyFiles.deprecated_task });
}
if (legacyFiles.unknown.length > 0) {
categories.push({ name: 'Unknown Files', files: legacyFiles.unknown });
}
for (const category of categories) {
console.log(chalk.yellow(`${category.name}:`));
for (const file of category.files) {
const size = (file.size / 1024).toFixed(1);
const date = file.mtime.toLocaleDateString();
let line = ` - ${file.relativePath} (${size}KB, ${date})`;
if (file.suggestedAlternative) {
line += chalk.dim(`${file.suggestedAlternative}`);
}
console.log(chalk.dim(line));
}
console.log();
}
console.log(chalk.cyan(`Found ${allLegacyFiles.length} legacy file(s) that could be cleaned up.\n`));
console.log(chalk.dim('Run "bmad cleanup" to actually delete these files.\n'));
return;
}
// Perform actual cleanup
console.log(chalk.cyan('\n🧹 Cleaning up legacy files...\n'));
const result = await installer.performCleanup(bmadDir, options.autoDelete);
if (result.message) {
console.log(chalk.dim(result.message));
} else {
if (result.deleted > 0) {
console.log(chalk.green(`✅ Deleted ${result.deleted} legacy file(s)`));
}
if (result.retained > 0) {
console.log(chalk.yellow(`⏭️ Retained ${result.retained} file(s)`));
console.log(chalk.dim('Run "bmad cleanup --list-retained" to see retained files\n'));
}
}
console.log();
} catch (error) {
console.error(chalk.red(`❌ Error: ${error.message}`));
process.exit(1);
}
},
};

View File

@ -11,8 +11,8 @@ const kiroGenerator = new KiroCLIGenerator();
module.exports = {
command: 'install',
description: 'Install BMAD Core agents and tools',
options: [],
action: async () => {
options: [['--skip-cleanup', 'Skip automatic cleanup of legacy files']],
action: async (options) => {
try {
const config = await ui.promptInstall();
@ -46,6 +46,11 @@ module.exports = {
config._requestedReinstall = true;
}
// Add skip cleanup flag if option provided
if (options && options.skipCleanup) {
config.skipCleanup = true;
}
// Regular install/update flow
const result = await installer.install(config);

View File

@ -1018,6 +1018,23 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
customFiles: customFiles.length > 0 ? customFiles : undefined,
});
// Offer cleanup for legacy files (only for updates, not fresh installs, and only if not skipped)
if (!config.skipCleanup && config._isUpdate) {
try {
const cleanupResult = await this.performCleanup(bmadDir, false);
if (cleanupResult.deleted > 0) {
console.log(chalk.green(`\n✓ Cleaned up ${cleanupResult.deleted} legacy file${cleanupResult.deleted > 1 ? 's' : ''}`));
}
if (cleanupResult.retained > 0) {
console.log(chalk.dim(`Run 'bmad cleanup' anytime to manage retained files`));
}
} catch (cleanupError) {
// Don't fail the installation for cleanup errors
console.log(chalk.yellow(`\n⚠️ Cleanup warning: ${cleanupError.message}`));
console.log(chalk.dim('Run "bmad cleanup" to manually clean up legacy files'));
}
}
return {
success: true,
path: bmadDir,
@ -1939,7 +1956,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
if (existingBmadFolderName === newBmadFolderName) {
// Normal quick update - start the spinner
spinner.start('Updating BMAD installation...');
console.log(chalk.cyan('Updating BMAD installation...'));
} else {
// Folder name has changed - stop spinner and let install() handle it
spinner.stop();
@ -2578,6 +2595,362 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice:
}
}
}
/**
* Scan for legacy/obsolete files in BMAD installation
* @param {string} bmadDir - BMAD installation directory
* @returns {Object} Categorized files for cleanup
*/
async scanForLegacyFiles(bmadDir) {
const legacyFiles = {
backup: [],
documentation: [],
deprecated_task: [],
unknown: [],
};
try {
// Load files manifest to understand what should exist
const manifestPath = path.join(bmadDir, 'files-manifest.csv');
const manifestFiles = new Set();
if (await fs.pathExists(manifestPath)) {
const manifestContent = await fs.readFile(manifestPath, 'utf8');
const lines = manifestContent.split('\n').slice(1); // Skip header
for (const line of lines) {
if (line.trim()) {
const relativePath = line.split(',')[0];
if (relativePath) {
manifestFiles.add(relativePath);
}
}
}
}
// Scan all files recursively
const allFiles = await this.getAllFiles(bmadDir);
for (const filePath of allFiles) {
const relativePath = path.relative(bmadDir, filePath);
// Skip expected files
if (this.isExpectedFile(relativePath, manifestFiles)) {
continue;
}
// Categorize legacy files
if (relativePath.endsWith('.bak')) {
legacyFiles.backup.push({
path: filePath,
relativePath: relativePath,
size: (await fs.stat(filePath)).size,
mtime: (await fs.stat(filePath)).mtime,
});
} else if (this.isDocumentationFile(relativePath)) {
legacyFiles.documentation.push({
path: filePath,
relativePath: relativePath,
size: (await fs.stat(filePath)).size,
mtime: (await fs.stat(filePath)).mtime,
});
} else if (this.isDeprecatedTaskFile(relativePath)) {
const suggestedAlternative = this.suggestAlternative(relativePath);
legacyFiles.deprecated_task.push({
path: filePath,
relativePath: relativePath,
size: (await fs.stat(filePath)).size,
mtime: (await fs.stat(filePath)).mtime,
suggestedAlternative,
});
} else {
legacyFiles.unknown.push({
path: filePath,
relativePath: relativePath,
size: (await fs.stat(filePath)).size,
mtime: (await fs.stat(filePath)).mtime,
});
}
}
} catch (error) {
console.warn(`Warning: Could not scan for legacy files: ${error.message}`);
}
return legacyFiles;
}
/**
* Get all files in directory recursively
* @param {string} dir - Directory to scan
* @returns {Array} Array of file paths
*/
async getAllFiles(dir) {
const files = [];
async function scan(currentDir) {
const entries = await fs.readdir(currentDir);
for (const entry of entries) {
const fullPath = path.join(currentDir, entry);
const stat = await fs.stat(fullPath);
if (stat.isDirectory()) {
// Skip certain directories
if (!['node_modules', '.git', 'dist', 'build'].includes(entry)) {
await scan(fullPath);
}
} else {
files.push(fullPath);
}
}
}
await scan(dir);
return files;
}
/**
* Check if file is expected in installation
* @param {string} relativePath - Relative path from BMAD dir
* @param {Set} manifestFiles - Files from manifest
* @returns {boolean} True if expected file
*/
isExpectedFile(relativePath, manifestFiles) {
// Core files in manifest
if (manifestFiles.has(relativePath)) {
return true;
}
// Configuration files
if (relativePath.startsWith('_cfg/') || relativePath === 'config.yaml') {
return true;
}
// Custom files
if (relativePath.startsWith('custom/') || relativePath === 'manifest.yaml') {
return true;
}
// Generated files
if (relativePath === 'manifest.csv' || relativePath === 'files-manifest.csv') {
return true;
}
// IDE-specific files
const ides = ['vscode', 'cursor', 'windsurf', 'claude-code', 'github-copilot', 'zsh', 'bash', 'fish'];
if (ides.some((ide) => relativePath.includes(ide))) {
return true;
}
// BMAD MODULE STRUCTURES - recognize valid module content
const modulePrefixes = ['bmb/', 'bmm/', 'cis/', 'core/', 'bmgd/'];
const validExtensions = ['.yaml', '.yml', '.json', '.csv', '.md', '.xml', '.svg', '.png', '.jpg', '.gif', '.excalidraw', '.js'];
// Check if this file is in a recognized module directory
for (const modulePrefix of modulePrefixes) {
if (relativePath.startsWith(modulePrefix)) {
// Check if it has a valid extension
const hasValidExtension = validExtensions.some((ext) => relativePath.endsWith(ext));
if (hasValidExtension) {
return true;
}
}
}
// Special case for core module resources
if (relativePath.startsWith('core/resources/')) {
return true;
}
// Special case for docs directory
if (relativePath.startsWith('docs/')) {
return true;
}
return false;
}
/**
* Check if file is documentation
* @param {string} relativePath - Relative path
* @returns {boolean} True if documentation
*/
isDocumentationFile(relativePath) {
const docExtensions = ['.md', '.txt', '.pdf'];
const docPatterns = ['docs/', 'README', 'CHANGELOG', 'LICENSE'];
return docExtensions.some((ext) => relativePath.endsWith(ext)) || docPatterns.some((pattern) => relativePath.includes(pattern));
}
/**
* Check if file is deprecated task file
* @param {string} relativePath - Relative path
* @returns {boolean} True if deprecated
*/
isDeprecatedTaskFile(relativePath) {
// Known deprecated files
const deprecatedFiles = ['adv-elicit-methods.csv', 'game-resources.json', 'ux-workflow.json'];
return deprecatedFiles.some((dep) => relativePath.includes(dep));
}
/**
* Suggest alternative for deprecated file
* @param {string} relativePath - Deprecated file path
* @returns {string} Suggested alternative
*/
suggestAlternative(relativePath) {
const alternatives = {
'adv-elicit-methods.csv': 'Use the new structured workflows in src/modules/',
'game-resources.json': 'Resources are now integrated into modules',
'ux-workflow.json': 'UX workflows are now in src/modules/bmm/workflows/',
};
for (const [deprecated, alternative] of Object.entries(alternatives)) {
if (relativePath.includes(deprecated)) {
return alternative;
}
}
return 'Check src/modules/ for new alternatives';
}
/**
* Perform interactive cleanup of legacy files
* @param {string} bmadDir - BMAD installation directory
* @param {boolean} skipInteractive - Skip interactive prompts
* @returns {Object} Cleanup results
*/
async performCleanup(bmadDir, skipInteractive = false) {
const inquirer = require('inquirer');
const yaml = require('js-yaml');
// Load user retention preferences
const retentionPath = path.join(bmadDir, '_cfg', 'user-retained-files.yaml');
let retentionData = { retainedFiles: [], history: [] };
if (await fs.pathExists(retentionPath)) {
const retentionContent = await fs.readFile(retentionPath, 'utf8');
retentionData = yaml.load(retentionContent) || retentionData;
}
// Scan for legacy files
const legacyFiles = await this.scanForLegacyFiles(bmadDir);
const allLegacyFiles = [...legacyFiles.backup, ...legacyFiles.documentation, ...legacyFiles.deprecated_task, ...legacyFiles.unknown];
if (allLegacyFiles.length === 0) {
return { deleted: 0, retained: 0, message: 'No legacy files found' };
}
let deletedCount = 0;
let retainedCount = 0;
const filesToDelete = [];
if (skipInteractive) {
// Auto-delete all non-retained files
for (const file of allLegacyFiles) {
if (!retentionData.retainedFiles.includes(file.relativePath)) {
filesToDelete.push(file);
}
}
} else {
// Interactive cleanup
console.log(chalk.cyan('\n🧹 Legacy File Cleanup\n'));
console.log(chalk.dim('The following obsolete files were found:\n'));
// Group files by category
const categories = [];
if (legacyFiles.backup.length > 0) {
categories.push({ name: 'Backup Files (.bak)', files: legacyFiles.backup });
}
if (legacyFiles.documentation.length > 0) {
categories.push({ name: 'Documentation', files: legacyFiles.documentation });
}
if (legacyFiles.deprecated_task.length > 0) {
categories.push({ name: 'Deprecated Task Files', files: legacyFiles.deprecated_task });
}
if (legacyFiles.unknown.length > 0) {
categories.push({ name: 'Unknown Files', files: legacyFiles.unknown });
}
for (const category of categories) {
console.log(chalk.yellow(`${category.name}:`));
for (const file of category.files) {
const size = (file.size / 1024).toFixed(1);
const date = file.mtime.toLocaleDateString();
let line = ` - ${file.relativePath} (${size}KB, ${date})`;
if (file.suggestedAlternative) {
line += chalk.dim(`${file.suggestedAlternative}`);
}
console.log(chalk.dim(line));
}
console.log();
}
const prompt = await inquirer.prompt([
{
type: 'confirm',
name: 'proceed',
message: 'Would you like to review these files for cleanup?',
default: true,
},
]);
if (!prompt.proceed) {
return { deleted: 0, retained: allLegacyFiles.length, message: 'Cleanup cancelled by user' };
}
// Show selection interface
const selectionPrompt = await inquirer.prompt([
{
type: 'checkbox',
name: 'filesToDelete',
message: 'Select files to delete (use SPACEBAR to select, ENTER to continue):',
choices: allLegacyFiles.map((file) => {
const isRetained = retentionData.retainedFiles.includes(file.relativePath);
const description = `${file.relativePath} (${(file.size / 1024).toFixed(1)}KB)`;
return {
name: description,
value: file,
checked: !isRetained && !file.relativePath.includes('.bak'),
};
}),
pageSize: Math.min(allLegacyFiles.length, 15),
},
]);
filesToDelete.push(...selectionPrompt.filesToDelete);
}
// Delete selected files
for (const file of filesToDelete) {
try {
await fs.remove(file.path);
deletedCount++;
} catch (error) {
console.warn(`Warning: Could not delete ${file.relativePath}: ${error.message}`);
}
}
// Count retained files
retainedCount = allLegacyFiles.length - deletedCount;
// Update retention data
const newlyRetained = allLegacyFiles.filter((f) => !filesToDelete.includes(f)).map((f) => f.relativePath);
retentionData.retainedFiles = [...new Set([...retentionData.retainedFiles, ...newlyRetained])];
retentionData.history.push({
date: new Date().toISOString(),
deleted: deletedCount,
retained: retainedCount,
files: filesToDelete.map((f) => f.relativePath),
});
// Save retention data
await fs.ensureDir(path.dirname(retentionPath));
await fs.writeFile(retentionPath, yaml.dump(retentionData), 'utf8');
return { deleted: deletedCount, retained: retainedCount };
}
}
module.exports = { Installer };

View File

@ -6,13 +6,13 @@ const { AgentCommandGenerator } = require('./shared/agent-command-generator');
/**
* GitHub Copilot setup handler
* Creates chat modes in .github/chatmodes/ and configures VS Code settings
* Creates agents in .github/agents/ and configures VS Code settings
*/
class GitHubCopilotSetup extends BaseIdeSetup {
constructor() {
super('github-copilot', 'GitHub Copilot', true); // preferred IDE
this.configDir = '.github';
this.chatmodesDir = 'chatmodes';
this.agentsDir = 'agents';
this.vscodeDir = '.vscode';
}
@ -50,7 +50,8 @@ class GitHubCopilotSetup extends BaseIdeSetup {
message: 'Maximum requests per session (1-50)?',
default: '15',
validate: (input) => {
const num = parseInt(input);
const num = parseInt(input, 10);
if (isNaN(num)) return 'Enter a valid number 1-50';
return (num >= 1 && num <= 50) || 'Enter 1-50';
},
},
@ -97,10 +98,10 @@ class GitHubCopilotSetup extends BaseIdeSetup {
const config = options.preCollectedConfig || {};
await this.configureVsCodeSettings(projectDir, { ...options, ...config });
// Create .github/chatmodes directory
// Create .github/agents directory
const githubDir = path.join(projectDir, this.configDir);
const chatmodesDir = path.join(githubDir, this.chatmodesDir);
await this.ensureDir(chatmodesDir);
const agentsDir = path.join(githubDir, this.agentsDir);
await this.ensureDir(agentsDir);
// Clean up any existing BMAD files before reinstalling
await this.cleanup(projectDir);
@ -109,29 +110,29 @@ class GitHubCopilotSetup extends BaseIdeSetup {
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
// Create chat mode files with bmad- prefix
let modeCount = 0;
// Create agent files with bmd- prefix
let agentCount = 0;
for (const artifact of agentArtifacts) {
const content = artifact.content;
const chatmodeContent = await this.createChatmodeContent({ module: artifact.module, name: artifact.name }, content);
const agentContent = await this.createAgentContent({ module: artifact.module, name: artifact.name }, content);
// Use bmad- prefix: bmad-agent-{module}-{name}.chatmode.md
const targetPath = path.join(chatmodesDir, `bmad-agent-${artifact.module}-${artifact.name}.chatmode.md`);
await this.writeFile(targetPath, chatmodeContent);
modeCount++;
// Use bmd- prefix: bmd-custom-{module}-{name}.agent.md
const targetPath = path.join(agentsDir, `bmd-custom-${artifact.module}-${artifact.name}.agent.md`);
await this.writeFile(targetPath, agentContent);
agentCount++;
console.log(chalk.green(` ✓ Created chat mode: bmad-agent-${artifact.module}-${artifact.name}`));
console.log(chalk.green(` ✓ Created agent: bmd-custom-${artifact.module}-${artifact.name}`));
}
console.log(chalk.green(`${this.name} configured:`));
console.log(chalk.dim(` - ${modeCount} chat modes created`));
console.log(chalk.dim(` - Chat modes directory: ${path.relative(projectDir, chatmodesDir)}`));
console.log(chalk.dim(` - ${agentCount} agents created`));
console.log(chalk.dim(` - Agents directory: ${path.relative(projectDir, agentsDir)}`));
console.log(chalk.dim(` - VS Code settings configured`));
console.log(chalk.dim('\n Chat modes available in VS Code Chat view'));
console.log(chalk.dim('\n Agents available in VS Code Chat view'));
return {
success: true,
chatmodes: modeCount,
agents: agentCount,
settings: true,
};
}
@ -187,9 +188,10 @@ class GitHubCopilotSetup extends BaseIdeSetup {
// Manual configuration - use pre-collected settings
const manual = options.manualSettings || {};
const maxRequests = parseInt(manual.maxRequests || '15', 10);
bmadSettings = {
'chat.agent.enabled': true,
'chat.agent.maxRequests': parseInt(manual.maxRequests || 15),
'chat.agent.maxRequests': isNaN(maxRequests) ? 15 : maxRequests,
'github.copilot.chat.agent.runTasks': manual.runTasks === undefined ? true : manual.runTasks,
'chat.mcp.discovery.enabled': manual.mcpDiscovery === undefined ? true : manual.mcpDiscovery,
'github.copilot.chat.agent.autoFix': manual.autoFix === undefined ? true : manual.autoFix,
@ -206,9 +208,9 @@ class GitHubCopilotSetup extends BaseIdeSetup {
}
/**
* Create chat mode content
* Create agent content
*/
async createChatmodeContent(agent, content) {
async createAgentContent(agent, content) {
// Extract metadata from launcher frontmatter if present
const descMatch = content.match(/description:\s*"([^"]+)"/);
const title = descMatch ? descMatch[1] : this.formatTitle(agent.name);
@ -226,30 +228,21 @@ class GitHubCopilotSetup extends BaseIdeSetup {
// Reference: https://code.visualstudio.com/docs/copilot/reference/copilot-vscode-features#_chat-tools
const tools = [
'changes', // List of source control changes
'codebase', // Perform code search in workspace
'createDirectory', // Create new directory in workspace
'createFile', // Create new file in workspace
'editFiles', // Apply edits to files in workspace
'edit', // Edit files in your workspace including: createFile, createDirectory, editNotebook, newJupyterNotebook and editFiles
'fetch', // Fetch content from web page
'fileSearch', // Search files using glob patterns
'githubRepo', // Perform code search in GitHub repo
'listDirectory', // List files in a directory
'problems', // Add workspace issues from Problems panel
'readFile', // Read content of a file in workspace
'runInTerminal', // Run shell command in integrated terminal
'runTask', // Run existing task in workspace
'runCommands', // Runs commands in the terminal including: getTerminalOutput, terminalSelection, terminalLastCommand and runInTerminal
'runTasks', // Runs tasks and gets their output for your workspace
'runTests', // Run unit tests in workspace
'runVscodeCommand', // Run VS Code command
'search', // Enable file searching in workspace
'searchResults', // Get search results from Search view
'terminalLastCommand', // Get last terminal command and output
'terminalSelection', // Get current terminal selection
'search', // Search and read files in your workspace, including:fileSearch, textSearch, listDirectory, readFile, codebase and searchResults
'runSubagent', // Runs a task within an isolated subagent context. Enables efficient organization of tasks and context window management.
'testFailure', // Get unit test failure information
'textSearch', // Find text in files
'todos', // Tool for managing and tracking todo items for task planning
'usages', // Find references and navigate definitions
];
let chatmodeContent = `---
let agentContent = `---
description: "${description.replaceAll('"', String.raw`\"`)}"
tools: ${JSON.stringify(tools)}
---
@ -260,7 +253,7 @@ ${cleanContent}
`;
return chatmodeContent;
return agentContent;
}
/**
@ -278,10 +271,10 @@ ${cleanContent}
*/
async cleanup(projectDir) {
const fs = require('fs-extra');
const chatmodesDir = path.join(projectDir, this.configDir, this.chatmodesDir);
// Clean up old chatmodes directory
const chatmodesDir = path.join(projectDir, this.configDir, 'chatmodes');
if (await fs.pathExists(chatmodesDir)) {
// Only remove files that start with bmad- prefix
const files = await fs.readdir(chatmodesDir);
let removed = 0;
@ -293,7 +286,25 @@ ${cleanContent}
}
if (removed > 0) {
console.log(chalk.dim(` Cleaned up ${removed} existing BMAD chat modes`));
console.log(chalk.dim(` Cleaned up ${removed} old BMAD chat modes`));
}
}
// Clean up new agents directory
const agentsDir = path.join(projectDir, this.configDir, this.agentsDir);
if (await fs.pathExists(agentsDir)) {
const files = await fs.readdir(agentsDir);
let removed = 0;
for (const file of files) {
if (file.startsWith('bmd-') && file.endsWith('.agent.md')) {
await fs.remove(path.join(agentsDir, file));
removed++;
}
}
if (removed > 0) {
console.log(chalk.dim(` Cleaned up ${removed} existing BMAD agents`));
}
}
}
@ -307,13 +318,13 @@ ${cleanContent}
* @returns {Object|null} Info about created command
*/
async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
const chatmodesDir = path.join(projectDir, this.configDir, this.chatmodesDir);
const agentsDir = path.join(projectDir, this.configDir, this.agentsDir);
if (!(await this.exists(path.join(projectDir, this.configDir)))) {
return null; // IDE not configured for this project
}
await this.ensureDir(chatmodesDir);
await this.ensureDir(agentsDir);
const launcherContent = `You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
@ -353,7 +364,7 @@ ${cleanContent}
'usages',
];
const chatmodeContent = `---
const agentContent = `---
description: "Activates the ${metadata.title || agentName} agent persona."
tools: ${JSON.stringify(copilotTools)}
---
@ -363,12 +374,12 @@ tools: ${JSON.stringify(copilotTools)}
${launcherContent}
`;
const chatmodePath = path.join(chatmodesDir, `bmad-agent-custom-${agentName}.chatmode.md`);
await this.writeFile(chatmodePath, chatmodeContent);
const agentFilePath = path.join(agentsDir, `bmd-custom-${agentName}.agent.md`);
await this.writeFile(agentFilePath, agentContent);
return {
path: chatmodePath,
command: `bmad-agent-custom-${agentName}`,
path: agentFilePath,
command: `bmd-custom-${agentName}`,
};
}
}

View File

@ -720,8 +720,8 @@ class UI {
{
type: 'confirm',
name: 'enableTts',
message: 'Enable AgentVibes TTS? (Claude Code only - Agents speak with unique voices in party mode)',
default: true, // Default to yes - recommended for best experience
message: 'Enable Agents to Speak Out loud (powered by Agent Vibes? Claude Code only currently)',
default: false, // Default to yes - recommended for best experience
},
]);