@openpond/evals 0.1.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/CONTRACT.md +39 -0
- package/LICENSE +21 -0
- package/README.md +60 -0
- package/RELEASING.md +49 -0
- package/dist/common.js +67 -0
- package/dist/conformance.js +66 -0
- package/dist/graders.js +87 -0
- package/dist/harness.js +206 -0
- package/dist/index.js +5 -0
- package/dist/runs.js +133 -0
- package/dist/sha256.js +91 -0
- package/dist/tasksets.js +163 -0
- package/dist/types/common.d.ts +51 -0
- package/dist/types/common.d.ts.map +1 -0
- package/dist/types/conformance.d.ts +573 -0
- package/dist/types/conformance.d.ts.map +1 -0
- package/dist/types/graders.d.ts +70 -0
- package/dist/types/graders.d.ts.map +1 -0
- package/dist/types/harness.d.ts +527 -0
- package/dist/types/harness.d.ts.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/runs.d.ts +293 -0
- package/dist/types/runs.d.ts.map +1 -0
- package/dist/types/sha256.d.ts +2 -0
- package/dist/types/sha256.d.ts.map +1 -0
- package/dist/types/tasksets.d.ts +637 -0
- package/dist/types/tasksets.d.ts.map +1 -0
- package/package.json +76 -0
package/dist/runs.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { FailureClassSchema, ImmutableArtifactRefSchema, ImmutableReleaseRefSchema, MetadataSchema, ReleaseHashSchema, ReleaseIdSchema, ReleaseTimestampSchema, contentHash, } from "./common.js";
|
|
3
|
+
export const ModelRefSchema = z.object({
|
|
4
|
+
provider: ReleaseIdSchema,
|
|
5
|
+
model: ReleaseIdSchema,
|
|
6
|
+
revision: z.string().trim().min(1).max(500).nullable().default(null),
|
|
7
|
+
artifactHash: ReleaseHashSchema.nullable().default(null),
|
|
8
|
+
tokenizerRevision: z.string().trim().min(1).max(500).nullable().default(null),
|
|
9
|
+
chatTemplateHash: ReleaseHashSchema.nullable().default(null),
|
|
10
|
+
}).strict();
|
|
11
|
+
export const RuntimeTargetBindingSchema = z.object({
|
|
12
|
+
adapterId: ReleaseIdSchema,
|
|
13
|
+
placement: z.enum(["local", "remote", "colocated", "provider_native"]),
|
|
14
|
+
runtimeVersion: z.string().trim().min(1).max(200),
|
|
15
|
+
capabilityReceipt: ReleaseHashSchema,
|
|
16
|
+
}).strict();
|
|
17
|
+
export const RunLimitsSchema = z.object({
|
|
18
|
+
maxTurns: z.number().int().positive().max(100_000),
|
|
19
|
+
timeoutMs: z.number().int().positive().max(86_400_000),
|
|
20
|
+
maxOutputBytes: z.number().int().positive().max(250_000_000),
|
|
21
|
+
maximumSpendUsd: z.number().nonnegative().nullable(),
|
|
22
|
+
}).strict();
|
|
23
|
+
export const RunManifestContentSchema = z.object({
|
|
24
|
+
schemaVersion: z.literal("openpond.runManifest.v1"),
|
|
25
|
+
id: ReleaseIdSchema,
|
|
26
|
+
harnessRelease: ImmutableReleaseRefSchema,
|
|
27
|
+
tasksetRelease: ImmutableReleaseRefSchema,
|
|
28
|
+
model: ModelRefSchema,
|
|
29
|
+
runtimeTarget: RuntimeTargetBindingSchema,
|
|
30
|
+
limits: RunLimitsSchema,
|
|
31
|
+
approval: z.object({ id: ReleaseIdSchema, contentHash: ReleaseHashSchema }).strict().nullable(),
|
|
32
|
+
createdAt: ReleaseTimestampSchema,
|
|
33
|
+
metadata: MetadataSchema,
|
|
34
|
+
}).strict();
|
|
35
|
+
export const RunManifestSchema = RunManifestContentSchema.extend({ contentHash: ReleaseHashSchema }).strict();
|
|
36
|
+
export const AttemptReceiptContentSchema = z.object({
|
|
37
|
+
schemaVersion: z.literal("openpond.attemptReceipt.v1"),
|
|
38
|
+
id: ReleaseIdSchema,
|
|
39
|
+
runManifest: ImmutableReleaseRefSchema,
|
|
40
|
+
taskId: ReleaseIdSchema,
|
|
41
|
+
seed: z.string().trim().min(1).max(500),
|
|
42
|
+
terminal: z.boolean(),
|
|
43
|
+
failureClass: FailureClassSchema.nullable(),
|
|
44
|
+
outputHash: ReleaseHashSchema.nullable(),
|
|
45
|
+
traceHash: ReleaseHashSchema,
|
|
46
|
+
artifactRefs: z.array(ImmutableArtifactRefSchema).max(100_000),
|
|
47
|
+
graderEvidenceRefs: z.array(ImmutableArtifactRefSchema).max(10_000),
|
|
48
|
+
startedAt: ReleaseTimestampSchema,
|
|
49
|
+
completedAt: ReleaseTimestampSchema,
|
|
50
|
+
latencyMs: z.number().int().nonnegative(),
|
|
51
|
+
costUsd: z.number().nonnegative().nullable(),
|
|
52
|
+
legacyAttemptRef: ReleaseIdSchema.nullable().default(null),
|
|
53
|
+
metadata: MetadataSchema,
|
|
54
|
+
}).strict();
|
|
55
|
+
export const AttemptReceiptSchema = AttemptReceiptContentSchema.extend({ contentHash: ReleaseHashSchema }).strict();
|
|
56
|
+
export const EvaluationResultContentSchema = z.object({
|
|
57
|
+
schemaVersion: z.literal("openpond.evaluationResult.v1"),
|
|
58
|
+
id: ReleaseIdSchema,
|
|
59
|
+
runManifest: ImmutableReleaseRefSchema,
|
|
60
|
+
harnessRelease: ImmutableReleaseRefSchema,
|
|
61
|
+
tasksetRelease: ImmutableReleaseRefSchema,
|
|
62
|
+
model: ModelRefSchema,
|
|
63
|
+
receiptRefs: z.array(ImmutableReleaseRefSchema).min(1).max(1_000_000),
|
|
64
|
+
attemptCount: z.number().int().positive(),
|
|
65
|
+
rewardEligibleCount: z.number().int().nonnegative(),
|
|
66
|
+
terminalCount: z.number().int().nonnegative(),
|
|
67
|
+
meanScore: z.number().min(0).max(1).nullable(),
|
|
68
|
+
failureCounts: z.record(FailureClassSchema, z.number().int().nonnegative()),
|
|
69
|
+
metadata: MetadataSchema,
|
|
70
|
+
}).strict();
|
|
71
|
+
export const EvaluationResultSchema = EvaluationResultContentSchema.extend({ contentHash: ReleaseHashSchema }).strict();
|
|
72
|
+
export function createRunManifest(input) {
|
|
73
|
+
const content = RunManifestContentSchema.parse(input);
|
|
74
|
+
return RunManifestSchema.parse({ ...content, contentHash: contentHash(content) });
|
|
75
|
+
}
|
|
76
|
+
export function createAttemptReceipt(input) {
|
|
77
|
+
const content = AttemptReceiptContentSchema.parse(input);
|
|
78
|
+
return AttemptReceiptSchema.parse({ ...content, contentHash: contentHash(content) });
|
|
79
|
+
}
|
|
80
|
+
export function verifyAttemptReceipt(receipt) {
|
|
81
|
+
const parsed = AttemptReceiptSchema.safeParse(receipt);
|
|
82
|
+
if (!parsed.success)
|
|
83
|
+
return false;
|
|
84
|
+
const { contentHash: actual, ...content } = parsed.data;
|
|
85
|
+
return contentHash(AttemptReceiptContentSchema.parse(content)) === actual;
|
|
86
|
+
}
|
|
87
|
+
export function aggregateEvaluationReceipts(input) {
|
|
88
|
+
if (!input.receipts.length)
|
|
89
|
+
throw new Error("An evaluation requires at least one attempt receipt.");
|
|
90
|
+
for (const receipt of input.receipts) {
|
|
91
|
+
if (receipt.runManifest.id !== input.manifest.id || receipt.runManifest.contentHash !== input.manifest.contentHash) {
|
|
92
|
+
throw new Error(`Attempt receipt ${receipt.id} belongs to a different Run Manifest.`);
|
|
93
|
+
}
|
|
94
|
+
if (!verifyAttemptReceipt(receipt))
|
|
95
|
+
throw new Error(`Attempt receipt ${receipt.id} has an invalid content hash.`);
|
|
96
|
+
}
|
|
97
|
+
const scores = input.receipts.flatMap((receipt) => typeof receipt.metadata.score === "number" && Number.isFinite(receipt.metadata.score)
|
|
98
|
+
? [receipt.metadata.score]
|
|
99
|
+
: []);
|
|
100
|
+
const failureCounts = Object.fromEntries(FailureClassSchema.options.map((failure) => [failure, input.receipts.filter((receipt) => receipt.failureClass === failure).length]));
|
|
101
|
+
const content = EvaluationResultContentSchema.parse({
|
|
102
|
+
schemaVersion: "openpond.evaluationResult.v1",
|
|
103
|
+
id: input.id,
|
|
104
|
+
runManifest: { id: input.manifest.id, contentHash: input.manifest.contentHash },
|
|
105
|
+
harnessRelease: input.manifest.harnessRelease,
|
|
106
|
+
tasksetRelease: input.manifest.tasksetRelease,
|
|
107
|
+
model: input.manifest.model,
|
|
108
|
+
receiptRefs: input.receipts.map((receipt) => ({ id: receipt.id, contentHash: receipt.contentHash })),
|
|
109
|
+
attemptCount: input.receipts.length,
|
|
110
|
+
rewardEligibleCount: input.receipts.filter((receipt) => receipt.metadata.rewardEligible === true && receipt.failureClass !== "infrastructure_failure").length,
|
|
111
|
+
terminalCount: input.receipts.filter((receipt) => receipt.terminal).length,
|
|
112
|
+
meanScore: scores.length ? scores.reduce((total, score) => total + score, 0) / scores.length : null,
|
|
113
|
+
failureCounts,
|
|
114
|
+
metadata: input.metadata ?? {},
|
|
115
|
+
});
|
|
116
|
+
return EvaluationResultSchema.parse({ ...content, contentHash: contentHash(content) });
|
|
117
|
+
}
|
|
118
|
+
export function assertComparableRunManifests(base, candidate) {
|
|
119
|
+
if (base.harnessRelease.contentHash !== candidate.harnessRelease.contentHash) {
|
|
120
|
+
throw new Error("Evaluation runs use different Harness Releases.");
|
|
121
|
+
}
|
|
122
|
+
if (base.tasksetRelease.contentHash !== candidate.tasksetRelease.contentHash) {
|
|
123
|
+
throw new Error("Evaluation runs use different Taskset Releases.");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
export function rewardEligibleReceipts(receipts) {
|
|
127
|
+
return receipts.filter((receipt) => receipt.terminal
|
|
128
|
+
&& receipt.failureClass !== "infrastructure_failure"
|
|
129
|
+
&& receipt.failureClass !== "timeout"
|
|
130
|
+
&& receipt.failureClass !== "cancelled"
|
|
131
|
+
&& receipt.metadata.rewardEligible === true
|
|
132
|
+
&& typeof receipt.metadata.score === "number");
|
|
133
|
+
}
|
package/dist/sha256.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
// FIPS 180-4 SHA-256 implemented over platform-neutral typed arrays so the
|
|
2
|
+
// portable contracts keep the same synchronous content-hash API in any host.
|
|
3
|
+
const INITIAL_STATE = new Uint32Array([
|
|
4
|
+
0x6a09e667,
|
|
5
|
+
0xbb67ae85,
|
|
6
|
+
0x3c6ef372,
|
|
7
|
+
0xa54ff53a,
|
|
8
|
+
0x510e527f,
|
|
9
|
+
0x9b05688c,
|
|
10
|
+
0x1f83d9ab,
|
|
11
|
+
0x5be0cd19,
|
|
12
|
+
]);
|
|
13
|
+
const ROUND_CONSTANTS = new Uint32Array([
|
|
14
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
|
|
15
|
+
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
|
16
|
+
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
|
17
|
+
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
|
18
|
+
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
|
|
19
|
+
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
20
|
+
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
|
|
21
|
+
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
22
|
+
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
23
|
+
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
24
|
+
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
|
|
25
|
+
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
26
|
+
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
|
|
27
|
+
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
28
|
+
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
|
29
|
+
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
30
|
+
]);
|
|
31
|
+
export function sha256Hex(value) {
|
|
32
|
+
const bytes = typeof value === "string" ? new TextEncoder().encode(value) : value;
|
|
33
|
+
const paddedLength = Math.ceil((bytes.byteLength + 9) / 64) * 64;
|
|
34
|
+
const padded = new Uint8Array(paddedLength);
|
|
35
|
+
padded.set(bytes);
|
|
36
|
+
padded[bytes.byteLength] = 0x80;
|
|
37
|
+
const bitLength = bytes.byteLength * 8;
|
|
38
|
+
const view = new DataView(padded.buffer);
|
|
39
|
+
view.setUint32(paddedLength - 8, Math.floor(bitLength / 0x1_0000_0000), false);
|
|
40
|
+
view.setUint32(paddedLength - 4, bitLength >>> 0, false);
|
|
41
|
+
const state = new Uint32Array(INITIAL_STATE);
|
|
42
|
+
const words = new Uint32Array(64);
|
|
43
|
+
for (let offset = 0; offset < paddedLength; offset += 64) {
|
|
44
|
+
for (let index = 0; index < 16; index += 1) {
|
|
45
|
+
words[index] = view.getUint32(offset + index * 4, false);
|
|
46
|
+
}
|
|
47
|
+
for (let index = 16; index < 64; index += 1) {
|
|
48
|
+
const previous = words[index - 15];
|
|
49
|
+
const recent = words[index - 2];
|
|
50
|
+
const sigma0 = rotateRight(previous, 7) ^ rotateRight(previous, 18) ^ (previous >>> 3);
|
|
51
|
+
const sigma1 = rotateRight(recent, 17) ^ rotateRight(recent, 19) ^ (recent >>> 10);
|
|
52
|
+
words[index] = (words[index - 16] + sigma0 + words[index - 7] + sigma1) >>> 0;
|
|
53
|
+
}
|
|
54
|
+
let a = state[0];
|
|
55
|
+
let b = state[1];
|
|
56
|
+
let c = state[2];
|
|
57
|
+
let d = state[3];
|
|
58
|
+
let e = state[4];
|
|
59
|
+
let f = state[5];
|
|
60
|
+
let g = state[6];
|
|
61
|
+
let h = state[7];
|
|
62
|
+
for (let index = 0; index < 64; index += 1) {
|
|
63
|
+
const choice = (e & f) ^ (~e & g);
|
|
64
|
+
const majority = (a & b) ^ (a & c) ^ (b & c);
|
|
65
|
+
const sum0 = rotateRight(a, 2) ^ rotateRight(a, 13) ^ rotateRight(a, 22);
|
|
66
|
+
const sum1 = rotateRight(e, 6) ^ rotateRight(e, 11) ^ rotateRight(e, 25);
|
|
67
|
+
const first = (h + sum1 + choice + ROUND_CONSTANTS[index] + words[index]) >>> 0;
|
|
68
|
+
const second = (sum0 + majority) >>> 0;
|
|
69
|
+
h = g;
|
|
70
|
+
g = f;
|
|
71
|
+
f = e;
|
|
72
|
+
e = (d + first) >>> 0;
|
|
73
|
+
d = c;
|
|
74
|
+
c = b;
|
|
75
|
+
b = a;
|
|
76
|
+
a = (first + second) >>> 0;
|
|
77
|
+
}
|
|
78
|
+
state[0] = (state[0] + a) >>> 0;
|
|
79
|
+
state[1] = (state[1] + b) >>> 0;
|
|
80
|
+
state[2] = (state[2] + c) >>> 0;
|
|
81
|
+
state[3] = (state[3] + d) >>> 0;
|
|
82
|
+
state[4] = (state[4] + e) >>> 0;
|
|
83
|
+
state[5] = (state[5] + f) >>> 0;
|
|
84
|
+
state[6] = (state[6] + g) >>> 0;
|
|
85
|
+
state[7] = (state[7] + h) >>> 0;
|
|
86
|
+
}
|
|
87
|
+
return Array.from(state, (word) => word.toString(16).padStart(8, "0")).join("");
|
|
88
|
+
}
|
|
89
|
+
function rotateRight(value, bits) {
|
|
90
|
+
return (value >>> bits) | (value << (32 - bits));
|
|
91
|
+
}
|
package/dist/tasksets.js
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { ImmutableAssetRefSchema, ImmutableReleaseRefSchema, MetadataSchema, ReleaseHashSchema, ReleaseIdSchema, assertContentHash, contentHash, } from "./common.js";
|
|
3
|
+
export const TaskSplitSchema = z.enum(["train", "validation", "test", "frozen_eval"]);
|
|
4
|
+
export const PolicyBoundarySchema = z.object({
|
|
5
|
+
policyVisibleFields: z.array(ReleaseIdSchema).max(1_000).default([]),
|
|
6
|
+
privilegedFields: z.array(ReleaseIdSchema).max(1_000).default([]),
|
|
7
|
+
hiddenGraderRefs: z.array(ReleaseIdSchema).max(1_000).default([]),
|
|
8
|
+
connectedAppScopes: z.array(ReleaseIdSchema).max(100).default([]),
|
|
9
|
+
}).strict();
|
|
10
|
+
export const ToolDeclarationSchema = z.object({
|
|
11
|
+
name: z.string().trim().min(1).max(64).regex(/^[a-zA-Z][a-zA-Z0-9_-]*$/),
|
|
12
|
+
description: z.string().trim().min(1).max(2_000),
|
|
13
|
+
inputSchema: z.record(z.string(), z.unknown()),
|
|
14
|
+
inputSchemaHash: ReleaseHashSchema,
|
|
15
|
+
sideEffect: z.enum(["read", "write"]),
|
|
16
|
+
timeoutMs: z.number().int().positive().max(3_600_000),
|
|
17
|
+
}).strict();
|
|
18
|
+
export const CapabilityRequirementSchema = z.object({
|
|
19
|
+
id: ReleaseIdSchema,
|
|
20
|
+
required: z.boolean(),
|
|
21
|
+
scopes: z.array(z.string().trim().min(1).max(500)).max(100).default([]),
|
|
22
|
+
portability: z.enum(["portable", "host_adapter", "local_only", "hosted_only"]),
|
|
23
|
+
}).strict();
|
|
24
|
+
export const EnvironmentContractSchema = z.object({
|
|
25
|
+
protocolVersion: z.literal("openpond.environment.v1"),
|
|
26
|
+
kind: z.enum(["text", "agent", "work", "custom_program"]),
|
|
27
|
+
entrypoint: z.string().trim().min(1).max(1_000),
|
|
28
|
+
stateful: z.boolean(),
|
|
29
|
+
deterministicSeeds: z.boolean(),
|
|
30
|
+
lifecycle: z.array(z.enum(["create", "reset", "step", "collect", "destroy"])).min(5).max(5),
|
|
31
|
+
networkPolicy: z.enum(["none", "declared_read_only", "declared_scoped"]),
|
|
32
|
+
defaultTimeoutMs: z.number().int().positive().max(3_600_000),
|
|
33
|
+
}).strict();
|
|
34
|
+
const GraderBaseSchema = z.object({
|
|
35
|
+
id: ReleaseIdSchema,
|
|
36
|
+
version: z.string().trim().min(1).max(100),
|
|
37
|
+
weight: z.number().nonnegative().max(1_000).default(1),
|
|
38
|
+
hardGate: z.boolean().default(false),
|
|
39
|
+
rewardEligible: z.boolean().default(false),
|
|
40
|
+
privileged: z.boolean().default(false),
|
|
41
|
+
});
|
|
42
|
+
export const DeterministicGraderSpecSchema = GraderBaseSchema.extend({
|
|
43
|
+
kind: z.enum(["content", "schema", "artifact", "runtime_event", "state"]),
|
|
44
|
+
config: z.record(z.string(), z.unknown()),
|
|
45
|
+
}).strict();
|
|
46
|
+
export const ModelJudgeGraderSpecSchema = GraderBaseSchema.extend({
|
|
47
|
+
kind: z.literal("model_judge"),
|
|
48
|
+
rubricRef: ImmutableAssetRefSchema,
|
|
49
|
+
calibrationStatus: z.enum(["pending", "passed", "failed"]),
|
|
50
|
+
}).strict();
|
|
51
|
+
export const CustomVerifierGraderSpecSchema = GraderBaseSchema.extend({
|
|
52
|
+
kind: z.literal("custom_verifier"),
|
|
53
|
+
verifierRef: ImmutableAssetRefSchema,
|
|
54
|
+
timeoutMs: z.number().int().positive().max(300_000),
|
|
55
|
+
networkPolicy: z.literal("none"),
|
|
56
|
+
}).strict();
|
|
57
|
+
export const HumanGraderSpecSchema = GraderBaseSchema.extend({
|
|
58
|
+
kind: z.literal("human"),
|
|
59
|
+
rubricRef: ImmutableAssetRefSchema,
|
|
60
|
+
reviewerRole: z.string().trim().min(1).max(500),
|
|
61
|
+
}).strict();
|
|
62
|
+
export const GraderSpecSchema = z.union([
|
|
63
|
+
DeterministicGraderSpecSchema,
|
|
64
|
+
ModelJudgeGraderSpecSchema,
|
|
65
|
+
CustomVerifierGraderSpecSchema,
|
|
66
|
+
HumanGraderSpecSchema,
|
|
67
|
+
]);
|
|
68
|
+
export const TaskRecordSchema = z.object({
|
|
69
|
+
id: ReleaseIdSchema,
|
|
70
|
+
clusterKey: ReleaseIdSchema,
|
|
71
|
+
split: TaskSplitSchema,
|
|
72
|
+
input: z.record(z.string(), z.unknown()),
|
|
73
|
+
expectedOutput: z.record(z.string(), z.unknown()).nullable(),
|
|
74
|
+
policyVisibleContext: z.record(z.string(), z.unknown()).default({}),
|
|
75
|
+
privilegedContextRef: ReleaseIdSchema.nullable(),
|
|
76
|
+
artifactRefs: z.array(ImmutableAssetRefSchema).max(1_000).default([]),
|
|
77
|
+
tags: z.array(ReleaseIdSchema).max(100).default([]),
|
|
78
|
+
}).strict();
|
|
79
|
+
export const TasksetReleaseContentSchema = z.object({
|
|
80
|
+
schemaVersion: z.literal("openpond.tasksetRelease.v1"),
|
|
81
|
+
id: ReleaseIdSchema,
|
|
82
|
+
revision: z.number().int().positive(),
|
|
83
|
+
harnessRelease: ImmutableReleaseRefSchema,
|
|
84
|
+
policy: PolicyBoundarySchema,
|
|
85
|
+
environment: EnvironmentContractSchema,
|
|
86
|
+
tools: z.array(ToolDeclarationSchema).max(200),
|
|
87
|
+
capabilities: z.array(CapabilityRequirementSchema).max(200),
|
|
88
|
+
tasks: z.array(TaskRecordSchema).min(1).max(1_000_000),
|
|
89
|
+
graders: z.array(GraderSpecSchema).min(1).max(1_000),
|
|
90
|
+
metadata: MetadataSchema,
|
|
91
|
+
}).strict();
|
|
92
|
+
export const TasksetReleaseSchema = TasksetReleaseContentSchema.extend({ contentHash: ReleaseHashSchema }).strict();
|
|
93
|
+
export function validateTasksetRelease(input) {
|
|
94
|
+
const parsed = TasksetReleaseSchema.safeParse(input);
|
|
95
|
+
if (!parsed.success) {
|
|
96
|
+
return {
|
|
97
|
+
valid: false,
|
|
98
|
+
taskset: null,
|
|
99
|
+
computedHash: null,
|
|
100
|
+
issues: parsed.error.issues.map((issue) => ({
|
|
101
|
+
code: "schema_invalid",
|
|
102
|
+
severity: "error",
|
|
103
|
+
message: issue.message,
|
|
104
|
+
path: issue.path.join("."),
|
|
105
|
+
})),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
const taskset = parsed.data;
|
|
109
|
+
const issues = [];
|
|
110
|
+
const clusterSplits = new Map();
|
|
111
|
+
for (const task of taskset.tasks) {
|
|
112
|
+
const splits = clusterSplits.get(task.clusterKey) ?? new Set();
|
|
113
|
+
splits.add(task.split);
|
|
114
|
+
clusterSplits.set(task.clusterKey, splits);
|
|
115
|
+
}
|
|
116
|
+
for (const [cluster, splits] of clusterSplits) {
|
|
117
|
+
if (splits.size > 1)
|
|
118
|
+
issues.push({
|
|
119
|
+
code: "split_cluster_contamination",
|
|
120
|
+
severity: "error",
|
|
121
|
+
message: `Source cluster ${cluster} appears in multiple splits.`,
|
|
122
|
+
path: "tasks",
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (!taskset.tasks.some((task) => task.split === "frozen_eval"))
|
|
126
|
+
issues.push({
|
|
127
|
+
code: "frozen_eval_missing",
|
|
128
|
+
severity: "warning",
|
|
129
|
+
message: "The release has no frozen-evaluation task.",
|
|
130
|
+
path: "tasks",
|
|
131
|
+
});
|
|
132
|
+
const { contentHash: _contentHash, ...tasksetContent } = taskset;
|
|
133
|
+
const computedHash = contentHash(TasksetReleaseContentSchema.parse(tasksetContent));
|
|
134
|
+
if (computedHash !== taskset.contentHash)
|
|
135
|
+
issues.push({
|
|
136
|
+
code: "content_hash_mismatch",
|
|
137
|
+
severity: "error",
|
|
138
|
+
message: `Taskset contentHash is ${taskset.contentHash}; expected ${computedHash}.`,
|
|
139
|
+
path: "contentHash",
|
|
140
|
+
});
|
|
141
|
+
return { valid: !issues.some((issue) => issue.severity === "error"), taskset, computedHash, issues };
|
|
142
|
+
}
|
|
143
|
+
export function assertTasksetRelease(taskset) {
|
|
144
|
+
assertContentHash(taskset, "Taskset release");
|
|
145
|
+
const report = validateTasksetRelease(taskset);
|
|
146
|
+
const error = report.issues.find((issue) => issue.severity === "error");
|
|
147
|
+
if (error)
|
|
148
|
+
throw new Error(error.message);
|
|
149
|
+
}
|
|
150
|
+
export function policyTaskView(task) {
|
|
151
|
+
return {
|
|
152
|
+
id: task.id,
|
|
153
|
+
input: structuredClone(task.input),
|
|
154
|
+
policyVisibleContext: structuredClone(task.policyVisibleContext),
|
|
155
|
+
artifactRefs: task.artifactRefs.filter((artifact) => artifact.visibility === "policy"),
|
|
156
|
+
tags: [...task.tags],
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
export function trainingPolicyTaskViews(taskset) {
|
|
160
|
+
return taskset.tasks
|
|
161
|
+
.filter((task) => task.split !== "frozen_eval")
|
|
162
|
+
.map(policyTaskView);
|
|
163
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const MAX_PORTABLE_PATH_BYTES = 2000;
|
|
3
|
+
export declare const MAX_PORTABLE_ASSET_BYTES = 250000000;
|
|
4
|
+
export declare const ReleaseIdSchema: z.ZodString;
|
|
5
|
+
export declare const ReleaseHashSchema: z.ZodString;
|
|
6
|
+
export declare const ReleaseTimestampSchema: z.ZodString;
|
|
7
|
+
export declare const MetadataSchema: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
8
|
+
export declare const ImmutableReleaseRefSchema: z.ZodObject<{
|
|
9
|
+
id: z.ZodString;
|
|
10
|
+
contentHash: z.ZodString;
|
|
11
|
+
}, z.core.$strict>;
|
|
12
|
+
export declare const ImmutableAssetRefSchema: z.ZodObject<{
|
|
13
|
+
id: z.ZodString;
|
|
14
|
+
path: z.ZodString;
|
|
15
|
+
contentHash: z.ZodString;
|
|
16
|
+
sizeBytes: z.ZodNumber;
|
|
17
|
+
mediaType: z.ZodString;
|
|
18
|
+
visibility: z.ZodEnum<{
|
|
19
|
+
policy: "policy";
|
|
20
|
+
verifier: "verifier";
|
|
21
|
+
host_private: "host_private";
|
|
22
|
+
}>;
|
|
23
|
+
}, z.core.$strict>;
|
|
24
|
+
export declare const ImmutableArtifactRefSchema: z.ZodObject<{
|
|
25
|
+
id: z.ZodString;
|
|
26
|
+
contentHash: z.ZodString;
|
|
27
|
+
mediaType: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
28
|
+
sizeBytes: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
|
|
29
|
+
}, z.core.$strict>;
|
|
30
|
+
export declare const FailureClassSchema: z.ZodEnum<{
|
|
31
|
+
policy_failure: "policy_failure";
|
|
32
|
+
grader_failure: "grader_failure";
|
|
33
|
+
environment_failure: "environment_failure";
|
|
34
|
+
infrastructure_failure: "infrastructure_failure";
|
|
35
|
+
timeout: "timeout";
|
|
36
|
+
cancelled: "cancelled";
|
|
37
|
+
}>;
|
|
38
|
+
export declare function canonicalJson(value: unknown): string;
|
|
39
|
+
export declare function sha256(value: string | Uint8Array): string;
|
|
40
|
+
export declare function contentHash(value: unknown): string;
|
|
41
|
+
export declare function withContentHash<T extends Record<string, unknown>>(value: T): T & {
|
|
42
|
+
contentHash: string;
|
|
43
|
+
};
|
|
44
|
+
export declare function assertContentHash(value: {
|
|
45
|
+
contentHash: string;
|
|
46
|
+
} & Record<string, unknown>, label: string): void;
|
|
47
|
+
export type ImmutableReleaseRef = z.infer<typeof ImmutableReleaseRefSchema>;
|
|
48
|
+
export type ImmutableAssetRef = z.infer<typeof ImmutableAssetRefSchema>;
|
|
49
|
+
export type ImmutableArtifactRef = z.infer<typeof ImmutableArtifactRefSchema>;
|
|
50
|
+
export type FailureClass = z.infer<typeof FailureClassSchema>;
|
|
51
|
+
//# sourceMappingURL=common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../src/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,uBAAuB,OAAQ,CAAC;AAC7C,eAAO,MAAM,wBAAwB,YAAc,CAAC;AACpD,eAAO,MAAM,eAAe,aAAoC,CAAC;AACjE,eAAO,MAAM,iBAAiB,aAAqC,CAAC;AACpE,eAAO,MAAM,sBAAsB,aAAwC,CAAC;AAC5E,eAAO,MAAM,cAAc,sDAAgD,CAAC;AAE5E,eAAO,MAAM,yBAAyB;;;kBAG3B,CAAC;AAEZ,eAAO,MAAM,uBAAuB;;;;;;;;;;;kBAOzB,CAAC;AAEZ,eAAO,MAAM,0BAA0B;;;;;kBAK5B,CAAC;AAEZ,eAAO,MAAM,kBAAkB;;;;;;;EAO7B,CAAC;AAEH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAEzD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAElD;AAED,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,CAExG;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAI/G;AAkBD,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAC5E,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACxE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
|