@openpond/evals 0.10.4 → 0.10.6

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.
Files changed (36) hide show
  1. package/LEARNING.md +23 -0
  2. package/dist/learning/admission.js +1 -0
  3. package/dist/learning/batch-service.js +12 -7
  4. package/dist/learning/contracts.js +2 -1
  5. package/dist/learning/index.js +1 -0
  6. package/dist/learning/iteration-budget.js +17 -0
  7. package/dist/learning/iteration-reservation-service.js +3 -13
  8. package/dist/learning/policy-inspection.js +82 -0
  9. package/dist/learning/service.js +6 -0
  10. package/dist/learning/transport.js +1 -0
  11. package/dist/types/learning/admission.d.ts +18 -0
  12. package/dist/types/learning/admission.d.ts.map +1 -1
  13. package/dist/types/learning/batch-service.d.ts +324 -0
  14. package/dist/types/learning/batch-service.d.ts.map +1 -1
  15. package/dist/types/learning/contracts.d.ts +54 -0
  16. package/dist/types/learning/contracts.d.ts.map +1 -1
  17. package/dist/types/learning/index.d.ts +1 -0
  18. package/dist/types/learning/index.d.ts.map +1 -1
  19. package/dist/types/learning/iteration-budget.d.ts +8 -0
  20. package/dist/types/learning/iteration-budget.d.ts.map +1 -0
  21. package/dist/types/learning/iteration-reservation-service.d.ts.map +1 -1
  22. package/dist/types/learning/operations.d.ts +72 -0
  23. package/dist/types/learning/operations.d.ts.map +1 -1
  24. package/dist/types/learning/policy-inspection.d.ts +47 -0
  25. package/dist/types/learning/policy-inspection.d.ts.map +1 -0
  26. package/dist/types/learning/repository.d.ts +18 -0
  27. package/dist/types/learning/repository.d.ts.map +1 -1
  28. package/dist/types/learning/service.d.ts +39 -0
  29. package/dist/types/learning/service.d.ts.map +1 -1
  30. package/dist/types/learning/transport.d.ts +62 -0
  31. package/dist/types/learning/transport.d.ts.map +1 -1
  32. package/package.json +1 -1
  33. package/schemas/learning/v1/command-request.schema.json +201 -136
  34. package/schemas/learning/v1/definition.schema.json +116 -14
  35. package/schemas/learning/v1/policy-inspection.schema.json +243 -0
  36. package/schemas/learning/v1/read-request.schema.json +47 -23
package/LEARNING.md CHANGED
@@ -232,6 +232,23 @@ owns it. Duplicate observations are idempotent, older decision revisions cannot
232
232
  overwrite newer ones, and contradictory observations at the same revision fail.
233
233
  This operation does not change the training parent or activate serving.
234
234
 
235
+ ### Policy readiness reads
236
+
237
+ `client.inspectPolicy({ id, revision, contentHash })` sends the read payload
238
+ `{ "action": "inspect_policy", "scope": "<profile-or-team>", "policy": { "id": "...", "revision": 1, "contentHash": "..." } }`.
239
+ The authenticated owner reads a scope-serialized snapshot of the current policy's
240
+ eligible, awaiting-review, excluded and consumed counts, chain identity, cooldown
241
+ and daily budget. It uses the same eligibility, complete batch validation and
242
+ budget accounting as manual or scheduled reservation. A stale policy reference is
243
+ rejected; source-only credentials cannot read it.
244
+
245
+ `canReserve` describes shared reservation readiness at `inspectedAt`. The actual
246
+ command rechecks current state and execution-owner preparation still validates
247
+ its training configuration. `blockers` explains unmet constraints. `counts: null`
248
+ means inspection could not count valid sources or supported admission, not that
249
+ the backlog is empty. Reads never write an iteration, timer fire, family
250
+ reservation, batch, consumption or operation record and never launch training.
251
+
235
252
  ### Durable learning schedules
236
253
 
237
254
  Policy publication atomically synchronizes a `schedule` resource. Enabling
@@ -257,3 +274,9 @@ retained diagnostic; a new reviewed policy revision may resume it. Hosts must
257
274
  poll due timers for their execution owner and supply an authorized actor. This
258
275
  worker does not execute a Work prompt or submit a provider Job; the existing
259
276
  iteration dispatch worker owns that next transition.
