From 31ae226bb43f8435352562edf6d94839dd3119dd Mon Sep 17 00:00:00 2001 From: Alex Verkhovsky Date: Sat, 21 Mar 2026 00:11:23 -0600 Subject: [PATCH] refactor(installer): discover skills by SKILL.md instead of manifest YAML (#2082) Switch skill discovery gate from requiring bmad-skill-manifest.yaml with type: skill to detecting any directory with a valid SKILL.md (frontmatter name + description, name matches directory name). Delete 34 stub manifests that carried no data beyond type: skill. Agent manifests (9) are retained for persona metadata consumed by agent-manifest.csv. --- .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-create-prd/bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-edit-prd/bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-code-review/bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-dev-story/bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-quick-dev/bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-distillator/bmad-skill-manifest.yaml | 15 -- .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-help/bmad-skill-manifest.yaml | 1 - .../bmad-index-docs/bmad-skill-manifest.yaml | 1 - .../bmad-init/bmad-skill-manifest.yaml | 1 - .../bmad-party-mode/bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-skill-manifest.yaml | 1 - .../bmad-shard-doc/bmad-skill-manifest.yaml | 1 - test/test-installation-components.js | 5 - .../installers/lib/core/manifest-generator.js | 154 ++++++------------ 36 files changed, 53 insertions(+), 154 deletions(-) delete mode 100644 src/bmm-skills/1-analysis/bmad-document-project/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/1-analysis/bmad-product-brief/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/1-analysis/research/bmad-domain-research/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/1-analysis/research/bmad-market-research/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/1-analysis/research/bmad-technical-research/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/2-plan-workflows/bmad-create-prd/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/2-plan-workflows/bmad-create-ux-design/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/2-plan-workflows/bmad-edit-prd/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/2-plan-workflows/bmad-validate-prd/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/3-solutioning/bmad-create-architecture/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/3-solutioning/bmad-generate-project-context/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/4-implementation/bmad-code-review/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/4-implementation/bmad-correct-course/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/4-implementation/bmad-create-story/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/4-implementation/bmad-dev-story/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/4-implementation/bmad-qa-generate-e2e-tests/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/4-implementation/bmad-quick-dev/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/4-implementation/bmad-retrospective/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/4-implementation/bmad-sprint-planning/bmad-skill-manifest.yaml delete mode 100644 src/bmm-skills/4-implementation/bmad-sprint-status/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-advanced-elicitation/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-brainstorming/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-distillator/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-editorial-review-prose/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-editorial-review-structure/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-help/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-index-docs/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-init/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-party-mode/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-review-adversarial-general/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-review-edge-case-hunter/bmad-skill-manifest.yaml delete mode 100644 src/core-skills/bmad-shard-doc/bmad-skill-manifest.yaml diff --git a/src/bmm-skills/1-analysis/bmad-document-project/bmad-skill-manifest.yaml b/src/bmm-skills/1-analysis/bmad-document-project/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/1-analysis/bmad-document-project/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/1-analysis/bmad-product-brief/bmad-skill-manifest.yaml b/src/bmm-skills/1-analysis/bmad-product-brief/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/1-analysis/bmad-product-brief/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/1-analysis/research/bmad-domain-research/bmad-skill-manifest.yaml b/src/bmm-skills/1-analysis/research/bmad-domain-research/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/1-analysis/research/bmad-domain-research/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/1-analysis/research/bmad-market-research/bmad-skill-manifest.yaml b/src/bmm-skills/1-analysis/research/bmad-market-research/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/1-analysis/research/bmad-market-research/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/1-analysis/research/bmad-technical-research/bmad-skill-manifest.yaml b/src/bmm-skills/1-analysis/research/bmad-technical-research/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/1-analysis/research/bmad-technical-research/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/2-plan-workflows/bmad-create-prd/bmad-skill-manifest.yaml b/src/bmm-skills/2-plan-workflows/bmad-create-prd/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/2-plan-workflows/bmad-create-prd/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/bmad-skill-manifest.yaml b/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/2-plan-workflows/bmad-create-ux-design/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/2-plan-workflows/bmad-edit-prd/bmad-skill-manifest.yaml b/src/bmm-skills/2-plan-workflows/bmad-edit-prd/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/2-plan-workflows/bmad-edit-prd/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/2-plan-workflows/bmad-validate-prd/bmad-skill-manifest.yaml b/src/bmm-skills/2-plan-workflows/bmad-validate-prd/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/2-plan-workflows/bmad-validate-prd/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/bmad-skill-manifest.yaml b/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/3-solutioning/bmad-check-implementation-readiness/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/3-solutioning/bmad-create-architecture/bmad-skill-manifest.yaml b/src/bmm-skills/3-solutioning/bmad-create-architecture/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/3-solutioning/bmad-create-architecture/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/bmad-skill-manifest.yaml b/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/3-solutioning/bmad-create-epics-and-stories/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/3-solutioning/bmad-generate-project-context/bmad-skill-manifest.yaml b/src/bmm-skills/3-solutioning/bmad-generate-project-context/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/3-solutioning/bmad-generate-project-context/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/4-implementation/bmad-code-review/bmad-skill-manifest.yaml b/src/bmm-skills/4-implementation/bmad-code-review/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/4-implementation/bmad-code-review/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/4-implementation/bmad-correct-course/bmad-skill-manifest.yaml b/src/bmm-skills/4-implementation/bmad-correct-course/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/4-implementation/bmad-correct-course/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/4-implementation/bmad-create-story/bmad-skill-manifest.yaml b/src/bmm-skills/4-implementation/bmad-create-story/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/4-implementation/bmad-create-story/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/4-implementation/bmad-dev-story/bmad-skill-manifest.yaml b/src/bmm-skills/4-implementation/bmad-dev-story/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/4-implementation/bmad-dev-story/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/4-implementation/bmad-qa-generate-e2e-tests/bmad-skill-manifest.yaml b/src/bmm-skills/4-implementation/bmad-qa-generate-e2e-tests/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/4-implementation/bmad-qa-generate-e2e-tests/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/4-implementation/bmad-quick-dev/bmad-skill-manifest.yaml b/src/bmm-skills/4-implementation/bmad-quick-dev/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/4-implementation/bmad-quick-dev/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/4-implementation/bmad-retrospective/bmad-skill-manifest.yaml b/src/bmm-skills/4-implementation/bmad-retrospective/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/4-implementation/bmad-retrospective/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/4-implementation/bmad-sprint-planning/bmad-skill-manifest.yaml b/src/bmm-skills/4-implementation/bmad-sprint-planning/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/4-implementation/bmad-sprint-planning/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/bmm-skills/4-implementation/bmad-sprint-status/bmad-skill-manifest.yaml b/src/bmm-skills/4-implementation/bmad-sprint-status/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/bmm-skills/4-implementation/bmad-sprint-status/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-advanced-elicitation/bmad-skill-manifest.yaml b/src/core-skills/bmad-advanced-elicitation/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-advanced-elicitation/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-brainstorming/bmad-skill-manifest.yaml b/src/core-skills/bmad-brainstorming/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-brainstorming/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-distillator/bmad-skill-manifest.yaml b/src/core-skills/bmad-distillator/bmad-skill-manifest.yaml deleted file mode 100644 index 7e0638933..000000000 --- a/src/core-skills/bmad-distillator/bmad-skill-manifest.yaml +++ /dev/null @@ -1,15 +0,0 @@ -type: skill -module: core -capabilities: - - name: bmad-distillator - menu-code: DSTL - description: "Produces lossless LLM-optimized distillate from source documents. Use after producing large human presentable documents that will be consumed later by LLMs" - supports-headless: true - input: source documents - args: output, validate - output: single distillate or folder of distillates next to source input - config-vars-used: null - phase: anytime - before: [] - after: [] - is-required: false diff --git a/src/core-skills/bmad-editorial-review-prose/bmad-skill-manifest.yaml b/src/core-skills/bmad-editorial-review-prose/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-editorial-review-prose/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-editorial-review-structure/bmad-skill-manifest.yaml b/src/core-skills/bmad-editorial-review-structure/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-editorial-review-structure/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-help/bmad-skill-manifest.yaml b/src/core-skills/bmad-help/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-help/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-index-docs/bmad-skill-manifest.yaml b/src/core-skills/bmad-index-docs/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-index-docs/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-init/bmad-skill-manifest.yaml b/src/core-skills/bmad-init/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-init/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-party-mode/bmad-skill-manifest.yaml b/src/core-skills/bmad-party-mode/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-party-mode/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-review-adversarial-general/bmad-skill-manifest.yaml b/src/core-skills/bmad-review-adversarial-general/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-review-adversarial-general/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-review-edge-case-hunter/bmad-skill-manifest.yaml b/src/core-skills/bmad-review-edge-case-hunter/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-review-edge-case-hunter/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/src/core-skills/bmad-shard-doc/bmad-skill-manifest.yaml b/src/core-skills/bmad-shard-doc/bmad-skill-manifest.yaml deleted file mode 100644 index d0f08abdb..000000000 --- a/src/core-skills/bmad-shard-doc/bmad-skill-manifest.yaml +++ /dev/null @@ -1 +0,0 @@ -type: skill diff --git a/test/test-installation-components.js b/test/test-installation-components.js index f7a8d325c..44455fbb7 100644 --- a/test/test-installation-components.js +++ b/test/test-installation-components.js @@ -78,7 +78,6 @@ async function createTestBmadFixture() { 'You are a test agent.', ].join('\n'), ); - await fs.writeFile(path.join(skillDir, 'bmad-skill-manifest.yaml'), 'SKILL.md:\n type: skill\n'); await fs.writeFile(path.join(skillDir, 'workflow.md'), '# Test Workflow\nStep 1: Do the thing.\n'); return fixtureDir; @@ -1535,7 +1534,6 @@ async function runTests() { // --- Skill at unusual path: core/custom-area/my-skill/ --- const skillDir29 = path.join(tempFixture29, 'core', 'custom-area', 'my-skill'); await fs.ensureDir(skillDir29); - await fs.writeFile(path.join(skillDir29, 'bmad-skill-manifest.yaml'), 'type: skill\n'); await fs.writeFile( path.join(skillDir29, 'SKILL.md'), '---\nname: my-skill\ndescription: A skill at an unusual path\n---\n\nFollow the instructions in [workflow.md](workflow.md).\n', @@ -1554,7 +1552,6 @@ async function runTests() { // --- Skill inside workflows/ dir: core/workflows/wf-skill/ (exercises findWorkflows skip logic) --- const wfSkillDir29 = path.join(tempFixture29, 'core', 'workflows', 'wf-skill'); await fs.ensureDir(wfSkillDir29); - await fs.writeFile(path.join(wfSkillDir29, 'bmad-skill-manifest.yaml'), 'type: skill\n'); await fs.writeFile( path.join(wfSkillDir29, 'SKILL.md'), '---\nname: wf-skill\ndescription: A skill inside workflows dir\n---\n\nFollow the instructions in [workflow.md](workflow.md).\n', @@ -1564,7 +1561,6 @@ async function runTests() { // --- Skill inside tasks/ dir: core/tasks/task-skill/ --- const taskSkillDir29 = path.join(tempFixture29, 'core', 'tasks', 'task-skill'); await fs.ensureDir(taskSkillDir29); - await fs.writeFile(path.join(taskSkillDir29, 'bmad-skill-manifest.yaml'), 'type: skill\n'); await fs.writeFile( path.join(taskSkillDir29, 'SKILL.md'), '---\nname: task-skill\ndescription: A skill inside tasks dir\n---\n\nFollow the instructions in [workflow.md](workflow.md).\n', @@ -1636,7 +1632,6 @@ async function runTests() { // Test scanInstalledModules recognizes skill-only modules const skillOnlyModDir29 = path.join(tempFixture29, 'skill-only-mod'); await fs.ensureDir(path.join(skillOnlyModDir29, 'deep', 'nested', 'my-skill')); - await fs.writeFile(path.join(skillOnlyModDir29, 'deep', 'nested', 'my-skill', 'bmad-skill-manifest.yaml'), 'type: skill\n'); await fs.writeFile( path.join(skillOnlyModDir29, 'deep', 'nested', 'my-skill', 'SKILL.md'), '---\nname: my-skill\ndescription: desc\n---\n\nFollow the instructions in [workflow.md](workflow.md).\n', diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index 53f2e11c6..69b6b509f 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -50,29 +50,6 @@ class ManifestGenerator { return getInstallToBmadShared(manifest, filename); } - /** - * Native SKILL.md entrypoints can be packaged as either skills or agents. - * Both need verbatim installation for skill-format IDEs. - * @param {string|null} artifactType - Manifest type resolved for SKILL.md - * @returns {boolean} True when the directory should be installed verbatim - */ - isNativeSkillDirType(artifactType) { - return artifactType === 'skill' || artifactType === 'agent'; - } - - /** - * Check whether a loaded bmad-skill-manifest.yaml declares a native - * SKILL.md entrypoint, either as a single-entry manifest or a multi-entry map. - * @param {Object|null} manifest - Loaded manifest - * @returns {boolean} True when the manifest contains a native skill/agent entrypoint - */ - hasNativeSkillManifest(manifest) { - if (!manifest) return false; - if (manifest.__single) return this.isNativeSkillDirType(manifest.__single.type); - - return Object.values(manifest).some((entry) => this.isNativeSkillDirType(entry?.type)); - } - /** * Clean text for CSV output by normalizing whitespace. * Note: Quote escaping is handled by escapeCsv() at write time. @@ -170,9 +147,9 @@ class ManifestGenerator { /** * Recursively walk a module directory tree, collecting native SKILL.md entrypoints. - * A native entrypoint directory is one that contains both a - * bmad-skill-manifest.yaml with type: skill or type: agent AND a SKILL.md file - * with name/description frontmatter. + * A directory is discovered as a skill when it contains a SKILL.md file with + * valid name/description frontmatter (name must match directory name). + * Manifest YAML is loaded only when present — for install_to_bmad and agent metadata. * Populates this.skills[] and this.skillClaimedDirs (Set of absolute paths). */ async collectSkills() { @@ -193,77 +170,55 @@ class ManifestGenerator { return; } - // Check this directory for skill manifest - const manifest = await this.loadSkillManifest(dir); - - // Determine if this directory is a native SKILL.md entrypoint + // SKILL.md with valid frontmatter is the primary discovery gate const skillFile = 'SKILL.md'; - const artifactType = this.getArtifactType(manifest, skillFile); + const skillMdPath = path.join(dir, skillFile); + const dirName = path.basename(dir); - if (this.isNativeSkillDirType(artifactType)) { - const skillMdPath = path.join(dir, 'SKILL.md'); - const dirName = path.basename(dir); + const skillMeta = await this.parseSkillMd(skillMdPath, dir, dirName, debug); - // Validate and parse SKILL.md - const skillMeta = await this.parseSkillMd(skillMdPath, dir, dirName, debug); + if (skillMeta) { + // Load manifest when present (for install_to_bmad and agent metadata) + const manifest = await this.loadSkillManifest(dir); + const artifactType = this.getArtifactType(manifest, skillFile); - if (skillMeta) { - // Build path relative from module root (points to SKILL.md — the permanent entrypoint) - const relativePath = path.relative(modulePath, dir).split(path.sep).join('/'); - const installPath = relativePath - ? `${this.bmadFolderName}/${moduleName}/${relativePath}/${skillFile}` - : `${this.bmadFolderName}/${moduleName}/${skillFile}`; + // Build path relative from module root (points to SKILL.md — the permanent entrypoint) + const relativePath = path.relative(modulePath, dir).split(path.sep).join('/'); + const installPath = relativePath + ? `${this.bmadFolderName}/${moduleName}/${relativePath}/${skillFile}` + : `${this.bmadFolderName}/${moduleName}/${skillFile}`; - // Native SKILL.md entrypoints derive canonicalId from directory name. - // Agent entrypoints may keep canonicalId metadata for compatibility, so - // only warn for non-agent SKILL.md directories. - if (manifest && manifest.__single && manifest.__single.canonicalId && artifactType !== 'agent') { - console.warn( - `Warning: Native entrypoint manifest at ${dir}/bmad-skill-manifest.yaml contains canonicalId — this field is ignored for SKILL.md directories (directory name is the canonical ID)`, - ); - } - const canonicalId = dirName; - - this.skills.push({ - name: skillMeta.name, - description: this.cleanForCSV(skillMeta.description), - module: moduleName, - path: installPath, - canonicalId, - install_to_bmad: this.getInstallToBmad(manifest, skillFile), - }); - - // Add to files list - this.files.push({ - type: 'skill', - name: skillMeta.name, - module: moduleName, - path: installPath, - }); - - this.skillClaimedDirs.add(dir); - - if (debug) { - console.log(`[DEBUG] collectSkills: claimed skill "${skillMeta.name}" as ${canonicalId} at ${dir}`); - } + // Native SKILL.md entrypoints derive canonicalId from directory name. + // Agent entrypoints may keep canonicalId metadata for compatibility, so + // only warn for non-agent SKILL.md directories. + if (manifest && manifest.__single && manifest.__single.canonicalId && artifactType !== 'agent') { + console.warn( + `Warning: Native entrypoint manifest at ${dir}/bmad-skill-manifest.yaml contains canonicalId — this field is ignored for SKILL.md directories (directory name is the canonical ID)`, + ); } - } + const canonicalId = dirName; - // Warn if manifest says this is a native entrypoint but the directory was not claimed - if (manifest && !this.skillClaimedDirs.has(dir)) { - let hasNativeSkillType = false; - if (manifest.__single) { - hasNativeSkillType = this.isNativeSkillDirType(manifest.__single.type); - } else { - for (const key of Object.keys(manifest)) { - if (this.isNativeSkillDirType(manifest[key]?.type)) { - hasNativeSkillType = true; - break; - } - } - } - if (hasNativeSkillType && debug) { - console.log(`[DEBUG] collectSkills: dir has native SKILL.md manifest but failed validation: ${dir}`); + this.skills.push({ + name: skillMeta.name, + description: this.cleanForCSV(skillMeta.description), + module: moduleName, + path: installPath, + canonicalId, + install_to_bmad: this.getInstallToBmad(manifest, skillFile), + }); + + // Add to files list + this.files.push({ + type: 'skill', + name: skillMeta.name, + module: moduleName, + path: installPath, + }); + + this.skillClaimedDirs.add(dir); + + if (debug) { + console.log(`[DEBUG] collectSkills: claimed skill "${skillMeta.name}" as ${canonicalId} at ${dir}`); } } @@ -1384,11 +1339,10 @@ class ManifestGenerator { const hasTasks = await fs.pathExists(path.join(modulePath, 'tasks')); const hasTools = await fs.pathExists(path.join(modulePath, 'tools')); - // Check for native-entrypoint-only modules: recursive scan for - // bmad-skill-manifest.yaml with type: skill or type: agent + // Check for native-entrypoint-only modules: recursive scan for SKILL.md let hasSkills = false; if (!hasAgents && !hasWorkflows && !hasTasks && !hasTools) { - hasSkills = await this._hasSkillManifestRecursive(modulePath); + hasSkills = await this._hasSkillMdRecursive(modulePath); } // If it has any of these directories or skill manifests, it's likely a module @@ -1404,13 +1358,12 @@ class ManifestGenerator { } /** - * Recursively check if a directory tree contains a bmad-skill-manifest.yaml that - * declares a native SKILL.md entrypoint (type: skill or type: agent). + * Recursively check if a directory tree contains a SKILL.md file. * Skips directories starting with . or _. * @param {string} dir - Directory to search - * @returns {boolean} True if a skill manifest is found + * @returns {boolean} True if a SKILL.md is found */ - async _hasSkillManifestRecursive(dir) { + async _hasSkillMdRecursive(dir) { let entries; try { entries = await fs.readdir(dir, { withFileTypes: true }); @@ -1418,15 +1371,14 @@ class ManifestGenerator { return false; } - // Check for manifest in this directory - const manifest = await this.loadSkillManifest(dir); - if (this.hasNativeSkillManifest(manifest)) return true; + // Check for SKILL.md in this directory + if (entries.some((e) => !e.isDirectory() && e.name === 'SKILL.md')) return true; // Recurse into subdirectories for (const entry of entries) { if (!entry.isDirectory()) continue; if (entry.name.startsWith('.') || entry.name.startsWith('_')) continue; - if (await this._hasSkillManifestRecursive(path.join(dir, entry.name))) return true; + if (await this._hasSkillMdRecursive(path.join(dir, entry.name))) return true; } return false;