ma-agents 2.22.2 → 3.0.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/.opencode/skills/.ma-agents.json +99 -99
- package/lib/bmad-cache/bmb/.claude-plugin/marketplace.json +22 -0
- package/lib/bmad-cache/bmb/.markdownlint-cli2.yaml +1 -0
- package/lib/bmad-cache/bmb/_git_preserved/index +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/logs/HEAD +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/logs/refs/heads/main +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/logs/refs/remotes/origin/HEAD +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-0de89e0854d5b2b3b3b0c1ee56eee73a739f15e7.idx +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-0de89e0854d5b2b3b3b0c1ee56eee73a739f15e7.pack +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-0de89e0854d5b2b3b3b0c1ee56eee73a739f15e7.rev +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/bmb/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/bmb/package-lock.json +2 -2
- package/lib/bmad-cache/bmb/package.json +7 -4
- package/lib/bmad-cache/bmb/skills/bmad-agent-builder/scripts/generate-html-report.py +534 -0
- package/lib/bmad-cache/bmb/{src/skills → skills}/bmad-agent-builder/scripts/prepass-execution-deps.py +4 -35
- package/lib/bmad-cache/bmb/{src/skills → skills}/bmad-agent-builder/scripts/prepass-prompt-metrics.py +2 -75
- package/lib/bmad-cache/bmb/{src/skills → skills}/bmad-agent-builder/scripts/prepass-structure-capabilities.py +3 -194
- package/lib/bmad-cache/bmb/{src/skills → skills}/bmad-agent-builder/scripts/scan-path-standards.py +104 -18
- package/lib/bmad-cache/bmb/skills/bmad-builder-setup/assets/module-help.csv +6 -0
- package/lib/bmad-cache/bmb/skills/bmad-builder-setup/assets/module.yaml +20 -0
- package/lib/bmad-cache/bmb/skills/bmad-builder-setup/scripts/cleanup-legacy.py +259 -0
- package/lib/bmad-cache/bmb/skills/bmad-builder-setup/scripts/merge-config.py +408 -0
- package/lib/bmad-cache/bmb/skills/bmad-builder-setup/scripts/merge-help-csv.py +220 -0
- package/lib/bmad-cache/bmb/skills/bmad-builder-setup/scripts/tests/test-cleanup-legacy.py +429 -0
- package/lib/bmad-cache/bmb/skills/bmad-builder-setup/scripts/tests/test-merge-config.py +644 -0
- package/lib/bmad-cache/bmb/skills/bmad-builder-setup/scripts/tests/test-merge-help-csv.py +237 -0
- package/lib/bmad-cache/bmb/skills/bmad-workflow-builder/scripts/generate-html-report.py +539 -0
- package/lib/bmad-cache/bmb/{src/skills → skills}/bmad-workflow-builder/scripts/prepass-execution-deps.py +5 -30
- package/lib/bmad-cache/bmb/{src/skills → skills}/bmad-workflow-builder/scripts/prepass-workflow-integrity.py +0 -5
- package/lib/bmad-cache/bmb/{src/skills → skills}/bmad-workflow-builder/scripts/scan-path-standards.py +103 -16
- package/lib/bmad-cache/bmb/skills/module-help.csv +6 -0
- package/lib/bmad-cache/bmb/skills/module.yaml +20 -0
- package/lib/bmad-cache/bmb/tools/validate-doc-links.cjs +407 -0
- package/lib/bmad-cache/bmb/tools/validate-file-refs.mjs +1 -1
- package/lib/bmad-cache/cache-manifest.json +16 -10
- package/lib/bmad-cache/cis/.claude-plugin/marketplace.json +33 -0
- package/lib/bmad-cache/cis/_git_preserved/index +0 -0
- package/lib/bmad-cache/cis/_git_preserved/logs/HEAD +1 -1
- package/lib/bmad-cache/cis/_git_preserved/logs/refs/heads/main +1 -1
- package/lib/bmad-cache/cis/_git_preserved/logs/refs/remotes/origin/HEAD +1 -1
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-9d60aae6b09bbea0d0c5e79fdbe96e8f66de84e6.idx +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/{pack-157d7eb8d527233a8607d926fc74ebf87f2ae0d3.pack → pack-9d60aae6b09bbea0d0c5e79fdbe96e8f66de84e6.pack} +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-9d60aae6b09bbea0d0c5e79fdbe96e8f66de84e6.rev +0 -0
- package/lib/bmad-cache/cis/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/cis/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/cis/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/cis/package-lock.json +17015 -0
- package/lib/bmad-cache/cis/package.json +3 -4
- package/lib/bmad-cache/cis/src/module-help.csv +6 -6
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-brainstorming-coach/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-creative-problem-solver/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-design-thinking-coach/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-innovation-strategist/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-presentation-master/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-cache/cis/src/skills/bmad-cis-agent-storyteller/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-cache/gds/.claude-plugin/marketplace.json +58 -0
- package/lib/bmad-cache/gds/_git_preserved/index +0 -0
- package/lib/bmad-cache/gds/_git_preserved/logs/HEAD +1 -1
- package/lib/bmad-cache/gds/_git_preserved/logs/refs/heads/main +1 -1
- package/lib/bmad-cache/gds/_git_preserved/logs/refs/remotes/origin/HEAD +1 -1
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-8099a88fca0ad946a573316a00887a2921ca1712.idx +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/{pack-44faafb9245b4ca17ad81bd6c9e6fc52fb5915a1.pack → pack-8099a88fca0ad946a573316a00887a2921ca1712.pack} +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-8099a88fca0ad946a573316a00887a2921ca1712.rev +0 -0
- package/lib/bmad-cache/gds/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/gds/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/gds/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/gds/package.json +1 -0
- package/lib/bmad-cache/gds/src/module-help.csv +35 -35
- package/lib/bmad-cache/tea/.claude-plugin/marketplace.json +33 -0
- package/lib/bmad-cache/tea/CHANGELOG.md +2 -14
- package/lib/bmad-cache/tea/README.md +31 -18
- package/lib/bmad-cache/tea/_git_preserved/index +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-d243f64f83b36190434d68872a69a40870c53030.idx +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/{pack-96ec1ce3a9ef4c891e00e060795b4434ba8f7163.pack → pack-d243f64f83b36190434d68872a69a40870c53030.pack} +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-d243f64f83b36190434d68872a69a40870c53030.rev +0 -0
- package/lib/bmad-cache/tea/_git_preserved/packed-refs +1 -1
- package/lib/bmad-cache/tea/_git_preserved/refs/heads/main +1 -1
- package/lib/bmad-cache/tea/_git_preserved/refs/tags/v1.7.3 +1 -0
- package/lib/bmad-cache/tea/_git_preserved/shallow +1 -1
- package/lib/bmad-cache/tea/docs/explanation/knowledge-base-system.md +5 -5
- package/lib/bmad-cache/tea/docs/explanation/step-file-architecture.md +2 -2
- package/lib/bmad-cache/tea/docs/explanation/tea-overview.md +3 -3
- package/lib/bmad-cache/tea/docs/glossary/index.md +1 -1
- package/lib/bmad-cache/tea/docs/how-to/customization/extend-tea-with-custom-workflows.md +73 -0
- package/lib/bmad-cache/tea/docs/how-to/workflows/teach-me-testing.md +7 -7
- package/lib/bmad-cache/tea/docs/index.md +2 -1
- package/lib/bmad-cache/tea/docs/reference/commands.md +4 -1
- package/lib/bmad-cache/tea/docs/reference/configuration.md +37 -15
- package/lib/bmad-cache/tea/docs/reference/knowledge-base.md +75 -73
- package/lib/bmad-cache/tea/docs/reference/troubleshooting.md +32 -19
- package/lib/bmad-cache/tea/docs/tutorials/learn-testing-tea-academy.md +3 -3
- package/lib/bmad-cache/tea/package-lock.json +2 -2
- package/lib/bmad-cache/tea/package.json +2 -1
- package/lib/bmad-cache/tea/src/agents/bmad-tea/SKILL.md +70 -0
- package/lib/bmad-cache/tea/src/agents/bmad-tea/bmad-skill-manifest.yaml +14 -0
- package/lib/bmad-cache/tea/src/module-help.csv +10 -10
- package/lib/bmad-cache/tea/src/module.yaml +8 -8
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/checklist.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/data/curriculum.yaml +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/data/session-content-map.yaml +26 -14
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/data/tea-resources-index.yaml +108 -73
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/instructions.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-03-session-menu.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-01.md +3 -3
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-04-session-07.md +14 -6
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/steps-c/step-05-completion.md +3 -3
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/templates/certificate-template.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-teach-me-testing/workflow-plan-teach-me-testing.md +8 -8
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/atdd-checklist-template.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-01-preflight-and-context.md +3 -3
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-atdd/steps-c/step-04a-subagent-api-failing.md +9 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-01-preflight-and-context.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-automate/steps-c/step-03b-subagent-e2e.md +2 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-02-generate-pipeline.md +6 -0
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-ci/steps-c/step-03-configure-quality-gates.md +6 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-framework/steps-c/step-03-scaffold-framework.md +3 -2
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-nfr/steps-c/step-01-load-context.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-design/steps-c/step-02-load-context.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/steps-c/step-01-load-context.md +1 -1
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-test-review/test-review-template.md +11 -11
- package/lib/bmad-cache/tea/src/workflows/testarch/bmad-testarch-trace/steps-c/step-01-load-context.md +1 -1
- package/lib/bmad-cache/tea/test/test-installation-components.js +85 -21
- package/lib/bmad-cache/tea/test/test-knowledge-base.js +1 -1
- package/lib/bmad-cache/tea/tools/validate-agent-schema.js +105 -5
- package/lib/bmad-cache/wds/.claude-plugin/marketplace.json +35 -0
- package/lib/bmad-cache/wds/.markdownlint-cli2.yaml +38 -0
- package/lib/bmad-cache/wds/.nvmrc +1 -0
- package/lib/bmad-cache/wds/.prettierignore +9 -0
- package/lib/bmad-cache/wds/LICENSE +27 -0
- package/lib/bmad-cache/wds/README.md +126 -0
- package/lib/bmad-cache/wds/_git_preserved/HEAD +1 -0
- package/lib/bmad-cache/wds/_git_preserved/config +13 -0
- package/lib/bmad-cache/wds/_git_preserved/description +1 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/applypatch-msg.sample +15 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/commit-msg.sample +24 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/fsmonitor-watchman.sample +174 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/post-update.sample +8 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/pre-applypatch.sample +14 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/pre-commit.sample +49 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/pre-merge-commit.sample +13 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/pre-push.sample +53 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/pre-rebase.sample +169 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/pre-receive.sample +24 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/prepare-commit-msg.sample +42 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/push-to-checkout.sample +78 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/sendemail-validate.sample +77 -0
- package/lib/bmad-cache/wds/_git_preserved/hooks/update.sample +128 -0
- package/lib/bmad-cache/wds/_git_preserved/index +0 -0
- package/lib/bmad-cache/wds/_git_preserved/info/exclude +6 -0
- package/lib/bmad-cache/wds/_git_preserved/logs/HEAD +1 -0
- package/lib/bmad-cache/wds/_git_preserved/logs/refs/heads/main +1 -0
- package/lib/bmad-cache/wds/_git_preserved/logs/refs/remotes/origin/HEAD +1 -0
- package/lib/bmad-cache/wds/_git_preserved/objects/pack/pack-92d32f26e3a97a0786dcea5cb2c24bf90384521c.idx +0 -0
- package/lib/bmad-cache/wds/_git_preserved/objects/pack/pack-92d32f26e3a97a0786dcea5cb2c24bf90384521c.pack +0 -0
- package/lib/bmad-cache/wds/_git_preserved/objects/pack/pack-92d32f26e3a97a0786dcea5cb2c24bf90384521c.rev +0 -0
- package/lib/bmad-cache/wds/_git_preserved/packed-refs +2 -0
- package/lib/bmad-cache/wds/_git_preserved/refs/heads/main +1 -0
- package/lib/bmad-cache/wds/_git_preserved/refs/remotes/origin/HEAD +1 -0
- package/lib/bmad-cache/wds/_git_preserved/shallow +1 -0
- package/lib/bmad-cache/wds/eslint.config.mjs +152 -0
- package/lib/bmad-cache/wds/package.json +82 -0
- package/lib/bmad-cache/wds/prettier.config.mjs +32 -0
- package/lib/bmad-cache/wds/src/agents/wds-agent-freya-ux/bmad-skill-manifest.yaml +12 -0
- package/lib/bmad-cache/wds/src/agents/wds-agent-saga-analyst/bmad-skill-manifest.yaml +12 -0
- package/lib/bmad-cache/wds/src/module-help.csv +18 -0
- package/lib/bmad-cache/wds/src/module.yaml +148 -0
- package/lib/bmad-cache/wds/src/workflows/wds-1-project-brief/bmad-skill-manifest.yaml +1 -0
- package/lib/bmad-cache/wds/src/workflows/wds-1-project-brief/templates/platform-requirements.template.yaml +69 -0
- package/lib/bmad-cache/wds/src/workflows/wds-2-trigger-mapping/bmad-skill-manifest.yaml +1 -0
- package/lib/bmad-cache/wds/src/workflows/wds-3-scenarios/bmad-skill-manifest.yaml +1 -0
- package/lib/bmad-cache/wds/src/workflows/wds-4-ux-design/bmad-skill-manifest.yaml +1 -0
- package/lib/bmad-cache/wds/src/workflows/wds-4-ux-design/templates/design-delivery.template.yaml +104 -0
- package/lib/bmad-cache/wds/src/workflows/wds-4-ux-design/templates/test-scenario.template.yaml +192 -0
- package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/bmad-skill-manifest.yaml +1 -0
- package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/components/dev-mode.css +164 -0
- package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/components/dev-mode.html +18 -0
- package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/components/dev-mode.js +430 -0
- package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/demo-data-template.json +63 -0
- package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/page-template.html +465 -0
- package/lib/bmad-cache/wds/src/workflows/wds-5-agentic-development/templates/work-file-template.yaml +264 -0
- package/lib/bmad-cache/wds/src/workflows/wds-6-asset-generation/bmad-skill-manifest.yaml +1 -0
- package/lib/bmad-cache/wds/src/workflows/wds-7-design-system/bmad-skill-manifest.yaml +1 -0
- package/lib/bmad-cache/wds/src/workflows/wds-7-design-system/templates/catalog.template.html +363 -0
- package/lib/bmad-cache/wds/src/workflows/wds-8-product-evolution/bmad-skill-manifest.yaml +1 -0
- package/lib/bmad-customize/bmm-architect.customize.yaml +6 -0
- package/lib/bmad-customize/bmm-bmad-master.customize.yaml +6 -0
- package/lib/bmad-customize/bmm-dev.customize.yaml +6 -0
- package/lib/bmad-customize/bmm-pm.customize.yaml +6 -0
- package/lib/bmad-customize/bmm-qa.customize.yaml +6 -0
- package/lib/bmad-customize/bmm-sm.customize.yaml +6 -0
- package/lib/bmad-customize/bmm-tech-writer.customize.yaml +6 -0
- package/lib/bmad-customize/bmm-ux-designer.customize.yaml +6 -0
- package/lib/bmad-extension/module-help.csv +37 -7
- package/lib/bmad-extension/module.yaml +4 -2
- package/lib/bmad-extension/skills/add-sprint/.gitkeep +0 -0
- package/lib/bmad-extension/skills/add-sprint/SKILL.md +121 -0
- package/lib/bmad-extension/skills/add-sprint/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/add-to-sprint/.gitkeep +0 -0
- package/lib/bmad-extension/skills/add-to-sprint/SKILL.md +215 -0
- package/lib/bmad-extension/skills/add-to-sprint/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-cyber/.gitkeep +0 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-cyber/SKILL.md +44 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-cyber/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-devops/.gitkeep +0 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-devops/SKILL.md +44 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-devops/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-mil498/.gitkeep +0 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-mil498/SKILL.md +48 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-mil498/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-sre/.gitkeep +0 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-sre/SKILL.md +44 -0
- package/lib/bmad-extension/skills/bmad-ma-agent-sre/bmad-skill-manifest.yaml +11 -0
- package/lib/bmad-extension/skills/create-bug-story/.gitkeep +0 -0
- package/lib/bmad-extension/skills/create-bug-story/SKILL.md +195 -0
- package/lib/bmad-extension/skills/create-bug-story/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/cyber-generate-certs/.gitkeep +0 -0
- package/lib/bmad-extension/skills/cyber-generate-certs/SKILL.md +27 -0
- package/lib/bmad-extension/skills/cyber-generate-certs/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/cyber-immunity-estimation/.gitkeep +0 -0
- package/lib/bmad-extension/skills/cyber-immunity-estimation/SKILL.md +29 -0
- package/lib/bmad-extension/skills/cyber-immunity-estimation/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/cyber-security-audit/.gitkeep +0 -0
- package/lib/bmad-extension/skills/cyber-security-audit/SKILL.md +27 -0
- package/lib/bmad-extension/skills/cyber-security-audit/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/cyber-vault-secrets/.gitkeep +0 -0
- package/lib/bmad-extension/skills/cyber-vault-secrets/SKILL.md +28 -0
- package/lib/bmad-extension/skills/cyber-vault-secrets/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/cyber-verify-docker-users/.gitkeep +0 -0
- package/lib/bmad-extension/skills/cyber-verify-docker-users/SKILL.md +23 -0
- package/lib/bmad-extension/skills/cyber-verify-docker-users/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/cyber-verify-image-signature/.gitkeep +0 -0
- package/lib/bmad-extension/skills/cyber-verify-image-signature/SKILL.md +22 -0
- package/lib/bmad-extension/skills/cyber-verify-image-signature/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/cyber-vulnerability-scan/.gitkeep +0 -0
- package/lib/bmad-extension/skills/cyber-vulnerability-scan/SKILL.md +28 -0
- package/lib/bmad-extension/skills/cyber-vulnerability-scan/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/devops-configure-infrastructure/.gitkeep +0 -0
- package/lib/bmad-extension/skills/devops-configure-infrastructure/SKILL.md +27 -0
- package/lib/bmad-extension/skills/devops-configure-infrastructure/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/devops-disconnected-deployment/.gitkeep +0 -0
- package/lib/bmad-extension/skills/devops-disconnected-deployment/SKILL.md +27 -0
- package/lib/bmad-extension/skills/devops-disconnected-deployment/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/devops-docker-compose-setup/.gitkeep +0 -0
- package/lib/bmad-extension/skills/devops-docker-compose-setup/SKILL.md +26 -0
- package/lib/bmad-extension/skills/devops-docker-compose-setup/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/devops-manage-helm/.gitkeep +0 -0
- package/lib/bmad-extension/skills/devops-manage-helm/SKILL.md +28 -0
- package/lib/bmad-extension/skills/devops-manage-helm/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/devops-sign-docker-image/.gitkeep +0 -0
- package/lib/bmad-extension/skills/devops-sign-docker-image/SKILL.md +24 -0
- package/lib/bmad-extension/skills/devops-sign-docker-image/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/mil498-ocd/.gitkeep +0 -0
- package/lib/bmad-extension/skills/mil498-ocd/SKILL.md +30 -0
- package/lib/bmad-extension/skills/mil498-ocd/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension/skills/mil498-ocd/prompts/01-discover-project-artifacts.md +26 -0
- package/lib/bmad-extension/skills/mil498-ocd/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension/skills/mil498-ocd/prompts/03-generate-document.md +90 -0
- package/lib/bmad-extension/skills/mil498-ocd/prompts/04-validate.md +14 -0
- package/lib/bmad-extension/skills/mil498-ocd/prompts/05-review.md +15 -0
- package/lib/bmad-extension/skills/mil498-ocd/prompts/06-save.md +15 -0
- package/lib/bmad-extension/skills/mil498-ocd/template.md +169 -0
- package/lib/bmad-extension/skills/mil498-sdd/.gitkeep +0 -0
- package/lib/bmad-extension/skills/mil498-sdd/SKILL.md +30 -0
- package/lib/bmad-extension/skills/mil498-sdd/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension/skills/mil498-sdd/prompts/01-discover-project-artifacts.md +50 -0
- package/lib/bmad-extension/skills/mil498-sdd/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension/skills/mil498-sdd/prompts/03-generate-document.md +98 -0
- package/lib/bmad-extension/skills/mil498-sdd/prompts/04-validate.md +16 -0
- package/lib/bmad-extension/skills/mil498-sdd/prompts/05-review.md +15 -0
- package/lib/bmad-extension/skills/mil498-sdd/prompts/06-save.md +19 -0
- package/lib/bmad-extension/skills/mil498-sdd/template.md +163 -0
- package/lib/bmad-extension/skills/mil498-sdp/.gitkeep +0 -0
- package/lib/bmad-extension/skills/mil498-sdp/SKILL.md +30 -0
- package/lib/bmad-extension/skills/mil498-sdp/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension/skills/mil498-sdp/prompts/01-discover-project-artifacts.md +32 -0
- package/lib/bmad-extension/skills/mil498-sdp/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension/skills/mil498-sdp/prompts/03-generate-document.md +187 -0
- package/lib/bmad-extension/skills/mil498-sdp/prompts/04-validate.md +13 -0
- package/lib/bmad-extension/skills/mil498-sdp/prompts/05-review.md +15 -0
- package/lib/bmad-extension/skills/mil498-sdp/prompts/06-save.md +14 -0
- package/lib/bmad-extension/skills/mil498-sdp/template.md +307 -0
- package/lib/bmad-extension/skills/mil498-srs/.gitkeep +0 -0
- package/lib/bmad-extension/skills/mil498-srs/SKILL.md +30 -0
- package/lib/bmad-extension/skills/mil498-srs/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension/skills/mil498-srs/prompts/01-discover-project-artifacts.md +42 -0
- package/lib/bmad-extension/skills/mil498-srs/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension/skills/mil498-srs/prompts/03-generate-document.md +100 -0
- package/lib/bmad-extension/skills/mil498-srs/prompts/04-validate.md +16 -0
- package/lib/bmad-extension/skills/mil498-srs/prompts/05-review.md +15 -0
- package/lib/bmad-extension/skills/mil498-srs/prompts/06-save.md +18 -0
- package/lib/bmad-extension/skills/mil498-srs/template.md +219 -0
- package/lib/bmad-extension/skills/mil498-ssdd/.gitkeep +0 -0
- package/lib/bmad-extension/skills/mil498-ssdd/SKILL.md +32 -0
- package/lib/bmad-extension/skills/mil498-ssdd/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension/skills/mil498-ssdd/prompts/01-discover-project-artifacts.md +32 -0
- package/lib/bmad-extension/skills/mil498-ssdd/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension/skills/mil498-ssdd/prompts/03-csci-discovery-interview.md +43 -0
- package/lib/bmad-extension/skills/mil498-ssdd/prompts/04-generate-document.md +96 -0
- package/lib/bmad-extension/skills/mil498-ssdd/prompts/05-validate.md +14 -0
- package/lib/bmad-extension/skills/mil498-ssdd/prompts/06-review.md +16 -0
- package/lib/bmad-extension/skills/mil498-ssdd/prompts/07-save.md +16 -0
- package/lib/bmad-extension/skills/mil498-ssdd/template.md +154 -0
- package/lib/bmad-extension/skills/mil498-sss/.gitkeep +0 -0
- package/lib/bmad-extension/skills/mil498-sss/SKILL.md +31 -0
- package/lib/bmad-extension/skills/mil498-sss/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension/skills/mil498-sss/prompts/01-discover-project-artifacts.md +31 -0
- package/lib/bmad-extension/skills/mil498-sss/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension/skills/mil498-sss/prompts/03-generate-document.md +108 -0
- package/lib/bmad-extension/skills/mil498-sss/prompts/04-validate.md +16 -0
- package/lib/bmad-extension/skills/mil498-sss/prompts/05-review.md +15 -0
- package/lib/bmad-extension/skills/mil498-sss/prompts/06-save.md +15 -0
- package/lib/bmad-extension/skills/mil498-sss/template.md +225 -0
- package/lib/bmad-extension/skills/mil498-std/.gitkeep +0 -0
- package/lib/bmad-extension/skills/mil498-std/SKILL.md +30 -0
- package/lib/bmad-extension/skills/mil498-std/bmad-skill-manifest.yaml +5 -0
- package/lib/bmad-extension/skills/mil498-std/prompts/01-discover-project-artifacts.md +42 -0
- package/lib/bmad-extension/skills/mil498-std/prompts/02-load-template.md +10 -0
- package/lib/bmad-extension/skills/mil498-std/prompts/03-generate-document.md +117 -0
- package/lib/bmad-extension/skills/mil498-std/prompts/04-validate.md +15 -0
- package/lib/bmad-extension/skills/mil498-std/prompts/05-review.md +15 -0
- package/lib/bmad-extension/skills/mil498-std/prompts/06-save.md +15 -0
- package/lib/bmad-extension/skills/mil498-std/template.md +188 -0
- package/lib/bmad-extension/skills/modify-sprint/.gitkeep +0 -0
- package/lib/bmad-extension/skills/modify-sprint/SKILL.md +259 -0
- package/lib/bmad-extension/skills/modify-sprint/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/project-context-expansion/.gitkeep +0 -0
- package/lib/bmad-extension/skills/project-context-expansion/SKILL.md +238 -0
- package/lib/bmad-extension/skills/project-context-expansion/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/sprint-status-view/.gitkeep +0 -0
- package/lib/bmad-extension/skills/sprint-status-view/SKILL.md +202 -0
- package/lib/bmad-extension/skills/sprint-status-view/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/sre-check-deployment-status/.gitkeep +0 -0
- package/lib/bmad-extension/skills/sre-check-deployment-status/SKILL.md +32 -0
- package/lib/bmad-extension/skills/sre-check-deployment-status/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/sre-check-secrets/.gitkeep +0 -0
- package/lib/bmad-extension/skills/sre-check-secrets/SKILL.md +23 -0
- package/lib/bmad-extension/skills/sre-check-secrets/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/sre-check-system-status/.gitkeep +0 -0
- package/lib/bmad-extension/skills/sre-check-system-status/SKILL.md +27 -0
- package/lib/bmad-extension/skills/sre-check-system-status/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/sre-day-2-ops/.gitkeep +0 -0
- package/lib/bmad-extension/skills/sre-day-2-ops/SKILL.md +26 -0
- package/lib/bmad-extension/skills/sre-day-2-ops/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/sre-deployment-strategies/.gitkeep +0 -0
- package/lib/bmad-extension/skills/sre-deployment-strategies/SKILL.md +28 -0
- package/lib/bmad-extension/skills/sre-deployment-strategies/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/sre-fix-deployments/.gitkeep +0 -0
- package/lib/bmad-extension/skills/sre-fix-deployments/SKILL.md +25 -0
- package/lib/bmad-extension/skills/sre-fix-deployments/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad-extension/skills/sre-gitops-status/.gitkeep +0 -0
- package/lib/bmad-extension/skills/sre-gitops-status/SKILL.md +25 -0
- package/lib/bmad-extension/skills/sre-gitops-status/bmad-skill-manifest.yaml +3 -0
- package/lib/bmad.js +541 -1
- package/package.json +3 -3
- package/test/bmad-extension.test.js +115 -69
- package/test/bmad-version-bump.test.js +313 -0
- package/test/convert-agents-to-skills.test.js +245 -0
- package/test/extension-module-restructure.test.js +359 -0
- package/test/integration-verification.test.js +71 -40
- package/test/migration-validation.test.js +499 -0
- package/test/migration.test.js +832 -0
- package/test/story-15-5-workflow-skills.test.js +311 -0
- package/test/yes-flag.test.js +8 -1
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-c6e539e2308f8ed764c5b54b6ab68a67f8a3796b.idx +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-c6e539e2308f8ed764c5b54b6ab68a67f8a3796b.pack +0 -0
- package/lib/bmad-cache/bmb/_git_preserved/objects/pack/pack-c6e539e2308f8ed764c5b54b6ab68a67f8a3796b.rev +0 -0
- package/lib/bmad-cache/bmb/samples/bmad-agent-dream-weaver/bmad-manifest.json +0 -62
- package/lib/bmad-cache/bmb/samples/bmad-excalidraw/bmad-manifest.json +0 -18
- package/lib/bmad-cache/bmb/src/module-help.csv +0 -7
- package/lib/bmad-cache/bmb/src/module.yaml +0 -20
- package/lib/bmad-cache/bmb/src/skills/bmad-agent-builder/bmad-manifest.json +0 -24
- package/lib/bmad-cache/bmb/src/skills/bmad-agent-builder/scripts/bmad-manifest-schema.json +0 -103
- package/lib/bmad-cache/bmb/src/skills/bmad-agent-builder/scripts/generate-html-report.py +0 -1002
- package/lib/bmad-cache/bmb/src/skills/bmad-agent-builder/scripts/manifest.py +0 -420
- package/lib/bmad-cache/bmb/src/skills/bmad-workflow-builder/bmad-manifest.json +0 -23
- package/lib/bmad-cache/bmb/src/skills/bmad-workflow-builder/scripts/bmad-manifest-schema.json +0 -103
- package/lib/bmad-cache/bmb/src/skills/bmad-workflow-builder/scripts/generate-html-report.py +0 -1002
- package/lib/bmad-cache/bmb/src/skills/bmad-workflow-builder/scripts/manifest.py +0 -420
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-157d7eb8d527233a8607d926fc74ebf87f2ae0d3.idx +0 -0
- package/lib/bmad-cache/cis/_git_preserved/objects/pack/pack-157d7eb8d527233a8607d926fc74ebf87f2ae0d3.rev +0 -0
- package/lib/bmad-cache/cis/src/agents/brainstorming-coach.agent.yaml +0 -21
- package/lib/bmad-cache/cis/src/agents/creative-problem-solver.agent.yaml +0 -21
- package/lib/bmad-cache/cis/src/agents/design-thinking-coach.agent.yaml +0 -21
- package/lib/bmad-cache/cis/src/agents/innovation-strategist.agent.yaml +0 -21
- package/lib/bmad-cache/cis/src/agents/presentation-master.agent.yaml +0 -53
- package/lib/bmad-cache/cis/src/agents/storyteller/storyteller.agent.yaml +0 -25
- package/lib/bmad-cache/cis/src/teams/creative-squad.yaml +0 -7
- package/lib/bmad-cache/cis/src/teams/default-party.csv +0 -12
- package/lib/bmad-cache/cis/src/workflows/README.md +0 -175
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-44faafb9245b4ca17ad81bd6c9e6fc52fb5915a1.idx +0 -0
- package/lib/bmad-cache/gds/_git_preserved/objects/pack/pack-44faafb9245b4ca17ad81bd6c9e6fc52fb5915a1.rev +0 -0
- package/lib/bmad-cache/gds/_git_preserved/refs/tags/v0.2.2 +0 -1
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-96ec1ce3a9ef4c891e00e060795b4434ba8f7163.idx +0 -0
- package/lib/bmad-cache/tea/_git_preserved/objects/pack/pack-96ec1ce3a9ef4c891e00e060795b4434ba8f7163.rev +0 -0
- package/lib/bmad-cache/tea/_git_preserved/refs/tags/v1.7.0 +0 -1
- package/lib/bmad-cache/tea/docs/MIGRATION.md +0 -488
- package/lib/bmad-cache/tea/src/agents/tea.agent.yaml +0 -67
- package/lib/bmad-cache/tea/src/teams/default-party.csv +0 -2
- package/lib/bmad-customizations/bmm-cyber.customize.yaml +0 -24
- package/lib/bmad-customizations/bmm-devops.customize.yaml +0 -24
- package/lib/bmad-customizations/bmm-mil498.customize.yaml +0 -36
- package/lib/bmad-customizations/bmm-sre.customize.yaml +0 -24
- package/lib/bmad-customizations/cyber.md +0 -71
- package/lib/bmad-customizations/devops.md +0 -71
- package/lib/bmad-customizations/mil498.md +0 -75
- package/lib/bmad-customizations/sre.md +0 -71
- package/lib/bmad-extension/agents/bmm-architect.customize.yaml +0 -5
- package/lib/bmad-extension/agents/bmm-bmad-master.customize.yaml +0 -5
- package/lib/bmad-extension/agents/bmm-cyber.customize.yaml +0 -30
- package/lib/bmad-extension/agents/bmm-dev.customize.yaml +0 -5
- package/lib/bmad-extension/agents/bmm-devops.customize.yaml +0 -30
- package/lib/bmad-extension/agents/bmm-mil498.customize.yaml +0 -42
- package/lib/bmad-extension/agents/bmm-pm.customize.yaml +0 -5
- package/lib/bmad-extension/agents/bmm-qa.customize.yaml +0 -5
- package/lib/bmad-extension/agents/bmm-sm.customize.yaml +0 -5
- package/lib/bmad-extension/agents/bmm-sre.customize.yaml +0 -30
- package/lib/bmad-extension/agents/bmm-tech-writer.customize.yaml +0 -5
- package/lib/bmad-extension/agents/bmm-ux-designer.customize.yaml +0 -5
- /package/lib/bmad-cache/bmb/{src/skills → skills}/bmad-agent-builder/scripts/scan-scripts.py +0 -0
- /package/lib/bmad-cache/bmb/{src/skills → skills}/bmad-workflow-builder/scripts/prepass-prompt-metrics.py +0 -0
- /package/lib/bmad-cache/bmb/{src/skills → skills}/bmad-workflow-builder/scripts/scan-scripts.py +0 -0
- /package/lib/bmad-cache/{bmb/src/skills/bmad-agent-builder → cis/src/skills/bmad-cis-design-thinking}/bmad-skill-manifest.yaml +0 -0
- /package/lib/bmad-cache/cis/src/{workflows → skills}/bmad-cis-design-thinking/design-methods.csv +0 -0
- /package/lib/bmad-cache/{bmb/src/skills/bmad-workflow-builder → cis/src/skills/bmad-cis-innovation-strategy}/bmad-skill-manifest.yaml +0 -0
- /package/lib/bmad-cache/cis/src/{workflows → skills}/bmad-cis-innovation-strategy/innovation-frameworks.csv +0 -0
- /package/lib/bmad-cache/cis/src/{workflows/bmad-cis-design-thinking → skills/bmad-cis-problem-solving}/bmad-skill-manifest.yaml +0 -0
- /package/lib/bmad-cache/cis/src/{workflows → skills}/bmad-cis-problem-solving/solving-methods.csv +0 -0
- /package/lib/bmad-cache/cis/src/{workflows/bmad-cis-innovation-strategy → skills/bmad-cis-storytelling}/bmad-skill-manifest.yaml +0 -0
- /package/lib/bmad-cache/cis/src/{workflows → skills}/bmad-cis-storytelling/story-types.csv +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/adr-quality-readiness-checklist.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/api-request.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/api-testing-patterns.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/auth-session.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/burn-in.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/ci-burn-in.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/component-tdd.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/contract-testing.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/data-factories.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/email-auth.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/error-handling.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/feature-flags.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/file-utils.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/fixture-architecture.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/fixtures-composition.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/intercept-network-call.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/log.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/network-error-monitor.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/network-first.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/network-recorder.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/nfr-criteria.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/overview.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/pact-consumer-di.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/pact-consumer-framework-setup.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/pact-mcp.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/pactjs-utils-consumer-helpers.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/pactjs-utils-overview.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/pactjs-utils-provider-verifier.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/pactjs-utils-request-filter.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/playwright-cli.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/playwright-config.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/probability-impact.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/recurse.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/risk-governance.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/selective-testing.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/selector-resilience.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/test-healing-patterns.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/test-levels-framework.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/test-priorities-matrix.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/test-quality.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/timing-debugging.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/knowledge/visual-debugging.md +0 -0
- /package/lib/bmad-cache/tea/src/{testarch → agents/bmad-tea/resources}/tea-index.csv +0 -0
- /package/lib/bmad-cache/{cis/src/workflows/bmad-cis-problem-solving → wds/src/workflows/wds-0-alignment-signoff}/bmad-skill-manifest.yaml +0 -0
- /package/lib/bmad-cache/{cis/src/workflows/bmad-cis-storytelling → wds/src/workflows/wds-0-project-setup}/bmad-skill-manifest.yaml +0 -0
|
@@ -0,0 +1,832 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Tests for Story 15-7: Migration Detection and Upgrade Path
|
|
4
|
+
*
|
|
5
|
+
* Task 1: detectMigrationNeed()
|
|
6
|
+
* Task 2: backupCustomizations()
|
|
7
|
+
* Task 3: mergeUserCustomizations()
|
|
8
|
+
* Task 4: cleanupLegacyArtifacts()
|
|
9
|
+
* Task 5: restoreCustomizations() (rollback)
|
|
10
|
+
* Task 6: Integration into install flow
|
|
11
|
+
*/
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
const assert = require('assert');
|
|
15
|
+
const path = require('path');
|
|
16
|
+
const fs = require('fs-extra');
|
|
17
|
+
const os = require('os');
|
|
18
|
+
|
|
19
|
+
let passed = 0;
|
|
20
|
+
let failed = 0;
|
|
21
|
+
const errors = [];
|
|
22
|
+
|
|
23
|
+
function test(name, fn) {
|
|
24
|
+
try {
|
|
25
|
+
fn();
|
|
26
|
+
console.log(` \u2713 ${name}`);
|
|
27
|
+
passed++;
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.error(` \u2717 ${name}: ${err.message}`);
|
|
30
|
+
failed++;
|
|
31
|
+
errors.push({ name, err });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function testAsync(name, fn) {
|
|
36
|
+
try {
|
|
37
|
+
await fn();
|
|
38
|
+
console.log(` \u2713 ${name}`);
|
|
39
|
+
passed++;
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.error(` \u2717 ${name}: ${err.message}`);
|
|
42
|
+
failed++;
|
|
43
|
+
errors.push({ name, err });
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Create a temp directory for test fixtures
|
|
48
|
+
let tmpRoot;
|
|
49
|
+
|
|
50
|
+
function setupTmpDir() {
|
|
51
|
+
tmpRoot = path.join(os.tmpdir(), `ma-agents-migration-test-${Date.now()}`);
|
|
52
|
+
fs.ensureDirSync(tmpRoot);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function cleanupTmpDir() {
|
|
56
|
+
if (tmpRoot && fs.existsSync(tmpRoot)) {
|
|
57
|
+
fs.removeSync(tmpRoot);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Create a mock project at the given subpath under tmpRoot.
|
|
63
|
+
*/
|
|
64
|
+
function createMockProject(subdir, opts = {}) {
|
|
65
|
+
const projectRoot = path.join(tmpRoot, subdir);
|
|
66
|
+
fs.ensureDirSync(projectRoot);
|
|
67
|
+
|
|
68
|
+
if (opts.bmadVersion !== undefined) {
|
|
69
|
+
// Create _bmad/core/config.yaml with specified version
|
|
70
|
+
const configDir = path.join(projectRoot, '_bmad', 'core');
|
|
71
|
+
fs.ensureDirSync(configDir);
|
|
72
|
+
|
|
73
|
+
if (opts.bmadVersion === null) {
|
|
74
|
+
// Write empty config (simulates 6.2.1 installer emptying it)
|
|
75
|
+
fs.writeFileSync(path.join(configDir, 'config.yaml'), '{}', 'utf-8');
|
|
76
|
+
} else if (opts.bmadVersion === 'missing-file') {
|
|
77
|
+
// _bmad/ exists but no config.yaml
|
|
78
|
+
// Do nothing — directory already created
|
|
79
|
+
} else {
|
|
80
|
+
fs.writeFileSync(
|
|
81
|
+
path.join(configDir, 'config.yaml'),
|
|
82
|
+
`version: ${opts.bmadVersion}\nname: bmad-method\n`,
|
|
83
|
+
'utf-8'
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (opts.customizeFiles) {
|
|
89
|
+
const configAgentsDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
90
|
+
fs.ensureDirSync(configAgentsDir);
|
|
91
|
+
for (const [name, content] of Object.entries(opts.customizeFiles)) {
|
|
92
|
+
fs.writeFileSync(path.join(configAgentsDir, name), content, 'utf-8');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (opts.legacyXml) {
|
|
97
|
+
const customAgentsDir = path.join(projectRoot, '_bmad', 'custom', 'agents');
|
|
98
|
+
fs.ensureDirSync(customAgentsDir);
|
|
99
|
+
for (const name of opts.legacyXml) {
|
|
100
|
+
fs.writeFileSync(path.join(customAgentsDir, name), '<agent/>', 'utf-8');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (opts.legacyWorkflowYaml) {
|
|
105
|
+
const workflowDir = path.join(projectRoot, '_bmad', 'bmm', 'workflows');
|
|
106
|
+
fs.ensureDirSync(workflowDir);
|
|
107
|
+
for (const name of opts.legacyWorkflowYaml) {
|
|
108
|
+
fs.writeFileSync(path.join(workflowDir, name), 'steps: []', 'utf-8');
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return projectRoot;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const bmad = require('../lib/bmad');
|
|
116
|
+
|
|
117
|
+
async function runAllTests() {
|
|
118
|
+
|
|
119
|
+
console.log('\nStory 15-7: Migration Detection and Upgrade Path Tests\n');
|
|
120
|
+
|
|
121
|
+
// ─── Task 1: detectMigrationNeed() ──────────────────────────────────────────
|
|
122
|
+
|
|
123
|
+
console.log('Task 1: detectMigrationNeed()');
|
|
124
|
+
|
|
125
|
+
setupTmpDir();
|
|
126
|
+
|
|
127
|
+
test('detectMigrationNeed is exported', () => {
|
|
128
|
+
assert.strictEqual(typeof bmad.detectMigrationNeed, 'function');
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test('fresh install — no _bmad/ directory', () => {
|
|
132
|
+
const projectRoot = createMockProject('fresh');
|
|
133
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
134
|
+
assert.strictEqual(result.action, 'install');
|
|
135
|
+
assert.strictEqual(result.migrate, false);
|
|
136
|
+
assert.strictEqual(result.fromVersion, undefined);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test('old version 6.0.4 — needs migration', () => {
|
|
140
|
+
const projectRoot = createMockProject('old-604', { bmadVersion: '6.0.4' });
|
|
141
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
142
|
+
assert.strictEqual(result.action, 'update');
|
|
143
|
+
assert.strictEqual(result.migrate, true);
|
|
144
|
+
assert.strictEqual(result.fromVersion, '6.0.4');
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
test('old version 5.1.0 — needs migration', () => {
|
|
148
|
+
const projectRoot = createMockProject('old-510', { bmadVersion: '5.1.0' });
|
|
149
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
150
|
+
assert.strictEqual(result.action, 'update');
|
|
151
|
+
assert.strictEqual(result.migrate, true);
|
|
152
|
+
assert.strictEqual(result.fromVersion, '5.1.0');
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test('old version 6.1.9 — needs migration', () => {
|
|
156
|
+
const projectRoot = createMockProject('old-619', { bmadVersion: '6.1.9' });
|
|
157
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
158
|
+
assert.strictEqual(result.action, 'update');
|
|
159
|
+
assert.strictEqual(result.migrate, true);
|
|
160
|
+
assert.strictEqual(result.fromVersion, '6.1.9');
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
test('current version 6.2.0 — update without migration', () => {
|
|
164
|
+
const projectRoot = createMockProject('current-620', { bmadVersion: '6.2.0' });
|
|
165
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
166
|
+
assert.strictEqual(result.action, 'update');
|
|
167
|
+
assert.strictEqual(result.migrate, false);
|
|
168
|
+
assert.strictEqual(result.fromVersion, undefined);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test('current version 6.2.1 — update without migration', () => {
|
|
172
|
+
const projectRoot = createMockProject('current-621', { bmadVersion: '6.2.1' });
|
|
173
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
174
|
+
assert.strictEqual(result.action, 'update');
|
|
175
|
+
assert.strictEqual(result.migrate, false);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test('future version 7.0.0 — update without migration', () => {
|
|
179
|
+
const projectRoot = createMockProject('future-700', { bmadVersion: '7.0.0' });
|
|
180
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
181
|
+
assert.strictEqual(result.action, 'update');
|
|
182
|
+
assert.strictEqual(result.migrate, false);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test('empty config.yaml ({}) — treats as needing migration', () => {
|
|
186
|
+
const projectRoot = createMockProject('empty-config', { bmadVersion: null });
|
|
187
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
188
|
+
assert.strictEqual(result.action, 'update');
|
|
189
|
+
assert.strictEqual(result.migrate, true);
|
|
190
|
+
assert.strictEqual(result.fromVersion, 'unknown');
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
test('missing config.yaml but _bmad/ exists — treats as needing migration', () => {
|
|
194
|
+
const projectRoot = createMockProject('no-config', { bmadVersion: 'missing-file' });
|
|
195
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
196
|
+
assert.strictEqual(result.action, 'update');
|
|
197
|
+
assert.strictEqual(result.migrate, true);
|
|
198
|
+
assert.strictEqual(result.fromVersion, 'unknown');
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
cleanupTmpDir();
|
|
202
|
+
|
|
203
|
+
// ─── Task 2: backupCustomizations() ─────────────────────────────────────────
|
|
204
|
+
|
|
205
|
+
console.log('\nTask 2: backupCustomizations()');
|
|
206
|
+
|
|
207
|
+
setupTmpDir();
|
|
208
|
+
|
|
209
|
+
test('backupCustomizations is exported', () => {
|
|
210
|
+
assert.strictEqual(typeof bmad.backupCustomizations, 'function');
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
await testAsync('backs up customize.yaml files', async () => {
|
|
214
|
+
const projectRoot = createMockProject('backup-test', {
|
|
215
|
+
bmadVersion: '6.0.4',
|
|
216
|
+
customizeFiles: {
|
|
217
|
+
'generic.customize.yaml': 'persona:\n name: "Test"\n',
|
|
218
|
+
'bmm-dev.customize.yaml': 'critical_actions:\n 1: "test action"\n',
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
const backedUp = await bmad.backupCustomizations(projectRoot);
|
|
223
|
+
assert.strictEqual(backedUp.length, 2);
|
|
224
|
+
assert.ok(backedUp.includes('generic.customize.yaml'));
|
|
225
|
+
assert.ok(backedUp.includes('bmm-dev.customize.yaml'));
|
|
226
|
+
|
|
227
|
+
// Verify backup files exist
|
|
228
|
+
const backupDir = path.join(projectRoot, '_bmad', '_config', 'agents', '.backup-pre-migration');
|
|
229
|
+
assert.ok(fs.existsSync(path.join(backupDir, 'generic.customize.yaml')));
|
|
230
|
+
assert.ok(fs.existsSync(path.join(backupDir, 'bmm-dev.customize.yaml')));
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
await testAsync('returns empty array when no _config/agents directory', async () => {
|
|
234
|
+
const projectRoot = createMockProject('no-config-dir');
|
|
235
|
+
const backedUp = await bmad.backupCustomizations(projectRoot);
|
|
236
|
+
assert.strictEqual(backedUp.length, 0);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
await testAsync('returns empty array when no customize.yaml files', async () => {
|
|
240
|
+
const projectRoot = createMockProject('empty-agents', { bmadVersion: '6.0.4' });
|
|
241
|
+
// Create _config/agents but with no customize files
|
|
242
|
+
const agentsDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
243
|
+
fs.ensureDirSync(agentsDir);
|
|
244
|
+
fs.writeFileSync(path.join(agentsDir, 'other.yaml'), 'test: true', 'utf-8');
|
|
245
|
+
|
|
246
|
+
const backedUp = await bmad.backupCustomizations(projectRoot);
|
|
247
|
+
assert.strictEqual(backedUp.length, 0);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
cleanupTmpDir();
|
|
251
|
+
|
|
252
|
+
// ─── Task 5: restoreCustomizations() (rollback) ─────────────────────────────
|
|
253
|
+
|
|
254
|
+
console.log('\nTask 5: restoreCustomizations()');
|
|
255
|
+
|
|
256
|
+
setupTmpDir();
|
|
257
|
+
|
|
258
|
+
test('restoreCustomizations is exported', () => {
|
|
259
|
+
assert.strictEqual(typeof bmad.restoreCustomizations, 'function');
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
await testAsync('restores backed-up files', async () => {
|
|
263
|
+
const projectRoot = createMockProject('restore-test', {
|
|
264
|
+
bmadVersion: '6.0.4',
|
|
265
|
+
customizeFiles: {
|
|
266
|
+
'generic.customize.yaml': 'persona:\n name: "Original"\n',
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
// Create backup
|
|
271
|
+
await bmad.backupCustomizations(projectRoot);
|
|
272
|
+
|
|
273
|
+
// Simulate update wiping the file
|
|
274
|
+
const configDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
275
|
+
fs.writeFileSync(path.join(configDir, 'generic.customize.yaml'), 'persona:\n name: "New"\n', 'utf-8');
|
|
276
|
+
|
|
277
|
+
// Restore
|
|
278
|
+
const success = await bmad.restoreCustomizations(projectRoot);
|
|
279
|
+
assert.strictEqual(success, true);
|
|
280
|
+
|
|
281
|
+
// Verify restored content
|
|
282
|
+
const content = fs.readFileSync(path.join(configDir, 'generic.customize.yaml'), 'utf-8');
|
|
283
|
+
assert.ok(content.includes('name: "Original"'));
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
await testAsync('returns false when no backup directory', async () => {
|
|
287
|
+
const projectRoot = createMockProject('no-backup');
|
|
288
|
+
const success = await bmad.restoreCustomizations(projectRoot);
|
|
289
|
+
assert.strictEqual(success, false);
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
cleanupTmpDir();
|
|
293
|
+
|
|
294
|
+
// ─── Task 3: mergeUserCustomizations() ──────────────────────────────────────
|
|
295
|
+
|
|
296
|
+
console.log('\nTask 3: mergeUserCustomizations()');
|
|
297
|
+
|
|
298
|
+
setupTmpDir();
|
|
299
|
+
|
|
300
|
+
test('mergeUserCustomizations is exported', () => {
|
|
301
|
+
assert.strictEqual(typeof bmad.mergeUserCustomizations, 'function');
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
await testAsync('merges user memories into new file', async () => {
|
|
305
|
+
const projectRoot = createMockProject('merge-memories', {
|
|
306
|
+
bmadVersion: '6.0.4',
|
|
307
|
+
customizeFiles: {
|
|
308
|
+
'bmm-dev.customize.yaml': [
|
|
309
|
+
'critical_actions:',
|
|
310
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
311
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
312
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
313
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
314
|
+
'memories:',
|
|
315
|
+
' - "Always use TypeScript strict mode"',
|
|
316
|
+
' - "Prefer functional patterns"',
|
|
317
|
+
].join('\n') + '\n',
|
|
318
|
+
}
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Backup
|
|
322
|
+
await bmad.backupCustomizations(projectRoot);
|
|
323
|
+
|
|
324
|
+
// Simulate new file deployed (no memories)
|
|
325
|
+
const configDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
326
|
+
fs.writeFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), [
|
|
327
|
+
'critical_actions:',
|
|
328
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
329
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
330
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
331
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
332
|
+
].join('\n') + '\n', 'utf-8');
|
|
333
|
+
|
|
334
|
+
const result = await bmad.mergeUserCustomizations(projectRoot);
|
|
335
|
+
assert.ok(result.merged.includes('bmm-dev.customize.yaml'));
|
|
336
|
+
|
|
337
|
+
const content = fs.readFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), 'utf-8');
|
|
338
|
+
assert.ok(content.includes('Always use TypeScript strict mode'), 'Should contain merged memory');
|
|
339
|
+
assert.ok(content.includes('Prefer functional patterns'), 'Should contain merged memory');
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
await testAsync('merges user-added critical_actions', async () => {
|
|
343
|
+
const projectRoot = createMockProject('merge-ca', {
|
|
344
|
+
bmadVersion: '6.0.4',
|
|
345
|
+
customizeFiles: {
|
|
346
|
+
'bmm-dev.customize.yaml': [
|
|
347
|
+
'critical_actions:',
|
|
348
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
349
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
350
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
351
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
352
|
+
' 5: "Always run linting before committing"',
|
|
353
|
+
' 6: "Check for security vulnerabilities in dependencies"',
|
|
354
|
+
].join('\n') + '\n',
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
await bmad.backupCustomizations(projectRoot);
|
|
359
|
+
|
|
360
|
+
// Simulate new file with standard 4 critical_actions
|
|
361
|
+
const configDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
362
|
+
fs.writeFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), [
|
|
363
|
+
'critical_actions:',
|
|
364
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
365
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
366
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
367
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
368
|
+
].join('\n') + '\n', 'utf-8');
|
|
369
|
+
|
|
370
|
+
const result = await bmad.mergeUserCustomizations(projectRoot);
|
|
371
|
+
assert.ok(result.merged.includes('bmm-dev.customize.yaml'));
|
|
372
|
+
|
|
373
|
+
const content = fs.readFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), 'utf-8');
|
|
374
|
+
assert.ok(content.includes('Always run linting before committing'), 'Should contain user CA');
|
|
375
|
+
assert.ok(content.includes('Check for security vulnerabilities'), 'Should contain user CA');
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
await testAsync('skips files with no user customizations', async () => {
|
|
379
|
+
const projectRoot = createMockProject('merge-skip', {
|
|
380
|
+
bmadVersion: '6.0.4',
|
|
381
|
+
customizeFiles: {
|
|
382
|
+
'bmm-dev.customize.yaml': [
|
|
383
|
+
'critical_actions:',
|
|
384
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
385
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
386
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
387
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
388
|
+
].join('\n') + '\n',
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
await bmad.backupCustomizations(projectRoot);
|
|
393
|
+
|
|
394
|
+
// Deploy identical new file
|
|
395
|
+
const configDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
396
|
+
fs.writeFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), [
|
|
397
|
+
'critical_actions:',
|
|
398
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
399
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
400
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
401
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
402
|
+
].join('\n') + '\n', 'utf-8');
|
|
403
|
+
|
|
404
|
+
const result = await bmad.mergeUserCustomizations(projectRoot);
|
|
405
|
+
assert.ok(result.skipped.includes('bmm-dev.customize.yaml'));
|
|
406
|
+
assert.strictEqual(result.merged.length, 0);
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
await testAsync('returns empty result when no backup directory', async () => {
|
|
410
|
+
const projectRoot = createMockProject('merge-no-backup');
|
|
411
|
+
const result = await bmad.mergeUserCustomizations(projectRoot);
|
|
412
|
+
assert.strictEqual(result.merged.length, 0);
|
|
413
|
+
assert.strictEqual(result.skipped.length, 0);
|
|
414
|
+
});
|
|
415
|
+
|
|
416
|
+
await testAsync('merge with YAML special characters produces valid output', async () => {
|
|
417
|
+
const projectRoot = createMockProject('merge-yaml-special', {
|
|
418
|
+
bmadVersion: '6.0.4',
|
|
419
|
+
customizeFiles: {
|
|
420
|
+
'bmm-dev.customize.yaml': [
|
|
421
|
+
'critical_actions:',
|
|
422
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
423
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
424
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
425
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
426
|
+
'memories:',
|
|
427
|
+
' - "Value with colon: inside it"',
|
|
428
|
+
' - "Value with # hash character"',
|
|
429
|
+
' - "Value with | pipe character"',
|
|
430
|
+
].join('\n') + '\n',
|
|
431
|
+
}
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
await bmad.backupCustomizations(projectRoot);
|
|
435
|
+
|
|
436
|
+
const configDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
437
|
+
fs.writeFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), [
|
|
438
|
+
'critical_actions:',
|
|
439
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
440
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
441
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
442
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
443
|
+
].join('\n') + '\n', 'utf-8');
|
|
444
|
+
|
|
445
|
+
const result = await bmad.mergeUserCustomizations(projectRoot);
|
|
446
|
+
assert.ok(result.merged.includes('bmm-dev.customize.yaml'));
|
|
447
|
+
|
|
448
|
+
const content = fs.readFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), 'utf-8');
|
|
449
|
+
assert.ok(content.includes('colon: inside it'), 'Should preserve colon in value');
|
|
450
|
+
assert.ok(content.includes('# hash character'), 'Should preserve hash in value');
|
|
451
|
+
assert.ok(content.includes('| pipe character'), 'Should preserve pipe in value');
|
|
452
|
+
|
|
453
|
+
// Validate the output can be re-parsed
|
|
454
|
+
const parsed = bmad.parseCustomizeYaml(content);
|
|
455
|
+
assert.ok(parsed.criticalActions.length >= 4, 'Merged output should have at least 4 critical actions');
|
|
456
|
+
assert.ok(parsed.memories.length >= 3, 'Merged output should have at least 3 memories');
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
await testAsync('corrupt merge output triggers backup restore', async () => {
|
|
460
|
+
// This test verifies that if mergeUserCustomizations produces output where
|
|
461
|
+
// critical_actions section exists but parses to nothing, it restores from backup.
|
|
462
|
+
// We simulate this by creating a scenario with adversarial content.
|
|
463
|
+
const projectRoot = createMockProject('merge-corrupt', {
|
|
464
|
+
bmadVersion: '6.0.4',
|
|
465
|
+
customizeFiles: {
|
|
466
|
+
'bmm-dev.customize.yaml': [
|
|
467
|
+
'critical_actions:',
|
|
468
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
469
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
470
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
471
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
472
|
+
'memories:',
|
|
473
|
+
' - "Normal memory"',
|
|
474
|
+
].join('\n') + '\n',
|
|
475
|
+
}
|
|
476
|
+
});
|
|
477
|
+
|
|
478
|
+
await bmad.backupCustomizations(projectRoot);
|
|
479
|
+
|
|
480
|
+
// Deploy a new file that has critical_actions section with valid entries
|
|
481
|
+
const configDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
482
|
+
fs.writeFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), [
|
|
483
|
+
'critical_actions:',
|
|
484
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
485
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
486
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
487
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
488
|
+
].join('\n') + '\n', 'utf-8');
|
|
489
|
+
|
|
490
|
+
// The merge should succeed since both files are valid
|
|
491
|
+
const result = await bmad.mergeUserCustomizations(projectRoot);
|
|
492
|
+
// Verify the output file exists and is parseable
|
|
493
|
+
const content = fs.readFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), 'utf-8');
|
|
494
|
+
const parsed = bmad.parseCustomizeYaml(content);
|
|
495
|
+
assert.ok(parsed.criticalActions.length >= 4, 'Output should have valid critical actions');
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
cleanupTmpDir();
|
|
499
|
+
|
|
500
|
+
// ─── Task 4: cleanupLegacyArtifacts() ───────────────────────────────────────
|
|
501
|
+
|
|
502
|
+
console.log('\nTask 4: cleanupLegacyArtifacts()');
|
|
503
|
+
|
|
504
|
+
setupTmpDir();
|
|
505
|
+
|
|
506
|
+
test('cleanupLegacyArtifacts is exported', () => {
|
|
507
|
+
assert.strictEqual(typeof bmad.cleanupLegacyArtifacts, 'function');
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
await testAsync('removes XML agent definitions', async () => {
|
|
511
|
+
const projectRoot = createMockProject('cleanup-xml', {
|
|
512
|
+
bmadVersion: '6.0.4',
|
|
513
|
+
legacyXml: ['sre.xml', 'devops.xml'],
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
const cleaned = await bmad.cleanupLegacyArtifacts(projectRoot);
|
|
517
|
+
assert.ok(cleaned.some(p => p.includes('sre.xml')));
|
|
518
|
+
assert.ok(cleaned.some(p => p.includes('devops.xml')));
|
|
519
|
+
|
|
520
|
+
// Verify files are gone
|
|
521
|
+
const customAgentsDir = path.join(projectRoot, '_bmad', 'custom', 'agents');
|
|
522
|
+
assert.ok(!fs.existsSync(path.join(customAgentsDir, 'sre.xml')));
|
|
523
|
+
assert.ok(!fs.existsSync(path.join(customAgentsDir, 'devops.xml')));
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
await testAsync('removes legacy YAML workflow files but not subdirectories', async () => {
|
|
527
|
+
const projectRoot = createMockProject('cleanup-workflows', {
|
|
528
|
+
bmadVersion: '6.0.4',
|
|
529
|
+
legacyWorkflowYaml: ['old-flow.yaml', 'legacy-engine.yaml'],
|
|
530
|
+
});
|
|
531
|
+
|
|
532
|
+
// Also create a subdirectory that should NOT be removed
|
|
533
|
+
const subDir = path.join(projectRoot, '_bmad', 'bmm', 'workflows', 'sre');
|
|
534
|
+
fs.ensureDirSync(subDir);
|
|
535
|
+
fs.writeFileSync(path.join(subDir, 'health-check.md'), '# workflow', 'utf-8');
|
|
536
|
+
|
|
537
|
+
const cleaned = await bmad.cleanupLegacyArtifacts(projectRoot);
|
|
538
|
+
assert.ok(cleaned.some(p => p.includes('old-flow.yaml')));
|
|
539
|
+
assert.ok(cleaned.some(p => p.includes('legacy-engine.yaml')));
|
|
540
|
+
|
|
541
|
+
// Subdirectory should still exist
|
|
542
|
+
assert.ok(fs.existsSync(subDir));
|
|
543
|
+
assert.ok(fs.existsSync(path.join(subDir, 'health-check.md')));
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
await testAsync('cleanupLegacyArtifacts preserves backup directory (retained until next install)', async () => {
|
|
547
|
+
const projectRoot = createMockProject('cleanup-backup', {
|
|
548
|
+
bmadVersion: '6.0.4',
|
|
549
|
+
customizeFiles: {
|
|
550
|
+
'generic.customize.yaml': 'persona:\n name: "Test"\n',
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
// Create backup
|
|
555
|
+
await bmad.backupCustomizations(projectRoot);
|
|
556
|
+
const backupDir = path.join(projectRoot, '_bmad', '_config', 'agents', '.backup-pre-migration');
|
|
557
|
+
assert.ok(fs.existsSync(backupDir), 'Backup should exist before cleanup');
|
|
558
|
+
|
|
559
|
+
await bmad.cleanupLegacyArtifacts(projectRoot);
|
|
560
|
+
assert.ok(fs.existsSync(backupDir), 'Backup should still exist after cleanup (retained for manual recovery)');
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
await testAsync('backupCustomizations removes pre-existing backup before creating new one', async () => {
|
|
564
|
+
const projectRoot = createMockProject('backup-replace', {
|
|
565
|
+
bmadVersion: '6.0.4',
|
|
566
|
+
customizeFiles: {
|
|
567
|
+
'generic.customize.yaml': 'persona:\n name: "First"\n',
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
// Create first backup
|
|
572
|
+
await bmad.backupCustomizations(projectRoot);
|
|
573
|
+
const backupDir = path.join(projectRoot, '_bmad', '_config', 'agents', '.backup-pre-migration');
|
|
574
|
+
assert.ok(fs.existsSync(backupDir), 'First backup should exist');
|
|
575
|
+
|
|
576
|
+
// Modify the source file
|
|
577
|
+
const configDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
578
|
+
fs.writeFileSync(path.join(configDir, 'generic.customize.yaml'), 'persona:\n name: "Second"\n', 'utf-8');
|
|
579
|
+
|
|
580
|
+
// Create second backup — should replace the first
|
|
581
|
+
await bmad.backupCustomizations(projectRoot);
|
|
582
|
+
const content = fs.readFileSync(path.join(backupDir, 'generic.customize.yaml'), 'utf-8');
|
|
583
|
+
assert.ok(content.includes('name: "Second"'), 'Backup should contain the newer content, not the old one');
|
|
584
|
+
});
|
|
585
|
+
|
|
586
|
+
await testAsync('returns empty array when no legacy artifacts', async () => {
|
|
587
|
+
const projectRoot = createMockProject('cleanup-nothing');
|
|
588
|
+
const cleaned = await bmad.cleanupLegacyArtifacts(projectRoot);
|
|
589
|
+
assert.strictEqual(cleaned.length, 0);
|
|
590
|
+
});
|
|
591
|
+
|
|
592
|
+
cleanupTmpDir();
|
|
593
|
+
|
|
594
|
+
// ─── Task 6: Integration / installBmad detection ────────────────────────────
|
|
595
|
+
|
|
596
|
+
console.log('\nTask 6: Integration tests');
|
|
597
|
+
|
|
598
|
+
test('installBmad is still exported and callable', () => {
|
|
599
|
+
assert.strictEqual(typeof bmad.installBmad, 'function');
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
test('updateBmad is still exported and callable', () => {
|
|
603
|
+
assert.strictEqual(typeof bmad.updateBmad, 'function');
|
|
604
|
+
});
|
|
605
|
+
|
|
606
|
+
// ─── Edge cases ─────────────────────────────────────────────────────────────
|
|
607
|
+
|
|
608
|
+
console.log('\nEdge cases');
|
|
609
|
+
|
|
610
|
+
setupTmpDir();
|
|
611
|
+
|
|
612
|
+
test('detectMigrationNeed handles version with quotes', () => {
|
|
613
|
+
const projectRoot = path.join(tmpRoot, 'quoted-version');
|
|
614
|
+
fs.ensureDirSync(path.join(projectRoot, '_bmad', 'core'));
|
|
615
|
+
fs.writeFileSync(
|
|
616
|
+
path.join(projectRoot, '_bmad', 'core', 'config.yaml'),
|
|
617
|
+
"version: '6.0.4'\nname: bmad-method\n",
|
|
618
|
+
'utf-8'
|
|
619
|
+
);
|
|
620
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
621
|
+
assert.strictEqual(result.action, 'update');
|
|
622
|
+
assert.strictEqual(result.migrate, true);
|
|
623
|
+
assert.strictEqual(result.fromVersion, '6.0.4');
|
|
624
|
+
});
|
|
625
|
+
|
|
626
|
+
test('detectMigrationNeed handles version with double quotes', () => {
|
|
627
|
+
const projectRoot = path.join(tmpRoot, 'dquoted-version');
|
|
628
|
+
fs.ensureDirSync(path.join(projectRoot, '_bmad', 'core'));
|
|
629
|
+
fs.writeFileSync(
|
|
630
|
+
path.join(projectRoot, '_bmad', 'core', 'config.yaml'),
|
|
631
|
+
'version: "6.0.4"\nname: bmad-method\n',
|
|
632
|
+
'utf-8'
|
|
633
|
+
);
|
|
634
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
635
|
+
assert.strictEqual(result.migrate, true);
|
|
636
|
+
assert.strictEqual(result.fromVersion, '6.0.4');
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
test('detectMigrationNeed handles version with comment', () => {
|
|
640
|
+
const projectRoot = path.join(tmpRoot, 'comment-version');
|
|
641
|
+
fs.ensureDirSync(path.join(projectRoot, '_bmad', 'core'));
|
|
642
|
+
fs.writeFileSync(
|
|
643
|
+
path.join(projectRoot, '_bmad', 'core', 'config.yaml'),
|
|
644
|
+
'version: 6.0.4 # old version\nname: bmad-method\n',
|
|
645
|
+
'utf-8'
|
|
646
|
+
);
|
|
647
|
+
const result = bmad.detectMigrationNeed(projectRoot);
|
|
648
|
+
assert.strictEqual(result.migrate, true);
|
|
649
|
+
assert.strictEqual(result.fromVersion, '6.0.4');
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
await testAsync('mergeUserCustomizations handles file in backup but not in new deployment', async () => {
|
|
653
|
+
const projectRoot = createMockProject('merge-no-new', {
|
|
654
|
+
bmadVersion: '6.0.4',
|
|
655
|
+
customizeFiles: {
|
|
656
|
+
'custom-agent.customize.yaml': [
|
|
657
|
+
'memories:',
|
|
658
|
+
' - "User memory 1"',
|
|
659
|
+
].join('\n') + '\n',
|
|
660
|
+
}
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
await bmad.backupCustomizations(projectRoot);
|
|
664
|
+
|
|
665
|
+
// Remove the file from config dir (simulating it not being re-deployed)
|
|
666
|
+
const configDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
667
|
+
fs.removeSync(path.join(configDir, 'custom-agent.customize.yaml'));
|
|
668
|
+
|
|
669
|
+
// Merge should use backup as base
|
|
670
|
+
const result = await bmad.mergeUserCustomizations(projectRoot);
|
|
671
|
+
assert.ok(result.merged.includes('custom-agent.customize.yaml'));
|
|
672
|
+
|
|
673
|
+
// The file should now exist with user memories
|
|
674
|
+
const content = fs.readFileSync(path.join(configDir, 'custom-agent.customize.yaml'), 'utf-8');
|
|
675
|
+
assert.ok(content.includes('User memory 1'));
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
cleanupTmpDir();
|
|
679
|
+
|
|
680
|
+
// ─── compareVersions edge cases ─────────────────────────────────────────────
|
|
681
|
+
|
|
682
|
+
console.log('\ncompareVersions edge cases');
|
|
683
|
+
|
|
684
|
+
test('compareVersions is exported', () => {
|
|
685
|
+
assert.strictEqual(typeof bmad.compareVersions, 'function');
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
test('compareVersions("6.2.1-beta.1", "6.2.1") does not crash', () => {
|
|
689
|
+
// Pre-release suffix causes NaN in patch segment, falls back to 0
|
|
690
|
+
const result = bmad.compareVersions('6.2.1-beta.1', '6.2.1');
|
|
691
|
+
assert.ok(typeof result === 'number', 'Should return a number');
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
test('compareVersions("6.2", "6.2.1") does not crash', () => {
|
|
695
|
+
// Two-segment version — missing patch treated as 0
|
|
696
|
+
const result = bmad.compareVersions('6.2', '6.2.1');
|
|
697
|
+
assert.ok(typeof result === 'number', 'Should return a number');
|
|
698
|
+
assert.strictEqual(result, -1, '"6.2" (= 6.2.0) should be less than "6.2.1"');
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
test('compareVersions standard cases', () => {
|
|
702
|
+
assert.strictEqual(bmad.compareVersions('6.0.4', '6.2.1'), -1);
|
|
703
|
+
assert.strictEqual(bmad.compareVersions('6.2.1', '6.2.1'), 0);
|
|
704
|
+
assert.strictEqual(bmad.compareVersions('7.0.0', '6.2.1'), 1);
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
// ─── Fix 9: Adversarial YAML merge tests ───────────────────────────────────
|
|
708
|
+
|
|
709
|
+
console.log('\nAdversarial YAML merge tests');
|
|
710
|
+
|
|
711
|
+
setupTmpDir();
|
|
712
|
+
|
|
713
|
+
await testAsync('adversarial: colons, hashes, and pipes in persona survive round-trip', async () => {
|
|
714
|
+
const projectRoot = createMockProject('adversarial-roundtrip', {
|
|
715
|
+
bmadVersion: '6.0.4',
|
|
716
|
+
customizeFiles: {
|
|
717
|
+
'bmm-dev.customize.yaml': [
|
|
718
|
+
'critical_actions:',
|
|
719
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
720
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
721
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
722
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
723
|
+
'memories:',
|
|
724
|
+
' - "Deploy to env: production # only on Fridays"',
|
|
725
|
+
' - "Use format: key|value pairs"',
|
|
726
|
+
' - "Config path: /etc/app/config.yaml"',
|
|
727
|
+
'persona:',
|
|
728
|
+
' role: "Senior Dev: specializing in backend | frontend"',
|
|
729
|
+
' style: "Cautious # but not paranoid"',
|
|
730
|
+
].join('\n') + '\n',
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
|
|
734
|
+
await bmad.backupCustomizations(projectRoot);
|
|
735
|
+
|
|
736
|
+
// Deploy a new file without user content
|
|
737
|
+
const configDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
738
|
+
fs.writeFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), [
|
|
739
|
+
'critical_actions:',
|
|
740
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
741
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
742
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
743
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
744
|
+
].join('\n') + '\n', 'utf-8');
|
|
745
|
+
|
|
746
|
+
const result = await bmad.mergeUserCustomizations(projectRoot);
|
|
747
|
+
assert.ok(result.merged.includes('bmm-dev.customize.yaml'));
|
|
748
|
+
|
|
749
|
+
const content = fs.readFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), 'utf-8');
|
|
750
|
+
assert.ok(content.includes('env: production # only on Fridays'), 'Colon and hash in memory must survive');
|
|
751
|
+
assert.ok(content.includes('key|value pairs'), 'Pipe in memory must survive');
|
|
752
|
+
assert.ok(content.includes('/etc/app/config.yaml'), 'Colon in path must survive');
|
|
753
|
+
assert.ok(content.includes('Senior Dev: specializing in backend | frontend'), 'Persona with colon and pipe must survive');
|
|
754
|
+
});
|
|
755
|
+
|
|
756
|
+
await testAsync('adversarial: broken input (unbalanced quotes, bare {) does not crash', async () => {
|
|
757
|
+
const projectRoot = createMockProject('adversarial-broken', {
|
|
758
|
+
bmadVersion: '6.0.4',
|
|
759
|
+
customizeFiles: {
|
|
760
|
+
'bmm-dev.customize.yaml': [
|
|
761
|
+
'critical_actions:',
|
|
762
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
763
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
764
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
765
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
766
|
+
'memories:',
|
|
767
|
+
' - "Unbalanced quote: she said \\"hello',
|
|
768
|
+
' - "Bare brace: { is fine"',
|
|
769
|
+
' - "Mixed: key: {val} # comment | pipe"',
|
|
770
|
+
].join('\n') + '\n',
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
await bmad.backupCustomizations(projectRoot);
|
|
775
|
+
|
|
776
|
+
const configDir = path.join(projectRoot, '_bmad', '_config', 'agents');
|
|
777
|
+
fs.writeFileSync(path.join(configDir, 'bmm-dev.customize.yaml'), [
|
|
778
|
+
'critical_actions:',
|
|
779
|
+
' 1: "Read the skills MANIFEST at {project-root}/_bmad/skills/MANIFEST.yaml"',
|
|
780
|
+
' 2: "For each skill marked always_load: true, read the skill file completely"',
|
|
781
|
+
' 3: "If _bmad-output/project-context.md exists, read it completely"',
|
|
782
|
+
' 4: "Follow all skill directives and project-context rules during this session"',
|
|
783
|
+
].join('\n') + '\n', 'utf-8');
|
|
784
|
+
|
|
785
|
+
// Should not crash — mergeUserCustomizations must be resilient
|
|
786
|
+
let error = null;
|
|
787
|
+
try {
|
|
788
|
+
await bmad.mergeUserCustomizations(projectRoot);
|
|
789
|
+
} catch (e) {
|
|
790
|
+
error = e;
|
|
791
|
+
}
|
|
792
|
+
assert.strictEqual(error, null, 'mergeUserCustomizations must not crash on broken input');
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
await testAsync('adversarial: parseCustomizeYaml handles adversarial content gracefully', async () => {
|
|
796
|
+
const adversarial = [
|
|
797
|
+
'critical_actions:',
|
|
798
|
+
' 1: "Normal action"',
|
|
799
|
+
' 2: "Action with: colon"',
|
|
800
|
+
'memories:',
|
|
801
|
+
' - "Memory with # hash"',
|
|
802
|
+
' - "Memory with | pipe and { brace"',
|
|
803
|
+
'persona:',
|
|
804
|
+
' name: "Agent: Test # Special"',
|
|
805
|
+
].join('\n');
|
|
806
|
+
|
|
807
|
+
const parsed = bmad.parseCustomizeYaml(adversarial);
|
|
808
|
+
assert.strictEqual(parsed.criticalActions.length, 2, 'Should parse 2 critical actions');
|
|
809
|
+
assert.ok(parsed.memories.length >= 2, 'Should parse at least 2 memories');
|
|
810
|
+
assert.ok(parsed.personaLines.length > 0, 'Should parse persona lines');
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
cleanupTmpDir();
|
|
814
|
+
|
|
815
|
+
// ── Summary ─────────────────────────────────────────────────────────────────
|
|
816
|
+
|
|
817
|
+
console.log(`\n${passed} passed, ${failed} failed`);
|
|
818
|
+
if (errors.length > 0) {
|
|
819
|
+
console.log('\nFailures:');
|
|
820
|
+
errors.forEach(({ name, err }) => {
|
|
821
|
+
console.log(` ${name}:`);
|
|
822
|
+
console.log(` ${err.message}`);
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
process.exit(failed > 0 ? 1 : 0);
|
|
826
|
+
|
|
827
|
+
} // end runAllTests
|
|
828
|
+
|
|
829
|
+
runAllTests().catch(err => {
|
|
830
|
+
console.error('Test runner failed:', err);
|
|
831
|
+
process.exit(1);
|
|
832
|
+
});
|