277
+
278
+ Task Definitions may declare `requiredOutputs`. These optional contracts use
279
+ Taskset output paths, media types, schema references and size bounds. Evidence
280
+ conversion copies them into every task before grading or sealing a batch, so a
281
+ changed output contract requires a new definition and new matching evidence and
282
+ review receipts. Definitions without this field retain their existing hashes.
@@ -85,6 +85,7 @@ export function taskRecordFromEvidence(evidence, definition) {
85
85
  policyVisibleContext: { instructions: definition.instructions },
86
86
  privilegedContextRef: evidence.submission.evaluatorContext === null ? null : `task-evidence:${evidence.contentHash}`,
87
87
  artifactRefs: evidence.submission.assets, tags: [definition.category],
88
+ ...(definition.requiredOutputs ? { requiredOutputs: definition.requiredOutputs } : {}),
88
89
  });
89
90
  }
90
91
  export function taskAttemptEvidence(evidence, output) {
@@ -4,6 +4,17 @@ import { learningRef, sameLearningRef } from "./contracts.js";
4
4
  import { LearningDomainError } from "./errors.js";
5
5
  import { requireLearningRelease, requireLearningResource } from "./repository.js";
6
6
  export async function sealLearningBatch(transaction, input, actorId, timestamp) {
7
+ const { batch, release, evidence, definition } = await prepareLearningBatch(transaction, input, actorId, timestamp);
8
+ for (const item of evidence) {
9
+ for (const reservation of taskFamilyReservations(item, definition))
10
+ await transaction.reserveFamilySplit(reservation.namespace, reservation.kind, reservation.key, reservation.split);
11
+ }
12
+ await transaction.put("batch", batch, 0, { parentId: definition.id });
13
+ await transaction.put("package", release, 0, { parentId: batch.id });
14
+ return [pointer("batch", batch), pointer("package", release)];
15
+ }
16
+ /** Performs the complete shared validation without reserving families or publishing resources. */
17
+ export async function prepareLearningBatch(transaction, input, actorId, timestamp) {
7
18
  const definition = await requireLearningRelease(transaction, "definition", input.taskDefinition);
8
19
  const binding = await requireLearningRelease(transaction, "binding", definition.rewardBinding);
9
20
  const rewards = await Promise.all(binding.sources.map((source) => requireLearningRelease(transaction, "reward", source.reward)));
@@ -26,13 +37,7 @@ export async function sealLearningBatch(transaction, input, actorId, timestamp)
26
37
  }
27
38
  const batch = sealTaskBatch({ id: input.batchId, definition, binding, rewards, purpose: input.purpose, evidence, decisions, priorSplits, actorId, now: timestamp });
28
39
  const release = compileTaskBatch({ batch, definition, binding, rewards, evidence, decisions });
29
- for (const item of evidence) {
30
- for (const reservation of taskFamilyReservations(item, definition))
31
- await transaction.reserveFamilySplit(reservation.namespace, reservation.kind, reservation.key, reservation.split);
32
- }
33
- await transaction.put("batch", batch, 0, { parentId: definition.id });
34
- await transaction.put("package", release, 0, { parentId: batch.id });
35
- return [pointer("batch", batch), pointer("package", release)];
40
+ return { batch, release, evidence, definition };
36
41
  }
