Luigit
repositories / pi-ext

pi-ext

bugabingas pi extensions

owned by admin

extensions/the-system/system.ts

Raw
import { existsSync, lstatSync, readFileSync } from "node:fs";
import path from "node:path";
import type {
	EditToolInput,
	WriteToolInput,
} from "@earendil-works/pi-coding-agent";
import {
	type Diagnostic,
	type DocumentMetadata,
	discoverDocumentBundles,
	discoverProjectRoot,
	indexBundleDocuments,
	parseAuthoredDocument,
	parseSystemConfig,
	readCurrentPhase,
	resolveGovernedPath,
	SCHEMA_VERSION,
	validateBundleCandidate,
} from "./documents.ts";
import { inspectInitialization } from "./init.ts";

export const CORE_BYTE_LIMIT = 32 * 1024;
const CORES = ["SYSTEM.md", "MISSION.md", "RULES.md"] as const;
const CONFIG_PATH = ".system/config.json";
const governanceError = (message: string) =>
	`# The System governance error\n\n${message}\n\nDo not mutate .system until this governance error is resolved.`;
const coreBlock = (root: string, name: (typeof CORES)[number]) => {
	const relative = `.system/${name}`;
	const target = path.join(root, relative);
	try {
		const stats = lstatSync(target, { throwIfNoEntry: false });
		if (!stats) return undefined;
		if (!stats.isFile())
			throw new Error(
				`Malformed core path ${relative}: expected a regular file.`,
			);
		if (stats.size > CORE_BYTE_LIMIT)
			return `## ${name}\n\n[Not injected: ${name} exceeds the ${CORE_BYTE_LIMIT}-byte injection limit.]`;
		return `## ${name}\n\n${readFileSync(target, "utf8")}`;
	} catch (error) {
		throw new Error(
			`Unable to read core path ${relative}: ${error instanceof Error ? error.message : String(error)}`,
		);
	}
};

export function composeSystemSection(cwd: string): string | undefined {
	const root = discoverProjectRoot(cwd);
	if (!root) return undefined;
	try {
		const [system, mission, rules] = CORES.map((name) => coreBlock(root, name));
		let phase: string | undefined;
		const configFile = path.join(root, CONFIG_PATH);
		if (existsSync(configFile)) {
			const config = parseSystemConfig(readFileSync(configFile, "utf8"));
			const current = readCurrentPhase(root, config);
			if (current)
				phase = `## Current phase: ${current.metadata.title} · ${current.metadata.label}\n\n${current.markdown}`;
		}
		const blocks = [system, mission, phase, rules].filter(
			(block): block is string => block !== undefined,
		);
		return blocks.length === 0
			? undefined
			: `# The System project law\n\n${blocks.join("\n\n")}`;
	} catch (error) {
		return governanceError(
			error instanceof Error ? error.message : String(error),
		);
	}
}

export type SystemRuntimeState = Readonly<{
	active: boolean;
	prefix?: string;
	phaseLabel?: string;
	notice?: string;
}>;

const INCOMPLETE_NOTICE =
	"The System is incomplete or invalid; run /system init before governed work.";
const SCHEMA_NOTICE = `The System schema does not match ${SCHEMA_VERSION}; run /system init to update it.`;

export function runtimeState(cwd: string): SystemRuntimeState {
	const root = discoverProjectRoot(cwd);
	if (!root) return { active: false };
	try {
		const inspection = inspectInitialization(root);
		if (inspection.rewrites.length > 0)
			return { active: true, notice: SCHEMA_NOTICE };
		const incomplete =
			inspection.creates.length > 0 ||
			inspection.cores.some(({ state }) => state === "missing");
		let phaseLabel: string | undefined;
		if (inspection.prefix) {
			const config = parseSystemConfig(
				readFileSync(path.join(root, CONFIG_PATH), "utf8"),
			);
			phaseLabel = readCurrentPhase(root, config)?.metadata.label;
		}
		const notice = incomplete ? INCOMPLETE_NOTICE : undefined;
		return {
			active: true,
			...(inspection.prefix ? { prefix: inspection.prefix } : {}),
			...(phaseLabel ? { phaseLabel } : {}),
			...(notice ? { notice } : {}),
		};
	} catch {
		return { active: true, notice: INCOMPLETE_NOTICE };
	}
}

export function runtimeNotice(cwd: string): string | undefined {
	return runtimeState(cwd).notice;
}

