Check execution workspace candidates with pinned artifact builders
This commit is contained in:
@@ -77,6 +77,7 @@
|
|||||||
mkdir -p "$out"
|
mkdir -p "$out"
|
||||||
install -Dm644 nix/checked-package.nix "$out/share/checked-package.nix"
|
install -Dm644 nix/checked-package.nix "$out/share/checked-package.nix"
|
||||||
install -Dm644 nix/checked-artifacts.nix "$out/share/checked-artifacts.nix"
|
install -Dm644 nix/checked-artifacts.nix "$out/share/checked-artifacts.nix"
|
||||||
|
install -Dm644 nix/check-execution.mjs "$out/share/check-execution.mjs"
|
||||||
substitute nix/checked-candidate.nix "$out/share/checked-candidate.nix" \
|
substitute nix/checked-candidate.nix "$out/share/checked-candidate.nix" \
|
||||||
--replace-fail '@nixpkgs@' '${pkgs.path}'
|
--replace-fail '@nixpkgs@' '${pkgs.path}'
|
||||||
cp --reflink=auto --recursive grammar "$out/grammar"
|
cp --reflink=auto --recursive grammar "$out/grammar"
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// Validate compiler-owned plans and immutable artifact receipts before publishing check outputs.
|
||||||
|
import { readFile, writeFile } from "node:fs/promises";
|
||||||
|
import { createHash } from "node:crypto";
|
||||||
|
import { pathToFileURL } from "node:url";
|
||||||
|
import { join } from "node:path";
|
||||||
|
const [compilerPath, planPath, checksPath, output] = process.argv.slice(2);
|
||||||
|
const compiler = await import(pathToFileURL(compilerPath));
|
||||||
|
const plan = JSON.parse(await readFile(planPath, "utf8"));
|
||||||
|
const checks = JSON.parse(await readFile(checksPath, "utf8"));
|
||||||
|
const roots = Object.create(null);
|
||||||
|
for (const check of checks) {
|
||||||
|
if (Object.hasOwn(roots, check.packageRevisionId)) throw Error("Duplicate checked package revision");
|
||||||
|
roots[check.packageRevisionId] = check.artifactPath;
|
||||||
|
}
|
||||||
|
const checked = await compiler.loadCheckedArtifactWorld(
|
||||||
|
plan,
|
||||||
|
roots,
|
||||||
|
createHash("sha256")
|
||||||
|
.update(await readFile(compilerPath))
|
||||||
|
.digest("hex"),
|
||||||
|
);
|
||||||
|
for (const [file, value] of [
|
||||||
|
["execution-world.json", checked.world],
|
||||||
|
["kernel.json", compiler.compileKernelProgram(plan)],
|
||||||
|
["queries.json", compiler.compileQueryProgram(plan)],
|
||||||
|
["execution-artifacts.json", { codec: "camino-checked-execution-v1", roots, manifests: checked.manifests }],
|
||||||
|
])
|
||||||
|
await writeFile(join(output, file), JSON.stringify(value) + "\n");
|
||||||
+54
-17
@@ -37,8 +37,18 @@ let
|
|||||||
entry: load (ancestors ++ [ (sourceKey source) ]) (entry.source // { inherit (entry) kind; })
|
entry: load (ancestors ++ [ (sourceKey source) ]) (entry.source // { inherit (entry) kind; })
|
||||||
) lock.resources;
|
) lock.resources;
|
||||||
in
|
in
|
||||||
source // { inherit directory children; };
|
source // { inherit directory children lock; };
|
||||||
root = load [ ] { inherit kind repository commit; };
|
root = load [ ] { inherit kind repository commit; };
|
||||||
|
configuration =
|
||||||
|
if builtins.pathExists (root.directory + "/quixos.check.json") then
|
||||||
|
builtins.fromJSON (builtins.readFile (root.directory + "/quixos.check.json"))
|
||||||
|
else
|
||||||
|
{ };
|
||||||
|
execution = (configuration.backend or "typescript") == "execution";
|
||||||
|
runtime = builtins.getFlake (
|
||||||
|
"git+${root.lock.quixos.repository}?rev=${root.lock.quixos.commit}&ref=refs/tags/quixos-reachability/${root.lock.quixos.commit}"
|
||||||
|
);
|
||||||
|
runtimePackages = runtime.packages.${system};
|
||||||
flatten = node: [ node ] ++ pkgs.lib.concatMap flatten node.children;
|
flatten = node: [ node ] ++ pkgs.lib.concatMap flatten node.children;
|
||||||
nodes = builtins.attrValues (
|
nodes = builtins.attrValues (
|
||||||
builtins.listToAttrs (
|
builtins.listToAttrs (
|
||||||
@@ -70,7 +80,8 @@ let
|
|||||||
${protocol}/bin/quixos-workspace-compile --root ${node.directory} \
|
${protocol}/bin/quixos-workspace-compile --root ${node.directory} \
|
||||||
--source-root-commit ${pkgs.lib.escapeShellArg node.commit} \
|
--source-root-commit ${pkgs.lib.escapeShellArg node.commit} \
|
||||||
--checkout-root "$TMPDIR/checkouts" --snapshot-map ${snapshots} \
|
--checkout-root "$TMPDIR/checkouts" --snapshot-map ${snapshots} \
|
||||||
--graph-out "$out/graph.json" --schemas-out "$out/package-schemas.json" > "$out/candidate.json"
|
--graph-out "$out/graph.json" --schemas-out "$out/package-schemas.json" \
|
||||||
|
${pkgs.lib.optionalString execution ''--execution-plan-out "$out/execution-plan.json"''} > "$out/candidate.json"
|
||||||
''
|
''
|
||||||
else
|
else
|
||||||
''
|
''
|
||||||
@@ -92,21 +103,37 @@ let
|
|||||||
"git+${node.repository}?rev=${node.commit}&ref=refs/tags/quixos-reachability/${node.commit}"
|
"git+${node.repository}?rev=${node.commit}&ref=refs/tags/quixos-reachability/${node.commit}"
|
||||||
);
|
);
|
||||||
checked =
|
checked =
|
||||||
package.quixosPackages.${system}.checkedServer
|
if execution then
|
||||||
or (throw "Package ${node.repository} lacks checkedServer; use the supported package scaffold.");
|
package.quixosPackages.${system}.checkedArtifacts
|
||||||
artifact = checked {
|
or (throw "Package ${node.repository} lacks checkedArtifacts; execution workspaces cannot import legacy servers.")
|
||||||
schema =
|
else
|
||||||
if kind == "workspace" then
|
package.quixosPackages.${system}.checkedServer
|
||||||
pkgs.writeText "package-specialization-schema.json" (
|
or (throw "Package ${node.repository} lacks checkedServer; use the supported package scaffold.");
|
||||||
builtins.toJSON
|
artifact = checked (
|
||||||
(builtins.fromJSON (builtins.readFile "${contract}/package-schemas.json"))
|
if execution then
|
||||||
.${candidate.revision.revisionId}
|
{
|
||||||
)
|
plan = "${contract}/execution-plan.json";
|
||||||
else
|
generator = protocol;
|
||||||
"${compiled}/bindings.json";
|
core = runtimePackages.camino-replica-core;
|
||||||
generator = protocol;
|
sharedRuntime = runtimePackages.camino-shared-runtime;
|
||||||
packageRevisionId = candidate.revision.revisionId;
|
typescript = runtimePackages.camino-replica-core.dependencies;
|
||||||
};
|
packageRevisionId = candidate.revision.revisionId;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
schema =
|
||||||
|
if kind == "workspace" then
|
||||||
|
pkgs.writeText "package-specialization-schema.json" (
|
||||||
|
builtins.toJSON
|
||||||
|
(builtins.fromJSON (builtins.readFile "${contract}/package-schemas.json"))
|
||||||
|
.${candidate.revision.revisionId}
|
||||||
|
)
|
||||||
|
else
|
||||||
|
"${compiled}/bindings.json";
|
||||||
|
generator = protocol;
|
||||||
|
packageRevisionId = candidate.revision.revisionId;
|
||||||
|
}
|
||||||
|
);
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
packageRevisionId = candidate.revision.revisionId;
|
packageRevisionId = candidate.revision.revisionId;
|
||||||
@@ -124,11 +151,21 @@ let
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
in
|
in
|
||||||
|
assert pkgs.lib.assertMsg (!execution || kind == "workspace")
|
||||||
|
"Execution packages must be checked in their complete workspace; run qx-workspace check from the workspace root.";
|
||||||
pkgs.runCommand (if contractOnly then "qx-contract" else "qx-checked-candidate") { } ''
|
pkgs.runCommand (if contractOnly then "qx-contract" else "qx-checked-candidate") { } ''
|
||||||
mkdir -p "$out"
|
mkdir -p "$out"
|
||||||
cp ${contract}/candidate.json "$out/candidate.json"
|
cp ${contract}/candidate.json "$out/candidate.json"
|
||||||
cp ${contract}/graph.json "$out/graph.json"
|
cp ${contract}/graph.json "$out/graph.json"
|
||||||
cp ${manifest} "$out/checks.json"
|
cp ${manifest} "$out/checks.json"
|
||||||
|
${pkgs.lib.optionalString execution ''
|
||||||
|
cp ${contract}/execution-plan.json "$out/execution-plan.json"
|
||||||
|
${pkgs.lib.optionalString (!contractOnly) ''
|
||||||
|
${pkgs.nodejs_24}/bin/node ${./check-execution.mjs} \
|
||||||
|
${protocol}/libexec/quixos-protocol/execution-world.mjs \
|
||||||
|
"$out/execution-plan.json" "$out/checks.json" "$out"
|
||||||
|
''}
|
||||||
|
''}
|
||||||
${pkgs.lib.optionalString (
|
${pkgs.lib.optionalString (
|
||||||
kind != "workspace"
|
kind != "workspace"
|
||||||
) ''cp ${contract}/bindings.json "$out/bindings.json"''}
|
) ''cp ${contract}/bindings.json "$out/bindings.json"''}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export async function checkAuthoring(
|
|||||||
phase: string;
|
phase: string;
|
||||||
output: string;
|
output: string;
|
||||||
compilation?: "passed";
|
compilation?: "passed";
|
||||||
|
runtime?: "execution";
|
||||||
activationReadiness?: "preserve" | "migration-required" | "blocked";
|
activationReadiness?: "preserve" | "migration-required" | "blocked";
|
||||||
migrationRequired?: string[];
|
migrationRequired?: string[];
|
||||||
} = {
|
} = {
|
||||||
@@ -98,7 +99,13 @@ export async function checkAuthoring(
|
|||||||
const candidateText = await fs.readFile(path.join(report.artifactPath, "candidate.json"), "utf8");
|
const candidateText = await fs.readFile(path.join(report.artifactPath, "candidate.json"), "utf8");
|
||||||
await fs.writeFile(path.join(output, "candidate.json"), candidateText);
|
await fs.writeFile(path.join(output, "candidate.json"), candidateText);
|
||||||
report.compilation = "passed";
|
report.compilation = "passed";
|
||||||
if (resource.kind === "workspace" && !options.contractOnly) {
|
try {
|
||||||
|
await fs.access(path.join(report.artifactPath, "execution-plan.json"));
|
||||||
|
report.runtime = "execution";
|
||||||
|
} catch (error) {
|
||||||
|
if ((error as NodeJS.ErrnoException).code !== "ENOENT") throw error;
|
||||||
|
}
|
||||||
|
if (resource.kind === "workspace" && !options.contractOnly && report.runtime !== "execution") {
|
||||||
report.phase = "evolution";
|
report.phase = "evolution";
|
||||||
await progress();
|
await progress();
|
||||||
let baseline = options.baseline;
|
let baseline = options.baseline;
|
||||||
|
|||||||
Reference in New Issue
Block a user