@openpond/evals 0.9.1 → 0.9.3

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.md CHANGED
@@ -46,6 +46,13 @@ resolve credentials, or persist artifacts.
46
46
 
47
47
  ## Ordinary graders
48
48
 
49
+ `gradeTaskEvidence` returns a sealed ordinary Taskset grade with the complete
50
+ grader population, weighted score, hard gates and explicit unavailable status.
51
+ `verifyTaskGrade` checks retained results against the exact admitted task,
52
+ attempt evidence and graders, including each component hash and aggregation.
53
+ `aggregateGraderScores` provides the same policy to native grading adapters.
54
+ Ordinary grades do not require or manufacture a Reward binding.
55
+
49
56
  `evaluateDeterministicGrader` and `portableDeterministicCheck` from `/graders`
50
57
  provide the shared local/portable interpretation of ordinary checks. They retain
51
58
  explicit exact-text normalization, final-answer extraction, structured JSON,
package/dist/graders.js CHANGED
@@ -70,3 +70,73 @@ function evidence(grader, result) {
70
70
  function unavailable(message) {
71
71
  return { score: null, passed: false, rewardEligible: false, failureClass: "grader_failure", feedback: [message], visibleEvidenceRefs: [], privilegedEvidenceRefs: [] };
72
72
  }
73
+ const GradeSummarySchema = z.object({
74
+ score: z.number().min(0).max(1).nullable(), passed: z.boolean(),
75
+ rewardEligible: z.boolean(), failureClass: FailureClassSchema.nullable(),
76
+ gradingStatus: z.enum(["scored", "unscorable", "not_configured"]),
77
+ }).strict();
78
+ /** Shared ordinary grading policy. Results must match the declared population;
79
+ * missing checks cannot disappear from the denominator or the hard gates. */
80
+ export function aggregateGraderScores(input) {
81
+ const ids = new Set(input.graders.map(grader => grader.id));
82
+ if (ids.size !== input.graders.length || input.components.length !== input.graders.length)
83
+ throw new Error("Grade population differs from its declared graders.");
84
+ const components = new Map(input.components.map(item => [item.graderId, item]));
85
+ if (components.size !== input.components.length)
86
+ throw new Error("Grade population contains duplicate graders.");
87
+ let weighted = 0;
88
+ let totalWeight = 0;
89
+ let hardGateFailed = false;
90
+ let passed = true;
91
+ let eligible = false;
92
+ let unavailable = false;
93
+ let infrastructure = !!input.infrastructureError;
94
+ for (const grader of input.graders) {
95
+ const item = components.get(grader.id);
96
+ if (!item || item.graderVersion !== grader.version)
97
+ throw new Error("Grade identity differs from its declared grader.");
98
+ if (!Number.isFinite(grader.weight) || grader.weight < 0 || (item.score !== null && (!Number.isFinite(item.score) || item.score < 0 || item.score > 1)))
99
+ throw new Error("Grade scores and weights must be finite and within their declared range.");
100
+ infrastructure ||= item.failureClass === "infrastructure_failure";
101
+ unavailable ||= item.score === null || (item.failureClass !== null && item.failureClass !== "policy_failure");
102
+ hardGateFailed ||= grader.hardGate && !item.passed;
103
+ passed &&= item.passed;
104
+ eligible ||= grader.rewardEligible && item.rewardEligible;
105
+ totalWeight += grader.weight;
106
+ weighted += (item.score ?? 0) * grader.weight;
107
+ }
108
+ const score = infrastructure || unavailable || totalWeight <= 0 ? null : hardGateFailed ? 0 : weighted / totalWeight;
109
+ passed = score !== null && !hardGateFailed && passed;
110
+ return GradeSummarySchema.parse({ score, passed, rewardEligible: score !== null && eligible,
111
+ failureClass: infrastructure ? "infrastructure_failure" : score === null ? "grader_failure" : passed ? null : "policy_failure",
112
+ gradingStatus: !input.graders.length && !infrastructure ? "not_configured" : score === null ? "unscorable" : "scored" });
113
+ }
114
+ export const TaskGradeSchema = GradeSummarySchema.extend({
115
+ schemaVersion: z.literal("openpond.taskGrade.v1"),
116
+ taskHash: ReleaseHashSchema, evidenceHash: ReleaseHashSchema, graderSetHash: ReleaseHashSchema,
117
+ components: z.array(GraderEvidenceSchema).max(1_000), contentHash: ReleaseHashSchema,
118
+ }).strict();
119
+ export async function gradeTaskEvidence(input) {
120
+ const components = await gradeEvidence(input);
121
+ const content = { schemaVersion: "openpond.taskGrade.v1",
122
+ taskHash: contentHash(input.task), evidenceHash: contentHash(input.evidence), graderSetHash: contentHash(input.graders), components,
123
+ ...aggregateGraderScores({ graders: input.graders, components, infrastructureError: input.evidence.infrastructureError }) };
124
+ return TaskGradeSchema.parse({ ...content, contentHash: contentHash(content) });
125
+ }
126
+ /** Verify retained results against the exact admitted inputs without rerunning
127
+ * graders. The storage owner supplies the trusted artifact, not the caller. */
128
+ export function verifyTaskGrade(value, input) {
129
+ const result = TaskGradeSchema.parse(value);
130
+ const { contentHash: hash, ...content } = result;
131
+ if (hash !== contentHash(content) || result.taskHash !== contentHash(input.task) || result.evidenceHash !== contentHash(input.evidence) || result.graderSetHash !== contentHash(input.graders))
132
+ throw new Error("Task grade differs from its admitted task, evidence or graders.");
133
+ for (const component of result.components) {
134
+ const { contentHash: componentHash, ...body } = component;
135
+ if (componentHash !== contentHash(body))
136
+ throw new Error("Grader evidence integrity failed.");
137
+ }
138
+ const summary = aggregateGraderScores({ graders: input.graders, components: result.components, infrastructureError: input.evidence.infrastructureError });
139
+ if (contentHash(GradeSummarySchema.parse({ score: result.score, passed: result.passed, rewardEligible: result.rewardEligible, failureClass: result.failureClass, gradingStatus: result.gradingStatus })) !== contentHash(summary))
140
+ throw new Error("Task grade summary differs from its grader evidence.");
141
+ return result;
142
+ }
@@ -68,4 +68,77 @@ export declare function gradeEvidence(input: {
68
68
  customVerifier?: CustomVerifierRunner;
69
69
  }): Promise<GraderEvidence[]>;
70
70
  export type GraderEvidence = z.infer<typeof GraderEvidenceSchema>;
71
+ declare const GradeSummarySchema: z.ZodObject<{
72
+ score: z.ZodNullable<z.ZodNumber>;
73
+ passed: z.ZodBoolean;
74
+ rewardEligible: z.ZodBoolean;
75
+ failureClass: z.ZodNullable<z.ZodEnum<{
76
+ policy_failure: "policy_failure";
77
+ grader_failure: "grader_failure";
78
+ environment_failure: "environment_failure";
79
+ infrastructure_failure: "infrastructure_failure";
80
+ timeout: "timeout";
81
+ cancelled: "cancelled";
82
+ }>>;
83
+ gradingStatus: z.ZodEnum<{
84
+ scored: "scored";
85
+ unscorable: "unscorable";
86
+ not_configured: "not_configured";
87
+ }>;
88
+ }, z.core.$strict>;
89
+ /** Shared ordinary grading policy. Results must match the declared population;
90
+ * missing checks cannot disappear from the denominator or the hard gates. */
91
+ export declare function aggregateGraderScores(input: {
92
+ graders: ReadonlyArray<Pick<GraderSpec, "id" | "version" | "weight" | "hardGate" | "rewardEligible">>;
93
+ components: ReadonlyArray<Pick<GraderEvidence, "graderId" | "graderVersion" | "score" | "passed" | "rewardEligible" | "failureClass">>;
94
+ infrastructureError?: string | null;
95
+ }): z.infer<typeof GradeSummarySchema>;
96
+ export declare const TaskGradeSchema: z.ZodObject<{
97
+ score: z.ZodNullable<z.ZodNumber>;
98
+ passed: z.ZodBoolean;
99
+ rewardEligible: z.ZodBoolean;
100
+ failureClass: z.ZodNullable<z.ZodEnum<{
101
+ policy_failure: "policy_failure";
102
+ grader_failure: "grader_failure";
103
+ environment_failure: "environment_failure";
104
+ infrastructure_failure: "infrastructure_failure";
105
+ timeout: "timeout";
106
+ cancelled: "cancelled";
107
+ }>>;
108
+ gradingStatus: z.ZodEnum<{
109
+ scored: "scored";
110
+ unscorable: "unscorable";
111
+ not_configured: "not_configured";
112
+ }>;
113
+ schemaVersion: z.ZodLiteral<"openpond.taskGrade.v1">;
114
+ taskHash: z.ZodString;
115
+ evidenceHash: z.ZodString;
116
+ graderSetHash: z.ZodString;
117
+ components: z.ZodArray<z.ZodObject<{
118
+ schemaVersion: z.ZodLiteral<"openpond.graderEvidence.v1">;
119
+ graderId: z.ZodString;
120
+ graderVersion: z.ZodString;
121
+ score: z.ZodNullable<z.ZodNumber>;
122
+ passed: z.ZodBoolean;
123
+ rewardEligible: z.ZodBoolean;
124
+ failureClass: z.ZodNullable<z.ZodEnum<{
125
+ policy_failure: "policy_failure";
126
+ grader_failure: "grader_failure";
127
+ environment_failure: "environment_failure";
128
+ infrastructure_failure: "infrastructure_failure";
129
+ timeout: "timeout";
130
+ cancelled: "cancelled";
131
+ }>>;
132
+ feedback: z.ZodArray<z.ZodString>;
133
+ visibleEvidenceRefs: z.ZodArray<z.ZodString>;
134
+ privilegedEvidenceRefs: z.ZodArray<z.ZodString>;
135
+ contentHash: z.ZodString;
136
+ }, z.core.$strict>>;
137
+ contentHash: z.ZodString;
138
+ }, z.core.$strict>;
139
+ export type TaskGrade = z.infer<typeof TaskGradeSchema>;
140
+ export declare function gradeTaskEvidence(input: Parameters<typeof gradeEvidence>[0]): Promise<TaskGrade>;
141
+ /** Verify retained results against the exact admitted inputs without rerunning
142
+ * graders. The storage owner supplies the trusted artifact, not the caller. */
143
+ export declare function verifyTaskGrade(value: unknown, input: Pick<Parameters<typeof gradeEvidence>[0], "task" | "evidence" | "graders">): TaskGrade;
71
144
  //# sourceMappingURL=graders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"graders.d.ts","sourceRoot":"","sources":["../../../../src/graders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAA2B,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAErF,OAAO,EAAE,2BAA2B,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAErG,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;;;;kBAW7B,CAAC;AACZ,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;kBAAkF,CAAC;AAEpH,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC,CAAC;AACF,MAAM,MAAM,gBAAgB,GAAG,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,GAAG,UAAU,GAAG,eAAe,GAAG,aAAa,CAAC,CAAC,CAAC;AAC/O,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,OAAO,CAAC,UAAU,EAAE;QAAE,IAAI,EAAE,iBAAiB,CAAA;KAAE,CAAC,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,eAAe,CAAA;CAAE,KAAK,OAAO,CAAC,IAAI,CAAC,cAAc,EAAE,eAAe,GAAG,UAAU,GAAG,eAAe,GAAG,aAAa,CAAC,CAAC,CAAC;AAEvP,wBAAsB,aAAa,CAAC,KAAK,EAAE;IACzC,IAAI,EAAE,UAAU,CAAC;IACjB,QAAQ,EAAE,eAAe,CAAC;IAC1B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,oBAAoB,CAAC;CACvC,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAwB5B;AA8BD,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
1
+ {"version":3,"file":"graders.d.ts","sourceRoot":"","sources":["../../../../src/graders.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openpond/evals",
3
- "version": "0.9.1",
3
+ "version": "0.9.3",
4
4
  "description": "Portable Tasksets, graders, evaluation runs, receipts, conformance fixtures, and Work evidence for OpenPond Harnesses",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -158,7 +158,7 @@
158
158
  "zod": "^4.1.13"
159
159
  },
160
160
  "peerDependencies": {
161
- "@openpond/harness": "^0.2.0"
161
+ "@openpond/harness": "^0.2.0 || ^0.3.0"
162
162
  },
163
163
  "devDependencies": {
164
164
  "@openpond/harness": "workspace:*",