import { compileKernelProgram } from "./kernel.js"; import { hexDigest, type ExecutionPlan } from "./plan.js"; import type { PublicQueryContract } from "./client-contracts.js"; import { portableValueSchema } from "../bindings/portable.js"; const scalar = (name: string) => ({ kind: "scalar", name }); const record = (fields: Record) => ({ kind: "record", fields }); const optional = (value: unknown) => ({ kind: "optional", value }); const selection = (name: string, extra: Record = {}) => ({ name, key: name, arguments: {}, conditions: [], selection: [], ...extra, }); const variable = (name: string) => ({ kind: "variable", name }); const meta = () => selection("_camino", { selection: [selection("ref")] }); export const inspectionPackage = "org.quixos.inspection/1"; export interface InspectionTemplate { interface: string; members: { id: string; name: string; key: string; flag: string; lane: "local" | "server"; many: boolean; relationship: boolean; }[]; inputs?: PublicQueryContract; view?: PublicQueryContract; server?: PublicQueryContract; completeInputs?: PublicQueryContract; completeView?: PublicQueryContract; } /** A finite installed template per interface/lane, not a per-client query compiler. * Flags select public cache boundaries; normal scope identity bounds specialization. */ export function compileInspectionTemplates(plan: ExecutionPlan) { const kernel = compileKernelProgram(plan) as { operations: { key: string; atom: string; interface: string; operation: string; effect: string; targets: string[]; unsupported: string | null; output: unknown; binding: { kind: string }; }[]; }; const queries: unknown[] = [], contracts: PublicQueryContract[] = [], templates: InspectionTemplate[] = []; for (const iface of plan.definition.workspace.interfaceImports) { if (iface.template) continue; const atoms = plan.definition.workspace.conformances .filter((c) => c.interfaceRevisionId === iface.revisionId) .map((c) => c.atomId) .sort(); if (!atoms.length) continue; const members = iface.members .filter((member) => (member.kind === "value" || member.kind === "relationship") && member.queryRead) .sort((a, b) => (a.id < b.id ? -1 : 1)); if (!members.length || members.length > 128) continue; const template: InspectionTemplate = { interface: iface.revisionId, members: [] }; for (const mode of ["local", "complete", "server"] as const) { const lane = mode === "server" ? "server" : "local"; const complete = mode === "complete"; const fields: unknown[] = [], selections: unknown[] = [], inputFields: Record = {}, outputFields: Record = {}; for (const [index, member] of members.entries()) { if (member.kind !== "value" && member.kind !== "relationship") continue; const getter = member.operations.find((op) => op.displayName === (member.kind === "value" ? "get" : "resolve")); if (!getter) continue; const providers = atoms.map((atom) => kernel.operations.find( (op) => op.atom === atom && op.interface === iface.revisionId && op.operation === getter.id, ), ); if (providers.some((op) => !op || op.unsupported || !["snapshot", "remote"].includes(op.effect))) continue; const portable = providers.every( (op) => op!.effect === "snapshot" && op!.targets.includes("target:org.quixos.execution.javascript@1"), ); if (lane === "local" && !portable) continue; const key = "m" + index, flag = "s" + index; const many = member.kind === "relationship" && ["many", "many-unique"].includes(member.cardinality); // Only native edges promise the relationship traversal used by the interpreter. if (member.kind === "relationship" && providers.some((op) => op!.binding.kind !== "edge")) continue; if (!complete && (lane === "local" || !portable)) template.members.push({ id: member.id, name: member.displayName, key, flag, lane, many, relationship: member.kind === "relationship", }); inputFields[flag] = scalar("bool"); const field = selection(member.displayName, { key, interfaceRevisionId: iface.revisionId, memberId: member.id, conditions: [{ include: true, value: variable(flag) }], }); let output = portableValueSchema(getter.outputType); if (member.kind === "relationship") { const expectation = member.target.kind === "atom" ? { kind: "atom", id: member.target.atomId } : { kind: "interface", id: member.target.interfaceRevisionId }; const node = record({ _camino: record({ ref: { kind: "object-ref", expectation } }) }); if (member.target.kind === "interface") Object.assign(field, { targetInterfaceRevisionId: member.target.interfaceRevisionId }); if (many) { const bound = key + (complete ? "All" : "First"); inputFields[bound] = scalar("int32"); if (!complete) inputFields[key + "After"] = optional(scalar("string")); const keyFields = { key: scalar("string"), ...(member.keyType ? { mapKey: scalar(member.keyType) } : {}) }; const keySelections = [selection("key"), ...(member.keyType ? [selection("mapKey")] : [])]; Object.assign(field, { arguments: complete ? { all: variable(bound) } : { first: variable(bound), after: variable(key + "After") }, selection: [ selection("entries", { selection: [...keySelections, selection("node", { selection: [meta()] })] }), ...(complete ? [] : [selection("pageInfo", { selection: [selection("hasNextPage"), selection("endCursor")] })]), ], }); output = record({ entries: { kind: "list", value: record({ ...keyFields, node }) }, ...(complete ? {} : { pageInfo: record({ hasNextPage: scalar("bool"), endCursor: optional(scalar("string")) }) }), }); } else { Object.assign(field, { selection: [meta()] }); output = node; } } outputFields[key] = optional(output); selections.push(field); for (const op of providers) fields.push({ atom: op!.atom, interface: iface.revisionId, member: member.id, name: member.displayName, operation: op!.key, }); } if (!selections.length) continue; const root = { kind: "object" as const, interface: iface.revisionId }; const input = record(inputFields), output = record({ root: record(outputFields) }); const base = { root, atoms, variables: input, defaults: {}, selection: [selection("root", { selection: selections })], fields, admittedOperations: [], budgets: { rows: 512, depth: 8, resultBytes: 8 * 1024 * 1024, candidates: 1000, rpcCalls: 128, concurrency: 8, deadlineMs: 10000, }, }; for (const kind of lane === "local" ? (["inputs", "view"] as const) : (["server"] as const)) { const templateKey = complete ? (kind === "inputs" ? "completeInputs" : "completeView") : kind; const query = JSON.stringify([iface.revisionId, templateKey]); const sourceQuery = JSON.stringify([iface.revisionId, complete ? "completeInputs" : "inputs"]); const program = { ...base, id: JSON.stringify([inspectionPackage, query]), placement: kind === "inputs" ? "replica" : kind === "view" ? "local" : "remote", source: kind === "view" ? JSON.stringify([inspectionPackage, sourceQuery]) : null, }; const contract: PublicQueryContract = { package: inspectionPackage, query, definitionDigest: hexDigest(program), root, placement: kind === "inputs" ? "replica" : kind === "view" ? "local" : "server", ...(kind === "view" ? { sourceQuery } : {}), input, output, }; queries.push(program); contracts.push(contract); template[templateKey] = contract; } } if (template.members.length) templates.push(template); } return { queries, contracts, templates }; }