mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-05 05:05:08 +02:00
fix: make skill/template discovery dynamic
Replace hardcoded SKILL_FILES and TEMPLATES arrays in skill-check.ts, gen-skill-docs.ts, and dev-skill.ts with a shared discover-skills.ts utility that scans the filesystem. New skills are now picked up automatically without updating three separate lists. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
+3
-15
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user