@openpond/evals 0.1.0 → 0.2.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.
@@ -0,0 +1,407 @@
1
+ import { z } from "zod";
2
+ import { ImmutableArtifactRefSchema, ImmutableReleaseRefSchema, ReleaseHashSchema, ReleaseIdSchema, ReleaseTimestampSchema, contentHash, } from "../common.js";
3
+ import { ModelRefSchema } from "../runs.js";
4
+ export const WORK_EVIDENCE_SCHEMA_VERSION = "openpond.workEvidenceReceipt.v1";
5
+ export const WORK_PROCESS_TRACE_SCHEMA_VERSION = "openpond.workProcessTrace.v1";
6
+ export const WORK_FEEDBACK_SCHEMA_VERSION = "openpond.workFeedbackReceipt.v1";
7
+ export const WORK_EVIDENCE_ELIGIBILITY_SCHEMA_VERSION = "openpond.workEvidenceEligibility.v1";
8
+ export const WorkSourceOpaqueRefSchema = z.string().regex(/^urn:openpond:work:[a-f0-9]{64}$/, "Work source references must be opaque SHA-256 URNs.");
9
+ export const WorkWorkspaceOpaqueRefSchema = z.string().regex(/^urn:openpond:workspace:[a-f0-9]{64}$/, "Workspace references must be opaque SHA-256 URNs.");
10
+ export const EvidenceArtifactIdSchema = z.string().regex(/^urn:openpond:artifact:[a-f0-9]{64}$/, "Evidence artifacts must use content-addressed SHA-256 URNs.");
11
+ export const EvidenceArtifactRefSchema = ImmutableArtifactRefSchema.extend({
12
+ id: EvidenceArtifactIdSchema,
13
+ }).strict().superRefine((artifact, context) => {
14
+ if (artifact.id !== evidenceArtifactId(artifact.contentHash)) {
15
+ context.addIssue({
16
+ code: "custom",
17
+ message: "Evidence artifact id must contain its content hash.",
18
+ path: ["id"],
19
+ });
20
+ }
21
+ });
22
+ export const WorkProcessStepKindSchema = z.enum([
23
+ "tool",
24
+ "validation",
25
+ "state_transition",
26
+ "approval",
27
+ "question",
28
+ "artifact",
29
+ "cleanup",
30
+ ]);
31
+ export const WorkProcessLayerSchema = z.enum(["agent", "environment"]);
32
+ export const WorkProcessActionSchema = z.enum([
33
+ "turn_started",
34
+ "turn_completed",
35
+ "turn_failed",
36
+ "turn_cancelled",
37
+ "turn_timed_out",
38
+ "tool_invoked",
39
+ "tool_completed",
40
+ "tool_failed",
41
+ "validation_completed",
42
+ "validation_failed",
43
+ "approval_requested",
44
+ "approval_resolved",
45
+ "question_asked",
46
+ "question_answered",
47
+ "question_dismissed",
48
+ "artifact_created",
49
+ "workspace_changed",
50
+ "environment_created",
51
+ "environment_reset",
52
+ "environment_destroyed",
53
+ "cleanup_completed",
54
+ "cleanup_failed",
55
+ ]);
56
+ export const WorkProcessStepStatusSchema = z.enum([
57
+ "started",
58
+ "completed",
59
+ "failed",
60
+ "cancelled",
61
+ ]);
62
+ export const WorkToolCategorySchema = z.enum([
63
+ "filesystem",
64
+ "source_control",
65
+ "command",
66
+ "browser",
67
+ "connected_app",
68
+ "sandbox",
69
+ "agent",
70
+ "other",
71
+ ]);
72
+ export const WorkValidationKindSchema = z.enum([
73
+ "structural",
74
+ "visual",
75
+ "test",
76
+ "user_review",
77
+ "other",
78
+ ]);
79
+ export const WorkTransitionStateSchema = z.enum([
80
+ "running",
81
+ "completed",
82
+ "failed",
83
+ "cancelled",
84
+ "timeout",
85
+ ]);
86
+ export const WorkInterventionOutcomeSchema = z.enum([
87
+ "requested",
88
+ "approved",
89
+ "denied",
90
+ "answered",
91
+ "dismissed",
92
+ ]);
93
+ export const WorkProcessErrorClassSchema = z.enum([
94
+ "policy",
95
+ "validation",
96
+ "environment",
97
+ "infrastructure",
98
+ "timeout",
99
+ "cancelled",
100
+ "unknown",
101
+ ]);
102
+ export const WorkTraceIncompleteReasonSchema = z.enum([
103
+ "missing_start",
104
+ "missing_terminal",
105
+ "source_truncated",
106
+ "unsupported_events_dropped",
107
+ "uncorrelated_environment_step",
108
+ "artifact_unavailable",
109
+ ]);
110
+ export const WorkProcessStepSchema = z.object({
111
+ sequence: z.number().int().nonnegative().max(1_000_000),
112
+ timestamp: ReleaseTimestampSchema,
113
+ layer: WorkProcessLayerSchema,
114
+ kind: WorkProcessStepKindSchema,
115
+ action: WorkProcessActionSchema,
116
+ status: WorkProcessStepStatusSchema,
117
+ inputHash: ReleaseHashSchema.nullable(),
118
+ outputHash: ReleaseHashSchema.nullable(),
119
+ receiptHash: ReleaseHashSchema.nullable(),
120
+ parentReceiptHash: ReleaseHashSchema.nullable(),
121
+ artifactRefs: z.array(EvidenceArtifactRefSchema).max(1_000),
122
+ attributes: z.object({
123
+ toolCategory: WorkToolCategorySchema.nullable(),
124
+ validationKind: WorkValidationKindSchema.nullable(),
125
+ transitionState: WorkTransitionStateSchema.nullable(),
126
+ interventionOutcome: WorkInterventionOutcomeSchema.nullable(),
127
+ artifactCount: z.number().int().nonnegative().max(100_000),
128
+ exitCode: z.number().int().min(-1).max(255).nullable(),
129
+ durationMs: z.number().int().nonnegative().max(31_536_000_000).nullable(),
130
+ cpuTimeMs: z.number().int().nonnegative().max(31_536_000_000).nullable(),
131
+ memoryPeakBytes: z.number().int().nonnegative().max(1_125_899_906_842_624).nullable(),
132
+ errorClass: WorkProcessErrorClassSchema.nullable(),
133
+ }).strict(),
134
+ }).strict().superRefine((step, context) => {
135
+ if (step.layer === "agent" && step.parentReceiptHash !== null) {
136
+ context.addIssue({
137
+ code: "custom",
138
+ message: "Agent-layer steps cannot have a parent environment correlation.",
139
+ path: ["parentReceiptHash"],
140
+ });
141
+ }
142
+ if (step.layer === "environment" && step.parentReceiptHash === null) {
143
+ context.addIssue({
144
+ code: "custom",
145
+ message: "Environment steps must correlate to an Agent receipt.",
146
+ path: ["parentReceiptHash"],
147
+ });
148
+ }
149
+ });
150
+ export const WorkProcessTraceContentSchema = z.object({
151
+ schemaVersion: z.literal(WORK_PROCESS_TRACE_SCHEMA_VERSION),
152
+ sourceRevisionHash: ReleaseHashSchema,
153
+ sanitationPolicyVersion: ReleaseIdSchema,
154
+ incomplete: z.boolean(),
155
+ incompleteReasons: z.array(WorkTraceIncompleteReasonSchema).max(10),
156
+ droppedEventCount: z.number().int().nonnegative().max(1_000_000),
157
+ steps: z.array(WorkProcessStepSchema).max(100_000),
158
+ }).strict().superRefine((trace, context) => {
159
+ if (trace.incomplete !== (trace.incompleteReasons.length > 0)) {
160
+ context.addIssue({
161
+ code: "custom",
162
+ message: "incomplete must match the presence of incompleteReasons.",
163
+ path: ["incomplete"],
164
+ });
165
+ }
166
+ for (let index = 0; index < trace.steps.length; index += 1) {
167
+ if (trace.steps[index].sequence !== index) {
168
+ context.addIssue({
169
+ code: "custom",
170
+ message: "Process trace sequences must be contiguous and zero-based.",
171
+ path: ["steps", index, "sequence"],
172
+ });
173
+ }
174
+ }
175
+ });
176
+ export const WorkProcessTraceSchema = WorkProcessTraceContentSchema.safeExtend({
177
+ contentHash: ReleaseHashSchema,
178
+ }).strict();
179
+ export const WorkFailureClassSchema = z.enum([
180
+ "policy_failure",
181
+ "validation_failure",
182
+ "model_failure",
183
+ "environment_failure",
184
+ "infrastructure_failure",
185
+ "timeout",
186
+ "cancelled",
187
+ "unknown",
188
+ ]);
189
+ export const WorkTerminalSchema = z.object({
190
+ status: z.enum(["completed", "failed", "cancelled", "timeout"]),
191
+ failureClass: WorkFailureClassSchema.nullable(),
192
+ }).strict().superRefine((terminal, context) => {
193
+ if (terminal.status === "completed" && terminal.failureClass !== null) {
194
+ context.addIssue({ code: "custom", message: "Completed Work cannot carry a failure class.", path: ["failureClass"] });
195
+ }
196
+ if (terminal.status !== "completed" && terminal.failureClass === null) {
197
+ context.addIssue({ code: "custom", message: "Non-completed Work requires a failure class.", path: ["failureClass"] });
198
+ }
199
+ if (terminal.status === "cancelled" && terminal.failureClass !== "cancelled") {
200
+ context.addIssue({ code: "custom", message: "Cancelled Work must use the cancelled failure class.", path: ["failureClass"] });
201
+ }
202
+ if (terminal.status === "timeout" && terminal.failureClass !== "timeout") {
203
+ context.addIssue({ code: "custom", message: "Timed-out Work must use the timeout failure class.", path: ["failureClass"] });
204
+ }
205
+ });
206
+ export const WorkEvidenceReceiptContentSchema = z.object({
207
+ schemaVersion: z.literal(WORK_EVIDENCE_SCHEMA_VERSION),
208
+ id: z.string().regex(/^work-evidence-[a-f0-9]{24}$/),
209
+ source: z.object({
210
+ surface: z.enum(["desktop", "hosted"]),
211
+ experience: z.enum(["work", "development"]),
212
+ opaqueRef: WorkSourceOpaqueRefSchema,
213
+ revisionHash: ReleaseHashSchema,
214
+ }).strict(),
215
+ agentSnapshot: ImmutableReleaseRefSchema.nullable(),
216
+ model: ModelRefSchema,
217
+ runtime: z.object({
218
+ adapterId: ReleaseIdSchema,
219
+ adapterVersion: ReleaseIdSchema,
220
+ capabilityRef: EvidenceArtifactRefSchema.nullable(),
221
+ }).strict(),
222
+ inputHash: ReleaseHashSchema,
223
+ terminal: WorkTerminalSchema,
224
+ trace: z.object({
225
+ sanitizedRef: EvidenceArtifactRefSchema,
226
+ traceHash: ReleaseHashSchema,
227
+ sanitationPolicyVersion: ReleaseIdSchema,
228
+ incomplete: z.boolean(),
229
+ }).strict(),
230
+ outputRefs: z.array(EvidenceArtifactRefSchema).max(10_000),
231
+ artifactRefs: z.array(EvidenceArtifactRefSchema).max(100_000),
232
+ validationEvidenceRefs: z.array(EvidenceArtifactRefSchema).max(10_000),
233
+ interventions: z.object({
234
+ approvals: z.number().int().nonnegative().max(1_000_000),
235
+ questions: z.number().int().nonnegative().max(1_000_000),
236
+ steeringEvents: z.number().int().nonnegative().max(1_000_000),
237
+ otherUserInterventions: z.number().int().nonnegative().max(1_000_000),
238
+ }).strict(),
239
+ timing: z.object({
240
+ startedAt: ReleaseTimestampSchema,
241
+ completedAt: ReleaseTimestampSchema,
242
+ latencyMs: z.number().int().nonnegative().max(31_536_000_000),
243
+ }).strict(),
244
+ usage: z.object({
245
+ promptTokens: z.number().int().nonnegative().nullable(),
246
+ completionTokens: z.number().int().nonnegative().nullable(),
247
+ totalTokens: z.number().int().nonnegative().nullable(),
248
+ }).strict(),
249
+ costUsd: z.number().nonnegative().max(1_000_000).nullable(),
250
+ provenance: z.object({
251
+ consentReceiptRef: EvidenceArtifactRefSchema,
252
+ consentScope: z.literal("work_process_and_artifacts"),
253
+ consentGrantedAt: ReleaseTimestampSchema,
254
+ policyVersion: ReleaseIdSchema,
255
+ projectorVersion: ReleaseIdSchema,
256
+ disclosure: z.literal("portable_sanitized"),
257
+ ownershipScope: z.enum(["personal", "workspace"]),
258
+ workspaceRef: WorkWorkspaceOpaqueRefSchema.nullable(),
259
+ participantPolicy: z.enum(["creator_only", "all_participants"]),
260
+ retention: z.object({
261
+ policy: z.literal("source_bound"),
262
+ deleteWithSource: z.literal(true),
263
+ expiresAt: ReleaseTimestampSchema.nullable(),
264
+ }).strict(),
265
+ }).strict(),
266
+ }).strict().superRefine((receipt, context) => {
267
+ if (receipt.trace.traceHash !== receipt.trace.sanitizedRef.contentHash) {
268
+ context.addIssue({
269
+ code: "custom",
270
+ message: "Sanitized trace reference must bind traceHash.",
271
+ path: ["trace", "traceHash"],
272
+ });
273
+ }
274
+ const elapsed = Date.parse(receipt.timing.completedAt) - Date.parse(receipt.timing.startedAt);
275
+ if (elapsed < 0 || elapsed !== receipt.timing.latencyMs) {
276
+ context.addIssue({
277
+ code: "custom",
278
+ message: "latencyMs must equal completedAt minus startedAt.",
279
+ path: ["timing", "latencyMs"],
280
+ });
281
+ }
282
+ if (receipt.provenance.ownershipScope === "workspace" && receipt.provenance.workspaceRef === null) {
283
+ context.addIssue({ code: "custom", message: "Workspace-owned evidence requires workspaceRef.", path: ["provenance", "workspaceRef"] });
284
+ }
285
+ if (receipt.provenance.ownershipScope === "personal" && receipt.provenance.workspaceRef !== null) {
286
+ context.addIssue({ code: "custom", message: "Personal evidence cannot carry workspaceRef.", path: ["provenance", "workspaceRef"] });
287
+ }
288
+ addDuplicateHashIssues(receipt.outputRefs, ["outputRefs"], context);
289
+ addDuplicateHashIssues(receipt.artifactRefs, ["artifactRefs"], context);
290
+ addDuplicateHashIssues(receipt.validationEvidenceRefs, ["validationEvidenceRefs"], context);
291
+ });
292
+ export const WorkEvidenceReceiptSchema = WorkEvidenceReceiptContentSchema.safeExtend({
293
+ contentHash: ReleaseHashSchema,
294
+ }).strict();
295
+ export const WorkFeedbackVerdictSchema = z.enum([
296
+ "accepted",
297
+ "needs_correction",
298
+ "not_useful",
299
+ ]);
300
+ export const WorkFeedbackReasonCodeSchema = z.enum([
301
+ "correct",
302
+ "complete",
303
+ "high_quality",
304
+ "incorrect",
305
+ "incomplete",
306
+ "wrong_format",
307
+ "unsafe",
308
+ "stale",
309
+ "irrelevant",
310
+ "other",
311
+ ]);
312
+ export const WorkFeedbackReceiptContentSchema = z.object({
313
+ schemaVersion: z.literal(WORK_FEEDBACK_SCHEMA_VERSION),
314
+ id: z.string().regex(/^work-feedback-[a-f0-9]{24}$/),
315
+ evidenceReceiptRef: EvidenceArtifactRefSchema,
316
+ outputRevisionRef: EvidenceArtifactRefSchema.nullable(),
317
+ verdict: WorkFeedbackVerdictSchema,
318
+ reasonCodes: z.array(WorkFeedbackReasonCodeSchema).max(16),
319
+ correctionRef: EvidenceArtifactRefSchema.nullable(),
320
+ correctedOutputRevisionRef: EvidenceArtifactRefSchema.nullable(),
321
+ actor: z.literal("user"),
322
+ createdAt: ReleaseTimestampSchema,
323
+ }).strict().superRefine((feedback, context) => {
324
+ if (new Set(feedback.reasonCodes).size !== feedback.reasonCodes.length) {
325
+ context.addIssue({ code: "custom", message: "Feedback reason codes must be unique.", path: ["reasonCodes"] });
326
+ }
327
+ if (feedback.verdict !== "needs_correction" && (feedback.correctionRef || feedback.correctedOutputRevisionRef)) {
328
+ context.addIssue({
329
+ code: "custom",
330
+ message: "Only needs_correction feedback may bind correction artifacts.",
331
+ path: ["verdict"],
332
+ });
333
+ }
334
+ });
335
+ export const WorkFeedbackReceiptSchema = WorkFeedbackReceiptContentSchema.safeExtend({
336
+ contentHash: ReleaseHashSchema,
337
+ }).strict();
338
+ export function evidenceArtifactId(hash) {
339
+ return `urn:openpond:artifact:${hash}`;
340
+ }
341
+ export function workSourceOpaqueRef(sourceIdentity) {
342
+ return `urn:openpond:work:${contentHash(sourceIdentity)}`;
343
+ }
344
+ export function workWorkspaceOpaqueRef(workspaceIdentity) {
345
+ return `urn:openpond:workspace:${contentHash(workspaceIdentity)}`;
346
+ }
347
+ export function evidenceArtifactRef(input) {
348
+ return EvidenceArtifactRefSchema.parse({
349
+ id: evidenceArtifactId(input.contentHash),
350
+ contentHash: input.contentHash,
351
+ mediaType: input.mediaType ?? null,
352
+ sizeBytes: input.sizeBytes ?? null,
353
+ });
354
+ }
355
+ export function createWorkProcessTrace(input) {
356
+ const trace = WorkProcessTraceContentSchema.parse(input);
357
+ return WorkProcessTraceSchema.parse({ ...trace, contentHash: contentHash(trace) });
358
+ }
359
+ export function createWorkEvidenceReceipt(input) {
360
+ const receipt = WorkEvidenceReceiptContentSchema.parse(input);
361
+ return WorkEvidenceReceiptSchema.parse({ ...receipt, contentHash: contentHash(receipt) });
362
+ }
363
+ export function createWorkFeedbackReceipt(input, evidence) {
364
+ const feedback = WorkFeedbackReceiptContentSchema.parse(input);
365
+ const receipt = WorkFeedbackReceiptSchema.parse({ ...feedback, contentHash: contentHash(feedback) });
366
+ if (evidence)
367
+ assertFeedbackTargetsEvidence(receipt, evidence);
368
+ return receipt;
369
+ }
370
+ export function verifyWorkProcessTrace(value) {
371
+ return verifyHashedValue(value, WorkProcessTraceSchema, WorkProcessTraceContentSchema);
372
+ }
373
+ export function verifyWorkEvidenceReceipt(value) {
374
+ return verifyHashedValue(value, WorkEvidenceReceiptSchema, WorkEvidenceReceiptContentSchema);
375
+ }
376
+ export function verifyWorkFeedbackReceipt(value) {
377
+ return verifyHashedValue(value, WorkFeedbackReceiptSchema, WorkFeedbackReceiptContentSchema);
378
+ }
379
+ export function workEvidenceReceiptRef(receipt) {
380
+ return evidenceArtifactRef({
381
+ contentHash: receipt.contentHash,
382
+ mediaType: "application/vnd.openpond.work-evidence+json",
383
+ sizeBytes: null,
384
+ });
385
+ }
386
+ export function assertFeedbackTargetsEvidence(feedback, evidence) {
387
+ if (feedback.evidenceReceiptRef.contentHash !== evidence.contentHash) {
388
+ throw new Error("Feedback targets a different Work evidence receipt.");
389
+ }
390
+ if (feedback.outputRevisionRef
391
+ && !evidence.outputRefs.some((output) => output.contentHash === feedback.outputRevisionRef.contentHash)) {
392
+ throw new Error("Feedback targets an output revision not bound by the Work evidence receipt.");
393
+ }
394
+ }
395
+ function verifyHashedValue(value, schema, contentSchema) {
396
+ const parsed = schema.safeParse(value);
397
+ if (!parsed.success)
398
+ return false;
399
+ const { contentHash: actual, ...content } = parsed.data;
400
+ return contentHash(contentSchema.parse(content)) === actual;
401
+ }
402
+ function addDuplicateHashIssues(artifacts, path, context) {
403
+ const hashes = artifacts.map((artifact) => artifact.contentHash);
404
+ if (new Set(hashes).size !== hashes.length) {
405
+ context.addIssue({ code: "custom", message: "Artifact content hashes must be unique.", path });
406
+ }
407
+ }
@@ -0,0 +1,168 @@
1
+ import { z } from "zod";
2
+ import { contentHash, ReleaseHashSchema } from "../common.js";
3
+ import { AttemptReceiptSchema, verifyAttemptReceipt } from "../runs.js";
4
+ import { WORK_EVIDENCE_ELIGIBILITY_SCHEMA_VERSION, WorkFeedbackReceiptSchema, createWorkFeedbackReceipt, verifyWorkEvidenceReceipt, } from "./contracts.js";
5
+ export const WorkEvidencePolicyStateSchema = z.enum([
6
+ "active",
7
+ "revoked",
8
+ "deleted",
9
+ "expired",
10
+ ]);
11
+ export const WorkEvidenceUseSchema = z.enum([
12
+ "discovery_only",
13
+ "eval_candidate",
14
+ "demonstration_candidate",
15
+ "preference_candidate",
16
+ "reward_candidate",
17
+ ]);
18
+ export const WorkEvidenceBlockerCodeSchema = z.enum([
19
+ "invalid_evidence_receipt",
20
+ "consent_revoked",
21
+ "source_deleted",
22
+ "retention_expired",
23
+ "trace_incomplete",
24
+ "terminal_not_completed",
25
+ "infrastructure_failure",
26
+ "agent_snapshot_missing",
27
+ "input_not_reconstructable",
28
+ "environment_not_reconstructable",
29
+ "output_missing",
30
+ "validation_evidence_missing",
31
+ "verifier_missing",
32
+ "accepted_feedback_missing",
33
+ "correction_pair_missing",
34
+ "attempt_receipt_missing",
35
+ "attempt_receipt_invalid",
36
+ "attempt_receipt_unbound",
37
+ "attempt_not_reward_eligible",
38
+ ]);
39
+ export const WorkEvidenceDecisionSchema = z.object({
40
+ eligible: z.boolean(),
41
+ blockers: z.array(WorkEvidenceBlockerCodeSchema).max(32),
42
+ }).strict().superRefine((decision, context) => {
43
+ if (decision.eligible === (decision.blockers.length > 0)) {
44
+ context.addIssue({ code: "custom", message: "Eligibility must be the inverse of blocker presence." });
45
+ }
46
+ });
47
+ export const WorkEvidenceEligibilityContentSchema = z.object({
48
+ schemaVersion: z.literal(WORK_EVIDENCE_ELIGIBILITY_SCHEMA_VERSION),
49
+ evidenceReceiptHash: ReleaseHashSchema,
50
+ policyState: WorkEvidencePolicyStateSchema,
51
+ decisions: z.object({
52
+ discovery_only: WorkEvidenceDecisionSchema,
53
+ eval_candidate: WorkEvidenceDecisionSchema,
54
+ demonstration_candidate: WorkEvidenceDecisionSchema,
55
+ preference_candidate: WorkEvidenceDecisionSchema,
56
+ reward_candidate: WorkEvidenceDecisionSchema,
57
+ }).strict(),
58
+ }).strict();
59
+ export const WorkEvidenceEligibilitySchema = WorkEvidenceEligibilityContentSchema.extend({
60
+ contentHash: ReleaseHashSchema,
61
+ }).strict();
62
+ export function classifyWorkEvidence(input) {
63
+ const evidenceValid = verifyWorkEvidenceReceipt(input.evidence);
64
+ const validFeedback = (input.feedback ?? []).filter((feedback) => {
65
+ if (!WorkFeedbackReceiptSchema.safeParse(feedback).success)
66
+ return false;
67
+ try {
68
+ createWorkFeedbackReceipt(withoutHash(feedback), input.evidence);
69
+ return true;
70
+ }
71
+ catch {
72
+ return false;
73
+ }
74
+ });
75
+ const policyBlockers = policyStateBlockers(input.policyState);
76
+ const discovery = [
77
+ ...(!evidenceValid ? ["invalid_evidence_receipt"] : []),
78
+ ...policyBlockers,
79
+ ];
80
+ const evaluation = [
81
+ ...discovery,
82
+ ...(input.evidence.trace.incomplete ? ["trace_incomplete"] : []),
83
+ ...(!input.evidence.agentSnapshot ? ["agent_snapshot_missing"] : []),
84
+ ...(!input.reconstructability.input ? ["input_not_reconstructable"] : []),
85
+ ...(!input.reconstructability.environment ? ["environment_not_reconstructable"] : []),
86
+ ...(!input.evidence.outputRefs.length ? ["output_missing"] : []),
87
+ ...(!input.reconstructability.verifier ? ["verifier_missing"] : []),
88
+ ];
89
+ const completed = input.evidence.terminal.status === "completed";
90
+ const accepted = validFeedback.some((feedback) => feedback.verdict === "accepted");
91
+ const demonstration = [
92
+ ...evaluation,
93
+ ...(!completed ? ["terminal_not_completed"] : []),
94
+ ...(input.evidence.terminal.failureClass === "infrastructure_failure" ? ["infrastructure_failure"] : []),
95
+ ...(!input.evidence.validationEvidenceRefs.length ? ["validation_evidence_missing"] : []),
96
+ ...(!accepted ? ["accepted_feedback_missing"] : []),
97
+ ];
98
+ const acceptedOutputs = new Set(validFeedback
99
+ .filter((feedback) => feedback.verdict === "accepted")
100
+ .flatMap((feedback) => feedback.outputRevisionRef?.contentHash ?? []));
101
+ const correctionPair = validFeedback.some((feedback) => feedback.verdict === "needs_correction"
102
+ && feedback.outputRevisionRef !== null
103
+ && feedback.correctedOutputRevisionRef !== null
104
+ && acceptedOutputs.has(feedback.correctedOutputRevisionRef.contentHash));
105
+ const preference = [
106
+ ...evaluation,
107
+ ...(!correctionPair ? ["correction_pair_missing"] : []),
108
+ ];
109
+ const replay = input.replay ?? null;
110
+ const replayParsed = replay ? AttemptReceiptSchema.safeParse(replay.attemptReceipt) : null;
111
+ const replayValid = replayParsed?.success === true && verifyAttemptReceipt(replayParsed.data);
112
+ const replayBound = replay?.sourceEvidenceReceiptHash === input.evidence.contentHash;
113
+ const replayEligible = replayValid
114
+ && replayBound
115
+ && replay.attemptReceipt.terminal
116
+ && replay.attemptReceipt.failureClass !== "infrastructure_failure"
117
+ && replay.attemptReceipt.failureClass !== "timeout"
118
+ && replay.attemptReceipt.failureClass !== "cancelled"
119
+ && replay.attemptReceipt.metadata.rewardEligible === true
120
+ && typeof replay.attemptReceipt.metadata.score === "number";
121
+ const reward = [
122
+ ...discovery,
123
+ ...(!replay ? ["attempt_receipt_missing"] : []),
124
+ ...(replay && !replayValid ? ["attempt_receipt_invalid"] : []),
125
+ ...(replay && !replayBound ? ["attempt_receipt_unbound"] : []),
126
+ ...(replay && replayValid && replayBound && !replayEligible ? ["attempt_not_reward_eligible"] : []),
127
+ ];
128
+ const report = WorkEvidenceEligibilityContentSchema.parse({
129
+ schemaVersion: WORK_EVIDENCE_ELIGIBILITY_SCHEMA_VERSION,
130
+ evidenceReceiptHash: input.evidence.contentHash,
131
+ policyState: input.policyState,
132
+ decisions: {
133
+ discovery_only: decision(discovery),
134
+ eval_candidate: decision(evaluation),
135
+ demonstration_candidate: decision(demonstration),
136
+ preference_candidate: decision(preference),
137
+ reward_candidate: decision(reward),
138
+ },
139
+ });
140
+ return WorkEvidenceEligibilitySchema.parse({ ...report, contentHash: contentHash(report) });
141
+ }
142
+ export function verifyWorkEvidenceEligibility(value) {
143
+ const parsed = WorkEvidenceEligibilitySchema.safeParse(value);
144
+ if (!parsed.success)
145
+ return false;
146
+ const { contentHash: actual, ...report } = parsed.data;
147
+ return contentHash(WorkEvidenceEligibilityContentSchema.parse(report)) === actual;
148
+ }
149
+ export function eligibleEvidenceUses(report) {
150
+ return WorkEvidenceUseSchema.options.filter((use) => report.decisions[use].eligible);
151
+ }
152
+ function policyStateBlockers(state) {
153
+ if (state === "revoked")
154
+ return ["consent_revoked"];
155
+ if (state === "deleted")
156
+ return ["source_deleted"];
157
+ if (state === "expired")
158
+ return ["retention_expired"];
159
+ return [];
160
+ }
161
+ function decision(blockers) {
162
+ const unique = [...new Set(blockers)];
163
+ return WorkEvidenceDecisionSchema.parse({ eligible: unique.length === 0, blockers: unique });
164
+ }
165
+ function withoutHash(value) {
166
+ const { contentHash: _contentHash, ...content } = value;
167
+ return content;
168
+ }
@@ -0,0 +1,4 @@
1
+ export * from "./authoring.js";
2
+ export * from "./conformance.js";
3
+ export * from "./contracts.js";
4
+ export * from "./eligibility.js";
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./common.js";
2
+ export * from "./evidence/index.js";
2
3
  export * from "./graders.js";
