repositories / pi-ext
pi-ext
bugabingas pi extensions
owned by admin
extensions/the-system/__tests__/documents.test.ts
Rawimport assert from "node:assert/strict";
import {
mkdirSync,
mkdtempSync,
rmSync,
symlinkSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import path from "node:path";
import { afterEach, describe, it } from "vitest";
import {
discoverDocumentBundles,
discoverProjectRoot,
indexBundleDocuments,
PHASE_BYTE_LIMIT,
parseAuthoredDocument,
parseDocumentId,
parseSystemConfig,
requireProjectRoot,
resolveGovernedPath,
SystemDocumentError,
systemConfigForInitialization,
validateBundleCandidate,
validateDocumentPath,
} from "../documents.ts";
const roots: string[] = [];
const tree = () => {
const root = mkdtempSync(path.join(tmpdir(), "the-system-documents-"));
roots.push(root);
return root;
};
const dir = (root: string, ...parts: string[]) => {
const target = path.join(root, ...parts);
mkdirSync(target, { recursive: true });
return target;
};
const write = (root: string, relative: string, content: string) => {
const target = path.join(root, relative);
dir(path.dirname(target));
writeFileSync(target, content);
};
const source = (
directory: string,
id: string,
slug: string,
frontmatter: string,
) => ({
path: `.system/${directory}/${id}-${slug}/index.md`,
markdown: `---\n${frontmatter}\n---\n\n# ${id}\n`,
});
const spec = (id = "PX-SPEC-ABCDEFGH") =>
`---\nid: ${id}\ntype: spec\ntitle: Contract\n---\n\n# ${id}\n`;
afterEach(() => {
for (const root of roots.splice(0))
rmSync(root, { recursive: true, force: true });
});
describe("project root and schema-0 config", () => {
it("resolves the nearest .system root", () => {
const root = tree();
dir(root, ".system");
const nested = dir(root, "nested");
assert.equal(discoverProjectRoot(nested), root);
dir(nested, ".system");
assert.equal(discoverProjectRoot(nested), nested);
assert.equal(resolveGovernedPath(root, "x/../x"), path.join(root, "x"));
assert.throws(
() => resolveGovernedPath(root, "../outside"),
SystemDocumentError,
);
});
it("returns undefined without a .system directory", () => {
assert.equal(discoverProjectRoot(tree()), undefined);
assert.throws(() => requireProjectRoot(tree()), SystemDocumentError);
});
it("ignores .system files and symbolic links while walking", () => {
const root = tree();
dir(root, ".system");
dir(root, "elsewhere");
const fileDirectory = dir(root, "file");
writeFileSync(path.join(fileDirectory, ".system"), "");
const linkDirectory = dir(root, "link");
symlinkSync(
path.join(root, "elsewhere"),
path.join(linkDirectory, ".system"),
"dir",
);
assert.equal(discoverProjectRoot(fileDirectory), root);
assert.equal(discoverProjectRoot(linkDirectory), root);
});
it("accepts schema 0 and prepares mismatched config for initialization", () => {
assert.deepEqual(
parseSystemConfig(
'{"prefix":"PX","schemaVersion":0,"title":"Project X","currentPhase":"PX-PHASE-PHASE001"}',
),
{
prefix: "PX",
schemaVersion: 0,
title: "Project X",
currentPhase: "PX-PHASE-PHASE001",
},
);
assert.deepEqual(parseSystemConfig('{"prefix":"PX","schemaVersion":0}'), {
prefix: "PX",
schemaVersion: 0,
});
assert.throws(
() => parseSystemConfig('{"prefix":"PX","schemaVersion":4}'),
/does not match 0; run \/system init/,
);
assert.deepEqual(
systemConfigForInitialization(
'{"prefix":"PX","schemaVersion":4,"title":"Project X"}',
),
{
config: { prefix: "PX", schemaVersion: 0, title: "Project X" },
sourceSchemaVersion: 4,
},
);
});
});
describe("schema-0 identity and metadata", () => {
it("parses uppercase token IDs and rejects short numeric IDs", () => {
assert.deepEqual(parseDocumentId("PX-SPEC-AZ3_P9QK", "PX"), {
id: "PX-SPEC-AZ3_P9QK",
prefix: "PX",
type: "spec",
token: "AZ3_P9QK",
});
assert.throws(
() => parseDocumentId("PX-SPEC-001", "PX"),
SystemDocumentError,
);
assert.throws(
() => parseDocumentId("PX-SPEC-az3_p9qk", "PX"),
SystemDocumentError,
);
});
it("projects known graph fields while preserving unknown frontmatter", () => {
const parsed = parseAuthoredDocument(
`---\nid: PX-PLAN-PL4N0001\ntype: plan\ntitle: Delivery\nspec: PX-SPEC-SPEC0001\nstatus: draft\ndepends_on: [PX-PLAN-PL4N0000]\nreview: human\n---\n`,
"PX",
);
assert.deepEqual(parsed.metadata, {
id: "PX-PLAN-PL4N0001",
type: "plan",
title: "Delivery",
spec: "PX-SPEC-SPEC0001",
status: "draft",
depends_on: ["PX-PLAN-PL4N0000"],
});
assert.deepEqual(
[...parsed.frontmatter.keys()],
["id", "type", "title", "spec", "status", "depends_on", "review"],
);
});
it("parses operating phases and validates their labels and size", () => {
assert.deepEqual(
parseAuthoredDocument(
"---\nid: PX-PHASE-PHASE001\ntype: phase\ntitle: Pre-v1\nlabel: pre-v1\n---\n",
"PX",
).metadata,
{
id: "PX-PHASE-PHASE001",
type: "phase",
title: "Pre-v1",
label: "pre-v1",
},
);
assert.throws(
() =>
parseAuthoredDocument(
"---\nid: PX-PHASE-PHASE001\ntype: phase\ntitle: Pre-v1\nlabel: label-is-too-long\n---\n",
"PX",
),
/1-12 ASCII/,
);
assert.throws(
() =>
parseAuthoredDocument(
`---\nid: PX-PHASE-PHASE001\ntype: phase\ntitle: Pre-v1\nlabel: pre-v1\n---\n\n${"x".repeat(PHASE_BYTE_LIMIT)}`,
"PX",
),
/byte limit/,
);
});
it("parses issue metadata without status and validates approval status", () => {
assert.deepEqual(
parseAuthoredDocument(
"---\nid: PX-ISSUE-ISSUE001\ntype: issue\ntitle: Bug\nspecs: []\n---\n",
"PX",
).metadata,
{
id: "PX-ISSUE-ISSUE001",
type: "issue",
title: "Bug",
specs: [],
},
);
assert.equal(
parseAuthoredDocument(
"---\nid: PX-PLAN-PLAN0001\ntype: plan\ntitle: Build\nspec: PX-SPEC-SPEC0001\nstatus: approved\n---\n",
"PX",
).metadata.status,
"approved",
);
assert.throws(
() =>
parseAuthoredDocument(
"---\nid: PX-PLAN-PLAN0001\ntype: plan\ntitle: Build\nspec: PX-SPEC-SPEC0001\nstatus: done\n---\n",
"PX",
),
/status must be draft or approved/,
);
});
it("accepts only canonical bundle paths", () => {
const metadata = {
id: "PX-SPEC-AZ3_P9QK",
type: "spec",
title: "Login",
} as const;
assert.doesNotThrow(() =>
validateDocumentPath(
".system/specs/PX-SPEC-AZ3_P9QK-login-flow/index.md",
metadata,
"PX",
),
);
for (const item of [
".system/specs/PX-SPEC-AZ3_P9QK-login-flow.md",
".system/phases/PX-SPEC-AZ3_P9QK-login-flow/index.md",
".system/specs/PX-SPEC-AZ3_P9QK-Login/index.md",
".system/specs/PX-SPEC-AZ3_P9QK-login-flow/other/index.md",
])
assert.throws(
() => validateDocumentPath(item, metadata, "PX"),
SystemDocumentError,
);
});
});
describe("bundle discovery and graph", () => {
it("returns authored indexes and structural diagnostics separately", () => {
const root = tree();
write(
root,
".system/specs/PX-SPEC-SPEC0001-contract/index.md",
spec("PX-SPEC-SPEC0001"),
);
write(
root,
".system/specs/PX-SPEC-SPEC0001-contract/assets/data.csv",
"a,b",
);
write(root, ".system/plans/loose.md", "bad");
dir(root, ".system", "specs", "PX-SPEC-SPEC0002-empty");
assert.equal(discoverDocumentBundles(root).sources.length, 1);
assert.deepEqual(
discoverDocumentBundles(root).diagnostics.map(
(item) => `${item.path} ${item.code}`,
),
[
".system/plans/loose.md bundle.expected-directory",
".system/specs/PX-SPEC-SPEC0002-empty bundle.missing-index",
],
);
});
it("reports symlinks without following them", () => {
const root = tree();
const outside = tree();
write(
root,
".system/specs/PX-SPEC-SPEC0001-contract/index.md",
spec("PX-SPEC-SPEC0001"),
);
symlinkSync(
outside,
path.join(root, ".system/specs/PX-SPEC-SPEC0002-link"),
"dir",
);
symlinkSync(
outside,
path.join(root, ".system/specs/PX-SPEC-SPEC0001-contract/assets-link"),
"dir",
);
assert.deepEqual(
discoverDocumentBundles(root).diagnostics.map((item) => item.code),
["bundle.symbolic-link", "bundle.symbolic-link"],
);
});
it("keeps phases separate from the spec-plan graph", () => {
const indexed = indexBundleDocuments(
[
source(
"research",
"PX-RESEARCH-RESEARCH",
"notes",
"id: PX-RESEARCH-RESEARCH\ntype: research\ntitle: Notes",
),
source(
"specs",
"PX-SPEC-SPEC0001",
"one",
"id: PX-SPEC-SPEC0001\ntype: spec\ntitle: One\nresearch: [PX-RESEARCH-RESEARCH]",
),
source(
"specs",
"PX-SPEC-SPEC0002",
"two",
"id: PX-SPEC-SPEC0002\ntype: spec\ntitle: Two",
),
source(
"phases",
"PX-PHASE-PHASE001",
"delivery",
"id: PX-PHASE-PHASE001\ntype: phase\ntitle: Delivery\nlabel: delivery",
),
source(
"plans",
"PX-PLAN-PLAN0001",
"build",
"id: PX-PLAN-PLAN0001\ntype: plan\ntitle: Build\nspec: PX-SPEC-SPEC0002\nstatus: draft",
),
],
"PX",
);
assert.deepEqual(indexed.diagnostics, []);
assert.deepEqual(
indexed.documents.find((document) => document.metadata.type === "phase")
?.metadata,
{
id: "PX-PHASE-PHASE001",
type: "phase",
title: "Delivery",
label: "delivery",
},
);
});
it("validates dependency references and cycles", () => {
const indexed = indexBundleDocuments(
[
source(
"specs",
"PX-SPEC-SPEC0001",
"one",
"id: PX-SPEC-SPEC0001\ntype: spec\ntitle: One",
),
source(
"specs",
"PX-SPEC-SPEC0002",
"two",
"id: PX-SPEC-SPEC0002\ntype: spec\ntitle: Two",
),
source(
"plans",
"PX-PLAN-PLAN0001",
"one",
"id: PX-PLAN-PLAN0001\ntype: plan\ntitle: One\nspec: PX-SPEC-SPEC0001\nstatus: draft\ndepends_on: [PX-PLAN-MISSING1]",
),
source(
"plans",
"PX-PLAN-PLAN0002",
"two",
"id: PX-PLAN-PLAN0002\ntype: plan\ntitle: Two\nspec: PX-SPEC-SPEC0001\nstatus: draft\ndepends_on: [PX-PLAN-PLAN0003]",
),
source(
"plans",
"PX-PLAN-PLAN0003",
"three",
"id: PX-PLAN-PLAN0003\ntype: plan\ntitle: Three\nspec: PX-SPEC-SPEC0001\nstatus: draft\ndepends_on: [PX-PLAN-PLAN0002]",
),
source(
"plans",
"PX-PLAN-PLAN0004",
"four",
"id: PX-PLAN-PLAN0004\ntype: plan\ntitle: Four\nspec: PX-SPEC-SPEC0002\nstatus: draft\ndepends_on: [PX-PLAN-PLAN0002]",
),
],
"PX",
);
assert.deepEqual(indexed.diagnostics.map((item) => item.code).sort(), [
"graph.dangling-reference",
"graph.dependency-cycle",
"graph.forbidden-edge",
]);
});
it("candidate validation reports only new candidate findings", () => {
const findings = validateBundleCandidate(
[
source(
"specs",
"PX-SPEC-SPEC0001",
"one",
"id: PX-SPEC-SPEC0001\ntype: spec\ntitle: One",
),
],
source(
"plans",
"PX-PLAN-PLAN0001",
"delivery",
"id: PX-PLAN-PLAN0001\ntype: plan\ntitle: Delivery\nspec: PX-SPEC-MISSING1\nstatus: draft",
),
"PX",
);
assert.deepEqual(
findings.map((item) => item.code),
["graph.dangling-reference"],
);
});
});