37
42
  export async function requireCurrentLearningEvidence(transaction, ref) {
38
43
  const evidence = await requireLearningRelease(transaction, "evidence", ref);
@@ -2,7 +2,7 @@ import { LearningDomainError } from "./errors.js";
2
2
  import { z } from "zod";
3
3
  import { ImmutableAssetRefSchema, ImmutableReleaseRefSchema, ReleaseHashSchema, ReleaseIdSchema, ReleaseTimestampSchema, contentHash } from "@openpond/harness";
4
4
  import { RewardBindingSchema, RewardCompositionSchema, RewardReleaseRefSchema, RewardReleaseSchema } from "../rewards.js";
5
- import { TaskSplitSchema, TasksetReleaseContentSchema } from "../tasksets.js";
5
+ import { TaskRecordSchema, TaskSplitSchema, TasksetReleaseContentSchema } from "../tasksets.js";
6
6
  import { assertBoundedTaskJson, validateTaskSchema } from "../task-schema.js";
7
7
  export const LearningJsonObjectSchema = z.record(z.string(), z.json());
8
8
  export const LearningRevisionRefSchema = RewardReleaseRefSchema;
@@ -18,6 +18,7 @@ export const TaskDefinitionContentSchema = z.object({
18
18
  familyNamespace: ReleaseIdSchema,
19
19
  inputSchema: z.record(z.string(), z.unknown()),
20
20
  outputSchema: z.record(z.string(), z.unknown()),
21
+ requiredOutputs: TaskRecordSchema.shape.requiredOutputs,
21
22
  rewardBinding: LearningRevisionRefSchema,
22
23
  harness: ImmutableReleaseRefSchema.nullable(),
23
24
  execution: TasksetReleaseContentSchema.pick({ policy: true, environment: true, environmentRelease: true, tools: true, capabilities: true, verifierSetRelease: true }).strict(),
@@ -19,3 +19,4 @@ export * from "./iteration-candidate-decision.js";
19
19
  export * from "./schedule-contracts.js";
20
20
  export * from "./schedule-service.js";
21
21
  export * from "./schedule-worker.js";
22
+ export * from "./policy-inspection.js";
@@ -0,0 +1,17 @@
1
+ /** Outstanding reservations survive midnight; settled spend belongs to its UTC day. */
2
+ export async function readLearningIterationBudget(transaction, chainId, now) {
3
+ const day = new Date(now).toISOString().slice(0, 10);
4
+ let reservedSpendUsd = 0;
5
+ let settledSpendUsd = 0;
6
+ let afterId;
7
+ do {
8
+ const page = await transaction.list("reservation", { parentId: chainId, limit: 100, ...(afterId ? { afterId } : {}) });
9
+ for (const { budget } of page.items) {
10
+ reservedSpendUsd += budget.reservedSpendUsd;
11
+ if (budget.settledAt && new Date(budget.settledAt).toISOString().slice(0, 10) === day)
12
+ settledSpendUsd += budget.settledSpendUsd;
13
+ }
14
+ afterId = page.nextCursor ?? undefined;
15
+ } while (afterId);
16
+ return { reservedSpendUsd, settledSpendUsd, committedSpendUsd: reservedSpendUsd + settledSpendUsd };
17
+ }
@@ -3,6 +3,7 @@ import { sealLearningBatch } from "./batch-service.js";
3
3
  import { LearningIterationSchema, learningRef, sameLearningRef } from "./contracts.js";
4
4
  import { LearningDomainError } from "./errors.js";
5
5
  import { inspectIterationEligibility, learningChainId, learningConsumptionId } from "./iteration-eligibility.js";
6
+ import { readLearningIterationBudget } from "./iteration-budget.js";
6
7
  import { LearningChainSchema, LearningConsumptionSchema, LearningIterationReservationSchema } from "./iteration-reservation-contracts.js";
7
8
  import { requireLearningRelease, requireLearningResource } from "./repository.js";
8
9
  /** The caller owns one scope-serialized transaction. This never submits a Job. */
@@ -89,18 +90,7 @@ export async function reserveLearningIteration(transaction, input, actorId, now)
89
90
  return [{ kind: "iteration", id, revision: 1 }, { kind: "reservation", id, revision: 1 }, ...pointers];
90
91
  }
91
92
  async function assertAvailableBudget(transaction, chainId, now, requested, maximum) {
92
- let committed = 0;
93
- let afterId;
94
- do {
95
- const page = await transaction.list("reservation", { parentId: chainId, limit: 100, ...(afterId ? { afterId } : {}) });
96
- for (const { budget } of page.items) {
97
- // Unsettled reservations carry across midnight and worker restarts.
98
- committed += budget.reservedSpendUsd;
99
- if (budget.settledAt && new Date(budget.settledAt).toISOString().slice(0, 10) === new Date(now).toISOString().slice(0, 10))
100
- committed += budget.settledSpendUsd;
101
- }
102
- afterId = page.nextCursor ?? undefined;
103
- } while (afterId);
104
- if (committed + requested > maximum)
93
+ const budget = await readLearningIterationBudget(transaction, chainId, now);
94
+ if (budget.committedSpendUsd + requested > maximum)
105
95
  throw new LearningDomainError("learning_daily_budget_exhausted", 409);
106
96
  }
@@ -0,0 +1,82 @@
1
+ import { ReleaseIdSchema, ReleaseTimestampSchema } from "@openpond/harness";
2
+ import { z } from "zod";
3
+ import { LearningRevisionRefSchema, learningRef, sameLearningRef } from "./contracts.js";
4
+ import { prepareLearningBatch } from "./batch-service.js";
5
+ import { LearningDomainError } from "./errors.js";
6
+ import { readLearningIterationBudget } from "./iteration-budget.js";
7
+ import { inspectIterationEligibility, learningChainId } from "./iteration-eligibility.js";
8
+ import { LearningChainSchema, LearningEligibilityCountsSchema } from "./iteration-reservation-contracts.js";
9
+ import { requireLearningRelease, requireLearningResource } from "./repository.js";
10
+ /** A scope-serialized snapshot of shared reservation readiness, not a Job guarantee.
11
+ * No iteration, timer, batch, consumption or operation record is written. */
12
+ export const LearningPolicyInspectionResultSchema = z.object({
13
+ policy: LearningRevisionRefSchema,
14
+ modelProjectId: ReleaseIdSchema,
15
+ inspectedAt: ReleaseTimestampSchema,
16
+ chain: LearningChainSchema.nullable(),
17
+ counts: LearningEligibilityCountsSchema.nullable(),
18
+ minimumApprovedExamples: z.number().int().positive(),
19
+ canReserve: z.boolean(),
20
+ blockers: z.array(z.object({ code: z.string().min(1).max(200), message: z.string().min(1).max(20_000) }).strict()).max(20),
21
+ cooldownUntil: ReleaseTimestampSchema.nullable(),
22
+ budget: z.object({
23
+ reservedSpendUsd: z.number().nonnegative(), settledSpendUsd: z.number().nonnegative(), committedSpendUsd: z.number().nonnegative(),
24
+ maximumIterationSpendUsd: z.number().nonnegative(), maximumDailySpendUsd: z.number().nonnegative(),
25
+ }).strict(),
26
+ }).strict();
27
+ export async function inspectLearningPolicy(transaction, reference, actorId, now) {
28
+ const policy = await requireLearningRelease(transaction, "policy", reference);
29
+ const current = await requireLearningResource(transaction, "policy", policy.id);
30
+ if (!sameLearningRef(learningRef(current), reference))
31
+ throw new LearningDomainError("learning_policy_revision_stale", 409);
32
+ const chainId = learningChainId(policy.modelProjectId);
33
+ const chain = await transaction.get("chain", chainId);
34
+ const budget = await readLearningIterationBudget(transaction, chainId, now);
35
+ const blockers = [];
36
+ const block = (code, message) => { blockers.push({ code, message }); };
37
+ if (!policy.enabled)
38
+ block("learning_policy_paused", "Learning is paused.");
39
+ if (policy.automation.accept || policy.automation.serve)
40
+ block("learning_automatic_acceptance_not_available", "Candidates require explicit acceptance and serving selection.");
41
+ if (chain?.activeIterationId)
42
+ block("learning_iteration_active", "An iteration is already active.");
43
+ const cooldownUntil = chain?.lastReservedAt && Date.parse(now) - Date.parse(chain.lastReservedAt) < policy.limits.cooldownSeconds * 1_000
44
+ ? new Date(Date.parse(chain.lastReservedAt) + policy.limits.cooldownSeconds * 1_000).toISOString() : null;
45
+ if (cooldownUntil)
46
+ block("learning_iteration_cooldown", "The training cooldown has not elapsed.");
47
+ if (budget.committedSpendUsd + policy.limits.maxIterationSpendUsd > policy.limits.maxDailySpendUsd) {
48
+ block("learning_daily_budget_exhausted", "The daily budget cannot cover another iteration's maximum spend.");
49
+ }
50
+ let counts = null;
51
+ try {
52
+ const eligibility = await inspectIterationEligibility(transaction, policy);
53
+ counts = eligibility.counts;
54
+ if (counts.eligible < policy.admission.minimumApprovedExamples) {
55
+ if (counts.awaitingReview > 0)
56
+ block("learning_waiting_for_review", "More approved tasks are required before training.");
57
+ else
58
+ block("learning_waiting_for_data", "More eligible new tasks are required before training.");
59
+ }
60
+ else {
61
+ await prepareLearningBatch(transaction, {
62
+ action: "seal_batch", operationId: "policy-inspection", batchId: "policy-inspection",
63
+ taskDefinition: policy.taskDefinition, purpose: eligibility.purpose,
64
+ evidence: eligibility.selected.map(item => learningRef(item.evidence)),
65
+ decisions: eligibility.selected.map(item => learningRef(item.decision)),
66
+ }, actorId, now);
67
+ }
68
+ }
69
+ catch (error) {
70
+ if (!(error instanceof LearningDomainError))
71
+ throw error;
72
+ // An unavailable count is not zero. Invalid sources or unsupported admission
73
+ // must remain visible while the Model's settings and history can still load.
74
+ block(error.code, error.message.slice(0, 20_000));
75
+ }
76
+ return LearningPolicyInspectionResultSchema.parse({
77
+ policy: learningRef(policy), modelProjectId: policy.modelProjectId, inspectedAt: now, chain,
78
+ counts, minimumApprovedExamples: policy.admission.minimumApprovedExamples, canReserve: blockers.length === 0,
79
+ blockers, cooldownUntil,
80
+ budget: { ...budget, maximumIterationSpendUsd: policy.limits.maxIterationSpendUsd, maximumDailySpendUsd: policy.limits.maxDailySpendUsd },
81
+ });
82
+ }
@@ -2,6 +2,7 @@ import { cancelLearningIterationReservation } from "./iteration-reservation-canc
2
2
  import { commandLearningIterationDispatch } from "./iteration-dispatch-commands.js";
3
3
  import { reserveLearningIteration } from "./iteration-reservation-service.js";
4
4
  import { synchronizeLearningSchedule } from "./schedule-service.js";
5
+ import { inspectLearningPolicy } from "./policy-inspection.js";
5
6
  import { requireCurrentLearningEvidence as currentEvidence, sealLearningBatch } from "./batch-service.js";
6
7
  import { saveAuthoringDraft, archiveAuthoringDraft, finalizeAuthoringDraft } from "./authoring-service.js";
7
8
  import { queueRewardCheck, cancelRewardCheck } from "./reward-check-service.js";
@@ -327,6 +328,11 @@ export function createLearningService(repository, options = {}) {
327
328
  }
328
329
  return {
329
330
  command,
331
+ async inspectPolicy(context, reference) {
332
+ authorizeRead(context);
333
+ const ref = LearningRevisionRefSchema.parse(reference);
334
+ return repository.transaction(context.scope, transaction => inspectLearningPolicy(transaction, ref, context.actor.id, now()));
335
+ },
330
336
  async inspectEvidence(context, reference) {
331
337
  authorizeRead(context);
332
338
  const ref = LearningRevisionRefSchema.parse(reference);
@@ -17,6 +17,7 @@ export function assertLearningRequestJson(raw) {
17
17
  /** Scope selection is never authorization; each host resolves its authenticated owner. */
18
18
  export const LearningCommandRequestSchema = z.object({ scope: ReleaseIdSchema, command: LearningCommandSchema }).strict();
19
19
  export const LearningReadRequestSchema = z.discriminatedUnion("action", [
20
+ z.object({ action: z.literal("inspect_policy"), scope: ReleaseIdSchema, policy: LearningRevisionRefSchema }).strict(),
20
21
  z.object({ action: z.literal("inspect_evidence"), scope: ReleaseIdSchema, evidence: LearningRevisionRefSchema }).strict(),
21
22
  z.object({ action: z.literal("get"), scope: ReleaseIdSchema, kind: LearningResourceKindSchema, id: ReleaseIdSchema, revision: z.number().int().positive().optional() }).strict(),
22
23
  z.object({ action: z.literal("list"), scope: ReleaseIdSchema, kind: LearningResourceKindSchema, parentId: ReleaseIdSchema.optional(), status: z.string().min(1).max(200).optional(), afterId: ReleaseIdSchema.optional(), limit: z.number().int().min(1).max(100).default(50) }).strict(),
@@ -79,6 +79,24 @@ export declare const TaskBatchPackageMetadataSchema: z.ZodObject<{
79
79
  familyNamespace: z.ZodString;
80
80
  inputSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
81
81
  outputSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
82
+ requiredOutputs: z.ZodOptional<z.ZodArray<z.ZodObject<{
83
+ path: z.ZodString;
84
+ mediaType: z.ZodString;
85
+ schemaRef: z.ZodDefault<z.ZodNullable<z.ZodObject<{
86
+ id: z.ZodString;
87
+ path: z.ZodString;
88
+ contentHash: z.ZodString;
89
+ sizeBytes: z.ZodNumber;
90
+ mediaType: z.ZodString;
91
+ visibility: z.ZodEnum<{
92
+ policy: "policy";
93
+ verifier: "verifier";
94
+ host_private: "host_private";
95
+ }>;
96
+ }, z.core.$strict>>>;
97
+ maxBytes: z.ZodDefault<z.ZodNullable<z.ZodNumber>>;
98
+ metadata: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
99
+ }, z.core.$strict>>>;
82
100
  rewardBinding: z.ZodObject<{
83
101
  id: z.ZodString;
84
102
  contentHash: z.ZodString;
@@ -1 +1 @@
1
- {"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../../../../src/learning/admission.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAsF,KAAK,aAAa,EAAE,KAAK,iBAAiB,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AACnL,OAAO,EAAuE,KAAK,UAAU,EAAE,KAAK,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC3I,OAAO,EAA4C,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACnG,OAAO,EAAwS,KAAK,cAAc,EAAE,KAAK,qBAAqB,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE3c,MAAM,MAAM,sBAAsB,GAAG;IACnC,gBAAgB,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,SAAS,EAAE,OAAO,CAAC;IACnB,mBAAmB,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE,eAAe,EAAE,CAAC;CAC3B,CAAC;AACF,MAAM,MAAM,eAAe,GAAG;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IAAC,KAAK,EAAE,qBAAqB,CAAC,OAAO,CAAC,CAAA;CAAE,CAAC;AAElI,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,GAAG,sBAAsB,CAe9G;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,qBAAqB,GAAG,qBAAqB,CAWnI;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,qBAAqB,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAmB/M;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAU5E;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,GAAG,UAAU,CAUrG;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;sBAChD,MAAM,EAAE;;EAClD;AAED,wBAAgB,uBAAuB,CAAC,KAAK,EAAE;IAAE,QAAQ,EAAE,qBAAqB,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAA;CAAE,GAAG,IAAI,CAkB3K;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAGvJ;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,GAAG,eAAe,EAAE,CAM5G;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,aAAa,EAAE,CAAC;IAAC,OAAO,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,SAAS,EAAE,qBAAqB,EAAE,CAAC;IAAC,WAAW,EAAE,eAAe,EAAE,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAuBvS;AAED,eAAO,MAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAOhC,CAAC;AAEZ,wBAAgB,gBAAgB,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,UAAU,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,aAAa,EAAE,CAAC;IAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;IAAC,SAAS,EAAE,qBAAqB,EAAE,CAAA;CAAE,GAAG,cAAc,CAuBxN;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAQhH"}
1
+ {"version":3,"file":"admission.d.ts","sourceRoot":"","sources":["../../../../../src/learning/admission.ts"],"names":[],"mappings":"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"}
@@ -4,5 +4,329 @@ import { type LearningResourcePointer, type LearningTransaction } from "./reposi
4
4
  export declare function sealLearningBatch(transaction: LearningTransaction, input: Extract<LearningCommand, {
5
5
  action: "seal_batch";
6
6
  }>, actorId: string, timestamp: string): Promise<LearningResourcePointer[]>;
7
+ /** Performs the complete shared validation without reserving families or publishing resources. */
8
+ export declare function prepareLearningBatch(transaction: LearningTransaction, input: Extract<LearningCommand, {
9
+ action: "seal_batch";
10
+ }>, actorId: string, timestamp: string): Promise<{
11
+ batch: {
12
+ schemaVersion: "openpond.taskBatch.v1";
13
+ id: string;
14
+ revision: 1;
15
+ taskDefinition: {
16
+ id: string;
17
+ contentHash: string;
18
+ revision: number;
19
+ };
20
+ rewardBinding: {
21
+ id: string;
22
+ contentHash: string;
23
+ revision: number;
24
+ };
25
+ purpose: "evaluation" | "supervised_training" | "reward_training";
26
+ examples: {
27
+ evidence: {
28
+ id: string;
29
+ contentHash: string;
30
+ revision: number;
31
+ };
32
+ decision: {
33
+ id: string;
34
+ contentHash: string;
35
+ revision: number;
36
+ };
37
+ familyKey: string;
38
+ inputHash: string;
39
+ split: "train" | "validation" | "test" | "frozen_eval";
40
+ }[];
41
+ sealedAt: string;
42
+ sealedBy: string;
43
+ contentHash: string;
44
+ };
45
+ release: {
46
+ schemaVersion: "openpond.tasksetRelease.v2";
47
+ id: string;
48
+ revision: number;
49
+ policy: {
50
+ policyVisibleFields: string[];
51
+ privilegedFields: string[];
52
+ hiddenGraderRefs: string[];
53
+ connectedAppScopes: string[];
54
+ };
55
+ environment: {
56
+ protocolVersion: "openpond.environment.v1";
57
+ kind: "text" | "agent" | "work" | "custom_program";
58
+ entrypoint: string;
59
+ stateful: boolean;
60
+ deterministicSeeds: boolean;
61
+ lifecycle: ("create" | "reset" | "step" | "collect" | "destroy")[];
62
+ networkPolicy: "none" | "declared_read_only" | "declared_scoped";
63
+ defaultTimeoutMs: number;
64
+ };
65
+ tools: {
66
+ name: string;
67
+ description: string;
68
+ inputSchema: Record<string, unknown>;
69
+ inputSchemaHash: string;
70
+ sideEffect: "read" | "write";
71
+ timeoutMs: number;
72
+ }[];
73
+ capabilities: {
74
+ id: string;
75
+ required: boolean;
76
+ scopes: string[];
77
+ portability: "portable" | "host_adapter" | "local_only" | "hosted_only";
78
+ }[];
79
+ tasks: {
80
+ id: string;
81
+ clusterKey: string;
82
+ split: "train" | "validation" | "test" | "frozen_eval";
83
+ input: Record<string, unknown>;
84
+ expectedOutput: Record<string, unknown> | null;
85
+ policyVisibleContext: Record<string, unknown>;
86
+ privilegedContextRef: string | null;
87
+ artifactRefs: {
88
+ id: string;
89
+ path: string;
90
+ contentHash: string;
91
+ sizeBytes: number;
92
+ mediaType: string;
93
+ visibility: "policy" | "verifier" | "host_private";
94
+ }[];
95
+ tags: string[];
96
+ requiredOutputs?: {
97
+ path: string;
98
+ mediaType: string;
99
+ schemaRef: {
100
+ id: string;
101
+ path: string;
102
+ contentHash: string;
103
+ sizeBytes: number;
104
+ mediaType: string;
105
+ visibility: "policy" | "verifier" | "host_private";
106
+ } | null;
107
+ maxBytes: number | null;
108
+ metadata: Record<string, unknown>;
109
+ }[] | undefined;
110
+ }[];
111
+ graders: ({
112
+ id: string;
113
+ version: string;
114
+ weight: number;
115
+ hardGate: boolean;
116
+ rewardEligible: boolean;
117
+ privileged: boolean;
118
+ kind: "content" | "schema" | "artifact" | "runtime_event" | "state";
119
+ config: Record<string, unknown>;
120
+ } | {
121
+ id: string;
122
+ version: string;
123
+ weight: number;
124
+ hardGate: boolean;
125
+ rewardEligible: boolean;
126
+ privileged: boolean;
127
+ kind: "model_judge";
128
+ rubricRef: {
129
+ id: string;
130
+ path: string;
131
+ contentHash: string;
132
+ sizeBytes: number;
133
+ mediaType: string;
134
+ visibility: "policy" | "verifier" | "host_private";
135
+ };
136
+ calibrationStatus: "pending" | "passed" | "failed";
137
+ model?: {
138
+ providerId: string;
139
+ modelId: string;
140
+ revision: string | null;
141
+ } | undefined;
142
+ temperature?: number | undefined;
143
+ } | {
144
+ id: string;
145
+ version: string;
146
+ weight: number;
147
+ hardGate: boolean;
148
+ rewardEligible: boolean;
149
+ privileged: boolean;
150
+ kind: "custom_verifier";
151
+ verifierRef: {
152
+ id: string;
153
+ path: string;
154
+ contentHash: string;
155
+ sizeBytes: number;
156
+ mediaType: string;
157
+ visibility: "policy" | "verifier" | "host_private";
158
+ };
159
+ timeoutMs: number;
160
+ networkPolicy: "none";
161
+ exportName?: string | undefined;
162
+ } | {
163
+ id: string;
164
+ version: string;
165
+ weight: number;
166
+ hardGate: boolean;
167
+ rewardEligible: boolean;
168
+ privileged: boolean;
169
+ kind: "human";
170
+ rubricRef: {
171
+ id: string;
172
+ path: string;
173
+ contentHash: string;
174
+ sizeBytes: number;
175
+ mediaType: string;
176
+ visibility: "policy" | "verifier" | "host_private";
177
+ };
178
+ reviewerRole: string;
179
+ })[];
180
+ metadata: Record<string, unknown>;
181
+ contentHash: string;
182
+ environmentRelease?: {
183
+ id: string;
184
+ contentHash: string;
185
+ } | undefined;
186
+ verifierSetRelease?: {
187
+ id: string;
188
+ contentHash: string;
189
+ } | undefined;
190
+ metrics?: {
191
+ schemaVersion: "openpond.tasksetMetricPolicy.v1";
192
+ primaryMetric: string;
193
+ aggregation: "mean_score" | "pass_rate" | "weighted_mean" | "custom";
194
+ missingReward: "zero" | "exclude";
195
+ customAggregator: {
196
+ module: string;
197
+ exportName: string;
198
+ contentHash: string;
199
+ timeoutMs: number;
200
+ networkPolicy: "none";
201
+ } | null;
202
+ taskWeights?: Record<string, number> | undefined;
203
+ } | undefined;
204
+ };
205
+ evidence: {
206
+ schemaVersion: "openpond.taskEvidence.v1";
207
+ id: string;
208
+ revision: number;
209
+ source: {
210
+ id: string;
211
+ contentHash: string;
212
+ revision: number;
213
+ };
214
+ submission: {
215
+ schemaVersion: "openpond.taskExample.v1";
216
+ sourceId: string;
217
+ idempotencyKey: string;
218
+ taskDefinition: {
219
+ id: string;
220
+ contentHash: string;
221
+ revision: number;
222
+ };
223
+ exampleId: string;
224
+ attemptId: string;
225
+ occurredAt: string;
226
+ familyKey: string | null;
227
+ split: "train" | "validation" | "test" | "frozen_eval";
228
+ input: Record<string, import("zod").JSONType>;
229
+ observedOutput: Record<string, import("zod").JSONType> | null;
230
+ expected: Record<string, import("zod").JSONType> | null;
231
+ evaluatorContext: Record<string, import("zod").JSONType> | null;
232
+ assets: {
233
+ id: string;
234
+ path: string;
235
+ contentHash: string;
236
+ sizeBytes: number;
237
+ mediaType: string;
238
+ visibility: "policy" | "verifier" | "host_private";
239
+ }[];
240
+ provenance: {
241
+ sourceRecordRef: string | null;
242
+ mappingHash: string | null;
243
+ };
244
+ };
245
+ supersedes: {
246
+ id: string;
247
+ contentHash: string;
248
+ revision: number;
249
+ } | null;
250
+ correctionFeedbackId: string | null;
251
+ receivedAt: string;
252
+ contentHash: string;
253
+ }[];
254
+ definition: {
255
+ schemaVersion: "openpond.taskDefinition.v1";
256
+ id: string;
257
+ revision: number;
258
+ name: string;
259
+ description: string;
260
+ instructions: string;
261
+ category: "custom" | "structured" | "question_answering" | "coding" | "tool_workflow";
262
+ familyNamespace: string;
263
+ inputSchema: Record<string, unknown>;
264
+ outputSchema: Record<string, unknown>;
265
+ rewardBinding: {
266
+ id: string;
267
+ contentHash: string;
268
+ revision: number;
269
+ };
270
+ harness: {
271
+ id: string;
272
+ contentHash: string;
273
+ } | null;
274
+ execution: {
275
+ policy: {
276
+ policyVisibleFields: string[];
277
+ privilegedFields: string[];
278
+ hiddenGraderRefs: string[];
279
+ connectedAppScopes: string[];
280
+ };
281
+ environment: {
282
+ protocolVersion: "openpond.environment.v1";
283
+ kind: "text" | "agent" | "work" | "custom_program";
284
+ entrypoint: string;
285
+ stateful: boolean;
286
+ deterministicSeeds: boolean;
287
+ lifecycle: ("create" | "reset" | "step" | "collect" | "destroy")[];
288
+ networkPolicy: "none" | "declared_read_only" | "declared_scoped";
289
+ defaultTimeoutMs: number;
290
+ };
291
+ tools: {
292
+ name: string;
293
+ description: string;
294
+ inputSchema: Record<string, unknown>;
295
+ inputSchemaHash: string;
296
+ sideEffect: "read" | "write";
297
+ timeoutMs: number;
298
+ }[];
299
+ capabilities: {
300
+ id: string;
301
+ required: boolean;
302
+ scopes: string[];
303
+ portability: "portable" | "host_adapter" | "local_only" | "hosted_only";
304
+ }[];
305
+ environmentRelease?: {
306
+ id: string;
307
+ contentHash: string;
308
+ } | undefined;
309
+ verifierSetRelease?: {
310
+ id: string;
311
+ contentHash: string;
312
+ } | undefined;
313
+ };
314
+ contentHash: string;
315
+ requiredOutputs?: {
316
+ path: string;
317
+ mediaType: string;
318
+ schemaRef: {
319
+ id: string;
320
+ path: string;
321
+ contentHash: string;
322
+ sizeBytes: number;
323
+ mediaType: string;
324
+ visibility: "policy" | "verifier" | "host_private";
325
+ } | null;
326
+ maxBytes: number | null;
327
+ metadata: Record<string, unknown>;
328
+ }[] | undefined;
329
+ };
330
+ }>;
7
331
  export declare function requireCurrentLearningEvidence(transaction: LearningTransaction, ref: LearningRevisionRef): Promise<TaskEvidence>;
8
332
  //# sourceMappingURL=batch-service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"batch-service.d.ts","sourceRoot":"","sources":["../../../../../src/learning/batch-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgC,KAAK,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE3G,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAA8E,KAAK,uBAAuB,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAErK,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,CAAC,eAAe,EAAE;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CA2B3M;AAED,wBAAsB,8BAA8B,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAKtI"}
1
+ {"version":3,"file":"batch-service.d.ts","sourceRoot":"","sources":["../../../../../src/learning/batch-service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgC,KAAK,mBAAmB,EAAE,KAAK,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE3G,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAA8E,KAAK,uBAAuB,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAErK,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,CAAC,eAAe,EAAE;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,uBAAuB,EAAE,CAAC,CAQ3M;AAED,kGAAkG;AAClG,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,mBAAmB,EAAE,KAAK,EAAE,OAAO,CAAC,eAAe,EAAE;IAAE,MAAM,EAAE,YAAY,CAAA;CAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsBzK;AAED,wBAAsB,8BAA8B,CAAC,WAAW,EAAE,mBAAmB,EAAE,GAAG,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC,CAKtI"}