import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; const skill = readFileSync(new URL("../SKILL.md", import.meta.url), "utf8"); const prompt = readFileSync(new URL("../../../prompts/wiki.md", import.meta.url), "utf8"); function body(markdown) { const match = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/.exec(markdown); assert.ok(match, "YAML frontmatter must be delimited"); assert.match(match[1], /^description: "[^\n]+"$/m); return match[2]; } function section(heading) { const text = body(skill).split(`## ${heading}\n`)[1]; assert.ok(text, `Missing section: ${heading}`); return text.split("\n## ")[0]; } test("prompt delegates behavior without duplicating the skill", () => { const text = body(prompt); assert.match(text, /Load and follow the `wiki` skill/); assert.match(text, /\$ARGUMENTS/); assert.doesNotMatch(text, /raw-sources|SCHEMA\.md|web_fetch|git_clone_safe|\/wiki init|→/); assert.ok(text.trim().split("\n").length <= 8, "Keep the dispatcher thin"); }); test("skill owns routing and keeps reads separate from mutations", () => { assert.match(skill, /^name: wiki$/m); assert.match(section("Dispatch"), /plain text.*recall/i); assert.match(section("Dispatch"), /No args.*current focus/i); assert.match(section("Dispatch"), /recall.*status.*lint.*digest.*read-only/i); assert.match(section("Dispatch"), /Loading.*not.*permission/i); assert.match(section("Dispatch"), /Do not auto-ingest/i); }); test("initialization checks precede schema reads without auto-repair", () => { const gate = section("Initialization gate"); for (const state of ["absent", "partial", "initialized"]) assert.match(gate, new RegExp(state)); for (const path of ["SCHEMA.md", "index.md", "log.md", "raw-sources/index.md"]) assert.ok(gate.includes(path)); assert.match(gate, /Do not use `read` as an existence check/); assert.match(gate, /wiki not initialized/); assert.match(gate, /explicit repair approval/); assert.match(gate, /permission.*errors.*stop/i); }); test("capture precedes registration and session lessons preserve actual evidence", () => { const ingest = section("Ingest"); assert.ok(ingest.indexOf("**Capture**") < ingest.indexOf("**Register**")); assert.match(ingest, /Never register a failed capture/); const retro = section("Retro"); assert.match(retro, /redacted.*excerpt/i); assert.match(retro, /session.*entry IDs/i); assert.match(retro, /same capture.*register.*compile/i); }); test("tool guidance cannot reintroduce obsolete or unbounded recipes", () => { assert.doesNotMatch(`${skill}\n${prompt}`, /web_fetch|curl -sL|/); assert.match(skill, /web.*action: fetch/); assert.match(skill, /current tool schema|current.*help/i); assert.match(skill, /redirect.*same.*checks/i); }); test("url ingest requires approval for private/internal network targets", () => { assert.match(skill, /private\/internal URLs.*explicit approval/i); assert.match(skill, /localhost|loopback/i); assert.match(skill, /169\.254\.169\.254/); }); test("file and archive ingest guard secrets and unsafe extraction", () => { assert.match(skill, /deny known secret paths/i); assert.match(skill, /zip-slip|parent paths/i); assert.match(skill, /file count.*total size|total size.*file count/i); }); test("recall searches are literal and bounded", () => { assert.match(skill, /rg -i -F --max-filesize/); assert.match(skill, /-- "\$query"/); assert.match(skill, /--glob '!raw-sources\/\*\*' -- "\$query"/); assert.doesNotMatch(skill, /-- "\$query"[^\n]*--glob/); assert.doesNotMatch(skill, /2>\/dev\/null/); assert.match(section("Recall"), /output.*limit|limit.*output/i); }); test("lint is read-only unless fix is approved", () => { assert.match(skill, /lint is read-only by default/i); assert.match(skill, /--fix/i); });