import { mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs"; import path from "node:path"; import { afterEach, describe, expect, it, vi } from "vitest"; import { createTestSession, type TestSession } from "../../../test/harness"; import { applyInitialization } from "../init.ts"; describe("the-system pi-test-harness", () => { let t: TestSession | undefined; afterEach(() => { t?.dispose(); t = undefined; }); it("loads in real Pi extension runtime", async () => { const extensionPath = path.resolve(import.meta.dirname, "../index.ts"); t = await createTestSession({ extensions: [extensionPath] }); expect(t.session.extensionRunner.extensions).toHaveLength(1); expect(t.session.extensionRunner.extensions[0].path).toBe(extensionPath); expect(t.session.getActiveToolNames()).not.toContain("mockup"); }); it("writes debug lifecycle records in its sandbox when enabled", async () => { const extensionPath = path.resolve(import.meta.dirname, "../index.ts"); t = await createTestSession({ env: { PI_THE_SYSTEM_DEBUG: "1" }, extensions: [extensionPath], }); const context = t.session.extensionRunner.createCommandContext(); for (const handler of t.session.extensionRunner.extensions[0].handlers.get( "session_start", )) await handler({ type: "session_start" }, context); for (const handler of t.session.extensionRunner.extensions[0].handlers.get( "session_shutdown", )) await handler({ type: "session_shutdown" }, context); const directory = path.join( t.cwd, ".test-state", "pi-ext", "debug", "the-system", ); const records = readFileSync( path.join(directory, readdirSync(directory)[0]), "utf8", ) .trim() .split("\n") .map((line) => JSON.parse(line)); expect(records.map((record) => record.event)).toEqual( expect.arrayContaining(["session.start", "session.shutdown"]), ); }); it("keeps system_bundle_slot through clarification and cancels it on the next lifecycle", async () => { const extensionPath = path.resolve(import.meta.dirname, "../index.ts"); t = await createTestSession({ extensions: [extensionPath] }); applyInitialization(t.cwd, "PX"); const [extension] = t.session.extensionRunner.extensions; const sendUserMessage = vi .spyOn(t.session, "sendUserMessage") .mockResolvedValue(); expect(extension.tools.has("system_bundle_slot")).toBe(false); expect(t.session.getActiveToolNames()).not.toContain("system_bundle_slot"); await extension.commands .get("system") .handler( "spec let us discuss caching", t.session.extensionRunner.createCommandContext(), ); expect(sendUserMessage).toHaveBeenCalledOnce(); expect(extension.tools.has("system_bundle_slot")).toBe(true); expect(t.session.getActiveToolNames()).toContain("system_bundle_slot"); expect(t.session.systemPrompt).toContain( "- system_bundle_slot: Reserve an ID and path for a System bundle", ); expect(t.session.systemPrompt).toContain( "Resolve needed clarifications before calling system_bundle_slot.", ); expect(t.session.systemPrompt).toContain( "- Call system_bundle_slot once per required bundle after choosing its final type and title; use each returned ID and path exactly.", ); for (const handler of extension.handlers.get("agent_settled")) await handler( { type: "agent_settled", messages: [] }, t.session.extensionRunner.createCommandContext(), ); expect(t.session.getActiveToolNames()).toContain("system_bundle_slot"); await extension.commands .get("system") .handler( "exec continue", t.session.extensionRunner.createCommandContext(), ); expect(t.session.getActiveToolNames()).not.toContain("system_bundle_slot"); expect(t.session.systemPrompt).not.toContain("- system_bundle_slot:"); }); it("requests one-shot approval for an existing core mutation", async () => { const extensionPath = path.resolve(import.meta.dirname, "../index.ts"); t = await createTestSession({ extensions: [extensionPath] }); mkdirSync(path.join(t.cwd, ".system")); writeFileSync(path.join(t.cwd, ".system", "SYSTEM.md"), "Approved.\n"); const blocked = await t.session.extensionRunner.emitToolCall({ type: "tool_call", toolName: "edit", toolCallId: "blocked-core-edit", input: { path: ".system/SYSTEM.md", edits: [{ oldText: "Approved.", newText: "Human-approved." }], }, }); expect(blocked).toBeUndefined(); const [approval] = t.events.uiCallsFor("select"); expect(approval?.args).toEqual([ "The System ownership approval", [ "Approve once: edit .system/SYSTEM.md", "Deny: keep .system/SYSTEM.md unchanged", ], ]); }); });