Compare commits

...

7 Commits

Author SHA1 Message Date
Sjoerd Bozon fe6e22ba0c
Merge 015c74c46f into d19cca79d2 2026-01-08 08:44:00 +01:00
Q00 d19cca79d2
fix: resolve ERR_REQUIRE_ESM by using dynamic import for inquirer (#1278)
Inquirer v9+ is ESM-only, causing ERR_REQUIRE_ESM when loaded via
require() in CommonJS. Convert all require('inquirer') calls to
dynamic import('inquirer') across 8 CLI files.

Fixes #1197
2026-01-08 15:42:22 +08:00
Alex Verkhovsky 8e165b9b57
chore: enable CodeRabbit auto-review on new PRs (#1276) 2026-01-08 07:59:30 +08:00
Alex Verkhovsky 67b70288a6
docs: update README links to new documentation site (#1274) 2026-01-08 07:58:53 +08:00
Sjoerd Bozon 015c74c46f
Merge branch 'bmad-code-org:main' into feat/workflow-prompt-recommendations 2026-01-05 10:24:53 +01:00
Sjoerd Bozon 9317ef5a62 fix: address Copilot review feedback on PR #1205
- Move step 6 before WORKFLOW COMPLETE marker (fixes workflow structure)
- Change PRD shortcut from PR to PD (avoids conflict with parallel-research)
- Clarify instructions for reading/updating VS Code settings
- Update phase 4 comment to match actual handoff flow
2025-12-29 00:16:38 +01:00
Sjoerd Bozon d662aee4b2 feat: add VS Code workflow prompt recommendations
Add chat.promptFilesRecommendations support for GitHub Copilot to show
workflow shortcuts as new chat starters.

- Add workflow-prompts-config.js with all BMM, BMGD, and core prompts
- Add workflow-prompt-generator.js to create .github/prompts/*.prompt.md
- Update github-copilot.js to generate prompts and configure VS Code
- Add phase-based prompt toggling to implementation-readiness workflow
- Add phase-based prompt toggling to sprint-planning workflow

When implementation-readiness passes or sprint-planning completes, the
workflows update VS Code settings to prioritize the 'keep going' cycle
(create-story → dev-story → code-review) over setup phase prompts.
2025-12-28 23:44:40 +01:00
14 changed files with 411 additions and 35 deletions

View File

@ -11,8 +11,8 @@ reviews:
walkthrough: false walkthrough: false
poem: false poem: false
auto_review: auto_review:
enabled: false enabled: true
drafts: true # Can review drafts. Since it's manually triggered, it's fine. drafts: false # Don't review drafts automatically
auto_incremental_review: false # always review the whole PR, not just new commits auto_incremental_review: false # always review the whole PR, not just new commits
base_branches: base_branches:
- main - main

View File

@ -24,8 +24,8 @@ The completely revamped **BMAD V6 installer** now includes built-in support for
**📚 Learn More:** **📚 Learn More:**
- [**Custom Content Overview**](docs/modules/bmb-bmad-builder/custom-content.md) - Discover all supported content types - [**Custom Content Overview**](http://docs.bmad-method.org/explanation/bmad-builder/custom-content-types/) - Discover all supported content types
- [**Installation Guide**](docs/modules/bmb-bmad-builder/custom-content-installation.md) - Learn to create and install custom content - [**Installation Guide**](http://docs.bmad-method.org/how-to/installation/install-custom-modules/) - Learn to create and install custom content
- [**2 Very simple Custom Modules of questionable quality**](./samples/sample-custom-modules/README.md) - if you want to download and try to install a custom shared module, get an idea of how to bundle and share your own, or create your own personal agents, workflows and modules. - [**2 Very simple Custom Modules of questionable quality**](./samples/sample-custom-modules/README.md) - if you want to download and try to install a custom shared module, get an idea of how to bundle and share your own, or create your own personal agents, workflows and modules.
</div> </div>
@ -67,7 +67,7 @@ With **BMad Builder**, you can architect both simple agents and vastly complex d
## 📊 See It In Action ## 📊 See It In Action
<p align="center"> <p align="center">
<img src="./docs/modules/bmm-bmad-method/images/workflow-method-greenfield.svg" alt="BMad Method Workflow" width="100%"> <img src="./docs/tutorials/getting-started/images/workflow-method-greenfield.svg" alt="BMad Method Workflow" width="100%">
</p> </p>
<p align="center"> <p align="center">
@ -146,17 +146,17 @@ Each agent brings deep expertise and can be customized to match your team's styl
- 12 specialized agents - 12 specialized agents
- 34 workflows across 4 phases - 34 workflows across 4 phases
- Stand Along Quick Spec Flow for a streamlined simple implementation process - Stand Along Quick Spec Flow for a streamlined simple implementation process
- [→ Documentation Hub](./docs/modules/bmm-bmad-method/index.md) - [→ Documentation Hub](http://docs.bmad-method.org/explanation/bmm/)
- **BMad Builder (BMB)** - Create custom agents and workflows - **BMad Builder (BMB)** - Create custom agents and workflows
- Build anything from simple agents to complex modules - Build anything from simple agents to complex modules
- Create domain-specific solutions (legal, medical, finance, education) - Create domain-specific solutions (legal, medical, finance, education)
- [→ Builder Guide](./docs/modules/bmb-bmad-builder/index.md) - [→ Builder Guide](http://docs.bmad-method.org/explanation/bmad-builder/)
- **Creative Intelligence Suite (CIS)** - Innovation & problem-solving - **Creative Intelligence Suite (CIS)** - Innovation & problem-solving
- Brainstorming, design thinking, storytelling - Brainstorming, design thinking, storytelling
- 5 creative facilitation workflows - 5 creative facilitation workflows
- [→ Creative Workflows](./docs/modules/cis-creative-intelligence-suite/index.md) - [→ Creative Workflows](http://docs.bmad-method.org/explanation/creative-intelligence/)
### Key Features ### Key Features
@ -170,15 +170,15 @@ Each agent brings deep expertise and can be customized to match your team's styl
### Quick Links ### Quick Links
- **[Quick Start Guide](./docs/modules/bmm-bmad-method/quick-start.md)** - 15-minute introduction - **[Quick Start Guide](http://docs.bmad-method.org/tutorials/getting-started/getting-started-bmadv6/)** - 15-minute introduction
- **[Complete BMM Documentation](./docs/modules/bmm-bmad-method/index.md)** - All guides and references - **[Complete BMM Documentation](http://docs.bmad-method.org/explanation/bmm/)** - All guides and references
- **[Agent Customization](docs/bmad-customization/agent-customization-guide.md)** - Personalize your agents - **[Agent Customization](http://docs.bmad-method.org/how-to/customization/customize-agents/)** - Personalize your agents
- **[All Documentation](./docs/index.md)** - Complete documentation index - **[All Documentation](http://docs.bmad-method.org/)** - Complete documentation index
### For v4 Users ### For v4 Users
- **[v4 Documentation](https://github.com/bmad-code-org/BMAD-METHOD/tree/V4/docs)** - **[v4 Documentation](https://github.com/bmad-code-org/BMAD-METHOD/tree/V4/docs)**
- **[v4 to v6 Upgrade Guide](./docs/v4-to-v6-upgrade.md)** - **[v4 to v6 Upgrade Guide](http://docs.bmad-method.org/how-to/installation/upgrade-to-v6/)**
## 💬 Community & Support ## 💬 Community & Support
@ -211,7 +211,7 @@ If you would like to contribute, first check the [CONTRIBUTING.md](CONTRIBUTING.
### 🔄 For v4 Users ### 🔄 For v4 Users
- **[Comprehensive Upgrade Guide](./docs/v4-to-v6-upgrade.md)** - Step-by-step migration - **[Comprehensive Upgrade Guide](http://docs.bmad-method.org/how-to/installation/upgrade-to-v6/)** - Step-by-step migration
- **[v4 Documentation Archive](https://github.com/bmad-code-org/BMAD-METHOD/tree/V4)** - Legacy reference - **[v4 Documentation Archive](https://github.com/bmad-code-org/BMAD-METHOD/tree/V4)** - Legacy reference
- Backwards compatibility where possible - Backwards compatibility where possible
- Smooth migration path with installer detection - Smooth migration path with installer detection

View File

@ -111,6 +111,29 @@ Report generated: {outputFile}
The assessment found [number] issues requiring attention. Review the detailed report for specific findings and recommendations." The assessment found [number] issues requiring attention. Review the detailed report for specific findings and recommendations."
### 6. Update IDE Prompt Recommendations
If the readiness status is **READY**, update `.vscode/settings.json` to prioritize the implementation cycle prompts.
Read the existing `chat.promptFilesRecommendations` object and modify these keys:
**Set to `true` (implementation cycle - "keep going" loop):**
- `bmd-create-story`
- `bmd-dev-story`
- `bmd-code-review`
- `bmd-retrospective`
- `bmd-correct-course`
**Set to `false` (setup phase - already completed):**
- `bmd-workflow-init`
- `bmd-brainstorm`
- `bmd-prd`
- `bmd-ux-design`
- `bmd-create-architecture`
- `bmd-epics-stories`
- `bmd-implementation-readiness`
- `bmd-sprint-planning`
## WORKFLOW COMPLETE ## WORKFLOW COMPLETE
The implementation readiness workflow is now complete. The report contains all findings and recommendations for the user to consider. The implementation readiness workflow is now complete. The report contains all findings and recommendations for the user to consider.

View File

@ -179,6 +179,38 @@ development_status:
</step> </step>
<step n="6" goal="Update IDE prompt recommendations for implementation phase">
<action>Read the existing `.vscode/settings.json` and update the `chat.promptFilesRecommendations` object.</action>
**Set to `true` (implementation cycle - "keep going" loop):**
- `bmd-create-story`
- `bmd-dev-story`
- `bmd-code-review`
- `bmd-retrospective`
- `bmd-correct-course`
**Set to `false` (setup phase - already completed):**
- `bmd-workflow-init`
- `bmd-brainstorm`
- `bmd-prd`
- `bmd-ux-design`
- `bmd-create-architecture`
- `bmd-epics-stories`
- `bmd-implementation-readiness`
- `bmd-sprint-planning`
<action>Inform {user_name}:</action>
**IDE Updated for Implementation Phase**
The "keep going" cycle prompts are now prioritized in VS Code:
- **@bmd-custom-bmm-sm → *create-story** (prepare a story)
- **@bmd-custom-bmm-dev → *dev-story** (implement it)
- **Same chat → *code-review** (review the code)
- **Repeat!**
</step>
</workflow> </workflow>
## Additional Documentation ## Additional Documentation

View File

@ -1,6 +1,5 @@
const chalk = require('chalk'); const chalk = require('chalk');
const path = require('node:path'); const path = require('node:path');
const inquirer = require('inquirer').default || require('inquirer');
const { Installer } = require('../installers/lib/core/installer'); const { Installer } = require('../installers/lib/core/installer');
const { UI } = require('../lib/ui'); const { UI } = require('../lib/ui');
@ -72,6 +71,7 @@ module.exports = {
console.log(chalk.dim(' • ElevenLabs AI (150+ premium voices)')); console.log(chalk.dim(' • ElevenLabs AI (150+ premium voices)'));
console.log(chalk.dim(' • Piper TTS (50+ free voices)\n')); console.log(chalk.dim(' • Piper TTS (50+ free voices)\n'));
const { default: inquirer } = await import('inquirer');
await inquirer.prompt([ await inquirer.prompt([
{ {
type: 'input', type: 'input',

View File

@ -2,10 +2,18 @@ const path = require('node:path');
const fs = require('fs-extra'); const fs = require('fs-extra');
const yaml = require('yaml'); const yaml = require('yaml');
const chalk = require('chalk'); const chalk = require('chalk');
const inquirer = require('inquirer').default || require('inquirer');
const { getProjectRoot, getModulePath } = require('../../../lib/project-root'); const { getProjectRoot, getModulePath } = require('../../../lib/project-root');
const { CLIUtils } = require('../../../lib/cli-utils'); const { CLIUtils } = require('../../../lib/cli-utils');
// Lazy-load inquirer (ESM module) to avoid ERR_REQUIRE_ESM
let _inquirer = null;
async function getInquirer() {
if (!_inquirer) {
_inquirer = (await import('inquirer')).default;
}
return _inquirer;
}
class ConfigCollector { class ConfigCollector {
constructor() { constructor() {
this.collectedConfig = {}; this.collectedConfig = {};
@ -175,6 +183,7 @@ class ConfigCollector {
* @returns {boolean} True if new fields were prompted, false if all fields existed * @returns {boolean} True if new fields were prompted, false if all fields existed
*/ */
async collectModuleConfigQuick(moduleName, projectDir, silentMode = true) { async collectModuleConfigQuick(moduleName, projectDir, silentMode = true) {
const inquirer = await getInquirer();
this.currentProjectDir = projectDir; this.currentProjectDir = projectDir;
// Load existing config if not already loaded // Load existing config if not already loaded
@ -493,6 +502,7 @@ class ConfigCollector {
* @param {boolean} skipCompletion - Skip showing completion message (for early core collection) * @param {boolean} skipCompletion - Skip showing completion message (for early core collection)
*/ */
async collectModuleConfig(moduleName, projectDir, skipLoadExisting = false, skipCompletion = false) { async collectModuleConfig(moduleName, projectDir, skipLoadExisting = false, skipCompletion = false) {
const inquirer = await getInquirer();
this.currentProjectDir = projectDir; this.currentProjectDir = projectDir;
// Load existing config if needed and not already loaded // Load existing config if needed and not already loaded
if (!skipLoadExisting && !this.existingConfig) { if (!skipLoadExisting && !this.existingConfig) {

View File

@ -2,7 +2,6 @@ const path = require('node:path');
const fs = require('fs-extra'); const fs = require('fs-extra');
const chalk = require('chalk'); const chalk = require('chalk');
const ora = require('ora'); const ora = require('ora');
const inquirer = require('inquirer').default || require('inquirer');
const { Detector } = require('./detector'); const { Detector } = require('./detector');
const { Manifest } = require('./manifest'); const { Manifest } = require('./manifest');
const { ModuleManager } = require('../modules/manager'); const { ModuleManager } = require('../modules/manager');
@ -2140,7 +2139,7 @@ class Installer {
* Private: Prompt for update action * Private: Prompt for update action
*/ */
async promptUpdateAction() { async promptUpdateAction() {
const inquirer = require('inquirer').default || require('inquirer'); const { default: inquirer } = await import('inquirer');
return await inquirer.prompt([ return await inquirer.prompt([
{ {
type: 'list', type: 'list',
@ -2157,7 +2156,7 @@ class Installer {
* @param {Object} _legacyV4 - Legacy V4 detection result (unused in simplified version) * @param {Object} _legacyV4 - Legacy V4 detection result (unused in simplified version)
*/ */
async handleLegacyV4Migration(_projectDir, _legacyV4) { async handleLegacyV4Migration(_projectDir, _legacyV4) {
const inquirer = require('inquirer').default || require('inquirer'); const { default: inquirer } = await import('inquirer');
console.log(''); console.log('');
console.log(chalk.yellow.bold('⚠️ Legacy BMAD v4 detected')); console.log(chalk.yellow.bold('⚠️ Legacy BMAD v4 detected'));
@ -2438,7 +2437,7 @@ class Installer {
console.log(chalk.yellow(`\n⚠️ Found ${customModulesWithMissingSources.length} custom module(s) with missing sources:`)); console.log(chalk.yellow(`\n⚠️ Found ${customModulesWithMissingSources.length} custom module(s) with missing sources:`));
const inquirer = require('inquirer').default || require('inquirer'); const { default: inquirer } = await import('inquirer');
let keptCount = 0; let keptCount = 0;
let updatedCount = 0; let updatedCount = 0;
let removedCount = 0; let removedCount = 0;

View File

@ -58,7 +58,7 @@ class AntigravitySetup extends BaseIdeSetup {
if (config.subagentChoices.install !== 'none') { if (config.subagentChoices.install !== 'none') {
// Ask for installation location // Ask for installation location
const inquirer = require('inquirer').default || require('inquirer'); const { default: inquirer } = await import('inquirer');
const locationAnswer = await inquirer.prompt([ const locationAnswer = await inquirer.prompt([
{ {
type: 'list', type: 'list',
@ -297,7 +297,7 @@ class AntigravitySetup extends BaseIdeSetup {
choices = await this.promptSubagentInstallation(config.subagents); choices = await this.promptSubagentInstallation(config.subagents);
if (choices.install !== 'none') { if (choices.install !== 'none') {
const inquirer = require('inquirer').default || require('inquirer'); const { default: inquirer } = await import('inquirer');
const locationAnswer = await inquirer.prompt([ const locationAnswer = await inquirer.prompt([
{ {
type: 'list', type: 'list',
@ -334,7 +334,7 @@ class AntigravitySetup extends BaseIdeSetup {
* Prompt user for subagent installation preferences * Prompt user for subagent installation preferences
*/ */
async promptSubagentInstallation(subagentConfig) { async promptSubagentInstallation(subagentConfig) {
const inquirer = require('inquirer').default || require('inquirer'); const { default: inquirer } = await import('inquirer');
// First ask if they want to install subagents // First ask if they want to install subagents
const { install } = await inquirer.prompt([ const { install } = await inquirer.prompt([

View File

@ -57,7 +57,7 @@ class ClaudeCodeSetup extends BaseIdeSetup {
if (config.subagentChoices.install !== 'none') { if (config.subagentChoices.install !== 'none') {
// Ask for installation location // Ask for installation location
const inquirer = require('inquirer').default || require('inquirer'); const { default: inquirer } = await import('inquirer');
const locationAnswer = await inquirer.prompt([ const locationAnswer = await inquirer.prompt([
{ {
type: 'list', type: 'list',
@ -305,7 +305,7 @@ class ClaudeCodeSetup extends BaseIdeSetup {
choices = await this.promptSubagentInstallation(config.subagents); choices = await this.promptSubagentInstallation(config.subagents);
if (choices.install !== 'none') { if (choices.install !== 'none') {
const inquirer = require('inquirer').default || require('inquirer'); const { default: inquirer } = await import('inquirer');
const locationAnswer = await inquirer.prompt([ const locationAnswer = await inquirer.prompt([
{ {
type: 'list', type: 'list',
@ -342,7 +342,7 @@ class ClaudeCodeSetup extends BaseIdeSetup {
* Prompt user for subagent installation preferences * Prompt user for subagent installation preferences
*/ */
async promptSubagentInstallation(subagentConfig) { async promptSubagentInstallation(subagentConfig) {
const inquirer = require('inquirer').default || require('inquirer'); const { default: inquirer } = await import('inquirer');
// First ask if they want to install subagents // First ask if they want to install subagents
const { install } = await inquirer.prompt([ const { install } = await inquirer.prompt([

View File

@ -21,7 +21,7 @@ class CodexSetup extends BaseIdeSetup {
* @returns {Object} Collected configuration * @returns {Object} Collected configuration
*/ */
async collectConfiguration(options = {}) { async collectConfiguration(options = {}) {
const inquirer = require('inquirer').default || require('inquirer'); const { default: inquirer } = await import('inquirer');
let confirmed = false; let confirmed = false;
let installLocation = 'global'; let installLocation = 'global';

View File

@ -1,8 +1,8 @@
const path = require('node:path'); const path = require('node:path');
const { BaseIdeSetup } = require('./_base-ide'); const { BaseIdeSetup } = require('./_base-ide');
const chalk = require('chalk'); const chalk = require('chalk');
const inquirer = require('inquirer').default || require('inquirer');
const { AgentCommandGenerator } = require('./shared/agent-command-generator'); const { AgentCommandGenerator } = require('./shared/agent-command-generator');
const { WorkflowPromptGenerator } = require('./shared/workflow-prompt-generator');
/** /**
* GitHub Copilot setup handler * GitHub Copilot setup handler
@ -13,6 +13,7 @@ class GitHubCopilotSetup extends BaseIdeSetup {
super('github-copilot', 'GitHub Copilot', true); // preferred IDE super('github-copilot', 'GitHub Copilot', true); // preferred IDE
this.configDir = '.github'; this.configDir = '.github';
this.agentsDir = 'agents'; this.agentsDir = 'agents';
this.promptsDir = 'prompts';
this.vscodeDir = '.vscode'; this.vscodeDir = '.vscode';
} }
@ -22,6 +23,7 @@ class GitHubCopilotSetup extends BaseIdeSetup {
* @returns {Object} Collected configuration * @returns {Object} Collected configuration
*/ */
async collectConfiguration(options = {}) { async collectConfiguration(options = {}) {
const { default: inquirer } = await import('inquirer');
const config = {}; const config = {};
console.log('\n' + chalk.blue(' 🔧 VS Code Settings Configuration')); console.log('\n' + chalk.blue(' 🔧 VS Code Settings Configuration'));
@ -94,14 +96,12 @@ class GitHubCopilotSetup extends BaseIdeSetup {
async setup(projectDir, bmadDir, options = {}) { async setup(projectDir, bmadDir, options = {}) {
console.log(chalk.cyan(`Setting up ${this.name}...`)); console.log(chalk.cyan(`Setting up ${this.name}...`));
// Configure VS Code settings using pre-collected config if available
const config = options.preCollectedConfig || {};
await this.configureVsCodeSettings(projectDir, { ...options, ...config });
// Create .github/agents directory // Create .github/agents directory
const githubDir = path.join(projectDir, this.configDir); const githubDir = path.join(projectDir, this.configDir);
const agentsDir = path.join(githubDir, this.agentsDir); const agentsDir = path.join(githubDir, this.agentsDir);
const promptsDir = path.join(githubDir, this.promptsDir);
await this.ensureDir(agentsDir); await this.ensureDir(agentsDir);
await this.ensureDir(promptsDir);
// Clean up any existing BMAD files before reinstalling // Clean up any existing BMAD files before reinstalling
await this.cleanup(projectDir); await this.cleanup(projectDir);
@ -117,22 +117,37 @@ class GitHubCopilotSetup extends BaseIdeSetup {
const agentContent = await this.createAgentContent({ module: artifact.module, name: artifact.name }, content); const agentContent = await this.createAgentContent({ module: artifact.module, name: artifact.name }, content);
// Use bmd- prefix: bmd-custom-{module}-{name}.agent.md // Use bmd- prefix: bmd-custom-{module}-{name}.agent.md
const targetPath = path.join(agentsDir, `bmd-custom-${artifact.module}-${artifact.name}.agent.md`); const agentFileName = `bmd-custom-${artifact.module}-${artifact.name}`;
const targetPath = path.join(agentsDir, `${agentFileName}.agent.md`);
await this.writeFile(targetPath, agentContent); await this.writeFile(targetPath, agentContent);
agentCount++; agentCount++;
console.log(chalk.green(` ✓ Created agent: bmd-custom-${artifact.module}-${artifact.name}`)); console.log(chalk.green(` ✓ Created agent: ${agentFileName}`));
} }
// Generate workflow prompts from config (shared logic)
// Each prompt includes nextSteps guidance for the agent to suggest next workflows
const promptGen = new WorkflowPromptGenerator();
const promptRecommendations = await promptGen.generatePromptFiles(promptsDir, options.selectedModules || []);
const promptCount = Object.keys(promptRecommendations).length;
// Configure VS Code settings using pre-collected config if available
const config = options.preCollectedConfig || {};
await this.configureVsCodeSettings(projectDir, { ...options, ...config, promptRecommendations });
console.log(chalk.green(`${this.name} configured:`)); console.log(chalk.green(`${this.name} configured:`));
console.log(chalk.dim(` - ${agentCount} agents created`)); console.log(chalk.dim(` - ${agentCount} agents created`));
console.log(chalk.dim(` - ${promptCount} workflow prompts configured`));
console.log(chalk.dim(` - Agents directory: ${path.relative(projectDir, agentsDir)}`)); console.log(chalk.dim(` - Agents directory: ${path.relative(projectDir, agentsDir)}`));
console.log(chalk.dim(` - Prompts directory: ${path.relative(projectDir, promptsDir)}`));
console.log(chalk.dim(` - VS Code settings configured`)); console.log(chalk.dim(` - VS Code settings configured`));
console.log(chalk.dim('\n Agents available in VS Code Chat view')); console.log(chalk.dim('\n Agents available in VS Code Chat view'));
console.log(chalk.dim(' Workflow prompts show as new chat starters'));
return { return {
success: true, success: true,
agents: agentCount, agents: agentCount,
prompts: promptCount,
settings: true, settings: true,
}; };
} }
@ -199,6 +214,11 @@ class GitHubCopilotSetup extends BaseIdeSetup {
}; };
} }
// Add prompt file recommendations for new chat starters
if (options.promptRecommendations && Object.keys(options.promptRecommendations).length > 0) {
bmadSettings['chat.promptFilesRecommendations'] = options.promptRecommendations;
}
// Merge settings (existing take precedence) // Merge settings (existing take precedence)
const mergedSettings = { ...bmadSettings, ...existingSettings }; const mergedSettings = { ...bmadSettings, ...existingSettings };
@ -307,6 +327,24 @@ ${cleanContent}
console.log(chalk.dim(` Cleaned up ${removed} existing BMAD agents`)); console.log(chalk.dim(` Cleaned up ${removed} existing BMAD agents`));
} }
} }
// Clean up prompts directory
const promptsDir = path.join(projectDir, this.configDir, this.promptsDir);
if (await fs.pathExists(promptsDir)) {
const files = await fs.readdir(promptsDir);
let removed = 0;
for (const file of files) {
if (file.startsWith('bmd-') && file.endsWith('.prompt.md')) {
await fs.remove(path.join(promptsDir, file));
removed++;
}
}
if (removed > 0) {
console.log(chalk.dim(` Cleaned up ${removed} existing BMAD prompt files`));
}
}
} }
/** /**

View File

@ -0,0 +1,61 @@
const path = require('node:path');
const fs = require('fs-extra');
const { workflowPromptsConfig } = require('./workflow-prompts-config');
/**
* Generate workflow prompt recommendations for IDE new chat starters
* Uses static configuration from workflow-prompts-config.js which mirrors
* the workflows documented in quick-start.md
*
* The implementation-readiness and sprint-planning workflows update
* VS Code settings to toggle which prompts are shown based on project phase.
*/
class WorkflowPromptGenerator {
/**
* Get workflow prompts for selected modules
* @param {Array<string>} selectedModules - Modules to include (e.g., ['bmm', 'bmgd'])
* @returns {Array<Object>} Array of workflow prompt configurations
*/
getWorkflowPrompts(selectedModules = []) {
const allPrompts = [];
// Always include core prompts
if (workflowPromptsConfig.core) {
allPrompts.push(...workflowPromptsConfig.core);
}
// Add prompts for each selected module
for (const moduleName of selectedModules) {
if (workflowPromptsConfig[moduleName]) {
allPrompts.push(...workflowPromptsConfig[moduleName]);
}
}
return allPrompts;
}
/**
* Generate prompt files for an IDE
* @param {string} promptsDir - Directory to write prompt files
* @param {Array<string>} selectedModules - Modules to include
* @returns {Object} Map of prompt names to true for VS Code settings
*/
async generatePromptFiles(promptsDir, selectedModules = []) {
const prompts = this.getWorkflowPrompts(selectedModules);
const recommendations = {};
for (const prompt of prompts) {
const promptContent = ['---', `agent: ${prompt.agent}`, `description: "${prompt.description}"`, '---', '', prompt.prompt, ''].join(
'\n',
);
const promptFilePath = path.join(promptsDir, `bmd-${prompt.name}.prompt.md`);
await fs.writeFile(promptFilePath, promptContent);
recommendations[`bmd-${prompt.name}`] = true;
}
return recommendations;
}
}
module.exports = { WorkflowPromptGenerator };

View File

@ -0,0 +1,192 @@
/**
* Workflow prompt configuration for IDE new chat starters
*
* This configuration defines the workflow prompts that appear as suggestions
* when starting a new chat in VS Code (via chat.promptFilesRecommendations).
*
* The implementation-readiness and sprint-planning workflows update the
* VS Code settings to toggle which prompts are shown based on project phase.
*
* Reference: docs/modules/bmm-bmad-method/quick-start.md
*/
const workflowPromptsConfig = {
// BMad Method Module (bmm) - Standard development workflow
bmm: [
// ═══════════════════════════════════════════════════════════════════════
// Phase 1 - Analysis (Optional)
// ═══════════════════════════════════════════════════════════════════════
{
name: 'workflow-init',
agent: 'bmd-custom-bmm-analyst',
shortcut: 'WI',
description: '[WI] Initialize workflow and choose planning track',
prompt: '*workflow-init',
},
{
name: 'brainstorm',
agent: 'bmd-custom-bmm-analyst',
shortcut: 'BP',
description: '[BP] Brainstorm project ideas and concepts',
prompt: '*brainstorm-project',
},
{
name: 'workflow-status',
agent: 'bmd-custom-bmm-pm',
shortcut: 'WS',
description: '[WS] Check current workflow status and next steps',
prompt: '*workflow-status',
},
// ═══════════════════════════════════════════════════════════════════════
// Phase 2 - Planning (Required)
// ═══════════════════════════════════════════════════════════════════════
{
name: 'prd',
agent: 'bmd-custom-bmm-pm',
shortcut: 'PD',
description: '[PD] Create Product Requirements Document (PRD)',
prompt: '*prd',
},
{
name: 'ux-design',
agent: 'bmd-custom-bmm-ux-designer',
shortcut: 'UD',
description: '[UD] Create UX Design specification',
prompt: '*ux-design',
},
// ═══════════════════════════════════════════════════════════════════════
// Phase 3 - Solutioning
// ═══════════════════════════════════════════════════════════════════════
{
name: 'create-architecture',
agent: 'bmd-custom-bmm-architect',
shortcut: 'CA',
description: '[CA] Create system architecture document',
prompt: '*create-architecture',
},
{
name: 'epics-stories',
agent: 'bmd-custom-bmm-pm',
shortcut: 'ES',
description: '[ES] Create Epics and User Stories from PRD',
prompt: '*epics-stories',
},
{
name: 'implementation-readiness',
agent: 'bmd-custom-bmm-architect',
shortcut: 'IR',
description: '[IR] Check implementation readiness across all docs',
prompt: '*implementation-readiness',
},
{
name: 'sprint-planning',
agent: 'bmd-custom-bmm-sm',
shortcut: 'SP',
description: '[SP] Initialize sprint planning from epics',
prompt: '*sprint-planning',
},
// ═══════════════════════════════════════════════════════════════════════
// Phase 4 - Implementation: The "Keep Going" Cycle
// SM → create-story → DEV → dev-story → code-review → (create-story | retrospective)
// ═══════════════════════════════════════════════════════════════════════
{
name: 'create-story',
agent: 'bmd-custom-bmm-sm',
shortcut: 'CS',
description: '[CS] Create developer-ready story from epic',
prompt: '*create-story',
},
{
name: 'dev-story',
agent: 'bmd-custom-bmm-dev',
shortcut: 'DS',
description: '[DS] Implement the current story',
prompt: '*dev-story',
},
{
name: 'code-review',
agent: 'bmd-custom-bmm-dev',
shortcut: 'CR',
description: '[CR] Perform code review on implementation',
prompt: '*code-review',
},
{
name: 'retrospective',
agent: 'bmd-custom-bmm-sm',
shortcut: 'ER',
description: '[ER] Run epic retrospective after completion',
prompt: '*epic-retrospective',
},
{
name: 'correct-course',
agent: 'bmd-custom-bmm-sm',
shortcut: 'CC',
description: '[CC] Course correction when things go off track',
prompt: '*correct-course',
},
],
// BMad Game Development Module (bmgd)
bmgd: [
// Implementation cycle
{
name: 'game-implement',
agent: 'bmd-custom-bmgd-game-dev',
shortcut: 'GI',
description: '[GI] Implement game feature',
prompt: '*game-implement',
},
{
name: 'game-qa',
agent: 'bmd-custom-bmgd-game-qa',
shortcut: 'GQ',
description: '[GQ] Test and QA game feature',
prompt: '*game-qa',
},
// Planning & Design
{
name: 'game-design',
agent: 'bmd-custom-bmgd-game-designer',
shortcut: 'GD',
description: '[GD] Design game mechanics and systems',
prompt: '*game-design',
},
{
name: 'game-architecture',
agent: 'bmd-custom-bmgd-game-architect',
shortcut: 'GA',
description: '[GA] Create game technical architecture',
prompt: '*game-architecture',
},
{
name: 'game-sprint',
agent: 'bmd-custom-bmgd-game-scrum-master',
shortcut: 'GS',
description: '[GS] Plan game development sprint',
prompt: '*game-sprint',
},
],
// Core agents (always available)
core: [
{
name: 'list-tasks',
agent: 'bmd-custom-core-bmad-master',
shortcut: 'LT',
description: '[LT] List available tasks',
prompt: '*list-tasks',
},
{
name: 'list-workflows',
agent: 'bmd-custom-core-bmad-master',
shortcut: 'LW',
description: '[LW] List available workflows',
prompt: '*list-workflows',
},
],
};
module.exports = { workflowPromptsConfig };

View File

@ -1,11 +1,19 @@
const chalk = require('chalk'); const chalk = require('chalk');
const inquirer = require('inquirer').default || require('inquirer');
const path = require('node:path'); const path = require('node:path');
const os = require('node:os'); const os = require('node:os');
const fs = require('fs-extra'); const fs = require('fs-extra');
const { CLIUtils } = require('./cli-utils'); const { CLIUtils } = require('./cli-utils');
const { CustomHandler } = require('../installers/lib/custom/handler'); const { CustomHandler } = require('../installers/lib/custom/handler');
// Lazy-load inquirer (ESM module) to avoid ERR_REQUIRE_ESM
let _inquirer = null;
async function getInquirer() {
if (!_inquirer) {
_inquirer = (await import('inquirer')).default;
}
return _inquirer;
}
/** /**
* UI utilities for the installer * UI utilities for the installer
*/ */
@ -15,6 +23,7 @@ class UI {
* @returns {Object} Installation configuration * @returns {Object} Installation configuration
*/ */
async promptInstall() { async promptInstall() {
const inquirer = await getInquirer();
CLIUtils.displayLogo(); CLIUtils.displayLogo();
// Display version-specific start message from install-messages.yaml // Display version-specific start message from install-messages.yaml
@ -450,6 +459,7 @@ class UI {
* @returns {Object} Tool configuration * @returns {Object} Tool configuration
*/ */
async promptToolSelection(projectDir, selectedModules) { async promptToolSelection(projectDir, selectedModules) {
const inquirer = await getInquirer();
// Check for existing configured IDEs - use findBmadDir to detect custom folder names // Check for existing configured IDEs - use findBmadDir to detect custom folder names
const { Detector } = require('../installers/lib/core/detector'); const { Detector } = require('../installers/lib/core/detector');
const { Installer } = require('../installers/lib/core/installer'); const { Installer } = require('../installers/lib/core/installer');
@ -582,6 +592,7 @@ class UI {
* @returns {Object} Update configuration * @returns {Object} Update configuration
*/ */
async promptUpdate() { async promptUpdate() {
const inquirer = await getInquirer();
const answers = await inquirer.prompt([ const answers = await inquirer.prompt([
{ {
type: 'confirm', type: 'confirm',
@ -606,6 +617,7 @@ class UI {
* @returns {Array} Selected modules * @returns {Array} Selected modules
*/ */
async promptModules(modules) { async promptModules(modules) {
const inquirer = await getInquirer();
const choices = modules.map((mod) => ({ const choices = modules.map((mod) => ({
name: `${mod.name} - ${mod.description}`, name: `${mod.name} - ${mod.description}`,
value: mod.id, value: mod.id,
@ -637,6 +649,7 @@ class UI {
* @returns {boolean} User confirmation * @returns {boolean} User confirmation
*/ */
async confirm(message, defaultValue = false) { async confirm(message, defaultValue = false) {
const inquirer = await getInquirer();
const { confirmed } = await inquirer.prompt([ const { confirmed } = await inquirer.prompt([
{ {
type: 'confirm', type: 'confirm',
@ -743,6 +756,7 @@ class UI {
* @returns {Array} Module choices for inquirer * @returns {Array} Module choices for inquirer
*/ */
async getModuleChoices(installedModuleIds, customContentConfig = null) { async getModuleChoices(installedModuleIds, customContentConfig = null) {
const inquirer = await getInquirer();
const moduleChoices = []; const moduleChoices = [];
const isNewInstallation = installedModuleIds.size === 0; const isNewInstallation = installedModuleIds.size === 0;
@ -823,6 +837,7 @@ class UI {
* @returns {Array} Selected module IDs * @returns {Array} Selected module IDs
*/ */
async selectModules(moduleChoices, defaultSelections = []) { async selectModules(moduleChoices, defaultSelections = []) {
const inquirer = await getInquirer();
const moduleAnswer = await inquirer.prompt([ const moduleAnswer = await inquirer.prompt([
{ {
type: 'checkbox', type: 'checkbox',
@ -843,6 +858,7 @@ class UI {
* @returns {Object} Directory answer from inquirer * @returns {Object} Directory answer from inquirer
*/ */
async promptForDirectory() { async promptForDirectory() {
const inquirer = await getInquirer();
return await inquirer.prompt([ return await inquirer.prompt([
{ {
type: 'input', type: 'input',
@ -899,6 +915,7 @@ class UI {
* @returns {boolean} Whether user confirmed * @returns {boolean} Whether user confirmed
*/ */
async confirmDirectory(directory) { async confirmDirectory(directory) {
const inquirer = await getInquirer();
const dirExists = await fs.pathExists(directory); const dirExists = await fs.pathExists(directory);
if (dirExists) { if (dirExists) {
@ -1085,6 +1102,7 @@ class UI {
* - GitHub Issue: paulpreibisch/AgentVibes#36 * - GitHub Issue: paulpreibisch/AgentVibes#36
*/ */
async promptAgentVibes(projectDir) { async promptAgentVibes(projectDir) {
const inquirer = await getInquirer();
CLIUtils.displaySection('🎤 Voice Features', 'Enable TTS for multi-agent conversations'); CLIUtils.displaySection('🎤 Voice Features', 'Enable TTS for multi-agent conversations');
// Check if AgentVibes is already installed // Check if AgentVibes is already installed
@ -1235,6 +1253,7 @@ class UI {
* @returns {Object} Custom content configuration * @returns {Object} Custom content configuration
*/ */
async promptCustomContentSource() { async promptCustomContentSource() {
const inquirer = await getInquirer();
const customContentConfig = { hasCustomContent: true, sources: [] }; const customContentConfig = { hasCustomContent: true, sources: [] };
// Keep asking for more sources until user is done // Keep asking for more sources until user is done
@ -1372,6 +1391,7 @@ class UI {
* @returns {Object} Result with selected custom modules and custom content config * @returns {Object} Result with selected custom modules and custom content config
*/ */
async handleCustomModulesInModifyFlow(directory, selectedModules) { async handleCustomModulesInModifyFlow(directory, selectedModules) {
const inquirer = await getInquirer();
// Get existing installation to find custom modules // Get existing installation to find custom modules
const { existingInstall } = await this.getExistingInstallation(directory); const { existingInstall } = await this.getExistingInstallation(directory);
@ -1566,6 +1586,7 @@ class UI {
* @returns {Promise<boolean>} True if user wants to proceed, false if they cancel * @returns {Promise<boolean>} True if user wants to proceed, false if they cancel
*/ */
async showOldAlphaVersionWarning(installedVersion, currentVersion, bmadFolderName) { async showOldAlphaVersionWarning(installedVersion, currentVersion, bmadFolderName) {
const inquirer = await getInquirer();
const versionInfo = this.checkAlphaVersionAge(installedVersion, currentVersion); const versionInfo = this.checkAlphaVersionAge(installedVersion, currentVersion);
// Also warn if version is unknown or can't be parsed (legacy/unsupported) // Also warn if version is unknown or can't be parsed (legacy/unsupported)