import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import { test } from "node:test"; import { compoundCrdtPlan } from "./compound-crdt-fixture.js"; import { compileCapabilityResourceSource, compileCapabilitySource } from "../src/capability-language/parser.js"; import { compileKernelProgram } from "../src/execution-world/index.js"; import { generatePortableTypeScriptBindings } from "../src/bindings/portable.js"; const source = { repository: "https://example.test/change.git", commit: "a".repeat(40) }; test("compound captured changes survive planning, transport lowering and typed edit ports", async () => { const plan = await compoundCrdtPlan(); const kernel = compileKernelProgram(plan) as { operations: { operation: string; inputChanges?: (string | null)[][]; input: { fields: { change: { kind: string } } }; }[]; }; const operation = kernel.operations.find((op) => op.operation === "compound:update:call")!; assert.equal(operation.input.fields.change.kind, "record"); const paths = kernel.operations as unknown as { operation: string; inputChanges?: (string | null)[][] }[]; assert.deepEqual(paths.find((op) => op.operation === "compound:update:call")!.inputChanges, [["change"]]); assert.deepEqual(paths.find((op) => op.operation === "compound:batch:call")!.inputChanges, [ ["edits", null, "change"], ]); assert.deepEqual(paths.find((op) => op.operation === "compound:content:edit")!.inputChanges, [[]]); const code = generatePortableTypeScriptBindings(plan.definition.bindingSchema, "compound:runtime@1", { target: "target:org.quixos.execution.javascript@1", }); assert.ok(code.includes("PreparedChange<")); assert.ok(code.includes('"edit"')); assert.ok(!code.includes('"compound:runtime:check"')); }); test("prepared changes require one storable materialized type", () => { for (const shape of ["change", "change", "change>", "change>"]) { const result = compileCapabilityResourceSource( `symbol JavaScript id "target:org.quixos.execution.javascript@1"; external atom N id "n"; package P id "p" revision "p@1" { function f id "f" : ${shape} -> unit execution transaction targets [JavaScript, server]; }`, { source }, ); assert.equal(result.ok, false, shape); } }); test("captured changes cannot be persisted in a register or CRDT", async () => { const iface = compileCapabilityResourceSource(await readFile("test/fixtures/compound-crdt/NoteData.qx", "utf8"), { source, }); assert.ok(iface.ok && iface.resource.kind === "interface", JSON.stringify(iface.diagnostics)); const pkg = compileCapabilityResourceSource(await readFile("test/fixtures/compound-crdt/EditRuntime.qx", "utf8"), { source, }); assert.ok(pkg.ok && pkg.resource.kind === "package", JSON.stringify(pkg.diagnostics)); const workspace = await readFile("test/fixtures/compound-crdt/workspace.qx", "utf8"); for (const policy of ["register", "crdt(change)"]) { const result = compileCapabilitySource( workspace.replace( "private state Allowed", `private state Captured id "captured" on Note : record { captured: change; } policy ${policy};\n private state Allowed`, ), "workspace.qx", { interfaces: new Map([["NoteData", iface.resource.revision]]), packages: new Map([["EditRuntime", pkg.resource.revision]]), }, ); assert.equal(result.ok, false); assert.ok( result.diagnostics.some((d) => d.code === "invalid-attachment"), JSON.stringify(result.diagnostics), ); } });