mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-05 13:15:24 +02:00
feat: use frontmatter name: for skill symlinks and Codex paths
Patch all 3 name-derivation paths to read name: from SKILL.md frontmatter instead of relying solely on directory basenames. This enables directory names that differ from invocation names (e.g., run-tests/ directory with name: test). - setup: link_claude_skill_dirs reads name: via grep, falls back to basename - gen-skill-docs.ts: codexSkillName uses frontmatter name for Codex output paths - gen-skill-docs.ts: moved frontmatter extraction before Codex path logic Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -83,11 +83,15 @@ const OPENAI_LITMUS_CHECKS = [
|
||||
// ─── External Host Helpers ───────────────────────────────────
|
||||
|
||||
// Re-export local copy for use in this file (matches codex-helpers.ts)
|
||||
function externalSkillName(skillDir: string): string {
|
||||
// Accepts optional frontmatter name to support directory/invocation name divergence
|
||||
function externalSkillName(skillDir: string, frontmatterName?: string): string {
|
||||
// Root skill (skillDir === '' or '.') always maps to 'gstack' regardless of frontmatter
|
||||
if (skillDir === '.' || skillDir === '') return 'gstack';
|
||||
// Use frontmatter name when it differs from directory name (e.g., run-tests/ with name: test)
|
||||
const baseName = frontmatterName && frontmatterName !== skillDir ? frontmatterName : skillDir;
|
||||
// Don't double-prefix: gstack-upgrade → gstack-upgrade (not gstack-gstack-upgrade)
|
||||
if (skillDir.startsWith('gstack-')) return skillDir;
|
||||
return `gstack-${skillDir}`;
|
||||
if (baseName.startsWith('gstack-')) return baseName;
|
||||
return `gstack-${baseName}`;
|
||||
}
|
||||
|
||||
function extractNameAndDescription(content: string): { name: string; description: string } {
|
||||
@@ -255,11 +259,12 @@ function processExternalHost(
|
||||
skillDir: string,
|
||||
extractedDescription: string,
|
||||
ctx: TemplateContext,
|
||||
frontmatterName?: string,
|
||||
): { content: string; outputPath: string; outputDir: string; symlinkLoop: boolean } {
|
||||
const config = EXTERNAL_HOST_CONFIG[host];
|
||||
if (!config) throw new Error(`No external host config for: ${host}`);
|
||||
|
||||
const name = externalSkillName(skillDir === '.' ? '' : skillDir);
|
||||
const name = externalSkillName(skillDir === '.' ? '' : skillDir, frontmatterName);
|
||||
const outputDir = path.join(ROOT, config.hostSubdir, 'skills', name);
|
||||
fs.mkdirSync(outputDir, { recursive: true });
|
||||
const outputPath = path.join(outputDir, 'SKILL.md');
|
||||
@@ -324,10 +329,13 @@ function processTemplate(tmplPath: string, host: Host = 'claude'): { outputPath:
|
||||
// Determine skill directory relative to ROOT
|
||||
const skillDir = path.relative(ROOT, path.dirname(tmplPath));
|
||||
|
||||
// Extract skill name from frontmatter for TemplateContext
|
||||
// Extract skill name from frontmatter early — needed for both TemplateContext and external host output paths.
|
||||
// When frontmatter name: differs from directory name (e.g., run-tests/ with name: test),
|
||||
// the frontmatter name is used for external skill naming and setup script symlinks.
|
||||
const { name: extractedName, description: extractedDescription } = extractNameAndDescription(tmplContent);
|
||||
const skillName = extractedName || path.basename(path.dirname(tmplPath));
|
||||
|
||||
|
||||
// Extract benefits-from list from frontmatter (inline YAML: benefits-from: [a, b])
|
||||
const benefitsMatch = tmplContent.match(/^benefits-from:\s*\[([^\]]*)\]/m);
|
||||
const benefitsFrom = benefitsMatch
|
||||
@@ -362,7 +370,7 @@ function processTemplate(tmplPath: string, host: Host = 'claude'): { outputPath:
|
||||
if (host === 'claude') {
|
||||
content = transformFrontmatter(content, host);
|
||||
} else {
|
||||
const result = processExternalHost(content, tmplContent, host, skillDir, extractedDescription, ctx);
|
||||
const result = processExternalHost(content, tmplContent, host, skillDir, extractedDescription, ctx, extractedName || undefined);
|
||||
content = result.content;
|
||||
outputPath = result.outputPath;
|
||||
symlinkLoop = result.symlinkLoop;
|
||||
|
||||
Reference in New Issue
Block a user