Add exact recursive source checkout, independent Git/jj developer workbenches and source-only backup/recovery commands, with Workspace instance binding outside source. Qualify two empty Reader Graphs, packaged source commands, Agent VM compilation, exact Gitea read grants and reconciled Reader settings/annotation stability. Publish checked Reader Package/root revisions to canonical review branches and retention tags, retain all 57 repositories independently in private versioned storage, verify downloaded-backup recovery and advance the example pin. Add bounded Central pin acquisition and selection-specific read-only identities, qualified against all 57 canonical repositories without write authority. Replace regex fork dependency discovery with compiler-parsed lock imports and rewrite proposals; preserve source identities and unrelated files, passing instance binding through packed and ordinary host checks. Hosted run-pin versus authoring preparation and maintained duplicate removal remain pending. Live source selections, Template defaults and default source branches are unchanged.
348 lines
13 KiB
TypeScript
348 lines
13 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { mkdtemp, mkdir, rm, writeFile } from "node:fs/promises";
|
|
import os from "node:os";
|
|
import path from "node:path";
|
|
import test from "node:test";
|
|
import { compileCapabilityResourceRepository, compileWorkspaceRepository } from "../src/capability-language/index.js";
|
|
|
|
const quixosCommit = "1".repeat(40);
|
|
const namedCommit = "2".repeat(40);
|
|
const packageCommit = "3".repeat(40);
|
|
|
|
const lock = (resources = "") => `quixos-lock version 1 {
|
|
quixos source {
|
|
repository "https://example.test/quixos.git";
|
|
commit "${quixosCommit}";
|
|
}
|
|
${resources}
|
|
}
|
|
`;
|
|
|
|
test("workspace assembly resolves resource-owned dependencies recursively", async (context) => {
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "quixos-assembly-"));
|
|
context.after(() => rm(directory, { recursive: true, force: true }));
|
|
const root = path.join(directory, "root");
|
|
const named = path.join(directory, "named");
|
|
const runtime = path.join(directory, "runtime");
|
|
await Promise.all([mkdir(root), mkdir(named), mkdir(runtime)]);
|
|
await writeFile(
|
|
path.join(root, "quixos.lock"),
|
|
lock(`package Runtime source {
|
|
repository "https://example.test/package-runtime.git";
|
|
commit "${packageCommit}";
|
|
}`),
|
|
);
|
|
await writeFile(
|
|
path.join(root, "workspace.qx"),
|
|
`workspace Test id "workspace:test" revision "workspace:test@1" commit "${"4".repeat(40)}" {
|
|
atom Subject id "atom:subject";
|
|
import package Runtime;
|
|
}
|
|
`,
|
|
);
|
|
await writeFile(path.join(named, "quixos.lock"), lock());
|
|
await writeFile(
|
|
path.join(named, "interface.qx"),
|
|
`interface Named id "interface:named" revision "interface:named@1" {
|
|
value name id "member:named:name" : string {
|
|
get id "operation:named:name:get";
|
|
}
|
|
}
|
|
`,
|
|
);
|
|
await writeFile(
|
|
path.join(runtime, "quixos.lock"),
|
|
lock(`interface Named source {
|
|
repository "https://example.test/interface-named.git";
|
|
commit "${namedCommit}";
|
|
}`),
|
|
);
|
|
await writeFile(
|
|
path.join(runtime, "package.qx"),
|
|
`import interface Named;
|
|
package Runtime id "package:runtime" revision "package:runtime@1" {
|
|
function describe id "export:runtime:describe" : interface-ref<Named> -> string;
|
|
}
|
|
`,
|
|
);
|
|
|
|
const directories = new Map([
|
|
[`interface\0https://example.test/interface-named.git\0${namedCommit}`, named],
|
|
[`package\0https://example.test/package-runtime.git\0${packageCommit}`, runtime],
|
|
]);
|
|
const result = await compileWorkspaceRepository({
|
|
rootDirectory: root,
|
|
resolveResource: async (source, kind) => {
|
|
const resolved = directories.get(`${kind}\0${source.repository}\0${source.commit}`);
|
|
if (!resolved) throw new Error(`Unexpected source ${source.repository}`);
|
|
return { directory: resolved };
|
|
},
|
|
});
|
|
|
|
assert.equal(result.resources.length, 2);
|
|
assert.deepEqual(
|
|
result.workspace.interfaceImports.map((entry) => entry.revisionId),
|
|
["interface:named@1"],
|
|
);
|
|
assert.deepEqual(
|
|
result.workspace.packageImports.map((entry) => entry.revisionId),
|
|
["package:runtime@1"],
|
|
);
|
|
assert.equal(result.directResources.size, 1);
|
|
|
|
const resolveResource = async (source: { repository: string; commit: string }, kind: string) => ({
|
|
directory: directories.get(`${kind}\0${source.repository}\0${source.commit}`)!,
|
|
});
|
|
const bound = await Promise.all(
|
|
["workspace:first", "workspace:second"].map((workspaceId) =>
|
|
compileWorkspaceRepository({
|
|
rootDirectory: root,
|
|
resolveResource,
|
|
workspaceId,
|
|
sourceRootCommit: "5".repeat(40),
|
|
}),
|
|
),
|
|
);
|
|
assert.notEqual(bound[0]!.workspace.workspaceId, bound[1]!.workspace.workspaceId);
|
|
assert.notEqual(bound[0]!.workspace.id, bound[1]!.workspace.id);
|
|
for (const instance of bound) {
|
|
assert.equal(instance.workspace.sourceRootCommit, "5".repeat(40));
|
|
assert.deepEqual(instance.workspace.packageImports, result.workspace.packageImports);
|
|
assert.deepEqual(instance.workspace.interfaceImports, result.workspace.interfaceImports);
|
|
assert.deepEqual(instance.resources, result.resources, "binding does not fork resource identities");
|
|
}
|
|
|
|
const resource = await compileCapabilityResourceRepository({
|
|
rootDirectory: runtime,
|
|
kind: "package",
|
|
source: {
|
|
resolver: "git",
|
|
repository: "https://example.test/package-runtime.git",
|
|
commit: packageCommit,
|
|
},
|
|
resolveResource: async (source, kind) => {
|
|
const resolved = directories.get(`${kind}\0${source.repository}\0${source.commit}`);
|
|
if (!resolved) throw new Error(`Unexpected source ${source.repository}`);
|
|
return { directory: resolved };
|
|
},
|
|
});
|
|
assert.equal(resource.resource.kind, "package");
|
|
assert.equal(resource.resources.length, 2);
|
|
assert.equal(resource.directResources.size, 1);
|
|
|
|
const checked = new Map(result.resources.map((node) => [node.key, node.resource]));
|
|
let generated = 0;
|
|
const reused = await compileWorkspaceRepository({
|
|
rootDirectory: root,
|
|
resolveResource: async (source, kind) => ({
|
|
directory: directories.get(`${kind}\0${source.repository}\0${source.commit}`)!,
|
|
}),
|
|
checkedResource: async (kind, source) => {
|
|
const value = checked.get(`${kind}\0${source.repository}\0${source.commit}`);
|
|
return value?.kind === "build" ? undefined : value;
|
|
},
|
|
generateQueries: async () => {
|
|
generated++;
|
|
return { queries: [], documents: new Map() };
|
|
},
|
|
});
|
|
assert.deepEqual(reused, result, "Nix-composed resource checks preserve full assembly results");
|
|
assert.equal(generated, 0, "unchanged checked packages do not run their query frontend again");
|
|
await assert.rejects(
|
|
compileWorkspaceRepository({
|
|
rootDirectory: root,
|
|
resolveResource: async (source, kind) => ({
|
|
directory: directories.get(`${kind}\0${source.repository}\0${source.commit}`)!,
|
|
}),
|
|
checkedResource: async () => (resource.resource.kind === "build" ? undefined : resource.resource),
|
|
}),
|
|
/Checked resource identity mismatch/,
|
|
);
|
|
});
|
|
|
|
test("resource repositories cannot own workspace Quixos selection policy", async (context) => {
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "quixos-resource-policy-"));
|
|
context.after(() => rm(directory, { recursive: true, force: true }));
|
|
await writeFile(
|
|
path.join(directory, "quixos.lock"),
|
|
`quixos-lock version 1 {
|
|
quixos source {
|
|
repository "https://example.test/quixos.git";
|
|
policy track-development;
|
|
ref "dev/alice/main";
|
|
commit "${quixosCommit}";
|
|
}
|
|
}`,
|
|
);
|
|
await writeFile(
|
|
path.join(directory, "package.qx"),
|
|
`package Runtime id "package:runtime" revision "package:runtime@1" { }\n`,
|
|
);
|
|
|
|
await assert.rejects(
|
|
compileCapabilityResourceRepository({
|
|
rootDirectory: directory,
|
|
kind: "package",
|
|
source: {
|
|
resolver: "git",
|
|
repository: "https://example.test/package-runtime.git",
|
|
commit: packageCommit,
|
|
},
|
|
resolveResource: async () => ({ directory }),
|
|
}),
|
|
/resource locks may only declare their exact authored-against commit/,
|
|
);
|
|
});
|
|
|
|
test("resource manifests cannot hide lock dependencies", async (context) => {
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "quixos-assembly-mismatch-"));
|
|
context.after(() => rm(directory, { recursive: true, force: true }));
|
|
const root = path.join(directory, "root");
|
|
const runtime = path.join(directory, "runtime");
|
|
await Promise.all([mkdir(root), mkdir(runtime)]);
|
|
await writeFile(
|
|
path.join(root, "quixos.lock"),
|
|
lock(`package Runtime source {
|
|
repository "https://example.test/package-runtime.git";
|
|
commit "${packageCommit}";
|
|
}`),
|
|
);
|
|
await writeFile(
|
|
path.join(root, "workspace.qx"),
|
|
`workspace Test id "workspace:test" revision "workspace:test@1" commit "${"4".repeat(40)}" {
|
|
atom Subject id "atom:subject";
|
|
import package Runtime;
|
|
}
|
|
`,
|
|
);
|
|
await writeFile(path.join(runtime, "quixos.lock"), lock());
|
|
await writeFile(
|
|
path.join(runtime, "package.qx"),
|
|
`import interface Hidden;
|
|
package Runtime id "package:runtime" revision "package:runtime@1" { }
|
|
`,
|
|
);
|
|
|
|
await assert.rejects(
|
|
compileWorkspaceRepository({
|
|
rootDirectory: root,
|
|
resolveResource: async () => ({ directory: runtime }),
|
|
}),
|
|
/No resolved interface is available for lock binding Hidden/,
|
|
);
|
|
});
|
|
|
|
test("workspace assembly must satisfy nominal external interfaces", async (context) => {
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "quixos-assembly-external-"));
|
|
context.after(() => rm(directory, { recursive: true, force: true }));
|
|
const root = path.join(directory, "root");
|
|
const runtime = path.join(directory, "runtime");
|
|
await Promise.all([mkdir(root), mkdir(runtime)]);
|
|
await writeFile(
|
|
path.join(root, "quixos.lock"),
|
|
lock(`package Runtime source {
|
|
repository "https://example.test/package-runtime.git";
|
|
commit "${packageCommit}";
|
|
}`),
|
|
);
|
|
await writeFile(
|
|
path.join(root, "workspace.qx"),
|
|
`workspace Test id "workspace:test" revision "workspace:test@1" commit "${"4".repeat(40)}" {
|
|
atom Subject id "atom:subject";
|
|
import package Runtime;
|
|
}
|
|
`,
|
|
);
|
|
await writeFile(path.join(runtime, "quixos.lock"), lock());
|
|
await writeFile(
|
|
path.join(runtime, "package.qx"),
|
|
`external interface Named revision "interface:named@1";
|
|
package Runtime id "package:runtime" revision "package:runtime@1" { }
|
|
`,
|
|
);
|
|
|
|
await assert.rejects(
|
|
compileWorkspaceRepository({
|
|
rootDirectory: root,
|
|
resolveResource: async () => ({ directory: runtime }),
|
|
}),
|
|
/requires external interface Named \(interface:named@1\)/,
|
|
);
|
|
});
|
|
|
|
test("resource-owned fragment imports compile through the locked package closure", async (context) => {
|
|
const directory = await mkdtemp(path.join(os.tmpdir(), "quixos-fragment-assembly-"));
|
|
context.after(() => rm(directory, { recursive: true, force: true }));
|
|
const dirs = Object.fromEntries(["item", "rows", "screen"].map((name) => [name, path.join(directory, name)]));
|
|
await Promise.all(Object.values(dirs).map((dir) => mkdir(dir)));
|
|
const dependency = (kind: string, name: string) =>
|
|
`${kind} ${name} source {repository "https://example.test/${name.toLowerCase()}.git"; commit "${namedCommit}";}`;
|
|
await writeFile(path.join(dirs.item!, "quixos.lock"), lock());
|
|
await writeFile(
|
|
path.join(dirs.item!, "interface.qx"),
|
|
`interface Item id "item" revision "item@1" {queryable value title id "title" : string {get id "title:get" execution snapshot;}}`,
|
|
);
|
|
await writeFile(path.join(dirs.rows!, "quixos.lock"), lock(dependency("interface", "Item")));
|
|
await writeFile(
|
|
path.join(dirs.rows!, "package.qx"),
|
|
`import interface Item; package Rows id "rows" revision "rows@1" {query fragment Row id "row" root Item document "row.graphql" fragment "Row";}`,
|
|
);
|
|
await writeFile(path.join(dirs.rows!, "row.graphql"), "fragment Row on Item {_camino {ref} title}");
|
|
await writeFile(
|
|
path.join(dirs.screen!, "quixos.lock"),
|
|
lock(dependency("interface", "Item") + dependency("package", "Rows")),
|
|
);
|
|
await writeFile(
|
|
path.join(dirs.screen!, "package.qx"),
|
|
`import interface Item; import package Rows; package Screen id "screen" revision "screen@1" {
|
|
query Inputs id "inputs" root Item document "screen.graphql" operation "Screen" {replica; fragments Rows.Row;}
|
|
query View id "view" root Item document "screen.graphql" operation "Screen" {local from Inputs; fragments Rows.Row;}
|
|
}`,
|
|
);
|
|
await writeFile(path.join(dirs.screen!, "screen.graphql"), "query Screen {root {...Row}}");
|
|
const options = {
|
|
rootDirectory: dirs.screen!,
|
|
kind: "package" as const,
|
|
source: { resolver: "git" as const, repository: "https://example.test/screen.git", commit: packageCommit },
|
|
resolveResource: async (source: { repository: string }) => {
|
|
const name = new URL(source.repository).pathname.slice(1, -4);
|
|
assert.ok(dirs[name], name);
|
|
return { directory: dirs[name]! };
|
|
},
|
|
};
|
|
const result = await compileCapabilityResourceRepository(options);
|
|
assert.equal(result.resource.kind, "package");
|
|
if (result.resource.kind !== "package") throw Error("expected package");
|
|
const view = result.resource.revision.checkedQueries!.find((q) => q.declaration.id === "view")!;
|
|
assert.equal(view.selection[0]!.selection[0]!.fragmentSpread?.package, "rows@1");
|
|
assert.equal(result.resources.length, 3);
|
|
const checked = new Map(result.resources.map((node) => [node.key, node.resource]));
|
|
let generated = 0;
|
|
const reused = await compileCapabilityResourceRepository({
|
|
...options,
|
|
checkedResource: async (kind, source) => {
|
|
if (source.repository === options.source.repository) return undefined;
|
|
const resource = checked.get(`${kind}\0${source.repository}\0${source.commit}`);
|
|
return resource?.kind === "build" ? undefined : resource;
|
|
},
|
|
generateQueries: async () => {
|
|
generated++;
|
|
return { queries: [], documents: new Map() };
|
|
},
|
|
});
|
|
assert.deepEqual(reused, result, "cached imported fragments and full checking produce identical contracts");
|
|
assert.equal(generated, 1, "only the uncached package checks its queries");
|
|
await writeFile(path.join(dirs.screen!, "screen.graphql"), "query Screen {root {unknownField}}");
|
|
await assert.rejects(
|
|
compileCapabilityResourceRepository({
|
|
...options,
|
|
source: { ...options.source, commit: "5".repeat(40) },
|
|
checkedResource: async (kind, source) => {
|
|
const resource = checked.get(`${kind}\0${source.repository}\0${source.commit}`);
|
|
return resource?.kind === "build" ? undefined : resource;
|
|
},
|
|
}),
|
|
/unknownField/,
|
|
);
|
|
});
|