import assert from "node:assert/strict"; import { mkdir, mkdtemp, readFile, rm, stat, writeFile, } from "node:fs/promises"; import { tmpdir } from "node:os"; import { join } from "node:path"; import test from "node:test"; import { createWorkspaceStore } from "../src/bridge/workspace-store.js"; test("persists an owner-only versioned workspace manifest atomically", async () => { const root = await mkdtemp(join(tmpdir(), "pi-workspace-store-")); const store = createWorkspaceStore(join(root, "sessions")); const first = await store.load(); assert.equal(first.migrating, true); await store.save({ version: 2, migrated: true, runtimes: [ { runtimeId: "runtime-1", worktreePath: join(root, "home"), sessionPath: join(root, "sessions", "agent", "one.jsonl"), sessionId: "session-1", }, ], }); const metadata = await stat(store.filePath); assert.equal(metadata.mode & 0o777, 0o600); const restored = (await store.load()).manifest; assert.equal(restored.runtimes[0].runtimeId, "runtime-1"); assert.deepEqual(restored.directories, [join(root, "home")]); assert.equal((await readFile(store.filePath, "utf8")).endsWith("\n"), true); }); test("accepts old manifests and persists managed empty directories", async () => { const root = await mkdtemp(join(tmpdir(), "pi-workspace-directories-")); const store = createWorkspaceStore(join(root, "sessions")); await store.save({ version: 2, migrated: true, directories: [join(root, "empty")], runtimes: [], }); assert.deepEqual((await store.load()).manifest.directories, [ join(root, "empty"), ]); await writeFile( store.filePath, JSON.stringify({ version: 2, migrated: true, runtimes: [] }), { mode: 0o600 }, ); assert.deepEqual((await store.load()).manifest.directories, []); }); test("reports a corrupt manifest without treating it as first migration", async () => { const root = await mkdtemp(join(tmpdir(), "pi-workspace-corrupt-")); const store = createWorkspaceStore(join(root, "sessions")); await store.save({ version: 2, migrated: true, runtimes: [] }); await writeFile(store.filePath, "{broken", { mode: 0o600 }); const loaded = await store.load(); assert.equal(loaded.migrating, false); assert.equal(loaded.manifest.runtimes.length, 0); assert.equal(loaded.issue.code, "invalid_workspace_manifest"); }); test("recovers its serialized write queue after a failed save", async () => { const root = await mkdtemp(join(tmpdir(), "pi-workspace-retry-")); const sessionRoot = join(root, "sessions"); const store = createWorkspaceStore(sessionRoot); await mkdir(sessionRoot); await mkdir(store.filePath); await assert.rejects( store.save({ version: 2, migrated: true, runtimes: [] }), ); await rm(store.filePath, { recursive: true }); await store.save({ version: 2, migrated: true, runtimes: [] }); assert.deepEqual((await store.load()).manifest.runtimes, []); });