mirror of
https://github.com/earendil-works/pi.git
synced 2026-06-18 15:54:04 +08:00
77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
import { mkdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import lockfile from "proper-lockfile";
|
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
import { hasProjectConfig, ProjectTrustStore } from "../src/core/trust-manager.ts";
|
|
|
|
describe("ProjectTrustStore", () => {
|
|
let tempDir: string;
|
|
let agentDir: string;
|
|
let cwd: string;
|
|
|
|
beforeEach(() => {
|
|
tempDir = join(tmpdir(), `trust-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
agentDir = join(tempDir, "agent");
|
|
cwd = join(tempDir, "project");
|
|
mkdirSync(agentDir, { recursive: true });
|
|
mkdirSync(cwd, { recursive: true });
|
|
});
|
|
|
|
afterEach(() => {
|
|
rmSync(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
it("stores decisions per cwd", () => {
|
|
const store = new ProjectTrustStore(agentDir);
|
|
|
|
expect(store.get(cwd)).toBeNull();
|
|
store.set(cwd, true);
|
|
expect(store.get(cwd)).toBe(true);
|
|
store.set(cwd, false);
|
|
expect(store.get(cwd)).toBe(false);
|
|
store.set(cwd, null);
|
|
expect(store.get(cwd)).toBeNull();
|
|
});
|
|
|
|
it("fails loudly without overwriting malformed trust stores", () => {
|
|
const trustPath = join(agentDir, "trust.json");
|
|
writeFileSync(trustPath, "{not json", "utf-8");
|
|
const store = new ProjectTrustStore(agentDir);
|
|
|
|
expect(() => store.get(cwd)).toThrow(/Failed to read trust store/);
|
|
expect(() => store.set(cwd, true)).toThrow(/Failed to read trust store/);
|
|
expect(readFileSync(trustPath, "utf-8")).toBe("{not json");
|
|
});
|
|
|
|
it("does not read trust.json while another process holds the trust lock", () => {
|
|
const trustPath = join(agentDir, "trust.json");
|
|
writeFileSync(trustPath, "{partial", "utf-8");
|
|
const release = lockfile.lockSync(agentDir, { realpath: false, lockfilePath: `${trustPath}.lock` });
|
|
const store = new ProjectTrustStore(agentDir);
|
|
|
|
try {
|
|
let error: unknown;
|
|
try {
|
|
store.get(cwd);
|
|
} catch (caught) {
|
|
error = caught;
|
|
}
|
|
|
|
expect(error).toBeInstanceOf(Error);
|
|
expect((error as { code?: unknown }).code).toBe("ELOCKED");
|
|
} finally {
|
|
release();
|
|
}
|
|
|
|
expect(() => store.get(cwd)).toThrow(/Failed to read trust store/);
|
|
});
|
|
|
|
it("detects .pi project config directories", () => {
|
|
expect(hasProjectConfig(cwd)).toBe(false);
|
|
|
|
mkdirSync(join(cwd, ".pi"), { recursive: true });
|
|
expect(hasProjectConfig(cwd)).toBe(true);
|
|
});
|
|
});
|