diff --git a/scripts/dev-skill.ts b/scripts/dev-skill.ts index 1842c83..ae6ba30 100644 --- a/scripts/dev-skill.ts +++ b/scripts/dev-skill.ts @@ -7,16 +7,17 @@ */ import { validateSkill } from '../test/helpers/skill-parser'; +import { discoverTemplates } from './discover-skills'; import { execSync } from 'child_process'; import * as fs from 'fs'; import * as path from 'path'; const ROOT = path.resolve(import.meta.dir, '..'); -const TEMPLATES = [ - { tmpl: path.join(ROOT, 'SKILL.md.tmpl'), output: 'SKILL.md' }, - { tmpl: path.join(ROOT, 'browse', 'SKILL.md.tmpl'), output: 'browse/SKILL.md' }, -]; +const TEMPLATES = discoverTemplates(ROOT).map(t => ({ + tmpl: path.join(ROOT, t.tmpl), + output: t.output, +})); function regenerateAndValidate() { // Regenerate diff --git a/scripts/discover-skills.ts b/scripts/discover-skills.ts new file mode 100644 index 0000000..5c50924 --- /dev/null +++ b/scripts/discover-skills.ts @@ -0,0 +1,39 @@ +/** + * Shared discovery for SKILL.md and .tmpl files. + * Scans root + one level of subdirs, skipping node_modules/.git/dist. + */ + +import * as fs from 'fs'; +import * as path from 'path'; + +const SKIP = new Set(['node_modules', '.git', 'dist']); + +function subdirs(root: string): string[] { + return fs.readdirSync(root, { withFileTypes: true }) + .filter(d => d.isDirectory() && !SKIP.has(d.name)) + .map(d => d.name); +} + +export function discoverTemplates(root: string): Array<{ tmpl: string; output: string }> { + const dirs = ['', ...subdirs(root)]; + const results: Array<{ tmpl: string; output: string }> = []; + for (const dir of dirs) { + const rel = dir ? `${dir}/SKILL.md.tmpl` : 'SKILL.md.tmpl'; + if (fs.existsSync(path.join(root, rel))) { + results.push({ tmpl: rel, output: rel.replace(/\.tmpl$/, '') }); + } + } + return results; +} + +export function discoverSkillFiles(root: string): string[] { + const dirs = ['', ...subdirs(root)]; + const results: string[] = []; + for (const dir of dirs) { + const rel = dir ? `${dir}/SKILL.md` : 'SKILL.md'; + if (fs.existsSync(path.join(root, rel))) { + results.push(rel); + } + } + return results; +} diff --git a/scripts/gen-skill-docs.ts b/scripts/gen-skill-docs.ts index bf14214..5f2ba45 100644 --- a/scripts/gen-skill-docs.ts +++ b/scripts/gen-skill-docs.ts @@ -11,6 +11,7 @@ import { COMMAND_DESCRIPTIONS } from '../browse/src/commands'; import { SNAPSHOT_FLAGS } from '../browse/src/snapshot'; +import { discoverTemplates } from './discover-skills'; import * as fs from 'fs'; import * as path from 'path'; @@ -171,23 +172,7 @@ function processTemplate(tmplPath: string): { outputPath: string; content: strin // ─── Main ─────────────────────────────────────────────────── function findTemplates(): string[] { - const templates: string[] = []; - const candidates = [ - path.join(ROOT, 'SKILL.md.tmpl'), - path.join(ROOT, 'browse', 'SKILL.md.tmpl'), - path.join(ROOT, 'qa', 'SKILL.md.tmpl'), - path.join(ROOT, 'setup-browser-cookies', 'SKILL.md.tmpl'), - path.join(ROOT, 'ship', 'SKILL.md.tmpl'), - path.join(ROOT, 'review', 'SKILL.md.tmpl'), - path.join(ROOT, 'plan-ceo-review', 'SKILL.md.tmpl'), - path.join(ROOT, 'plan-eng-review', 'SKILL.md.tmpl'), - path.join(ROOT, 'retro', 'SKILL.md.tmpl'), - path.join(ROOT, 'gstack-upgrade', 'SKILL.md.tmpl'), - ]; - for (const p of candidates) { - if (fs.existsSync(p)) templates.push(p); - } - return templates; + return discoverTemplates(ROOT).map(t => path.join(ROOT, t.tmpl)); } let hasChanges = false; diff --git a/scripts/skill-check.ts b/scripts/skill-check.ts index fd10b52..71628c8 100644 --- a/scripts/skill-check.ts +++ b/scripts/skill-check.ts @@ -9,6 +9,7 @@ */ import { validateSkill } from '../test/helpers/skill-parser'; +import { discoverTemplates, discoverSkillFiles } from './discover-skills'; import * as fs from 'fs'; import * as path from 'path'; import { execSync } from 'child_process'; @@ -16,17 +17,7 @@ import { execSync } from 'child_process'; const ROOT = path.resolve(import.meta.dir, '..'); // Find all SKILL.md files -const SKILL_FILES = [ - 'SKILL.md', - 'browse/SKILL.md', - 'qa/SKILL.md', - 'ship/SKILL.md', - 'review/SKILL.md', - 'retro/SKILL.md', - 'plan-ceo-review/SKILL.md', - 'plan-eng-review/SKILL.md', - 'setup-browser-cookies/SKILL.md', -].filter(f => fs.existsSync(path.join(ROOT, f))); +const SKILL_FILES = discoverSkillFiles(ROOT); let hasErrors = false; @@ -63,10 +54,7 @@ for (const file of SKILL_FILES) { // ─── Templates ────────────────────────────────────────────── console.log('\n Templates:'); -const TEMPLATES = [ - { tmpl: 'SKILL.md.tmpl', output: 'SKILL.md' }, - { tmpl: 'browse/SKILL.md.tmpl', output: 'browse/SKILL.md' }, -]; +const TEMPLATES = discoverTemplates(ROOT); for (const { tmpl, output } of TEMPLATES) { const tmplPath = path.join(ROOT, tmpl);