type MutationKind = "write" | "edit";
type MutationInput = WriteToolInput | EditToolInput;
type GateResult = Readonly<{ block: true; reason: string }> | undefined;
export type GovernanceUI = Readonly<{
	hasUI: boolean;
	select(title: string, items: string[]): Promise<string | undefined>;
}>;
type MutationOptions = Readonly<{ bundleMigration?: boolean }>;
const CORE_PATHS = new Set([
	".system/SYSTEM.md",
	".system/MISSION.md",
	".system/RULES.md",
]);
const posixRelative = (root: string, target: string) =>
	path.relative(root, target).split(path.sep).join("/");
const blocked = (reason: string): GateResult => ({ block: true, reason });
const diagnosticsReason = (diagnostics: readonly Diagnostic[]) => {
	const shown = diagnostics
		.slice(0, 3)
		.map((item) => `${item.path} ${item.code}: ${item.message}`);
	if (diagnostics.length > shown.length)
		shown.push(`+${diagnostics.length - shown.length} more finding(s)`);
	return `The System candidate validation failed: ${shown.join("; ")}`;
};
const applyExactEdits = (source: string, edits: EditToolInput["edits"]) => {
	const replacements = edits
		.map((edit) => {
			const start = source.indexOf(edit.oldText);
			if (start < 0 || source.indexOf(edit.oldText, start + 1) >= 0)
				throw new Error("each governed edit oldText must match exactly once");
			return { start, end: start + edit.oldText.length, newText: edit.newText };
		})
		.sort((left, right) => left.start - right.start);
	for (let index = 1; index < replacements.length; index++) {
		const previous = replacements[index - 1];
		const next = replacements[index];
		if (previous && next && previous.end > next.start)
			throw new Error("governed edits must not overlap");
	}
	let candidate = source;
	for (const replacement of replacements.reverse())
		candidate =
			candidate.slice(0, replacement.start) +
			replacement.newText +
			candidate.slice(replacement.end);
	return candidate;
};
const candidateContent = (
	target: string,
	kind: MutationKind,
	input: MutationInput,
) => {
	if (kind === "write") return (input as WriteToolInput).content;
	if (!existsSync(target))
		throw new Error("edit cannot create a governed file; use write");
	return applyExactEdits(
		readFileSync(target, "utf8"),
		(input as EditToolInput).edits,
	);
};
const approveOwnedMutation = async (
	relative: string,
	kind: MutationKind,
	ui: GovernanceUI,
): Promise<GateResult> => {
	if (!ui.hasUI)
		return blocked(
			`The System blocked existing human-owned ${relative}: interactive UI is unavailable.`,
		);
	const approve = `Approve once: ${kind} ${relative}`;
	const deny = `Deny: keep ${relative} unchanged`;
	const decision = await ui.select("The System ownership approval", [
		approve,
		deny,
	]);
	if (decision === approve) return undefined;
	return blocked(
		decision === deny
			? `The System ownership approval was denied for ${relative}.`
			: `The System ownership approval was cancelled for ${relative}.`,
	);
};
const projectPrefix = (root: string) =>
	parseSystemConfig(readFileSync(path.join(root, CONFIG_PATH), "utf8")).prefix;

const preflightCurrentPhase = async (
	root: string,
	target: string,
	kind: MutationKind,
	input: MutationInput,
	ui: GovernanceUI,
): Promise<GateResult> => {
	const stats = lstatSync(target, { throwIfNoEntry: false });
	if (!stats?.isFile())
		return blocked(
			"The System config must be initialized before selecting a phase.",
		);
	try {
		const current = parseSystemConfig(readFileSync(target, "utf8"));
		const candidate = parseSystemConfig(candidateContent(target, kind, input));
		if (
			candidate.prefix !== current.prefix ||
			candidate.title !== current.title
		)
			return blocked(
				"The System config mutation may only change currentPhase.",
			);
		if (candidate.currentPhase === current.currentPhase)
			return blocked(
				candidate.currentPhase
					? `The System phase is already ${candidate.currentPhase}.`
					: "The System already has no current phase.",
			);
		const phase = readCurrentPhase(root, candidate);
		if (!ui.hasUI)
			return blocked(
				`The System blocked phase ${candidate.currentPhase ? "activation" : "deactivation"}: interactive UI is unavailable.`,
			);
		const approve = phase
			? `Activate: ${phase.metadata.label} · ${phase.metadata.title}`
			: "Deactivate current phase";
		const deny = `Deny: keep ${current.currentPhase ?? "no current phase"}`;
		const decision = await ui.select("The System phase transition", [
			approve,
			deny,
		]);
		if (decision === approve) return undefined;
		return blocked(
			decision === deny
				? "The System phase transition was denied."
				: "The System phase transition was cancelled.",
		);
	} catch (error) {
		return blocked(
			`The System rejected the config change: ${error instanceof Error ? error.message : String(error)}`,
		);
	}
};