3
4
  export * from "./harness.js";
4
5
  export * from "./runs.js";
@@ -1 +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"}
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"}
@@ -1 +1 @@
1
- {"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../src/conformance.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAEjC,CAAC;AAEH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGxC,CAAC"}
1
+ {"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../../../src/conformance.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAEjC,CAAC;AAEH,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAGxC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { z } from "zod";
2
+ import { type WorkEvidenceReceipt } from "./contracts.js";
3
+ import { type WorkEvidenceEligibility } from "./eligibility.js";
4
+ export declare const WorkEvidenceAuthoringInputSchema: z.ZodObject<{
5
+ schemaVersion: z.ZodLiteral<"openpond.workEvidenceAuthoringInput.v1">;
6
+ evidenceReceiptRef: z.ZodObject<{
7
+ contentHash: z.ZodString;
8
+ mediaType: z.ZodDefault<z.ZodNullable<z.ZodString>>;
9
+ sizeBytes: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
10
+ id: z.ZodString;
11
+ }, z.core.$strict>;
12
+ inputHash: z.ZodString;
13
+ agentSnapshot: z.ZodNullable<z.ZodObject<{
14
+ id: z.ZodString;
15
+ contentHash: z.ZodString;
16
+ }, z.core.$strict>>;
17
+ sanitizedTraceRef: z.ZodObject<{
18
+ contentHash: z.ZodString;
19
+ mediaType: z.ZodDefault<z.ZodNullable<z.ZodString>>;
20
+ sizeBytes: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
21
+ id: z.ZodString;
22
+ }, z.core.$strict>;
23
+ outputRefs: z.ZodArray<z.ZodObject<{
24
+ contentHash: z.ZodString;
25
+ mediaType: z.ZodDefault<z.ZodNullable<z.ZodString>>;
26
+ sizeBytes: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
27
+ id: z.ZodString;
28
+ }, z.core.$strict>>;
29
+ validationEvidenceRefs: z.ZodArray<z.ZodObject<{
30
+ contentHash: z.ZodString;
31
+ mediaType: z.ZodDefault<z.ZodNullable<z.ZodString>>;
32
+ sizeBytes: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
33
+ id: z.ZodString;
34
+ }, z.core.$strict>>;
35
+ incomplete: z.ZodBoolean;
36
+ evalCandidate: z.ZodBoolean;
37
+ blockerCodes: z.ZodArray<z.ZodString>;
38
+ }, z.core.$strict>;
39
+ export declare function toWorkEvidenceAuthoringInput(evidenceInput: WorkEvidenceReceipt, eligibilityInput: WorkEvidenceEligibility): WorkEvidenceAuthoringInput;
40
+ export type WorkEvidenceAuthoringInput = z.infer<typeof WorkEvidenceAuthoringInputSchema>;
41
+ //# sourceMappingURL=authoring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authoring.d.ts","sourceRoot":"","sources":["../../../../../src/evidence/authoring.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAiC,KAAK,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE/F,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAWlC,CAAC;AAEZ,wBAAgB,4BAA4B,CAC1C,aAAa,EAAE,mBAAmB,EAClC,gBAAgB,EAAE,uBAAuB,GACxC,0BAA0B,CAuB5B;AAED,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC"}