diff --git a/.bmad-core/tasks/doc-migration-task.md b/.bmad-core/tasks/doc-migration-task.md new file mode 100644 index 00000000..3cd20851 --- /dev/null +++ b/.bmad-core/tasks/doc-migration-task.md @@ -0,0 +1,188 @@ +# Document Migration Task (V3 to V4) + +## Purpose + +Migrate BMAD-METHOD V3 documents to V4 format by aligning section headings, structure, and content organization with V4 templates while preserving all user-generated content. + +## When to Use This Task + +[[LLM: This task should be used after a V3 to V4 upgrade when the user has existing PRD and Architecture documents that need to be aligned with V4 templates. The task handles: + +- PRD migration to V4 format +- Architecture migration (single backend or full-stack) +- Merging separate front-end and backend architecture docs into full-stack-architecture.md + ]] + +Use this task when: + +- You've upgraded from BMAD V3 to V4 +- Your documents have V3 section headings that differ from V4 +- You have separate front-end and backend architecture documents +- You need to align your documents with V4 agent expectations + +## Prerequisites + +- Completed V3 to V4 upgrade +- Documents located in `docs/` folder +- Access to V4 templates in `.bmad-core/templates/` + +## Process + +### 1. Analyze Existing Documents + +[[LLM: First, examine what documents exist in the docs/ folder: + +- Look for prd.md or similar +- Look for architecture.md or similar +- Check for front-end-architecture.md or similar +- Note which documents need migration + ]] + +Identify which documents need migration: + +- PRD document +- Architecture document(s) +- Any front-end specific architecture + +### 2. PRD Migration + +[[LLM: When migrating the PRD: + +1. Read the existing PRD content +2. Compare with `.bmad-core/templates/prd-tmpl.md` +3. Map V3 sections to V4 sections: + - Keep all user content + - Update section headings to match V4 + - Add any missing V4 sections with placeholder content + - Preserve any custom sections at the end + +V3 → V4 Common Mappings: + +- "Executive Summary" → "Goals and Background Context" +- "Goals" → "Goals and Background Context > Goals" +- "Requirements" → Keep as is +- "User Stories" → "Epics and User Stories" + ]] + +**PRD Section Mapping:** + +1. Update main heading structure to match V4 template +2. Preserve all existing content under new headings +3. Add missing sections with appropriate prompts for completion +4. Maintain any project-specific custom sections + +### 3. Architecture Migration + +[[LLM: Determine architecture migration path: + +1. If ONLY backend architecture exists: + - Use `.bmad-core/templates/architecture-tmpl.md` + - Map sections appropriately +2. If BOTH backend AND front-end architecture exist: + - Use `.bmad-core/templates/full-stack-architecture-tmpl.md` + - Merge content from both documents + - Create unified architecture document +3. Section mapping approach: + - Preserve all technical decisions and content + - Update headings to match V4 structure + - Combine overlapping sections intelligently + ]] + +**Architecture Migration Paths:** + +#### Single Architecture → architecture.md + +- Update section headings to V4 format +- Add any missing V4 sections +- Preserve all technical content + +#### Multiple Architecture Files → full-stack-architecture.md + +- Merge backend and front-end content +- Organize under V4 full-stack sections +- Eliminate redundancy while preserving all unique content +- Create unified system view + +### 4. Content Preservation Rules + +[[LLM: CRITICAL preservation rules: + +1. NEVER delete user content +2. If unsure where content belongs, add it to the most relevant section +3. Preserve all: + - Technical decisions + - Diagrams and code blocks + - Lists and tables + - Custom sections + - Links and references +4. Add [[LLM: migration note]] comments where manual review might be needed + ]] + +**Always Preserve:** + +- All user-written content +- Technical specifications +- Diagrams (Mermaid, ASCII, etc.) +- Code examples +- Custom sections not in V4 template + +### 5. Create Migration Report + +[[LLM: After migration, create a brief report: + +- List all documents migrated +- Note any sections that need manual review +- Highlight any content that was moved significantly +- Suggest next steps + ]] + +Generate `migration-report.md` with: + +- Documents migrated +- Section mappings performed +- Any content requiring review +- Recommendations for manual updates + +## Validation Checklist + +Before completing migration: + +- [ ] All original content is preserved +- [ ] Section headings match V4 templates +- [ ] No duplicate content in merged documents +- [ ] Documents are properly formatted +- [ ] Any uncertain mappings are marked for review + +## Example Migrations + +### V3 PRD Section → V4 PRD Section + +``` +V3: ## Executive Summary → V4: ## Goals and Background Context +V3: ## Goals → V4: ### Goals +V3: ## Success Metrics → V4: ## Success Metrics and KPIs +``` + +### Architecture Merge Example + +``` +backend-architecture.md + front-end-architecture.md → full-stack-architecture.md + +V3 Backend: ## Technology Stack → V4: ## Technology Stack > ### Backend +V3 Frontend: ## UI Architecture → V4: ## Technology Stack > ### Frontend +``` + +## Post-Migration Steps + +1. Review migrated documents for accuracy +2. Fill in any placeholder sections added +3. Run document sharding if needed +4. Update any cross-references between documents + +## Important Notes + +- This task requires careful analysis of existing content +- When in doubt, preserve content and mark for review +- The goal is structure alignment, not content rewriting +- Custom sections should be retained even if not in V4 template +- MOST CRITICAL - The ONLY LEVEL 2 HEADINGS should be what are in the V4 templates. so content preservation might mean making some content that was level 2 a level 3 now. UNDERSTAND that the LEVEL 2 headings result in file names diff --git a/README.md b/README.md index f713f5f7..2e67935e 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,14 @@ [![Version](https://img.shields.io/badge/version-4.0.0-blue.svg)](docs/versions.md) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) [![Node.js Version](https://img.shields.io/badge/node-%3E%3D14.0.0-brightgreen)](https://nodejs.org) +[![Discord](https://img.shields.io/discord/1234567890?color=7289da&label=Discord&logo=discord&logoColor=white)](https://discord.gg/g6ypHytrCB) **AI-Powered Agile Development Framework** - Transform your software development with specialized AI agents that work as your complete Agile team. +📺 **[Subscribe to BMadCode on YouTube](https://www.youtube.com/@BMadCode?sub_confirmation=1)** - V4 walkthrough and comprehensive guide coming soon! + +⭐ **If you find this project helpful or useful, please give it a star!** It helps others discover BMAD-METHOD and you will be notified of updates! + ## 🚀 Quick Start ### Fastest Start: Web UI (2 minutes) 🏃‍♂️ @@ -98,6 +103,7 @@ The BMad Method works with any IDE, but has built-in integration for: - `cursor` - Cursor IDE with @agent commands - `claude-code` - Claude Code with /agent commands - `windsurf` - Windsurf with @agent commands +- More coming soon - BUT ITS easy to use with ANY IDE! ## Available Agents @@ -116,10 +122,10 @@ The BMad Method works with any IDE, but has built-in integration for: ### Meta Agents -| Agent | Role | Specialty | -| ------------------- | ---------------- | ------------------------------------- | -| `bmad-orchestrator` | Team Coordinator | Multi-agent workflows, role switching | -| `bmad-master` | Universal Expert | All capabilities without switching | +| Agent | Role | Specialty | +| ------------------- | ---------------- | ------------------------------------------------------------------- | +| `bmad-orchestrator` | Team Coordinator | Multi-agent workflows, role switching, is part of every team bundle | +| `bmad-master` | Universal Expert | All capabilities without switching | ## Usage @@ -155,6 +161,33 @@ npx bmad-method update npx bmad-method status ``` +### Upgrading from V3 to V4 + +If you have an existing BMAD-METHOD V3 project: + +```bash +# Run the upgrade command and follow the prompts including entering existing project location +npm run upgrade + +# Run the upgrade command and follow the prompts including entering existing project location +npx bmad-method upgrade +``` + +The upgrade process will: + +1. Create a backup of your V3 files in `.bmad-v3-backup/` +2. Install the new V4 `.bmad-core/` structure +3. Migrate your documents (PRD, Architecture, Stories, Epics) +4. Set up IDE integration for all V4 agents (Cursor Windsurf and Claude-Code - others coming soon) + +After upgrading: + +1. Review your documents in the `docs/` folder +2. Use `@bmad-master` agent to run the `doc-migration-task` to align your documents with V4 templates +3. If you have separate front-end and backend architecture docs, the migration task will help merge them into a unified `full-stack-architecture.md` + +**Note**: The agents in .bmad-core fully replace the items in bmad-agent. + ## Teams & Workflows ### Pre-Configured Teams @@ -211,14 +244,9 @@ Rich templates for all document types: - Test Plans - And more... -### Slash Commands +### Slash Star Commands -Quick actions and role switching: - -- `/help` - Show available commands -- `/pm` - Switch to Product Manager -- `*create-doc` - Create from template -- `*validate` - Run validations +Ask the agent you are using for help with /help (in the web) or \*help in the ide to see what commands are available! ## Contributing @@ -230,12 +258,11 @@ We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. git clone https://github.com/bmadcode/bmad-method.git cd bmad-method npm install -npm run validate # Check configurations -npm test # Run tests ``` ## Support +- 💬 [Discord Community](https://discord.gg/g6ypHytrCB) - 📖 [Documentation](docs/) - 🐛 [Issue Tracker](https://github.com/bmadcode/bmad-method/issues) - 💬 [Discussions](https://github.com/bmadcode/bmad-method/discussions) diff --git a/package.json b/package.json index f5d7d26c..8013f337 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,9 @@ "build:teams": "node tools/cli.js build --teams-only", "list:agents": "node tools/cli.js list:agents", "validate": "node tools/cli.js validate", - "install:bmad": "node tools/installer/bin/bmad.js install" + "install:bmad": "node tools/installer/bin/bmad.js install", + "upgrade": "node tools/cli.js upgrade", + "upgrade:dry-run": "node tools/cli.js upgrade --dry-run" }, "dependencies": { "commander": "^9.4.1", diff --git a/tools/cli.js b/tools/cli.js index 006427b6..b9794b84 100644 --- a/tools/cli.js +++ b/tools/cli.js @@ -2,6 +2,7 @@ const { Command } = require('commander'); const WebBuilder = require('./builders/web-builder'); +const V3ToV4Upgrader = require('./upgraders/v3-to-v4-upgrader'); const path = require('path'); const program = new Command(); @@ -84,4 +85,19 @@ program } }); +program + .command('upgrade') + .description('Upgrade a BMAD-METHOD V3 project to V4') + .option('-p, --project ', 'Path to V3 project (defaults to current directory)') + .option('--dry-run', 'Show what would be changed without making changes') + .option('--no-backup', 'Skip creating backup (not recommended)') + .action(async (options) => { + const upgrader = new V3ToV4Upgrader(); + await upgrader.upgrade({ + projectPath: options.project, + dryRun: options.dryRun, + backup: options.backup + }); + }); + program.parse(); \ No newline at end of file diff --git a/tools/installer/lib/ide-setup.js b/tools/installer/lib/ide-setup.js index f4f27d55..fcffadff 100644 --- a/tools/installer/lib/ide-setup.js +++ b/tools/installer/lib/ide-setup.js @@ -43,7 +43,7 @@ class IdeSetup { const mdcPath = path.join(cursorRulesDir, `${agentId}.mdc`); // Create MDC content with proper format - let mdcContent = '\n---\n'; + let mdcContent = '---\n'; mdcContent += 'description: \n'; mdcContent += 'globs: []\n'; mdcContent += 'alwaysApply: false\n'; diff --git a/tools/upgraders/v3-to-v4-upgrader.js b/tools/upgraders/v3-to-v4-upgrader.js new file mode 100644 index 00000000..a89395b6 --- /dev/null +++ b/tools/upgraders/v3-to-v4-upgrader.js @@ -0,0 +1,530 @@ +const fs = require('fs').promises; +const path = require('path'); +const chalk = require('chalk'); +const ora = require('ora'); +const glob = require('glob'); +const inquirer = require('inquirer'); +const { promisify } = require('util'); +const globAsync = promisify(glob); + +class V3ToV4Upgrader { + constructor() { + // Constructor remains empty + } + + async upgrade(options = {}) { + try { + // Keep readline open throughout the process + process.stdin.resume(); + + // 1. Welcome message + console.log(chalk.bold('\nWelcome to BMAD-METHOD V3 to V4 Upgrade Tool\n')); + console.log('This tool will help you upgrade your BMAD-METHOD V3 project to V4.\n'); + console.log(chalk.cyan('What this tool does:')); + console.log('- Creates a backup of your V3 files (.bmad-v3-backup/)'); + console.log('- Installs the new V4 .bmad-core structure'); + console.log('- Preserves your PRD, Architecture, and Stories in the new format\n'); + console.log(chalk.yellow('What this tool does NOT do:')); + console.log('- Modify your document content (use doc-migration-task after upgrade)'); + console.log('- Touch any files outside bmad-agent/ and docs/\n'); + + // 2. Get project path + const projectPath = await this.getProjectPath(options.projectPath); + + // 3. Validate V3 structure + const validation = await this.validateV3Project(projectPath); + if (!validation.isValid) { + console.error(chalk.red('\nError: This doesn\'t appear to be a V3 project.')); + console.error('Expected to find:'); + console.error('- bmad-agent/ directory'); + console.error('- docs/ directory\n'); + console.error('Please check you\'re in the correct directory and try again.'); + return; + } + + // 4. Pre-flight check + const analysis = await this.analyzeProject(projectPath); + await this.showPreflightCheck(analysis, options); + + if (!options.dryRun) { + const { confirm } = await inquirer.prompt([{ + type: 'confirm', + name: 'confirm', + message: 'Continue with upgrade?', + default: true + }]); + + if (!confirm) { + console.log('Upgrade cancelled.'); + return; + } + } + + // 5. Create backup + if (options.backup !== false && !options.dryRun) { + await this.createBackup(projectPath); + } + + // 6. Install V4 structure + if (!options.dryRun) { + await this.installV4Structure(projectPath); + } + + // 7. Migrate documents + if (!options.dryRun) { + await this.migrateDocuments(projectPath, analysis); + } + + // 8. Setup IDE + if (!options.dryRun) { + await this.setupIDE(projectPath); + } + + // 9. Show completion report + this.showCompletionReport(projectPath, analysis); + + process.exit(0); + } catch (error) { + console.error(chalk.red('\nUpgrade error:'), error.message); + process.exit(1); + } + } + + async getProjectPath(providedPath) { + if (providedPath) { + return path.resolve(providedPath); + } + + const { projectPath } = await inquirer.prompt([{ + type: 'input', + name: 'projectPath', + message: 'Please enter the path to your V3 project:', + default: process.cwd() + }]); + + return path.resolve(projectPath); + } + + async validateV3Project(projectPath) { + const spinner = ora('Validating project structure...').start(); + + try { + const bmadAgentPath = path.join(projectPath, 'bmad-agent'); + const docsPath = path.join(projectPath, 'docs'); + + const hasBmadAgent = await this.pathExists(bmadAgentPath); + const hasDocs = await this.pathExists(docsPath); + + if (hasBmadAgent) { + spinner.text = '✓ Found bmad-agent/ directory'; + console.log(chalk.green('\n✓ Found bmad-agent/ directory')); + } + + if (hasDocs) { + console.log(chalk.green('✓ Found docs/ directory')); + } + + const isValid = hasBmadAgent && hasDocs; + + if (isValid) { + spinner.succeed('This appears to be a valid V3 project'); + } else { + spinner.fail('Invalid V3 project structure'); + } + + return { isValid, hasBmadAgent, hasDocs }; + } catch (error) { + spinner.fail('Validation failed'); + throw error; + } + } + + async analyzeProject(projectPath) { + const docsPath = path.join(projectPath, 'docs'); + const bmadAgentPath = path.join(projectPath, 'bmad-agent'); + + // Find PRD + const prdCandidates = ['prd.md', 'PRD.md', 'product-requirements.md']; + let prdFile = null; + for (const candidate of prdCandidates) { + const candidatePath = path.join(docsPath, candidate); + if (await this.pathExists(candidatePath)) { + prdFile = candidate; + break; + } + } + + // Find Architecture + const archCandidates = ['architecture.md', 'Architecture.md', 'technical-architecture.md']; + let archFile = null; + for (const candidate of archCandidates) { + const candidatePath = path.join(docsPath, candidate); + if (await this.pathExists(candidatePath)) { + archFile = candidate; + break; + } + } + + // Find Front-end Architecture (V3 specific) + const frontEndCandidates = ['front-end-architecture.md', 'frontend-architecture.md', 'ui-architecture.md']; + let frontEndArchFile = null; + for (const candidate of frontEndCandidates) { + const candidatePath = path.join(docsPath, candidate); + if (await this.pathExists(candidatePath)) { + frontEndArchFile = candidate; + break; + } + } + + // Find epic files + const epicFiles = await globAsync('epic*.md', { cwd: docsPath }); + + // Find story files + const storiesPath = path.join(docsPath, 'stories'); + let storyFiles = []; + if (await this.pathExists(storiesPath)) { + storyFiles = await globAsync('*.md', { cwd: storiesPath }); + } + + // Count custom files in bmad-agent + const bmadAgentFiles = await globAsync('**/*.md', { + cwd: bmadAgentPath, + ignore: ['node_modules/**'] + }); + + return { + prdFile, + archFile, + frontEndArchFile, + epicFiles, + storyFiles, + customFileCount: bmadAgentFiles.length + }; + } + + async showPreflightCheck(analysis, options) { + console.log(chalk.bold('\nProject Analysis:')); + console.log(`- PRD found: ${analysis.prdFile ? `docs/${analysis.prdFile}` : chalk.yellow('Not found')}`); + console.log(`- Architecture found: ${analysis.archFile ? `docs/${analysis.archFile}` : chalk.yellow('Not found')}`); + if (analysis.frontEndArchFile) { + console.log(`- Front-end Architecture found: docs/${analysis.frontEndArchFile}`); + } + console.log(`- Epic files found: ${analysis.epicFiles.length} files (epic*.md)`); + console.log(`- Stories found: ${analysis.storyFiles.length} files in docs/stories/`); + console.log(`- Custom files in bmad-agent/: ${analysis.customFileCount}`); + + if (!options.dryRun) { + console.log('\nThe following will be backed up to .bmad-v3-backup/:'); + console.log('- bmad-agent/ (entire directory)'); + console.log('- docs/ (entire directory)'); + + if (analysis.epicFiles.length > 0) { + console.log(chalk.green('\nNote: Epic files found! They will be placed in docs/prd/ with an index.md file.')); + console.log(chalk.green('Since epic files exist, you won\'t need to shard the PRD after upgrade.')); + } + } + } + + async createBackup(projectPath) { + const spinner = ora('Creating backup...').start(); + + try { + const backupPath = path.join(projectPath, '.bmad-v3-backup'); + + // Check if backup already exists + if (await this.pathExists(backupPath)) { + spinner.fail('Backup directory already exists'); + console.error(chalk.red('\nError: Backup directory .bmad-v3-backup/ already exists.')); + console.error('\nThis might mean an upgrade was already attempted.'); + console.error('Please remove or rename the existing backup and try again.'); + throw new Error('Backup already exists'); + } + + // Create backup directory + await fs.mkdir(backupPath, { recursive: true }); + spinner.text = '✓ Created .bmad-v3-backup/'; + console.log(chalk.green('\n✓ Created .bmad-v3-backup/')); + + // Move bmad-agent + const bmadAgentSrc = path.join(projectPath, 'bmad-agent'); + const bmadAgentDest = path.join(backupPath, 'bmad-agent'); + await fs.rename(bmadAgentSrc, bmadAgentDest); + console.log(chalk.green('✓ Moved bmad-agent/ to backup')); + + // Move docs + const docsSrc = path.join(projectPath, 'docs'); + const docsDest = path.join(backupPath, 'docs'); + await fs.rename(docsSrc, docsDest); + console.log(chalk.green('✓ Moved docs/ to backup')); + + spinner.succeed('Backup created successfully'); + } catch (error) { + spinner.fail('Backup failed'); + throw error; + } + } + + async installV4Structure(projectPath) { + const spinner = ora('Installing V4 structure...').start(); + + try { + // Get the source .bmad-core directory + const sourcePath = path.join(__dirname, '..', '..', '.bmad-core'); + const destPath = path.join(projectPath, '.bmad-core'); + + // Copy .bmad-core + await this.copyDirectory(sourcePath, destPath); + spinner.text = '✓ Copied fresh .bmad-core/ directory from V4'; + console.log(chalk.green('\n✓ Copied fresh .bmad-core/ directory from V4')); + + // Create docs directory + const docsPath = path.join(projectPath, 'docs'); + await fs.mkdir(docsPath, { recursive: true }); + console.log(chalk.green('✓ Created new docs/ directory')); + + console.log(chalk.yellow('\nNote: Your V3 bmad-agent content has been backed up and NOT migrated.')); + console.log(chalk.yellow('The new V4 agents are completely different and look for different file structures.')); + + spinner.succeed('V4 structure installed successfully'); + } catch (error) { + spinner.fail('V4 installation failed'); + throw error; + } + } + + async migrateDocuments(projectPath, analysis) { + const spinner = ora('Migrating your project documents...').start(); + + try { + const backupDocsPath = path.join(projectPath, '.bmad-v3-backup', 'docs'); + const newDocsPath = path.join(projectPath, 'docs'); + let copiedCount = 0; + + // Copy PRD + if (analysis.prdFile) { + const src = path.join(backupDocsPath, analysis.prdFile); + const dest = path.join(newDocsPath, analysis.prdFile); + await fs.copyFile(src, dest); + console.log(chalk.green(`\n✓ Copied PRD to docs/${analysis.prdFile}`)); + copiedCount++; + } + + // Copy Architecture + if (analysis.archFile) { + const src = path.join(backupDocsPath, analysis.archFile); + const dest = path.join(newDocsPath, analysis.archFile); + await fs.copyFile(src, dest); + console.log(chalk.green(`✓ Copied Architecture to docs/${analysis.archFile}`)); + copiedCount++; + } + + // Copy Front-end Architecture if exists + if (analysis.frontEndArchFile) { + const src = path.join(backupDocsPath, analysis.frontEndArchFile); + const dest = path.join(newDocsPath, analysis.frontEndArchFile); + await fs.copyFile(src, dest); + console.log(chalk.green(`✓ Copied Front-end Architecture to docs/${analysis.frontEndArchFile}`)); + console.log(chalk.yellow('Note: V4 uses a single full-stack-architecture.md - use doc-migration-task to merge')); + copiedCount++; + } + + // Copy stories + if (analysis.storyFiles.length > 0) { + const storiesDir = path.join(newDocsPath, 'stories'); + await fs.mkdir(storiesDir, { recursive: true }); + + for (const storyFile of analysis.storyFiles) { + const src = path.join(backupDocsPath, 'stories', storyFile); + const dest = path.join(storiesDir, storyFile); + await fs.copyFile(src, dest); + } + console.log(chalk.green(`✓ Copied ${analysis.storyFiles.length} story files to docs/stories/`)); + copiedCount += analysis.storyFiles.length; + } + + // Copy epic files to prd subfolder + if (analysis.epicFiles.length > 0) { + const prdDir = path.join(newDocsPath, 'prd'); + await fs.mkdir(prdDir, { recursive: true }); + + for (const epicFile of analysis.epicFiles) { + const src = path.join(backupDocsPath, epicFile); + const dest = path.join(prdDir, epicFile); + await fs.copyFile(src, dest); + } + console.log(chalk.green(`✓ Found and copied ${analysis.epicFiles.length} epic files to docs/prd/`)); + + // Create index.md for the prd folder + await this.createPrdIndex(projectPath, analysis); + console.log(chalk.green('✓ Created index.md in docs/prd/')); + + console.log(chalk.green('\nNote: Epic files detected! These are compatible with V4 and have been copied.')); + console.log(chalk.green('You won\'t need to shard the PRD since epics already exist.')); + copiedCount += analysis.epicFiles.length; + } + + spinner.succeed(`Migrated ${copiedCount} documents successfully`); + } catch (error) { + spinner.fail('Document migration failed'); + throw error; + } + } + + async setupIDE(projectPath) { + const { ide } = await inquirer.prompt([{ + type: 'list', + name: 'ide', + message: 'Which IDE are you using?', + choices: [ + { name: 'Cursor', value: 'cursor' }, + { name: 'Claude Code', value: 'claude-code' }, + { name: 'Windsurf', value: 'windsurf' }, + { name: 'VS Code', value: 'skip' }, + { name: 'Other/Skip', value: 'skip' } + ] + }]); + + const selectedIde = ide === 'skip' ? null : ide; + + if (selectedIde) { + const ideSetup = require('../installer/lib/ide-setup'); + const spinner = ora('Setting up IDE rules for all agents...').start(); + + try { + await ideSetup.setup(selectedIde, projectPath); + spinner.succeed('IDE setup complete!'); + + const ideMessages = { + 'cursor': 'Rules created in .cursor/rules/', + 'claude-code': 'Commands created in .claude/commands/', + 'windsurf': 'Rules created in .windsurf/rules/' + }; + + console.log(chalk.green(`- ${ideMessages[selectedIde]}`)); + } catch (error) { + spinner.fail('IDE setup failed'); + console.error(chalk.yellow('IDE setup failed, but upgrade is complete.')); + } + } + } + + showCompletionReport(projectPath, analysis) { + console.log(chalk.bold.green('\n✓ Upgrade Complete!\n')); + console.log(chalk.bold('Summary:')); + console.log(`- V3 files backed up to: .bmad-v3-backup/`); + console.log(`- V4 structure installed: .bmad-core/ (fresh from V4)`); + + const totalDocs = (analysis.prdFile ? 1 : 0) + + (analysis.archFile ? 1 : 0) + + (analysis.frontEndArchFile ? 1 : 0) + + analysis.storyFiles.length; + console.log(`- Documents migrated: ${totalDocs} files${analysis.epicFiles.length > 0 ? ` + ${analysis.epicFiles.length} epics` : ''}`); + + console.log(chalk.bold('\nImportant Changes:')); + console.log('- The V4 agents (sm, dev, etc.) expect different file structures than V3'); + console.log('- Your V3 bmad-agent content was NOT migrated (it\'s incompatible)'); + if (analysis.epicFiles.length > 0) { + console.log('- Epic files were found and copied - no PRD sharding needed!'); + } + if (analysis.frontEndArchFile) { + console.log('- Front-end architecture found - V4 uses full-stack-architecture.md, migration needed'); + } + + console.log(chalk.bold('\nNext Steps:')); + console.log('1. Review your documents in the new docs/ folder'); + console.log('2. Use @bmad-master agent to run the doc-migration-task to align your documents with V4 templates'); + if (analysis.epicFiles.length === 0) { + console.log('3. Use @bmad-master agent to shard the PRD to create epic files'); + } + + console.log(chalk.dim('\nYour V3 backup is preserved in .bmad-v3-backup/ and can be restored if needed.')); + } + + async pathExists(filePath) { + try { + await fs.access(filePath); + return true; + } catch { + return false; + } + } + + async copyDirectory(src, dest) { + await fs.mkdir(dest, { recursive: true }); + const entries = await fs.readdir(src, { withFileTypes: true }); + + for (const entry of entries) { + const srcPath = path.join(src, entry.name); + const destPath = path.join(dest, entry.name); + + if (entry.isDirectory()) { + await this.copyDirectory(srcPath, destPath); + } else { + await fs.copyFile(srcPath, destPath); + } + } + } + + async createPrdIndex(projectPath, analysis) { + const prdIndexPath = path.join(projectPath, 'docs', 'prd', 'index.md'); + const prdPath = path.join(projectPath, 'docs', analysis.prdFile || 'prd.md'); + + let indexContent = '# Product Requirements Document\n\n'; + + // Try to read the PRD to get the title and intro content + if (analysis.prdFile && await this.pathExists(prdPath)) { + try { + const prdContent = await fs.readFile(prdPath, 'utf8'); + const lines = prdContent.split('\n'); + + // Find the first heading + const titleMatch = lines.find(line => line.startsWith('# ')); + if (titleMatch) { + indexContent = titleMatch + '\n\n'; + } + + // Get any content before the first ## section + let introContent = ''; + let foundFirstSection = false; + for (const line of lines) { + if (line.startsWith('## ')) { + foundFirstSection = true; + break; + } + if (!line.startsWith('# ')) { + introContent += line + '\n'; + } + } + + if (introContent.trim()) { + indexContent += introContent.trim() + '\n\n'; + } + } catch (error) { + // If we can't read the PRD, just use default content + } + } + + // Add sections list + indexContent += '## Sections\n\n'; + + // Sort epic files for consistent ordering + const sortedEpics = [...analysis.epicFiles].sort(); + + for (const epicFile of sortedEpics) { + // Extract epic name from filename + const epicName = epicFile + .replace(/\.md$/, '') + .replace(/^epic-?/i, '') + .replace(/-/g, ' ') + .replace(/^\d+\s*/, '') // Remove leading numbers + .trim(); + + const displayName = epicName.charAt(0).toUpperCase() + epicName.slice(1); + indexContent += `- [${displayName || epicFile.replace('.md', '')}](./${epicFile})\n`; + } + + await fs.writeFile(prdIndexPath, indexContent); + } +} + +module.exports = V3ToV4Upgrader; \ No newline at end of file