bmad-method 6.0.0-alpha.0 → 6.0.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/bmad/bmb/agents/bmad-builder.md +70 -0
- package/.claude/commands/bmad/bmb/workflows/README.md +67 -0
- package/.claude/commands/bmad/bmb/workflows/audit-workflow.md +15 -0
- package/.claude/commands/bmad/bmb/workflows/convert-legacy.md +15 -0
- package/.claude/commands/bmad/bmb/workflows/create-agent.md +15 -0
- package/.claude/commands/bmad/bmb/workflows/create-module.md +15 -0
- package/.claude/commands/bmad/bmb/workflows/create-workflow.md +15 -0
- package/.claude/commands/bmad/bmb/workflows/edit-agent.md +15 -0
- package/.claude/commands/bmad/bmb/workflows/edit-module.md +15 -0
- package/.claude/commands/bmad/bmb/workflows/edit-workflow.md +15 -0
- package/.claude/commands/bmad/bmb/workflows/module-brief.md +15 -0
- package/.claude/commands/bmad/bmb/workflows/redoc.md +15 -0
- package/.claude/commands/bmad/bmd/agents/cli-chief.md +108 -0
- package/.claude/commands/bmad/bmd/agents/doc-keeper.md +115 -0
- package/.claude/commands/bmad/bmd/agents/release-chief.md +109 -0
- package/.claude/commands/bmad/core/agents/bmad-master.md +71 -0
- package/.claude/commands/bmad/core/tasks/index-docs.md +9 -0
- package/.claude/commands/bmad/core/tools/shard-doc.md +9 -0
- package/.claude/commands/bmad/core/workflows/README.md +27 -0
- package/.claude/commands/bmad/core/workflows/brainstorming.md +15 -0
- package/.claude/commands/bmad/core/workflows/party-mode.md +15 -0
- package/.claude/hooks/bmad-tts-injector.sh +415 -0
- package/.claude/hooks/bmad-voice-manager.sh +511 -0
- package/.claude/hooks/check-output-style.sh +112 -0
- package/.claude/hooks/download-extra-voices.sh +244 -0
- package/.claude/hooks/github-star-reminder.sh +154 -0
- package/.claude/hooks/language-manager.sh +392 -0
- package/.claude/hooks/learn-manager.sh +475 -0
- package/.claude/hooks/personality-manager.sh +438 -0
- package/.claude/hooks/piper-download-voices.sh +165 -0
- package/.claude/hooks/piper-installer.sh +178 -0
- package/.claude/hooks/piper-multispeaker-registry.sh +165 -0
- package/.claude/hooks/piper-voice-manager.sh +293 -0
- package/.claude/hooks/play-tts-elevenlabs.sh +404 -0
- package/.claude/hooks/play-tts-piper.sh +338 -0
- package/.claude/hooks/play-tts.sh +100 -0
- package/.claude/hooks/provider-commands.sh +540 -0
- package/.claude/hooks/provider-manager.sh +298 -0
- package/.claude/hooks/replay-target-audio.sh +95 -0
- package/.claude/hooks/sentiment-manager.sh +201 -0
- package/.claude/hooks/speed-manager.sh +291 -0
- package/.claude/hooks/voice-manager.sh +594 -0
- package/.claude/hooks/voices-config.sh +70 -0
- package/.claude/settings.local.json +41 -0
- package/.github/ISSUE_TEMPLATE/config.yaml +4 -0
- package/.github/ISSUE_TEMPLATE/idea_submission.md +2 -2
- package/.github/workflows/{format-check.yaml → lint.yaml} +19 -1
- package/.prettierignore +2 -0
- package/CHANGELOG.md +8 -2
- package/CONTRIBUTING.md +1 -0
- package/README.md +263 -0
- package/bmad/_cfg/agent-manifest.csv +7 -0
- package/bmad/_cfg/agents/bmb-bmad-builder.customize.yaml +42 -0
- package/bmad/_cfg/agents/bmd-cli-chief.customize.yaml +32 -0
- package/bmad/_cfg/agents/bmd-doc-keeper.customize.yaml +42 -0
- package/bmad/_cfg/agents/bmd-release-chief.customize.yaml +42 -0
- package/bmad/_cfg/agents/core-bmad-master.customize.yaml +42 -0
- package/bmad/_cfg/files-manifest.csv +83 -0
- package/bmad/_cfg/manifest.yaml +12 -0
- package/bmad/_cfg/task-manifest.csv +5 -0
- package/bmad/_cfg/tool-manifest.csv +2 -0
- package/bmad/_cfg/workflow-manifest.csv +15 -0
- package/bmad/bmb/README.md +132 -0
- package/bmad/bmb/agents/bmad-builder.md +70 -0
- package/bmad/bmb/config.yaml +14 -0
- package/bmad/bmb/workflows/audit-workflow/checklist.md +143 -0
- package/bmad/bmb/workflows/audit-workflow/instructions.md +341 -0
- package/bmad/bmb/workflows/audit-workflow/template.md +118 -0
- package/bmad/bmb/workflows/audit-workflow/workflow.yaml +23 -0
- package/bmad/bmb/workflows/audit-workflow/workflow.yaml.bak +21 -0
- package/bmad/bmb/workflows/convert-legacy/README.md +262 -0
- package/bmad/bmb/workflows/convert-legacy/checklist.md +205 -0
- package/bmad/bmb/workflows/convert-legacy/instructions.md +377 -0
- package/bmad/bmb/workflows/convert-legacy/workflow.yaml +32 -0
- package/bmad/bmb/workflows/create-agent/README.md +320 -0
- package/bmad/bmb/workflows/create-agent/agent-architecture.md +419 -0
- package/bmad/bmb/workflows/create-agent/agent-architecture.md.bak +412 -0
- package/bmad/bmb/workflows/create-agent/agent-command-patterns.md +759 -0
- package/bmad/bmb/workflows/create-agent/agent-command-patterns.md.bak +759 -0
- package/bmad/bmb/workflows/create-agent/agent-types.md +292 -0
- package/bmad/bmb/workflows/create-agent/brainstorm-context.md +174 -0
- package/bmad/bmb/workflows/create-agent/checklist.md +62 -0
- package/bmad/bmb/workflows/create-agent/communication-styles.md +202 -0
- package/bmad/bmb/workflows/create-agent/instructions.md +430 -0
- package/bmad/bmb/workflows/create-agent/workflow.yaml +37 -0
- package/bmad/bmb/workflows/create-module/README.md +220 -0
- package/bmad/bmb/workflows/create-module/README.md.bak +218 -0
- package/bmad/bmb/workflows/create-module/brainstorm-context.md +137 -0
- package/bmad/bmb/workflows/create-module/checklist.md +244 -0
- package/bmad/bmb/workflows/create-module/checklist.md.bak +245 -0
- package/bmad/bmb/workflows/create-module/installer-templates/install-config.yaml +92 -0
- package/bmad/bmb/workflows/create-module/installer-templates/installer.js +231 -0
- package/bmad/bmb/workflows/create-module/installer-templates/installer.js.bak +231 -0
- package/bmad/bmb/workflows/create-module/instructions.md +581 -0
- package/bmad/bmb/workflows/create-module/instructions.md.bak +521 -0
- package/bmad/bmb/workflows/create-module/module-structure.md +366 -0
- package/bmad/bmb/workflows/create-module/module-structure.md.bak +310 -0
- package/bmad/bmb/workflows/create-module/workflow.yaml +42 -0
- package/bmad/bmb/workflows/create-module/workflow.yaml.bak +40 -0
- package/bmad/bmb/workflows/create-workflow/README.md +277 -0
- package/bmad/bmb/workflows/create-workflow/brainstorm-context.md +197 -0
- package/bmad/bmb/workflows/create-workflow/checklist.md +94 -0
- package/bmad/bmb/workflows/create-workflow/instructions.md +716 -0
- package/bmad/bmb/workflows/create-workflow/workflow-creation-guide.md +1150 -0
- package/bmad/bmb/workflows/create-workflow/workflow-template/checklist.md +24 -0
- package/bmad/bmb/workflows/create-workflow/workflow-template/instructions.md +13 -0
- package/bmad/bmb/workflows/create-workflow/workflow-template/template.md +9 -0
- package/bmad/bmb/workflows/create-workflow/workflow-template/workflow.yaml +39 -0
- package/bmad/bmb/workflows/create-workflow/workflow-template/workflow.yaml.bak +39 -0
- package/bmad/bmb/workflows/create-workflow/workflow.yaml +40 -0
- package/bmad/bmb/workflows/create-workflow/workflow.yaml.bak +38 -0
- package/bmad/bmb/workflows/edit-agent/README.md +112 -0
- package/bmad/bmb/workflows/edit-agent/checklist.md +112 -0
- package/bmad/bmb/workflows/edit-agent/instructions.md +290 -0
- package/bmad/bmb/workflows/edit-agent/workflow.yaml +33 -0
- package/bmad/bmb/workflows/edit-module/README.md +187 -0
- package/bmad/bmb/workflows/edit-module/checklist.md +165 -0
- package/bmad/bmb/workflows/edit-module/instructions.md +339 -0
- package/bmad/bmb/workflows/edit-module/workflow.yaml +34 -0
- package/bmad/bmb/workflows/edit-workflow/README.md +119 -0
- package/bmad/bmb/workflows/edit-workflow/checklist.md +70 -0
- package/bmad/bmb/workflows/edit-workflow/instructions.md +342 -0
- package/bmad/bmb/workflows/edit-workflow/workflow.yaml +27 -0
- package/bmad/bmb/workflows/edit-workflow/workflow.yaml.bak +25 -0
- package/bmad/bmb/workflows/module-brief/README.md +264 -0
- package/bmad/bmb/workflows/module-brief/checklist.md +116 -0
- package/bmad/bmb/workflows/module-brief/instructions.md +267 -0
- package/bmad/bmb/workflows/module-brief/template.md +275 -0
- package/bmad/bmb/workflows/module-brief/workflow.yaml +29 -0
- package/bmad/bmb/workflows/module-brief/workflow.yaml.bak +27 -0
- package/bmad/bmb/workflows/redoc/README.md +87 -0
- package/bmad/bmb/workflows/redoc/checklist.md +99 -0
- package/bmad/bmb/workflows/redoc/instructions.md +265 -0
- package/bmad/bmb/workflows/redoc/workflow.yaml +32 -0
- package/bmad/bmb/workflows/redoc/workflow.yaml.bak +31 -0
- package/bmad/bmd/README.md +193 -0
- package/bmad/bmd/README.md.bak +193 -0
- package/bmad/bmd/agents/cli-chief-sidecar/instructions.md +102 -0
- package/bmad/bmd/agents/cli-chief-sidecar/instructions.md.bak +102 -0
- package/bmad/bmd/agents/cli-chief-sidecar/knowledge/README.md +68 -0
- package/bmad/bmd/agents/cli-chief-sidecar/knowledge/README.md.bak +68 -0
- package/bmad/bmd/agents/cli-chief-sidecar/knowledge/cli-reference.md +123 -0
- package/bmad/bmd/agents/cli-chief-sidecar/knowledge/cli-reference.md.bak +123 -0
- package/bmad/bmd/agents/cli-chief-sidecar/memories.md +53 -0
- package/bmad/bmd/agents/cli-chief-sidecar/memories.md.bak +53 -0
- package/bmad/bmd/agents/cli-chief.md +108 -0
- package/bmad/bmd/agents/cli-chief.md.bak +108 -0
- package/bmad/bmd/agents/doc-keeper-sidecar/instructions.md +177 -0
- package/bmad/bmd/agents/doc-keeper-sidecar/instructions.md.bak +177 -0
- package/bmad/bmd/agents/doc-keeper-sidecar/knowledge/README.md +81 -0
- package/bmad/bmd/agents/doc-keeper-sidecar/knowledge/README.md.bak +81 -0
- package/bmad/bmd/agents/doc-keeper-sidecar/memories.md +88 -0
- package/bmad/bmd/agents/doc-keeper-sidecar/memories.md.bak +88 -0
- package/bmad/bmd/agents/doc-keeper.md +115 -0
- package/bmad/bmd/agents/doc-keeper.md.bak +115 -0
- package/bmad/bmd/agents/release-chief-sidecar/instructions.md +164 -0
- package/bmad/bmd/agents/release-chief-sidecar/instructions.md.bak +164 -0
- package/bmad/bmd/agents/release-chief-sidecar/knowledge/README.md +82 -0
- package/bmad/bmd/agents/release-chief-sidecar/knowledge/README.md.bak +82 -0
- package/bmad/bmd/agents/release-chief-sidecar/memories.md +73 -0
- package/bmad/bmd/agents/release-chief-sidecar/memories.md.bak +73 -0
- package/bmad/bmd/agents/release-chief.md +109 -0
- package/bmad/bmd/agents/release-chief.md.bak +109 -0
- package/bmad/bmd/config.yaml +10 -0
- package/bmad/core/agents/bmad-master.md +71 -0
- package/bmad/core/agents/bmad-web-orchestrator.agent.xml +122 -0
- package/bmad/core/config.yaml +9 -0
- package/bmad/core/tasks/adv-elicit-methods.csv +39 -0
- package/{src/core/tasks/adv-elicit.md → bmad/core/tasks/adv-elicit.xml} +6 -11
- package/{src/core/tasks/index-docs.md → bmad/core/tasks/index-docs.xml} +6 -10
- package/{src/core/tasks/validate-workflow.md → bmad/core/tasks/validate-workflow.xml} +4 -7
- package/bmad/core/tasks/workflow.xml +174 -0
- package/bmad/core/tools/shard-doc.xml +100 -0
- package/{src/modules/cis → bmad/core}/workflows/brainstorming/README.md +2 -2
- package/{src/modules/cis → bmad/core}/workflows/brainstorming/instructions.md +26 -22
- package/{src/modules/cis → bmad/core}/workflows/brainstorming/template.md +2 -2
- package/{src/modules/cis → bmad/core}/workflows/brainstorming/workflow.yaml +16 -3
- package/bmad/core/workflows/party-mode/instructions.md +188 -0
- package/bmad/core/workflows/party-mode/workflow.yaml +23 -0
- package/bmad/docs/claude-code-instructions.md +25 -0
- package/bmad/docs/codex-instructions.md +21 -0
- package/bmd/README.md +193 -0
- package/bmd/agents/cli-chief-sidecar/instructions.md +102 -0
- package/bmd/agents/cli-chief-sidecar/knowledge/README.md +68 -0
- package/bmd/agents/cli-chief-sidecar/knowledge/cli-reference.md +123 -0
- package/bmd/agents/cli-chief-sidecar/memories.md +53 -0
- package/bmd/agents/cli-chief.agent.yaml +126 -0
- package/bmd/agents/doc-keeper-sidecar/instructions.md +177 -0
- package/bmd/agents/doc-keeper-sidecar/knowledge/README.md +81 -0
- package/bmd/agents/doc-keeper-sidecar/memories.md +88 -0
- package/bmd/agents/doc-keeper.agent.yaml +137 -0
- package/bmd/agents/release-chief-sidecar/instructions.md +164 -0
- package/bmd/agents/release-chief-sidecar/knowledge/README.md +82 -0
- package/bmd/agents/release-chief-sidecar/memories.md +73 -0
- package/bmd/agents/release-chief.agent.yaml +127 -0
- package/bmd/bmad-custom-module-installer-plan.md +1176 -0
- package/bmd/config.yaml +12 -0
- package/docs/bmad-brownfield-guide.md +1260 -0
- package/docs/conversion-report-shard-doc-2025-10-26.md +188 -0
- package/docs/ide-info/auggie.md +2 -2
- package/docs/ide-info/claude-code.md +4 -4
- package/docs/ide-info/codex.md +9 -20
- package/docs/ide-info/opencode.md +24 -0
- package/docs/installers-bundlers/ide-injections.md +0 -10
- package/docs/installers-bundlers/installers-modules-platforms-reference.md +22 -50
- package/docs/v4-to-v6-upgrade.md +225 -0
- package/eslint.config.mjs +4 -2
- package/package.json +11 -6
- package/src/core/_module-installer/{install-menu-config.yaml → install-config.yaml} +8 -4
- package/src/core/_module-installer/installer.js +1 -1
- package/src/core/agents/bmad-master.agent.yaml +39 -0
- package/src/core/agents/bmad-web-orchestrator.agent.xml +122 -0
- package/src/core/tasks/adv-elicit.xml +104 -0
- package/src/core/tasks/index-docs.xml +65 -0
- package/src/core/tasks/validate-workflow.xml +89 -0
- package/src/core/tasks/{workflow.md → workflow.xml} +42 -17
- package/src/core/tools/shard-doc.xml +100 -0
- package/src/core/workflows/brainstorming/README.md +271 -0
- package/src/core/workflows/brainstorming/brain-methods.csv +36 -0
- package/src/core/workflows/brainstorming/instructions.md +314 -0
- package/src/core/workflows/brainstorming/template.md +102 -0
- package/src/core/workflows/brainstorming/workflow.yaml +43 -0
- package/src/core/workflows/party-mode/instructions.md +30 -23
- package/src/core/workflows/party-mode/workflow.yaml +7 -8
- package/src/modules/bmb/README.md +132 -0
- package/src/modules/bmb/_module-installer/install-config.yaml +26 -0
- package/src/modules/bmb/agents/bmad-builder.agent.yaml +58 -0
- package/src/modules/bmb/workflows/audit-workflow/checklist.md +143 -0
- package/src/modules/bmb/workflows/audit-workflow/instructions.md +341 -0
- package/src/modules/bmb/workflows/audit-workflow/template.md +118 -0
- package/src/modules/bmb/workflows/audit-workflow/workflow.yaml +25 -0
- package/src/modules/bmb/workflows/convert-legacy/README.md +32 -32
- package/src/modules/bmb/workflows/convert-legacy/checklist.md +21 -20
- package/src/modules/bmb/workflows/convert-legacy/instructions.md +130 -81
- package/src/modules/bmb/workflows/convert-legacy/workflow.yaml +7 -8
- package/src/modules/bmb/workflows/create-agent/README.md +96 -44
- package/src/modules/bmb/workflows/create-agent/agent-architecture.md +58 -51
- package/src/modules/bmb/workflows/create-agent/agent-command-patterns.md +153 -151
- package/src/modules/bmb/workflows/create-agent/agent-types.md +137 -22
- package/src/modules/bmb/workflows/create-agent/brainstorm-context.md +4 -4
- package/src/modules/bmb/workflows/create-agent/checklist.md +30 -102
- package/src/modules/bmb/workflows/create-agent/communication-styles.md +22 -60
- package/src/modules/bmb/workflows/create-agent/instructions.md +309 -219
- package/src/modules/bmb/workflows/create-agent/workflow.yaml +24 -14
- package/src/modules/bmb/workflows/create-module/README.md +23 -21
- package/src/modules/bmb/workflows/create-module/brainstorm-context.md +1 -1
- package/src/modules/bmb/workflows/create-module/checklist.md +20 -21
- package/src/modules/bmb/workflows/create-module/installer-templates/install-config.yaml +92 -0
- package/src/modules/bmb/workflows/create-module/installer-templates/installer.js +1 -1
- package/src/modules/bmb/workflows/create-module/instructions.md +309 -237
- package/src/modules/bmb/workflows/create-module/module-structure.md +104 -48
- package/src/modules/bmb/workflows/create-module/workflow.yaml +14 -17
- package/src/modules/bmb/workflows/create-workflow/README.md +68 -7
- package/src/modules/bmb/workflows/create-workflow/brainstorm-context.md +4 -4
- package/src/modules/bmb/workflows/create-workflow/checklist.md +22 -0
- package/src/modules/bmb/workflows/create-workflow/instructions.md +496 -47
- package/src/modules/bmb/workflows/create-workflow/workflow-creation-guide.md +753 -59
- package/src/modules/bmb/workflows/create-workflow/workflow-template/instructions.md +4 -3
- package/src/modules/bmb/workflows/create-workflow/workflow-template/workflow.yaml +30 -0
- package/src/modules/bmb/workflows/create-workflow/workflow.yaml +11 -11
- package/src/modules/bmb/workflows/edit-agent/README.md +112 -0
- package/src/modules/bmb/workflows/edit-agent/checklist.md +112 -0
- package/src/modules/bmb/workflows/edit-agent/instructions.md +290 -0
- package/src/modules/bmb/workflows/edit-agent/workflow.yaml +35 -0
- package/src/modules/bmb/workflows/edit-module/README.md +187 -0
- package/src/modules/bmb/workflows/edit-module/checklist.md +165 -0
- package/src/modules/bmb/workflows/edit-module/instructions.md +339 -0
- package/src/modules/bmb/workflows/edit-module/workflow.yaml +36 -0
- package/src/modules/bmb/workflows/edit-workflow/README.md +58 -2
- package/src/modules/bmb/workflows/edit-workflow/instructions.md +289 -117
- package/src/modules/bmb/workflows/edit-workflow/workflow.yaml +5 -10
- package/src/modules/bmb/workflows/module-brief/README.md +16 -16
- package/src/modules/bmb/workflows/module-brief/checklist.md +4 -4
- package/src/modules/bmb/workflows/module-brief/instructions.md +9 -7
- package/src/modules/bmb/workflows/module-brief/template.md +9 -9
- package/src/modules/bmb/workflows/module-brief/workflow.yaml +5 -4
- package/src/modules/bmb/workflows/redoc/checklist.md +2 -2
- package/src/modules/bmb/workflows/redoc/instructions.md +20 -10
- package/src/modules/bmb/workflows/redoc/workflow.yaml +5 -4
- package/src/modules/bmm/README.md +141 -0
- package/src/modules/bmm/_module-installer/install-config.yaml +74 -0
- package/src/modules/bmm/_module-installer/installer.js +1 -1
- package/src/modules/bmm/_module-installer/platform-specifics/claude-code.js +1 -1
- package/src/modules/bmm/_module-installer/platform-specifics/windsurf.js +1 -1
- package/src/modules/bmm/agents/analyst.agent.yaml +43 -0
- package/src/modules/bmm/agents/architect.agent.yaml +41 -0
- package/src/modules/bmm/agents/dev.agent.yaml +43 -0
- package/src/modules/bmm/agents/game-architect.agent.yaml +35 -0
- package/src/modules/bmm/agents/game-designer.agent.yaml +47 -0
- package/src/modules/bmm/agents/game-dev.agent.yaml +39 -0
- package/src/modules/bmm/agents/pm.agent.yaml +50 -0
- package/src/modules/bmm/agents/sm.agent.yaml +67 -0
- package/src/modules/bmm/agents/tea.agent.yaml +59 -0
- package/src/modules/bmm/agents/ux-designer.agent.yaml +33 -0
- package/src/modules/bmm/sub-modules/claude-code/injections.yaml +1 -1
- package/src/modules/bmm/sub-modules/claude-code/readme.md +1 -1
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{api-documenter.md → bmad-analysis/api-documenter.md} +17 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{codebase-analyzer.md → bmad-analysis/codebase-analyzer.md} +19 -1
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{data-analyst.md → bmad-analysis/data-analyst.md} +17 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{pattern-detector.md → bmad-analysis/pattern-detector.md} +17 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{dependency-mapper.md → bmad-planning/dependency-mapper.md} +16 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{epic-optimizer.md → bmad-planning/epic-optimizer.md} +15 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{technical-decisions-curator.md → bmad-planning/technical-decisions-curator.md} +24 -2
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{trend-spotter.md → bmad-planning/trend-spotter.md} +16 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{user-journey-mapper.md → bmad-planning/user-journey-mapper.md} +22 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{user-researcher.md → bmad-planning/user-researcher.md} +16 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{market-researcher.md → bmad-research/market-researcher.md} +17 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{tech-debt-auditor.md → bmad-research/tech-debt-auditor.md} +17 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{document-reviewer.md → bmad-review/document-reviewer.md} +17 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{technical-evaluator.md → bmad-review/technical-evaluator.md} +17 -0
- package/src/modules/bmm/sub-modules/claude-code/sub-agents/{test-coverage-analyzer.md → bmad-review/test-coverage-analyzer.md} +17 -0
- package/src/modules/bmm/tasks/{daily-standup.md → daily-standup.xml} +21 -27
- package/src/modules/bmm/tasks/{retrospective.md → retrospective.xml} +22 -28
- package/src/modules/bmm/teams/team-fullstack.yaml +11 -0
- package/src/modules/bmm/teams/team-gamedev.yaml +5 -0
- package/src/modules/bmm/testarch/README.md +311 -0
- package/src/modules/bmm/testarch/knowledge/ci-burn-in.md +675 -0
- package/src/modules/bmm/testarch/knowledge/component-tdd.md +486 -0
- package/src/modules/bmm/testarch/knowledge/contract-testing.md +957 -0
- package/src/modules/bmm/testarch/knowledge/data-factories.md +500 -0
- package/src/modules/bmm/testarch/knowledge/email-auth.md +721 -0
- package/src/modules/bmm/testarch/knowledge/error-handling.md +725 -0
- package/src/modules/bmm/testarch/knowledge/feature-flags.md +750 -0
- package/src/modules/bmm/testarch/knowledge/fixture-architecture.md +401 -0
- package/src/modules/bmm/testarch/knowledge/network-first.md +486 -0
- package/src/modules/bmm/testarch/knowledge/nfr-criteria.md +670 -0
- package/src/modules/bmm/testarch/knowledge/playwright-config.md +730 -0
- package/src/modules/bmm/testarch/knowledge/probability-impact.md +601 -0
- package/src/modules/bmm/testarch/knowledge/risk-governance.md +615 -0
- package/src/modules/bmm/testarch/knowledge/selective-testing.md +732 -0
- package/src/modules/bmm/testarch/knowledge/selector-resilience.md +527 -0
- package/src/modules/bmm/testarch/knowledge/test-healing-patterns.md +644 -0
- package/src/modules/bmm/testarch/knowledge/test-levels-framework.md +473 -0
- package/src/modules/bmm/testarch/knowledge/test-priorities-matrix.md +373 -0
- package/src/modules/bmm/testarch/knowledge/test-quality.md +664 -0
- package/src/modules/bmm/testarch/knowledge/timing-debugging.md +372 -0
- package/src/modules/bmm/testarch/knowledge/visual-debugging.md +524 -0
- package/src/modules/bmm/testarch/tea-index.csv +22 -0
- package/src/modules/bmm/workflows/1-analysis/brainstorm-game/README.md +38 -0
- package/src/modules/bmm/workflows/1-analysis/brainstorm-game/game-context.md +3 -3
- package/src/modules/bmm/workflows/1-analysis/brainstorm-game/instructions.md +74 -12
- package/src/modules/bmm/workflows/1-analysis/brainstorm-game/workflow.yaml +22 -3
- package/src/modules/bmm/workflows/1-analysis/brainstorm-project/README.md +29 -0
- package/src/modules/bmm/workflows/1-analysis/brainstorm-project/instructions.md +61 -8
- package/src/modules/bmm/workflows/1-analysis/brainstorm-project/project-context.md +4 -4
- package/src/modules/bmm/workflows/1-analysis/brainstorm-project/workflow.yaml +21 -3
- package/src/modules/bmm/workflows/1-analysis/game-brief/README.md +5 -5
- package/src/modules/bmm/workflows/1-analysis/game-brief/checklist.md +2 -2
- package/src/modules/bmm/workflows/1-analysis/game-brief/instructions.md +151 -311
- package/src/modules/bmm/workflows/1-analysis/game-brief/template.md +2 -2
- package/src/modules/bmm/workflows/1-analysis/game-brief/workflow.yaml +16 -6
- package/src/modules/bmm/workflows/1-analysis/product-brief/README.md +4 -4
- package/src/modules/bmm/workflows/1-analysis/product-brief/checklist.md +2 -2
- package/src/modules/bmm/workflows/1-analysis/product-brief/instructions.md +147 -179
- package/src/modules/bmm/workflows/1-analysis/product-brief/template.md +4 -4
- package/src/modules/bmm/workflows/1-analysis/product-brief/workflow.yaml +16 -6
- package/src/modules/bmm/workflows/1-analysis/research/README.md +3 -3
- package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-competitor-analyzer.md +1 -1
- package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-market-researcher.md +2 -2
- package/src/modules/bmm/workflows/1-analysis/research/claude-code/sub-agents/bmm-trend-spotter.md +2 -2
- package/src/modules/bmm/workflows/1-analysis/research/instructions-deep-prompt.md +80 -17
- package/src/modules/bmm/workflows/1-analysis/research/instructions-market.md +71 -11
- package/src/modules/bmm/workflows/1-analysis/research/instructions-router.md +72 -38
- package/src/modules/bmm/workflows/1-analysis/research/instructions-technical.md +73 -14
- package/src/modules/bmm/workflows/1-analysis/research/template-deep-prompt.md +1 -1
- package/src/modules/bmm/workflows/1-analysis/research/template-market.md +1 -1
- package/src/modules/bmm/workflows/1-analysis/research/workflow.yaml +21 -121
- package/src/modules/bmm/workflows/2-plan-workflows/README.md +258 -0
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/checklist.md +310 -0
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/instructions.md +1283 -0
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/ux-design-template.md +145 -0
- package/src/modules/bmm/workflows/2-plan-workflows/create-ux-design/workflow.yaml +42 -0
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/README.md +16 -16
- package/src/modules/bmm/workflows/2-plan-workflows/gdd/checklist.md +148 -0
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/action-platformer.md +1 -1
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/adventure.md +1 -1
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/card-game.md +2 -2
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/fighting.md +1 -1
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/horror.md +2 -2
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/idle-incremental.md +1 -1
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/moba.md +4 -4
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/party-game.md +1 -1
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/racing.md +3 -3
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/rhythm.md +1 -1
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/roguelike.md +2 -2
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/rpg.md +3 -3
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/sandbox.md +4 -4
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/shooter.md +3 -3
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/simulation.md +3 -3
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/sports.md +3 -3
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/strategy.md +3 -3
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/survival.md +2 -2
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/text-based.md +3 -3
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/tower-defense.md +5 -5
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/turn-based-tactics.md +4 -4
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/visual-novel.md +1 -1
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/gdd-template.md +6 -12
- package/src/modules/bmm/workflows/2-plan-workflows/gdd/instructions-gdd.md +475 -0
- package/src/modules/bmm/workflows/2-plan-workflows/gdd/workflow.yaml +67 -0
- package/src/modules/bmm/workflows/2-plan-workflows/narrative/checklist.md +139 -0
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/narrative/instructions-narrative.md +52 -12
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/narrative/narrative-template.md +8 -8
- package/src/modules/bmm/workflows/2-plan-workflows/narrative/workflow.yaml +38 -0
- package/src/modules/bmm/workflows/2-plan-workflows/prd/checklist.md +117 -0
- package/src/modules/bmm/workflows/2-plan-workflows/prd/epics-template.md +63 -0
- package/src/modules/bmm/workflows/2-plan-workflows/prd/instructions.md +449 -0
- package/src/modules/bmm/workflows/2-plan-workflows/prd/prd-template.md +62 -0
- package/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.yaml +46 -0
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/checklist.md +107 -0
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/epics-template.md +11 -0
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/instructions-level0-story.md +167 -0
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/instructions-level1-stories.md +278 -0
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/instructions.md +269 -0
- package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/tech-spec/tech-spec-template.md +0 -4
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/user-story-template.md +56 -0
- package/src/modules/bmm/workflows/2-plan-workflows/tech-spec/workflow.yaml +52 -0
- package/src/modules/bmm/workflows/3-solutioning/README.md +1 -565
- package/src/modules/bmm/workflows/3-solutioning/architecture/architecture-patterns.yaml +347 -0
- package/src/modules/bmm/workflows/3-solutioning/architecture/architecture-template.md +103 -0
- package/src/modules/bmm/workflows/3-solutioning/architecture/checklist.md +244 -0
- package/src/modules/bmm/workflows/3-solutioning/architecture/decision-catalog.yaml +222 -0
- package/src/modules/bmm/workflows/3-solutioning/architecture/instructions.md +703 -0
- package/src/modules/bmm/workflows/3-solutioning/architecture/pattern-categories.csv +13 -0
- package/src/modules/bmm/workflows/3-solutioning/architecture/readme.md +318 -0
- package/src/modules/bmm/workflows/3-solutioning/architecture/workflow.yaml +54 -0
- package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/README.md +177 -0
- package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/checklist.md +175 -0
- package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/instructions.md +273 -0
- package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/template.md +146 -0
- package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/validation-criteria.yaml +189 -0
- package/src/modules/bmm/workflows/3-solutioning/solutioning-gate-check/workflow.yaml +40 -0
- package/src/modules/bmm/workflows/4-implementation/README.md +221 -0
- package/src/modules/bmm/workflows/4-implementation/{review-story → code-review}/README.md +4 -7
- package/src/modules/bmm/workflows/4-implementation/code-review/instructions.md +391 -0
- package/src/modules/bmm/workflows/4-implementation/code-review/workflow.yaml +56 -0
- package/src/modules/bmm/workflows/4-implementation/correct-course/README.md +73 -0
- package/src/modules/bmm/workflows/4-implementation/correct-course/checklist.md +5 -5
- package/src/modules/bmm/workflows/4-implementation/correct-course/instructions.md +64 -53
- package/src/modules/bmm/workflows/4-implementation/correct-course/workflow.yaml +10 -0
- package/src/modules/bmm/workflows/4-implementation/create-story/README.md +117 -30
- package/src/modules/bmm/workflows/4-implementation/create-story/checklist.md +240 -39
- package/src/modules/bmm/workflows/4-implementation/create-story/instructions.md +193 -22
- package/src/modules/bmm/workflows/4-implementation/create-story/template.md +2 -8
- package/src/modules/bmm/workflows/4-implementation/create-story/workflow.yaml +11 -34
- package/src/modules/bmm/workflows/4-implementation/dev-story/AUDIT-REPORT.md +367 -0
- package/src/modules/bmm/workflows/4-implementation/dev-story/README.md +189 -67
- package/src/modules/bmm/workflows/4-implementation/dev-story/checklist.md +1 -1
- package/src/modules/bmm/workflows/4-implementation/dev-story/instructions.md +215 -40
- package/src/modules/bmm/workflows/4-implementation/dev-story/workflow.yaml +12 -37
- package/src/modules/bmm/workflows/{3-solutioning/tech-spec → 4-implementation/epic-tech-context}/README.md +6 -6
- package/src/modules/bmm/workflows/{3-solutioning/tech-spec → 4-implementation/epic-tech-context}/checklist.md +1 -1
- package/src/modules/bmm/workflows/4-implementation/epic-tech-context/instructions.md +160 -0
- package/src/modules/bmm/workflows/{3-solutioning/tech-spec → 4-implementation/epic-tech-context}/template.md +1 -1
- package/src/modules/bmm/workflows/4-implementation/epic-tech-context/workflow.yaml +34 -0
- package/src/modules/bmm/workflows/4-implementation/retrospective/README.md +77 -0
- package/src/modules/bmm/workflows/4-implementation/retrospective/instructions.md +236 -148
- package/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml +8 -4
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/README.md +156 -0
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/checklist.md +33 -0
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/instructions.md +221 -0
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +55 -0
- package/src/modules/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +41 -0
- package/src/modules/bmm/workflows/4-implementation/story-context/README.md +1 -1
- package/src/modules/bmm/workflows/4-implementation/story-context/instructions.md +146 -21
- package/src/modules/bmm/workflows/4-implementation/story-context/workflow.yaml +8 -32
- package/src/modules/bmm/workflows/4-implementation/story-done/instructions.md +111 -0
- package/src/modules/bmm/workflows/4-implementation/story-done/workflow.yaml +27 -0
- package/src/modules/bmm/workflows/4-implementation/story-ready/instructions.md +117 -0
- package/src/modules/bmm/workflows/4-implementation/story-ready/workflow.yaml +27 -0
- package/src/modules/bmm/workflows/README.md +577 -0
- package/src/modules/bmm/workflows/document-project/README.md +444 -0
- package/src/modules/bmm/workflows/document-project/checklist.md +245 -0
- package/src/modules/bmm/workflows/document-project/documentation-requirements.csv +12 -0
- package/src/modules/bmm/workflows/document-project/instructions.md +222 -0
- package/src/modules/bmm/workflows/document-project/templates/README.md +38 -0
- package/src/modules/bmm/workflows/document-project/templates/deep-dive-template.md +345 -0
- package/src/modules/bmm/workflows/document-project/templates/index-template.md +169 -0
- package/src/modules/bmm/workflows/document-project/templates/project-overview-template.md +103 -0
- package/src/modules/bmm/workflows/document-project/templates/project-scan-report-schema.json +160 -0
- package/src/modules/bmm/workflows/document-project/templates/source-tree-template.md +135 -0
- package/src/modules/bmm/workflows/document-project/workflow.yaml +36 -0
- package/src/modules/bmm/workflows/document-project/workflows/deep-dive-instructions.md +298 -0
- package/src/modules/bmm/workflows/document-project/workflows/deep-dive.yaml +31 -0
- package/src/modules/bmm/workflows/document-project/workflows/full-scan-instructions.md +1106 -0
- package/src/modules/bmm/workflows/document-project/workflows/full-scan.yaml +31 -0
- package/src/modules/bmm/workflows/testarch/README.md +26 -0
- package/src/modules/bmm/workflows/testarch/atdd/README.md +672 -0
- package/src/modules/bmm/workflows/testarch/atdd/atdd-checklist-template.md +363 -0
- package/src/modules/bmm/workflows/testarch/atdd/checklist.md +373 -0
- package/src/modules/bmm/workflows/testarch/atdd/instructions.md +785 -0
- package/src/modules/bmm/workflows/testarch/atdd/workflow.yaml +54 -0
- package/src/modules/bmm/workflows/testarch/automate/README.md +869 -0
- package/src/modules/bmm/workflows/testarch/automate/checklist.md +580 -0
- package/src/modules/bmm/workflows/testarch/automate/instructions.md +1303 -0
- package/src/modules/bmm/workflows/testarch/automate/workflow.yaml +63 -0
- package/src/modules/bmm/workflows/testarch/ci/README.md +493 -0
- package/src/modules/bmm/workflows/testarch/ci/checklist.md +246 -0
- package/src/modules/bmm/workflows/testarch/ci/github-actions-template.yaml +165 -0
- package/src/modules/bmm/workflows/testarch/ci/gitlab-ci-template.yaml +128 -0
- package/src/modules/bmm/workflows/testarch/ci/instructions.md +517 -0
- package/src/modules/bmm/workflows/testarch/ci/workflow.yaml +55 -0
- package/src/modules/bmm/workflows/testarch/framework/README.md +340 -0
- package/src/modules/bmm/workflows/testarch/framework/checklist.md +321 -0
- package/src/modules/bmm/workflows/testarch/framework/instructions.md +455 -0
- package/src/modules/bmm/workflows/testarch/framework/workflow.yaml +55 -0
- package/src/modules/bmm/workflows/testarch/nfr-assess/README.md +469 -0
- package/src/modules/bmm/workflows/testarch/nfr-assess/checklist.md +405 -0
- package/src/modules/bmm/workflows/testarch/nfr-assess/instructions.md +722 -0
- package/src/modules/bmm/workflows/testarch/nfr-assess/nfr-report-template.md +443 -0
- package/src/modules/bmm/workflows/testarch/nfr-assess/workflow.yaml +58 -0
- package/src/modules/bmm/workflows/testarch/test-design/README.md +493 -0
- package/src/modules/bmm/workflows/testarch/test-design/checklist.md +234 -0
- package/src/modules/bmm/workflows/testarch/test-design/instructions.md +621 -0
- package/src/modules/bmm/workflows/testarch/test-design/test-design-template.md +285 -0
- package/src/modules/bmm/workflows/testarch/test-design/workflow.yaml +54 -0
- package/src/modules/bmm/workflows/testarch/test-review/README.md +775 -0
- package/src/modules/bmm/workflows/testarch/test-review/checklist.md +470 -0
- package/src/modules/bmm/workflows/testarch/test-review/instructions.md +608 -0
- package/src/modules/bmm/workflows/testarch/test-review/test-review-template.md +388 -0
- package/src/modules/bmm/workflows/testarch/test-review/workflow.yaml +55 -0
- package/src/modules/bmm/workflows/testarch/trace/README.md +802 -0
- package/src/modules/bmm/workflows/testarch/trace/checklist.md +654 -0
- package/src/modules/bmm/workflows/testarch/trace/instructions.md +1045 -0
- package/src/modules/bmm/workflows/testarch/trace/trace-template.md +673 -0
- package/src/modules/bmm/workflows/testarch/trace/workflow.yaml +68 -0
- package/src/modules/bmm/workflows/workflow-status/README.md +241 -0
- package/src/modules/bmm/workflows/workflow-status/init/instructions.md +297 -0
- package/src/modules/bmm/workflows/workflow-status/init/workflow.yaml +28 -0
- package/src/modules/bmm/workflows/workflow-status/instructions.md +324 -0
- package/src/modules/bmm/workflows/workflow-status/paths/brownfield-level-0.yaml +54 -0
- package/src/modules/bmm/workflows/workflow-status/paths/brownfield-level-1.yaml +58 -0
- package/src/modules/bmm/workflows/workflow-status/paths/brownfield-level-2.yaml +76 -0
- package/src/modules/bmm/workflows/workflow-status/paths/brownfield-level-3.yaml +95 -0
- package/src/modules/bmm/workflows/workflow-status/paths/brownfield-level-4.yaml +88 -0
- package/src/modules/bmm/workflows/workflow-status/paths/game-design.yaml +75 -0
- package/src/modules/bmm/workflows/workflow-status/paths/greenfield-level-0.yaml +45 -0
- package/src/modules/bmm/workflows/workflow-status/paths/greenfield-level-1.yaml +49 -0
- package/src/modules/bmm/workflows/workflow-status/paths/greenfield-level-2.yaml +78 -0
- package/src/modules/bmm/workflows/workflow-status/paths/greenfield-level-3.yaml +73 -0
- package/src/modules/bmm/workflows/workflow-status/paths/greenfield-level-4.yaml +75 -0
- package/src/modules/bmm/workflows/workflow-status/project-levels.yaml +59 -0
- package/src/modules/bmm/workflows/workflow-status/workflow-status-template.md +30 -0
- package/src/modules/bmm/workflows/workflow-status/workflow.yaml +30 -0
- package/src/modules/cis/_module-installer/installer.js +1 -1
- package/src/modules/cis/agents/brainstorming-coach.agent.yaml +23 -0
- package/src/modules/cis/agents/creative-problem-solver.agent.yaml +23 -0
- package/src/modules/cis/agents/design-thinking-coach.agent.yaml +23 -0
- package/src/modules/cis/agents/innovation-strategist.agent.yaml +23 -0
- package/src/modules/cis/agents/storyteller.agent.yaml +23 -0
- package/src/modules/cis/workflows/design-thinking/design-methods.csv +1 -1
- package/src/modules/cis/workflows/design-thinking/instructions.md +1 -1
- package/src/modules/cis/workflows/design-thinking/workflow.yaml +14 -0
- package/src/modules/cis/workflows/innovation-strategy/innovation-frameworks.csv +2 -2
- package/src/modules/cis/workflows/innovation-strategy/instructions.md +1 -1
- package/src/modules/cis/workflows/innovation-strategy/template.md +4 -4
- package/src/modules/cis/workflows/innovation-strategy/workflow.yaml +14 -0
- package/src/modules/cis/workflows/problem-solving/instructions.md +1 -1
- package/src/modules/cis/workflows/problem-solving/solving-methods.csv +6 -6
- package/src/modules/cis/workflows/problem-solving/template.md +3 -3
- package/src/modules/cis/workflows/problem-solving/workflow.yaml +14 -0
- package/src/modules/cis/workflows/storytelling/instructions.md +35 -27
- package/src/modules/cis/workflows/storytelling/template.md +2 -2
- package/src/modules/cis/workflows/storytelling/workflow.yaml +14 -0
- package/src/utility/models/agent-activation-ide.xml +3 -3
- package/src/utility/models/agent-activation-web.xml +60 -0
- package/src/utility/models/agent-in-team-activation.xml +3 -0
- package/src/utility/models/fragments/activation-rules.xml +8 -0
- package/src/utility/models/fragments/activation-steps.xml +15 -0
- package/src/utility/models/fragments/handler-action.xml +4 -0
- package/src/utility/models/fragments/handler-data.xml +5 -0
- package/src/utility/models/fragments/handler-exec.xml +5 -0
- package/src/utility/models/fragments/handler-tmpl.xml +5 -0
- package/src/utility/models/fragments/handler-validate-workflow.xml +7 -0
- package/src/utility/models/fragments/handler-workflow.xml +9 -0
- package/src/utility/models/fragments/menu-handlers.xml +6 -0
- package/src/utility/models/fragments/web-bundle-activation-steps.xml +32 -0
- package/src/utility/templates/agent.customize.template.yaml +42 -0
- package/test/README.md +295 -0
- package/test/fixtures/agent-schema/invalid/critical-actions/actions-as-string.agent.yaml +26 -0
- package/test/fixtures/agent-schema/invalid/critical-actions/empty-string-in-actions.agent.yaml +29 -0
- package/test/fixtures/agent-schema/invalid/menu/empty-menu.agent.yaml +21 -0
- package/test/fixtures/agent-schema/invalid/menu/missing-menu.agent.yaml +19 -0
- package/test/fixtures/agent-schema/invalid/menu-commands/empty-command-target.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/menu-commands/no-command-target.agent.yaml +23 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/camel-case.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/duplicate-triggers.agent.yaml +30 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/empty-trigger.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/leading-asterisk.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/snake-case.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/menu-triggers/trigger-with-spaces.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/metadata/core-agent-with-module.agent.yaml +26 -0
- package/test/fixtures/agent-schema/invalid/metadata/empty-module-string.agent.yaml +26 -0
- package/test/fixtures/agent-schema/invalid/metadata/empty-name.agent.yaml +24 -0
- package/test/fixtures/agent-schema/invalid/metadata/extra-metadata-fields.agent.yaml +26 -0
- package/test/fixtures/agent-schema/invalid/metadata/missing-id.agent.yaml +23 -0
- package/test/fixtures/agent-schema/invalid/metadata/module-agent-missing-module.agent.yaml +25 -0
- package/test/fixtures/agent-schema/invalid/metadata/wrong-module-value.agent.yaml +26 -0
- package/test/fixtures/agent-schema/invalid/persona/empty-principles-array.agent.yaml +23 -0
- package/test/fixtures/agent-schema/invalid/persona/empty-string-in-principles.agent.yaml +26 -0
- package/test/fixtures/agent-schema/invalid/persona/extra-persona-fields.agent.yaml +26 -0
- package/test/fixtures/agent-schema/invalid/persona/missing-role.agent.yaml +23 -0
- package/test/fixtures/agent-schema/invalid/persona/principles-as-string.agent.yaml +23 -0
- package/test/fixtures/agent-schema/invalid/prompts/empty-content.agent.yaml +28 -0
- package/test/fixtures/agent-schema/invalid/prompts/extra-prompt-fields.agent.yaml +30 -0
- package/test/fixtures/agent-schema/invalid/prompts/missing-content.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/prompts/missing-id.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/top-level/empty-file.agent.yaml +5 -0
- package/test/fixtures/agent-schema/invalid/top-level/extra-top-level-keys.agent.yaml +27 -0
- package/test/fixtures/agent-schema/invalid/top-level/missing-agent-key.agent.yaml +11 -0
- package/test/fixtures/agent-schema/invalid/yaml-errors/invalid-indentation.agent.yaml +19 -0
- package/test/fixtures/agent-schema/invalid/yaml-errors/malformed-yaml.agent.yaml +18 -0
- package/test/fixtures/agent-schema/valid/critical-actions/empty-critical-actions.agent.yaml +23 -0
- package/test/fixtures/agent-schema/valid/critical-actions/no-critical-actions.agent.yaml +21 -0
- package/test/fixtures/agent-schema/valid/critical-actions/valid-critical-actions.agent.yaml +26 -0
- package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +30 -0
- package/test/fixtures/agent-schema/valid/menu/single-menu-item.agent.yaml +21 -0
- package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +39 -0
- package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +23 -0
- package/test/fixtures/agent-schema/valid/menu-triggers/kebab-case-triggers.agent.yaml +33 -0
- package/test/fixtures/agent-schema/valid/metadata/empty-module-name-in-path.agent.yaml +23 -0
- package/test/fixtures/agent-schema/valid/metadata/malformed-path-treated-as-core.agent.yaml +23 -0
- package/test/fixtures/agent-schema/valid/metadata/module-agent-correct.agent.yaml +23 -0
- package/test/fixtures/agent-schema/valid/persona/complete-persona.agent.yaml +23 -0
- package/test/fixtures/agent-schema/valid/prompts/empty-prompts.agent.yaml +23 -0
- package/test/fixtures/agent-schema/valid/prompts/no-prompts.agent.yaml +21 -0
- package/test/fixtures/agent-schema/valid/prompts/valid-prompts-minimal.agent.yaml +27 -0
- package/test/fixtures/agent-schema/valid/prompts/valid-prompts-with-description.agent.yaml +29 -0
- package/test/fixtures/agent-schema/valid/top-level/minimal-core-agent.agent.yaml +23 -0
- package/test/test-agent-schema.js +387 -0
- package/test/test-cli-integration.sh +159 -0
- package/test/unit-test-schema.js +133 -0
- package/tools/bmad-npx-wrapper.js +38 -0
- package/tools/cli/README.md +590 -0
- package/tools/cli/bmad-cli.js +0 -2
- package/tools/cli/bundlers/bundle-web.js +24 -2
- package/tools/cli/bundlers/test-bundler.js +1 -1
- package/tools/cli/bundlers/web-bundler.js +639 -40
- package/tools/cli/commands/build.js +458 -0
- package/tools/cli/commands/install.js +49 -8
- package/tools/cli/installers/lib/core/config-collector.js +222 -15
- package/tools/cli/installers/lib/core/dependency-resolver.js +5 -1
- package/tools/cli/installers/lib/core/detector.js +80 -14
- package/tools/cli/installers/lib/core/ide-config-manager.js +152 -0
- package/tools/cli/installers/lib/core/installer.js +1175 -150
- package/tools/cli/installers/lib/core/manifest-generator.js +454 -63
- package/tools/cli/installers/lib/core/manifest.js +95 -43
- package/tools/cli/installers/lib/ide/_base-ide.js +311 -20
- package/tools/cli/installers/lib/ide/auggie.js +92 -27
- package/tools/cli/installers/lib/ide/claude-code.js +132 -308
- package/tools/cli/installers/lib/ide/cline.js +149 -227
- package/tools/cli/installers/lib/ide/codex.js +141 -174
- package/tools/cli/installers/lib/ide/crush.js +109 -37
- package/tools/cli/installers/lib/ide/cursor.js +81 -13
- package/tools/cli/installers/lib/ide/gemini.js +24 -28
- package/tools/cli/installers/lib/ide/github-copilot.js +15 -14
- package/tools/cli/installers/lib/ide/manager.js +26 -35
- package/tools/cli/installers/lib/ide/opencode.js +213 -0
- package/tools/cli/installers/lib/ide/qwen.js +172 -70
- package/tools/cli/installers/lib/ide/shared/bmad-artifacts.js +143 -0
- package/tools/cli/installers/lib/ide/shared/module-injections.js +133 -0
- package/tools/cli/installers/lib/ide/task-tool-command-generator.js +119 -0
- package/tools/cli/installers/lib/ide/trae.js +120 -24
- package/tools/cli/installers/lib/ide/windsurf.js +88 -36
- package/tools/cli/installers/lib/ide/workflow-command-generator.js +119 -46
- package/tools/cli/installers/lib/ide/workflow-command-template.md +7 -3
- package/tools/cli/installers/lib/modules/manager.js +123 -7
- package/tools/cli/lib/activation-builder.js +168 -0
- package/tools/cli/lib/agent-analyzer.js +81 -0
- package/tools/cli/lib/agent-party-generator.js +3 -3
- package/tools/cli/lib/ui.js +78 -3
- package/tools/cli/lib/xml-handler.js +46 -1
- package/tools/cli/lib/yaml-xml-builder.js +439 -0
- package/tools/cli/regenerate-manifests.js +1 -1
- package/tools/cli/test-yaml-builder.js +43 -0
- package/tools/format-workflow-md.js +263 -0
- package/tools/platform-codes.yaml +6 -0
- package/tools/schema/agent.js +231 -0
- package/tools/validate-agent-schema.js +110 -0
- package/v6-open-items.md +23 -0
- package/docs/codebase-flattener.md +0 -19
- package/readme.md +0 -216
- package/src/core/agents/bmad-master.md +0 -27
- package/src/core/agents/bmad-web-orchestrator.md +0 -71
- package/src/core/tasks/shard-doc.md +0 -57
- package/src/core/workflows/bmad-init/instructions.md +0 -79
- package/src/core/workflows/bmad-init/workflow.yaml +0 -24
- package/src/modules/bmb/_module-installer/install-menu-config.yaml +0 -16
- package/src/modules/bmb/agents/bmad-builder.md +0 -30
- package/src/modules/bmb/workflows/create-module/installer-templates/install-module-config.yaml +0 -132
- package/src/modules/bmm/_module-installer/install-menu-config.yaml +0 -49
- package/src/modules/bmm/agents/analyst.md +0 -26
- package/src/modules/bmm/agents/architect.md +0 -29
- package/src/modules/bmm/agents/dev.md +0 -61
- package/src/modules/bmm/agents/game-architect.md +0 -26
- package/src/modules/bmm/agents/game-designer.md +0 -27
- package/src/modules/bmm/agents/game-dev.md +0 -28
- package/src/modules/bmm/agents/pm.md +0 -26
- package/src/modules/bmm/agents/po.md +0 -25
- package/src/modules/bmm/agents/sm.md +0 -29
- package/src/modules/bmm/agents/tea.md +0 -32
- package/src/modules/bmm/agents/ux-expert.md +0 -24
- package/src/modules/bmm/teams/team-all.yaml +0 -7
- package/src/modules/bmm/teams/team-dev.yaml +0 -14
- package/src/modules/bmm/testarch/atdd.md +0 -40
- package/src/modules/bmm/testarch/automate.md +0 -38
- package/src/modules/bmm/testarch/ci.md +0 -39
- package/src/modules/bmm/testarch/framework.md +0 -41
- package/src/modules/bmm/testarch/nfr-assess.md +0 -38
- package/src/modules/bmm/testarch/risk-profile.md +0 -38
- package/src/modules/bmm/testarch/tea-commands.csv +0 -11
- package/src/modules/bmm/testarch/tea-gate.md +0 -38
- package/src/modules/bmm/testarch/tea-knowledge.md +0 -275
- package/src/modules/bmm/testarch/test-design.md +0 -39
- package/src/modules/bmm/testarch/test-levels-framework.md +0 -148
- package/src/modules/bmm/testarch/test-priorities-matrix.md +0 -174
- package/src/modules/bmm/testarch/trace-requirements.md +0 -38
- package/src/modules/bmm/workflows/2-plan/README.md +0 -203
- package/src/modules/bmm/workflows/2-plan/checklist.md +0 -369
- package/src/modules/bmm/workflows/2-plan/gdd/instructions-gdd.md +0 -480
- package/src/modules/bmm/workflows/2-plan/instructions-router.md +0 -222
- package/src/modules/bmm/workflows/2-plan/prd/analysis-template.md +0 -53
- package/src/modules/bmm/workflows/2-plan/prd/epics-template.md +0 -18
- package/src/modules/bmm/workflows/2-plan/prd/instructions-lg.md +0 -267
- package/src/modules/bmm/workflows/2-plan/prd/instructions-med.md +0 -251
- package/src/modules/bmm/workflows/2-plan/prd/prd-template.md +0 -73
- package/src/modules/bmm/workflows/2-plan/tech-spec/instructions-sm.md +0 -137
- package/src/modules/bmm/workflows/2-plan/ux/instructions-ux.md +0 -360
- package/src/modules/bmm/workflows/2-plan/ux/ux-spec-template.md +0 -162
- package/src/modules/bmm/workflows/2-plan/workflow.yaml +0 -60
- package/src/modules/bmm/workflows/3-solutioning/ADR-template.md +0 -74
- package/src/modules/bmm/workflows/3-solutioning/checklist.md +0 -170
- package/src/modules/bmm/workflows/3-solutioning/instructions.md +0 -661
- package/src/modules/bmm/workflows/3-solutioning/project-types/backend-questions.md +0 -490
- package/src/modules/bmm/workflows/3-solutioning/project-types/cli-questions.md +0 -337
- package/src/modules/bmm/workflows/3-solutioning/project-types/data-questions.md +0 -472
- package/src/modules/bmm/workflows/3-solutioning/project-types/desktop-questions.md +0 -299
- package/src/modules/bmm/workflows/3-solutioning/project-types/embedded-questions.md +0 -118
- package/src/modules/bmm/workflows/3-solutioning/project-types/extension-questions.md +0 -374
- package/src/modules/bmm/workflows/3-solutioning/project-types/game-questions.md +0 -133
- package/src/modules/bmm/workflows/3-solutioning/project-types/infra-questions.md +0 -484
- package/src/modules/bmm/workflows/3-solutioning/project-types/library-questions.md +0 -146
- package/src/modules/bmm/workflows/3-solutioning/project-types/mobile-questions.md +0 -110
- package/src/modules/bmm/workflows/3-solutioning/project-types/project-types.csv +0 -12
- package/src/modules/bmm/workflows/3-solutioning/project-types/web-questions.md +0 -136
- package/src/modules/bmm/workflows/3-solutioning/tech-spec/instructions.md +0 -73
- package/src/modules/bmm/workflows/3-solutioning/tech-spec/workflow.yaml +0 -51
- package/src/modules/bmm/workflows/3-solutioning/templates/backend-service-architecture.md +0 -66
- package/src/modules/bmm/workflows/3-solutioning/templates/cli-tool-architecture.md +0 -66
- package/src/modules/bmm/workflows/3-solutioning/templates/data-pipeline-architecture.md +0 -66
- package/src/modules/bmm/workflows/3-solutioning/templates/desktop-app-architecture.md +0 -66
- package/src/modules/bmm/workflows/3-solutioning/templates/embedded-firmware-architecture.md +0 -66
- package/src/modules/bmm/workflows/3-solutioning/templates/game-engine-architecture.md +0 -244
- package/src/modules/bmm/workflows/3-solutioning/templates/game-engine-godot-guide.md +0 -428
- package/src/modules/bmm/workflows/3-solutioning/templates/game-engine-unity-guide.md +0 -333
- package/src/modules/bmm/workflows/3-solutioning/templates/game-engine-web-guide.md +0 -528
- package/src/modules/bmm/workflows/3-solutioning/templates/infrastructure-architecture.md +0 -66
- package/src/modules/bmm/workflows/3-solutioning/templates/library-package-architecture.md +0 -66
- package/src/modules/bmm/workflows/3-solutioning/templates/mobile-app-architecture.md +0 -66
- package/src/modules/bmm/workflows/3-solutioning/templates/registry.csv +0 -172
- package/src/modules/bmm/workflows/3-solutioning/templates/web-api-architecture.md +0 -66
- package/src/modules/bmm/workflows/3-solutioning/templates/web-fullstack-architecture.md +0 -277
- package/src/modules/bmm/workflows/3-solutioning/workflow.yaml +0 -65
- package/src/modules/bmm/workflows/4-implementation/review-story/instructions.md +0 -176
- package/src/modules/bmm/workflows/4-implementation/review-story/workflow.yaml +0 -99
- package/src/modules/cis/agents/brainstorming-coach.md +0 -24
- package/src/modules/cis/agents/creative-problem-solver.md +0 -24
- package/src/modules/cis/agents/design-thinking-coach.md +0 -24
- package/src/modules/cis/agents/innovation-strategist.md +0 -24
- package/src/modules/cis/agents/storyteller.md +0 -24
- package/tools/test-agents/captain-kirk-commander.md +0 -110
- package/tools/test-agents/data-operations-android.md +0 -123
- package/tools/test-agents/geordi-chief-engineer.md +0 -135
- package/tools/test-agents/isabella-martinez-ethicist.md +0 -109
- package/tools/test-agents/marcus-thompson-security.md +0 -109
- package/tools/test-agents/maya-patel-pragmatist.md +0 -82
- package/tools/test-agents/picard-diplomat-captain.md +0 -134
- package/tools/test-agents/spock-science-officer.md +0 -124
- package/tools/test-agents/william-smithers-technocrat.md +0 -71
- package/tools/test-agents/zara-chen-designer.md +0 -94
- /package/{src/modules/cis → bmad/core}/workflows/brainstorming/brain-methods.csv +0 -0
- /package/src/modules/bmm/_module-installer/assets/{technical-decisions-template.md → technical-decisions.md} +0 -0
- /package/src/modules/bmm/sub-modules/claude-code/sub-agents/{requirements-analyst.md → bmad-planning/requirements-analyst.md} +0 -0
- /package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/metroidvania.md +0 -0
- /package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types/puzzle.md +0 -0
- /package/src/modules/bmm/workflows/{2-plan → 2-plan-workflows}/gdd/game-types.csv +0 -0
- /package/src/modules/bmm/workflows/4-implementation/{review-story → code-review}/backlog_template.md +0 -0
- /package/src/modules/bmm/workflows/4-implementation/{review-story → code-review}/checklist.md +0 -0
- /package/src/modules/cis/_module-installer/{install-menu-config.yaml → install-config.yaml} +0 -0
|
@@ -16,6 +16,7 @@ const { getProjectRoot, getSourcePath, getModulePath } = require('../../../lib/p
|
|
|
16
16
|
const { AgentPartyGenerator } = require('../../../lib/agent-party-generator');
|
|
17
17
|
const { CLIUtils } = require('../../../lib/cli-utils');
|
|
18
18
|
const { ManifestGenerator } = require('./manifest-generator');
|
|
19
|
+
const { IdeConfigManager } = require('./ide-config-manager');
|
|
19
20
|
|
|
20
21
|
class Installer {
|
|
21
22
|
constructor() {
|
|
@@ -28,6 +29,7 @@ class Installer {
|
|
|
28
29
|
this.xmlHandler = new XmlHandler();
|
|
29
30
|
this.dependencyResolver = new DependencyResolver();
|
|
30
31
|
this.configCollector = new ConfigCollector();
|
|
32
|
+
this.ideConfigManager = new IdeConfigManager();
|
|
31
33
|
this.installedFiles = []; // Track all installed files
|
|
32
34
|
}
|
|
33
35
|
|
|
@@ -35,65 +37,114 @@ class Installer {
|
|
|
35
37
|
* Collect Tool/IDE configurations after module configuration
|
|
36
38
|
* @param {string} projectDir - Project directory
|
|
37
39
|
* @param {Array} selectedModules - Selected modules from configuration
|
|
40
|
+
* @param {boolean} isFullReinstall - Whether this is a full reinstall
|
|
41
|
+
* @param {Array} previousIdes - Previously configured IDEs (for reinstalls)
|
|
42
|
+
* @param {Array} preSelectedIdes - Pre-selected IDEs from early prompt (optional)
|
|
38
43
|
* @returns {Object} Tool/IDE selection and configurations
|
|
39
44
|
*/
|
|
40
|
-
async collectToolConfigurations(projectDir, selectedModules) {
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
async collectToolConfigurations(projectDir, selectedModules, isFullReinstall = false, previousIdes = [], preSelectedIdes = null) {
|
|
46
|
+
// Use pre-selected IDEs if provided, otherwise prompt
|
|
47
|
+
let toolConfig;
|
|
48
|
+
if (preSelectedIdes === null) {
|
|
49
|
+
// Fallback: prompt for tool selection (backwards compatibility)
|
|
50
|
+
const { UI } = require('../../../lib/ui');
|
|
51
|
+
const ui = new UI();
|
|
52
|
+
toolConfig = await ui.promptToolSelection(projectDir, selectedModules);
|
|
53
|
+
} else {
|
|
54
|
+
// IDEs were already selected during initial prompts
|
|
55
|
+
toolConfig = {
|
|
56
|
+
ides: preSelectedIdes,
|
|
57
|
+
skipIde: !preSelectedIdes || preSelectedIdes.length === 0,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Check for already configured IDEs
|
|
62
|
+
const { Detector } = require('./detector');
|
|
63
|
+
const detector = new Detector();
|
|
64
|
+
const bmadDir = path.join(projectDir, 'bmad');
|
|
65
|
+
|
|
66
|
+
// During full reinstall, use the saved previous IDEs since bmad dir was deleted
|
|
67
|
+
// Otherwise detect from existing installation
|
|
68
|
+
let previouslyConfiguredIdes;
|
|
69
|
+
if (isFullReinstall) {
|
|
70
|
+
// During reinstall, treat all IDEs as new (need configuration)
|
|
71
|
+
previouslyConfiguredIdes = [];
|
|
72
|
+
} else {
|
|
73
|
+
const existingInstall = await detector.detect(bmadDir);
|
|
74
|
+
previouslyConfiguredIdes = existingInstall.ides || [];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Load saved IDE configurations for already-configured IDEs
|
|
78
|
+
const savedIdeConfigs = await this.ideConfigManager.loadAllIdeConfigs(bmadDir);
|
|
45
79
|
|
|
46
80
|
// Collect IDE-specific configurations if any were selected
|
|
47
81
|
const ideConfigurations = {};
|
|
48
|
-
|
|
82
|
+
|
|
83
|
+
// First, add saved configs for already-configured IDEs
|
|
84
|
+
for (const ide of toolConfig.ides || []) {
|
|
85
|
+
if (previouslyConfiguredIdes.includes(ide) && savedIdeConfigs[ide]) {
|
|
86
|
+
ideConfigurations[ide] = savedIdeConfigs[ide];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
49
89
|
|
|
50
90
|
if (!toolConfig.skipIde && toolConfig.ides && toolConfig.ides.length > 0) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
91
|
+
// Determine which IDEs are newly selected (not previously configured)
|
|
92
|
+
const newlySelectedIdes = toolConfig.ides.filter((ide) => !previouslyConfiguredIdes.includes(ide));
|
|
93
|
+
|
|
94
|
+
if (newlySelectedIdes.length > 0) {
|
|
95
|
+
console.log('\n'); // Add spacing before IDE questions
|
|
96
|
+
|
|
97
|
+
for (const ide of newlySelectedIdes) {
|
|
98
|
+
// List of IDEs that have interactive prompts
|
|
99
|
+
const needsPrompts = ['claude-code', 'github-copilot', 'roo', 'cline', 'auggie', 'codex', 'qwen', 'gemini'].includes(ide);
|
|
100
|
+
|
|
101
|
+
if (needsPrompts) {
|
|
102
|
+
// Get IDE handler and collect configuration
|
|
103
|
+
try {
|
|
104
|
+
// Dynamically load the IDE setup module
|
|
105
|
+
const ideModule = require(`../ide/${ide}`);
|
|
106
|
+
|
|
107
|
+
// Get the setup class (handle different export formats)
|
|
108
|
+
let SetupClass;
|
|
109
|
+
const className =
|
|
110
|
+
ide
|
|
111
|
+
.split('-')
|
|
112
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
113
|
+
.join('') + 'Setup';
|
|
114
|
+
|
|
115
|
+
if (ideModule[className]) {
|
|
116
|
+
SetupClass = ideModule[className];
|
|
117
|
+
} else if (ideModule.default) {
|
|
118
|
+
SetupClass = ideModule.default;
|
|
119
|
+
} else {
|
|
120
|
+
// Skip if no setup class found
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
79
123
|
|
|
80
|
-
|
|
124
|
+
const ideSetup = new SetupClass();
|
|
81
125
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
126
|
+
// Check if this IDE has a collectConfiguration method
|
|
127
|
+
if (typeof ideSetup.collectConfiguration === 'function') {
|
|
128
|
+
console.log(chalk.cyan(`\nConfiguring ${ide}...`));
|
|
129
|
+
ideConfigurations[ide] = await ideSetup.collectConfiguration({
|
|
130
|
+
selectedModules: selectedModules || [],
|
|
131
|
+
projectDir,
|
|
132
|
+
bmadDir,
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
} catch {
|
|
136
|
+
// IDE doesn't have a setup file or collectConfiguration method
|
|
137
|
+
console.warn(chalk.yellow(`Warning: Could not load configuration for ${ide}`));
|
|
90
138
|
}
|
|
91
|
-
} catch {
|
|
92
|
-
// IDE doesn't have a setup file or collectConfiguration method
|
|
93
|
-
console.warn(chalk.yellow(`Warning: Could not load configuration for ${ide}`));
|
|
94
139
|
}
|
|
95
140
|
}
|
|
96
141
|
}
|
|
142
|
+
|
|
143
|
+
// Log which IDEs are already configured and being kept
|
|
144
|
+
const keptIdes = toolConfig.ides.filter((ide) => previouslyConfiguredIdes.includes(ide));
|
|
145
|
+
if (keptIdes.length > 0) {
|
|
146
|
+
console.log(chalk.dim(`\nKeeping existing configuration for: ${keptIdes.join(', ')}`));
|
|
147
|
+
}
|
|
97
148
|
}
|
|
98
149
|
|
|
99
150
|
return {
|
|
@@ -119,12 +170,11 @@ class Installer {
|
|
|
119
170
|
// Display welcome message
|
|
120
171
|
CLIUtils.displaySection('BMAD™ Installation', 'Version ' + require(path.join(getProjectRoot(), 'package.json')).version);
|
|
121
172
|
|
|
122
|
-
// Preflight:
|
|
173
|
+
// Preflight: Handle legacy BMAD v4 footprints before any prompts/writes
|
|
123
174
|
const projectDir = path.resolve(config.directory);
|
|
124
175
|
const legacyV4 = await this.detector.detectLegacyV4(projectDir);
|
|
125
176
|
if (legacyV4.hasLegacyV4) {
|
|
126
|
-
|
|
127
|
-
throw error;
|
|
177
|
+
await this.handleLegacyV4Migration(projectDir, legacyV4);
|
|
128
178
|
}
|
|
129
179
|
|
|
130
180
|
// If core config was pre-collected (from interactive mode), use it
|
|
@@ -137,15 +187,17 @@ class Installer {
|
|
|
137
187
|
}
|
|
138
188
|
}
|
|
139
189
|
|
|
140
|
-
// Collect configurations for modules (
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
190
|
+
// Collect configurations for modules (skip if quick update already collected them)
|
|
191
|
+
let moduleConfigs;
|
|
192
|
+
if (config._quickUpdate) {
|
|
193
|
+
// Quick update already collected all configs, use them directly
|
|
194
|
+
moduleConfigs = this.configCollector.collectedConfig;
|
|
195
|
+
} else {
|
|
196
|
+
// Regular install - collect configurations (core was already collected in UI.promptInstall if interactive)
|
|
197
|
+
moduleConfigs = await this.configCollector.collectAllConfigurations(config.modules || [], path.resolve(config.directory));
|
|
198
|
+
}
|
|
144
199
|
|
|
145
|
-
//
|
|
146
|
-
config.ides = toolSelection.ides;
|
|
147
|
-
config.skipIde = toolSelection.skipIde;
|
|
148
|
-
const ideConfigurations = toolSelection.configurations;
|
|
200
|
+
// Tool selection will be collected after we determine if it's a reinstall/update/new install
|
|
149
201
|
|
|
150
202
|
const spinner = ora('Preparing installation...').start();
|
|
151
203
|
|
|
@@ -179,21 +231,206 @@ class Installer {
|
|
|
179
231
|
spinner.text = 'Checking for existing installation...';
|
|
180
232
|
const existingInstall = await this.detector.detect(bmadDir);
|
|
181
233
|
|
|
182
|
-
if (existingInstall.installed && !config.force) {
|
|
234
|
+
if (existingInstall.installed && !config.force && !config._quickUpdate) {
|
|
183
235
|
spinner.stop();
|
|
184
236
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
237
|
+
// Check if user already decided what to do (from early menu in ui.js)
|
|
238
|
+
let action = null;
|
|
239
|
+
if (config._requestedReinstall) {
|
|
240
|
+
action = 'reinstall';
|
|
241
|
+
} else if (config.actionType === 'update') {
|
|
242
|
+
action = 'update';
|
|
243
|
+
} else {
|
|
244
|
+
// Fallback: Ask the user (backwards compatibility for other code paths)
|
|
245
|
+
console.log(chalk.yellow('\n⚠️ Existing BMAD installation detected'));
|
|
246
|
+
console.log(chalk.dim(` Location: ${bmadDir}`));
|
|
247
|
+
console.log(chalk.dim(` Version: ${existingInstall.version}`));
|
|
248
|
+
|
|
249
|
+
const promptResult = await this.promptUpdateAction();
|
|
250
|
+
action = promptResult.action;
|
|
251
|
+
}
|
|
188
252
|
|
|
189
|
-
// TODO: Handle update scenario
|
|
190
|
-
const { action } = await this.promptUpdateAction();
|
|
191
253
|
if (action === 'cancel') {
|
|
192
254
|
console.log('Installation cancelled.');
|
|
193
|
-
return;
|
|
255
|
+
return { success: false, cancelled: true };
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
if (action === 'reinstall') {
|
|
259
|
+
// Warn about destructive operation
|
|
260
|
+
console.log(chalk.red.bold('\n⚠️ WARNING: This is a destructive operation!'));
|
|
261
|
+
console.log(chalk.red('All custom files and modifications in the bmad directory will be lost.'));
|
|
262
|
+
|
|
263
|
+
const inquirer = require('inquirer');
|
|
264
|
+
const { confirmReinstall } = await inquirer.prompt([
|
|
265
|
+
{
|
|
266
|
+
type: 'confirm',
|
|
267
|
+
name: 'confirmReinstall',
|
|
268
|
+
message: chalk.yellow('Are you sure you want to delete and reinstall?'),
|
|
269
|
+
default: false,
|
|
270
|
+
},
|
|
271
|
+
]);
|
|
272
|
+
|
|
273
|
+
if (!confirmReinstall) {
|
|
274
|
+
console.log('Installation cancelled.');
|
|
275
|
+
return { success: false, cancelled: true };
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Remember previously configured IDEs before deleting
|
|
279
|
+
config._previouslyConfiguredIdes = existingInstall.ides || [];
|
|
280
|
+
|
|
281
|
+
// Remove existing installation
|
|
282
|
+
await fs.remove(bmadDir);
|
|
283
|
+
console.log(chalk.green('✓ Removed existing installation\n'));
|
|
284
|
+
|
|
285
|
+
// Mark this as a full reinstall so we re-collect IDE configurations
|
|
286
|
+
config._isFullReinstall = true;
|
|
287
|
+
} else if (action === 'update') {
|
|
288
|
+
// Store that we're updating for later processing
|
|
289
|
+
config._isUpdate = true;
|
|
290
|
+
config._existingInstall = existingInstall;
|
|
291
|
+
|
|
292
|
+
// Detect custom and modified files BEFORE updating (compare current files vs files-manifest.csv)
|
|
293
|
+
const existingFilesManifest = await this.readFilesManifest(bmadDir);
|
|
294
|
+
console.log(chalk.dim(`DEBUG: Read ${existingFilesManifest.length} files from manifest`));
|
|
295
|
+
console.log(chalk.dim(`DEBUG: Manifest has hashes: ${existingFilesManifest.some((f) => f.hash)}`));
|
|
296
|
+
|
|
297
|
+
const { customFiles, modifiedFiles } = await this.detectCustomFiles(bmadDir, existingFilesManifest);
|
|
298
|
+
|
|
299
|
+
console.log(chalk.dim(`DEBUG: Found ${customFiles.length} custom files, ${modifiedFiles.length} modified files`));
|
|
300
|
+
if (modifiedFiles.length > 0) {
|
|
301
|
+
console.log(chalk.yellow('DEBUG: Modified files:'));
|
|
302
|
+
for (const f of modifiedFiles) console.log(chalk.dim(` - ${f.path}`));
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
config._customFiles = customFiles;
|
|
306
|
+
config._modifiedFiles = modifiedFiles;
|
|
307
|
+
|
|
308
|
+
// If there are custom files, back them up temporarily
|
|
309
|
+
if (customFiles.length > 0) {
|
|
310
|
+
const tempBackupDir = path.join(projectDir, '.bmad-custom-backup-temp');
|
|
311
|
+
await fs.ensureDir(tempBackupDir);
|
|
312
|
+
|
|
313
|
+
spinner.start(`Backing up ${customFiles.length} custom files...`);
|
|
314
|
+
for (const customFile of customFiles) {
|
|
315
|
+
const relativePath = path.relative(bmadDir, customFile);
|
|
316
|
+
const backupPath = path.join(tempBackupDir, relativePath);
|
|
317
|
+
await fs.ensureDir(path.dirname(backupPath));
|
|
318
|
+
await fs.copy(customFile, backupPath);
|
|
319
|
+
}
|
|
320
|
+
spinner.succeed(`Backed up ${customFiles.length} custom files`);
|
|
321
|
+
|
|
322
|
+
config._tempBackupDir = tempBackupDir;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// For modified files, back them up to temp directory (will be restored as .bak files after install)
|
|
326
|
+
if (modifiedFiles.length > 0) {
|
|
327
|
+
const tempModifiedBackupDir = path.join(projectDir, '.bmad-modified-backup-temp');
|
|
328
|
+
await fs.ensureDir(tempModifiedBackupDir);
|
|
329
|
+
|
|
330
|
+
console.log(chalk.yellow(`\nDEBUG: Backing up ${modifiedFiles.length} modified files to temp location`));
|
|
331
|
+
spinner.start(`Backing up ${modifiedFiles.length} modified files...`);
|
|
332
|
+
for (const modifiedFile of modifiedFiles) {
|
|
333
|
+
const relativePath = path.relative(bmadDir, modifiedFile.path);
|
|
334
|
+
const tempBackupPath = path.join(tempModifiedBackupDir, relativePath);
|
|
335
|
+
console.log(chalk.dim(`DEBUG: Backing up ${relativePath} to temp`));
|
|
336
|
+
await fs.ensureDir(path.dirname(tempBackupPath));
|
|
337
|
+
await fs.copy(modifiedFile.path, tempBackupPath, { overwrite: true });
|
|
338
|
+
}
|
|
339
|
+
spinner.succeed(`Backed up ${modifiedFiles.length} modified files`);
|
|
340
|
+
|
|
341
|
+
config._tempModifiedBackupDir = tempModifiedBackupDir;
|
|
342
|
+
} else {
|
|
343
|
+
console.log(chalk.dim('DEBUG: No modified files detected'));
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
} else if (existingInstall.installed && config._quickUpdate) {
|
|
347
|
+
// Quick update mode - automatically treat as update without prompting
|
|
348
|
+
spinner.text = 'Preparing quick update...';
|
|
349
|
+
config._isUpdate = true;
|
|
350
|
+
config._existingInstall = existingInstall;
|
|
351
|
+
|
|
352
|
+
// Detect custom and modified files BEFORE updating
|
|
353
|
+
const existingFilesManifest = await this.readFilesManifest(bmadDir);
|
|
354
|
+
const { customFiles, modifiedFiles } = await this.detectCustomFiles(bmadDir, existingFilesManifest);
|
|
355
|
+
|
|
356
|
+
config._customFiles = customFiles;
|
|
357
|
+
config._modifiedFiles = modifiedFiles;
|
|
358
|
+
|
|
359
|
+
// Back up custom files
|
|
360
|
+
if (customFiles.length > 0) {
|
|
361
|
+
const tempBackupDir = path.join(projectDir, '.bmad-custom-backup-temp');
|
|
362
|
+
await fs.ensureDir(tempBackupDir);
|
|
363
|
+
|
|
364
|
+
spinner.start(`Backing up ${customFiles.length} custom files...`);
|
|
365
|
+
for (const customFile of customFiles) {
|
|
366
|
+
const relativePath = path.relative(bmadDir, customFile);
|
|
367
|
+
const backupPath = path.join(tempBackupDir, relativePath);
|
|
368
|
+
await fs.ensureDir(path.dirname(backupPath));
|
|
369
|
+
await fs.copy(customFile, backupPath);
|
|
370
|
+
}
|
|
371
|
+
spinner.succeed(`Backed up ${customFiles.length} custom files`);
|
|
372
|
+
config._tempBackupDir = tempBackupDir;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Back up modified files
|
|
376
|
+
if (modifiedFiles.length > 0) {
|
|
377
|
+
const tempModifiedBackupDir = path.join(projectDir, '.bmad-modified-backup-temp');
|
|
378
|
+
await fs.ensureDir(tempModifiedBackupDir);
|
|
379
|
+
|
|
380
|
+
spinner.start(`Backing up ${modifiedFiles.length} modified files...`);
|
|
381
|
+
for (const modifiedFile of modifiedFiles) {
|
|
382
|
+
const relativePath = path.relative(bmadDir, modifiedFile.path);
|
|
383
|
+
const tempBackupPath = path.join(tempModifiedBackupDir, relativePath);
|
|
384
|
+
await fs.ensureDir(path.dirname(tempBackupPath));
|
|
385
|
+
await fs.copy(modifiedFile.path, tempBackupPath, { overwrite: true });
|
|
386
|
+
}
|
|
387
|
+
spinner.succeed(`Backed up ${modifiedFiles.length} modified files`);
|
|
388
|
+
config._tempModifiedBackupDir = tempModifiedBackupDir;
|
|
194
389
|
}
|
|
195
390
|
}
|
|
196
391
|
|
|
392
|
+
// Now collect tool configurations after we know if it's a reinstall
|
|
393
|
+
// Skip for quick update since we already have the IDE list
|
|
394
|
+
spinner.stop();
|
|
395
|
+
let toolSelection;
|
|
396
|
+
if (config._quickUpdate) {
|
|
397
|
+
// Quick update already has IDEs configured, use saved configurations
|
|
398
|
+
const preConfiguredIdes = {};
|
|
399
|
+
const savedIdeConfigs = config._savedIdeConfigs || {};
|
|
400
|
+
|
|
401
|
+
for (const ide of config.ides || []) {
|
|
402
|
+
// Use saved config if available, otherwise mark as already configured (legacy)
|
|
403
|
+
if (savedIdeConfigs[ide]) {
|
|
404
|
+
preConfiguredIdes[ide] = savedIdeConfigs[ide];
|
|
405
|
+
} else {
|
|
406
|
+
preConfiguredIdes[ide] = { _alreadyConfigured: true };
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
toolSelection = {
|
|
410
|
+
ides: config.ides || [],
|
|
411
|
+
skipIde: !config.ides || config.ides.length === 0,
|
|
412
|
+
configurations: preConfiguredIdes,
|
|
413
|
+
};
|
|
414
|
+
} else {
|
|
415
|
+
// Pass pre-selected IDEs from early prompt (if available)
|
|
416
|
+
// This allows IDE selection to happen before file copying, improving UX
|
|
417
|
+
const preSelectedIdes = config.ides && config.ides.length > 0 ? config.ides : null;
|
|
418
|
+
toolSelection = await this.collectToolConfigurations(
|
|
419
|
+
path.resolve(config.directory),
|
|
420
|
+
config.modules,
|
|
421
|
+
config._isFullReinstall || false,
|
|
422
|
+
config._previouslyConfiguredIdes || [],
|
|
423
|
+
preSelectedIdes,
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Merge tool selection into config (for both quick update and regular flow)
|
|
428
|
+
config.ides = toolSelection.ides;
|
|
429
|
+
config.skipIde = toolSelection.skipIde;
|
|
430
|
+
const ideConfigurations = toolSelection.configurations;
|
|
431
|
+
|
|
432
|
+
spinner.start('Continuing installation...');
|
|
433
|
+
|
|
197
434
|
// Create bmad directory structure
|
|
198
435
|
spinner.text = 'Creating directory structure...';
|
|
199
436
|
await this.createDirectoryStructure(bmadDir);
|
|
@@ -230,7 +467,13 @@ class Installer {
|
|
|
230
467
|
// Install partial modules (only dependencies)
|
|
231
468
|
for (const [module, files] of Object.entries(resolution.byModule)) {
|
|
232
469
|
if (!config.modules.includes(module) && module !== 'core') {
|
|
233
|
-
const totalFiles =
|
|
470
|
+
const totalFiles =
|
|
471
|
+
files.agents.length +
|
|
472
|
+
files.tasks.length +
|
|
473
|
+
files.tools.length +
|
|
474
|
+
files.templates.length +
|
|
475
|
+
files.data.length +
|
|
476
|
+
files.other.length;
|
|
234
477
|
if (totalFiles > 0) {
|
|
235
478
|
spinner.start(`Installing ${module} dependencies...`);
|
|
236
479
|
await this.installPartialModule(module, bmadDir, files);
|
|
@@ -246,57 +489,102 @@ class Installer {
|
|
|
246
489
|
spinner.succeed('Module configurations generated');
|
|
247
490
|
|
|
248
491
|
// Create agent configuration files
|
|
249
|
-
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
}
|
|
492
|
+
// Note: Legacy createAgentConfigs removed - using YAML customize system instead
|
|
493
|
+
// Customize templates are now created in processAgentFiles when building YAML agents
|
|
494
|
+
|
|
495
|
+
// Pre-register manifest files that will be created (except files-manifest.csv to avoid recursion)
|
|
496
|
+
const cfgDir = path.join(bmadDir, '_cfg');
|
|
497
|
+
this.installedFiles.push(
|
|
498
|
+
path.join(cfgDir, 'manifest.yaml'),
|
|
499
|
+
path.join(cfgDir, 'workflow-manifest.csv'),
|
|
500
|
+
path.join(cfgDir, 'agent-manifest.csv'),
|
|
501
|
+
path.join(cfgDir, 'task-manifest.csv'),
|
|
502
|
+
);
|
|
261
503
|
|
|
262
|
-
// Generate CSV manifests for workflows, agents,
|
|
504
|
+
// Generate CSV manifests for workflows, agents, tasks AND ALL FILES with hashes BEFORE IDE setup
|
|
263
505
|
spinner.start('Generating workflow and agent manifests...');
|
|
264
506
|
const manifestGen = new ManifestGenerator();
|
|
265
|
-
|
|
507
|
+
|
|
508
|
+
// Include preserved modules (from quick update) in the manifest
|
|
509
|
+
const allModulesToList = config._preserveModules ? [...(config.modules || []), ...config._preserveModules] : config.modules || [];
|
|
510
|
+
|
|
511
|
+
const manifestStats = await manifestGen.generateManifests(bmadDir, config.modules || [], this.installedFiles, {
|
|
512
|
+
ides: config.ides || [],
|
|
513
|
+
preservedModules: config._preserveModules || [], // Scan these from installed bmad/ dir
|
|
514
|
+
});
|
|
515
|
+
|
|
266
516
|
spinner.succeed(
|
|
267
|
-
`Manifests generated: ${manifestStats.workflows} workflows, ${manifestStats.agents} agents, ${manifestStats.tasks} tasks`,
|
|
517
|
+
`Manifests generated: ${manifestStats.workflows} workflows, ${manifestStats.agents} agents, ${manifestStats.tasks} tasks, ${manifestStats.tools} tools, ${manifestStats.files} files`,
|
|
268
518
|
);
|
|
269
519
|
|
|
270
520
|
// Configure IDEs and copy documentation
|
|
271
521
|
if (!config.skipIde && config.ides && config.ides.length > 0) {
|
|
272
|
-
|
|
522
|
+
// Filter out any undefined/null values from the IDE list
|
|
523
|
+
const validIdes = config.ides.filter((ide) => ide && typeof ide === 'string');
|
|
273
524
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
525
|
+
if (validIdes.length === 0) {
|
|
526
|
+
console.log(chalk.yellow('⚠️ No valid IDEs selected. Skipping IDE configuration.'));
|
|
527
|
+
} else {
|
|
528
|
+
// Check if any IDE might need prompting (no pre-collected config)
|
|
529
|
+
const needsPrompting = validIdes.some((ide) => !ideConfigurations[ide]);
|
|
279
530
|
|
|
280
|
-
|
|
281
|
-
|
|
531
|
+
if (!needsPrompting) {
|
|
532
|
+
spinner.start('Configuring IDEs...');
|
|
533
|
+
}
|
|
282
534
|
|
|
283
|
-
//
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
535
|
+
// Temporarily suppress console output if not verbose
|
|
536
|
+
const originalLog = console.log;
|
|
537
|
+
if (!config.verbose) {
|
|
538
|
+
console.log = () => {};
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
for (const ide of validIdes) {
|
|
542
|
+
// Only show spinner if we have pre-collected config (no prompts expected)
|
|
543
|
+
if (ideConfigurations[ide] && !needsPrompting) {
|
|
544
|
+
spinner.text = `Configuring ${ide}...`;
|
|
545
|
+
} else if (!ideConfigurations[ide]) {
|
|
546
|
+
// Stop spinner before prompting
|
|
547
|
+
if (spinner.isSpinning) {
|
|
548
|
+
spinner.stop();
|
|
549
|
+
}
|
|
550
|
+
console.log(chalk.cyan(`\nConfiguring ${ide}...`));
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// Pass pre-collected configuration to avoid re-prompting
|
|
554
|
+
await this.ideManager.setup(ide, projectDir, bmadDir, {
|
|
555
|
+
selectedModules: config.modules || [],
|
|
556
|
+
preCollectedConfig: ideConfigurations[ide] || null,
|
|
557
|
+
verbose: config.verbose,
|
|
558
|
+
});
|
|
559
|
+
|
|
560
|
+
// Save IDE configuration for future updates
|
|
561
|
+
if (ideConfigurations[ide] && !ideConfigurations[ide]._alreadyConfigured) {
|
|
562
|
+
await this.ideConfigManager.saveIdeConfig(bmadDir, ide, ideConfigurations[ide]);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Restart spinner if we stopped it
|
|
566
|
+
if (!ideConfigurations[ide] && !spinner.isSpinning) {
|
|
567
|
+
spinner.start('Configuring IDEs...');
|
|
568
|
+
}
|
|
569
|
+
}
|
|
290
570
|
|
|
291
|
-
|
|
292
|
-
|
|
571
|
+
// Restore console.log
|
|
572
|
+
console.log = originalLog;
|
|
293
573
|
|
|
294
|
-
|
|
574
|
+
if (spinner.isSpinning) {
|
|
575
|
+
spinner.succeed(`Configured ${validIdes.length} IDE${validIdes.length > 1 ? 's' : ''}`);
|
|
576
|
+
} else {
|
|
577
|
+
console.log(chalk.green(`✓ Configured ${validIdes.length} IDE${validIdes.length > 1 ? 's' : ''}`));
|
|
578
|
+
}
|
|
579
|
+
}
|
|
295
580
|
|
|
296
|
-
// Copy IDE-specific documentation
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
581
|
+
// Copy IDE-specific documentation (only for valid IDEs)
|
|
582
|
+
const validIdesForDocs = (config.ides || []).filter((ide) => ide && typeof ide === 'string');
|
|
583
|
+
if (validIdesForDocs.length > 0) {
|
|
584
|
+
spinner.start('Copying IDE documentation...');
|
|
585
|
+
await this.copyIdeDocumentation(validIdesForDocs, bmadDir);
|
|
586
|
+
spinner.succeed('IDE documentation copied');
|
|
587
|
+
}
|
|
300
588
|
}
|
|
301
589
|
|
|
302
590
|
// Run module-specific installers after IDE setup
|
|
@@ -337,24 +625,83 @@ class Installer {
|
|
|
337
625
|
|
|
338
626
|
spinner.succeed('Module-specific installers completed');
|
|
339
627
|
|
|
340
|
-
//
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
628
|
+
// Note: Manifest files are already created by ManifestGenerator above
|
|
629
|
+
// No need to create legacy manifest.csv anymore
|
|
630
|
+
|
|
631
|
+
// If this was an update, restore custom files
|
|
632
|
+
let customFiles = [];
|
|
633
|
+
let modifiedFiles = [];
|
|
634
|
+
if (config._isUpdate) {
|
|
635
|
+
if (config._customFiles && config._customFiles.length > 0) {
|
|
636
|
+
spinner.start(`Restoring ${config._customFiles.length} custom files...`);
|
|
637
|
+
|
|
638
|
+
for (const originalPath of config._customFiles) {
|
|
639
|
+
const relativePath = path.relative(bmadDir, originalPath);
|
|
640
|
+
const backupPath = path.join(config._tempBackupDir, relativePath);
|
|
641
|
+
|
|
642
|
+
if (await fs.pathExists(backupPath)) {
|
|
643
|
+
await fs.ensureDir(path.dirname(originalPath));
|
|
644
|
+
await fs.copy(backupPath, originalPath, { overwrite: true });
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
// Clean up temp backup
|
|
649
|
+
if (config._tempBackupDir && (await fs.pathExists(config._tempBackupDir))) {
|
|
650
|
+
await fs.remove(config._tempBackupDir);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
spinner.succeed(`Restored ${config._customFiles.length} custom files`);
|
|
654
|
+
customFiles = config._customFiles;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
if (config._modifiedFiles && config._modifiedFiles.length > 0) {
|
|
658
|
+
modifiedFiles = config._modifiedFiles;
|
|
659
|
+
|
|
660
|
+
// Restore modified files as .bak files
|
|
661
|
+
if (config._tempModifiedBackupDir && (await fs.pathExists(config._tempModifiedBackupDir))) {
|
|
662
|
+
spinner.start(`Restoring ${modifiedFiles.length} modified files as .bak...`);
|
|
663
|
+
|
|
664
|
+
for (const modifiedFile of modifiedFiles) {
|
|
665
|
+
const relativePath = path.relative(bmadDir, modifiedFile.path);
|
|
666
|
+
const tempBackupPath = path.join(config._tempModifiedBackupDir, relativePath);
|
|
667
|
+
const bakPath = modifiedFile.path + '.bak';
|
|
668
|
+
|
|
669
|
+
if (await fs.pathExists(tempBackupPath)) {
|
|
670
|
+
await fs.ensureDir(path.dirname(bakPath));
|
|
671
|
+
await fs.copy(tempBackupPath, bakPath, { overwrite: true });
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// Clean up temp backup
|
|
676
|
+
await fs.remove(config._tempModifiedBackupDir);
|
|
677
|
+
|
|
678
|
+
spinner.succeed(`Restored ${modifiedFiles.length} modified files as .bak`);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
}
|
|
355
682
|
|
|
356
683
|
spinner.stop();
|
|
357
684
|
|
|
685
|
+
// Report custom and modified files if any were found
|
|
686
|
+
if (customFiles.length > 0) {
|
|
687
|
+
console.log(chalk.cyan(`\n📁 Custom files preserved: ${customFiles.length}`));
|
|
688
|
+
console.log(chalk.dim('The following custom files were found and restored:\n'));
|
|
689
|
+
for (const file of customFiles) {
|
|
690
|
+
console.log(chalk.dim(` - ${path.relative(bmadDir, file)}`));
|
|
691
|
+
}
|
|
692
|
+
console.log('');
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
if (modifiedFiles.length > 0) {
|
|
696
|
+
console.log(chalk.yellow(`\n⚠️ Modified files detected: ${modifiedFiles.length}`));
|
|
697
|
+
console.log(chalk.dim('The following files were modified and backed up with .bak extension:\n'));
|
|
698
|
+
for (const file of modifiedFiles) {
|
|
699
|
+
console.log(chalk.dim(` - ${file.relativePath} → ${file.relativePath}.bak`));
|
|
700
|
+
}
|
|
701
|
+
console.log(chalk.dim('\nThese files have been updated with the new version.'));
|
|
702
|
+
console.log(chalk.dim('Review the .bak files to see your changes and merge if needed.\n'));
|
|
703
|
+
}
|
|
704
|
+
|
|
358
705
|
// Display completion message
|
|
359
706
|
const { UI } = require('../../../lib/ui');
|
|
360
707
|
const ui = new UI();
|
|
@@ -362,6 +709,7 @@ class Installer {
|
|
|
362
709
|
path: bmadDir,
|
|
363
710
|
modules: config.modules,
|
|
364
711
|
ides: config.ides,
|
|
712
|
+
customFiles: customFiles.length > 0 ? customFiles : undefined,
|
|
365
713
|
});
|
|
366
714
|
|
|
367
715
|
return { success: true, path: bmadDir, modules: config.modules, ides: config.ides };
|
|
@@ -560,6 +908,9 @@ class Installer {
|
|
|
560
908
|
|
|
561
909
|
// Write the clean config file
|
|
562
910
|
await fs.writeFile(configPath, header + yamlContent, 'utf8');
|
|
911
|
+
|
|
912
|
+
// Track the config file in installedFiles
|
|
913
|
+
this.installedFiles.push(configPath);
|
|
563
914
|
}
|
|
564
915
|
}
|
|
565
916
|
}
|
|
@@ -589,6 +940,9 @@ class Installer {
|
|
|
589
940
|
* @param {Object} moduleFiles - Module files to install
|
|
590
941
|
*/
|
|
591
942
|
async installModuleWithDependencies(moduleName, bmadDir, moduleFiles) {
|
|
943
|
+
// Get module configuration for conditional installation
|
|
944
|
+
const moduleConfig = this.configCollector.collectedConfig[moduleName] || {};
|
|
945
|
+
|
|
592
946
|
// Use existing module manager for full installation with file tracking
|
|
593
947
|
// Note: Module-specific installers are called separately after IDE setup
|
|
594
948
|
await this.moduleManager.install(
|
|
@@ -599,9 +953,14 @@ class Installer {
|
|
|
599
953
|
},
|
|
600
954
|
{
|
|
601
955
|
skipModuleInstaller: true, // We'll run it later after IDE setup
|
|
956
|
+
moduleConfig: moduleConfig, // Pass module config for conditional filtering
|
|
602
957
|
},
|
|
603
958
|
);
|
|
604
959
|
|
|
960
|
+
// Process agent files to build YAML agents and create customize templates
|
|
961
|
+
const modulePath = path.join(bmadDir, moduleName);
|
|
962
|
+
await this.processAgentFiles(modulePath, moduleName);
|
|
963
|
+
|
|
605
964
|
// Dependencies are already included in full module install
|
|
606
965
|
}
|
|
607
966
|
|
|
@@ -648,6 +1007,22 @@ class Installer {
|
|
|
648
1007
|
}
|
|
649
1008
|
}
|
|
650
1009
|
|
|
1010
|
+
if (files.tools && files.tools.length > 0) {
|
|
1011
|
+
const toolsDir = path.join(targetBase, 'tools');
|
|
1012
|
+
await fs.ensureDir(toolsDir);
|
|
1013
|
+
|
|
1014
|
+
for (const toolPath of files.tools) {
|
|
1015
|
+
const fileName = path.basename(toolPath);
|
|
1016
|
+
const sourcePath = path.join(sourceBase, 'tools', fileName);
|
|
1017
|
+
const targetPath = path.join(toolsDir, fileName);
|
|
1018
|
+
|
|
1019
|
+
if (await fs.pathExists(sourcePath)) {
|
|
1020
|
+
await fs.copy(sourcePath, targetPath);
|
|
1021
|
+
this.installedFiles.push(targetPath);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
|
|
651
1026
|
if (files.templates && files.templates.length > 0) {
|
|
652
1027
|
const templatesDir = path.join(targetBase, 'templates');
|
|
653
1028
|
await fs.ensureDir(templatesDir);
|
|
@@ -771,8 +1146,8 @@ class Installer {
|
|
|
771
1146
|
}
|
|
772
1147
|
|
|
773
1148
|
/**
|
|
774
|
-
* Process agent files to inject activation
|
|
775
|
-
* @param {string} modulePath - Path to module
|
|
1149
|
+
* Process agent files to build YAML agents and inject activation blocks
|
|
1150
|
+
* @param {string} modulePath - Path to module in bmad/ installation
|
|
776
1151
|
* @param {string} moduleName - Module name
|
|
777
1152
|
*/
|
|
778
1153
|
async processAgentFiles(modulePath, moduleName) {
|
|
@@ -783,21 +1158,360 @@ class Installer {
|
|
|
783
1158
|
return; // No agents to process
|
|
784
1159
|
}
|
|
785
1160
|
|
|
1161
|
+
// Determine project directory (parent of bmad/ directory)
|
|
1162
|
+
const bmadDir = path.dirname(modulePath);
|
|
1163
|
+
const projectDir = path.dirname(bmadDir);
|
|
1164
|
+
const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
|
|
1165
|
+
|
|
1166
|
+
// Ensure _cfg/agents directory exists
|
|
1167
|
+
await fs.ensureDir(cfgAgentsDir);
|
|
1168
|
+
|
|
786
1169
|
// Get all agent files
|
|
787
1170
|
const agentFiles = await fs.readdir(agentsPath);
|
|
788
1171
|
|
|
789
1172
|
for (const agentFile of agentFiles) {
|
|
790
|
-
|
|
1173
|
+
// Handle YAML agents - build them to .md
|
|
1174
|
+
if (agentFile.endsWith('.agent.yaml')) {
|
|
1175
|
+
const agentName = agentFile.replace('.agent.yaml', '');
|
|
1176
|
+
const yamlPath = path.join(agentsPath, agentFile);
|
|
1177
|
+
const mdPath = path.join(agentsPath, `${agentName}.md`);
|
|
1178
|
+
const customizePath = path.join(cfgAgentsDir, `${moduleName}-${agentName}.customize.yaml`);
|
|
1179
|
+
|
|
1180
|
+
// Create customize template if it doesn't exist
|
|
1181
|
+
if (!(await fs.pathExists(customizePath))) {
|
|
1182
|
+
const genericTemplatePath = getSourcePath('utility', 'templates', 'agent.customize.template.yaml');
|
|
1183
|
+
if (await fs.pathExists(genericTemplatePath)) {
|
|
1184
|
+
await fs.copy(genericTemplatePath, customizePath);
|
|
1185
|
+
console.log(chalk.dim(` Created customize: ${moduleName}-${agentName}.customize.yaml`));
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// Build YAML + customize to .md
|
|
1190
|
+
const customizeExists = await fs.pathExists(customizePath);
|
|
1191
|
+
const xmlContent = await this.xmlHandler.buildFromYaml(yamlPath, customizeExists ? customizePath : null, {
|
|
1192
|
+
includeMetadata: true,
|
|
1193
|
+
});
|
|
1194
|
+
|
|
1195
|
+
// DO NOT replace {project-root} - LLMs understand this placeholder at runtime
|
|
1196
|
+
// const processedContent = xmlContent.replaceAll('{project-root}', projectDir);
|
|
1197
|
+
|
|
1198
|
+
// Write the built .md file to bmad/{module}/agents/
|
|
1199
|
+
await fs.writeFile(mdPath, xmlContent, 'utf8');
|
|
1200
|
+
this.installedFiles.push(mdPath);
|
|
1201
|
+
|
|
1202
|
+
// Remove the source YAML file - we can regenerate from installer source if needed
|
|
1203
|
+
await fs.remove(yamlPath);
|
|
1204
|
+
|
|
1205
|
+
console.log(chalk.dim(` Built agent: ${agentName}.md`));
|
|
1206
|
+
}
|
|
1207
|
+
// Handle legacy .md agents - inject activation if needed
|
|
1208
|
+
else if (agentFile.endsWith('.md')) {
|
|
1209
|
+
const agentPath = path.join(agentsPath, agentFile);
|
|
1210
|
+
let content = await fs.readFile(agentPath, 'utf8');
|
|
1211
|
+
|
|
1212
|
+
// Check if content has agent XML and no activation block
|
|
1213
|
+
if (content.includes('<agent') && !content.includes('<activation')) {
|
|
1214
|
+
// Inject the activation block using XML handler
|
|
1215
|
+
content = this.xmlHandler.injectActivationSimple(content);
|
|
1216
|
+
await fs.writeFile(agentPath, content, 'utf8');
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
/**
|
|
1223
|
+
* Build standalone agents in bmad/agents/ directory
|
|
1224
|
+
* @param {string} bmadDir - Path to bmad directory
|
|
1225
|
+
* @param {string} projectDir - Path to project directory
|
|
1226
|
+
*/
|
|
1227
|
+
async buildStandaloneAgents(bmadDir, projectDir) {
|
|
1228
|
+
const standaloneAgentsPath = path.join(bmadDir, 'agents');
|
|
1229
|
+
const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
|
|
1230
|
+
|
|
1231
|
+
// Check if standalone agents directory exists
|
|
1232
|
+
if (!(await fs.pathExists(standaloneAgentsPath))) {
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
// Get all subdirectories in agents/
|
|
1237
|
+
const agentDirs = await fs.readdir(standaloneAgentsPath, { withFileTypes: true });
|
|
1238
|
+
|
|
1239
|
+
for (const agentDir of agentDirs) {
|
|
1240
|
+
if (!agentDir.isDirectory()) continue;
|
|
1241
|
+
|
|
1242
|
+
const agentDirPath = path.join(standaloneAgentsPath, agentDir.name);
|
|
1243
|
+
|
|
1244
|
+
// Find any .agent.yaml file in the directory
|
|
1245
|
+
const files = await fs.readdir(agentDirPath);
|
|
1246
|
+
const yamlFile = files.find((f) => f.endsWith('.agent.yaml'));
|
|
1247
|
+
|
|
1248
|
+
if (!yamlFile) continue;
|
|
1249
|
+
|
|
1250
|
+
const agentName = path.basename(yamlFile, '.agent.yaml');
|
|
1251
|
+
const sourceYamlPath = path.join(agentDirPath, yamlFile);
|
|
1252
|
+
const targetMdPath = path.join(agentDirPath, `${agentName}.md`);
|
|
1253
|
+
const customizePath = path.join(cfgAgentsDir, `${agentName}.customize.yaml`);
|
|
1254
|
+
|
|
1255
|
+
// Check for customizations
|
|
1256
|
+
const customizeExists = await fs.pathExists(customizePath);
|
|
1257
|
+
let customizedFields = [];
|
|
1258
|
+
|
|
1259
|
+
if (customizeExists) {
|
|
1260
|
+
const customizeContent = await fs.readFile(customizePath, 'utf8');
|
|
1261
|
+
const yaml = require('js-yaml');
|
|
1262
|
+
const customizeYaml = yaml.load(customizeContent);
|
|
1263
|
+
|
|
1264
|
+
// Detect what fields are customized (similar to rebuildAgentFiles)
|
|
1265
|
+
if (customizeYaml) {
|
|
1266
|
+
if (customizeYaml.persona) {
|
|
1267
|
+
for (const [key, value] of Object.entries(customizeYaml.persona)) {
|
|
1268
|
+
if (value !== '' && value !== null && !(Array.isArray(value) && value.length === 0)) {
|
|
1269
|
+
customizedFields.push(`persona.${key}`);
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
if (customizeYaml.agent?.metadata) {
|
|
1274
|
+
for (const [key, value] of Object.entries(customizeYaml.agent.metadata)) {
|
|
1275
|
+
if (value !== '' && value !== null) {
|
|
1276
|
+
customizedFields.push(`metadata.${key}`);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
if (customizeYaml.critical_actions && customizeYaml.critical_actions.length > 0) {
|
|
1281
|
+
customizedFields.push('critical_actions');
|
|
1282
|
+
}
|
|
1283
|
+
if (customizeYaml.menu && customizeYaml.menu.length > 0) {
|
|
1284
|
+
customizedFields.push('menu');
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
// Build YAML to XML .md
|
|
1290
|
+
const xmlContent = await this.xmlHandler.buildFromYaml(sourceYamlPath, customizeExists ? customizePath : null, {
|
|
1291
|
+
includeMetadata: true,
|
|
1292
|
+
});
|
|
791
1293
|
|
|
792
|
-
|
|
793
|
-
|
|
1294
|
+
// DO NOT replace {project-root} - LLMs understand this placeholder at runtime
|
|
1295
|
+
// const processedContent = xmlContent.replaceAll('{project-root}', projectDir);
|
|
794
1296
|
|
|
795
|
-
//
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
1297
|
+
// Write the built .md file
|
|
1298
|
+
await fs.writeFile(targetMdPath, xmlContent, 'utf8');
|
|
1299
|
+
|
|
1300
|
+
// Display result
|
|
1301
|
+
if (customizedFields.length > 0) {
|
|
1302
|
+
console.log(chalk.dim(` Built standalone agent: ${agentName}.md `) + chalk.yellow(`(customized: ${customizedFields.join(', ')})`));
|
|
1303
|
+
} else {
|
|
1304
|
+
console.log(chalk.dim(` Built standalone agent: ${agentName}.md`));
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
|
|
1309
|
+
/**
|
|
1310
|
+
* Rebuild agent files from installer source (for compile command)
|
|
1311
|
+
* @param {string} modulePath - Path to module in bmad/ installation
|
|
1312
|
+
* @param {string} moduleName - Module name
|
|
1313
|
+
*/
|
|
1314
|
+
async rebuildAgentFiles(modulePath, moduleName) {
|
|
1315
|
+
// Get source agents directory from installer
|
|
1316
|
+
const sourceAgentsPath =
|
|
1317
|
+
moduleName === 'core' ? path.join(getModulePath('core'), 'agents') : path.join(getSourcePath(`modules/${moduleName}`), 'agents');
|
|
1318
|
+
|
|
1319
|
+
if (!(await fs.pathExists(sourceAgentsPath))) {
|
|
1320
|
+
return; // No source agents to rebuild
|
|
1321
|
+
}
|
|
1322
|
+
|
|
1323
|
+
// Determine project directory (parent of bmad/ directory)
|
|
1324
|
+
const bmadDir = path.dirname(modulePath);
|
|
1325
|
+
const projectDir = path.dirname(bmadDir);
|
|
1326
|
+
const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents');
|
|
1327
|
+
const targetAgentsPath = path.join(modulePath, 'agents');
|
|
1328
|
+
|
|
1329
|
+
// Ensure target directory exists
|
|
1330
|
+
await fs.ensureDir(targetAgentsPath);
|
|
1331
|
+
|
|
1332
|
+
// Get all YAML agent files from source
|
|
1333
|
+
const sourceFiles = await fs.readdir(sourceAgentsPath);
|
|
1334
|
+
|
|
1335
|
+
for (const file of sourceFiles) {
|
|
1336
|
+
if (file.endsWith('.agent.yaml')) {
|
|
1337
|
+
const agentName = file.replace('.agent.yaml', '');
|
|
1338
|
+
const sourceYamlPath = path.join(sourceAgentsPath, file);
|
|
1339
|
+
const targetMdPath = path.join(targetAgentsPath, `${agentName}.md`);
|
|
1340
|
+
const customizePath = path.join(cfgAgentsDir, `${moduleName}-${agentName}.customize.yaml`);
|
|
1341
|
+
|
|
1342
|
+
// Check for customizations
|
|
1343
|
+
const customizeExists = await fs.pathExists(customizePath);
|
|
1344
|
+
let customizedFields = [];
|
|
1345
|
+
|
|
1346
|
+
if (customizeExists) {
|
|
1347
|
+
const customizeContent = await fs.readFile(customizePath, 'utf8');
|
|
1348
|
+
const yaml = require('js-yaml');
|
|
1349
|
+
const customizeYaml = yaml.load(customizeContent);
|
|
1350
|
+
|
|
1351
|
+
// Detect what fields are customized
|
|
1352
|
+
if (customizeYaml) {
|
|
1353
|
+
if (customizeYaml.persona) {
|
|
1354
|
+
for (const [key, value] of Object.entries(customizeYaml.persona)) {
|
|
1355
|
+
if (value !== '' && value !== null && !(Array.isArray(value) && value.length === 0)) {
|
|
1356
|
+
customizedFields.push(`persona.${key}`);
|
|
1357
|
+
}
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
if (customizeYaml.agent?.metadata) {
|
|
1361
|
+
for (const [key, value] of Object.entries(customizeYaml.agent.metadata)) {
|
|
1362
|
+
if (value !== '' && value !== null) {
|
|
1363
|
+
customizedFields.push(`metadata.${key}`);
|
|
1364
|
+
}
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
if (customizeYaml.critical_actions && customizeYaml.critical_actions.length > 0) {
|
|
1368
|
+
customizedFields.push('critical_actions');
|
|
1369
|
+
}
|
|
1370
|
+
if (customizeYaml.memories && customizeYaml.memories.length > 0) {
|
|
1371
|
+
customizedFields.push('memories');
|
|
1372
|
+
}
|
|
1373
|
+
if (customizeYaml.menu && customizeYaml.menu.length > 0) {
|
|
1374
|
+
customizedFields.push('menu');
|
|
1375
|
+
}
|
|
1376
|
+
if (customizeYaml.prompts && customizeYaml.prompts.length > 0) {
|
|
1377
|
+
customizedFields.push('prompts');
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
// Build YAML + customize to .md
|
|
1383
|
+
const xmlContent = await this.xmlHandler.buildFromYaml(sourceYamlPath, customizeExists ? customizePath : null, {
|
|
1384
|
+
includeMetadata: true,
|
|
1385
|
+
});
|
|
1386
|
+
|
|
1387
|
+
// DO NOT replace {project-root} - LLMs understand this placeholder at runtime
|
|
1388
|
+
// const processedContent = xmlContent.replaceAll('{project-root}', projectDir);
|
|
1389
|
+
|
|
1390
|
+
// Write the rebuilt .md file
|
|
1391
|
+
await fs.writeFile(targetMdPath, xmlContent, 'utf8');
|
|
1392
|
+
|
|
1393
|
+
// Display result with customizations if any
|
|
1394
|
+
if (customizedFields.length > 0) {
|
|
1395
|
+
console.log(chalk.dim(` Rebuilt agent: ${agentName}.md `) + chalk.yellow(`(customized: ${customizedFields.join(', ')})`));
|
|
1396
|
+
} else {
|
|
1397
|
+
console.log(chalk.dim(` Rebuilt agent: ${agentName}.md`));
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
/**
|
|
1404
|
+
* Compile/rebuild all agents and tasks for quick updates
|
|
1405
|
+
* @param {Object} config - Compilation configuration
|
|
1406
|
+
* @returns {Object} Compilation results
|
|
1407
|
+
*/
|
|
1408
|
+
async compileAgents(config) {
|
|
1409
|
+
const ora = require('ora');
|
|
1410
|
+
const spinner = ora('Starting agent compilation...').start();
|
|
1411
|
+
|
|
1412
|
+
try {
|
|
1413
|
+
const projectDir = path.resolve(config.directory);
|
|
1414
|
+
const bmadDir = path.join(projectDir, 'bmad');
|
|
1415
|
+
|
|
1416
|
+
// Check if bmad directory exists
|
|
1417
|
+
if (!(await fs.pathExists(bmadDir))) {
|
|
1418
|
+
spinner.fail('No BMAD installation found');
|
|
1419
|
+
throw new Error(`BMAD not installed at ${bmadDir}`);
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
let agentCount = 0;
|
|
1423
|
+
let taskCount = 0;
|
|
1424
|
+
|
|
1425
|
+
// Process all modules in bmad directory
|
|
1426
|
+
spinner.text = 'Rebuilding agent files...';
|
|
1427
|
+
const entries = await fs.readdir(bmadDir, { withFileTypes: true });
|
|
1428
|
+
|
|
1429
|
+
for (const entry of entries) {
|
|
1430
|
+
if (entry.isDirectory() && entry.name !== '_cfg' && entry.name !== 'docs') {
|
|
1431
|
+
const modulePath = path.join(bmadDir, entry.name);
|
|
1432
|
+
|
|
1433
|
+
// Special handling for standalone agents in bmad/agents/ directory
|
|
1434
|
+
if (entry.name === 'agents') {
|
|
1435
|
+
spinner.text = 'Building standalone agents...';
|
|
1436
|
+
await this.buildStandaloneAgents(bmadDir, projectDir);
|
|
1437
|
+
|
|
1438
|
+
// Count standalone agents
|
|
1439
|
+
const standaloneAgentsPath = path.join(bmadDir, 'agents');
|
|
1440
|
+
const standaloneAgentDirs = await fs.readdir(standaloneAgentsPath, { withFileTypes: true });
|
|
1441
|
+
for (const agentDir of standaloneAgentDirs) {
|
|
1442
|
+
if (agentDir.isDirectory()) {
|
|
1443
|
+
const agentDirPath = path.join(standaloneAgentsPath, agentDir.name);
|
|
1444
|
+
const agentFiles = await fs.readdir(agentDirPath);
|
|
1445
|
+
agentCount += agentFiles.filter((f) => f.endsWith('.md') && !f.endsWith('.agent.yaml')).length;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
} else {
|
|
1449
|
+
// Rebuild module agents from installer source
|
|
1450
|
+
const agentsPath = path.join(modulePath, 'agents');
|
|
1451
|
+
if (await fs.pathExists(agentsPath)) {
|
|
1452
|
+
await this.rebuildAgentFiles(modulePath, entry.name);
|
|
1453
|
+
const agentFiles = await fs.readdir(agentsPath);
|
|
1454
|
+
agentCount += agentFiles.filter((f) => f.endsWith('.md')).length;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
// Count tasks (already built)
|
|
1458
|
+
const tasksPath = path.join(modulePath, 'tasks');
|
|
1459
|
+
if (await fs.pathExists(tasksPath)) {
|
|
1460
|
+
const taskFiles = await fs.readdir(tasksPath);
|
|
1461
|
+
taskCount += taskFiles.filter((f) => f.endsWith('.md')).length;
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
// Regenerate manifests after compilation
|
|
1468
|
+
spinner.start('Regenerating manifests...');
|
|
1469
|
+
const installedModules = entries
|
|
1470
|
+
.filter((e) => e.isDirectory() && e.name !== '_cfg' && e.name !== 'docs' && e.name !== 'agents' && e.name !== 'core')
|
|
1471
|
+
.map((e) => e.name);
|
|
1472
|
+
const manifestGen = new ManifestGenerator();
|
|
1473
|
+
|
|
1474
|
+
// Get existing IDE list from manifest
|
|
1475
|
+
const existingManifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml');
|
|
1476
|
+
let existingIdes = [];
|
|
1477
|
+
if (await fs.pathExists(existingManifestPath)) {
|
|
1478
|
+
const manifestContent = await fs.readFile(existingManifestPath, 'utf8');
|
|
1479
|
+
const yaml = require('js-yaml');
|
|
1480
|
+
const manifest = yaml.load(manifestContent);
|
|
1481
|
+
existingIdes = manifest.ides || [];
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
await manifestGen.generateManifests(bmadDir, installedModules, [], {
|
|
1485
|
+
ides: existingIdes,
|
|
1486
|
+
});
|
|
1487
|
+
spinner.succeed('Manifests regenerated');
|
|
1488
|
+
|
|
1489
|
+
// Ask for IDE to update
|
|
1490
|
+
spinner.stop();
|
|
1491
|
+
// Note: UI lives in tools/cli/lib/ui.js; from installers/lib/core use '../../../lib/ui'
|
|
1492
|
+
const { UI } = require('../../../lib/ui');
|
|
1493
|
+
const ui = new UI();
|
|
1494
|
+
const toolConfig = await ui.promptToolSelection(projectDir, []);
|
|
1495
|
+
|
|
1496
|
+
if (!toolConfig.skipIde && toolConfig.ides && toolConfig.ides.length > 0) {
|
|
1497
|
+
spinner.start('Updating IDE configurations...');
|
|
1498
|
+
|
|
1499
|
+
for (const ide of toolConfig.ides) {
|
|
1500
|
+
spinner.text = `Updating ${ide}...`;
|
|
1501
|
+
await this.ideManager.setup(ide, projectDir, bmadDir, {
|
|
1502
|
+
selectedModules: installedModules,
|
|
1503
|
+
skipModuleInstall: true, // Skip module installation, just update IDE files
|
|
1504
|
+
verbose: config.verbose,
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
spinner.succeed('IDE configurations updated');
|
|
800
1509
|
}
|
|
1510
|
+
|
|
1511
|
+
return { agentCount, taskCount };
|
|
1512
|
+
} catch (error) {
|
|
1513
|
+
spinner.fail('Compilation failed');
|
|
1514
|
+
throw error;
|
|
801
1515
|
}
|
|
802
1516
|
}
|
|
803
1517
|
|
|
@@ -817,6 +1531,116 @@ class Installer {
|
|
|
817
1531
|
}
|
|
818
1532
|
}
|
|
819
1533
|
|
|
1534
|
+
/**
|
|
1535
|
+
* Quick update method - preserves all settings and only prompts for new config fields
|
|
1536
|
+
* @param {Object} config - Configuration with directory
|
|
1537
|
+
* @returns {Object} Update result
|
|
1538
|
+
*/
|
|
1539
|
+
async quickUpdate(config) {
|
|
1540
|
+
const ora = require('ora');
|
|
1541
|
+
const spinner = ora('Starting quick update...').start();
|
|
1542
|
+
|
|
1543
|
+
try {
|
|
1544
|
+
const projectDir = path.resolve(config.directory);
|
|
1545
|
+
const bmadDir = path.join(projectDir, 'bmad');
|
|
1546
|
+
|
|
1547
|
+
// Check if bmad directory exists
|
|
1548
|
+
if (!(await fs.pathExists(bmadDir))) {
|
|
1549
|
+
spinner.fail('No BMAD installation found');
|
|
1550
|
+
throw new Error(`BMAD not installed at ${bmadDir}. Use regular install for first-time setup.`);
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
spinner.text = 'Detecting installed modules and configuration...';
|
|
1554
|
+
|
|
1555
|
+
// Detect existing installation
|
|
1556
|
+
const existingInstall = await this.detector.detect(bmadDir);
|
|
1557
|
+
const installedModules = existingInstall.modules.map((m) => m.id);
|
|
1558
|
+
const configuredIdes = existingInstall.ides || [];
|
|
1559
|
+
|
|
1560
|
+
// Load saved IDE configurations
|
|
1561
|
+
const savedIdeConfigs = await this.ideConfigManager.loadAllIdeConfigs(bmadDir);
|
|
1562
|
+
|
|
1563
|
+
// Get available modules (what we have source for)
|
|
1564
|
+
const availableModules = await this.moduleManager.listAvailable();
|
|
1565
|
+
const availableModuleIds = new Set(availableModules.map((m) => m.id));
|
|
1566
|
+
|
|
1567
|
+
// Only update modules that are BOTH installed AND available (we have source for)
|
|
1568
|
+
const modulesToUpdate = installedModules.filter((id) => availableModuleIds.has(id));
|
|
1569
|
+
const skippedModules = installedModules.filter((id) => !availableModuleIds.has(id));
|
|
1570
|
+
|
|
1571
|
+
spinner.succeed(`Found ${modulesToUpdate.length} module(s) to update and ${configuredIdes.length} configured tool(s)`);
|
|
1572
|
+
|
|
1573
|
+
if (skippedModules.length > 0) {
|
|
1574
|
+
console.log(chalk.yellow(`⚠️ Skipping ${skippedModules.length} module(s) - no source available: ${skippedModules.join(', ')}`));
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
// Load existing configs and collect new fields (if any)
|
|
1578
|
+
console.log(chalk.cyan('\n📋 Checking for new configuration options...'));
|
|
1579
|
+
await this.configCollector.loadExistingConfig(projectDir);
|
|
1580
|
+
|
|
1581
|
+
let promptedForNewFields = false;
|
|
1582
|
+
|
|
1583
|
+
// Check core config for new fields
|
|
1584
|
+
const corePrompted = await this.configCollector.collectModuleConfigQuick('core', projectDir, true);
|
|
1585
|
+
if (corePrompted) {
|
|
1586
|
+
promptedForNewFields = true;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
// Check each module we're updating for new fields (NOT skipped modules)
|
|
1590
|
+
for (const moduleName of modulesToUpdate) {
|
|
1591
|
+
const modulePrompted = await this.configCollector.collectModuleConfigQuick(moduleName, projectDir, true);
|
|
1592
|
+
if (modulePrompted) {
|
|
1593
|
+
promptedForNewFields = true;
|
|
1594
|
+
}
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
if (!promptedForNewFields) {
|
|
1598
|
+
console.log(chalk.green('✓ All configuration is up to date, no new options to configure'));
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
// Add metadata
|
|
1602
|
+
this.configCollector.collectedConfig._meta = {
|
|
1603
|
+
version: require(path.join(getProjectRoot(), 'package.json')).version,
|
|
1604
|
+
installDate: new Date().toISOString(),
|
|
1605
|
+
lastModified: new Date().toISOString(),
|
|
1606
|
+
};
|
|
1607
|
+
|
|
1608
|
+
// Now run the full installation with the collected configs
|
|
1609
|
+
spinner.start('Updating BMAD installation...');
|
|
1610
|
+
|
|
1611
|
+
// Build the config object for the installer
|
|
1612
|
+
const installConfig = {
|
|
1613
|
+
directory: projectDir,
|
|
1614
|
+
installCore: true,
|
|
1615
|
+
modules: modulesToUpdate, // Only update modules we have source for
|
|
1616
|
+
ides: configuredIdes,
|
|
1617
|
+
skipIde: configuredIdes.length === 0,
|
|
1618
|
+
coreConfig: this.configCollector.collectedConfig.core,
|
|
1619
|
+
actionType: 'install', // Use regular install flow
|
|
1620
|
+
_quickUpdate: true, // Flag to skip certain prompts
|
|
1621
|
+
_preserveModules: skippedModules, // Preserve these in manifest even though we didn't update them
|
|
1622
|
+
_savedIdeConfigs: savedIdeConfigs, // Pass saved IDE configs to installer
|
|
1623
|
+
};
|
|
1624
|
+
|
|
1625
|
+
// Call the standard install method
|
|
1626
|
+
const result = await this.install(installConfig);
|
|
1627
|
+
|
|
1628
|
+
spinner.succeed('Quick update complete!');
|
|
1629
|
+
|
|
1630
|
+
return {
|
|
1631
|
+
success: true,
|
|
1632
|
+
moduleCount: modulesToUpdate.length + 1, // +1 for core
|
|
1633
|
+
hadNewFields: promptedForNewFields,
|
|
1634
|
+
modules: ['core', ...modulesToUpdate],
|
|
1635
|
+
skippedModules: skippedModules,
|
|
1636
|
+
ides: configuredIdes,
|
|
1637
|
+
};
|
|
1638
|
+
} catch (error) {
|
|
1639
|
+
spinner.fail('Quick update failed');
|
|
1640
|
+
throw error;
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1643
|
+
|
|
820
1644
|
/**
|
|
821
1645
|
* Private: Prompt for update action
|
|
822
1646
|
*/
|
|
@@ -837,36 +1661,236 @@ class Installer {
|
|
|
837
1661
|
}
|
|
838
1662
|
|
|
839
1663
|
/**
|
|
840
|
-
*
|
|
1664
|
+
* Handle legacy BMAD v4 migration with automatic backup
|
|
1665
|
+
* @param {string} projectDir - Project directory
|
|
841
1666
|
* @param {Object} legacyV4 - Legacy V4 detection result with offenders array
|
|
842
|
-
* @returns {Error} Formatted error with fullMessage property
|
|
843
1667
|
*/
|
|
844
|
-
|
|
845
|
-
|
|
1668
|
+
async handleLegacyV4Migration(projectDir, legacyV4) {
|
|
1669
|
+
console.log(chalk.yellow.bold('\n⚠️ Legacy BMAD v4 detected'));
|
|
1670
|
+
console.log(chalk.dim('The installer found legacy artefacts in your project.\n'));
|
|
1671
|
+
|
|
1672
|
+
// Separate .bmad* folders (auto-backup) from other offending paths (manual cleanup)
|
|
1673
|
+
const bmadFolders = legacyV4.offenders.filter((p) => {
|
|
1674
|
+
const name = path.basename(p);
|
|
1675
|
+
return name.startsWith('.bmad'); // Only dot-prefixed folders get auto-backed up
|
|
1676
|
+
});
|
|
1677
|
+
const otherOffenders = legacyV4.offenders.filter((p) => {
|
|
1678
|
+
const name = path.basename(p);
|
|
1679
|
+
return !name.startsWith('.bmad'); // Everything else is manual cleanup
|
|
1680
|
+
});
|
|
1681
|
+
|
|
1682
|
+
const inquirer = require('inquirer');
|
|
1683
|
+
|
|
1684
|
+
// Show warning for other offending paths FIRST
|
|
1685
|
+
if (otherOffenders.length > 0) {
|
|
1686
|
+
console.log(chalk.yellow('⚠️ Recommended cleanup:'));
|
|
1687
|
+
console.log(chalk.dim('It is recommended to remove the following items before proceeding:\n'));
|
|
1688
|
+
for (const p of otherOffenders) console.log(chalk.dim(` - ${p}`));
|
|
1689
|
+
|
|
1690
|
+
console.log(chalk.cyan('\nCleanup commands you can copy/paste:'));
|
|
1691
|
+
console.log(chalk.dim('macOS/Linux:'));
|
|
1692
|
+
for (const p of otherOffenders) console.log(chalk.dim(` rm -rf '${p}'`));
|
|
1693
|
+
console.log(chalk.dim('Windows:'));
|
|
1694
|
+
for (const p of otherOffenders) console.log(chalk.dim(` rmdir /S /Q "${p}"`));
|
|
1695
|
+
|
|
1696
|
+
const { cleanedUp } = await inquirer.prompt([
|
|
1697
|
+
{
|
|
1698
|
+
type: 'confirm',
|
|
1699
|
+
name: 'cleanedUp',
|
|
1700
|
+
message: 'Have you completed the recommended cleanup? (You can proceed without it, but it is recommended)',
|
|
1701
|
+
default: false,
|
|
1702
|
+
},
|
|
1703
|
+
]);
|
|
1704
|
+
|
|
1705
|
+
if (cleanedUp) {
|
|
1706
|
+
console.log(chalk.green('✓ Cleanup acknowledged\n'));
|
|
1707
|
+
} else {
|
|
1708
|
+
console.log(chalk.yellow('⚠️ Proceeding without recommended cleanup\n'));
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
// Handle .bmad* folders with automatic backup
|
|
1713
|
+
if (bmadFolders.length > 0) {
|
|
1714
|
+
console.log(chalk.cyan('The following legacy folders will be moved to v4-backup:'));
|
|
1715
|
+
for (const p of bmadFolders) console.log(chalk.dim(` - ${p}`));
|
|
1716
|
+
|
|
1717
|
+
const { proceed } = await inquirer.prompt([
|
|
1718
|
+
{
|
|
1719
|
+
type: 'confirm',
|
|
1720
|
+
name: 'proceed',
|
|
1721
|
+
message: 'Proceed with backing up legacy v4 folders?',
|
|
1722
|
+
default: true,
|
|
1723
|
+
},
|
|
1724
|
+
]);
|
|
1725
|
+
|
|
1726
|
+
if (proceed) {
|
|
1727
|
+
const backupDir = path.join(projectDir, 'v4-backup');
|
|
1728
|
+
await fs.ensureDir(backupDir);
|
|
1729
|
+
|
|
1730
|
+
for (const folder of bmadFolders) {
|
|
1731
|
+
const folderName = path.basename(folder);
|
|
1732
|
+
const backupPath = path.join(backupDir, folderName);
|
|
1733
|
+
|
|
1734
|
+
// If backup already exists, add timestamp
|
|
1735
|
+
let finalBackupPath = backupPath;
|
|
1736
|
+
if (await fs.pathExists(backupPath)) {
|
|
1737
|
+
const timestamp = new Date().toISOString().replaceAll(/[:.]/g, '-').split('T')[0];
|
|
1738
|
+
finalBackupPath = path.join(backupDir, `${folderName}-${timestamp}`);
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
await fs.move(folder, finalBackupPath, { overwrite: false });
|
|
1742
|
+
console.log(chalk.green(`✓ Moved ${folderName} to ${path.relative(projectDir, finalBackupPath)}`));
|
|
1743
|
+
}
|
|
1744
|
+
} else {
|
|
1745
|
+
throw new Error('Installation cancelled by user');
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
/**
|
|
1751
|
+
* Read files-manifest.csv
|
|
1752
|
+
* @param {string} bmadDir - BMAD installation directory
|
|
1753
|
+
* @returns {Array} Array of file entries from files-manifest.csv
|
|
1754
|
+
*/
|
|
1755
|
+
async readFilesManifest(bmadDir) {
|
|
1756
|
+
const filesManifestPath = path.join(bmadDir, '_cfg', 'files-manifest.csv');
|
|
1757
|
+
if (!(await fs.pathExists(filesManifestPath))) {
|
|
1758
|
+
return [];
|
|
1759
|
+
}
|
|
1760
|
+
|
|
1761
|
+
try {
|
|
1762
|
+
const content = await fs.readFile(filesManifestPath, 'utf8');
|
|
1763
|
+
const lines = content.split('\n');
|
|
1764
|
+
const files = [];
|
|
1765
|
+
|
|
1766
|
+
for (let i = 1; i < lines.length; i++) {
|
|
1767
|
+
// Skip header
|
|
1768
|
+
const line = lines[i].trim();
|
|
1769
|
+
if (!line) continue;
|
|
1770
|
+
|
|
1771
|
+
// Parse CSV line properly handling quoted values
|
|
1772
|
+
const parts = [];
|
|
1773
|
+
let current = '';
|
|
1774
|
+
let inQuotes = false;
|
|
1775
|
+
|
|
1776
|
+
for (const char of line) {
|
|
1777
|
+
if (char === '"') {
|
|
1778
|
+
inQuotes = !inQuotes;
|
|
1779
|
+
} else if (char === ',' && !inQuotes) {
|
|
1780
|
+
parts.push(current);
|
|
1781
|
+
current = '';
|
|
1782
|
+
} else {
|
|
1783
|
+
current += char;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
parts.push(current); // Add last part
|
|
1787
|
+
|
|
1788
|
+
if (parts.length >= 4) {
|
|
1789
|
+
files.push({
|
|
1790
|
+
type: parts[0],
|
|
1791
|
+
name: parts[1],
|
|
1792
|
+
module: parts[2],
|
|
1793
|
+
path: parts[3],
|
|
1794
|
+
hash: parts[4] || null, // Hash may not exist in old manifests
|
|
1795
|
+
});
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
return files;
|
|
1800
|
+
} catch (error) {
|
|
1801
|
+
console.warn('Warning: Could not read files-manifest.csv:', error.message);
|
|
1802
|
+
return [];
|
|
1803
|
+
}
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
/**
|
|
1807
|
+
* Detect custom and modified files
|
|
1808
|
+
* @param {string} bmadDir - BMAD installation directory
|
|
1809
|
+
* @param {Array} existingFilesManifest - Previous files from files-manifest.csv
|
|
1810
|
+
* @returns {Object} Object with customFiles and modifiedFiles arrays
|
|
1811
|
+
*/
|
|
1812
|
+
async detectCustomFiles(bmadDir, existingFilesManifest) {
|
|
1813
|
+
const customFiles = [];
|
|
1814
|
+
const modifiedFiles = [];
|
|
1815
|
+
|
|
1816
|
+
// Check if the manifest has hashes - if not, we can't detect modifications
|
|
1817
|
+
let manifestHasHashes = false;
|
|
1818
|
+
if (existingFilesManifest && existingFilesManifest.length > 0) {
|
|
1819
|
+
manifestHasHashes = existingFilesManifest.some((f) => f.hash);
|
|
1820
|
+
}
|
|
846
1821
|
|
|
847
|
-
// Build
|
|
848
|
-
const
|
|
849
|
-
|
|
850
|
-
|
|
1822
|
+
// Build map of previously installed files from files-manifest.csv with their hashes
|
|
1823
|
+
const installedFilesMap = new Map();
|
|
1824
|
+
for (const fileEntry of existingFilesManifest) {
|
|
1825
|
+
if (fileEntry.path) {
|
|
1826
|
+
// Files in manifest are stored as relative paths starting with 'bmad/'
|
|
1827
|
+
// Convert to absolute path
|
|
1828
|
+
const relativePath = fileEntry.path.startsWith('bmad/') ? fileEntry.path.slice(5) : fileEntry.path;
|
|
1829
|
+
const absolutePath = path.join(bmadDir, relativePath);
|
|
1830
|
+
installedFilesMap.set(path.normalize(absolutePath), {
|
|
1831
|
+
hash: fileEntry.hash,
|
|
1832
|
+
relativePath: relativePath,
|
|
1833
|
+
});
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
// Recursively scan bmadDir for all files
|
|
1838
|
+
const scanDirectory = async (dir) => {
|
|
1839
|
+
try {
|
|
1840
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
1841
|
+
for (const entry of entries) {
|
|
1842
|
+
const fullPath = path.join(dir, entry.name);
|
|
1843
|
+
|
|
1844
|
+
if (entry.isDirectory()) {
|
|
1845
|
+
// Skip certain directories
|
|
1846
|
+
if (entry.name === 'node_modules' || entry.name === '.git') {
|
|
1847
|
+
continue;
|
|
1848
|
+
}
|
|
1849
|
+
await scanDirectory(fullPath);
|
|
1850
|
+
} else if (entry.isFile()) {
|
|
1851
|
+
const normalizedPath = path.normalize(fullPath);
|
|
1852
|
+
const fileInfo = installedFilesMap.get(normalizedPath);
|
|
851
1853
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
1854
|
+
// Skip certain system files that are auto-generated
|
|
1855
|
+
const relativePath = path.relative(bmadDir, fullPath);
|
|
1856
|
+
const fileName = path.basename(fullPath);
|
|
855
1857
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
${legacyV4.offenders.map((p) => ` rmdir /S /Q "${p}"`).join('\n')}`;
|
|
1858
|
+
// Skip _cfg directory - system files
|
|
1859
|
+
if (relativePath.startsWith('_cfg/') || relativePath.startsWith('_cfg\\')) {
|
|
1860
|
+
continue;
|
|
1861
|
+
}
|
|
861
1862
|
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
1863
|
+
// Skip config.yaml files - these are regenerated on each install/update
|
|
1864
|
+
// Users should use _cfg/agents/ override files instead
|
|
1865
|
+
if (fileName === 'config.yaml') {
|
|
1866
|
+
continue;
|
|
1867
|
+
}
|
|
865
1868
|
|
|
866
|
-
|
|
867
|
-
|
|
1869
|
+
if (!fileInfo) {
|
|
1870
|
+
// File not in manifest = custom file
|
|
1871
|
+
customFiles.push(fullPath);
|
|
1872
|
+
} else if (manifestHasHashes && fileInfo.hash) {
|
|
1873
|
+
// File in manifest with hash - check if it was modified
|
|
1874
|
+
const currentHash = await this.manifest.calculateFileHash(fullPath);
|
|
1875
|
+
if (currentHash && currentHash !== fileInfo.hash) {
|
|
1876
|
+
// Hash changed = file was modified
|
|
1877
|
+
modifiedFiles.push({
|
|
1878
|
+
path: fullPath,
|
|
1879
|
+
relativePath: fileInfo.relativePath,
|
|
1880
|
+
});
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
// If manifest doesn't have hashes, we can't detect modifications
|
|
1884
|
+
// so we just skip files that are in the manifest
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
} catch {
|
|
1888
|
+
// Ignore errors scanning directories
|
|
1889
|
+
}
|
|
1890
|
+
};
|
|
868
1891
|
|
|
869
|
-
|
|
1892
|
+
await scanDirectory(bmadDir);
|
|
1893
|
+
return { customFiles, modifiedFiles };
|
|
870
1894
|
}
|
|
871
1895
|
|
|
872
1896
|
/**
|
|
@@ -982,6 +2006,7 @@ Note: You may also want to remove other BMAD-related v4 files/folders left over
|
|
|
982
2006
|
configContent += processedTemplate;
|
|
983
2007
|
|
|
984
2008
|
await fs.writeFile(configPath, configContent, 'utf8');
|
|
2009
|
+
this.installedFiles.push(configPath); // Track agent config files
|
|
985
2010
|
createdCount++;
|
|
986
2011
|
}
|
|
987
2012
|
|
|
@@ -997,7 +2022,7 @@ Note: You may also want to remove other BMAD-related v4 files/folders left over
|
|
|
997
2022
|
* @param {Array} agentDetails - Array of agent details
|
|
998
2023
|
*/
|
|
999
2024
|
async generateAgentManifest(bmadDir, agentDetails) {
|
|
1000
|
-
const manifestPath = path.join(bmadDir, '_cfg', 'agent-
|
|
2025
|
+
const manifestPath = path.join(bmadDir, '_cfg', 'agent-manifest.csv');
|
|
1001
2026
|
await AgentPartyGenerator.writeAgentParty(manifestPath, agentDetails, { forWeb: false });
|
|
1002
2027
|
}
|
|
1003
2028
|
|