Q121: a file id keeps the bytes it was recorded with; rewrites get new ids

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ZacharyZhang-NYandClaude Opus 5.5 committed 2026-10-08 19:34:44 -04:00
1 parent 04c8cce0c4
commit 8f192eabe7
11 files changed
+143 -19

No files matched your search

+1 -1
View File
@@ -24,7 +24,7 @@ describe("domain services", () => {
const connection = createConnection();
const rows = connection.db.prepare("select version from schema_migrations order by version asc").all() as Array<{ version: number }>;
expect(rows.map((row) => row.version)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88]);
expect(rows.map((row) => row.version)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89]);
connection.close();
});
+1 -1
View File
@@ -14,7 +14,7 @@ function agent(id: string, department: string): AgentRecord {
function file(id: string, ownerType: FileObjectRecord["ownerType"], ownerId: string | null): FileObjectRecord {
return {
id, orgId: "org", name: id, kind: "doc", sizeBytes: 1, sha256: "x", storagePath: `/tmp/${id}`,
id, orgId: "org", name: id, kind: "doc", sizeBytes: 1, sha256: "x", storagePath: `/tmp/${id}`, sourcePath: null, supersededAt: null,
ownerType, ownerId, spaceId: null, pinned: false, scanState: "approved", scanLabelsJson: "[]",
scannedAt: null, createdAt: "2026-01-01", updatedAt: null,
};
@@ -0,0 +1,60 @@
import { createHash, randomUUID } from "node:crypto";
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, expect, test } from "vitest";
import { DatabaseConnection } from "../../src/main/database/connection";
import { OrganizationService } from "../../src/main/services/organization-service";
import { preserveRecordedFiles, recordWorkspaceFile } from "../../src/main/services/files/file-object-store";
describe("recorded workspace files", () => {
test("a file id keeps the bytes it was recorded with after the workspace file is rewritten", () => {
const connection = new DatabaseConnection(join(tmpdir(), `ac-versions-${randomUUID()}.db`));
const root = join(tmpdir(), `ac-versions-ws-${randomUUID()}`);
mkdirSync(root, { recursive: true });
let orgId = "";
connection.transaction(() => {
orgId = new OrganizationService(connection.db).createOrganization({ organizationName: "Acme", employeeName: "Dana", mission: "m", goal: "g" });
});
const record = () => recordWorkspaceFile(connection.db, { orgId, ownerType: "agent", ownerId: null, workspaceRoot: root, relativePath: "plan.md" });
const file = (id: string) => connection.db.prepare("select storage_path, superseded_at from file_objects where id = ?").get(id) as { storage_path: string; superseded_at: string | null };
writeFileSync(join(root, "plan.md"), "handed over");
const first = record();
expect(record()).toBe(first);
writeFileSync(join(root, "plan.md"), "rewritten later");
const second = record();
expect(second).not.toBe(first);
expect(readFileSync(file(first).storage_path, "utf8")).toBe("handed over");
expect(readFileSync(file(second).storage_path, "utf8")).toBe("rewritten later");
expect(file(first).superseded_at).not.toBeNull();
expect(file(second).superseded_at).toBeNull();
connection.close();
});
test("ids recorded before copies existed get their bytes kept at startup, with their extension", () => {
const connection = new DatabaseConnection(join(tmpdir(), `ac-legacy-${randomUUID()}.db`));
const root = join(tmpdir(), `ac-legacy-ws-${randomUUID()}`);
mkdirSync(root, { recursive: true });
let orgId = "";
connection.transaction(() => {
orgId = new OrganizationService(connection.db).createOrganization({ organizationName: "Acme", employeeName: "Dana", mission: "m", goal: "g" });
new OrganizationService(connection.db).createWorkspace({ orgId, name: "HQ", localPath: root, projectId: null });
});
const live = join(root, "report.md");
writeFileSync(live, "as handed over");
const sha = createHash("sha256").update("as handed over").digest("hex");
const now = new Date().toISOString();
connection.db.prepare(`
insert into file_objects(id, org_id, name, kind, size_bytes, sha256, storage_path, source_path, owner_type, owner_id, pinned, scan_state, scan_labels_json, created_at)
values ('fil_legacy', ?, 'report.md', 'doc', 14, ?, ?, ?, 'agent', null, 0, 'approved', '[]', ?)
`).run(orgId, sha, live, live, now);
preserveRecordedFiles(connection.db);
writeFileSync(live, "rewritten");
const kept = (connection.db.prepare("select storage_path from file_objects where id = 'fil_legacy'").get() as { storage_path: string }).storage_path;
expect(kept.endsWith(`${sha}.md`)).toBe(true);
expect(readFileSync(kept, "utf8")).toBe("as handed over");
connection.close();
});
});