bmad-method 5.0.0 → 5.1.0
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/.github/FUNDING.yaml +15 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
- package/.github/workflows/discord.yaml +25 -0
- package/.github/workflows/format-check.yaml +42 -0
- package/.github/workflows/manual-release.yaml +173 -0
- package/.husky/pre-commit +3 -2
- package/.vscode/settings.json +67 -74
- package/CHANGELOG.md +564 -19
- package/CONTRIBUTING.md +168 -5
- package/LICENSE +1 -1
- package/README.md +146 -218
- package/bmad-core/agent-teams/team-all.yaml +14 -0
- package/bmad-core/agent-teams/team-fullstack.yaml +18 -0
- package/bmad-core/agent-teams/team-ide-minimal.yaml +10 -0
- package/bmad-core/agent-teams/team-no-ui.yaml +13 -0
- package/bmad-core/agents/analyst.md +81 -0
- package/bmad-core/agents/architect.md +83 -0
- package/bmad-core/agents/bmad-master.md +107 -0
- package/bmad-core/agents/bmad-orchestrator.md +149 -0
- package/bmad-core/agents/dev.md +75 -0
- package/bmad-core/agents/pm.md +81 -0
- package/bmad-core/agents/po.md +76 -0
- package/bmad-core/agents/qa.md +88 -0
- package/bmad-core/agents/sm.md +62 -0
- package/bmad-core/agents/ux-expert.md +66 -0
- package/{.bmad-core → bmad-core}/checklists/architect-checklist.md +0 -5
- package/{.bmad-core → bmad-core}/checklists/change-checklist.md +2 -2
- package/{.bmad-core → bmad-core}/checklists/pm-checklist.md +0 -5
- package/{.bmad-core → bmad-core}/checklists/po-master-checklist.md +0 -9
- package/{.bmad-core → bmad-core}/checklists/story-dod-checklist.md +0 -7
- package/{.bmad-core → bmad-core}/checklists/story-draft-checklist.md +1 -4
- package/bmad-core/core-config.yaml +20 -0
- package/bmad-core/data/bmad-kb.md +806 -0
- package/bmad-core/data/brainstorming-techniques.md +36 -0
- package/bmad-core/data/elicitation-methods.md +154 -0
- package/bmad-core/data/test-levels-framework.md +146 -0
- package/bmad-core/data/test-priorities-matrix.md +172 -0
- package/bmad-core/tasks/advanced-elicitation.md +117 -0
- package/{.bmad-core → bmad-core}/tasks/correct-course.md +9 -12
- package/bmad-core/tasks/create-brownfield-story.md +312 -0
- package/{.bmad-core → bmad-core}/tasks/create-deep-research-prompt.md +4 -27
- package/bmad-core/tasks/create-next-story.md +112 -0
- package/bmad-core/tasks/document-project.md +343 -0
- package/bmad-core/tasks/facilitate-brainstorming-session.md +136 -0
- package/bmad-core/tasks/generate-ai-frontend-prompt.md +51 -0
- package/{.bmad-core → bmad-core}/tasks/index-docs.md +3 -13
- package/bmad-core/tasks/kb-mode-interaction.md +75 -0
- package/bmad-core/tasks/nfr-assess.md +343 -0
- package/bmad-core/tasks/qa-gate.md +159 -0
- package/bmad-core/tasks/review-story.md +314 -0
- package/bmad-core/tasks/risk-profile.md +353 -0
- package/{.bmad-core → bmad-core}/tasks/shard-doc.md +27 -15
- package/bmad-core/tasks/test-design.md +174 -0
- package/bmad-core/tasks/trace-requirements.md +264 -0
- package/bmad-core/tasks/validate-next-story.md +134 -0
- package/bmad-core/templates/architecture-tmpl.yaml +650 -0
- package/bmad-core/templates/brainstorming-output-tmpl.yaml +156 -0
- package/bmad-core/templates/brownfield-architecture-tmpl.yaml +476 -0
- package/bmad-core/templates/brownfield-prd-tmpl.yaml +280 -0
- package/bmad-core/templates/competitor-analysis-tmpl.yaml +306 -0
- package/bmad-core/templates/front-end-architecture-tmpl.yaml +218 -0
- package/bmad-core/templates/front-end-spec-tmpl.yaml +349 -0
- package/bmad-core/templates/fullstack-architecture-tmpl.yaml +823 -0
- package/bmad-core/templates/market-research-tmpl.yaml +252 -0
- package/bmad-core/templates/prd-tmpl.yaml +202 -0
- package/bmad-core/templates/project-brief-tmpl.yaml +221 -0
- package/bmad-core/templates/qa-gate-tmpl.yaml +102 -0
- package/bmad-core/templates/story-tmpl.yaml +137 -0
- package/bmad-core/workflows/brownfield-fullstack.yaml +297 -0
- package/bmad-core/workflows/brownfield-service.yaml +187 -0
- package/bmad-core/workflows/brownfield-ui.yaml +197 -0
- package/{.bmad-core/workflows/greenfield-fullstack.yml → bmad-core/workflows/greenfield-fullstack.yaml} +140 -77
- package/bmad-core/workflows/greenfield-service.yaml +206 -0
- package/bmad-core/workflows/greenfield-ui.yaml +235 -0
- package/common/tasks/create-doc.md +101 -0
- package/{.bmad-core → common}/tasks/execute-checklist.md +2 -13
- package/common/utils/bmad-doc-template.md +325 -0
- package/common/utils/workflow-management.md +69 -0
- package/dist/agents/analyst.txt +2889 -0
- package/dist/agents/architect.txt +3552 -0
- package/dist/agents/bmad-master.txt +8769 -0
- package/dist/agents/bmad-orchestrator.txt +1513 -0
- package/dist/agents/dev.txt +414 -0
- package/{.bmad-core/web-bundles → dist}/agents/pm.txt +668 -1119
- package/{.bmad-core/web-bundles → dist}/agents/po.txt +341 -484
- package/dist/agents/qa.txt +1987 -0
- package/dist/agents/sm.txt +658 -0
- package/dist/agents/ux-expert.txt +694 -0
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +2371 -0
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +1620 -0
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +815 -0
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +10952 -0
- package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.txt +4012 -0
- package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.txt +3698 -0
- package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.txt +450 -0
- package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.txt +973 -0
- package/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +15376 -0
- package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +2075 -0
- package/dist/teams/team-all.txt +12682 -0
- package/dist/teams/team-fullstack.txt +10421 -0
- package/dist/teams/team-ide-minimal.txt +5103 -0
- package/dist/teams/team-no-ui.txt +8980 -0
- package/docs/GUIDING-PRINCIPLES.md +91 -0
- package/docs/core-architecture.md +219 -0
- package/docs/enhanced-ide-development-workflow.md +248 -0
- package/docs/expansion-packs.md +280 -0
- package/docs/how-to-contribute-with-pull-requests.md +158 -0
- package/docs/user-guide.md +504 -0
- package/docs/versioning-and-releases.md +8 -16
- package/docs/versions.md +4 -5
- package/docs/working-in-the-brownfield.md +597 -0
- package/eslint.config.mjs +119 -0
- package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/Complete AI Agent System - Flowchart.svg +102 -0
- package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.1 Google Cloud Project Setup/1.1.1 - Initial Project Configuration - bash copy.txt +13 -0
- package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.1 Google Cloud Project Setup/1.1.1 - Initial Project Configuration - bash.txt +13 -0
- package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.2 Agent Development Kit Installation/1.2.2 - Basic Project Structure - txt.txt +25 -0
- package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.3 Core Configuration Files/1.3.1 - settings.py +34 -0
- package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.3 Core Configuration Files/1.3.2 - main.py - Base Application.py +70 -0
- package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.4 Deployment Configuration/1.4.2 - cloudbuild.yaml +26 -0
- package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/README.md +109 -0
- package/expansion-packs/README.md +2 -112
- package/expansion-packs/bmad-2d-phaser-game-dev/agent-teams/phaser-2d-nodejs-game-team.yaml +13 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.md +71 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +78 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +64 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-design-checklist.md +201 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-story-dod-checklist.md +160 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/config.yaml +8 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/data/bmad-kb.md +250 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +647 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/tasks/advanced-elicitation.md +110 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/tasks/create-game-story.md +216 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/tasks/game-design-brainstorming.md +290 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +613 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +356 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +343 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +253 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +484 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +183 -0
- package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +175 -0
- package/expansion-packs/bmad-2d-unity-game-dev/agent-teams/unity-2d-game-team.yaml +14 -0
- package/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.md +80 -0
- package/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.md +77 -0
- package/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.md +78 -0
- package/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.md +65 -0
- package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-architect-checklist.md +391 -0
- package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-change-checklist.md +203 -0
- package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-design-checklist.md +201 -0
- package/expansion-packs/bmad-2d-unity-game-dev/checklists/game-story-dod-checklist.md +124 -0
- package/expansion-packs/bmad-2d-unity-game-dev/config.yaml +6 -0
- package/expansion-packs/bmad-2d-unity-game-dev/data/bmad-kb.md +769 -0
- package/expansion-packs/bmad-2d-unity-game-dev/data/development-guidelines.md +586 -0
- package/expansion-packs/bmad-2d-unity-game-dev/tasks/advanced-elicitation.md +110 -0
- package/expansion-packs/bmad-2d-unity-game-dev/tasks/correct-course-game.md +141 -0
- package/expansion-packs/bmad-2d-unity-game-dev/tasks/create-game-story.md +184 -0
- package/expansion-packs/bmad-2d-unity-game-dev/tasks/game-design-brainstorming.md +290 -0
- package/expansion-packs/bmad-2d-unity-game-dev/tasks/validate-game-story.md +200 -0
- package/expansion-packs/bmad-2d-unity-game-dev/templates/game-architecture-tmpl.yaml +1030 -0
- package/expansion-packs/bmad-2d-unity-game-dev/templates/game-brief-tmpl.yaml +356 -0
- package/expansion-packs/bmad-2d-unity-game-dev/templates/game-design-doc-tmpl.yaml +705 -0
- package/expansion-packs/bmad-2d-unity-game-dev/templates/game-story-tmpl.yaml +256 -0
- package/expansion-packs/bmad-2d-unity-game-dev/templates/level-design-doc-tmpl.yaml +484 -0
- package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-dev-greenfield.yaml +183 -0
- package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-prototype.yaml +175 -0
- package/expansion-packs/{infrastructure-devops → bmad-infrastructure-devops}/README.md +9 -9
- package/expansion-packs/{infrastructure-devops → bmad-infrastructure-devops}/agents/infra-devops-platform.md +30 -18
- package/expansion-packs/{infrastructure-devops → bmad-infrastructure-devops}/checklists/infrastructure-checklist.md +1 -1
- package/expansion-packs/bmad-infrastructure-devops/config.yaml +9 -0
- package/expansion-packs/bmad-infrastructure-devops/data/bmad-kb.md +305 -0
- package/expansion-packs/{infrastructure-devops → bmad-infrastructure-devops}/tasks/review-infrastructure.md +4 -5
- package/expansion-packs/{infrastructure-devops → bmad-infrastructure-devops}/tasks/validate-infrastructure.md +4 -5
- package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +424 -0
- package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +629 -0
- package/package.json +74 -42
- package/prettier.config.mjs +32 -0
- package/release_notes.md +25 -0
- package/tools/bmad-npx-wrapper.js +13 -15
- package/tools/builders/web-builder.js +544 -15
- package/tools/bump-all-versions.js +115 -0
- package/tools/bump-expansion-version.js +90 -0
- package/tools/cli.js +65 -32
- package/tools/flattener/aggregate.js +76 -0
- package/tools/flattener/binary.js +80 -0
- package/tools/flattener/discovery.js +71 -0
- package/tools/flattener/files.js +35 -0
- package/tools/flattener/ignoreRules.js +176 -0
- package/tools/flattener/main.js +573 -0
- package/tools/flattener/projectRoot.js +206 -0
- package/tools/flattener/prompts.js +44 -0
- package/tools/flattener/stats.helpers.js +395 -0
- package/tools/flattener/stats.js +80 -0
- package/tools/flattener/test-matrix.js +413 -0
- package/tools/flattener/xml.js +88 -0
- package/tools/installer/README.md +3 -53
- package/tools/installer/bin/bmad.js +475 -90
- package/tools/installer/config/ide-agent-config.yaml +58 -0
- package/tools/installer/config/install.config.yaml +123 -0
- package/tools/installer/lib/config-loader.js +208 -40
- package/tools/installer/lib/file-manager.js +258 -55
- package/tools/installer/lib/ide-base-setup.js +228 -0
- package/tools/installer/lib/ide-setup.js +1265 -253
- package/tools/installer/lib/installer.js +1651 -310
- package/tools/installer/lib/memory-profiler.js +225 -0
- package/tools/installer/lib/module-manager.js +114 -0
- package/tools/installer/lib/resource-locator.js +308 -0
- package/tools/installer/package.json +25 -24
- package/tools/lib/dependency-resolver.js +44 -48
- package/tools/lib/yaml-utils.js +29 -0
- package/tools/md-assets/web-agent-startup-instructions.md +39 -0
- package/tools/preview-release-notes.js +66 -0
- package/tools/shared/bannerArt.js +105 -0
- package/tools/sync-installer-version.js +7 -9
- package/tools/update-expansion-version.js +53 -0
- package/tools/upgraders/v3-to-v4-upgrader.js +221 -320
- package/tools/version-bump.js +42 -27
- package/tools/yaml-format.js +57 -44
- package/.bmad-core/agent-teams/team-all.yml +0 -16
- package/.bmad-core/agent-teams/team-fullstack.yml +0 -26
- package/.bmad-core/agent-teams/team-no-ui.yml +0 -15
- package/.bmad-core/agents/analyst.md +0 -59
- package/.bmad-core/agents/architect.md +0 -66
- package/.bmad-core/agents/bmad-master.md +0 -104
- package/.bmad-core/agents/bmad-orchestrator.md +0 -81
- package/.bmad-core/agents/dev.md +0 -70
- package/.bmad-core/agents/pm.md +0 -59
- package/.bmad-core/agents/po.md +0 -60
- package/.bmad-core/agents/qa.md +0 -52
- package/.bmad-core/agents/sm.md +0 -55
- package/.bmad-core/agents/ux-expert.md +0 -66
- package/.bmad-core/data/bmad-kb.md +0 -47
- package/.bmad-core/schemas/agent-team-schema.yml +0 -153
- package/.bmad-core/tasks/advanced-elicitation.md +0 -92
- package/.bmad-core/tasks/brainstorming-techniques.md +0 -238
- package/.bmad-core/tasks/core-dump.md +0 -74
- package/.bmad-core/tasks/create-agent.md +0 -202
- package/.bmad-core/tasks/create-doc.md +0 -74
- package/.bmad-core/tasks/create-expansion-pack.md +0 -425
- package/.bmad-core/tasks/create-next-story.md +0 -206
- package/.bmad-core/tasks/create-team.md +0 -229
- package/.bmad-core/tasks/doc-migration-task.md +0 -143
- package/.bmad-core/tasks/generate-ai-frontend-prompt.md +0 -58
- package/.bmad-core/templates/agent-tmpl.md +0 -58
- package/.bmad-core/templates/architecture-tmpl.md +0 -771
- package/.bmad-core/templates/brownfield-architecture-tmpl.md +0 -542
- package/.bmad-core/templates/brownfield-prd-tmpl.md +0 -240
- package/.bmad-core/templates/competitor-analysis-tmpl.md +0 -289
- package/.bmad-core/templates/expansion-pack-plan-tmpl.md +0 -91
- package/.bmad-core/templates/front-end-architecture-tmpl.md +0 -173
- package/.bmad-core/templates/front-end-spec-tmpl.md +0 -411
- package/.bmad-core/templates/fullstack-architecture-tmpl.md +0 -1016
- package/.bmad-core/templates/market-research-tmpl.md +0 -261
- package/.bmad-core/templates/prd-tmpl.md +0 -200
- package/.bmad-core/templates/project-brief-tmpl.md +0 -228
- package/.bmad-core/templates/simple-project-prd-tmpl.md +0 -461
- package/.bmad-core/templates/story-tmpl.md +0 -61
- package/.bmad-core/templates/web-agent-startup-instructions-template.md +0 -39
- package/.bmad-core/utils/agent-switcher.ide.md +0 -112
- package/.bmad-core/utils/template-format.md +0 -26
- package/.bmad-core/utils/workflow-management.md +0 -224
- package/.bmad-core/web-bundles/agents/analyst.txt +0 -1684
- package/.bmad-core/web-bundles/agents/architect.txt +0 -3584
- package/.bmad-core/web-bundles/agents/bmad-master.txt +0 -9491
- package/.bmad-core/web-bundles/agents/bmad-orchestrator.txt +0 -1466
- package/.bmad-core/web-bundles/agents/dev.txt +0 -316
- package/.bmad-core/web-bundles/agents/qa.txt +0 -129
- package/.bmad-core/web-bundles/agents/sm.txt +0 -658
- package/.bmad-core/web-bundles/agents/ux-expert.txt +0 -1099
- package/.bmad-core/web-bundles/teams/team-all.txt +0 -10757
- package/.bmad-core/web-bundles/teams/team-fullstack.txt +0 -10109
- package/.bmad-core/web-bundles/teams/team-no-ui.txt +0 -8950
- package/.bmad-core/workflows/brownfield-fullstack.yml +0 -116
- package/.bmad-core/workflows/brownfield-service.yml +0 -117
- package/.bmad-core/workflows/brownfield-ui.yml +0 -127
- package/.bmad-core/workflows/greenfield-service.yml +0 -143
- package/.bmad-core/workflows/greenfield-ui.yml +0 -172
- package/.claude/commands/analyst.md +0 -63
- package/.claude/commands/architect.md +0 -70
- package/.claude/commands/bmad-master.md +0 -108
- package/.claude/commands/bmad-orchestrator.md +0 -85
- package/.claude/commands/dev.md +0 -74
- package/.claude/commands/pm.md +0 -63
- package/.claude/commands/po.md +0 -64
- package/.claude/commands/qa.md +0 -56
- package/.claude/commands/sm.md +0 -59
- package/.claude/commands/ux-expert.md +0 -70
- package/.cursor/rules/analyst.mdc +0 -77
- package/.cursor/rules/architect.mdc +0 -84
- package/.cursor/rules/bmad-master.mdc +0 -122
- package/.cursor/rules/bmad-orchestrator.mdc +0 -99
- package/.cursor/rules/dev.mdc +0 -88
- package/.cursor/rules/pm.mdc +0 -77
- package/.cursor/rules/po.mdc +0 -78
- package/.cursor/rules/qa.mdc +0 -70
- package/.cursor/rules/sm.mdc +0 -73
- package/.cursor/rules/ux-expert.mdc +0 -84
- package/.github/workflows/release.yml +0 -59
- package/.releaserc.json +0 -18
- package/.roo/.roomodes +0 -95
- package/.roo/README.md +0 -38
- package/.vscode/extensions.json +0 -6
- package/.windsurf/rules/analyst.md +0 -71
- package/.windsurf/rules/architect.md +0 -78
- package/.windsurf/rules/bmad-master.md +0 -116
- package/.windsurf/rules/bmad-orchestrator.md +0 -93
- package/.windsurf/rules/dev.md +0 -82
- package/.windsurf/rules/pm.md +0 -71
- package/.windsurf/rules/po.md +0 -72
- package/.windsurf/rules/qa.md +0 -64
- package/.windsurf/rules/sm.md +0 -67
- package/.windsurf/rules/ux-expert.md +0 -78
- package/docs/bmad-workflow-guide.md +0 -161
- package/docs/claude-code-guide.md +0 -119
- package/docs/cursor-guide.md +0 -127
- package/docs/roo-code-guide.md +0 -140
- package/docs/sample-output/simple-fullstack-greenfield/prd.md +0 -42
- package/docs/windsurf-guide.md +0 -127
- package/expansion-packs/infrastructure-devops/manifest.yml +0 -38
- package/expansion-packs/infrastructure-devops/templates/infrastructure-architecture-tmpl.md +0 -415
- package/expansion-packs/infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.md +0 -0
- package/tools/installer/config/install.config.yml +0 -139
- package/tools/installer/package-lock.json +0 -906
- package/tools/installer/templates/claude-commands.md +0 -7
- package/tools/installer/templates/cursor-rules.md +0 -22
- package/tools/installer/templates/windsurf-rules.md +0 -22
- package/tools/semantic-release-sync-installer.js +0 -31
- /package/{.bmad-core → bmad-core}/data/technical-preferences.md +0 -0
- /package/{.bmad-core → bmad-core}/tasks/brownfield-create-epic.md +0 -0
- /package/{.bmad-core → bmad-core}/tasks/brownfield-create-story.md +0 -0
|
@@ -1,31 +1,26 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const path = require(
|
|
3
|
-
const crypto = require(
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// Initialize ES modules
|
|
10
|
-
async function initializeModules() {
|
|
11
|
-
if (!chalk) {
|
|
12
|
-
chalk = (await import("chalk")).default;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
1
|
+
const fs = require('fs-extra');
|
|
2
|
+
const path = require('node:path');
|
|
3
|
+
const crypto = require('node:crypto');
|
|
4
|
+
const yaml = require('js-yaml');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const { createReadStream, createWriteStream, promises: fsPromises } = require('node:fs');
|
|
7
|
+
const { pipeline } = require('node:stream/promises');
|
|
8
|
+
const resourceLocator = require('./resource-locator');
|
|
15
9
|
|
|
16
10
|
class FileManager {
|
|
17
|
-
constructor() {
|
|
18
|
-
this.manifestDir = ".bmad-core";
|
|
19
|
-
this.manifestFile = "install-manifest.yml";
|
|
20
|
-
}
|
|
11
|
+
constructor() {}
|
|
21
12
|
|
|
22
13
|
async copyFile(source, destination) {
|
|
23
14
|
try {
|
|
24
15
|
await fs.ensureDir(path.dirname(destination));
|
|
25
|
-
|
|
16
|
+
|
|
17
|
+
// Use streaming for large files (> 10MB)
|
|
18
|
+
const stats = await fs.stat(source);
|
|
19
|
+
await (stats.size > 10 * 1024 * 1024
|
|
20
|
+
? pipeline(createReadStream(source), createWriteStream(destination))
|
|
21
|
+
: fs.copy(source, destination));
|
|
26
22
|
return true;
|
|
27
23
|
} catch (error) {
|
|
28
|
-
await initializeModules();
|
|
29
24
|
console.error(chalk.red(`Failed to copy ${source}:`), error.message);
|
|
30
25
|
return false;
|
|
31
26
|
}
|
|
@@ -34,27 +29,46 @@ class FileManager {
|
|
|
34
29
|
async copyDirectory(source, destination) {
|
|
35
30
|
try {
|
|
36
31
|
await fs.ensureDir(destination);
|
|
37
|
-
|
|
32
|
+
|
|
33
|
+
// Use streaming copy for large directories
|
|
34
|
+
const files = await resourceLocator.findFiles('**/*', {
|
|
35
|
+
cwd: source,
|
|
36
|
+
nodir: true,
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Process files in batches to avoid memory issues
|
|
40
|
+
const batchSize = 50;
|
|
41
|
+
for (let index = 0; index < files.length; index += batchSize) {
|
|
42
|
+
const batch = files.slice(index, index + batchSize);
|
|
43
|
+
await Promise.all(
|
|
44
|
+
batch.map((file) => this.copyFile(path.join(source, file), path.join(destination, file))),
|
|
45
|
+
);
|
|
46
|
+
}
|
|
38
47
|
return true;
|
|
39
48
|
} catch (error) {
|
|
40
|
-
|
|
41
|
-
console.error(
|
|
42
|
-
chalk.red(`Failed to copy directory ${source}:`),
|
|
43
|
-
error.message
|
|
44
|
-
);
|
|
49
|
+
console.error(chalk.red(`Failed to copy directory ${source}:`), error.message);
|
|
45
50
|
return false;
|
|
46
51
|
}
|
|
47
52
|
}
|
|
48
53
|
|
|
49
|
-
async copyGlobPattern(pattern, sourceDir, destDir) {
|
|
50
|
-
const files =
|
|
54
|
+
async copyGlobPattern(pattern, sourceDir, destDir, rootValue = null) {
|
|
55
|
+
const files = await resourceLocator.findFiles(pattern, { cwd: sourceDir });
|
|
51
56
|
const copied = [];
|
|
52
57
|
|
|
53
58
|
for (const file of files) {
|
|
54
59
|
const sourcePath = path.join(sourceDir, file);
|
|
55
|
-
const
|
|
60
|
+
const destinationPath = path.join(destDir, file);
|
|
61
|
+
|
|
62
|
+
// Use root replacement if rootValue is provided and file needs it
|
|
63
|
+
const needsRootReplacement =
|
|
64
|
+
rootValue && (file.endsWith('.md') || file.endsWith('.yaml') || file.endsWith('.yml'));
|
|
65
|
+
|
|
66
|
+
let success = false;
|
|
67
|
+
success = await (needsRootReplacement
|
|
68
|
+
? this.copyFileWithRootReplacement(sourcePath, destinationPath, rootValue)
|
|
69
|
+
: this.copyFile(sourcePath, destinationPath));
|
|
56
70
|
|
|
57
|
-
if (
|
|
71
|
+
if (success) {
|
|
58
72
|
copied.push(file);
|
|
59
73
|
}
|
|
60
74
|
}
|
|
@@ -64,31 +78,40 @@ class FileManager {
|
|
|
64
78
|
|
|
65
79
|
async calculateFileHash(filePath) {
|
|
66
80
|
try {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
.
|
|
73
|
-
|
|
81
|
+
// Use streaming for hash calculation to reduce memory usage
|
|
82
|
+
const stream = createReadStream(filePath);
|
|
83
|
+
const hash = crypto.createHash('sha256');
|
|
84
|
+
|
|
85
|
+
for await (const chunk of stream) {
|
|
86
|
+
hash.update(chunk);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return hash.digest('hex').slice(0, 16);
|
|
90
|
+
} catch {
|
|
74
91
|
return null;
|
|
75
92
|
}
|
|
76
93
|
}
|
|
77
94
|
|
|
78
95
|
async createManifest(installDir, config, files) {
|
|
79
|
-
const manifestPath = path.join(
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
96
|
+
const manifestPath = path.join(installDir, this.manifestDir, this.manifestFile);
|
|
97
|
+
|
|
98
|
+
// Read version from package.json
|
|
99
|
+
let coreVersion = 'unknown';
|
|
100
|
+
try {
|
|
101
|
+
const packagePath = path.join(__dirname, '..', '..', '..', 'package.json');
|
|
102
|
+
const packageJson = require(packagePath);
|
|
103
|
+
coreVersion = packageJson.version;
|
|
104
|
+
} catch {
|
|
105
|
+
console.warn("Could not read version from package.json, using 'unknown'");
|
|
106
|
+
}
|
|
84
107
|
|
|
85
108
|
const manifest = {
|
|
86
|
-
version:
|
|
109
|
+
version: coreVersion,
|
|
87
110
|
installed_at: new Date().toISOString(),
|
|
88
111
|
install_type: config.installType,
|
|
89
112
|
agent: config.agent || null,
|
|
90
|
-
ide_setup: config.ide || null,
|
|
91
113
|
ides_setup: config.ides || [],
|
|
114
|
+
expansion_packs: config.expansionPacks || [],
|
|
92
115
|
files: [],
|
|
93
116
|
};
|
|
94
117
|
|
|
@@ -106,22 +129,29 @@ class FileManager {
|
|
|
106
129
|
|
|
107
130
|
// Write manifest
|
|
108
131
|
await fs.ensureDir(path.dirname(manifestPath));
|
|
109
|
-
await fs.writeFile(manifestPath,
|
|
132
|
+
await fs.writeFile(manifestPath, yaml.dump(manifest, { indent: 2 }));
|
|
110
133
|
|
|
111
134
|
return manifest;
|
|
112
135
|
}
|
|
113
136
|
|
|
114
137
|
async readManifest(installDir) {
|
|
115
|
-
const manifestPath = path.join(
|
|
116
|
-
installDir,
|
|
117
|
-
this.manifestDir,
|
|
118
|
-
this.manifestFile
|
|
119
|
-
);
|
|
138
|
+
const manifestPath = path.join(installDir, this.manifestDir, this.manifestFile);
|
|
120
139
|
|
|
121
140
|
try {
|
|
122
|
-
const content = await fs.readFile(manifestPath,
|
|
123
|
-
return
|
|
124
|
-
} catch
|
|
141
|
+
const content = await fs.readFile(manifestPath, 'utf8');
|
|
142
|
+
return yaml.load(content);
|
|
143
|
+
} catch {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async readExpansionPackManifest(installDir, packId) {
|
|
149
|
+
const manifestPath = path.join(installDir, `.${packId}`, this.manifestFile);
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
const content = await fs.readFile(manifestPath, 'utf8');
|
|
153
|
+
return yaml.load(content);
|
|
154
|
+
} catch {
|
|
125
155
|
return null;
|
|
126
156
|
}
|
|
127
157
|
}
|
|
@@ -141,8 +171,35 @@ class FileManager {
|
|
|
141
171
|
return modified;
|
|
142
172
|
}
|
|
143
173
|
|
|
174
|
+
async checkFileIntegrity(installDir, manifest) {
|
|
175
|
+
const result = {
|
|
176
|
+
missing: [],
|
|
177
|
+
modified: [],
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
for (const file of manifest.files) {
|
|
181
|
+
const filePath = path.join(installDir, file.path);
|
|
182
|
+
|
|
183
|
+
// Skip checking the manifest file itself - it will always be different due to timestamps
|
|
184
|
+
if (file.path.endsWith('install-manifest.yaml')) {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (await this.pathExists(filePath)) {
|
|
189
|
+
const currentHash = await this.calculateFileHash(filePath);
|
|
190
|
+
if (currentHash && currentHash !== file.hash) {
|
|
191
|
+
result.modified.push(file.path);
|
|
192
|
+
}
|
|
193
|
+
} else {
|
|
194
|
+
result.missing.push(file.path);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return result;
|
|
199
|
+
}
|
|
200
|
+
|
|
144
201
|
async backupFile(filePath) {
|
|
145
|
-
const backupPath = filePath +
|
|
202
|
+
const backupPath = filePath + '.bak';
|
|
146
203
|
let counter = 1;
|
|
147
204
|
let finalBackupPath = backupPath;
|
|
148
205
|
|
|
@@ -170,7 +227,7 @@ class FileManager {
|
|
|
170
227
|
}
|
|
171
228
|
|
|
172
229
|
async readFile(filePath) {
|
|
173
|
-
return fs.readFile(filePath,
|
|
230
|
+
return fs.readFile(filePath, 'utf8');
|
|
174
231
|
}
|
|
175
232
|
|
|
176
233
|
async writeFile(filePath, content) {
|
|
@@ -181,6 +238,152 @@ class FileManager {
|
|
|
181
238
|
async removeDirectory(dirPath) {
|
|
182
239
|
await fs.remove(dirPath);
|
|
183
240
|
}
|
|
241
|
+
|
|
242
|
+
async createExpansionPackManifest(installDir, packId, config, files) {
|
|
243
|
+
const manifestPath = path.join(installDir, `.${packId}`, this.manifestFile);
|
|
244
|
+
|
|
245
|
+
const manifest = {
|
|
246
|
+
version: config.expansionPackVersion || require('../../../package.json').version,
|
|
247
|
+
installed_at: new Date().toISOString(),
|
|
248
|
+
install_type: config.installType,
|
|
249
|
+
expansion_pack_id: config.expansionPackId,
|
|
250
|
+
expansion_pack_name: config.expansionPackName,
|
|
251
|
+
ides_setup: config.ides || [],
|
|
252
|
+
files: [],
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
// Add file information
|
|
256
|
+
for (const file of files) {
|
|
257
|
+
const filePath = path.join(installDir, file);
|
|
258
|
+
const hash = await this.calculateFileHash(filePath);
|
|
259
|
+
|
|
260
|
+
manifest.files.push({
|
|
261
|
+
path: file,
|
|
262
|
+
hash: hash,
|
|
263
|
+
modified: false,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Write manifest
|
|
268
|
+
await fs.ensureDir(path.dirname(manifestPath));
|
|
269
|
+
await fs.writeFile(manifestPath, yaml.dump(manifest, { indent: 2 }));
|
|
270
|
+
|
|
271
|
+
return manifest;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async modifyCoreConfig(installDir, config) {
|
|
275
|
+
const coreConfigPath = path.join(installDir, '.bmad-core', 'core-config.yaml');
|
|
276
|
+
|
|
277
|
+
try {
|
|
278
|
+
// Read the existing core-config.yaml
|
|
279
|
+
const coreConfigContent = await fs.readFile(coreConfigPath, 'utf8');
|
|
280
|
+
const coreConfig = yaml.load(coreConfigContent);
|
|
281
|
+
|
|
282
|
+
// Modify sharding settings if provided
|
|
283
|
+
if (config.prdSharded !== undefined) {
|
|
284
|
+
coreConfig.prd.prdSharded = config.prdSharded;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
if (config.architectureSharded !== undefined) {
|
|
288
|
+
coreConfig.architecture.architectureSharded = config.architectureSharded;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// Write back the modified config
|
|
292
|
+
await fs.writeFile(coreConfigPath, yaml.dump(coreConfig, { indent: 2 }));
|
|
293
|
+
|
|
294
|
+
return true;
|
|
295
|
+
} catch (error) {
|
|
296
|
+
console.error(chalk.red(`Failed to modify core-config.yaml:`), error.message);
|
|
297
|
+
return false;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
async copyFileWithRootReplacement(source, destination, rootValue) {
|
|
302
|
+
try {
|
|
303
|
+
// Check file size to determine if we should stream
|
|
304
|
+
const stats = await fs.stat(source);
|
|
305
|
+
|
|
306
|
+
if (stats.size > 5 * 1024 * 1024) {
|
|
307
|
+
// 5MB threshold
|
|
308
|
+
// Use streaming for large files
|
|
309
|
+
const { Transform } = require('node:stream');
|
|
310
|
+
const replaceStream = new Transform({
|
|
311
|
+
transform(chunk, encoding, callback) {
|
|
312
|
+
const modified = chunk.toString().replaceAll('{root}', rootValue);
|
|
313
|
+
callback(null, modified);
|
|
314
|
+
},
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
await this.ensureDirectory(path.dirname(destination));
|
|
318
|
+
await pipeline(
|
|
319
|
+
createReadStream(source, { encoding: 'utf8' }),
|
|
320
|
+
replaceStream,
|
|
321
|
+
createWriteStream(destination, { encoding: 'utf8' }),
|
|
322
|
+
);
|
|
323
|
+
} else {
|
|
324
|
+
// Regular approach for smaller files
|
|
325
|
+
const content = await fsPromises.readFile(source, 'utf8');
|
|
326
|
+
const updatedContent = content.replaceAll('{root}', rootValue);
|
|
327
|
+
await this.ensureDirectory(path.dirname(destination));
|
|
328
|
+
await fsPromises.writeFile(destination, updatedContent, 'utf8');
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return true;
|
|
332
|
+
} catch (error) {
|
|
333
|
+
console.error(chalk.red(`Failed to copy ${source} with root replacement:`), error.message);
|
|
334
|
+
return false;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async copyDirectoryWithRootReplacement(
|
|
339
|
+
source,
|
|
340
|
+
destination,
|
|
341
|
+
rootValue,
|
|
342
|
+
fileExtensions = ['.md', '.yaml', '.yml'],
|
|
343
|
+
) {
|
|
344
|
+
try {
|
|
345
|
+
await this.ensureDirectory(destination);
|
|
346
|
+
|
|
347
|
+
// Get all files in source directory
|
|
348
|
+
const files = await resourceLocator.findFiles('**/*', {
|
|
349
|
+
cwd: source,
|
|
350
|
+
nodir: true,
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
let replacedCount = 0;
|
|
354
|
+
|
|
355
|
+
for (const file of files) {
|
|
356
|
+
const sourcePath = path.join(source, file);
|
|
357
|
+
const destinationPath = path.join(destination, file);
|
|
358
|
+
|
|
359
|
+
// Check if this file type should have {root} replacement
|
|
360
|
+
const shouldReplace = fileExtensions.some((extension) => file.endsWith(extension));
|
|
361
|
+
|
|
362
|
+
if (shouldReplace) {
|
|
363
|
+
if (await this.copyFileWithRootReplacement(sourcePath, destinationPath, rootValue)) {
|
|
364
|
+
replacedCount++;
|
|
365
|
+
}
|
|
366
|
+
} else {
|
|
367
|
+
// Regular copy for files that don't need replacement
|
|
368
|
+
await this.copyFile(sourcePath, destinationPath);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (replacedCount > 0) {
|
|
373
|
+
console.log(chalk.dim(` Processed ${replacedCount} files with {root} replacement`));
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return true;
|
|
377
|
+
} catch (error) {
|
|
378
|
+
console.error(
|
|
379
|
+
chalk.red(`Failed to copy directory ${source} with root replacement:`),
|
|
380
|
+
error.message,
|
|
381
|
+
);
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
manifestDir = '.bmad-core';
|
|
386
|
+
manifestFile = 'install-manifest.yaml';
|
|
184
387
|
}
|
|
185
388
|
|
|
186
389
|
module.exports = new FileManager();
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base IDE Setup - Common functionality for all IDE setups
|
|
3
|
+
* Reduces duplication and provides shared methods
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const path = require('node:path');
|
|
7
|
+
const fs = require('fs-extra');
|
|
8
|
+
const yaml = require('js-yaml');
|
|
9
|
+
const chalk = require('chalk').default || require('chalk');
|
|
10
|
+
const fileManager = require('./file-manager');
|
|
11
|
+
const resourceLocator = require('./resource-locator');
|
|
12
|
+
const { extractYamlFromAgent } = require('../../lib/yaml-utils');
|
|
13
|
+
|
|
14
|
+
class BaseIdeSetup {
|
|
15
|
+
constructor() {
|
|
16
|
+
this._agentCache = new Map();
|
|
17
|
+
this._pathCache = new Map();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get all agent IDs with caching
|
|
22
|
+
*/
|
|
23
|
+
async getAllAgentIds(installDir) {
|
|
24
|
+
const cacheKey = `all-agents:${installDir}`;
|
|
25
|
+
if (this._agentCache.has(cacheKey)) {
|
|
26
|
+
return this._agentCache.get(cacheKey);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const allAgents = new Set();
|
|
30
|
+
|
|
31
|
+
// Get core agents
|
|
32
|
+
const coreAgents = await this.getCoreAgentIds(installDir);
|
|
33
|
+
for (const id of coreAgents) allAgents.add(id);
|
|
34
|
+
|
|
35
|
+
// Get expansion pack agents
|
|
36
|
+
const expansionPacks = await this.getInstalledExpansionPacks(installDir);
|
|
37
|
+
for (const pack of expansionPacks) {
|
|
38
|
+
const packAgents = await this.getExpansionPackAgents(pack.path);
|
|
39
|
+
for (const id of packAgents) allAgents.add(id);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const result = [...allAgents];
|
|
43
|
+
this._agentCache.set(cacheKey, result);
|
|
44
|
+
return result;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get core agent IDs
|
|
49
|
+
*/
|
|
50
|
+
async getCoreAgentIds(installDir) {
|
|
51
|
+
const coreAgents = [];
|
|
52
|
+
const corePaths = [
|
|
53
|
+
path.join(installDir, '.bmad-core', 'agents'),
|
|
54
|
+
path.join(installDir, 'bmad-core', 'agents'),
|
|
55
|
+
];
|
|
56
|
+
|
|
57
|
+
for (const agentsDir of corePaths) {
|
|
58
|
+
if (await fileManager.pathExists(agentsDir)) {
|
|
59
|
+
const files = await resourceLocator.findFiles('*.md', { cwd: agentsDir });
|
|
60
|
+
coreAgents.push(...files.map((file) => path.basename(file, '.md')));
|
|
61
|
+
break; // Use first found
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return coreAgents;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Find agent path with caching
|
|
70
|
+
*/
|
|
71
|
+
async findAgentPath(agentId, installDir) {
|
|
72
|
+
const cacheKey = `agent-path:${agentId}:${installDir}`;
|
|
73
|
+
if (this._pathCache.has(cacheKey)) {
|
|
74
|
+
return this._pathCache.get(cacheKey);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Use resource locator for efficient path finding
|
|
78
|
+
let agentPath = await resourceLocator.getAgentPath(agentId);
|
|
79
|
+
|
|
80
|
+
if (!agentPath) {
|
|
81
|
+
// Check installation-specific paths
|
|
82
|
+
const possiblePaths = [
|
|
83
|
+
path.join(installDir, '.bmad-core', 'agents', `${agentId}.md`),
|
|
84
|
+
path.join(installDir, 'bmad-core', 'agents', `${agentId}.md`),
|
|
85
|
+
path.join(installDir, 'common', 'agents', `${agentId}.md`),
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
for (const testPath of possiblePaths) {
|
|
89
|
+
if (await fileManager.pathExists(testPath)) {
|
|
90
|
+
agentPath = testPath;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (agentPath) {
|
|
97
|
+
this._pathCache.set(cacheKey, agentPath);
|
|
98
|
+
}
|
|
99
|
+
return agentPath;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Get agent title from metadata
|
|
104
|
+
*/
|
|
105
|
+
async getAgentTitle(agentId, installDir) {
|
|
106
|
+
const agentPath = await this.findAgentPath(agentId, installDir);
|
|
107
|
+
if (!agentPath) return agentId;
|
|
108
|
+
|
|
109
|
+
try {
|
|
110
|
+
const content = await fileManager.readFile(agentPath);
|
|
111
|
+
const yamlContent = extractYamlFromAgent(content);
|
|
112
|
+
if (yamlContent) {
|
|
113
|
+
const metadata = yaml.load(yamlContent);
|
|
114
|
+
return metadata.agent_name || agentId;
|
|
115
|
+
}
|
|
116
|
+
} catch {
|
|
117
|
+
// Fallback to agent ID
|
|
118
|
+
}
|
|
119
|
+
return agentId;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get installed expansion packs
|
|
124
|
+
*/
|
|
125
|
+
async getInstalledExpansionPacks(installDir) {
|
|
126
|
+
const cacheKey = `expansion-packs:${installDir}`;
|
|
127
|
+
if (this._pathCache.has(cacheKey)) {
|
|
128
|
+
return this._pathCache.get(cacheKey);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const expansionPacks = [];
|
|
132
|
+
|
|
133
|
+
// Check for dot-prefixed expansion packs
|
|
134
|
+
const dotExpansions = await resourceLocator.findFiles('.bmad-*', { cwd: installDir });
|
|
135
|
+
|
|
136
|
+
for (const dotExpansion of dotExpansions) {
|
|
137
|
+
if (dotExpansion !== '.bmad-core') {
|
|
138
|
+
const packPath = path.join(installDir, dotExpansion);
|
|
139
|
+
const packName = dotExpansion.slice(1); // remove the dot
|
|
140
|
+
expansionPacks.push({
|
|
141
|
+
name: packName,
|
|
142
|
+
path: packPath,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Check other dot folders that have config.yaml
|
|
148
|
+
const allDotFolders = await resourceLocator.findFiles('.*', { cwd: installDir });
|
|
149
|
+
for (const folder of allDotFolders) {
|
|
150
|
+
if (!folder.startsWith('.bmad-') && folder !== '.bmad-core') {
|
|
151
|
+
const packPath = path.join(installDir, folder);
|
|
152
|
+
const configPath = path.join(packPath, 'config.yaml');
|
|
153
|
+
if (await fileManager.pathExists(configPath)) {
|
|
154
|
+
expansionPacks.push({
|
|
155
|
+
name: folder.slice(1), // remove the dot
|
|
156
|
+
path: packPath,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
this._pathCache.set(cacheKey, expansionPacks);
|
|
163
|
+
return expansionPacks;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Get expansion pack agents
|
|
168
|
+
*/
|
|
169
|
+
async getExpansionPackAgents(packPath) {
|
|
170
|
+
const agentsDir = path.join(packPath, 'agents');
|
|
171
|
+
if (!(await fileManager.pathExists(agentsDir))) {
|
|
172
|
+
return [];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const agentFiles = await resourceLocator.findFiles('*.md', { cwd: agentsDir });
|
|
176
|
+
return agentFiles.map((file) => path.basename(file, '.md'));
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Create agent rule content (shared logic)
|
|
181
|
+
*/
|
|
182
|
+
async createAgentRuleContent(agentId, agentPath, installDir, format = 'mdc') {
|
|
183
|
+
const agentContent = await fileManager.readFile(agentPath);
|
|
184
|
+
const agentTitle = await this.getAgentTitle(agentId, installDir);
|
|
185
|
+
const yamlContent = extractYamlFromAgent(agentContent);
|
|
186
|
+
|
|
187
|
+
let content = '';
|
|
188
|
+
|
|
189
|
+
if (format === 'mdc') {
|
|
190
|
+
// MDC format for Cursor
|
|
191
|
+
content = '---\n';
|
|
192
|
+
content += 'description: \n';
|
|
193
|
+
content += 'globs: []\n';
|
|
194
|
+
content += 'alwaysApply: false\n';
|
|
195
|
+
content += '---\n\n';
|
|
196
|
+
content += `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
|
197
|
+
content += `This rule is triggered when the user types \`@${agentId}\` and activates the ${agentTitle} agent persona.\n\n`;
|
|
198
|
+
content += '## Agent Activation\n\n';
|
|
199
|
+
content +=
|
|
200
|
+
'CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n';
|
|
201
|
+
content += '```yaml\n';
|
|
202
|
+
content += yamlContent || agentContent.replace(/^#.*$/m, '').trim();
|
|
203
|
+
content += '\n```\n\n';
|
|
204
|
+
content += '## File Reference\n\n';
|
|
205
|
+
const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
|
|
206
|
+
content += `The complete agent definition is available in [${relativePath}](mdc:${relativePath}).\n\n`;
|
|
207
|
+
content += '## Usage\n\n';
|
|
208
|
+
content += `When the user types \`@${agentId}\`, activate this ${agentTitle} persona and follow all instructions defined in the YAML configuration above.\n`;
|
|
209
|
+
} else if (format === 'claude') {
|
|
210
|
+
// Claude Code format
|
|
211
|
+
content = `# /${agentId} Command\n\n`;
|
|
212
|
+
content += `When this command is used, adopt the following agent persona:\n\n`;
|
|
213
|
+
content += agentContent;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return content;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Clear all caches
|
|
221
|
+
*/
|
|
222
|
+
clearCache() {
|
|
223
|
+
this._agentCache.clear();
|
|
224
|
+
this._pathCache.clear();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
module.exports = BaseIdeSetup;
|