Files
PaperClipAI/tests/runner-e2e/directory-cleanup.test.ts
T
DottaandPaperclip 8679fa7646 test(evals): remove immutable caches during controller retirement
Share the launcher cleanup traversal with rolling replacement. Make stopped controller directories removable without following dependency symlinks, then delete the entire predecessor home. Cover immutable bundles and external symlink protection with real filesystem tests.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-11-01 06:43:42 -06:00

30 lines
1.6 KiB
TypeScript

import { chmod, lstat, mkdir, mkdtemp, readFile, rm, symlink, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import path from "node:path";
import { expect, it } from "vitest";
import { makeDirectoryTreeRemovable } from "./directory-cleanup.js";
it("removes a retired home with immutable bundles without changing linked dependencies", async () => {
const root = await mkdtemp(path.join(tmpdir(), "paperclip-retired-home-"));
const home = path.join(root, "controller"), external = path.join(root, "external");
const bundle = path.join(home, "runtime-context-assets/bundles/digest");
try {
await mkdir(bundle, { recursive: true }); await mkdir(external);
await writeFile(path.join(bundle, "SKILL.md"), "immutable skill");
await writeFile(path.join(external, "keep"), "dependency");
await chmod(bundle, 0o555); await chmod(external, 0o555);
await symlink(external, path.join(home, "node_modules"));
await makeDirectoryTreeRemovable(home);
await rm(home, { recursive: true });
await expect(lstat(home)).rejects.toMatchObject({ code: "ENOENT" });
expect((await lstat(external)).mode & 0o777).toBe(0o555);
expect(await readFile(path.join(external, "keep"), "utf8")).toBe("dependency");
const link = path.join(root, "not-an-owned-home");
await symlink(external, link);
await expect(makeDirectoryTreeRemovable(link)).rejects.toThrow("not a symlink");
expect((await lstat(external)).mode & 0o777).toBe(0o555);
} finally {
await makeDirectoryTreeRemovable(root); await rm(root, { recursive: true });
}
});