Files

204 lines
7.4 KiB
TypeScript

import assert from "node:assert/strict"
import { existsSync, mkdtempSync, mkdirSync, readFileSync, 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"
import {
buildSkills,
loadClassification,
renderMatrix,
updateDocMatrix,
type ClassificationEntry,
} from "../scripts/generate.ts"
import { isUserInvoked, parseFrontmatter } from "../src/frontmatter.ts"
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..")
test("parseFrontmatter: plain, quoted with escapes and colons, DMI, nested blocks skipped", () => {
const plain = parseFrontmatter(
"---\nname: tdd\ndescription: Test-driven development\n---\nBody\n",
)
assert.equal(plain.frontmatter.name, "tdd")
assert.equal(plain.frontmatter.description, "Test-driven development")
assert.equal(plain.body, "Body\n")
const quoted = parseFrontmatter(
'---\nname: code-review\ndescription: "Review since a fixed point: commit, branch, or \\"X\\"."\nmetadata:\n credits:\n author: Dex\n---\nx',
)
assert.equal(
quoted.frontmatter.description,
'Review since a fixed point: commit, branch, or "X".',
)
assert.equal(quoted.frontmatter.metadata, "") // nested block skipped, not misparsed
const dmi = parseFrontmatter("---\nname: to-spec\ndisable-model-invocation: true\n---\nx")
assert.equal(isUserInvoked(dmi.frontmatter), true)
assert.equal(isUserInvoked(plain.frontmatter), false)
const none = parseFrontmatter("no frontmatter here")
assert.deepEqual(none.frontmatter, {})
})
function fixtureSkill(
upstream: string,
bucket: string,
name: string,
opts: { dmi?: boolean } = {},
) {
const dir = path.join(upstream, bucket, name)
mkdirSync(path.join(dir, "agents"), { recursive: true })
writeFileSync(
path.join(dir, "SKILL.md"),
`---\nname: ${name}\ndescription: "The ${name} skill"\n` +
(opts.dmi ? "disable-model-invocation: true\n" : "") +
`---\n\nBody of ${name}.\n`,
)
writeFileSync(path.join(dir, "agents", "openai.yaml"), "interface:\n display_name: X\n")
writeFileSync(path.join(dir, "EXTRA.md"), "supporting file")
return dir
}
function entry(name: string, bucket: string, over: Partial<ClassificationEntry> = {}) {
return {
name,
bucket,
classification: "skill",
user_invoked: false,
artifacts: ["skill:verbatim"],
depends_on: [],
status: "analyzed",
rationale: "r",
...over,
} as ClassificationEntry
}
test("buildSkills copies verbatim minus agents/, builds manifest, honors exclusions", () => {
const dir = mkdtempSync(path.join(tmpdir(), "gen-test-"))
try {
const upstream = path.join(dir, "upstream")
fixtureSkill(upstream, "engineering", "tdd")
fixtureSkill(upstream, "engineering", "to-spec", { dmi: true })
fixtureSkill(upstream, "in-progress", "beta")
const out = path.join(dir, "skills")
const manifest = buildSkills({
upstreamSkills: upstream,
entries: [
entry("tdd", "engineering"),
entry("to-spec", "engineering"),
entry("beta", "in-progress", { artifacts: ["excluded"] }),
],
skillsOut: out,
})
assert.deepEqual(
manifest,
[
{
id: "tdd",
name: "tdd",
description: "The tdd skill",
autoinvoke: true,
path: "skills/tdd/SKILL.md",
},
{
id: "to-spec",
name: "to-spec",
description: "The to-spec skill",
autoinvoke: false,
path: "skills/to-spec/SKILL.md",
},
].sort((a, b) => a.id.localeCompare(b.id)),
)
assert.ok(existsSync(path.join(out, "tdd/SKILL.md")))
assert.ok(existsSync(path.join(out, "tdd/EXTRA.md")), "supporting files preserved")
assert.ok(!existsSync(path.join(out, "tdd/agents")), "agents/openai.yaml stripped")
assert.ok(!existsSync(path.join(out, "beta")), "excluded skill not copied")
} finally {
rmSync(dir, { recursive: true, force: true })
}
})
test("buildSkills throws on unclassified upstream skills and missing classified ones", () => {
const dir = mkdtempSync(path.join(tmpdir(), "gen-test-"))
try {
const upstream = path.join(dir, "upstream")
fixtureSkill(upstream, "engineering", "mystery")
assert.throws(
() =>
buildSkills({ upstreamSkills: upstream, entries: [], skillsOut: path.join(dir, "out") }),
/unclassified upstream skill: engineering\/mystery/,
)
assert.throws(
() =>
buildSkills({
upstreamSkills: upstream,
entries: [entry("ghost", "engineering")],
skillsOut: path.join(dir, "out"),
}),
/classified skill missing upstream: engineering\/ghost/,
)
} finally {
rmSync(dir, { recursive: true, force: true })
}
})
test("updateDocMatrix replaces only the marked section", () => {
const dir = mkdtempSync(path.join(tmpdir(), "gen-test-"))
try {
const doc = path.join(dir, "doc.md")
writeFileSync(doc, "prose\n<!-- matrix:start -->\nold\n<!-- matrix:end -->\nmore prose\n")
updateDocMatrix(doc, "NEW TABLE")
assert.equal(
readFileSync(doc, "utf8"),
"prose\n<!-- matrix:start -->\n\nNEW TABLE\n\n<!-- matrix:end -->\nmore prose\n",
)
assert.throws(() => updateDocMatrix(doc.replace("doc", "x"), "t"), /ENOENT/)
writeFileSync(path.join(dir, "bad.md"), "no markers")
assert.throws(() => updateDocMatrix(path.join(dir, "bad.md"), "t"), /missing matrix markers/)
} finally {
rmSync(dir, { recursive: true, force: true })
}
})
test("renderMatrix: one row per entry with escaped cells", () => {
const md = renderMatrix([
entry("tdd", "engineering", { depends_on: ["codebase-design"], rationale: "a | b" }),
])
const [header, sep, row] = md.split("\n")
assert.match(header, /^\| Upstream skill \| Bucket \| DMI \|/)
assert.match(sep, /^\| --- \|/)
assert.equal(
row,
"| tdd | eng | | skill | skill:verbatim | codebase-design | analyzed | a \\| b |",
)
})
// Regression against the real vendored snapshot: every classified-verbatim skill must parse,
// and upstream disable-model-invocation must agree with classification.json user_invoked.
test("real snapshot: all vendored skills parse and DMI flags match classification", () => {
const entries = loadClassification(path.join(root, ".opencode/state/classification.json"))
const manifest = JSON.parse(readFileSync(path.join(root, "manifest.json"), "utf8"))
const vendored = entries.filter((e) => e.artifacts.includes("skill:verbatim"))
assert.equal(vendored.length, manifest.length)
assert.equal(entries.filter((e) => e.status === "needs-review").length, 0)
for (const e of vendored) {
const md = readFileSync(path.join(root, "skills", e.name, "SKILL.md"), "utf8")
const { frontmatter } = parseFrontmatter(md)
assert.ok(frontmatter.name, `${e.name}: name parsed`)
assert.ok(frontmatter.description, `${e.name}: description parsed`)
assert.equal(
isUserInvoked(frontmatter),
e.user_invoked,
`${e.name}: DMI flag disagrees with classification.json`,
)
const m = manifest.find((x: { id: string }) => x.id === e.name)
assert.equal(m.autoinvoke, !e.user_invoked, `${e.name}: manifest autoinvoke`)
assert.ok(
!existsSync(path.join(root, "skills", e.name, "agents")),
`${e.name}: openai.yaml stripped`,
)
}
assert.equal(manifest.filter((m: { autoinvoke: boolean }) => !m.autoinvoke).length, 16)
})