Q126: a file write and its record succeed or fail together

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-08 20:27:28 -04:00
1 parent 11cdc4af20
commit 5799a3561f
7 files changed
+119 -48

No files matched your search

+15
View File
@@ -66,4 +66,19 @@ describe("files shared in a private conversation", () => {
rmSync(huge);
connection.close();
});
test("an import whose record fails leaves no stored copy behind", async () => {
const connection = new DatabaseConnection(join(tmpdir(), `ac-import-fail-${randomUUID()}.db`));
let orgId = "";
connection.transaction(() => {
orgId = new OrganizationService(connection.db).createOrganization({ organizationName: "Acme", employeeName: "Yang", mission: "m", goal: "g" });
});
const source = join(tmpdir(), `ac-import-fail-${randomUUID()}.md`);
writeFileSync(source, "notes");
connection.db.exec("create trigger registry_down before insert on file_objects begin select raise(abort, 'registry down'); end;");
const artifacts = join(tmpdir(), `ac-import-fail-art-${randomUUID()}`);
await expect(new FileService(connection.db, artifacts).importPath(orgId, source, null)).rejects.toThrow("registry down");
expect(readdirSync(artifacts, { recursive: true }).filter((entry) => String(entry).endsWith(".md"))).toEqual([]);
connection.close();
});
});
+45 -1
View File
@@ -1,5 +1,5 @@
import { createHash, randomUUID } from "node:crypto";
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, expect, test } from "vitest";
@@ -8,6 +8,7 @@ import { OrganizationService } from "../../src/main/services/organization-servic
import { preserveRecordedFiles, recordWorkspaceFile, rescanLegacyFiles } from "../../src/main/services/files/file-object-store";
import { ChatService } from "../../src/main/services/chat-service";
import { readAttachmentTool } from "../../src/main/services/agent-attachment-tools";
import { dispatchAgentTool } from "../../src/main/services/agent-tools";
describe("recorded workspace files", () => {
test("a file id keeps the bytes it was recorded with after the workspace file is rewritten", () => {
@@ -106,3 +107,46 @@ describe("files scanned before whole-file scanning", () => {
connection.close();
});
});
describe("a file write whose record fails", () => {
test("leaves the workspace and the artifact store as they were", async () => {
const connection = new DatabaseConnection(join(tmpdir(), `ac-partial-${randomUUID()}.db`));
const root = join(tmpdir(), `ac-partial-ws-${randomUUID()}`);
mkdirSync(root, { recursive: true });
let orgId = "";
let ceoId = "";
connection.transaction(() => {
const organization = new OrganizationService(connection.db);
orgId = organization.createOrganization({ organizationName: "Acme", employeeName: "Dana", mission: "m", goal: "g" });
ceoId = organization.createAgent({ orgId, name: "CEO", role: "CEO", department: "Executive", modelProviderId: null, modelId: null, budgetCents: 1000, managerAgentId: null, roleLevel: "c_suite" });
});
writeFileSync(join(root, "kept.md"), "old");
connection.db.exec("create trigger registry_down before insert on file_objects begin select raise(abort, 'registry down'); end;");
const deps = { db: connection.db, organization: new OrganizationService(connection.db), chat: new ChatService(connection.db) };
const ctx = { orgId, agent: { id: ceoId, modelProviderId: null, modelId: null }, taskProjectId: null, taskGoalId: null, taskId: null, sourceThreadId: null, workspace: { id: "wsp", localPath: root, writeAccess: true } };
expect(dispatchAgentTool(deps, ctx, { id: "c1", name: "write_deliverable", arguments: { path: "kept.md", content: "new" } })).toBe("ERROR: registry down");
expect(dispatchAgentTool(deps, ctx, { id: "c2", name: "write_deliverable", arguments: { path: "fresh.md", content: "new" } })).toBe("ERROR: registry down");
expect(readFileSync(join(root, "kept.md"), "utf8")).toBe("old");
expect(existsSync(join(root, "fresh.md"))).toBe(false);
// No content copy outlives the record that failed.
expect(existsSync(join(root, ".agentcompany", "files")) ? readdirSync(join(root, ".agentcompany", "files")) : []).toEqual([]);
connection.close();
});
test("a damaged content copy is replaced, never reused", () => {
const connection = new DatabaseConnection(join(tmpdir(), `ac-damaged-${randomUUID()}.db`));
const root = join(tmpdir(), `ac-damaged-ws-${randomUUID()}`);
mkdirSync(join(root, ".agentcompany", "files"), { recursive: true });
let orgId = "";
connection.transaction(() => {
orgId = new OrganizationService(connection.db).createOrganization({ organizationName: "Acme", employeeName: "Dana", mission: "m", goal: "g" });
});
writeFileSync(join(root, "plan.md"), "new");
const sha = createHash("sha256").update("new").digest("hex");
writeFileSync(join(root, ".agentcompany", "files", `${sha}.md`), "n");
const fileId = recordWorkspaceFile(connection.db, { orgId, ownerType: "agent", ownerId: null, workspaceRoot: root, relativePath: "plan.md" });
const stored = (connection.db.prepare("select storage_path from file_objects where id = ?").get(fileId) as { storage_path: string }).storage_path;
expect(readFileSync(stored, "utf8")).toBe("new");
connection.close();
});
});