fix(installer): skip workflow metadata for native skills

This commit is contained in:
Alex Verkhovsky 2026-03-12 16:42:59 -06:00
parent 08464ca6a1
commit d52e7026ed
2 changed files with 36 additions and 3 deletions

View File

@ -1,6 +1,4 @@
--- ---
name: bmad-brainstorming
description: 'Facilitate interactive brainstorming sessions using diverse creative techniques and ideation methods. Use when the user says help me brainstorm or help me ideate.'
context_file: '' # Optional context file path for project-specific guidance context_file: '' # Optional context file path for project-specific guidance
--- ---

View File

@ -1,5 +1,6 @@
const path = require('node:path'); const path = require('node:path');
const fs = require('fs-extra'); const fs = require('fs-extra');
const yaml = require('yaml');
const { XmlHandler } = require('../../../lib/xml-handler'); const { XmlHandler } = require('../../../lib/xml-handler');
const prompts = require('../../../lib/prompts'); const prompts = require('../../../lib/prompts');
const { getSourcePath } = require('../../../lib/project-root'); const { getSourcePath } = require('../../../lib/project-root');
@ -339,6 +340,10 @@ class BaseIdeSetup {
const entries = await fs.readdir(dir, { withFileTypes: true }); const entries = await fs.readdir(dir, { withFileTypes: true });
if (await this.isSkillDirectory(dir)) {
return workflows;
}
for (const entry of entries) { for (const entry of entries) {
const fullPath = path.join(dir, entry.name); const fullPath = path.join(dir, entry.name);
@ -349,7 +354,6 @@ class BaseIdeSetup {
} else if (entry.isFile() && entry.name === 'workflow.md') { } else if (entry.isFile() && entry.name === 'workflow.md') {
// Read workflow.md frontmatter to get name and standalone property // Read workflow.md frontmatter to get name and standalone property
try { try {
const yaml = require('yaml');
const content = await fs.readFile(fullPath, 'utf8'); const content = await fs.readFile(fullPath, 'utf8');
const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/); const frontmatterMatch = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
if (!frontmatterMatch) continue; if (!frontmatterMatch) continue;
@ -377,6 +381,37 @@ class BaseIdeSetup {
return workflows; return workflows;
} }
/**
* Check whether a directory is claimed by a native skill.
* Skill directories should be surfaced via SKILL.md, not workflow.md metadata.
* @param {string} dir - Directory path
* @returns {boolean}
*/
async isSkillDirectory(dir) {
const manifestPath = path.join(dir, 'bmad-skill-manifest.yaml');
const skillPath = path.join(dir, 'SKILL.md');
if (!(await fs.pathExists(manifestPath)) || !(await fs.pathExists(skillPath))) {
return false;
}
try {
const manifest = yaml.parse(await fs.readFile(manifestPath, 'utf8'));
if (!manifest || typeof manifest !== 'object') {
return false;
}
if (manifest.__single) {
return manifest.__single.type === 'skill';
}
return Object.values(manifest).some((entry) => entry && typeof entry === 'object' && entry.type === 'skill');
} catch {
return false;
}
}
/** /**
* Scan a directory for files with specific extension(s) * Scan a directory for files with specific extension(s)
* @param {string} dir - Directory to scan * @param {string} dir - Directory to scan