openclaw/src/plugins/pi-package-graph.test.ts

79 lines
2.8 KiB
TypeScript

import fs from "node:fs";
import path from "node:path";
import { describe, expect, it } from "vitest";
type RootPackageManifest = {
dependencies?: Record<string, string>;
pnpm?: {
overrides?: Record<string, string>;
};
};
const PI_PACKAGE_NAMES = [
"@mariozechner/pi-agent-core",
"@mariozechner/pi-ai",
"@mariozechner/pi-coding-agent",
"@mariozechner/pi-tui",
] as const;
function readRootManifest(): RootPackageManifest {
const manifestPath = path.resolve(process.cwd(), "package.json");
return JSON.parse(fs.readFileSync(manifestPath, "utf8")) as RootPackageManifest;
}
function isExactPinnedVersion(spec: string): boolean {
return !spec.startsWith("^") && !spec.startsWith("~");
}
function isPiOverrideKey(key: string): boolean {
return key.startsWith("@mariozechner/pi-") || key.includes("@mariozechner/pi-");
}
function readPiDependencySpecs() {
const dependencies = readRootManifest().dependencies ?? {};
return PI_PACKAGE_NAMES.map((name) => ({
name,
spec: dependencies[name],
}));
}
function expectNoGraphViolations(violations: string[], message: string) {
expect(violations, message).toEqual([]);
}
describe("pi package graph guardrails", () => {
it("keeps root Pi packages aligned to the same exact version", () => {
const specs = readPiDependencySpecs();
const missing = specs.filter((entry) => !entry.spec).map((entry) => entry.name);
expectNoGraphViolations(
missing,
`Missing required root Pi dependencies: ${missing.join(", ") || "<none>"}. Mixed or incomplete Pi root dependencies create an unsupported package graph.`,
);
const presentSpecs = specs.map((entry) => entry.spec);
const uniqueSpecs = [...new Set(presentSpecs)];
expect(
uniqueSpecs,
`Root Pi dependencies must stay aligned to one exact version. Found: ${specs.map((entry) => `${entry.name}=${entry.spec}`).join(", ")}. Mixed Pi versions create an unsupported package graph.`,
).toHaveLength(1);
const inexact = specs.filter((entry) => !isExactPinnedVersion(entry.spec));
expectNoGraphViolations(
inexact.map((entry) => `${entry.name}=${entry.spec}`),
`Root Pi dependencies must use exact pins, not ranges. Found: ${inexact.map((entry) => `${entry.name}=${entry.spec}`).join(", ") || "<none>"}. Range-based Pi specs can silently create an unsupported package graph.`,
);
});
it("forbids pnpm overrides that target Pi packages", () => {
const manifest = readRootManifest();
const overrides = manifest.pnpm?.overrides ?? {};
const piOverrides = Object.keys(overrides).filter(isPiOverrideKey);
expectNoGraphViolations(
piOverrides,
`pnpm.overrides must not target Pi packages. Found: ${piOverrides.join(", ") || "<none>"}. Pi-specific overrides can silently create an unsupported package graph.`,
);
});
});