assertledger 1.3.1 → 1.5.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/README.fr.md +6 -3
- package/README.md +6 -3
- package/conformance/schema-extensions.json +15 -0
- package/dist/build-info.json +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +218 -8
- package/dist/cli.js.map +1 -1
- package/dist/contracts/index.d.ts +467 -4
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/contracts/index.js +256 -3
- package/dist/contracts/index.js.map +1 -1
- package/dist/contracts/qualification.d.ts +528 -0
- package/dist/contracts/qualification.d.ts.map +1 -0
- package/dist/contracts/qualification.js +357 -0
- package/dist/contracts/qualification.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +46 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/qualification.d.ts +17 -0
- package/dist/core/qualification.d.ts.map +1 -0
- package/dist/core/qualification.js +571 -0
- package/dist/core/qualification.js.map +1 -0
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +81 -4
- package/dist/diagnostics.js.map +1 -1
- package/dist/engine/adapters/bun-native.d.ts +35 -0
- package/dist/engine/adapters/bun-native.d.ts.map +1 -0
- package/dist/engine/adapters/bun-native.js +179 -0
- package/dist/engine/adapters/bun-native.js.map +1 -0
- package/dist/engine/adapters/bun-test-designated-profile.d.ts +23 -0
- package/dist/engine/adapters/bun-test-designated-profile.d.ts.map +1 -0
- package/dist/engine/adapters/bun-test-designated-profile.js +24 -0
- package/dist/engine/adapters/bun-test-designated-profile.js.map +1 -0
- package/dist/engine/container.d.ts +7 -0
- package/dist/engine/container.d.ts.map +1 -1
- package/dist/engine/container.js +22 -7
- package/dist/engine/container.js.map +1 -1
- package/dist/engine/git-regression.d.ts.map +1 -1
- package/dist/engine/git-regression.js +9 -2
- package/dist/engine/git-regression.js.map +1 -1
- package/dist/engine/index.d.ts +14 -0
- package/dist/engine/index.d.ts.map +1 -1
- package/dist/engine/index.js +828 -97
- package/dist/engine/index.js.map +1 -1
- package/dist/engine/qualification.d.ts +154 -0
- package/dist/engine/qualification.d.ts.map +1 -0
- package/dist/engine/qualification.js +725 -0
- package/dist/engine/qualification.js.map +1 -0
- package/dist/engine/test-closure.d.ts +39 -0
- package/dist/engine/test-closure.d.ts.map +1 -0
- package/dist/engine/test-closure.js +513 -0
- package/dist/engine/test-closure.js.map +1 -0
- package/dist/engine/witness-import.d.ts +31 -0
- package/dist/engine/witness-import.d.ts.map +1 -0
- package/dist/engine/witness-import.js +224 -0
- package/dist/engine/witness-import.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +65 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/sdk/index.d.ts +292 -3
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/index.js +39 -1
- package/dist/sdk/index.js.map +1 -1
- package/docs/container-isolation.md +6 -0
- package/docs/migration-orchestration-qualification-v1.md +109 -0
- package/docs/migration-verification-v4.md +94 -0
- package/docs/orchestration-qualification.md +167 -0
- package/docs/reference.md +13 -0
- package/docs/witness-import.md +67 -0
- package/examples/orchestration/README.md +68 -0
- package/examples/orchestration/consumer-obligations.json +101 -0
- package/examples/orchestration/workspace/bitbucket-pipelines.yml +10 -0
- package/examples/orchestration/workspace/command-shape.test.mjs +25 -0
- package/examples/orchestration/workspace/commands.mjs +14 -0
- package/examples/orchestration/workspace/completion.mjs +39 -0
- package/examples/orchestration/workspace/faults.json +1 -0
- package/examples/orchestration/workspace/native.test.ts +4 -0
- package/examples/orchestration/workspace/package.json +6 -0
- package/examples/orchestration/workspace/packages/app/package.json +12 -0
- package/examples/orchestration/workspace/packages/app/verdict.txt +1 -0
- package/examples/orchestration/workspace/packages/leaf/package.json +9 -0
- package/examples/orchestration/workspace/packages/leaf/verdict.txt +1 -0
- package/examples/orchestration/workspace/pnpm-lock.yaml +170 -0
- package/examples/orchestration/workspace/pnpm-workspace.yaml +2 -0
- package/examples/orchestration/workspace/task.mjs +23 -0
- package/examples/orchestration/workspace/turbo.json +38 -0
- package/examples/orchestration/workspace/wrapper.mjs +45 -0
- package/integrations/bun/driver.d.mts +30 -1
- package/integrations/bun/driver.mjs +215 -6
- package/integrations/bun/preload.mjs +186 -5
- package/integrations/bun-native/README.md +86 -0
- package/integrations/bun-native/driver.mjs +396 -0
- package/integrations/bun-native/preload.mjs +375 -0
- package/integrations/skill/SKILL.md +25 -5
- package/package.json +1 -1
- package/schemas/evidence-manifest.v4.json +995 -0
- package/schemas/qualification-execution-request.v1.json +571 -0
- package/schemas/qualification-plan.v1.json +528 -0
- package/schemas/qualification-receipt.v1.json +821 -0
- package/schemas/qualification-replay-result.v1.json +37 -0
- package/schemas/verification-request.v4.json +590 -0
- package/schemas/witness-import-request.v1.json +231 -0
package/dist/contracts/index.js
CHANGED
|
@@ -83,6 +83,14 @@ export const TrustedLocalIsolationSchema = z.strictObject({
|
|
|
83
83
|
});
|
|
84
84
|
export const VERIFICATION_SCHEMA_VERSION_V2 = "2.0.0";
|
|
85
85
|
export const VERIFICATION_SCHEMA_VERSION_V3 = "3.0.0";
|
|
86
|
+
export const VERIFICATION_SCHEMA_VERSION_V4 = "4.0.0";
|
|
87
|
+
// Windows-native execution is a distinct, operator-declared level: it is never inferred from a
|
|
88
|
+
// trusted-local request and requires its own authorization on a Windows host.
|
|
89
|
+
export const WindowsNativeIsolationSchema = z.strictObject({
|
|
90
|
+
kind: z.literal("windows-native"),
|
|
91
|
+
acknowledgedUnsafeExecution: z.boolean(),
|
|
92
|
+
environmentAllowlist: z.array(EnvironmentVariableSchema).max(100),
|
|
93
|
+
});
|
|
86
94
|
// Only digest-pinned references are accepted; the leading alphanumeric also keeps a reference
|
|
87
95
|
// from being parsed as a container runtime option.
|
|
88
96
|
export const ContainerImageReferenceSchema = z
|
|
@@ -171,6 +179,94 @@ export const VerificationRequestV3Schema = z
|
|
|
171
179
|
title: "AssertLedger verification request v3",
|
|
172
180
|
description: "A versioned campaign with an official Bun test adapter and explicit execution backend.",
|
|
173
181
|
});
|
|
182
|
+
/**
|
|
183
|
+
* "excluded" keeps the snapshot without Git metadata. "synthesized" commits the snapshot once into
|
|
184
|
+
* a fresh repository, never the source's own .git, for tests that ask Git for the tracked files.
|
|
185
|
+
*/
|
|
186
|
+
export const RepositoryGitModeSchema = z.enum(["excluded", "synthesized"]);
|
|
187
|
+
/** One existing repository test, named by its file and its describe path ending with the test. */
|
|
188
|
+
export const DesignatedTestSchema = z.strictObject({
|
|
189
|
+
file: z.string().min(1).max(512),
|
|
190
|
+
path: z.array(z.string().min(1).max(1_024)).min(1).max(32),
|
|
191
|
+
});
|
|
192
|
+
export const BunDesignatedTestAdapterSchema = z.strictObject({
|
|
193
|
+
kind: z.literal("bun-test-designated"),
|
|
194
|
+
executable: z.string().min(1),
|
|
195
|
+
/** Bun's per-test timeout (`bun test --timeout`); null keeps Bun's default. */
|
|
196
|
+
testTimeoutMs: z.number().int().min(1).max(3_600_000).nullable(),
|
|
197
|
+
});
|
|
198
|
+
export const AdapterV4Schema = z.discriminatedUnion("kind", [
|
|
199
|
+
NodeTestAdapterSchema,
|
|
200
|
+
StructuredCommandAdapterSchema,
|
|
201
|
+
BunTestAdapterSchema,
|
|
202
|
+
BunDesignatedTestAdapterSchema,
|
|
203
|
+
]);
|
|
204
|
+
export const DesignatedCandidateSchema = z.strictObject({
|
|
205
|
+
id: IdentifierSchema,
|
|
206
|
+
test: DesignatedTestSchema,
|
|
207
|
+
expectedFailure: z.string().min(1).max(1_024).nullable(),
|
|
208
|
+
});
|
|
209
|
+
export const CandidateV4Schema = z.union([CandidateSchema, DesignatedCandidateSchema]);
|
|
210
|
+
export const VerificationRequestV4Schema = z
|
|
211
|
+
.strictObject({
|
|
212
|
+
...VerificationRequestV3Schema.shape,
|
|
213
|
+
schemaVersion: z.literal(VERIFICATION_SCHEMA_VERSION_V4),
|
|
214
|
+
repository: z.strictObject({
|
|
215
|
+
root: z.string().min(1),
|
|
216
|
+
exclude: z.array(z.string().min(1).max(512)).max(1_000),
|
|
217
|
+
includeDependencies: z.boolean(),
|
|
218
|
+
git: RepositoryGitModeSchema,
|
|
219
|
+
}),
|
|
220
|
+
adapter: AdapterV4Schema,
|
|
221
|
+
isolation: z.discriminatedUnion("kind", [
|
|
222
|
+
TrustedLocalIsolationSchema,
|
|
223
|
+
ContainerIsolationSchema,
|
|
224
|
+
WindowsNativeIsolationSchema,
|
|
225
|
+
]),
|
|
226
|
+
candidates: z.array(CandidateV4Schema).min(1).max(1_000),
|
|
227
|
+
})
|
|
228
|
+
.meta({
|
|
229
|
+
id: "https://testforge.dev/schemas/verification-request.v4.json",
|
|
230
|
+
title: "AssertLedger verification request v4",
|
|
231
|
+
description: "A versioned campaign that can designate existing Bun tests, snapshot dependencies, and declare Windows-native execution.",
|
|
232
|
+
});
|
|
233
|
+
// A recorded red/green witness: the mutated targets, the one test expected to detect them and the
|
|
234
|
+
// first line of its expected failure. The isolation backend is an operator flag, never request data.
|
|
235
|
+
export const WitnessImportRequestSchema = z
|
|
236
|
+
.strictObject({
|
|
237
|
+
schemaVersion: z.literal("1.0.0"),
|
|
238
|
+
provenance: z.string().min(1).max(512),
|
|
239
|
+
repository: z.strictObject({
|
|
240
|
+
root: z.string().min(1),
|
|
241
|
+
exclude: z.array(z.string().min(1).max(512)).max(1_000),
|
|
242
|
+
includeDependencies: z.boolean(),
|
|
243
|
+
git: RepositoryGitModeSchema,
|
|
244
|
+
}),
|
|
245
|
+
adapter: BunDesignatedTestAdapterSchema,
|
|
246
|
+
test: DesignatedTestSchema,
|
|
247
|
+
expectedFailure: z.string().min(1).max(1_024),
|
|
248
|
+
targets: z
|
|
249
|
+
.array(z.strictObject({
|
|
250
|
+
path: z.string().min(1).max(512),
|
|
251
|
+
beforeDigest: Sha256DigestSchema,
|
|
252
|
+
content: z.string().max(1_048_576),
|
|
253
|
+
}))
|
|
254
|
+
.min(1)
|
|
255
|
+
.max(100),
|
|
256
|
+
neutral: z
|
|
257
|
+
.strictObject({
|
|
258
|
+
reason: z.string().min(1).max(1_024),
|
|
259
|
+
files: z.array(FileOverlaySchema).min(1).max(100),
|
|
260
|
+
})
|
|
261
|
+
.nullable(),
|
|
262
|
+
requiredAttempts: z.int().min(2).max(10),
|
|
263
|
+
timeoutMsPerExecution: z.int().min(1_000).max(3_600_000),
|
|
264
|
+
})
|
|
265
|
+
.meta({
|
|
266
|
+
id: "https://testforge.dev/schemas/witness-import-request.v1.json",
|
|
267
|
+
title: "AssertLedger witness import request",
|
|
268
|
+
description: "A recorded red/green witness to replay: mutated targets, one designated test and its expected failure line.",
|
|
269
|
+
});
|
|
174
270
|
export const RepositoryAnalysisSchema = z
|
|
175
271
|
.strictObject({
|
|
176
272
|
root: z.string().min(1),
|
|
@@ -575,6 +671,64 @@ export const EvidenceManifestV3Schema = z
|
|
|
575
671
|
title: "AssertLedger evidence manifest v3",
|
|
576
672
|
description: "A replayable campaign artifact recording the official Bun test adapter and execution backend.",
|
|
577
673
|
});
|
|
674
|
+
const FinalAdapterSummaryV4Schema = z.discriminatedUnion("kind", [
|
|
675
|
+
z.strictObject({ kind: z.literal("node-test") }),
|
|
676
|
+
z.strictObject({ kind: z.literal("bun-test") }),
|
|
677
|
+
z.strictObject({ kind: z.literal("bun-test-designated") }),
|
|
678
|
+
z.strictObject({
|
|
679
|
+
kind: z.literal("testforge-command"),
|
|
680
|
+
protocolVersion: z.literal("1.0.0"),
|
|
681
|
+
}),
|
|
682
|
+
]);
|
|
683
|
+
const ExecutionBackendRecordV4Schema = z.discriminatedUnion("kind", [
|
|
684
|
+
...ExecutionBackendRecordSchema.options,
|
|
685
|
+
z.strictObject({
|
|
686
|
+
kind: z.literal("windows-native"),
|
|
687
|
+
level: z.literal("WINDOWS_NATIVE_UNSANDBOXED"),
|
|
688
|
+
platform: z.literal("win32"),
|
|
689
|
+
}),
|
|
690
|
+
]);
|
|
691
|
+
// The snapshot record qualifies the repository digest: which dependency directories it covers and
|
|
692
|
+
// which repository links outside every executed test's closure were omitted from the snapshot.
|
|
693
|
+
const RepositorySnapshotRecordSchema = z.strictObject({
|
|
694
|
+
includeDependencies: z.boolean(),
|
|
695
|
+
omittedLinks: z.array(z.string().min(1).max(1_024)).max(10_000),
|
|
696
|
+
git: z
|
|
697
|
+
.strictObject({
|
|
698
|
+
mode: z.literal("synthesized"),
|
|
699
|
+
treeId: z.string().regex(/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/),
|
|
700
|
+
gitVersion: z.string().min(1).max(256),
|
|
701
|
+
})
|
|
702
|
+
.nullable(),
|
|
703
|
+
});
|
|
704
|
+
const EvidenceContextV4Schema = z.strictObject({
|
|
705
|
+
...EvidenceContextSchema.shape,
|
|
706
|
+
execution: z.strictObject({
|
|
707
|
+
...EvidenceContextSchema.shape.execution.shape,
|
|
708
|
+
backend: ExecutionBackendRecordV4Schema,
|
|
709
|
+
}),
|
|
710
|
+
repository: RepositorySnapshotRecordSchema,
|
|
711
|
+
});
|
|
712
|
+
export const EvidenceManifestV4Schema = z
|
|
713
|
+
.strictObject({
|
|
714
|
+
...EvidenceManifestV3Schema.shape,
|
|
715
|
+
schemaVersion: z.literal(VERIFICATION_SCHEMA_VERSION_V4),
|
|
716
|
+
evidenceContext: EvidenceContextV4Schema,
|
|
717
|
+
adapter: FinalAdapterSummaryV4Schema,
|
|
718
|
+
isolation: z.discriminatedUnion("kind", [
|
|
719
|
+
...EvidenceManifestV2Schema.shape.isolation.options,
|
|
720
|
+
z.strictObject({
|
|
721
|
+
kind: z.literal("windows-native"),
|
|
722
|
+
level: z.literal("WINDOWS_NATIVE_UNSANDBOXED"),
|
|
723
|
+
acknowledgedUnsafeExecution: z.literal(true),
|
|
724
|
+
}),
|
|
725
|
+
]),
|
|
726
|
+
})
|
|
727
|
+
.meta({
|
|
728
|
+
id: "https://testforge.dev/schemas/evidence-manifest.v4.json",
|
|
729
|
+
title: "AssertLedger evidence manifest v4",
|
|
730
|
+
description: "A replayable campaign artifact that records designated tests, the repository snapshot scope and the declared isolation level.",
|
|
731
|
+
});
|
|
578
732
|
export const ReplayResultSchema = z
|
|
579
733
|
.strictObject({
|
|
580
734
|
valid: z.boolean(),
|
|
@@ -1836,7 +1990,8 @@ function assertBudgets(request) {
|
|
|
1836
1990
|
}
|
|
1837
1991
|
let totalCandidateBytes = 0;
|
|
1838
1992
|
for (const candidate of request.candidates) {
|
|
1839
|
-
|
|
1993
|
+
// A designated candidate overlays nothing; its test bytes belong to the repository snapshot.
|
|
1994
|
+
const bytes = (candidate.files ?? []).reduce((total, file) => total + Buffer.byteLength(file.content, "utf8"), 0);
|
|
1840
1995
|
totalCandidateBytes += bytes;
|
|
1841
1996
|
if (bytes > request.budgets.maximumCandidateBytes) {
|
|
1842
1997
|
throw new ContractError("CANDIDATE_BYTES_EXCEEDED", `${candidate.id}: ${bytes} > ${request.budgets.maximumCandidateBytes}`);
|
|
@@ -1908,8 +2063,14 @@ export function parseVerificationRequest(value) {
|
|
|
1908
2063
|
assertBudgets(request);
|
|
1909
2064
|
return request;
|
|
1910
2065
|
}
|
|
1911
|
-
/** Parses a frozen v1/v2 request or a
|
|
2066
|
+
/** Parses a frozen v1/v2/v3 request or a v4 request that adds designated Bun tests. */
|
|
1912
2067
|
export function parseVersionedVerificationRequest(value) {
|
|
2068
|
+
if (typeof value === "object" &&
|
|
2069
|
+
value !== null &&
|
|
2070
|
+
"schemaVersion" in value &&
|
|
2071
|
+
value.schemaVersion === VERIFICATION_SCHEMA_VERSION_V4) {
|
|
2072
|
+
return parseVerificationRequestV4(value);
|
|
2073
|
+
}
|
|
1913
2074
|
if (typeof value === "object" &&
|
|
1914
2075
|
value !== null &&
|
|
1915
2076
|
"schemaVersion" in value &&
|
|
@@ -1952,6 +2113,70 @@ export function parseVerificationRequestV3(value) {
|
|
|
1952
2113
|
}
|
|
1953
2114
|
return request;
|
|
1954
2115
|
}
|
|
2116
|
+
function isDesignatedCandidate(candidate) {
|
|
2117
|
+
return "test" in candidate;
|
|
2118
|
+
}
|
|
2119
|
+
/**
|
|
2120
|
+
* Parses a v4 request. Designated candidates belong to the designated Bun adapter only, and that
|
|
2121
|
+
* adapter accepts nothing else, so native expect attribution never reaches a v3-style campaign.
|
|
2122
|
+
*/
|
|
2123
|
+
export function parseVerificationRequestV4(value) {
|
|
2124
|
+
if (typeof value !== "object" ||
|
|
2125
|
+
value === null ||
|
|
2126
|
+
!("schemaVersion" in value) ||
|
|
2127
|
+
value.schemaVersion !== VERIFICATION_SCHEMA_VERSION_V4) {
|
|
2128
|
+
throw new ContractError("SCHEMA_VERSION_UNSUPPORTED");
|
|
2129
|
+
}
|
|
2130
|
+
assertVerificationRequestPreconditions(value);
|
|
2131
|
+
const parsed = VerificationRequestV4Schema.safeParse(value);
|
|
2132
|
+
if (!parsed.success) {
|
|
2133
|
+
throw new ContractError("REQUEST_SCHEMA_INVALID", z.prettifyError(parsed.error));
|
|
2134
|
+
}
|
|
2135
|
+
const request = parsed.data;
|
|
2136
|
+
assertUniqueIdentifiers(request.worlds, "DUPLICATE_WORLD_ID");
|
|
2137
|
+
assertUniqueIdentifiers(request.candidates, "DUPLICATE_CANDIDATE_ID");
|
|
2138
|
+
assertWorldKinds(request);
|
|
2139
|
+
assertBudgets(request);
|
|
2140
|
+
const designated = request.candidates.filter(isDesignatedCandidate);
|
|
2141
|
+
if (request.adapter.kind === "bun-test-designated") {
|
|
2142
|
+
if (designated.length !== request.candidates.length) {
|
|
2143
|
+
throw new ContractError("DESIGNATED_CANDIDATE_REQUIRED");
|
|
2144
|
+
}
|
|
2145
|
+
assertDesignatedTestTimeout(request.adapter.testTimeoutMs, request.budgets.timeoutMsPerExecution);
|
|
2146
|
+
}
|
|
2147
|
+
else if (designated.length > 0) {
|
|
2148
|
+
throw new ContractError("DESIGNATED_CANDIDATE_ADAPTER_MISMATCH", request.adapter.kind);
|
|
2149
|
+
}
|
|
2150
|
+
if (request.isolation.kind === "container") {
|
|
2151
|
+
// Only the designated adapter qualifies Bun inside a container; candidate files stay local.
|
|
2152
|
+
if (request.adapter.kind === "bun-test") {
|
|
2153
|
+
throw new ContractError("BUN_TEST_CONTAINER_UNSUPPORTED");
|
|
2154
|
+
}
|
|
2155
|
+
const names = request.isolation.environment.map((variable) => variable.name);
|
|
2156
|
+
if (new Set(names).size !== names.length) {
|
|
2157
|
+
throw new ContractError("DUPLICATE_CONTAINER_ENVIRONMENT_VARIABLE");
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
return request;
|
|
2161
|
+
}
|
|
2162
|
+
/** A per-test timeout must end before the execution timeout, or it could never be observed. */
|
|
2163
|
+
function assertDesignatedTestTimeout(testTimeoutMs, executionTimeoutMs) {
|
|
2164
|
+
if (testTimeoutMs !== null && testTimeoutMs >= executionTimeoutMs) {
|
|
2165
|
+
throw new ContractError("DESIGNATED_TEST_TIMEOUT_EXCEEDS_EXECUTION");
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
/** Parses a witness import request; its targets and test are checked against the repository later. */
|
|
2169
|
+
export function parseWitnessImportRequest(value) {
|
|
2170
|
+
if (!isJsonObject(value) || value.schemaVersion !== "1.0.0") {
|
|
2171
|
+
throw new ContractError("SCHEMA_VERSION_UNSUPPORTED");
|
|
2172
|
+
}
|
|
2173
|
+
const parsed = WitnessImportRequestSchema.safeParse(value);
|
|
2174
|
+
if (!parsed.success) {
|
|
2175
|
+
throw new ContractError("WITNESS_IMPORT_REQUEST_INVALID", z.prettifyError(parsed.error));
|
|
2176
|
+
}
|
|
2177
|
+
assertDesignatedTestTimeout(parsed.data.adapter.testTimeoutMs, parsed.data.timeoutMsPerExecution);
|
|
2178
|
+
return parsed.data;
|
|
2179
|
+
}
|
|
1955
2180
|
/** Parses only the v2 request, which adds container isolation to the frozen v1 request. */
|
|
1956
2181
|
export function parseVerificationRequestV2(value) {
|
|
1957
2182
|
if (typeof value !== "object" ||
|
|
@@ -2537,8 +2762,27 @@ export function parseEvidenceManifestV3(value) {
|
|
|
2537
2762
|
}
|
|
2538
2763
|
return manifest;
|
|
2539
2764
|
}
|
|
2540
|
-
|
|
2765
|
+
export function parseEvidenceManifestV4(value) {
|
|
2766
|
+
const parsed = EvidenceManifestV4Schema.safeParse(value);
|
|
2767
|
+
if (!parsed.success) {
|
|
2768
|
+
throw new ContractError("EVIDENCE_MANIFEST_INVALID", z.prettifyError(parsed.error));
|
|
2769
|
+
}
|
|
2770
|
+
const manifest = parsed.data;
|
|
2771
|
+
const omittedLinks = manifest.evidenceContext.repository.omittedLinks;
|
|
2772
|
+
if (!manifestSummariesAreConsistent(manifest) ||
|
|
2773
|
+
!manifestReferencesAreConsistent(manifest) ||
|
|
2774
|
+
!executionBackendIsConsistent(manifest) ||
|
|
2775
|
+
new Set(omittedLinks).size !== omittedLinks.length ||
|
|
2776
|
+
omittedLinks.some((link, index) => index > 0 && (omittedLinks[index - 1] ?? "") >= link)) {
|
|
2777
|
+
throw new ContractError("EVIDENCE_MANIFEST_INCONSISTENT");
|
|
2778
|
+
}
|
|
2779
|
+
return manifest;
|
|
2780
|
+
}
|
|
2781
|
+
/** Parses a frozen v1/v2/v3 manifest or a v4 manifest with designated tests. */
|
|
2541
2782
|
export function parseVersionedEvidenceManifest(value) {
|
|
2783
|
+
if (isJsonObject(value) && value.schemaVersion === VERIFICATION_SCHEMA_VERSION_V4) {
|
|
2784
|
+
return parseEvidenceManifestV4(value);
|
|
2785
|
+
}
|
|
2542
2786
|
if (isJsonObject(value) && value.schemaVersion === VERIFICATION_SCHEMA_VERSION_V3) {
|
|
2543
2787
|
return parseEvidenceManifestV3(value);
|
|
2544
2788
|
}
|
|
@@ -3227,6 +3471,15 @@ export function verificationRequestV3JsonSchema() {
|
|
|
3227
3471
|
export function evidenceManifestV3JsonSchema() {
|
|
3228
3472
|
return jsonSchemaFor(EvidenceManifestV3Schema, "https://testforge.dev/schemas/evidence-manifest.v3.json");
|
|
3229
3473
|
}
|
|
3474
|
+
export function verificationRequestV4JsonSchema() {
|
|
3475
|
+
return jsonSchemaFor(VerificationRequestV4Schema, "https://testforge.dev/schemas/verification-request.v4.json");
|
|
3476
|
+
}
|
|
3477
|
+
export function evidenceManifestV4JsonSchema() {
|
|
3478
|
+
return jsonSchemaFor(EvidenceManifestV4Schema, "https://testforge.dev/schemas/evidence-manifest.v4.json");
|
|
3479
|
+
}
|
|
3480
|
+
export function witnessImportRequestJsonSchema() {
|
|
3481
|
+
return jsonSchemaFor(WitnessImportRequestSchema, "https://testforge.dev/schemas/witness-import-request.v1.json");
|
|
3482
|
+
}
|
|
3230
3483
|
export function replayResultJsonSchema() {
|
|
3231
3484
|
return jsonSchemaFor(ReplayResultSchema, "https://testforge.dev/schemas/replay-result.v1.json");
|
|
3232
3485
|
}
|