From 22e466937a34fe4f2c7d2d199599c7a76cbcf51f Mon Sep 17 00:00:00 2001 From: Pedro Rodrigues <44656907+Rodriguespn@users.noreply.github.com> Date: Fri, 30 Jan 2026 13:39:59 +0000 Subject: [PATCH] fix: require reference files at root of references/ directory (#32) Remove support for nested subdirectories in references/. All markdown reference files must now be placed directly in the references/ directory (e.g., references/auth-signup.md). - Replace getMarkdownFilesRecursive with getMarkdownFiles (flat) - Simplify parseAllSections to only read root _sections.md - Update getReferenceFiles to skip subdirectories - Keep deprecated getMarkdownFilesRecursive alias for compatibility Co-authored-by: Claude Opus 4.5 --- packages/skills-build/src/build.ts | 63 ++++++++++----------------- packages/skills-build/src/validate.ts | 6 +-- 2 files changed, 26 insertions(+), 43 deletions(-) diff --git a/packages/skills-build/src/build.ts b/packages/skills-build/src/build.ts index bb9561d..03b06c8 100644 --- a/packages/skills-build/src/build.ts +++ b/packages/skills-build/src/build.ts @@ -29,9 +29,9 @@ function generateSectionMap(sections: Section[]): Record { } /** - * Recursively get all markdown files from a directory + * Get all markdown files from a directory (flat, no subdirectories) */ -function getMarkdownFilesRecursive(dir: string): string[] { +function getMarkdownFiles(dir: string): string[] { const files: string[] = []; if (!existsSync(dir)) { @@ -49,10 +49,8 @@ function getMarkdownFilesRecursive(dir: string): string[] { const fullPath = join(dir, entry); const stat = statSync(fullPath); - if (stat.isDirectory()) { - // Recursively scan subdirectories - files.push(...getMarkdownFilesRecursive(fullPath)); - } else if (entry.endsWith(".md")) { + // Only include files, skip directories + if (stat.isFile() && entry.endsWith(".md")) { files.push(fullPath); } } @@ -60,6 +58,13 @@ function getMarkdownFilesRecursive(dir: string): string[] { return files; } +/** + * @deprecated Use getMarkdownFiles instead - nested directories are not supported + */ +function getMarkdownFilesRecursive(dir: string): string[] { + return getMarkdownFiles(dir); +} + /** * Parse section definitions from _sections.md (legacy function for validation) */ @@ -171,36 +176,20 @@ function parseSectionsFromFile(filePath: string): Section[] { } /** - * Parse all _sections.md files from references directory and subdirectories + * Parse _sections.md from references directory root only + * Note: Nested directories are not supported - all reference files should be in references/ root */ function parseAllSections(referencesDir: string): Section[] { - const allSections: Section[] = []; - - // Parse root _sections.md - const rootSectionsFile = join(referencesDir, "_sections.md"); - if (existsSync(rootSectionsFile)) { - allSections.push(...parseSectionsFromFile(rootSectionsFile)); + const sectionsFile = join(referencesDir, "_sections.md"); + if (existsSync(sectionsFile)) { + return parseSectionsFromFile(sectionsFile); } - - // Scan subdirectories for _sections.md files - if (existsSync(referencesDir)) { - const entries = readdirSync(referencesDir); - for (const entry of entries) { - const fullPath = join(referencesDir, entry); - if (statSync(fullPath).isDirectory()) { - const subSectionsFile = join(fullPath, "_sections.md"); - if (existsSync(subSectionsFile)) { - allSections.push(...parseSectionsFromFile(subSectionsFile)); - } - } - } - } - - return allSections; + return []; } /** - * Get all reference files (excluding _sections.md) + * Get all reference files from references/ root (excluding _sections.md) + * Note: Nested directories are not supported - all reference files should be in references/ root */ function getReferenceFiles(referencesDir: string): string[] { const files: string[] = []; @@ -220,15 +209,8 @@ function getReferenceFiles(referencesDir: string): string[] { const fullPath = join(referencesDir, entry); const stat = statSync(fullPath); - if (stat.isDirectory()) { - // Recursively scan subdirectories - const subEntries = readdirSync(fullPath); - for (const subEntry of subEntries) { - if (!subEntry.startsWith("_") && subEntry.endsWith(".md")) { - files.push(join(fullPath, subEntry)); - } - } - } else if (entry.endsWith(".md")) { + // Only include files at root level, skip directories + if (stat.isFile() && entry.endsWith(".md")) { files.push(fullPath); } } @@ -416,7 +398,8 @@ if (isMainModule) { export { buildSkill, generateSectionMap, - getMarkdownFilesRecursive, + getMarkdownFiles, + getMarkdownFilesRecursive, // deprecated, use getMarkdownFiles getReferenceFiles, parseAllSections, parseSections, diff --git a/packages/skills-build/src/validate.ts b/packages/skills-build/src/validate.ts index f1f5ee5..10830f1 100644 --- a/packages/skills-build/src/validate.ts +++ b/packages/skills-build/src/validate.ts @@ -2,7 +2,7 @@ import { existsSync } from "node:fs"; import { basename } from "node:path"; import { generateSectionMap, - getMarkdownFilesRecursive, + getMarkdownFiles, parseAllSections, parseSections, } from "./build.js"; @@ -158,8 +158,8 @@ function validateSkill(paths: SkillPaths): boolean { const sections = parseAllSections(paths.referencesDir); const sectionMap = generateSectionMap(sections); - // Get all markdown files recursively (excluding _ prefixed files) - const files = getMarkdownFilesRecursive(paths.referencesDir); + // Get all markdown files from references/ root (excluding _ prefixed files) + const files = getMarkdownFiles(paths.referencesDir); if (files.length === 0) { console.log(` No rule files found.`);