// Tests for the pure parts of task.ts: root overlap and the pre-launch spec // validation that turns a guaranteed false FAIL into an immediate error. // task.ts imports typebox / @earendil-works/pi-ai at runtime (only resolvable // inside pi), so the functions are cut out of the shipped source by brace // matching and type-stripped — the same approach as mempalace-toolkit's tests. import { test } from "node:test"; import assert from "node:assert/strict"; import { readFileSync, writeFileSync, mkdtempSync, mkdirSync } from "node:fs"; import { stripTypeScriptTypes } from "node:module"; import { tmpdir } from "node:os"; import path from "node:path"; const src = readFileSync(new URL("../extensions/task.ts", import.meta.url), "utf8"); function fn(name) { const start = src.indexOf(`export function ${name}(`); if (start < 0) throw new Error(`not found: ${name}`); let depth = 0, seen = false; for (let i = start; i < src.length; i++) { if (src[i] === "{") { depth++; seen = true; } else if (src[i] === "}") { depth--; if (seen && depth === 0) return src.slice(start, i + 1); } } throw new Error(`unterminated: ${name}`); } const work = mkdtempSync(path.join(tmpdir(), "task-test-")); const modPath = path.join(work, "pure.mjs"); writeFileSync(modPath, stripTypeScriptTypes( `import { existsSync } from "node:fs";\nimport path from "node:path";\n` + [fn("rootsOverlap"), fn("anyOverlap"), fn("validateRoots")].join("\n\n"), { mode: "strip" })); const { rootsOverlap, anyOverlap, validateRoots } = await import(modPath); // Real directories, since validateRoots checks existence. const repo = path.join(work, "repo"); const docs = path.join(repo, "docs"); const srcd = path.join(repo, "src"); const other = path.join(work, "other"); for (const d of [docs, srcd, other]) mkdirSync(d, { recursive: true }); test("rootsOverlap: identity, containment both ways, siblings, prefix-but-not-parent", () => { assert.equal(rootsOverlap(repo, repo), true); assert.equal(rootsOverlap(repo, docs), true); assert.equal(rootsOverlap(docs, repo), true); assert.equal(rootsOverlap(docs, srcd), false); assert.equal(rootsOverlap(path.join(work, "repo"), path.join(work, "repo2")), false, "'/x/repo' is not a parent of '/x/repo2'"); assert.equal(anyOverlap([docs], [srcd, other]), false); assert.equal(anyOverlap([docs, other], [srcd, other]), true); }); test("validateRoots: read-only spec with existing absolute roots is accepted", () => { assert.deepEqual(validateRoots([docs, srcd], undefined, true), []); }); test("validateRoots: the migrate-0N shape (sibling roots, write_allowed subset) is accepted", () => { assert.deepEqual(validateRoots([docs, srcd, other], [docs], false), []); }); test("validateRoots: write task without write_allowed is rejected (violations undetectable)", () => { const p = validateRoots([docs], undefined, false); assert.equal(p.length, 1); assert.match(p[0], /requires write_allowed/); }); test("validateRoots: write_allowed must be an exact root string", () => { const p = validateRoots([repo], [docs], false); assert.ok(p.some((x) => /not one of roots/.test(x)), p.join("\n")); }); test("validateRoots: writable root nested in a watched-only root is rejected (certain false FAIL)", () => { const p = validateRoots([repo, docs], [docs], false); assert.ok(p.some((x) => /nested in/.test(x)), p.join("\n")); }); test("validateRoots: read_only with write_allowed, relative root, missing root are each named", () => { const p = validateRoots(["relative/path", path.join(work, "nope"), docs], [docs], true); assert.ok(p.some((x) => /not absolute/.test(x))); assert.ok(p.some((x) => /does not exist/.test(x))); assert.ok(p.some((x) => /pick one/.test(x))); });