import type { ValueType, InitializationField, PersistentAttachment, DependencyBinding, BoundDependency, PackageExport, } from "../capability-model/types.js"; import { type ExecutionPlan, ExecutionPlanError, hexDigest } from "./plan.js"; import { portableValueSchema } from "../bindings/portable.js"; function preparedInputPaths(type: ValueType, path: (string | null)[] = []): (string | null)[][] { if (type.kind === "change") return [path]; if (type.kind === "optional") return preparedInputPaths(type.value, path); if (type.kind === "list") return preparedInputPaths(type.value, [...path, null]); if (type.kind === "record") return Object.entries(type.fields).flatMap(([key, value]) => preparedInputPaths(value, [...path, key])); return []; } /** Small data-only interpreter input; no compiler, parser, Node module or SQL dependency reaches the browser. */ export function compileKernelProgram(plan: ExecutionPlan): unknown { if (hexDigest(plan.definition) !== plan.digest) throw new ExecutionPlanError("INVALID_PLAN", "kernel", "Plan digest mismatch"); const workspace = plan.definition.workspace; if (workspace.sharedAttachments.length) throw new ExecutionPlanError( "UNSUPPORTED_SHARED_STORAGE", "kernel", "Stage 0 requires explicit conformance-owned storage", ); const schema = (type: ValueType): unknown | null => { try { return portableValueSchema(type); } catch { return null; } }; const ownerBySlot = new Map(); const edges: unknown[] = []; const owners = plan.definition.owners.map((owner) => { const slots: unknown[] = []; for (const storage of owner.storage as PersistentAttachment[]) { if (storage.kind === "state") { const shape = schema(storage.valueType); if (!shape) throw new ExecutionPlanError("UNSUPPORTED_STORAGE_CODEC", storage.id, "Unsupported canonical value type"); ownerBySlot.set(storage.id, owner.id); slots.push({ id: storage.id, schema: shape, policy: storage.storagePolicy.kind === "register" ? "register" : "crdt", ...(Object.hasOwn(storage, "defaultValue") ? { defaultLiteral: storage.defaultValue } : {}), }); } else { const endpoints = storage.endpoints.map((endpoint) => { if (endpoint.ordered || endpoint.keyType || endpoint.retainOther) throw new ExecutionPlanError( "UNSUPPORTED_GRAPH_FEATURE", storage.id, "Ordered/keyed relations and automatic retention are not implemented", ); return { projection: endpoint.projectionId, constraint: { kind: endpoint.constraint.kind, id: endpoint.constraint.kind === "atom" ? endpoint.constraint.atomId : endpoint.constraint.interfaceRevisionId, }, cardinality: endpoint.cardinality, ...(endpoint.onDelete ? { onDelete: endpoint.onDelete } : {}), }; }); edges.push({ id: storage.id, owner: owner.id, a: endpoints[0], b: endpoints[1] }); } } return { id: owner.id, atom: owner.atom, interface: owner.interface, slots, initialize: (owner.initialization as InitializationField[]).map((field) => ({ input: field.input, binding: field.binding.kind === "state" ? { kind: "state", slot: field.binding.slotId } : { kind: "edge", edge: field.binding.edgeTypeId, projection: field.binding.projectionId }, })), }; }); const slotOwner = (slot: string) => { const owner = ownerBySlot.get(slot); if (!owner) throw new ExecutionPlanError("MISSING_STORAGE_OWNER", slot, "No checked owner"); return owner; }; const via = (binding: DependencyBinding) => "via" in binding && binding.via ? { via: { edge: binding.via.edgeTypeId, projection: binding.via.projectionId } } : {}; const operations = plan.definition.operations.map((operation) => { const binding = operation.binding; let target: unknown; let unsupported: string | null = null; if (binding.kind === "lifecycle") target = { kind: "lifecycle", primitive: binding.primitive }; else if (binding.kind === "state") target = { kind: "state", owner: slotOwner(binding.slotId), slot: binding.slotId, primitive: binding.primitive }; else if (binding.kind === "edge") target = { kind: "edge", edge: binding.edgeTypeId, projection: binding.projectionId, primitive: binding.primitive, }; else { const pkg = workspace.packageImports.find((p) => p.revisionId === binding.packageRevisionId)!; const entry = pkg.exports.find((e) => e.id === binding.exportId)!; const compilePorts = (entry: PackageExport, dependencies: BoundDependency[]) => dependencies.map((dependency) => { const requirement = entry.dependencyPorts.find((p) => p.id === dependency.portId)!.requirement; const bound = dependency.binding; const common = { id: dependency.portId, ...via(bound) }; if (bound.kind === "state" && requirement.kind === "state") return { ...common, kind: "state", owner: slotOwner(bound.slotId), slot: bound.slotId, primitives: requirement.primitives, }; if (bound.kind === "edge" && requirement.kind === "edge") return { ...common, kind: "edge", edge: bound.edgeTypeId, projection: bound.projectionId, primitives: requirement.primitives, }; if (bound.kind === "interface" && requirement.kind === "interface") { const iface = workspace.interfaceImports.find((i) => i.revisionId === bound.interfaceRevisionId)!; return { ...common, kind: "interface", interface: bound.interfaceRevisionId, ...(bound.receiver ? { receiver: bound.receiver } : {}), operations: requirement.operations ?? iface.members.flatMap((m) => m.operations.map((o) => o.id)), }; } if (bound.kind === "creation" && requirement.kind === "creation") return { ...common, kind: "creation", atom: bound.atomId, schema: portableValueSchema(requirement.inputType), recipe: hexDigest({ plan: plan.digest, operation: operation.key, port: dependency.portId }), owners: bound.owners.map((seed) => { const owner = owners.find((o) => o.atom === bound.atomId && o.interface === seed.interfaceRevisionId); if (!owner) throw new ExecutionPlanError( "MISSING_STORAGE_OWNER", dependency.portId, "Creation has no initialization owner", ); return { owner: owner.id, inputPath: seed.inputPath }; }), }; unsupported = `UNSUPPORTED_EXECUTION_PORT:${bound.kind}`; return { ...common, kind: "unavailable" }; }); const ports = compilePorts(entry, binding.dependencies); const check = entry.acceptanceExportId ? pkg.exports.find((candidate) => candidate.id === entry.acceptanceExportId)! : undefined; target = { kind: "package", package: binding.packageRevisionId, export: binding.exportId, ports, ...(check ? { acceptance: { export: check.id, ports: compilePorts(check, binding.acceptanceDependencies ?? []) } } : {}), }; } const inputChanges = preparedInputPaths(operation.input); const input = schema(operation.input), output = schema(operation.output); return { key: operation.key, atom: operation.atomId, interface: operation.interfaceRevisionId, operation: operation.operationId, scope: operation.scope, effect: operation.execution.kind, targets: operation.execution.kind === "remote" ? [] : operation.execution.targets, input, ...(inputChanges.length ? { inputChanges } : {}), output, unsupported: unsupported ?? (input && output ? null : "UNSUPPORTED_OPERATION_CODEC"), binding: target, }; }); const packages = workspace.packageImports.map((pkg) => ({ revision: pkg.revisionId, exports: pkg.exports.map((entry) => ({ id: entry.id, ...(entry.acceptanceExportId ? { acceptance: entry.acceptanceExportId } : {}), effect: entry.execution?.kind ?? "remote", targets: entry.execution && entry.execution.kind !== "remote" ? entry.execution.targets : [], receiver: entry.kind === "function" ? null : entry.kind === "operation" && entry.receiverRequirement.kind === "exact-atom" ? { kind: "atom", id: entry.receiverRequirement.atomId } : "object", input: schema(entry.inputType), output: schema(entry.outputType), })), })); return { codec: "camino-kernel-program-v1", plan: plan.digest, model: { workspace: workspace.workspaceId, atoms: workspace.atoms.map((atom) => atom.id), owners, edges }, operations, packages, }; }