type GovernedDocumentPath = Readonly<{
	directory: "specs" | "phases" | "plans" | "issues" | "research";
	bundle: string;
	asset: string;
	index: boolean;
}>;
const governedDocumentPath = (
	relative: string,
): GovernedDocumentPath | undefined => {
	const match =
		/^\.system\/(specs|phases|plans|issues|research)\/([^/]+)\/(.+)$/.exec(
			relative,
		);
	if (!match) return undefined;
	const [, directory, bundle, asset] = match;
	if (!directory || !bundle || !asset || asset.endsWith("/index.md"))
		return undefined;
	return {
		directory: directory as GovernedDocumentPath["directory"],
		bundle,
		asset,
		index: asset === "index.md",
	};
};
type ResolvedBundleMutation = Readonly<{
	location: GovernedDocumentPath;
	metadata?: DocumentMetadata;
	findings: readonly Diagnostic[];
}>;
const resolveBundleMutation = (
	root: string,
	relative: string,
	content: string | undefined,
): ResolvedBundleMutation => {
	const location = governedDocumentPath(relative);
	if (!location)
		throw new Error(
			`Authored paths require .system/<type-plural>/<ID>-<slug>/<file>: ${relative}`,
		);
	const prefix = projectPrefix(root);
	const discovery = discoverDocumentBundles(root);
	const bundlePath = `.system/${location.directory}/${location.bundle}`;
	const localDiscovery = discovery.diagnostics
		.filter(
			(item) =>
				item.path === bundlePath || item.path.startsWith(`${bundlePath}/`),
		)
		.filter(
			(item) =>
				!(
					location.index &&
					item.path === bundlePath &&
					item.code === "bundle.missing-index"
				),
		);
	if (localDiscovery.length > 0) return { location, findings: localDiscovery };
	if (location.index) {
		if (content === undefined)
			throw new Error("Missing index candidate content");
		const findings = validateBundleCandidate(
			discovery.sources,
			{ path: relative, markdown: content },
			prefix,
		);
		const parsed = parseAuthoredDocument(content, prefix);
		return { location, metadata: parsed.metadata, findings };
	}
	const indexPath = `${bundlePath}/index.md`;
	const owner = discovery.sources.find((source) => source.path === indexPath);
	if (!owner)
		throw new Error(
			`Bundle requires a valid index.md before assets: ${bundlePath}`,
		);
	const indexed = indexBundleDocuments(discovery.sources, prefix);
	const findings = indexed.diagnostics.filter(
		(item) => item.path === indexPath,
	);
	const document = indexed.documents.find((item) => item.path === indexPath);
	if (!document) throw new Error(`Bundle index is invalid: ${indexPath}`);
	return { location, metadata: document.metadata, findings };
};
const currentBundleMetadata = (
	root: string,
	location: GovernedDocumentPath,
): DocumentMetadata | undefined => {
	const prefix = projectPrefix(root);
	const bundlePath = `.system/${location.directory}/${location.bundle}`;
	const indexPath = `${bundlePath}/index.md`;
	const indexed = indexBundleDocuments(
		discoverDocumentBundles(root).sources,
		prefix,
	);
	return indexed.documents.find((item) => item.path === indexPath)?.metadata;
};

const symbolicLinkInPath = (root: string, target: string) => {
	let current = root;
	for (const part of path.relative(root, target).split(path.sep)) {
		if (!part) continue;
		current = path.join(current, part);
		if (lstatSync(current, { throwIfNoEntry: false })?.isSymbolicLink())
			return posixRelative(root, current);
	}
	return undefined;
};

