bmad-method 6.0.3 → 6.0.5-next.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/.augment/code_review_guidelines.yaml +2 -42
- package/.claude/skills/bmad-os-findings-triage/SKILL.md +6 -0
- package/.claude/skills/bmad-os-findings-triage/prompts/agent-prompt.md +104 -0
- package/.claude/skills/bmad-os-findings-triage/prompts/instructions.md +286 -0
- package/.claude/skills/bmad-os-review-pr/SKILL.md +1 -1
- package/.claude/skills/bmad-os-review-pr/prompts/instructions.md +63 -6
- package/.claude/skills/bmad-os-review-prompt/SKILL.md +177 -0
- package/.claude/skills/bmad-os-root-cause-analysis/SKILL.md +12 -0
- package/.claude/skills/bmad-os-root-cause-analysis/prompts/instructions.md +74 -0
- package/.github/ISSUE_TEMPLATE/config.yaml +1 -1
- package/.github/ISSUE_TEMPLATE/documentation.yaml +1 -1
- package/.github/workflows/publish.yaml +243 -0
- package/CHANGELOG.md +32 -0
- package/CONTRIBUTING.md +1 -1
- package/README.md +8 -8
- package/README_CN.md +121 -0
- package/docs/_STYLE_GUIDE.md +10 -10
- package/docs/explanation/brainstorming.md +1 -1
- package/docs/explanation/party-mode.md +1 -1
- package/docs/explanation/preventing-agent-conflicts.md +1 -1
- package/docs/explanation/project-context.md +15 -15
- package/docs/explanation/quick-flow.md +9 -9
- package/docs/how-to/established-projects.md +7 -7
- package/docs/how-to/get-answers-about-bmad.md +2 -2
- package/docs/how-to/install-bmad.md +16 -6
- package/docs/how-to/project-context.md +2 -2
- package/docs/how-to/quick-fixes.md +5 -5
- package/docs/how-to/shard-large-documents.md +1 -1
- package/docs/how-to/upgrade-to-v6.md +8 -5
- package/docs/index.md +2 -2
- package/docs/reference/agents.md +14 -14
- package/docs/reference/commands.md +64 -70
- package/docs/reference/testing.md +1 -1
- package/docs/reference/workflow-map.md +19 -19
- package/docs/tutorials/getting-started.md +34 -34
- package/docs/zh-cn/404.md +9 -0
- package/docs/zh-cn/_STYLE_GUIDE.md +370 -0
- package/docs/zh-cn/explanation/advanced-elicitation.md +62 -0
- package/docs/zh-cn/explanation/adversarial-review.md +71 -0
- package/docs/zh-cn/explanation/brainstorming.md +43 -0
- package/docs/zh-cn/explanation/established-projects-faq.md +60 -0
- package/docs/zh-cn/explanation/party-mode.md +79 -0
- package/docs/zh-cn/explanation/preventing-agent-conflicts.md +137 -0
- package/docs/zh-cn/explanation/project-context.md +176 -0
- package/docs/zh-cn/explanation/quick-flow.md +93 -0
- package/docs/zh-cn/explanation/why-solutioning-matters.md +90 -0
- package/docs/zh-cn/how-to/customize-bmad.md +182 -0
- package/docs/zh-cn/how-to/established-projects.md +134 -0
- package/docs/zh-cn/how-to/get-answers-about-bmad.md +144 -0
- package/docs/zh-cn/how-to/install-bmad.md +105 -0
- package/docs/zh-cn/how-to/non-interactive-installation.md +181 -0
- package/docs/zh-cn/how-to/project-context.md +152 -0
- package/docs/zh-cn/how-to/quick-fixes.md +140 -0
- package/docs/zh-cn/how-to/shard-large-documents.md +86 -0
- package/docs/zh-cn/how-to/upgrade-to-v6.md +120 -0
- package/docs/zh-cn/index.md +69 -0
- package/docs/zh-cn/reference/agents.md +41 -0
- package/docs/zh-cn/reference/commands.md +166 -0
- package/docs/zh-cn/reference/modules.md +94 -0
- package/docs/zh-cn/reference/testing.md +122 -0
- package/docs/zh-cn/reference/workflow-map.md +104 -0
- package/docs/zh-cn/roadmap.mdx +152 -0
- package/docs/zh-cn/tutorials/getting-started.md +300 -0
- package/package.json +1 -1
- package/src/bmm/agents/analyst.agent.yaml +1 -1
- package/src/bmm/agents/bmad-skill-manifest.yaml +39 -0
- package/src/bmm/agents/dev.agent.yaml +2 -2
- package/src/bmm/agents/pm.agent.yaml +1 -1
- package/src/bmm/agents/qa.agent.yaml +1 -1
- package/src/bmm/agents/quick-flow-solo-dev.agent.yaml +6 -2
- package/src/bmm/agents/sm.agent.yaml +4 -4
- package/src/bmm/agents/tech-writer/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/agents/tech-writer/tech-writer.agent.yaml +1 -1
- package/src/bmm/module-help.csv +11 -10
- package/src/bmm/workflows/1-analysis/create-product-brief/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-02-vision.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-03-users.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-04-metrics.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-05-scope.md +1 -1
- package/src/bmm/workflows/1-analysis/create-product-brief/steps/step-06-complete.md +1 -1
- package/src/bmm/workflows/1-analysis/research/bmad-skill-manifest.yaml +14 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/bmad-skill-manifest.yaml +14 -0
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02-discovery.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02b-vision.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-02c-executive-summary.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-03-success.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-04-journeys.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-05-domain.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-06-innovation.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-07-project-type.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-08-scoping.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-09-functional.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-10-nonfunctional.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-11-polish.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-c/step-12-complete.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-01-discovery.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-e/step-e-02-review.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-01-discovery.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-10-smart-validation.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-11-holistic-quality-validation.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-prd/steps-v/step-v-13-report-complete.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-02-discovery.md +1 -1
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-03-core-experience.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-04-emotional-response.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-05-inspiration.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-06-design-system.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-07-defining-experience.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-08-visual-foundation.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-09-design-directions.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-10-user-journeys.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-11-component-strategy.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-12-ux-patterns.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-13-responsive-accessibility.md +2 -2
- package/src/bmm/workflows/2-plan-workflows/create-ux-design/steps/step-14-complete.md +1 -1
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/3-solutioning/check-implementation-readiness/steps/step-06-final-assessment.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-architecture/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-02-context.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-03-starter.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-04-decisions.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-05-patterns.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-06-structure.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-07-validation.md +2 -2
- package/src/bmm/workflows/3-solutioning/create-architecture/steps/step-08-complete.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-01-validate-prerequisites.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-02-design-epics.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-03-create-stories.md +1 -1
- package/src/bmm/workflows/3-solutioning/create-epics-and-stories/steps/step-04-final-validation.md +2 -2
- package/src/bmm/workflows/4-implementation/code-review/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/4-implementation/code-review/discover-inputs.md +88 -0
- package/src/bmm/workflows/4-implementation/code-review/workflow.md +271 -0
- package/src/bmm/workflows/4-implementation/correct-course/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/4-implementation/correct-course/checklist.md +1 -1
- package/src/bmm/workflows/4-implementation/correct-course/{instructions.md → workflow.md} +79 -12
- package/src/bmm/workflows/4-implementation/create-story/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/4-implementation/create-story/checklist.md +9 -10
- package/src/bmm/workflows/4-implementation/create-story/discover-inputs.md +88 -0
- package/src/bmm/workflows/4-implementation/create-story/workflow.md +388 -0
- package/src/bmm/workflows/4-implementation/dev-story/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/4-implementation/dev-story/{instructions.xml → workflow.md} +49 -2
- package/src/bmm/workflows/4-implementation/retrospective/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/4-implementation/retrospective/{instructions.md → workflow.md} +64 -23
- package/src/bmm/workflows/4-implementation/sprint-planning/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/sprint-status-template.yaml +1 -0
- package/src/bmm/workflows/4-implementation/sprint-planning/{instructions.md → workflow.md} +55 -10
- package/src/bmm/workflows/4-implementation/sprint-status/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/4-implementation/sprint-status/{instructions.md → workflow.md} +45 -8
- package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/SKILL.md +6 -0
- package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/bmad-skill-manifest.yaml +1 -0
- package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-01-clarify-and-route.md +54 -0
- package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-02-plan.md +39 -0
- package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-03-implement.md +35 -0
- package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-04-review.md +55 -0
- package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/steps/step-05-present.md +19 -0
- package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/tech-spec-template.md +90 -0
- package/src/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md +84 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/steps/step-05-adversarial-review.md +8 -14
- package/src/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md +1 -1
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/steps/step-04-review.md +4 -6
- package/src/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md +1 -1
- package/src/bmm/workflows/document-project/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/document-project/instructions.md +5 -7
- package/src/bmm/workflows/document-project/workflow.md +39 -0
- package/src/bmm/workflows/document-project/workflows/deep-dive-instructions.md +0 -1
- package/src/bmm/workflows/document-project/workflows/deep-dive-workflow.md +42 -0
- package/src/bmm/workflows/document-project/workflows/full-scan-instructions.md +0 -1
- package/src/bmm/workflows/document-project/workflows/full-scan-workflow.md +42 -0
- package/src/bmm/workflows/generate-project-context/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/generate-project-context/steps/step-02-generate.md +2 -2
- package/src/bmm/workflows/qa-generate-e2e-tests/bmad-skill-manifest.yaml +3 -0
- package/src/bmm/workflows/qa-generate-e2e-tests/checklist.md +1 -1
- package/src/bmm/workflows/qa-generate-e2e-tests/{instructions.md → workflow.md} +40 -7
- package/src/core/agents/bmad-master.agent.yaml +1 -1
- package/src/core/agents/bmad-skill-manifest.yaml +3 -0
- package/src/core/module-help.csv +3 -2
- package/src/core/module.yaml +1 -1
- package/src/core/tasks/bmad-help/SKILL.md +6 -0
- package/src/core/tasks/bmad-help/bmad-skill-manifest.yaml +1 -0
- package/src/core/tasks/{help.md → bmad-help/workflow.md} +6 -4
- package/src/core/tasks/bmad-review-adversarial-general/SKILL.md +6 -0
- package/src/core/tasks/bmad-review-adversarial-general/bmad-skill-manifest.yaml +1 -0
- package/src/core/tasks/bmad-review-adversarial-general/workflow.md +32 -0
- package/src/core/tasks/bmad-review-edge-case-hunter/SKILL.md +6 -0
- package/src/core/tasks/bmad-review-edge-case-hunter/bmad-skill-manifest.yaml +1 -0
- package/src/core/tasks/bmad-review-edge-case-hunter/workflow.md +62 -0
- package/src/core/tasks/bmad-skill-manifest.yaml +19 -0
- package/src/core/workflows/advanced-elicitation/bmad-skill-manifest.yaml +3 -0
- package/src/core/workflows/advanced-elicitation/workflow.md +138 -0
- package/src/core/workflows/brainstorming/bmad-skill-manifest.yaml +3 -0
- package/src/core/workflows/brainstorming/steps/step-01-session-setup.md +31 -18
- package/src/core/workflows/brainstorming/steps/step-01b-continue.md +1 -1
- package/src/core/workflows/brainstorming/steps/step-03-technique-execution.md +3 -3
- package/src/core/workflows/brainstorming/steps/step-04-idea-organization.md +2 -2
- package/src/core/workflows/brainstorming/workflow.md +5 -3
- package/src/core/workflows/party-mode/bmad-skill-manifest.yaml +3 -0
- package/src/core/workflows/party-mode/workflow.md +1 -1
- package/src/utility/agent-components/activation-steps.txt +2 -2
- package/src/utility/agent-components/handler-multi.txt +1 -2
- package/test/adversarial-review-tests/README.md +3 -3
- package/test/adversarial-review-tests/test-cases.yaml +2 -2
- package/test/fixtures/agent-schema/valid/menu/multiple-menu-items.agent.yaml +1 -1
- package/test/fixtures/agent-schema/valid/menu-commands/all-command-types.agent.yaml +1 -1
- package/test/fixtures/agent-schema/valid/menu-commands/multiple-commands.agent.yaml +1 -2
- package/test/fixtures/file-refs-csv/valid/bmm-style.csv +1 -1
- package/test/test-file-refs-csv.js +1 -1
- package/test/test-install-to-bmad.js +154 -0
- package/test/test-installation-components.js +1586 -2
- package/test/test-workflow-path-regex.js +88 -0
- package/tools/cli/installers/install-messages.yaml +1 -1
- package/tools/cli/installers/lib/core/installer.js +34 -1
- package/tools/cli/installers/lib/core/manifest-generator.js +332 -41
- package/tools/cli/installers/lib/ide/_base-ide.js +24 -15
- package/tools/cli/installers/lib/ide/_config-driven.js +547 -53
- package/tools/cli/installers/lib/ide/manager.js +26 -62
- package/tools/cli/installers/lib/ide/platform-codes.yaml +116 -29
- package/tools/cli/installers/lib/ide/shared/agent-command-generator.js +1 -0
- package/tools/cli/installers/lib/ide/shared/bmad-artifacts.js +7 -0
- package/tools/cli/installers/lib/ide/shared/path-utils.js +68 -3
- package/tools/cli/installers/lib/ide/shared/skill-manifest.js +90 -0
- package/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +2 -0
- package/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +6 -145
- package/tools/cli/installers/lib/ide/templates/agent-command-template.md +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/default-workflow.md +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow-yaml.toml +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/gemini-workflow.toml +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/opencode-agent.md +1 -1
- package/tools/cli/installers/lib/ide/templates/combined/opencode-task.md +0 -1
- package/tools/cli/installers/lib/ide/templates/combined/opencode-tool.md +0 -1
- package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow-yaml.md +0 -1
- package/tools/cli/installers/lib/ide/templates/combined/opencode-workflow.md +0 -1
- package/tools/cli/installers/lib/modules/manager.js +9 -132
- package/tools/cli/lib/agent/compiler.js +1 -10
- package/tools/cli/lib/agent-analyzer.js +2 -14
- package/tools/cli/lib/yaml-xml-builder.js +1 -18
- package/tools/docs/native-skills-migration-checklist.md +281 -0
- package/tools/platform-codes.yaml +1 -1
- package/tools/schema/agent.js +1 -3
- package/tools/validate-file-refs.js +2 -0
- package/website/astro.config.mjs +24 -3
- package/website/src/content/config.ts +2 -1
- package/website/src/content/i18n/zh-CN.json +28 -0
- package/src/bmm/workflows/4-implementation/code-review/instructions.xml +0 -227
- package/src/bmm/workflows/4-implementation/code-review/workflow.yaml +0 -43
- package/src/bmm/workflows/4-implementation/correct-course/workflow.yaml +0 -53
- package/src/bmm/workflows/4-implementation/create-story/instructions.xml +0 -346
- package/src/bmm/workflows/4-implementation/create-story/workflow.yaml +0 -52
- package/src/bmm/workflows/4-implementation/dev-story/workflow.yaml +0 -20
- package/src/bmm/workflows/4-implementation/retrospective/workflow.yaml +0 -52
- package/src/bmm/workflows/4-implementation/sprint-planning/workflow.yaml +0 -47
- package/src/bmm/workflows/4-implementation/sprint-status/workflow.yaml +0 -25
- package/src/bmm/workflows/document-project/workflow.yaml +0 -22
- package/src/bmm/workflows/document-project/workflows/deep-dive.yaml +0 -31
- package/src/bmm/workflows/document-project/workflows/full-scan.yaml +0 -31
- package/src/bmm/workflows/qa-generate-e2e-tests/workflow.yaml +0 -42
- package/src/core/tasks/review-adversarial-general.xml +0 -49
- package/src/core/tasks/workflow.xml +0 -235
- package/src/core/workflows/advanced-elicitation/workflow.xml +0 -118
- package/src/utility/agent-components/handler-validate-workflow.txt +0 -7
- package/src/utility/agent-components/handler-workflow.txt +0 -10
- package/tools/cli/installers/lib/ide/codex.js +0 -440
- package/tools/cli/installers/lib/ide/github-copilot.js +0 -699
- package/tools/cli/installers/lib/ide/kilo.js +0 -269
- package/tools/cli/installers/lib/ide/rovodev.js +0 -257
- package/tools/cli/installers/lib/ide/templates/combined/default-workflow-yaml.md +0 -14
- package/tools/cli/installers/lib/ide/templates/combined/kiro-workflow-yaml.md +0 -15
- package/tools/cli/installers/lib/ide/templates/workflow-command-template.md +0 -13
- package/tools/cli/installers/lib/ide/templates/workflow-commander.md +0 -5
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
const path = require('node:path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const yaml = require('yaml');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Load bmad-skill-manifest.yaml from a directory.
|
|
7
|
+
* Single-entry manifests (canonicalId at top level) apply to all files in the directory.
|
|
8
|
+
* Multi-entry manifests are keyed by source filename.
|
|
9
|
+
* @param {string} dirPath - Directory to check for bmad-skill-manifest.yaml
|
|
10
|
+
* @returns {Object|null} Parsed manifest or null
|
|
11
|
+
*/
|
|
12
|
+
async function loadSkillManifest(dirPath) {
|
|
13
|
+
const manifestPath = path.join(dirPath, 'bmad-skill-manifest.yaml');
|
|
14
|
+
try {
|
|
15
|
+
if (!(await fs.pathExists(manifestPath))) return null;
|
|
16
|
+
const content = await fs.readFile(manifestPath, 'utf8');
|
|
17
|
+
const parsed = yaml.parse(content);
|
|
18
|
+
if (!parsed || typeof parsed !== 'object') return null;
|
|
19
|
+
if (parsed.canonicalId || parsed.type) return { __single: parsed };
|
|
20
|
+
return parsed;
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.warn(`Warning: Failed to parse bmad-skill-manifest.yaml in ${dirPath}: ${error.message}`);
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get the canonicalId for a specific file from a loaded skill manifest.
|
|
29
|
+
* @param {Object|null} manifest - Loaded manifest (from loadSkillManifest)
|
|
30
|
+
* @param {string} filename - Source filename to look up (e.g., 'pm.md', 'help.md', 'pm.agent.yaml')
|
|
31
|
+
* @returns {string} canonicalId or empty string
|
|
32
|
+
*/
|
|
33
|
+
function getCanonicalId(manifest, filename) {
|
|
34
|
+
if (!manifest) return '';
|
|
35
|
+
// Single-entry manifest applies to all files in the directory
|
|
36
|
+
if (manifest.__single) return manifest.__single.canonicalId || '';
|
|
37
|
+
// Multi-entry: look up by filename directly
|
|
38
|
+
if (manifest[filename]) return manifest[filename].canonicalId || '';
|
|
39
|
+
// Fallback: try alternate extensions for compiled files
|
|
40
|
+
const baseName = filename.replace(/\.(md|xml)$/i, '');
|
|
41
|
+
const agentKey = `${baseName}.agent.yaml`;
|
|
42
|
+
if (manifest[agentKey]) return manifest[agentKey].canonicalId || '';
|
|
43
|
+
const xmlKey = `${baseName}.xml`;
|
|
44
|
+
if (manifest[xmlKey]) return manifest[xmlKey].canonicalId || '';
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Get the artifact type for a specific file from a loaded skill manifest.
|
|
50
|
+
* @param {Object|null} manifest - Loaded manifest (from loadSkillManifest)
|
|
51
|
+
* @param {string} filename - Source filename to look up
|
|
52
|
+
* @returns {string|null} type or null
|
|
53
|
+
*/
|
|
54
|
+
function getArtifactType(manifest, filename) {
|
|
55
|
+
if (!manifest) return null;
|
|
56
|
+
// Single-entry manifest applies to all files in the directory
|
|
57
|
+
if (manifest.__single) return manifest.__single.type || null;
|
|
58
|
+
// Multi-entry: look up by filename directly
|
|
59
|
+
if (manifest[filename]) return manifest[filename].type || null;
|
|
60
|
+
// Fallback: try alternate extensions for compiled files
|
|
61
|
+
const baseName = filename.replace(/\.(md|xml)$/i, '');
|
|
62
|
+
const agentKey = `${baseName}.agent.yaml`;
|
|
63
|
+
if (manifest[agentKey]) return manifest[agentKey].type || null;
|
|
64
|
+
const xmlKey = `${baseName}.xml`;
|
|
65
|
+
if (manifest[xmlKey]) return manifest[xmlKey].type || null;
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get the install_to_bmad flag for a specific file from a loaded skill manifest.
|
|
71
|
+
* @param {Object|null} manifest - Loaded manifest (from loadSkillManifest)
|
|
72
|
+
* @param {string} filename - Source filename to look up
|
|
73
|
+
* @returns {boolean} install_to_bmad value (defaults to true)
|
|
74
|
+
*/
|
|
75
|
+
function getInstallToBmad(manifest, filename) {
|
|
76
|
+
if (!manifest) return true;
|
|
77
|
+
// Single-entry manifest applies to all files in the directory
|
|
78
|
+
if (manifest.__single) return manifest.__single.install_to_bmad !== false;
|
|
79
|
+
// Multi-entry: look up by filename directly
|
|
80
|
+
if (manifest[filename]) return manifest[filename].install_to_bmad !== false;
|
|
81
|
+
// Fallback: try alternate extensions for compiled files
|
|
82
|
+
const baseName = filename.replace(/\.(md|xml)$/i, '');
|
|
83
|
+
const agentKey = `${baseName}.agent.yaml`;
|
|
84
|
+
if (manifest[agentKey]) return manifest[agentKey].install_to_bmad !== false;
|
|
85
|
+
const xmlKey = `${baseName}.xml`;
|
|
86
|
+
if (manifest[xmlKey]) return manifest[xmlKey].install_to_bmad !== false;
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
module.exports = { loadSkillManifest, getCanonicalId, getArtifactType, getInstallToBmad };
|
|
@@ -50,6 +50,7 @@ class TaskToolCommandGenerator {
|
|
|
50
50
|
displayName: task.displayName || task.name,
|
|
51
51
|
description: task.description || `Execute ${task.displayName || task.name}`,
|
|
52
52
|
module: task.module,
|
|
53
|
+
canonicalId: task.canonicalId || '',
|
|
53
54
|
// Use forward slashes for cross-platform consistency (not path.join which uses backslashes on Windows)
|
|
54
55
|
relativePath: `${task.module}/tasks/${task.name}${taskExt}`,
|
|
55
56
|
path: taskPath,
|
|
@@ -75,6 +76,7 @@ class TaskToolCommandGenerator {
|
|
|
75
76
|
displayName: tool.displayName || tool.name,
|
|
76
77
|
description: tool.description || `Execute ${tool.displayName || tool.name}`,
|
|
77
78
|
module: tool.module,
|
|
79
|
+
canonicalId: tool.canonicalId || '',
|
|
78
80
|
// Use forward slashes for cross-platform consistency (not path.join which uses backslashes on Windows)
|
|
79
81
|
relativePath: `${tool.module}/tools/${tool.name}${toolExt}`,
|
|
80
82
|
path: toolPath,
|
|
@@ -1,58 +1,16 @@
|
|
|
1
1
|
const path = require('node:path');
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const csv = require('csv-parse/sync');
|
|
4
|
-
const
|
|
5
|
-
const { toColonPath, toDashPath, customAgentColonName, customAgentDashName, BMAD_FOLDER_NAME } = require('./path-utils');
|
|
4
|
+
const { BMAD_FOLDER_NAME } = require('./path-utils');
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* Generates command files for each workflow in the manifest
|
|
9
8
|
*/
|
|
10
9
|
class WorkflowCommandGenerator {
|
|
11
10
|
constructor(bmadFolderName = BMAD_FOLDER_NAME) {
|
|
12
|
-
this.templatePath = path.join(__dirname, '../templates/workflow-command-template.md');
|
|
13
11
|
this.bmadFolderName = bmadFolderName;
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
/**
|
|
17
|
-
* Generate workflow commands from the manifest CSV
|
|
18
|
-
* @param {string} projectDir - Project directory
|
|
19
|
-
* @param {string} bmadDir - BMAD installation directory
|
|
20
|
-
*/
|
|
21
|
-
async generateWorkflowCommands(projectDir, bmadDir) {
|
|
22
|
-
const workflows = await this.loadWorkflowManifest(bmadDir);
|
|
23
|
-
|
|
24
|
-
if (!workflows) {
|
|
25
|
-
await prompts.log.warn('Workflow manifest not found. Skipping command generation.');
|
|
26
|
-
return { generated: 0 };
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// ALL workflows now generate commands - no standalone filtering
|
|
30
|
-
const allWorkflows = workflows;
|
|
31
|
-
|
|
32
|
-
// Base commands directory
|
|
33
|
-
const baseCommandsDir = path.join(projectDir, '.claude', 'commands', 'bmad');
|
|
34
|
-
|
|
35
|
-
let generatedCount = 0;
|
|
36
|
-
|
|
37
|
-
// Generate a command file for each workflow, organized by module
|
|
38
|
-
for (const workflow of allWorkflows) {
|
|
39
|
-
const moduleWorkflowsDir = path.join(baseCommandsDir, workflow.module, 'workflows');
|
|
40
|
-
await fs.ensureDir(moduleWorkflowsDir);
|
|
41
|
-
|
|
42
|
-
const commandContent = await this.generateCommandContent(workflow, bmadDir);
|
|
43
|
-
const commandPath = path.join(moduleWorkflowsDir, `${workflow.name}.md`);
|
|
44
|
-
|
|
45
|
-
await fs.writeFile(commandPath, commandContent);
|
|
46
|
-
generatedCount++;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// Also create a workflow launcher README in each module
|
|
50
|
-
const groupedWorkflows = this.groupWorkflowsByModule(allWorkflows);
|
|
51
|
-
await this.createModuleWorkflowLaunchers(baseCommandsDir, groupedWorkflows);
|
|
52
|
-
|
|
53
|
-
return { generated: generatedCount };
|
|
54
|
-
}
|
|
55
|
-
|
|
56
14
|
async collectWorkflowArtifacts(bmadDir) {
|
|
57
15
|
const workflows = await this.loadWorkflowManifest(bmadDir);
|
|
58
16
|
|
|
@@ -66,8 +24,7 @@ class WorkflowCommandGenerator {
|
|
|
66
24
|
const artifacts = [];
|
|
67
25
|
|
|
68
26
|
for (const workflow of allWorkflows) {
|
|
69
|
-
|
|
70
|
-
// Calculate the relative workflow path (e.g., bmm/workflows/4-implementation/sprint-planning/workflow.yaml)
|
|
27
|
+
// Calculate the relative workflow path (e.g., bmm/workflows/4-implementation/sprint-planning/workflow.md)
|
|
71
28
|
let workflowRelPath = workflow.path || '';
|
|
72
29
|
// Normalize path separators for cross-platform compatibility
|
|
73
30
|
workflowRelPath = workflowRelPath.replaceAll('\\', '/');
|
|
@@ -85,17 +42,14 @@ class WorkflowCommandGenerator {
|
|
|
85
42
|
workflowRelPath = `${match[1]}/${match[2]}`;
|
|
86
43
|
}
|
|
87
44
|
}
|
|
88
|
-
// Determine if this is a YAML workflow (use normalized path which is guaranteed to be a string)
|
|
89
|
-
const isYamlWorkflow = workflowRelPath.endsWith('.yaml') || workflowRelPath.endsWith('.yml');
|
|
90
45
|
artifacts.push({
|
|
91
46
|
type: 'workflow-command',
|
|
92
|
-
isYamlWorkflow: isYamlWorkflow, // For template selection
|
|
93
47
|
name: workflow.name,
|
|
94
48
|
description: workflow.description || `${workflow.name} workflow`,
|
|
95
49
|
module: workflow.module,
|
|
50
|
+
canonicalId: workflow.canonicalId || '',
|
|
96
51
|
relativePath: path.join(workflow.module, 'workflows', `${workflow.name}.md`),
|
|
97
52
|
workflowPath: workflowRelPath, // Relative path to actual workflow file
|
|
98
|
-
content: commandContent,
|
|
99
53
|
sourcePath: workflow.path,
|
|
100
54
|
});
|
|
101
55
|
}
|
|
@@ -120,46 +74,6 @@ class WorkflowCommandGenerator {
|
|
|
120
74
|
};
|
|
121
75
|
}
|
|
122
76
|
|
|
123
|
-
/**
|
|
124
|
-
* Generate command content for a workflow
|
|
125
|
-
*/
|
|
126
|
-
async generateCommandContent(workflow, bmadDir) {
|
|
127
|
-
// Determine template based on workflow file type
|
|
128
|
-
const isMarkdownWorkflow = workflow.path.endsWith('workflow.md');
|
|
129
|
-
const templateName = isMarkdownWorkflow ? 'workflow-commander.md' : 'workflow-command-template.md';
|
|
130
|
-
const templatePath = path.join(path.dirname(this.templatePath), templateName);
|
|
131
|
-
|
|
132
|
-
// Load the appropriate template
|
|
133
|
-
const template = await fs.readFile(templatePath, 'utf8');
|
|
134
|
-
|
|
135
|
-
// Convert source path to installed path
|
|
136
|
-
// From: /Users/.../src/bmm/workflows/.../workflow.yaml
|
|
137
|
-
// To: {project-root}/_bmad/bmm/workflows/.../workflow.yaml
|
|
138
|
-
let workflowPath = workflow.path;
|
|
139
|
-
|
|
140
|
-
// Extract the relative path from source
|
|
141
|
-
if (workflowPath.includes('/src/bmm/')) {
|
|
142
|
-
// bmm is directly under src/
|
|
143
|
-
const match = workflowPath.match(/\/src\/bmm\/(.+)/);
|
|
144
|
-
if (match) {
|
|
145
|
-
workflowPath = `${this.bmadFolderName}/bmm/${match[1]}`;
|
|
146
|
-
}
|
|
147
|
-
} else if (workflowPath.includes('/src/core/')) {
|
|
148
|
-
const match = workflowPath.match(/\/src\/core\/(.+)/);
|
|
149
|
-
if (match) {
|
|
150
|
-
workflowPath = `${this.bmadFolderName}/core/${match[1]}`;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Replace template variables
|
|
155
|
-
return template
|
|
156
|
-
.replaceAll('{{name}}', workflow.name)
|
|
157
|
-
.replaceAll('{{module}}', workflow.module)
|
|
158
|
-
.replaceAll('{{description}}', workflow.description)
|
|
159
|
-
.replaceAll('{{workflow_path}}', workflowPath)
|
|
160
|
-
.replaceAll('_bmad', this.bmadFolderName);
|
|
161
|
-
}
|
|
162
|
-
|
|
163
77
|
/**
|
|
164
78
|
* Create workflow launcher files for each module
|
|
165
79
|
*/
|
|
@@ -217,10 +131,9 @@ class WorkflowCommandGenerator {
|
|
|
217
131
|
## Execution
|
|
218
132
|
|
|
219
133
|
When running any workflow:
|
|
220
|
-
1. LOAD
|
|
221
|
-
2.
|
|
222
|
-
3.
|
|
223
|
-
4. Save outputs after EACH section
|
|
134
|
+
1. LOAD the workflow.md file at the path shown above
|
|
135
|
+
2. READ its entire contents and follow its directions exactly
|
|
136
|
+
3. Save outputs after EACH section
|
|
224
137
|
|
|
225
138
|
## Modes
|
|
226
139
|
- Normal: Full interaction
|
|
@@ -261,58 +174,6 @@ When running any workflow:
|
|
|
261
174
|
skip_empty_lines: true,
|
|
262
175
|
});
|
|
263
176
|
}
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* Write workflow command artifacts using underscore format (Windows-compatible)
|
|
267
|
-
* Creates flat files like: bmad_bmm_correct-course.md
|
|
268
|
-
*
|
|
269
|
-
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
|
270
|
-
* @param {Array} artifacts - Workflow artifacts
|
|
271
|
-
* @returns {number} Count of commands written
|
|
272
|
-
*/
|
|
273
|
-
async writeColonArtifacts(baseCommandsDir, artifacts) {
|
|
274
|
-
let writtenCount = 0;
|
|
275
|
-
|
|
276
|
-
for (const artifact of artifacts) {
|
|
277
|
-
if (artifact.type === 'workflow-command') {
|
|
278
|
-
// Convert relativePath to underscore format: bmm/workflows/correct-course.md → bmad_bmm_correct-course.md
|
|
279
|
-
const flatName = toColonPath(artifact.relativePath);
|
|
280
|
-
const commandPath = path.join(baseCommandsDir, flatName);
|
|
281
|
-
await fs.ensureDir(path.dirname(commandPath));
|
|
282
|
-
await fs.writeFile(commandPath, artifact.content);
|
|
283
|
-
writtenCount++;
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return writtenCount;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Write workflow command artifacts using dash format (NEW STANDARD)
|
|
292
|
-
* Creates flat files like: bmad-bmm-correct-course.md
|
|
293
|
-
*
|
|
294
|
-
* Note: Workflows do NOT have bmad-agent- prefix - only agents do.
|
|
295
|
-
*
|
|
296
|
-
* @param {string} baseCommandsDir - Base commands directory for the IDE
|
|
297
|
-
* @param {Array} artifacts - Workflow artifacts
|
|
298
|
-
* @returns {number} Count of commands written
|
|
299
|
-
*/
|
|
300
|
-
async writeDashArtifacts(baseCommandsDir, artifacts) {
|
|
301
|
-
let writtenCount = 0;
|
|
302
|
-
|
|
303
|
-
for (const artifact of artifacts) {
|
|
304
|
-
if (artifact.type === 'workflow-command') {
|
|
305
|
-
// Convert relativePath to dash format: bmm/workflows/correct-course.md → bmad-bmm-correct-course.md
|
|
306
|
-
const flatName = toDashPath(artifact.relativePath);
|
|
307
|
-
const commandPath = path.join(baseCommandsDir, flatName);
|
|
308
|
-
await fs.ensureDir(path.dirname(commandPath));
|
|
309
|
-
await fs.writeFile(commandPath, artifact.content);
|
|
310
|
-
writtenCount++;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return writtenCount;
|
|
315
|
-
}
|
|
316
177
|
}
|
|
317
178
|
|
|
318
179
|
module.exports = { WorkflowCommandGenerator };
|
|
@@ -6,7 +6,7 @@ description: '{{description}}'
|
|
|
6
6
|
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
|
|
7
7
|
|
|
8
8
|
<agent-activation CRITICAL="TRUE">
|
|
9
|
-
1. LOAD the FULL agent file from
|
|
9
|
+
1. LOAD the FULL agent file from {project-root}/_bmad/{{module}}/agents/{{path}}
|
|
10
10
|
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
|
|
11
11
|
3. Execute ALL activation steps exactly as written in the agent file
|
|
12
12
|
4. Follow the agent's persona and menu system precisely
|
|
@@ -3,4 +3,4 @@ name: '{{name}}'
|
|
|
3
3
|
description: '{{description}}'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL
|
|
6
|
+
IT IS CRITICAL THAT YOU FOLLOW THIS COMMAND: LOAD the FULL {project-root}/{{bmadFolderName}}/{{path}}, READ its entire contents and follow its directions exactly!
|
|
@@ -762,14 +762,8 @@ class ModuleManager {
|
|
|
762
762
|
}
|
|
763
763
|
}
|
|
764
764
|
|
|
765
|
-
//
|
|
766
|
-
|
|
767
|
-
await fs.ensureDir(path.dirname(targetFile));
|
|
768
|
-
await this.copyWorkflowYamlStripped(sourceFile, targetFile);
|
|
769
|
-
} else {
|
|
770
|
-
// Copy the file with placeholder replacement
|
|
771
|
-
await this.copyFileWithPlaceholderReplacement(sourceFile, targetFile);
|
|
772
|
-
}
|
|
765
|
+
// Copy the file with placeholder replacement
|
|
766
|
+
await this.copyFileWithPlaceholderReplacement(sourceFile, targetFile);
|
|
773
767
|
|
|
774
768
|
// Track the file if callback provided
|
|
775
769
|
if (fileTrackingCallback) {
|
|
@@ -778,92 +772,6 @@ class ModuleManager {
|
|
|
778
772
|
}
|
|
779
773
|
}
|
|
780
774
|
|
|
781
|
-
/**
|
|
782
|
-
* Copy workflow.yaml file with web_bundle section stripped
|
|
783
|
-
* Preserves comments, formatting, and line breaks
|
|
784
|
-
* @param {string} sourceFile - Source workflow.yaml file path
|
|
785
|
-
* @param {string} targetFile - Target workflow.yaml file path
|
|
786
|
-
*/
|
|
787
|
-
async copyWorkflowYamlStripped(sourceFile, targetFile) {
|
|
788
|
-
// Read the source YAML file
|
|
789
|
-
let yamlContent = await fs.readFile(sourceFile, 'utf8');
|
|
790
|
-
|
|
791
|
-
// IMPORTANT: Replace escape sequence and placeholder BEFORE parsing YAML
|
|
792
|
-
// Otherwise parsing will fail on the placeholder
|
|
793
|
-
yamlContent = yamlContent.replaceAll('_bmad', this.bmadFolderName);
|
|
794
|
-
|
|
795
|
-
try {
|
|
796
|
-
// First check if web_bundle exists by parsing
|
|
797
|
-
const workflowConfig = yaml.parse(yamlContent);
|
|
798
|
-
|
|
799
|
-
if (workflowConfig.web_bundle === undefined) {
|
|
800
|
-
// No web_bundle section, just write (placeholders already replaced above)
|
|
801
|
-
await fs.writeFile(targetFile, yamlContent, 'utf8');
|
|
802
|
-
return;
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
// Find the line that starts web_bundle
|
|
806
|
-
const lines = yamlContent.split('\n');
|
|
807
|
-
let startIdx = -1;
|
|
808
|
-
let endIdx = -1;
|
|
809
|
-
let baseIndent = 0;
|
|
810
|
-
|
|
811
|
-
// Find the start of web_bundle section
|
|
812
|
-
for (const [i, line] of lines.entries()) {
|
|
813
|
-
const match = line.match(/^(\s*)web_bundle:/);
|
|
814
|
-
if (match) {
|
|
815
|
-
startIdx = i;
|
|
816
|
-
baseIndent = match[1].length;
|
|
817
|
-
break;
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
|
|
821
|
-
if (startIdx === -1) {
|
|
822
|
-
// web_bundle not found in text (shouldn't happen), copy as-is
|
|
823
|
-
await fs.writeFile(targetFile, yamlContent, 'utf8');
|
|
824
|
-
return;
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
// Find the end of web_bundle section
|
|
828
|
-
// It ends when we find a line with same or less indentation that's not empty/comment
|
|
829
|
-
endIdx = startIdx;
|
|
830
|
-
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
831
|
-
const line = lines[i];
|
|
832
|
-
|
|
833
|
-
// Skip empty lines and comments
|
|
834
|
-
if (line.trim() === '' || line.trim().startsWith('#')) {
|
|
835
|
-
continue;
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
// Check indentation
|
|
839
|
-
const indent = line.match(/^(\s*)/)[1].length;
|
|
840
|
-
if (indent <= baseIndent) {
|
|
841
|
-
// Found next section at same or lower indentation
|
|
842
|
-
endIdx = i - 1;
|
|
843
|
-
break;
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
// If we didn't find an end, it goes to end of file
|
|
848
|
-
if (endIdx === startIdx) {
|
|
849
|
-
endIdx = lines.length - 1;
|
|
850
|
-
}
|
|
851
|
-
|
|
852
|
-
// Remove the web_bundle section (including the line before if it's just a blank line)
|
|
853
|
-
const newLines = [...lines.slice(0, startIdx), ...lines.slice(endIdx + 1)];
|
|
854
|
-
|
|
855
|
-
// Clean up any double blank lines that might result
|
|
856
|
-
const strippedYaml = newLines.join('\n').replaceAll(/\n\n\n+/g, '\n\n');
|
|
857
|
-
|
|
858
|
-
// Placeholders already replaced at the beginning of this function
|
|
859
|
-
await fs.writeFile(targetFile, strippedYaml, 'utf8');
|
|
860
|
-
} catch {
|
|
861
|
-
// If anything fails, just copy the file as-is
|
|
862
|
-
await prompts.log.warn(` Could not process ${path.basename(sourceFile)}, copying as-is`);
|
|
863
|
-
await fs.copy(sourceFile, targetFile, { overwrite: true });
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
|
|
867
775
|
/**
|
|
868
776
|
* Compile .agent.yaml files to .md format in modules
|
|
869
777
|
* @param {string} sourcePath - Source module path
|
|
@@ -1165,13 +1073,11 @@ class ModuleManager {
|
|
|
1165
1073
|
await prompts.log.message(` Processing: ${agentFile}`);
|
|
1166
1074
|
|
|
1167
1075
|
for (const item of workflowInstallItems) {
|
|
1168
|
-
const sourceWorkflowPath = item.
|
|
1076
|
+
const sourceWorkflowPath = item.exec; // Where to copy FROM
|
|
1169
1077
|
const installWorkflowPath = item['workflow-install']; // Where to copy TO
|
|
1170
1078
|
|
|
1171
1079
|
// Parse SOURCE workflow path
|
|
1172
|
-
//
|
|
1173
|
-
// Example: {project-root}/_bmad/bmm/workflows/4-implementation/create-story/workflow.yaml
|
|
1174
|
-
// Or: {project-root}/bmad/bmm/workflows/4-implementation/create-story/workflow.yaml
|
|
1080
|
+
// Example: {project-root}/_bmad/bmm/workflows/4-implementation/create-story/workflow.md
|
|
1175
1081
|
const sourceMatch = sourceWorkflowPath.match(/\{project-root\}\/(?:_bmad)\/([^/]+)\/workflows\/(.+)/);
|
|
1176
1082
|
if (!sourceMatch) {
|
|
1177
1083
|
await prompts.log.warn(` Could not parse workflow path: ${sourceWorkflowPath}`);
|
|
@@ -1181,9 +1087,8 @@ class ModuleManager {
|
|
|
1181
1087
|
const [, sourceModule, sourceWorkflowSubPath] = sourceMatch;
|
|
1182
1088
|
|
|
1183
1089
|
// Parse INSTALL workflow path
|
|
1184
|
-
//
|
|
1185
|
-
|
|
1186
|
-
const installMatch = installWorkflowPath.match(/\{project-root\}\/(_bmad)\/([^/]+)\/workflows\/(.+)/);
|
|
1090
|
+
// Example: {project-root}/_bmad/bmgd/workflows/4-production/create-story/workflow.md
|
|
1091
|
+
const installMatch = installWorkflowPath.match(/\{project-root\}\/(?:_bmad)\/([^/]+)\/workflows\/(.+)/);
|
|
1187
1092
|
if (!installMatch) {
|
|
1188
1093
|
await prompts.log.warn(` Could not parse workflow-install path: ${installWorkflowPath}`);
|
|
1189
1094
|
continue;
|
|
@@ -1192,9 +1097,9 @@ class ModuleManager {
|
|
|
1192
1097
|
const installWorkflowSubPath = installMatch[2];
|
|
1193
1098
|
|
|
1194
1099
|
const sourceModulePath = getModulePath(sourceModule);
|
|
1195
|
-
const actualSourceWorkflowPath = path.join(sourceModulePath, 'workflows', sourceWorkflowSubPath.replace(/\/workflow\.
|
|
1100
|
+
const actualSourceWorkflowPath = path.join(sourceModulePath, 'workflows', sourceWorkflowSubPath.replace(/\/workflow\.md$/, ''));
|
|
1196
1101
|
|
|
1197
|
-
const actualDestWorkflowPath = path.join(targetPath, 'workflows', installWorkflowSubPath.replace(/\/workflow\.
|
|
1102
|
+
const actualDestWorkflowPath = path.join(targetPath, 'workflows', installWorkflowSubPath.replace(/\/workflow\.md$/, ''));
|
|
1198
1103
|
|
|
1199
1104
|
// Check if source workflow exists
|
|
1200
1105
|
if (!(await fs.pathExists(actualSourceWorkflowPath))) {
|
|
@@ -1204,18 +1109,12 @@ class ModuleManager {
|
|
|
1204
1109
|
|
|
1205
1110
|
// Copy the entire workflow folder
|
|
1206
1111
|
await prompts.log.message(
|
|
1207
|
-
` Vendoring: ${sourceModule}/workflows/${sourceWorkflowSubPath.replace(/\/workflow\.
|
|
1112
|
+
` Vendoring: ${sourceModule}/workflows/${sourceWorkflowSubPath.replace(/\/workflow\.md$/, '')} → ${moduleName}/workflows/${installWorkflowSubPath.replace(/\/workflow\.md$/, '')}`,
|
|
1208
1113
|
);
|
|
1209
1114
|
|
|
1210
1115
|
await fs.ensureDir(path.dirname(actualDestWorkflowPath));
|
|
1211
1116
|
// Copy the workflow directory recursively with placeholder replacement
|
|
1212
1117
|
await this.copyDirectoryWithPlaceholderReplacement(actualSourceWorkflowPath, actualDestWorkflowPath);
|
|
1213
|
-
|
|
1214
|
-
// Update the workflow.yaml config_source reference
|
|
1215
|
-
const workflowYamlPath = path.join(actualDestWorkflowPath, 'workflow.yaml');
|
|
1216
|
-
if (await fs.pathExists(workflowYamlPath)) {
|
|
1217
|
-
await this.updateWorkflowConfigSource(workflowYamlPath, moduleName);
|
|
1218
|
-
}
|
|
1219
1118
|
}
|
|
1220
1119
|
}
|
|
1221
1120
|
|
|
@@ -1224,28 +1123,6 @@ class ModuleManager {
|
|
|
1224
1123
|
}
|
|
1225
1124
|
}
|
|
1226
1125
|
|
|
1227
|
-
/**
|
|
1228
|
-
* Update workflow.yaml config_source to point to new module
|
|
1229
|
-
* @param {string} workflowYamlPath - Path to workflow.yaml file
|
|
1230
|
-
* @param {string} newModuleName - New module name to reference
|
|
1231
|
-
*/
|
|
1232
|
-
async updateWorkflowConfigSource(workflowYamlPath, newModuleName) {
|
|
1233
|
-
let yamlContent = await fs.readFile(workflowYamlPath, 'utf8');
|
|
1234
|
-
|
|
1235
|
-
// Replace config_source: "{project-root}/_bmad/OLD_MODULE/config.yaml"
|
|
1236
|
-
// with config_source: "{project-root}/_bmad/NEW_MODULE/config.yaml"
|
|
1237
|
-
// Note: At this point _bmad has already been replaced with actual folder name
|
|
1238
|
-
const configSourcePattern = /config_source:\s*["']?\{project-root\}\/[^/]+\/[^/]+\/config\.yaml["']?/g;
|
|
1239
|
-
const newConfigSource = `config_source: "{project-root}/${this.bmadFolderName}/${newModuleName}/config.yaml"`;
|
|
1240
|
-
|
|
1241
|
-
const updatedYaml = yamlContent.replaceAll(configSourcePattern, newConfigSource);
|
|
1242
|
-
|
|
1243
|
-
if (updatedYaml !== yamlContent) {
|
|
1244
|
-
await fs.writeFile(workflowYamlPath, updatedYaml, 'utf8');
|
|
1245
|
-
await prompts.log.message(` Updated config_source to: ${this.bmadFolderName}/${newModuleName}/config.yaml`);
|
|
1246
|
-
}
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
1126
|
/**
|
|
1250
1127
|
* Create directories declared in module.yaml's `directories` key
|
|
1251
1128
|
* This replaces the security-risky module installer pattern with declarative config
|
|
@@ -147,7 +147,6 @@ function buildMenuXml(menuItems) {
|
|
|
147
147
|
const attrs = [`cmd="${trigger}"`];
|
|
148
148
|
|
|
149
149
|
// Add handler attributes
|
|
150
|
-
if (item.workflow) attrs.push(`workflow="${item.workflow}"`);
|
|
151
150
|
if (item.exec) attrs.push(`exec="${item.exec}"`);
|
|
152
151
|
if (item.tmpl) attrs.push(`tmpl="${item.tmpl}"`);
|
|
153
152
|
if (item.data) attrs.push(`data="${item.data}"`);
|
|
@@ -187,8 +186,6 @@ function buildNestedHandlers(triggers) {
|
|
|
187
186
|
|
|
188
187
|
// Add handler attributes based on exec data
|
|
189
188
|
if (execData.route) attrs.push(`exec="${execData.route}"`);
|
|
190
|
-
if (execData.workflow) attrs.push(`workflow="${execData.workflow}"`);
|
|
191
|
-
if (execData['validate-workflow']) attrs.push(`validate-workflow="${execData['validate-workflow']}"`);
|
|
192
189
|
if (execData.action) attrs.push(`action="${execData.action}"`);
|
|
193
190
|
if (execData.data) attrs.push(`data="${execData.data}"`);
|
|
194
191
|
if (execData.tmpl) attrs.push(`tmpl="${execData.tmpl}"`);
|
|
@@ -212,7 +209,6 @@ function processExecArray(execArray) {
|
|
|
212
209
|
const result = {
|
|
213
210
|
description: '',
|
|
214
211
|
route: null,
|
|
215
|
-
workflow: null,
|
|
216
212
|
data: null,
|
|
217
213
|
action: null,
|
|
218
214
|
type: null,
|
|
@@ -229,12 +225,7 @@ function processExecArray(execArray) {
|
|
|
229
225
|
}
|
|
230
226
|
|
|
231
227
|
if (exec.route) {
|
|
232
|
-
|
|
233
|
-
if (exec.route.endsWith('.yaml') || exec.route.endsWith('.yml')) {
|
|
234
|
-
result.workflow = exec.route;
|
|
235
|
-
} else {
|
|
236
|
-
result.route = exec.route;
|
|
237
|
-
}
|
|
228
|
+
result.route = exec.route;
|
|
238
229
|
}
|
|
239
230
|
|
|
240
231
|
if (exec.data !== null && exec.data !== undefined) {
|
|
@@ -39,16 +39,10 @@ class AgentAnalyzer {
|
|
|
39
39
|
if (Array.isArray(execArray)) {
|
|
40
40
|
for (const exec of execArray) {
|
|
41
41
|
if (exec.route) {
|
|
42
|
-
|
|
43
|
-
if (exec.route.endsWith('.yaml') || exec.route.endsWith('.yml')) {
|
|
44
|
-
profile.usedAttributes.add('workflow');
|
|
45
|
-
} else {
|
|
46
|
-
profile.usedAttributes.add('exec');
|
|
47
|
-
}
|
|
42
|
+
profile.usedAttributes.add('exec');
|
|
48
43
|
}
|
|
49
|
-
if (exec.workflow) profile.usedAttributes.add('workflow');
|
|
50
44
|
if (exec.action) profile.usedAttributes.add('action');
|
|
51
|
-
if (exec.type && ['exec', 'action'
|
|
45
|
+
if (exec.type && ['exec', 'action'].includes(exec.type)) {
|
|
52
46
|
profile.usedAttributes.add(exec.type);
|
|
53
47
|
}
|
|
54
48
|
}
|
|
@@ -57,12 +51,6 @@ class AgentAnalyzer {
|
|
|
57
51
|
}
|
|
58
52
|
} else {
|
|
59
53
|
// Check for each possible attribute in legacy items
|
|
60
|
-
if (item.workflow) {
|
|
61
|
-
profile.usedAttributes.add('workflow');
|
|
62
|
-
}
|
|
63
|
-
if (item['validate-workflow']) {
|
|
64
|
-
profile.usedAttributes.add('validate-workflow');
|
|
65
|
-
}
|
|
66
54
|
if (item.exec) {
|
|
67
55
|
profile.usedAttributes.add('exec');
|
|
68
56
|
}
|