import assert from "node:assert/strict"; import { test } from "node:test"; import { compileCapabilityResourceSource, compileCapabilitySource, formatQx, } from "../src/capability-language/index.js"; import { validateWorkspaceRevision, compileWorkspaceRevision, computeCapabilityClosure, capabilityId, type InterfaceRevision, } from "../src/capability-model/index.js"; import { compileExecutionPlan, checkExecutionWorld } from "../src/execution-world/index.js"; const source = { repository: "https://example.test/modules.git", commit: "a".repeat(40) }; const interfaces = new Map(); function define(text: string) { const result = compileCapabilityResourceSource(text, { source, environment: { interfaces, interfaceClosure: [...interfaces.values()] }, }); assert.ok(result.ok && result.resource.kind === "interface", JSON.stringify(result.diagnostics)); interfaces.set(result.resource.revision.displayName, result.resource.revision); } define('interface Data id "interface:data" revision "interface:data@1" {}'); define('interface Other id "interface:other" revision "interface:other@1" {}'); define(`import interface Data; interface Row id "interface:row" revision "interface:row@1" { module render id "member:row:render" contract "org.quixos.react.component/1" subject interface Data; }`); define(`interface Standalone id "interface:standalone" revision "interface:standalone@1" { module render id "member:standalone:render" contract "org.quixos.react.subject-only/1" subject object Subject; }`); const packageSource = `import interface Row; import interface Data; import interface Standalone; package UI id "package:ui" revision "package:ui@1" { module Row id "module:row" implements Row.render; module Editor id "module:editor" implements Standalone.render; }`; function compile( body = `conform Item as Data id "owner:data" {} conform Item as Row id "owner:row" {bind render to UI.Row;} conform Item as Standalone id "owner:standalone" {bind render to UI.Editor;}`, ) { const pkg = compileCapabilityResourceSource(packageSource, { source, environment: { interfaces, interfaceClosure: [...interfaces.values()] }, }); assert.ok(pkg.ok && pkg.resource.kind === "package", JSON.stringify(pkg.diagnostics)); return compileCapabilitySource( `workspace Demo id "workspace:demo" revision "workspace:demo@1" commit "${source.commit}" { import interface Data; import interface Other; import interface Row; import interface Standalone; import package UI; atom Item id "atom:item"; ${body} }`, "workspace.qx", { interfaces, interfaceClosure: [...interfaces.values()], packages: new Map([["UI", pkg.resource.revision]]), }, ); } test("module members bind independent roles, including closed generic subjects, without operations or storage", () => { const result = compile(); assert.ok(result.ok, JSON.stringify(result.diagnostics)); const pkg = result.workspace.packageImports[0]!; assert.equal(pkg.exports.length, 0); assert.equal(pkg.modules?.length, 2); const roles = result.workspace.conformances.filter((entry) => entry.moduleBindings?.length); assert.equal(roles.length, 2); for (const role of roles) { assert.deepEqual(role.operationBindings, []); assert.deepEqual(role.privateAttachments, []); const iface: InterfaceRevision = result.workspace.interfaceImports.find( (entry) => entry.revisionId === role.interfaceRevisionId, )!; assert.equal(iface.members[0]!.kind, "module"); assert.deepEqual(iface.members[0]!.operations, []); } }); test("module bindings reject missing, duplicate and wrong nominal roles and unsatisfied subjects", () => { for (const body of [ "conform Item as Data {} conform Item as Row {}", "conform Item as Data {} conform Item as Row {bind render to UI.Editor;}", "conform Item as Data {} conform Item as Row {bind render to UI.Row; bind render to UI.Row;}", "conform Item as Other {} conform Item as Row {bind render to UI.Row;}", "conform Item as Data {} conform Item as Row {bind render to UI.Missing;}", ]) { const result = compile(body); assert.equal(result.ok, false, body); if (!result.ok) assert.match(JSON.stringify(result.diagnostics), /module/i); } }); test("module declarations and bindings round-trip through the ordinary formatter", () => { const formatted = formatQx(packageSource); assert.equal(formatQx(formatted), formatted); const result = compileCapabilityResourceSource(formatted, { source, environment: { interfaces, interfaceClosure: [...interfaces.values()] }, }); assert.ok(result.ok, JSON.stringify(result.diagnostics)); }); test("the old React-specific package declaration is no longer a public language path", () => { const result = compileCapabilityResourceSource( 'import interface Data; package UI id "package:ui" revision "package:ui@1" { component Card id "card" subject Data runtime react; }', { source, environment: { interfaces, interfaceClosure: [...interfaces.values()] } }, ); assert.equal(result.ok, false); assert.ok(result.diagnostics.some((diagnostic) => diagnostic.phase === "syntax")); }); test("module closure retains the provider and subject but no synthetic state", () => { const result = compile(); assert.ok(result.ok, JSON.stringify(result.diagnostics)); const compiled = compileWorkspaceRevision(result.workspace); assert.ok(compiled.ok); const closure = computeCapabilityClosure(compiled.plan, [ { atomId: capabilityId.atom("atom:item"), interfaceRevisionId: capabilityId.interfaceRevision("interface:row@1"), }, ]); assert.deepEqual(closure.packageRevisionIds, ["package:ui@1"]); assert.deepEqual(closure.attachmentIds, []); assert.deepEqual( new Set(closure.conformances.map((entry) => entry.interfaceRevisionId)), new Set(["interface:row@1", "interface:data@1"]), ); }); test("unknown namespaced module contracts remain metadata and malformed contracts reject", () => { const result = compile(); assert.ok(result.ok, JSON.stringify(result.diagnostics)); const workspace = structuredClone(result.workspace); const iface: InterfaceRevision = workspace.interfaceImports.find((entry) => entry.revisionId === "interface:row@1")!; const member = iface.members[0]!; assert.equal(member.kind, "module"); if (member.kind !== "module") throw Error("Expected module"); member.contract = "example.device.firmware/2"; assert.deepEqual(validateWorkspaceRevision(workspace), []); member.contract = "react"; assert.ok(validateWorkspaceRevision(workspace).some((issue) => issue.code === "invalid-module-contract")); }); test("execution plans retain nominal module contracts without synthesizing callable operations", async () => { const result = compile(); assert.ok(result.ok, JSON.stringify(result.diagnostics)); const plan = compileExecutionPlan(result.workspace); assert.deepEqual(plan.definition.operations, []); const pkg = plan.definition.packages[0]!; assert.equal(pkg.modules?.length, 2); assert.deepEqual(pkg.modules?.find((module) => module.id === "module:editor")?.subject, { kind: "interface", interfaceRevisionId: "interface:data@1", }); // A language declaration cannot silently pass installation without an artifact consumer. await assert.rejects( checkExecutionWorld( plan, [ { schemaVersion: 1, packageRevisionId: pkg.revision, bindingDigest: pkg.bindingDigest, sourceDigest: pkg.sourceDigest, versions: plan.definition.versions, implementations: [], }, ], async () => { throw Error("Must reject before reading files"); }, ), /Missing component artifact/, ); }); test("unrecognized module consumers fail before artifact execution, not during interface compilation", async () => { const result = compile(); assert.ok(result.ok, JSON.stringify(result.diagnostics)); const workspace = structuredClone(result.workspace); const member = workspace.interfaceImports.find((iface) => iface.revisionId === "interface:row@1")!.members[0]!; assert.equal(member.kind, "module"); if (member.kind !== "module") throw Error("Expected module"); member.contract = "example.device.firmware/2"; const plan = compileExecutionPlan(workspace); const pkg = plan.definition.packages[0]!; await assert.rejects( checkExecutionWorld( plan, [ { schemaVersion: 1, packageRevisionId: pkg.revision, bindingDigest: pkg.bindingDigest, sourceDigest: pkg.sourceDigest, versions: plan.definition.versions, implementations: [], }, ], async () => { throw Error("Must reject before reading files"); }, ), /No artifact consumer.*example.device.firmware/, ); }); test("artifact consumers receive checked closed role arguments and prerequisites", async () => { const { moduleTypeContext } = await import("../src/execution-world/module-contracts.js"); const { generateInterfaceClientBindings } = await import("../src/execution-world/client-contracts.js"); const result = compile(); assert.ok(result.ok, JSON.stringify(result.diagnostics)); const role = result.workspace.interfaceImports.find((iface) => iface.application)!; const expected = [{ kind: "object", target: { kind: "interface", interfaceRevisionId: "interface:data@1" } }]; assert.deepEqual(moduleTypeContext(role), { typeArguments: expected }); const plan = compileExecutionPlan(result.workspace); assert.deepEqual( plan.definition.packages[0]!.modules!.find((module) => module.displayName === "Editor")!.typeArguments, expected, ); assert.match(generateInterfaceClientBindings({ Editor: role }), /"typeArguments":\[/); assert.deepEqual(moduleTypeContext(interfaces.get("Row")!), {}); // Prerequisites are public nominal contracts, never private storage inventory. assert.deepEqual( moduleTypeContext({ ...role, requiredInterfaces: [capabilityId.interfaceRevision("z"), capabilityId.interfaceRevision("a")], }).requiredInterfaces, ["a", "z"], ); });