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')