feat: replace revision counters with domain state contracts

Use content digests, key fingerprints, binding and trust identities, immutable mutation receipts, and observation tokens instead of state-update ordinals across API, storage, Runtime, and Web contracts.

Preserve historical replay and secret material through frozen migrations; preflight uncertain removals before cutover, resume provisioning receipts, validate encrypted migration candidates, and align fresh/upgraded schemas. Include reviewed regression fixes, generated artifacts, and validation evidence.
This commit is contained in:
2026-10-10 15:55:20 +09:00
parent 72ce817de4
commit c78f7f7d80
358 changed files with 25965 additions and 12069 deletions
+9 -12
View File
@@ -10,7 +10,7 @@ import {
commitConfigTree,
ConfigSourceApiError,
fetchConfigEntry,
fetchConfigRevision,
fetchConfigHistory,
fetchConfigTree,
parseWorkspaceConfigTreeResponse,
} from "../../src/lib/workspace/config-source/api.ts";
@@ -29,7 +29,6 @@ const entry = {
content_digest: "sha256:entry",
};
const snapshot = {
revision: 7,
digest: "sha256:tree",
entries: { "profiles/main.dcdl": entry },
};
@@ -57,15 +56,14 @@ Deno.test("config source API commits directly through the workspace scope", asyn
const url = String(input);
calls.push({ url, init });
if (url.includes("/entries/")) return Promise.resolve(response(entry));
if (url.includes("/revisions/")) return Promise.resolve(response(snapshot));
if (url.includes("/history/")) return Promise.resolve(response(snapshot));
return Promise.resolve(response(tree));
}) as typeof fetch;
await fetchConfigTree("w/one", fetcher);
await fetchConfigRevision("w/one", 7, fetcher);
await fetchConfigHistory("w/one", "sha256:tree", fetcher);
await fetchConfigEntry("w/one", "profiles/main.dcdl", fetcher);
await commitConfigTree("w/one", {
base_revision: 4,
base_digest: "sha256:base",
changes: [],
entrypoints: [],
@@ -73,7 +71,7 @@ Deno.test("config source API commits directly through the workspace scope", asyn
assertEquals<unknown>(calls.map((call) => call.url), [
"/api/w/w%2Fone/config/source-tree",
"/api/w/w%2Fone/config/source-tree/revisions/7",
"/api/w/w%2Fone/config/source-tree/history/sha256%3Atree",
"/api/w/w%2Fone/config/source-tree/entries/profiles%2Fmain.dcdl",
"/api/w/w%2Fone/config/source-tree/commit",
]);
@@ -81,6 +79,9 @@ Deno.test("config source API commits directly through the workspace scope", asyn
assert(
String(calls[3].init?.body).includes('"base_digest":"sha256:base"'),
);
assertEquals(JSON.parse(String(calls[3].init?.body)), {
base_digest: "sha256:base", changes: [], entrypoints: [],
});
});
function withSchema(source: unknown, contributionSource: unknown = "builtin") {
@@ -113,7 +114,6 @@ for (const field of ["bundle", "contribution"] as const) {
assertEquals<unknown>(await fetchConfigTree("w", fetcher), body);
assertEquals<unknown>(
await commitConfigTree("w", {
base_revision: 7,
base_digest: snapshot.digest,
changes: [],
entrypoints: ["main.dcdl"],
@@ -197,12 +197,12 @@ Deno.test("config source API rejects mismatched entry map paths", async () => {
);
});
Deno.test("config source API rejects unsafe revisions and oversized entry content", () => {
Deno.test("config source API rejects removed snapshot revision fields and oversized entry content", () => {
assertThrows(
() =>
parseWorkspaceConfigTreeResponse({
...tree,
snapshot: { ...snapshot, revision: Number.MAX_SAFE_INTEGER + 1 },
snapshot: { ...snapshot, revision: 7 },
}),
ConfigSourceApiError,
"invalid response",
@@ -251,7 +251,6 @@ Deno.test("config source API does not materialize imported builtins in the works
Deno.test("config source API preserves unknown read-only builtin diagnostics without fallback requests", async () => {
const diagnostic = {
path: "main.dcdl",
revision: 7,
tree_digest: "sha256:tree",
kind: "import",
span: { start_byte: 8, end_byte: 40 },
@@ -270,7 +269,6 @@ Deno.test("config source API preserves unknown read-only builtin diagnostics wit
const error = await assertRejects(
() =>
commitConfigTree("w", {
base_revision: 7,
base_digest: "sha256:tree",
changes: [],
entrypoints: ["main.dcdl"],
@@ -290,7 +288,6 @@ Deno.test("config source API surfaces bounded failed evaluation details", async
let message = "";
try {
await commitConfigTree("w", {
base_revision: 1,
base_digest: "sha256:base",
changes: [],
entrypoints: [],
@@ -156,7 +156,7 @@ Deno.test("commit formats every working Decodal source without a preview roundtr
assert(
source.includes("await formatWorkingSources();") &&
source.includes("entrypoints: entrypoints()") &&
source.includes("Committed formatted revision"),
source.includes("Committed formatted source tree"),
"commit should format first and send the working changes directly to Backend authority",
);
assert(
@@ -167,7 +167,7 @@ Deno.test("commit formats every working Decodal source without a preview roundtr
);
});
Deno.test("config diagnostics analyze continuously with debounce and generation fencing", async () => {
Deno.test("config diagnostics analyze continuously with debounce and request cancellation", async () => {
const source = await Deno.readTextFile(
new URL(
"../../src/lib/workspace/config-source/ConfigSourceEditor.svelte",
@@ -179,7 +179,7 @@ Deno.test("config diagnostics analyze continuously with debounce and generation
source.includes("setTimeout(() =>") &&
source.includes("}, 250)") &&
source.includes("analyzer.analyze(path, value)") &&
source.includes("generation === analysisGeneration") &&
source.includes("!request.signal.aborted") &&
source.includes("analysisReady"),
"source changes should trigger only the latest debounced analysis after snapshot initialization",
);
@@ -16,7 +16,6 @@ function assert(condition: unknown, message: string): asserts condition {
Deno.test("toolchain converts reactive-like proxies to plain Worker messages", async () => {
const snapshot = new Proxy(
{
revision: 1,
digest: "sha256:test",
entries: {},
},
@@ -1,8 +1,11 @@
/// <reference lib="deno.ns" />
import { assertEquals } from "jsr:@std/assert";
import { createHash } from "node:crypto";
import { assertEquals, assertThrows } from "jsr:@std/assert";
import init, {
analyze_snapshot,
apply_changes,
changes_between,
complete_current,
compose_schema_bundle,
evaluate_snapshot,
@@ -32,6 +35,23 @@ async function digestText(text: string): Promise<string> {
}`;
}
function fixtureSnapshot(tree: Pick<ConfigTreeSnapshot, "entries">): ConfigTreeSnapshot {
const hash = createHash("sha256").update("yoi-config-tree-v1\0");
const entries: ConfigTreeSnapshot["entries"] = {};
for (const path of Object.keys(tree.entries).toSorted()) {
const entry = tree.entries[path];
entries[path] = {
...entry,
content_digest: "sha256:" + createHash("sha256").update(entry.content).digest("hex"),
};
hash.update(path).update("\0")
.update(entry.content_type === "decodal" ? "text/x-decodal" : "text/plain")
.update("\0").update(entry.content).update("\0");
}
return { digest: "sha256:" + hash.digest("hex"), entries };
}
async function toolchainFingerprint(
entrypoints: string[],
schemaBundle: WorkspaceConfigSchemaBundle,
@@ -47,7 +67,6 @@ async function toolchainFingerprint(
}
const snapshot: ConfigTreeSnapshot = {
revision: 4,
digest: "sha256:test-tree",
entries: {
"workspace.dcdl": {
@@ -88,15 +107,40 @@ const mainEntrypointContract: ToolchainContract = {
};
Deno.test("generated WASM evaluates the same virtual import contract", () => {
const result = evaluate_snapshot(snapshot, contract) as {
const result = evaluate_snapshot(fixtureSnapshot(snapshot), contract) as {
projections: Array<{ data_json: { answer: number } }>;
};
assertEquals(result.projections[0].data_json, { answer: 42 });
});
Deno.test("generated WASM keeps literal paths matching old cache identities as relative import bases", async () => {
const source = "{}";
const literalPath = `a.dcdl@text/x-decodal@${await digestText(source)}`;
// Match the native fixture: even an unreferenced source must resolve its
// relative import from the literal path rather than another entry's cache ID.
const entries: ConfigTreeSnapshot["entries"] = {};
for (const [path, content] of [
["main.dcdl", "{}"],
["a.dcdl", source],
[literalPath, 'import "./shared.dcdl"'],
["a.dcdl@text/shared.dcdl", "{ answer = 42; }"],
]) {
entries[path] = {
path,
content_type: "decodal",
content,
content_digest: await digestText(content),
};
}
const result = evaluate_snapshot(
fixtureSnapshot({ entries }),
mainEntrypointContract,
) as { projections: Array<{ data_json: unknown }> };
assertEquals(result.projections[0].data_json, {});
});
Deno.test("generated WASM accepts the mandatory main schema assertion", () => {
const assertedSnapshot: ConfigTreeSnapshot = {
revision: 1,
digest: "sha256:asserted-main",
entries: {
"main.dcdl": {
@@ -107,8 +151,7 @@ Deno.test("generated WASM accepts the mandatory main schema assertion", () => {
},
},
};
const result = evaluate_snapshot(
assertedSnapshot,
const result = evaluate_snapshot(fixtureSnapshot(assertedSnapshot),
mainEntrypointContract,
) as { projections: Array<{ data_json: { answer: number } }> };
@@ -116,19 +159,17 @@ Deno.test("generated WASM accepts the mandatory main schema assertion", () => {
});
Deno.test("generated WASM diagnostics carry snapshot provenance", () => {
const diagnostics = analyze_snapshot(
snapshot,
const diagnostics = analyze_snapshot(fixtureSnapshot(snapshot),
"workspace.dcdl",
"{ broken = ; }",
) as Array<{
path: string;
revision: number;
tree_digest: string;
kind: string;
}>;
assertEquals(diagnostics[0].path, "workspace.dcdl");
assertEquals(diagnostics[0].revision, 4);
assertEquals(diagnostics[0].tree_digest, "sha256:test-tree");
assertEquals(diagnostics[0].tree_digest, fixtureSnapshot(snapshot).digest);
assertEquals("revision" in diagnostics[0], false);
assertEquals(diagnostics[0].kind, "syntax");
});
@@ -153,7 +194,6 @@ const schemaBundle = compose_schema_bundle([
function schemaSnapshot(source: string): ConfigTreeSnapshot {
return {
revision: 7,
digest: "sha256:schema-tree",
entries: {
"main.dcdl": {
@@ -177,7 +217,6 @@ const schemaContract: ToolchainContract = {
};
const markdownSnapshot: ConfigTreeSnapshot = {
revision: 8,
digest: "sha256:markdown-tree",
entries: {
"main.dcdl": {
@@ -203,7 +242,7 @@ const markdownContract: ToolchainContract = {
};
Deno.test("generated WASM evaluates Markdown with the shared Skill projection", () => {
const result = evaluate_snapshot(markdownSnapshot, markdownContract) as {
const result = evaluate_snapshot(fixtureSnapshot(markdownSnapshot), markdownContract) as {
projections: Array<{ data_json: Record<string, unknown> }>;
};
assertEquals(result.projections[0].data_json, {
@@ -219,10 +258,9 @@ Deno.test("generated WASM evaluates Markdown with the shared Skill projection",
});
Deno.test("generated WASM applies Decodal 0.4 typed maps and explicit object rest", () => {
const result = evaluate_snapshot(
schemaSnapshot(
const result = evaluate_snapshot(fixtureSnapshot(schemaSnapshot(
"{ features = { console = { enabled = true; }; }; web = { enabled = true; extension_value = 42; }; }",
),
)),
schemaContract,
) as { projections: Array<{ data_json: Record<string, unknown> }> };
assertEquals(result.projections[0].data_json, {
@@ -240,7 +278,7 @@ type ProjectedDiagnostic = {
function evaluateFailure(source: string): ProjectedDiagnostic {
try {
evaluate_snapshot(schemaSnapshot(source), schemaContract);
evaluate_snapshot(fixtureSnapshot(schemaSnapshot(source)), schemaContract);
} catch (error) {
const diagnostics = error as ProjectedDiagnostic[];
assertEquals(Array.isArray(diagnostics), true);
@@ -274,7 +312,7 @@ Deno.test("generated WASM preserves native Decodal 0.4 diagnostic semantics", ()
Deno.test("generated WASM returns completion items for the editor adapter", () => {
const source = 'import "./"';
set_snapshot({
set_snapshot(fixtureSnapshot({
...snapshot,
entries: {
...snapshot.entries,
@@ -283,7 +321,7 @@ Deno.test("generated WASM returns completion items for the editor adapter", () =
content: source,
},
},
});
}));
const result = complete_current(
"workspace.dcdl",
source,
@@ -301,7 +339,7 @@ Deno.test("generated WASM returns completion items for the editor adapter", () =
Deno.test("generated WASM exposes read-only builtin completions without editable builtin entries", () => {
const tree = schemaSnapshot("{}");
set_snapshot(tree);
set_snapshot(fixtureSnapshot(tree));
set_schema_bundle(emptySchemaBundle);
const source = 'let 名 = 1; import "$builtin/profiles/comp"';
const result = complete_current(
@@ -320,8 +358,7 @@ Deno.test("generated WASM exposes read-only builtin completions without editable
assertEquals(companion?.kind, "file");
assertEquals(companion?.detail, "read-only builtin Decodal source");
assertEquals(Object.keys(tree.entries), ["main.dcdl"]);
const evaluated = evaluate_snapshot(
schemaSnapshot('import "$builtin/profiles/companion.dcdl"'),
const evaluated = evaluate_snapshot(fixtureSnapshot(schemaSnapshot('import "$builtin/profiles/companion.dcdl"')),
mainEntrypointContract,
) as {
projections: Array<{ data_json: { slug: string } }>;
@@ -338,16 +375,14 @@ Deno.test("generated WASM rejects unknown builtin imports without same-suffix wo
content_digest: "sha256:workspace-fallback",
};
set_schema_bundle(emptySchemaBundle);
const diagnostics = analyze_snapshot(tree, "main.dcdl", undefined) as Array<{
const diagnostics = analyze_snapshot(fixtureSnapshot(tree), "main.dcdl", undefined) as Array<{
path: string;
revision: number;
tree_digest: string;
message: string;
}>;
assertEquals(diagnostics.length > 0, true);
assertEquals(diagnostics[0].path, "main.dcdl");
assertEquals(diagnostics[0].revision, tree.revision);
assertEquals(diagnostics[0].tree_digest, tree.digest);
assertEquals(diagnostics[0].tree_digest, fixtureSnapshot(tree).digest);
assertEquals(
diagnostics[0].message.includes(
"unknown or non-public read-only builtin source",
@@ -360,7 +395,7 @@ Deno.test("generated WASM rejects unknown builtin imports without same-suffix wo
);
let failed = false;
try {
evaluate_snapshot(tree, mainEntrypointContract);
evaluate_snapshot(fixtureSnapshot(tree), mainEntrypointContract);
} catch (error) {
failed = true;
assertEquals(
@@ -372,26 +407,24 @@ Deno.test("generated WASM rejects unknown builtin imports without same-suffix wo
}
assertEquals(failed, true);
assertEquals(
analyze_snapshot(tree, "main.dcdl", 'import "./profiles/missing.dcdl"'),
analyze_snapshot(fixtureSnapshot(tree), "main.dcdl", 'import "./profiles/missing.dcdl"'),
[],
);
});
function importFailure(tree: ConfigTreeSnapshot): ProjectedDiagnostic[] {
try {
evaluate_snapshot(tree, mainEntrypointContract);
evaluate_snapshot(fixtureSnapshot(tree), mainEntrypointContract);
} catch (error) {
// A WASM trap/stack overflow must not count as a structured import failure.
assertEquals(Array.isArray(error), true);
const diagnostics = error as Array<
ProjectedDiagnostic & {
revision: number;
tree_digest: string;
}
>;
assertEquals(diagnostics.length > 0, true);
assertEquals(diagnostics[0].revision, tree.revision);
assertEquals(diagnostics[0].tree_digest, tree.digest);
assertEquals(diagnostics[0].tree_digest, fixtureSnapshot(tree).digest);
return diagnostics;
}
throw new Error("expected a structured import diagnostic");
@@ -427,7 +460,7 @@ Deno.test("generated WASM enforces the import depth budget on a real 33-deep cha
return tree;
}
// The synthetic evaluation-wrapper import consumes one of the 32 edges.
const accepted = evaluate_snapshot(chain(31), mainEntrypointContract) as {
const accepted = evaluate_snapshot(fixtureSnapshot(chain(31)), mainEntrypointContract) as {
projections: Array<{ data_json: { answer: number } }>;
};
assertEquals(accepted.projections[0].data_json, { answer: 42 });
@@ -447,7 +480,7 @@ Deno.test("generated WASM completes blank nested schema positions after Unicode"
const source =
'{ description = "日本語"; profile = { }\n} as WorkspaceConfigSchema';
const cursor = source.indexOf("{ }") + 2;
set_snapshot({
set_snapshot(fixtureSnapshot({
...snapshot,
entries: {
...snapshot.entries,
@@ -456,7 +489,7 @@ Deno.test("generated WASM completes blank nested schema positions after Unicode"
content: source,
},
},
});
}));
set_schema_bundle({
contributions: [],
source: "{ profile = { default_profile = String; }; prompts = {}; }",
@@ -486,7 +519,7 @@ Deno.test("generated WASM completes asserted WorkspaceConfigSchema keys", () =>
const bareSource = "{ pro }";
const source = "{ pro } as WorkspaceConfigSchema";
const cursor = source.indexOf("pro") + 3;
set_snapshot({
set_snapshot(fixtureSnapshot({
...snapshot,
entries: {
...snapshot.entries,
@@ -495,7 +528,7 @@ Deno.test("generated WASM completes asserted WorkspaceConfigSchema keys", () =>
content: source,
},
},
});
}));
set_schema_bundle({
contributions: [],
source: "{ profile = { default_profile = String; }; prompts = {}; }",
@@ -566,7 +599,6 @@ Deno.test("generated WASM authors value-based Profiles using the Backend schema
const content =
'{ profile = { entries = [{ selector = "project:alpha"; profile = {}; }]; }; } as WorkspaceConfigSchema';
const tree: ConfigTreeSnapshot = {
revision: 8,
digest: "sha256:value-profile-tree",
entries: {
"main.dcdl": {
@@ -583,9 +615,9 @@ Deno.test("generated WASM authors value-based Profiles using the Backend schema
schema_bundle: schema,
fingerprint: await toolchainFingerprint(["main.dcdl"], schema),
};
set_snapshot(tree);
set_snapshot(fixtureSnapshot(tree));
set_schema_bundle(schema);
const evaluated = evaluate_snapshot(tree, valueContract) as {
const evaluated = evaluate_snapshot(fixtureSnapshot(tree), valueContract) as {
projections: Array<
{ data_json: { profile: { entries: Array<{ profile: unknown }> } } }
>;
@@ -648,13 +680,13 @@ Deno.test("generated WASM authors value-based Profiles using the Backend schema
`profile = ${value};`,
);
assertEquals(
analyze_snapshot(tree, "main.dcdl", partialContent),
analyze_snapshot(fixtureSnapshot(tree), "main.dcdl", partialContent),
[],
value,
);
}
const recipe = "{ worker = { mode = 42; }; }";
const analysisTree = {
const analysisTree: ConfigTreeSnapshot = {
...tree,
entries: {
...tree.entries,
@@ -685,13 +717,12 @@ Deno.test("generated WASM authors value-based Profiles using the Backend schema
"profile = {};",
`profile = ${value};`,
);
const diagnostics = analyze_snapshot(
analysisTree,
const diagnostics = analyze_snapshot(fixtureSnapshot(analysisTree),
"main.dcdl",
invalidContent,
) as Array<{
path: string;
revision: number;
tree_digest: string;
kind: string;
span: { start_byte: number; end_byte: number };
message: string;
@@ -702,7 +733,7 @@ Deno.test("generated WASM authors value-based Profiles using the Backend schema
assertEquals(diagnostics.length > 0, true, value);
const diagnostic = diagnostics[0];
assertEquals(diagnostic.path, expectedPath);
assertEquals(diagnostic.revision, tree.revision);
assertEquals(diagnostic.tree_digest, fixtureSnapshot(analysisTree).digest);
assertEquals(
["constraint_violation", "type_mismatch"].includes(diagnostic.kind),
true,
@@ -783,7 +814,7 @@ Deno.test("generated WASM authors value-based Profiles using the Backend schema
"profile = {};",
`profile = ${form};`,
);
const scopedTree = {
const scopedTree: ConfigTreeSnapshot = {
...tree,
entries: {
"main.dcdl": {
@@ -800,12 +831,11 @@ Deno.test("generated WASM authors value-based Profiles using the Backend schema
},
};
assertEquals(
analyze_snapshot(scopedTree, "main.dcdl", undefined),
analyze_snapshot(fixtureSnapshot(scopedTree), "main.dcdl", undefined),
[],
form,
);
const result = evaluate_snapshot(
scopedTree,
const result = evaluate_snapshot(fixtureSnapshot(scopedTree),
valueContract,
) as typeof evaluated;
assertEquals(
@@ -839,7 +869,7 @@ Deno.test("generated WASM authors value-based Profiles using the Backend schema
"profile = {};",
`profile = ${form};`,
);
const fixtureTree = {
const fixtureTree: ConfigTreeSnapshot = {
...tree,
entries: {
"main.dcdl": {
@@ -856,12 +886,11 @@ Deno.test("generated WASM authors value-based Profiles using the Backend schema
},
};
assertEquals(
analyze_snapshot(fixtureTree, "main.dcdl", undefined),
analyze_snapshot(fixtureSnapshot(fixtureTree), "main.dcdl", undefined),
[],
`${fixture.name}: ${form}`,
);
const result = evaluate_snapshot(
fixtureTree,
const result = evaluate_snapshot(fixtureSnapshot(fixtureTree),
valueContract,
) as typeof evaluated;
assertEquals(
@@ -896,5 +925,65 @@ Deno.test("generated WASM authors value-based Profiles using the Backend schema
);
}
// Neither completion nor diagnostic shape checking changes the saved value.
assertEquals(evaluate_snapshot(tree, valueContract), evaluated);
assertEquals(evaluate_snapshot(fixtureSnapshot(tree), valueContract), evaluated);
});
Deno.test("generated WASM returns to the same content digest and enforces entry digest CAS", () => {
const base = fixtureSnapshot(schemaSnapshot("{ answer = 1; }"));
set_schema_bundle(emptySchemaBundle);
set_snapshot(base);
const changed = apply_changes([{
kind: "update", path: "main.dcdl",
expected_digest: base.entries["main.dcdl"].content_digest,
content: "{ broken = ; }",
}]) as ConfigTreeSnapshot;
assertEquals(changed.digest === base.digest, false);
assertEquals("revision" in changed, false);
const diagnostics = analyze_snapshot(changed, "main.dcdl", undefined) as Array<{ tree_digest: string }>;
assertEquals(diagnostics.length > 0, true);
assertEquals(diagnostics.every((diagnostic) => diagnostic.tree_digest === changed.digest), true);
assertThrows(() => apply_changes([{
kind: "update", path: "main.dcdl",
expected_digest: base.entries["main.dcdl"].content_digest,
content: "{ answer = 2; }",
}]));
const restored = apply_changes(changes_between(changed, base)) as ConfigTreeSnapshot;
assertEquals(restored, base);
assertEquals(analyze_snapshot(restored, "main.dcdl", undefined), []);
});
Deno.test("generated WASM rejects cache URI paths in snapshot JSON despite valid content digests", async () => {
const source = "{}";
const cacheUri = `config-source://a.dcdl@text/x-decodal@${await digestText(source)}`;
// Both entry and tree digests are correct, so rejection must come from the
// untrusted VirtualPath boundary rather than a content-identity mismatch.
const snapshot = fixtureSnapshot({
entries: {
"a.dcdl": {
path: "a.dcdl",
content_type: "decodal",
content: source,
content_digest: await digestText(source),
},
[cacheUri]: {
path: cacheUri,
content_type: "decodal",
content: 'import "./shared.dcdl"',
content_digest: await digestText('import "./shared.dcdl"'),
},
},
});
const json = JSON.stringify(snapshot);
const rejection = assertThrows(() => set_snapshot(JSON.parse(json)));
assertEquals(String(rejection).includes("config-source://"), true);
});
Deno.test("generated WASM rejects forged content identity at the snapshot boundary", () => {
const base = fixtureSnapshot(schemaSnapshot("{}"));
for (const forged of [
{ ...base, digest: "sha256:forged" },
{ ...base, entries: { "main.dcdl": { ...base.entries["main.dcdl"], content: "{ changed = true; }" } } },
]) {
assertThrows(() => set_snapshot(forged));
}
});