export async function preflightFileMutation(
	cwd: string,
	kind: MutationKind,
	input: MutationInput,
	ui: GovernanceUI,
	options: MutationOptions = {},
): Promise<GateResult> {
	const root = discoverProjectRoot(cwd);
	if (!root) return undefined;
	const candidate = path.resolve(cwd, input.path);
	const candidateRelative = path.relative(root, candidate);
	if (
		candidateRelative === ".." ||
		candidateRelative.startsWith(`..${path.sep}`) ||
		path.isAbsolute(candidateRelative)
	)
		return undefined;
	let target: string;
	try {
		target = resolveGovernedPath(root, candidate);
	} catch (error) {
		return blocked(
			`The System rejected the governed path: ${error instanceof Error ? error.message : String(error)}`,
		);
	}
	const relative = posixRelative(root, target);
	if (
		relative !== CONFIG_PATH &&
		!CORE_PATHS.has(relative) &&
		!/^\.system\/(specs|phases|plans|issues|research)(?:\/|$)/.test(relative)
	)
		return relative.startsWith(".system/")
			? blocked(
					`The System only allows governed document bundles under .system/specs, .system/phases, .system/plans, .system/issues, or .system/research: ${relative}.`,
				)
			: undefined;
	try {
		const link = symbolicLinkInPath(root, target);
		if (link)
			return blocked(
				`The System rejected symbolic link in governed path: ${link}.`,
			);
	} catch (error) {
		return blocked(
			`The System rejected unsafe governed path: ${error instanceof Error ? error.message : String(error)}`,
		);
	}
	const targetStats = lstatSync(target, { throwIfNoEntry: false });
	if (relative === CONFIG_PATH)
		return preflightCurrentPhase(root, target, kind, input, ui);
	if (CORE_PATHS.has(relative)) {
		if (targetStats && !targetStats.isFile())
			return blocked(
				`The System expected a regular owned file at ${relative}.`,
			);
		let content: string;
		try {
			content = candidateContent(target, kind, input);
		} catch (error) {
			return blocked(
				`The System candidate validation failed: ${error instanceof Error ? error.message : String(error)}`,
			);
		}
		if (Buffer.byteLength(content, "utf8") > CORE_BYTE_LIMIT)
			return blocked(
				`The System candidate validation failed: ${relative} exceeds the ${CORE_BYTE_LIMIT}-byte core limit.`,
			);
		return targetStats ? approveOwnedMutation(relative, kind, ui) : undefined;
	}
	const location = governedDocumentPath(relative);
	if (!location)
		return blocked(
			`The System requires document bundles at .system/<type-plural>/<ID>-<slug>/<file>: ${relative}.`,
		);
	if (options.bundleMigration) {
		if (!location.index || !targetStats?.isFile())
			return blocked(
				`The System bundle migration may only update an existing index.md: ${relative}.`,
			);
		try {
			const content = candidateContent(target, kind, input);
			const discovery = discoverDocumentBundles(root);
			const findings = validateBundleCandidate(
				discovery.sources,
				{ path: relative, markdown: content },
				projectPrefix(root),
			);
			if (findings.length > 0) return blocked(diagnosticsReason(findings));
			return undefined;
		} catch (error) {
			return blocked(
				`The System candidate validation failed: ${error instanceof Error ? error.message : String(error)}`,
			);
		}
	}
	try {
		const current = currentBundleMetadata(root, location);
		if (current?.type === "plan" && current.status === "approved")
			return blocked(
				`The System blocked mutation of approved ${current.type} ${current.id}; create a new bundle instead.`,
			);
	} catch (error) {
		return blocked(
			`The System candidate validation failed: ${error instanceof Error ? error.message : String(error)}`,
		);
	}
	let content: string | undefined;
	if (location.index)
		try {
			content = candidateContent(target, kind, input);
		} catch (error) {
			return blocked(
				`The System candidate validation failed: ${error instanceof Error ? error.message : String(error)}`,
			);
		}
	let resolved: ResolvedBundleMutation;
	try {
		resolved = resolveBundleMutation(root, relative, content);
	} catch (error) {
		return blocked(
			`The System candidate validation failed: ${error instanceof Error ? error.message : String(error)}`,
		);
	}
	if (resolved.findings.length > 0)
		return blocked(diagnosticsReason(resolved.findings));
	if (!resolved.metadata)
		return blocked(
			`The System could not determine bundle ownership: ${relative}.`,
		);
	if (!targetStats) return undefined;
	if (!targetStats.isFile())
		return blocked(`The System expected a regular owned file at ${relative}.`);
	if (
		location.index &&
		resolved.metadata.type === "plan" &&
		resolved.metadata.status === "approved"
	) {
		const current = currentBundleMetadata(root, location);
		if (current?.type === "plan" && current.status !== "approved") {
			if (!ui.hasUI)
				return blocked(
					`The System blocked approval of ${resolved.metadata.type} ${resolved.metadata.id}: interactive UI is unavailable.`,
				);
			const approve = `Approve: ${resolved.metadata.id}`;
			const deny = `Deny: keep ${resolved.metadata.id} draft`;
			const decision = await ui.select("The System document approval", [
				approve,
				deny,
			]);
			if (decision !== approve)
				return blocked(
					decision === deny
						? `The System approval was denied for ${resolved.metadata.id}.`
						: `The System approval was cancelled for ${resolved.metadata.id}.`,
				);
		}
	}
	if (resolved.metadata.type !== "spec" && resolved.metadata.type !== "phase")
		return undefined;
	return approveOwnedMutation(relative, kind, ui);
}