Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

pi/agent/skills/writing-skills/scripts/check.test.mjs

Raw
import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import {
	mkdtempSync,
	mkdirSync,
	rmSync,
	writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import test from "node:test";
import { fileURLToPath } from "node:url";

const skillDir = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
const checker = path.join(skillDir, "scripts", "check.mjs");
const temporaryDirectories = [];

function fixture(name, files) {
	const directory = mkdtempSync(path.join(tmpdir(), "writing-skills-check-"));
	temporaryDirectories.push(directory);
	const root = path.join(directory, name);
	mkdirSync(root, { recursive: true });
	for (const [relativePath, contents] of Object.entries(files)) {
		const file = path.join(root, relativePath);
		mkdirSync(path.dirname(file), { recursive: true });
		writeFileSync(file, contents);
	}
	return root;
}

function skill(name = "fixture", body = "") {
	return `---\nname: ${name}\ndescription: Fixture skill\n---\n\n# Fixture\n\n${body}`;
}

function check(directory) {
	const result = spawnSync(process.execPath, [checker, directory], {
		encoding: "utf8",
	});
	assert.equal(result.error, undefined, result.error?.message);
	return {
		status: result.status,
		output: JSON.parse(result.stdout),
	};
}

function codes(output) {
	return output.issues.map((issue) => issue.code).sort();
}

test.after(() => {
	for (const directory of temporaryDirectories) {
		rmSync(directory, { recursive: true, force: true });
	}
});

test("minimal prose-only skill needs no package", () => {
	const directory = fixture("fixture", { "SKILL.md": skill() });
	const result = check(directory);

	assert.equal(result.status, 0);
	assert.equal(result.output.ok, true);
	assert.deepEqual(result.output.issues, []);
});

test("scripted skill requires package and test file", () => {
	const directory = fixture("fixture", {
		"SKILL.md": skill(),
		"scripts/helper.mjs": "// fixture helper; never execute\n",
	});
	const result = check(directory);

	assert.equal(result.status, 1);
	assert.equal(result.output.ok, false);
	assert.deepEqual(codes(result.output), ["package.missing", "tests.missing"]);
});

test("scripted skill rejects a missing test file", () => {
	const directory = fixture("fixture", {
		"SKILL.md": skill(),
		"package.json": JSON.stringify({ scripts: { test: "node --test" } }),
		"scripts/helper.mjs": "// fixture helper; never execute\n",
	});
	const result = check(directory);

	assert.equal(result.status, 1);
	assert.deepEqual(codes(result.output), ["tests.missing"]);
});

test("scripted skill accepts direct node test packaging", () => {
	const directory = fixture("fixture", {
		"SKILL.md": skill(),
		"package.json": JSON.stringify({
			scripts: { test: "node --test scripts/*.test.mjs" },
		}),
		"scripts/helper.mjs": "// fixture helper; never execute\n",
		"scripts/helper.test.mjs": "// fixture test; never execute\n",
	});
	const result = check(directory);

	assert.equal(result.status, 0);
	assert.equal(result.output.ok, true);
});

test("CLI reports usage errors with status 2", () => {
	const result = spawnSync(process.execPath, [checker], { encoding: "utf8" });

	assert.equal(result.status, 2);
	assert.deepEqual(JSON.parse(result.stdout), {
		error: "Usage: node scripts/check.mjs <skill-dir>",
	});
});

test("owning skill passes its structural self-check", () => {
	const result = check(skillDir);

	assert.equal(result.status, 0);
	assert.equal(result.output.skill, skillDir);
	assert.equal(result.output.ok, true);
	assert.deepEqual(result.output.issues, []);
});