diff --git a/scripts/generate-skill-references.mjs b/scripts/generate-skill-references.mjs index 4bc0f0e..9002f26 100644 --- a/scripts/generate-skill-references.mjs +++ b/scripts/generate-skill-references.mjs @@ -8,7 +8,11 @@ * shape. The agent reads these alongside the hand-written reference to get * the exact current field surface without us re-documenting fields in prose. * - * Usage: node scripts/generate-skill-references.mjs + * Usage: node scripts/generate-skill-references.mjs [--out ] + * + * `--out` writes the tree under instead of the repo (and leaves the + * SKILL.md version stamps alone), so the drift test never rewrites files + * other tests are reading. * * Output is idempotent: re-running produces byte-identical files. The * openapi-drift test (`test/skills/openapi-drift.test.ts`) depends on this. @@ -22,6 +26,8 @@ import { preprocessSpec } from './lib/preprocess.mjs'; const __dirname = dirname(fileURLToPath(import.meta.url)); const ROOT = join(__dirname, '..'); const SPEC_PATH = join(ROOT, 'docs/openapi/monitoring-api.json'); +const outFlag = process.argv.indexOf('--out'); +const OUT_ROOT = outFlag === -1 ? ROOT : process.argv[outFlag + 1]; /** * Map each skill + resource to the OpenAPI schema names we care about. @@ -244,12 +250,12 @@ function stampVersions() { } function main() { - stampVersions(); + if (OUT_ROOT === ROOT) stampVersions(); const spec = loadSpec(); let total = 0; for (const [skill, resources] of Object.entries(RESOURCES)) { - const outDir = join(ROOT, 'skills', skill, 'references', '_generated'); + const outDir = join(OUT_ROOT, 'skills', skill, 'references', '_generated'); if (existsSync(outDir)) rmSync(outDir, { recursive: true, force: true }); mkdirSync(outDir, { recursive: true }); diff --git a/test/skills/openapi-drift.test.ts b/test/skills/openapi-drift.test.ts index e84f1a6..0abd126 100644 --- a/test/skills/openapi-drift.test.ts +++ b/test/skills/openapi-drift.test.ts @@ -1,6 +1,7 @@ import {expect, test} from 'vitest' import {execSync} from 'node:child_process' -import {readFileSync, readdirSync} from 'node:fs' +import {mkdtempSync, readFileSync, readdirSync, rmSync} from 'node:fs' +import {tmpdir} from 'node:os' import {dirname, join} from 'node:path' import {fileURLToPath} from 'node:url' @@ -16,12 +17,17 @@ const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..') * changes (via spec-propagate from mono), the drift check fires. */ test('generated skill references are in sync with OpenAPI spec', () => { - const before = snapshotGenerated() + const before = snapshotGenerated(ROOT) - // Regenerate. - execSync('node scripts/generate-skill-references.mjs', {cwd: ROOT, stdio: 'pipe'}) - - const after = snapshotGenerated() + // Regenerate into a temp dir: other tests read the committed copies. + const out = mkdtempSync(join(tmpdir(), 'skill-refs-')) + let after: Record + try { + execSync(`node scripts/generate-skill-references.mjs --out ${JSON.stringify(out)}`, {cwd: ROOT, stdio: 'pipe'}) + after = snapshotGenerated(out) + } finally { + rmSync(out, {recursive: true, force: true}) + } const diffs: string[] = [] for (const [path, content] of Object.entries(after)) { @@ -37,9 +43,9 @@ test('generated skill references are in sync with OpenAPI spec', () => { ).toEqual([]) }) -function snapshotGenerated(): Record { +function snapshotGenerated(root: string): Record { const out: Record = {} - const skillsDir = join(ROOT, 'skills') + const skillsDir = join(root, 'skills') for (const skill of readdirSync(skillsDir)) { if (!skill.startsWith('devhelm-')) continue const gen = join(skillsDir, skill, 'references', '_generated')