@world-engines/tmw 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +46 -0
- package/dist/activation.d.ts +50 -0
- package/dist/activation.js +113 -0
- package/dist/audio-presentation-projection.d.ts +23 -0
- package/dist/audio-presentation-projection.js +39 -0
- package/dist/author-scenario-source-v3.d.ts +34 -0
- package/dist/author-scenario-source-v3.js +1 -0
- package/dist/authoring-runtime.d.ts +76 -0
- package/dist/authoring-runtime.js +282 -0
- package/dist/builder-diagnostics.d.ts +3 -0
- package/dist/builder-diagnostics.js +8 -0
- package/dist/builder-node.d.ts +178 -0
- package/dist/builder-node.js +212 -0
- package/dist/builder.d.ts +32 -0
- package/dist/builder.js +127 -0
- package/dist/capability-registry.d.ts +32 -0
- package/dist/capability-registry.js +33 -0
- package/dist/compile-target-profile.d.ts +16 -0
- package/dist/compile-target-profile.js +70 -0
- package/dist/compiled-plan.d.ts +44 -0
- package/dist/compiled-plan.js +1 -0
- package/dist/compiler-compatibility-gate.d.ts +96 -0
- package/dist/compiler-compatibility-gate.js +609 -0
- package/dist/compiler-release-authority.d.ts +212 -0
- package/dist/compiler-release-authority.js +676 -0
- package/dist/compiler-stage-cache.d.ts +42 -0
- package/dist/compiler-stage-cache.js +100 -0
- package/dist/compiler-stage-registry.d.ts +48 -0
- package/dist/compiler-stage-registry.js +126 -0
- package/dist/compiler.d.ts +7 -0
- package/dist/compiler.js +68 -0
- package/dist/condition-graph.d.ts +46 -0
- package/dist/condition-graph.js +135 -0
- package/dist/diagnostics.d.ts +20 -0
- package/dist/diagnostics.js +20 -0
- package/dist/durable-intent.d.ts +29 -0
- package/dist/durable-intent.js +60 -0
- package/dist/effect-flow.d.ts +69 -0
- package/dist/effect-flow.js +98 -0
- package/dist/event-fabric.d.ts +81 -0
- package/dist/event-fabric.js +227 -0
- package/dist/event-lifecycle.d.ts +59 -0
- package/dist/event-lifecycle.js +161 -0
- package/dist/evidence.d.ts +37 -0
- package/dist/evidence.js +92 -0
- package/dist/gameplay-state.d.ts +127 -0
- package/dist/gameplay-state.js +214 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +52 -0
- package/dist/isolated-replay.d.ts +81 -0
- package/dist/isolated-replay.js +316 -0
- package/dist/music-candidate-set.d.ts +38 -0
- package/dist/music-candidate-set.js +102 -0
- package/dist/natural-language-chunking.d.ts +10 -0
- package/dist/natural-language-chunking.js +62 -0
- package/dist/natural-language-ingestion.d.ts +14 -0
- package/dist/natural-language-ingestion.js +128 -0
- package/dist/natural-language-structured-decode.d.ts +2 -0
- package/dist/natural-language-structured-decode.js +69 -0
- package/dist/natural-language-world-types.d.ts +142 -0
- package/dist/natural-language-world-types.js +2 -0
- package/dist/neutral-source-compiler.d.ts +135 -0
- package/dist/neutral-source-compiler.js +608 -0
- package/dist/presentation-intent.d.ts +42 -0
- package/dist/presentation-intent.js +137 -0
- package/dist/recall-query-envelope.d.ts +32 -0
- package/dist/recall-query-envelope.js +51 -0
- package/dist/rewrite-compensation.d.ts +28 -0
- package/dist/rewrite-compensation.js +85 -0
- package/dist/runtime-contract.d.ts +56 -0
- package/dist/runtime-contract.js +96 -0
- package/dist/runtime-domain-capabilities.d.ts +12 -0
- package/dist/runtime-domain-capabilities.js +20 -0
- package/dist/runtime-sav.d.ts +117 -0
- package/dist/runtime-sav.js +356 -0
- package/dist/runtime-trace.d.ts +44 -0
- package/dist/runtime-trace.js +119 -0
- package/dist/runtime.d.ts +238 -0
- package/dist/runtime.js +1887 -0
- package/dist/scene-author-source.d.ts +13 -0
- package/dist/scene-author-source.js +25 -0
- package/dist/scene-state.d.ts +275 -0
- package/dist/scene-state.js +334 -0
- package/dist/scheduler.d.ts +55 -0
- package/dist/scheduler.js +235 -0
- package/dist/selector-ast.d.ts +24 -0
- package/dist/selector-ast.js +18 -0
- package/dist/semantic-verdict.d.ts +48 -0
- package/dist/semantic-verdict.js +101 -0
- package/dist/simulator.d.ts +45 -0
- package/dist/simulator.js +58 -0
- package/dist/source-canonical.d.ts +4 -0
- package/dist/source-canonical.js +51 -0
- package/dist/source-crypto.d.ts +20 -0
- package/dist/source-crypto.js +17 -0
- package/dist/source-revision.d.ts +22 -0
- package/dist/source-revision.js +43 -0
- package/dist/spatial-impact-receipt.d.ts +38 -0
- package/dist/spatial-impact-receipt.js +67 -0
- package/dist/temporal-rewrite.d.ts +59 -0
- package/dist/temporal-rewrite.js +214 -0
- package/dist/time-domains.d.ts +37 -0
- package/dist/time-domains.js +142 -0
- package/dist/timeline-revision.d.ts +28 -0
- package/dist/timeline-revision.js +59 -0
- package/dist/trigger-document-v3.d.ts +99 -0
- package/dist/trigger-document-v3.js +334 -0
- package/dist/turn-commit.d.ts +56 -0
- package/dist/turn-commit.js +190 -0
- package/dist/validator.d.ts +7 -0
- package/dist/validator.js +142 -0
- package/dist/value-graph.d.ts +98 -0
- package/dist/value-graph.js +318 -0
- package/dist/view-event-delivery.d.ts +47 -0
- package/dist/view-event-delivery.js +197 -0
- package/dist/view-interaction-manifest-v3.d.ts +60 -0
- package/dist/view-interaction-manifest-v3.js +198 -0
- package/dist/view-payload-schema.d.ts +17 -0
- package/dist/view-payload-schema.js +84 -0
- package/package.json +62 -0
|
@@ -0,0 +1,609 @@
|
|
|
1
|
+
import { compileTargetProfileDigest, parseCompileTargetProfile, } from "./compile-target-profile.js";
|
|
2
|
+
import { captureNeutralSourceCompileInput, decodeNeutralScenarioSource, sha256Bytes, sha256Hex, } from "@world-engines/scenario-author-source";
|
|
3
|
+
import { compileNeutralScenarioSource, } from "./neutral-source-compiler.js";
|
|
4
|
+
import { tmwSha256Hex } from "./runtime-contract.js";
|
|
5
|
+
export const ACCEPTED_NEUTRAL_SOURCE_CORPUS_SCHEMA_VERSION = 1;
|
|
6
|
+
const IDENTIFIER_PATTERN = /^[a-z0-9][a-z0-9._-]{0,127}$/u;
|
|
7
|
+
const SHA256_PATTERN = /^[0-9a-f]{64}$/u;
|
|
8
|
+
const SECTION_KEY_PATTERN = /^[a-z][a-z0-9_.-]{0,127}$/u;
|
|
9
|
+
const DECIMAL_UINT_PATTERN = /^(?:0|[1-9][0-9]*)$/u;
|
|
10
|
+
function decodeBase64Bytes(value) {
|
|
11
|
+
let binary;
|
|
12
|
+
try {
|
|
13
|
+
binary = globalThis.atob(value);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw new Error("accepted_fixture_base64_invalid");
|
|
17
|
+
}
|
|
18
|
+
return Uint8Array.from(binary, (character) => character.charCodeAt(0));
|
|
19
|
+
}
|
|
20
|
+
function compareAscii(left, right) {
|
|
21
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
22
|
+
}
|
|
23
|
+
function requireIdentifier(value, code) {
|
|
24
|
+
if (typeof value !== "string" || !IDENTIFIER_PATTERN.test(value))
|
|
25
|
+
throw new Error(code);
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
function requireText(value, code) {
|
|
29
|
+
if (typeof value !== "string"
|
|
30
|
+
|| value.length === 0
|
|
31
|
+
|| value !== value.trim().normalize("NFC"))
|
|
32
|
+
throw new Error(code);
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
function requireSha256(value, code) {
|
|
36
|
+
if (typeof value !== "string" || !SHA256_PATTERN.test(value))
|
|
37
|
+
throw new Error(code);
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
function requireRelativePath(value, code) {
|
|
41
|
+
const path = requireText(value, code);
|
|
42
|
+
if (path.startsWith("/")
|
|
43
|
+
|| path.includes("\\")
|
|
44
|
+
|| path.split("/").some((part) => part.length === 0 || part === "." || part === ".."))
|
|
45
|
+
throw new Error(code);
|
|
46
|
+
return path;
|
|
47
|
+
}
|
|
48
|
+
function requireSectionKey(value, code) {
|
|
49
|
+
if (typeof value !== "string"
|
|
50
|
+
|| !SECTION_KEY_PATTERN.test(value)
|
|
51
|
+
|| value !== value.normalize("NFC"))
|
|
52
|
+
throw new Error(code);
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
function requireByteLength(value, code) {
|
|
56
|
+
if (typeof value !== "string" || !DECIMAL_UINT_PATTERN.test(value))
|
|
57
|
+
throw new Error(code);
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
function parseSectionDigests(value, index) {
|
|
61
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
62
|
+
throw new Error(`accepted_fixture_section_digests_required:${index}`);
|
|
63
|
+
}
|
|
64
|
+
const digests = value.map((item, digestIndex) => {
|
|
65
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
66
|
+
throw new Error(`accepted_fixture_section_digest_invalid:${index}:${digestIndex}`);
|
|
67
|
+
}
|
|
68
|
+
const digest = item;
|
|
69
|
+
const keys = Object.keys(digest).sort();
|
|
70
|
+
const expected = ["byte_length", "section_key", "sha256"];
|
|
71
|
+
if (keys.length !== expected.length
|
|
72
|
+
|| keys.some((key, keyIndex) => key !== expected[keyIndex]))
|
|
73
|
+
throw new Error(`accepted_fixture_section_digest_fields_mismatch:${index}:${digestIndex}`);
|
|
74
|
+
return Object.freeze({
|
|
75
|
+
section_key: requireSectionKey(digest.section_key, `accepted_fixture_section_key_invalid:${index}:${digestIndex}`),
|
|
76
|
+
sha256: requireSha256(digest.sha256, `accepted_fixture_section_digest_hash_invalid:${index}:${digestIndex}`),
|
|
77
|
+
byte_length: requireByteLength(digest.byte_length, `accepted_fixture_section_byte_length_invalid:${index}:${digestIndex}`),
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
for (let digestIndex = 1; digestIndex < digests.length; digestIndex += 1) {
|
|
81
|
+
const previous = digests[digestIndex - 1];
|
|
82
|
+
const current = digests[digestIndex];
|
|
83
|
+
if (previous === undefined || current === undefined) {
|
|
84
|
+
throw new Error(`accepted_fixture_section_digest_invalid:${index}`);
|
|
85
|
+
}
|
|
86
|
+
if (compareAscii(previous.section_key, current.section_key) !== -1) {
|
|
87
|
+
throw new Error(`accepted_fixture_section_digests_unsorted:${index}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (new Set(digests.map((digest) => digest.section_key)).size !== digests.length) {
|
|
91
|
+
throw new Error(`accepted_fixture_section_digest_duplicate:${index}`);
|
|
92
|
+
}
|
|
93
|
+
return Object.freeze(digests);
|
|
94
|
+
}
|
|
95
|
+
function parseByteRangeWitnesses(value, index) {
|
|
96
|
+
if (!Array.isArray(value)) {
|
|
97
|
+
throw new Error(`accepted_fixture_byte_range_witnesses_required:${index}`);
|
|
98
|
+
}
|
|
99
|
+
const witnesses = value.map((item, witnessIndex) => {
|
|
100
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
101
|
+
throw new Error(`accepted_fixture_byte_range_witness_invalid:${index}:${witnessIndex}`);
|
|
102
|
+
}
|
|
103
|
+
const witness = item;
|
|
104
|
+
const keys = Object.keys(witness).sort();
|
|
105
|
+
const expected = ["end", "kind", "path", "sha256", "start"];
|
|
106
|
+
if (keys.length !== expected.length
|
|
107
|
+
|| keys.some((key, keyIndex) => key !== expected[keyIndex]))
|
|
108
|
+
throw new Error(`accepted_fixture_byte_range_witness_fields_mismatch:${index}:${witnessIndex}`);
|
|
109
|
+
const start = requireByteLength(witness.start, `accepted_fixture_byte_range_start_invalid:${index}:${witnessIndex}`);
|
|
110
|
+
const end = requireByteLength(witness.end, `accepted_fixture_byte_range_end_invalid:${index}:${witnessIndex}`);
|
|
111
|
+
if (!(BigInt(start) < BigInt(end))) {
|
|
112
|
+
throw new Error(`accepted_fixture_byte_range_bounds_invalid:${index}:${witnessIndex}`);
|
|
113
|
+
}
|
|
114
|
+
return Object.freeze({
|
|
115
|
+
kind: requireIdentifier(witness.kind, `accepted_fixture_byte_range_kind_invalid:${index}:${witnessIndex}`),
|
|
116
|
+
path: requireText(witness.path, `accepted_fixture_byte_range_path_invalid:${index}:${witnessIndex}`),
|
|
117
|
+
start,
|
|
118
|
+
end,
|
|
119
|
+
sha256: requireSha256(witness.sha256, `accepted_fixture_byte_range_hash_invalid:${index}:${witnessIndex}`),
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
for (let witnessIndex = 1; witnessIndex < witnesses.length; witnessIndex += 1) {
|
|
123
|
+
const previous = witnesses[witnessIndex - 1];
|
|
124
|
+
const current = witnesses[witnessIndex];
|
|
125
|
+
if (previous === undefined || current === undefined) {
|
|
126
|
+
throw new Error(`accepted_fixture_byte_range_witness_invalid:${index}`);
|
|
127
|
+
}
|
|
128
|
+
const startOrder = BigInt(previous.start) < BigInt(current.start)
|
|
129
|
+
? -1
|
|
130
|
+
: BigInt(previous.start) > BigInt(current.start) ? 1 : 0;
|
|
131
|
+
const pathOrder = compareAscii(previous.path, current.path);
|
|
132
|
+
if (startOrder === 1 || (startOrder === 0 && pathOrder !== -1)) {
|
|
133
|
+
throw new Error(`accepted_fixture_byte_range_witnesses_unsorted:${index}`);
|
|
134
|
+
}
|
|
135
|
+
if (BigInt(previous.end) > BigInt(current.start)) {
|
|
136
|
+
throw new Error(`accepted_fixture_byte_range_witness_overlap:${index}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (new Set(witnesses.map((witness) => `${witness.kind}:${witness.path}:${witness.start}:${witness.end}`)).size
|
|
140
|
+
!== witnesses.length)
|
|
141
|
+
throw new Error(`accepted_fixture_byte_range_witness_duplicate:${index}`);
|
|
142
|
+
return Object.freeze(witnesses);
|
|
143
|
+
}
|
|
144
|
+
function parseContentWitnesses(value, index) {
|
|
145
|
+
if (!Array.isArray(value)) {
|
|
146
|
+
throw new Error(`accepted_fixture_content_witnesses_required:${index}`);
|
|
147
|
+
}
|
|
148
|
+
const witnesses = value.map((item, witnessIndex) => {
|
|
149
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
150
|
+
throw new Error(`accepted_fixture_content_witness_invalid:${index}:${witnessIndex}`);
|
|
151
|
+
}
|
|
152
|
+
const witness = item;
|
|
153
|
+
const keys = Object.keys(witness).sort();
|
|
154
|
+
const expected = ["kind", "metrics", "section_key", "sha256"];
|
|
155
|
+
if (keys.length !== expected.length
|
|
156
|
+
|| keys.some((key, keyIndex) => key !== expected[keyIndex]))
|
|
157
|
+
throw new Error(`accepted_fixture_content_witness_fields_mismatch:${index}:${witnessIndex}`);
|
|
158
|
+
if (typeof witness.metrics !== "object"
|
|
159
|
+
|| witness.metrics === null
|
|
160
|
+
|| Array.isArray(witness.metrics))
|
|
161
|
+
throw new Error(`accepted_fixture_content_witness_metrics_invalid:${index}:${witnessIndex}`);
|
|
162
|
+
const metricsEntries = Object.entries(witness.metrics)
|
|
163
|
+
.sort(([left], [right]) => compareAscii(left, right))
|
|
164
|
+
.map(([key, metricValue], metricIndex) => {
|
|
165
|
+
if (!/^[a-z][a-z0-9_]{0,127}$/u.test(key)) {
|
|
166
|
+
throw new Error(`accepted_fixture_content_witness_metric_key_invalid:${index}:${witnessIndex}:${metricIndex}`);
|
|
167
|
+
}
|
|
168
|
+
if (typeof metricValue !== "string"
|
|
169
|
+
|| metricValue.length === 0
|
|
170
|
+
|| metricValue !== metricValue.trim().normalize("NFC"))
|
|
171
|
+
throw new Error(`accepted_fixture_content_witness_metric_value_invalid:${index}:${witnessIndex}:${key}`);
|
|
172
|
+
return [key, metricValue];
|
|
173
|
+
});
|
|
174
|
+
const metricKeys = metricsEntries.map(([key]) => key);
|
|
175
|
+
if (JSON.stringify(metricKeys) !== JSON.stringify([...metricKeys].sort(compareAscii))) {
|
|
176
|
+
throw new Error(`accepted_fixture_content_witness_metrics_unsorted:${index}:${witnessIndex}`);
|
|
177
|
+
}
|
|
178
|
+
if (new Set(metricKeys).size !== metricKeys.length) {
|
|
179
|
+
throw new Error(`accepted_fixture_content_witness_metric_duplicate:${index}:${witnessIndex}`);
|
|
180
|
+
}
|
|
181
|
+
return Object.freeze({
|
|
182
|
+
kind: requireIdentifier(witness.kind, `accepted_fixture_content_witness_kind_invalid:${index}:${witnessIndex}`),
|
|
183
|
+
section_key: requireSectionKey(witness.section_key, `accepted_fixture_content_witness_section_key_invalid:${index}:${witnessIndex}`),
|
|
184
|
+
sha256: requireSha256(witness.sha256, `accepted_fixture_content_witness_hash_invalid:${index}:${witnessIndex}`),
|
|
185
|
+
metrics: Object.freeze(Object.fromEntries(metricsEntries)),
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
for (let witnessIndex = 1; witnessIndex < witnesses.length; witnessIndex += 1) {
|
|
189
|
+
const previous = witnesses[witnessIndex - 1];
|
|
190
|
+
const current = witnesses[witnessIndex];
|
|
191
|
+
if (previous === undefined || current === undefined) {
|
|
192
|
+
throw new Error(`accepted_fixture_content_witness_invalid:${index}`);
|
|
193
|
+
}
|
|
194
|
+
const kindOrder = compareAscii(previous.kind, current.kind);
|
|
195
|
+
const sectionOrder = compareAscii(previous.section_key, current.section_key);
|
|
196
|
+
if (kindOrder === 1 || (kindOrder === 0 && sectionOrder !== -1)) {
|
|
197
|
+
throw new Error(`accepted_fixture_content_witnesses_unsorted:${index}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
if (new Set(witnesses.map((witness) => `${witness.kind}:${witness.section_key}`)).size
|
|
201
|
+
!== witnesses.length)
|
|
202
|
+
throw new Error(`accepted_fixture_content_witness_duplicate:${index}`);
|
|
203
|
+
return Object.freeze(witnesses);
|
|
204
|
+
}
|
|
205
|
+
function parseMutationWitnesses(value, index) {
|
|
206
|
+
if (!Array.isArray(value)) {
|
|
207
|
+
throw new Error(`accepted_fixture_mutation_witnesses_required:${index}`);
|
|
208
|
+
}
|
|
209
|
+
const witnesses = value.map((item, witnessIndex) => {
|
|
210
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
211
|
+
throw new Error(`accepted_fixture_mutation_witness_invalid:${index}:${witnessIndex}`);
|
|
212
|
+
}
|
|
213
|
+
const witness = item;
|
|
214
|
+
const keys = Object.keys(witness).sort();
|
|
215
|
+
const expected = [
|
|
216
|
+
"after_head_sha256",
|
|
217
|
+
"after_manifest_sha256",
|
|
218
|
+
"after_revision",
|
|
219
|
+
"after_source_sha256",
|
|
220
|
+
"after_value_sha256",
|
|
221
|
+
"author_client",
|
|
222
|
+
"before_head_sha256",
|
|
223
|
+
"before_manifest_sha256",
|
|
224
|
+
"before_revision",
|
|
225
|
+
"before_source_base64",
|
|
226
|
+
"before_source_sha256",
|
|
227
|
+
"before_value_sha256",
|
|
228
|
+
"changed_field_path",
|
|
229
|
+
"changed_section_key",
|
|
230
|
+
"operation_id",
|
|
231
|
+
"preserved_section_digests",
|
|
232
|
+
"preserved_unknown_sha256s",
|
|
233
|
+
];
|
|
234
|
+
if (keys.length !== expected.length
|
|
235
|
+
|| keys.some((key, keyIndex) => key !== expected[keyIndex]))
|
|
236
|
+
throw new Error(`accepted_fixture_mutation_witness_fields_mismatch:${index}:${witnessIndex}`);
|
|
237
|
+
if (!Array.isArray(witness.preserved_section_digests) || witness.preserved_section_digests.length === 0) {
|
|
238
|
+
throw new Error(`accepted_fixture_mutation_preserved_sections_required:${index}:${witnessIndex}`);
|
|
239
|
+
}
|
|
240
|
+
const preserved = witness.preserved_section_digests.map((digestValue, digestIndex) => {
|
|
241
|
+
if (typeof digestValue !== "object" || digestValue === null || Array.isArray(digestValue)) {
|
|
242
|
+
throw new Error(`accepted_fixture_mutation_preserved_section_invalid:${index}:${witnessIndex}:${digestIndex}`);
|
|
243
|
+
}
|
|
244
|
+
const digest = digestValue;
|
|
245
|
+
const digestKeys = Object.keys(digest).sort();
|
|
246
|
+
if (digestKeys.length !== 2 || digestKeys[0] !== "section_key" || digestKeys[1] !== "sha256") {
|
|
247
|
+
throw new Error(`accepted_fixture_mutation_preserved_section_fields_mismatch:${index}:${witnessIndex}:${digestIndex}`);
|
|
248
|
+
}
|
|
249
|
+
return Object.freeze({
|
|
250
|
+
section_key: requireSectionKey(digest.section_key, `accepted_fixture_mutation_preserved_section_key_invalid:${index}:${witnessIndex}:${digestIndex}`),
|
|
251
|
+
sha256: requireSha256(digest.sha256, `accepted_fixture_mutation_preserved_section_hash_invalid:${index}:${witnessIndex}:${digestIndex}`),
|
|
252
|
+
});
|
|
253
|
+
});
|
|
254
|
+
for (let digestIndex = 1; digestIndex < preserved.length; digestIndex += 1) {
|
|
255
|
+
const previous = preserved[digestIndex - 1];
|
|
256
|
+
const current = preserved[digestIndex];
|
|
257
|
+
if (previous === undefined || current === undefined || compareAscii(previous.section_key, current.section_key) !== -1) {
|
|
258
|
+
throw new Error(`accepted_fixture_mutation_preserved_sections_unsorted:${index}:${witnessIndex}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (!Array.isArray(witness.preserved_unknown_sha256s)) {
|
|
262
|
+
throw new Error(`accepted_fixture_mutation_preserved_unknown_required:${index}:${witnessIndex}`);
|
|
263
|
+
}
|
|
264
|
+
const unknown = witness.preserved_unknown_sha256s.map((item, unknownIndex) => {
|
|
265
|
+
if (typeof item !== "string" || !/^(?:[a-z][a-z0-9_.-]+:)?[0-9]+:[0-9a-f]{64}$/u.test(item)) {
|
|
266
|
+
throw new Error(`accepted_fixture_mutation_preserved_unknown_invalid:${index}:${witnessIndex}:${unknownIndex}`);
|
|
267
|
+
}
|
|
268
|
+
return item;
|
|
269
|
+
});
|
|
270
|
+
for (let unknownIndex = 1; unknownIndex < unknown.length; unknownIndex += 1) {
|
|
271
|
+
if (compareAscii(unknown[unknownIndex - 1] ?? "", unknown[unknownIndex] ?? "") !== -1) {
|
|
272
|
+
throw new Error(`accepted_fixture_mutation_preserved_unknown_unsorted:${index}:${witnessIndex}`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
let beforeBytes;
|
|
276
|
+
try {
|
|
277
|
+
beforeBytes = decodeBase64Bytes(String(witness.before_source_base64));
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
throw new Error(`accepted_fixture_mutation_before_source_invalid:${index}:${witnessIndex}`);
|
|
281
|
+
}
|
|
282
|
+
if (beforeBytes.byteLength === 0) {
|
|
283
|
+
throw new Error(`accepted_fixture_mutation_before_source_empty:${index}:${witnessIndex}`);
|
|
284
|
+
}
|
|
285
|
+
return Object.freeze({
|
|
286
|
+
after_head_sha256: requireSha256(witness.after_head_sha256, `accepted_fixture_mutation_after_head_invalid:${index}:${witnessIndex}`),
|
|
287
|
+
after_manifest_sha256: requireSha256(witness.after_manifest_sha256, `accepted_fixture_mutation_after_manifest_invalid:${index}:${witnessIndex}`),
|
|
288
|
+
after_revision: requireByteLength(witness.after_revision, `accepted_fixture_mutation_after_revision_invalid:${index}:${witnessIndex}`),
|
|
289
|
+
after_source_sha256: requireSha256(witness.after_source_sha256, `accepted_fixture_mutation_after_source_invalid:${index}:${witnessIndex}`),
|
|
290
|
+
after_value_sha256: requireSha256(witness.after_value_sha256, `accepted_fixture_mutation_after_value_invalid:${index}:${witnessIndex}`),
|
|
291
|
+
author_client: requireIdentifier(witness.author_client, `accepted_fixture_mutation_author_client_invalid:${index}:${witnessIndex}`),
|
|
292
|
+
before_head_sha256: requireSha256(witness.before_head_sha256, `accepted_fixture_mutation_before_head_invalid:${index}:${witnessIndex}`),
|
|
293
|
+
before_manifest_sha256: requireSha256(witness.before_manifest_sha256, `accepted_fixture_mutation_before_manifest_invalid:${index}:${witnessIndex}`),
|
|
294
|
+
before_revision: requireByteLength(witness.before_revision, `accepted_fixture_mutation_before_revision_invalid:${index}:${witnessIndex}`),
|
|
295
|
+
before_source_base64: requireText(witness.before_source_base64, `accepted_fixture_mutation_before_source_text_invalid:${index}:${witnessIndex}`),
|
|
296
|
+
before_source_sha256: requireSha256(witness.before_source_sha256, `accepted_fixture_mutation_before_source_hash_invalid:${index}:${witnessIndex}`),
|
|
297
|
+
before_value_sha256: requireSha256(witness.before_value_sha256, `accepted_fixture_mutation_before_value_invalid:${index}:${witnessIndex}`),
|
|
298
|
+
changed_field_path: requireText(witness.changed_field_path, `accepted_fixture_mutation_changed_field_path_invalid:${index}:${witnessIndex}`),
|
|
299
|
+
changed_section_key: requireSectionKey(witness.changed_section_key, `accepted_fixture_mutation_changed_section_invalid:${index}:${witnessIndex}`),
|
|
300
|
+
operation_id: requireIdentifier(witness.operation_id, `accepted_fixture_mutation_operation_id_invalid:${index}:${witnessIndex}`),
|
|
301
|
+
preserved_section_digests: Object.freeze(preserved),
|
|
302
|
+
preserved_unknown_sha256s: Object.freeze(unknown),
|
|
303
|
+
});
|
|
304
|
+
});
|
|
305
|
+
for (let witnessIndex = 1; witnessIndex < witnesses.length; witnessIndex += 1) {
|
|
306
|
+
const previous = witnesses[witnessIndex - 1];
|
|
307
|
+
const current = witnesses[witnessIndex];
|
|
308
|
+
if (previous === undefined || current === undefined || compareAscii(previous.operation_id, current.operation_id) !== -1) {
|
|
309
|
+
throw new Error(`accepted_fixture_mutation_witnesses_unsorted:${index}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (new Set(witnesses.map((witness) => witness.operation_id)).size !== witnesses.length) {
|
|
313
|
+
throw new Error(`accepted_fixture_mutation_witness_duplicate:${index}`);
|
|
314
|
+
}
|
|
315
|
+
return Object.freeze(witnesses);
|
|
316
|
+
}
|
|
317
|
+
function parseSizeWitnesses(value, index) {
|
|
318
|
+
if (!Array.isArray(value)) {
|
|
319
|
+
throw new Error(`accepted_fixture_size_witnesses_required:${index}`);
|
|
320
|
+
}
|
|
321
|
+
const witnesses = value.map((item, witnessIndex) => {
|
|
322
|
+
if (typeof item !== "object" || item === null || Array.isArray(item)) {
|
|
323
|
+
throw new Error(`accepted_fixture_size_witness_invalid:${index}:${witnessIndex}`);
|
|
324
|
+
}
|
|
325
|
+
const witness = item;
|
|
326
|
+
const keys = Object.keys(witness).sort();
|
|
327
|
+
const expected = ["kind", "limit_bytes", "plus_one_byte_length", "source_byte_length"];
|
|
328
|
+
if (keys.length !== expected.length
|
|
329
|
+
|| keys.some((key, keyIndex) => key !== expected[keyIndex]))
|
|
330
|
+
throw new Error(`accepted_fixture_size_witness_fields_mismatch:${index}:${witnessIndex}`);
|
|
331
|
+
const limit = requireByteLength(witness.limit_bytes, `accepted_fixture_size_limit_invalid:${index}:${witnessIndex}`);
|
|
332
|
+
const sourceLength = requireByteLength(witness.source_byte_length, `accepted_fixture_size_source_length_invalid:${index}:${witnessIndex}`);
|
|
333
|
+
const plusOne = requireByteLength(witness.plus_one_byte_length, `accepted_fixture_size_plus_one_invalid:${index}:${witnessIndex}`);
|
|
334
|
+
if (BigInt(plusOne) !== BigInt(limit) + 1n) {
|
|
335
|
+
throw new Error(`accepted_fixture_size_plus_one_not_limit_plus_one:${index}:${witnessIndex}`);
|
|
336
|
+
}
|
|
337
|
+
return Object.freeze({
|
|
338
|
+
kind: requireIdentifier(witness.kind, `accepted_fixture_size_kind_invalid:${index}:${witnessIndex}`),
|
|
339
|
+
limit_bytes: limit,
|
|
340
|
+
source_byte_length: sourceLength,
|
|
341
|
+
plus_one_byte_length: plusOne,
|
|
342
|
+
});
|
|
343
|
+
});
|
|
344
|
+
for (let witnessIndex = 1; witnessIndex < witnesses.length; witnessIndex += 1) {
|
|
345
|
+
const previous = witnesses[witnessIndex - 1];
|
|
346
|
+
const current = witnesses[witnessIndex];
|
|
347
|
+
if (previous === undefined || current === undefined || compareAscii(previous.kind, current.kind) !== -1) {
|
|
348
|
+
throw new Error(`accepted_fixture_size_witnesses_unsorted:${index}`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (new Set(witnesses.map((witness) => witness.kind)).size !== witnesses.length) {
|
|
352
|
+
throw new Error(`accepted_fixture_size_witness_duplicate:${index}`);
|
|
353
|
+
}
|
|
354
|
+
return Object.freeze(witnesses);
|
|
355
|
+
}
|
|
356
|
+
function parseTargetProfiles(value, index) {
|
|
357
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
358
|
+
throw new Error(`accepted_fixture_target_profiles_required:${index}`);
|
|
359
|
+
}
|
|
360
|
+
const profiles = value.map((item, profileIndex) => {
|
|
361
|
+
try {
|
|
362
|
+
return parseCompileTargetProfile(item);
|
|
363
|
+
}
|
|
364
|
+
catch (error) {
|
|
365
|
+
const code = error instanceof Error ? error.message : "compile_target_profile_invalid";
|
|
366
|
+
throw new Error(`accepted_fixture_target_profile_invalid:${index}:${profileIndex}:${code}`);
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
const identities = profiles.map((profile) => JSON.stringify([
|
|
370
|
+
profile.compiler_release,
|
|
371
|
+
profile.runtime_semantics,
|
|
372
|
+
profile.sdk_schema,
|
|
373
|
+
profile.artifact_format,
|
|
374
|
+
...profile.stage_versions.map((stage) => `${stage.stage_id}:${stage.stage_version}`),
|
|
375
|
+
]));
|
|
376
|
+
if (new Set(identities).size !== identities.length) {
|
|
377
|
+
throw new Error(`accepted_fixture_target_profile_duplicate:${index}`);
|
|
378
|
+
}
|
|
379
|
+
const sorted = [...profiles].sort((left, right) => compareAscii(left.compiler_release, right.compiler_release)
|
|
380
|
+
|| compareAscii(left.runtime_semantics, right.runtime_semantics)
|
|
381
|
+
|| compareAscii(left.sdk_schema, right.sdk_schema)
|
|
382
|
+
|| compareAscii(left.artifact_format, right.artifact_format));
|
|
383
|
+
if (sorted.some((profile, profileIndex) => profile !== profiles[profileIndex])) {
|
|
384
|
+
throw new Error(`accepted_fixture_target_profiles_unsorted:${index}`);
|
|
385
|
+
}
|
|
386
|
+
return Object.freeze(profiles);
|
|
387
|
+
}
|
|
388
|
+
export function parseAcceptedNeutralSourceCorpus(value) {
|
|
389
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
390
|
+
throw new Error("accepted_source_corpus_object_required");
|
|
391
|
+
}
|
|
392
|
+
const root = value;
|
|
393
|
+
const rootKeys = Object.keys(root).sort();
|
|
394
|
+
if (rootKeys.length !== 2
|
|
395
|
+
|| rootKeys[0] !== "schema_version"
|
|
396
|
+
|| rootKeys[1] !== "sources")
|
|
397
|
+
throw new Error("accepted_source_corpus_fields_mismatch");
|
|
398
|
+
if (root.schema_version !== ACCEPTED_NEUTRAL_SOURCE_CORPUS_SCHEMA_VERSION) {
|
|
399
|
+
throw new Error("accepted_source_corpus_schema_version_invalid");
|
|
400
|
+
}
|
|
401
|
+
if (!Array.isArray(root.sources) || root.sources.length === 0) {
|
|
402
|
+
throw new Error("accepted_source_corpus_empty");
|
|
403
|
+
}
|
|
404
|
+
const sources = root.sources.map((value, index) => {
|
|
405
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
406
|
+
throw new Error(`accepted_source_corpus_entry_invalid:${index}`);
|
|
407
|
+
}
|
|
408
|
+
const entry = value;
|
|
409
|
+
const keys = Object.keys(entry).sort();
|
|
410
|
+
const expected = [
|
|
411
|
+
"acceptance_ref",
|
|
412
|
+
"byte_range_witnesses",
|
|
413
|
+
"content_witnesses",
|
|
414
|
+
"fixture_id",
|
|
415
|
+
"manifest_sha256",
|
|
416
|
+
"mutation_witnesses",
|
|
417
|
+
"relative_path",
|
|
418
|
+
"scenario_id",
|
|
419
|
+
"section_digests",
|
|
420
|
+
"size_witnesses",
|
|
421
|
+
"source_sha256",
|
|
422
|
+
"target_profiles",
|
|
423
|
+
];
|
|
424
|
+
if (keys.length !== expected.length
|
|
425
|
+
|| keys.some((key, keyIndex) => key !== expected[keyIndex]))
|
|
426
|
+
throw new Error(`accepted_source_corpus_entry_fields_mismatch:${index}`);
|
|
427
|
+
return Object.freeze({
|
|
428
|
+
fixture_id: requireIdentifier(entry.fixture_id, `accepted_fixture_id_invalid:${index}`),
|
|
429
|
+
relative_path: requireRelativePath(entry.relative_path, `accepted_fixture_path_invalid:${index}`),
|
|
430
|
+
source_sha256: requireSha256(entry.source_sha256, `accepted_fixture_source_hash_invalid:${index}`),
|
|
431
|
+
scenario_id: requireText(entry.scenario_id, `accepted_fixture_scenario_id_invalid:${index}`),
|
|
432
|
+
manifest_sha256: requireSha256(entry.manifest_sha256, `accepted_fixture_manifest_hash_invalid:${index}`),
|
|
433
|
+
acceptance_ref: requireText(entry.acceptance_ref, `accepted_fixture_acceptance_ref_invalid:${index}`),
|
|
434
|
+
section_digests: parseSectionDigests(entry.section_digests, index),
|
|
435
|
+
target_profiles: parseTargetProfiles(entry.target_profiles, index),
|
|
436
|
+
byte_range_witnesses: parseByteRangeWitnesses(entry.byte_range_witnesses, index),
|
|
437
|
+
content_witnesses: parseContentWitnesses(entry.content_witnesses, index),
|
|
438
|
+
mutation_witnesses: parseMutationWitnesses(entry.mutation_witnesses, index),
|
|
439
|
+
size_witnesses: parseSizeWitnesses(entry.size_witnesses, index),
|
|
440
|
+
});
|
|
441
|
+
}).sort((left, right) => compareAscii(left.fixture_id, right.fixture_id));
|
|
442
|
+
if (new Set(sources.map((entry) => entry.fixture_id)).size !== sources.length
|
|
443
|
+
|| new Set(sources.map((entry) => entry.relative_path)).size !== sources.length
|
|
444
|
+
|| new Set(sources.map((entry) => entry.scenario_id)).size !== sources.length
|
|
445
|
+
|| new Set(sources.map((entry) => entry.source_sha256)).size !== sources.length)
|
|
446
|
+
throw new Error("accepted_source_corpus_entry_duplicate");
|
|
447
|
+
return Object.freeze({
|
|
448
|
+
schema_version: ACCEPTED_NEUTRAL_SOURCE_CORPUS_SCHEMA_VERSION,
|
|
449
|
+
sources: Object.freeze(sources),
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
export async function evaluateCompilerCandidate(candidate, corpusValue, loadFixture) {
|
|
453
|
+
let corpus;
|
|
454
|
+
try {
|
|
455
|
+
corpus = parseAcceptedNeutralSourceCorpus(corpusValue);
|
|
456
|
+
}
|
|
457
|
+
catch (error) {
|
|
458
|
+
return Object.freeze({
|
|
459
|
+
promotable: false,
|
|
460
|
+
passes: Object.freeze([]),
|
|
461
|
+
failures: Object.freeze([{
|
|
462
|
+
fixture_id: "$corpus",
|
|
463
|
+
code: error instanceof Error ? error.message : "accepted_source_corpus_invalid",
|
|
464
|
+
}]),
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
const passes = [];
|
|
468
|
+
const failures = [];
|
|
469
|
+
for (const entry of corpus.sources) {
|
|
470
|
+
try {
|
|
471
|
+
const bytes = await loadFixture(entry.relative_path);
|
|
472
|
+
if (!(bytes instanceof Uint8Array))
|
|
473
|
+
throw new Error("accepted_fixture_bytes_invalid");
|
|
474
|
+
if (await tmwSha256Hex(bytes) !== entry.source_sha256) {
|
|
475
|
+
throw new Error("accepted_fixture_source_hash_mismatch");
|
|
476
|
+
}
|
|
477
|
+
const source = await decodeNeutralScenarioSource(bytes.slice());
|
|
478
|
+
if (source.scenario_id !== entry.scenario_id
|
|
479
|
+
|| source.manifest === undefined
|
|
480
|
+
|| sha256Hex(source.manifest.manifest_sha256) !== entry.manifest_sha256) {
|
|
481
|
+
throw new Error("accepted_fixture_source_identity_mismatch");
|
|
482
|
+
}
|
|
483
|
+
const actualDigests = [...source.manifest.sections]
|
|
484
|
+
.map((identity) => Object.freeze({
|
|
485
|
+
section_key: identity.section_key,
|
|
486
|
+
sha256: sha256Hex(identity.sha256),
|
|
487
|
+
byte_length: identity.byte_length,
|
|
488
|
+
}))
|
|
489
|
+
.sort((left, right) => compareAscii(left.section_key, right.section_key));
|
|
490
|
+
if (actualDigests.length !== entry.section_digests.length
|
|
491
|
+
|| actualDigests.some((digest, digestIndex) => {
|
|
492
|
+
const expected = entry.section_digests[digestIndex];
|
|
493
|
+
return expected === undefined
|
|
494
|
+
|| digest.section_key !== expected.section_key
|
|
495
|
+
|| digest.sha256 !== expected.sha256
|
|
496
|
+
|| digest.byte_length !== expected.byte_length;
|
|
497
|
+
}))
|
|
498
|
+
throw new Error("accepted_fixture_section_digest_mismatch");
|
|
499
|
+
if (entry.byte_range_witnesses.some((witness) => {
|
|
500
|
+
const start = Number(witness.start);
|
|
501
|
+
const end = Number(witness.end);
|
|
502
|
+
return !Number.isSafeInteger(start)
|
|
503
|
+
|| !Number.isSafeInteger(end)
|
|
504
|
+
|| start < 0
|
|
505
|
+
|| end > bytes.byteLength;
|
|
506
|
+
}))
|
|
507
|
+
throw new Error("accepted_fixture_byte_range_out_of_bounds");
|
|
508
|
+
for (const witness of entry.byte_range_witnesses) {
|
|
509
|
+
const start = Number(witness.start);
|
|
510
|
+
const end = Number(witness.end);
|
|
511
|
+
if (sha256Hex(await sha256Bytes(bytes.subarray(start, end))) !== witness.sha256) {
|
|
512
|
+
throw new Error("accepted_fixture_byte_range_digest_mismatch");
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
for (const witness of entry.content_witnesses) {
|
|
516
|
+
const section = source.sections.find((item) => item.section_key === witness.section_key);
|
|
517
|
+
if (section === undefined)
|
|
518
|
+
throw new Error("accepted_fixture_content_witness_section_missing");
|
|
519
|
+
if (sha256Hex(await sha256Bytes(section.payload)) !== witness.sha256) {
|
|
520
|
+
throw new Error("accepted_fixture_content_witness_digest_mismatch");
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
for (const witness of entry.size_witnesses) {
|
|
524
|
+
if (String(bytes.byteLength) !== witness.source_byte_length) {
|
|
525
|
+
throw new Error("accepted_fixture_size_source_length_mismatch");
|
|
526
|
+
}
|
|
527
|
+
if (witness.kind === "max_size_boundary" && String(bytes.byteLength) !== witness.limit_bytes) {
|
|
528
|
+
throw new Error("accepted_fixture_size_limit_mismatch");
|
|
529
|
+
}
|
|
530
|
+
if (BigInt(witness.plus_one_byte_length) !== BigInt(witness.limit_bytes) + 1n) {
|
|
531
|
+
throw new Error("accepted_fixture_size_plus_one_mismatch");
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
for (const witness of entry.mutation_witnesses) {
|
|
535
|
+
if (witness.after_source_sha256 !== entry.source_sha256 || witness.after_manifest_sha256 !== entry.manifest_sha256) {
|
|
536
|
+
throw new Error("accepted_fixture_mutation_after_identity_mismatch");
|
|
537
|
+
}
|
|
538
|
+
const beforeBytes = decodeBase64Bytes(witness.before_source_base64);
|
|
539
|
+
if (sha256Hex(await sha256Bytes(beforeBytes)) !== witness.before_source_sha256) {
|
|
540
|
+
throw new Error("accepted_fixture_mutation_before_source_hash_mismatch");
|
|
541
|
+
}
|
|
542
|
+
const before = await decodeNeutralScenarioSource(beforeBytes.slice());
|
|
543
|
+
if (before.manifest === undefined || sha256Hex(before.manifest.manifest_sha256) !== witness.before_manifest_sha256) {
|
|
544
|
+
throw new Error("accepted_fixture_mutation_before_manifest_mismatch");
|
|
545
|
+
}
|
|
546
|
+
const beforeDigest = new Map(before.manifest.sections.map((identity) => [identity.section_key, sha256Hex(identity.sha256)]));
|
|
547
|
+
const afterDigest = new Map(source.manifest.sections.map((identity) => [identity.section_key, sha256Hex(identity.sha256)]));
|
|
548
|
+
if (beforeDigest.get(witness.changed_section_key) === afterDigest.get(witness.changed_section_key)) {
|
|
549
|
+
throw new Error("accepted_fixture_mutation_changed_section_unmodified");
|
|
550
|
+
}
|
|
551
|
+
for (const preserved of witness.preserved_section_digests) {
|
|
552
|
+
if (beforeDigest.get(preserved.section_key) !== preserved.sha256 || afterDigest.get(preserved.section_key) !== preserved.sha256) {
|
|
553
|
+
throw new Error("accepted_fixture_mutation_preserved_section_mismatch");
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
const candidateProfile = parseCompileTargetProfile(candidate.target_profile);
|
|
558
|
+
const candidateDigest = await compileTargetProfileDigest(candidateProfile);
|
|
559
|
+
const declaredDigests = await Promise.all(entry.target_profiles.map((profile) => compileTargetProfileDigest(profile)));
|
|
560
|
+
if (!declaredDigests.includes(candidateDigest)) {
|
|
561
|
+
throw new Error("accepted_fixture_target_profile_not_declared");
|
|
562
|
+
}
|
|
563
|
+
const input = await captureNeutralSourceCompileInput({
|
|
564
|
+
witness: {
|
|
565
|
+
owner_id: "accepted-source-corpus",
|
|
566
|
+
scenario_id: entry.scenario_id,
|
|
567
|
+
source_revision: 1,
|
|
568
|
+
manifest_digest: entry.manifest_sha256,
|
|
569
|
+
source_digest: sha256Hex(await sha256Bytes(bytes)),
|
|
570
|
+
revision_digest: entry.source_sha256,
|
|
571
|
+
previous_head_digest: null,
|
|
572
|
+
head_digest: entry.manifest_sha256,
|
|
573
|
+
},
|
|
574
|
+
source_bytes: bytes,
|
|
575
|
+
});
|
|
576
|
+
const compiled = await compileNeutralScenarioSource(input, candidate.target_profile, candidate.registry, candidate.createCache());
|
|
577
|
+
if (!compiled.ok) {
|
|
578
|
+
const first = compiled.diagnostics[0];
|
|
579
|
+
throw new Error(first?.code ?? "accepted_fixture_compile_failed");
|
|
580
|
+
}
|
|
581
|
+
if (compiled.receipt.scenario_id !== entry.scenario_id
|
|
582
|
+
|| compiled.receipt.source_manifest_sha256 !== entry.manifest_sha256)
|
|
583
|
+
throw new Error("accepted_fixture_compile_identity_mismatch");
|
|
584
|
+
passes.push(Object.freeze({
|
|
585
|
+
fixture_id: entry.fixture_id,
|
|
586
|
+
source_sha256: entry.source_sha256,
|
|
587
|
+
manifest_sha256: entry.manifest_sha256,
|
|
588
|
+
receipt: compiled.receipt,
|
|
589
|
+
}));
|
|
590
|
+
}
|
|
591
|
+
catch (error) {
|
|
592
|
+
failures.push(Object.freeze({
|
|
593
|
+
fixture_id: entry.fixture_id,
|
|
594
|
+
code: error instanceof Error ? error.message : "accepted_fixture_evaluation_failed",
|
|
595
|
+
}));
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
return failures.length === 0
|
|
599
|
+
? Object.freeze({
|
|
600
|
+
promotable: true,
|
|
601
|
+
passes: Object.freeze(passes),
|
|
602
|
+
failures: Object.freeze([]),
|
|
603
|
+
})
|
|
604
|
+
: Object.freeze({
|
|
605
|
+
promotable: false,
|
|
606
|
+
passes: Object.freeze(passes),
|
|
607
|
+
failures: Object.freeze(failures),
|
|
608
|
+
});
|
|
609
|
+
}
|