openpond-sdk 0.12.4 → 0.12.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 (160) hide show
  1. package/TASKSETS.md +13 -0
  2. package/TRAINING_PROTOCOL.md +25 -0
  3. package/dist/advanced-refiner-evaluations.js +7 -7
  4. package/dist/candidate-evaluations.js +6 -6
  5. package/dist/{chunk-MO4HAJZG.js → chunk-2XLKMZH5.js} +486 -252
  6. package/dist/chunk-2XLKMZH5.js.map +1 -0
  7. package/dist/{chunk-HGXVOFCL.js → chunk-3SIGXGAE.js} +133 -88
  8. package/dist/chunk-3SIGXGAE.js.map +1 -0
  9. package/dist/{chunk-WMIKJGXW.js → chunk-3VGTVZHL.js} +3 -3
  10. package/dist/{chunk-U7XWIOSB.js → chunk-5T76GARR.js} +2 -2
  11. package/dist/{chunk-WQFU635Q.js → chunk-ATVQQCYN.js} +8 -4
  12. package/dist/chunk-ATVQQCYN.js.map +1 -0
  13. package/dist/{chunk-QRS7Y3EM.js → chunk-B2MKB7NB.js} +2 -2
  14. package/dist/{chunk-H4NTJFEE.js → chunk-D3WOJTUY.js} +3 -2
  15. package/dist/{chunk-H4NTJFEE.js.map → chunk-D3WOJTUY.js.map} +1 -1
  16. package/dist/{chunk-EFUT3XKW.js → chunk-ETFWUMEJ.js} +2 -2
  17. package/dist/{chunk-B5XTGEBE.js → chunk-FPA3AVCP.js} +85 -8
  18. package/dist/chunk-FPA3AVCP.js.map +1 -0
  19. package/dist/{chunk-BVMR5OFW.js → chunk-HRJKDHHG.js} +6 -4
  20. package/dist/chunk-HRJKDHHG.js.map +1 -0
  21. package/dist/{chunk-VN5V2E2S.js → chunk-HRZLFJXX.js} +3 -3
  22. package/dist/{chunk-I54WQBXL.js → chunk-KD6MM67B.js} +6 -6
  23. package/dist/{chunk-ZHQK3MOM.js → chunk-LIMTJR3A.js} +3 -3
  24. package/dist/{chunk-GAIDBPFY.js → chunk-ONGOAEY6.js} +14 -2
  25. package/dist/chunk-ONGOAEY6.js.map +1 -0
  26. package/dist/{chunk-CMWZZZGW.js → chunk-QDYHSJT5.js} +22 -8
  27. package/dist/chunk-QDYHSJT5.js.map +1 -0
  28. package/dist/{chunk-VHGC44HA.js → chunk-RDL6QIQO.js} +2 -2
  29. package/dist/{chunk-LHX7ENKZ.js → chunk-S2IASCGW.js} +3 -3
  30. package/dist/{chunk-XON75UFN.js → chunk-SER76PQ7.js} +2 -2
  31. package/dist/{chunk-ETX25FTB.js → chunk-SMHZT6RM.js} +2 -2
  32. package/dist/{chunk-24N6A6SF.js → chunk-SQBYHWZU.js} +2 -2
  33. package/dist/{chunk-DF2QXVZ3.js → chunk-VBVFE33M.js} +5 -5
  34. package/dist/{chunk-53LLNDXF.js → chunk-VQGTYGZH.js} +2 -2
  35. package/dist/{chunk-OR3TMIJN.js → chunk-VTAGUWXH.js} +2 -2
  36. package/dist/{chunk-LR5CTOC5.js → chunk-XF3JR72U.js} +3 -3
  37. package/dist/{chunk-ZIFZFP5I.js → chunk-Y3I7SN5W.js} +61 -35
  38. package/dist/chunk-Y3I7SN5W.js.map +1 -0
  39. package/dist/{chunk-RRKRA237.js → chunk-Z4XGSEKC.js} +577 -249
  40. package/dist/chunk-Z4XGSEKC.js.map +1 -0
  41. package/dist/{chunk-K5LWSWV7.js → chunk-ZGZLN4LH.js} +2 -2
  42. package/dist/connected-evidence.js +14 -14
  43. package/dist/dataset-workspaces.js +14 -14
  44. package/dist/experiment-evaluation-schedules.js +18 -18
  45. package/dist/experiment-improvements.js +7 -7
  46. package/dist/experiments.js +17 -17
  47. package/dist/index.js +90 -45
  48. package/dist/index.js.map +1 -1
  49. package/dist/learning.js +113 -9
  50. package/dist/learning.js.map +1 -1
  51. package/dist/model-projects.js +1 -1
  52. package/dist/model-starter-attempts.js +2 -2
  53. package/dist/model-starter-catalog.js +9 -9
  54. package/dist/model-starters.js +13 -9
  55. package/dist/model-taskset-runs.js +3 -3
  56. package/dist/post-training.js +6 -6
  57. package/dist/taskset-drafts.js +12 -12
  58. package/dist/taskset-packages.js +15 -15
  59. package/dist/training-bundle.js +81 -19
  60. package/dist/training-bundle.js.map +1 -1
  61. package/dist/training.js +39 -7
  62. package/dist/types/packages/cloud/src/hosted-chat.d.ts +28 -0
  63. package/dist/types/packages/cloud/src/hosted-chat.d.ts.map +1 -1
  64. package/dist/types/packages/cloud/src/sandbox/sandbox-instance-client.d.ts.map +1 -1
  65. package/dist/types/packages/cloud/src/sandbox/url.d.ts +3 -1
  66. package/dist/types/packages/cloud/src/sandbox/url.d.ts.map +1 -1
  67. package/dist/types/packages/sdk/src/connected-evidence-client.d.ts +4 -0
  68. package/dist/types/packages/sdk/src/connected-evidence-client.d.ts.map +1 -1
  69. package/dist/types/packages/sdk/src/dataset-preparation-workspace.d.ts +2 -0
  70. package/dist/types/packages/sdk/src/dataset-preparation-workspace.d.ts.map +1 -1
  71. package/dist/types/packages/sdk/src/dataset-workspace-client.d.ts +14 -0
  72. package/dist/types/packages/sdk/src/dataset-workspace-client.d.ts.map +1 -1
  73. package/dist/types/packages/sdk/src/dataset-workspace-contracts.d.ts +4 -0
  74. package/dist/types/packages/sdk/src/dataset-workspace-contracts.d.ts.map +1 -1
  75. package/dist/types/packages/sdk/src/dataset-workspace-operations.d.ts +4 -0
  76. package/dist/types/packages/sdk/src/dataset-workspace-operations.d.ts.map +1 -1
  77. package/dist/types/packages/sdk/src/learning-client.d.ts +1 -0
  78. package/dist/types/packages/sdk/src/learning-client.d.ts.map +1 -1
  79. package/dist/types/packages/sdk/src/learning-correction-metrics.d.ts +358 -0
  80. package/dist/types/packages/sdk/src/learning-correction-metrics.d.ts.map +1 -0
  81. package/dist/types/packages/sdk/src/learning.d.ts +1 -0
  82. package/dist/types/packages/sdk/src/learning.d.ts.map +1 -1
  83. package/dist/types/packages/sdk/src/managed-training-preparation.d.ts +24 -0
  84. package/dist/types/packages/sdk/src/managed-training-preparation.d.ts.map +1 -1
  85. package/dist/types/packages/sdk/src/model-bound-taskset-authoring.d.ts.map +1 -1
  86. package/dist/types/packages/sdk/src/model-learning-policy.d.ts +16 -0
  87. package/dist/types/packages/sdk/src/model-learning-policy.d.ts.map +1 -1
  88. package/dist/types/packages/sdk/src/model-projects.d.ts +192 -0
  89. package/dist/types/packages/sdk/src/model-projects.d.ts.map +1 -1
  90. package/dist/types/packages/sdk/src/model-starters.d.ts +84 -1
  91. package/dist/types/packages/sdk/src/model-starters.d.ts.map +1 -1
  92. package/dist/types/packages/sdk/src/model-taskset-runs.d.ts +28 -28
  93. package/dist/types/packages/sdk/src/model-training-defaults.d.ts +14 -0
  94. package/dist/types/packages/sdk/src/model-training-defaults.d.ts.map +1 -1
  95. package/dist/types/packages/sdk/src/post-training.d.ts +54 -0
  96. package/dist/types/packages/sdk/src/post-training.d.ts.map +1 -1
  97. package/dist/types/packages/sdk/src/taskset-authored-files.d.ts.map +1 -1
  98. package/dist/types/packages/sdk/src/taskset-authored-portable-release.d.ts.map +1 -1
  99. package/dist/types/packages/sdk/src/taskset-draft-api-contracts.d.ts +4 -0
  100. package/dist/types/packages/sdk/src/taskset-draft-api-contracts.d.ts.map +1 -1
  101. package/dist/types/packages/sdk/src/taskset-draft-client.d.ts +142 -120
  102. package/dist/types/packages/sdk/src/taskset-draft-client.d.ts.map +1 -1
  103. package/dist/types/packages/sdk/src/taskset-draft-document.d.ts +4 -0
  104. package/dist/types/packages/sdk/src/taskset-draft-document.d.ts.map +1 -1
  105. package/dist/types/packages/sdk/src/taskset-draft-source.d.ts +4 -0
  106. package/dist/types/packages/sdk/src/taskset-draft-source.d.ts.map +1 -1
  107. package/dist/types/packages/sdk/src/taskset-draft-workspace.d.ts +4 -0
  108. package/dist/types/packages/sdk/src/taskset-draft-workspace.d.ts.map +1 -1
  109. package/dist/types/packages/sdk/src/taskset-package-client.d.ts +63 -0
  110. package/dist/types/packages/sdk/src/taskset-package-client.d.ts.map +1 -1
  111. package/dist/types/packages/sdk/src/taskset-package-contracts.d.ts.map +1 -1
  112. package/dist/types/packages/sdk/src/taskset-package-projection.d.ts.map +1 -1
  113. package/dist/types/packages/sdk/src/training-bundle.d.ts.map +1 -1
  114. package/dist/types/packages/sdk/src/training-compute-selection.d.ts +52 -0
  115. package/dist/types/packages/sdk/src/training-compute-selection.d.ts.map +1 -0
  116. package/dist/types/packages/sdk/src/training-estimates.d.ts +1069 -0
  117. package/dist/types/packages/sdk/src/training-estimates.d.ts.map +1 -0
  118. package/dist/types/packages/sdk/src/training-learning-batch.d.ts +40 -40
  119. package/dist/types/packages/sdk/src/training-physical-placement.d.ts +16 -0
  120. package/dist/types/packages/sdk/src/training-physical-placement.d.ts.map +1 -0
  121. package/dist/types/packages/sdk/src/training-preparations.d.ts +248 -0
  122. package/dist/types/packages/sdk/src/training-preparations.d.ts.map +1 -1
  123. package/dist/types/packages/sdk/src/training-qualification-preparation.d.ts +20 -0
  124. package/dist/types/packages/sdk/src/training-qualification-preparation.d.ts.map +1 -1
  125. package/dist/types/packages/sdk/src/training-queue.d.ts +24 -0
  126. package/dist/types/packages/sdk/src/training-queue.d.ts.map +1 -0
  127. package/dist/types/packages/sdk/src/training-recipe-binding.d.ts.map +1 -1
  128. package/dist/types/packages/sdk/src/training-recovery.d.ts +85 -0
  129. package/dist/types/packages/sdk/src/training-recovery.d.ts.map +1 -0
  130. package/dist/types/packages/sdk/src/training-verifier-assets.d.ts +7 -0
  131. package/dist/types/packages/sdk/src/training-verifier-assets.d.ts.map +1 -0
  132. package/dist/types/packages/sdk/src/training.d.ts +599 -0
  133. package/dist/types/packages/sdk/src/training.d.ts.map +1 -1
  134. package/package.json +3 -3
  135. package/dist/chunk-B5XTGEBE.js.map +0 -1
  136. package/dist/chunk-BVMR5OFW.js.map +0 -1
  137. package/dist/chunk-CMWZZZGW.js.map +0 -1
  138. package/dist/chunk-GAIDBPFY.js.map +0 -1
  139. package/dist/chunk-HGXVOFCL.js.map +0 -1
  140. package/dist/chunk-MO4HAJZG.js.map +0 -1
  141. package/dist/chunk-RRKRA237.js.map +0 -1
  142. package/dist/chunk-WQFU635Q.js.map +0 -1
  143. package/dist/chunk-ZIFZFP5I.js.map +0 -1
  144. /package/dist/{chunk-WMIKJGXW.js.map → chunk-3VGTVZHL.js.map} +0 -0
  145. /package/dist/{chunk-U7XWIOSB.js.map → chunk-5T76GARR.js.map} +0 -0
  146. /package/dist/{chunk-QRS7Y3EM.js.map → chunk-B2MKB7NB.js.map} +0 -0
  147. /package/dist/{chunk-EFUT3XKW.js.map → chunk-ETFWUMEJ.js.map} +0 -0
  148. /package/dist/{chunk-VN5V2E2S.js.map → chunk-HRZLFJXX.js.map} +0 -0
  149. /package/dist/{chunk-I54WQBXL.js.map → chunk-KD6MM67B.js.map} +0 -0
  150. /package/dist/{chunk-ZHQK3MOM.js.map → chunk-LIMTJR3A.js.map} +0 -0
  151. /package/dist/{chunk-VHGC44HA.js.map → chunk-RDL6QIQO.js.map} +0 -0
  152. /package/dist/{chunk-LHX7ENKZ.js.map → chunk-S2IASCGW.js.map} +0 -0
  153. /package/dist/{chunk-XON75UFN.js.map → chunk-SER76PQ7.js.map} +0 -0
  154. /package/dist/{chunk-ETX25FTB.js.map → chunk-SMHZT6RM.js.map} +0 -0
  155. /package/dist/{chunk-24N6A6SF.js.map → chunk-SQBYHWZU.js.map} +0 -0
  156. /package/dist/{chunk-DF2QXVZ3.js.map → chunk-VBVFE33M.js.map} +0 -0
  157. /package/dist/{chunk-53LLNDXF.js.map → chunk-VQGTYGZH.js.map} +0 -0
  158. /package/dist/{chunk-OR3TMIJN.js.map → chunk-VTAGUWXH.js.map} +0 -0
  159. /package/dist/{chunk-LR5CTOC5.js.map → chunk-XF3JR72U.js.map} +0 -0
  160. /package/dist/{chunk-K5LWSWV7.js.map → chunk-ZGZLN4LH.js.map} +0 -0
@@ -1,26 +1,28 @@
1
1
  import {
2
2
  prepareImportedTasksetPackage,
3
3
  projectLearningBatchGraders
4
- } from "./chunk-CMWZZZGW.js";
4
+ } from "./chunk-QDYHSJT5.js";
5
5
  import {
6
6
  projectPortableTaskRecord,
7
7
  resolvePortableTasksetRewardExecution
8
- } from "./chunk-WQFU635Q.js";
8
+ } from "./chunk-ATVQQCYN.js";
9
9
  import {
10
+ TasksetDraftOutputContractSchema,
10
11
  TasksetSchema,
11
12
  computeTasksetHash
12
- } from "./chunk-GAIDBPFY.js";
13
+ } from "./chunk-ONGOAEY6.js";
13
14
  import {
14
15
  LearningBatchDatasetSourceRefSchema,
15
16
  MAX_TASKSET_PACKAGE_BYTES,
16
17
  decodeTasksetPackageFile,
17
18
  validateTasksetPackage
18
- } from "./chunk-MO4HAJZG.js";
19
+ } from "./chunk-2XLKMZH5.js";
19
20
  import "./chunk-TK3DXH7A.js";
20
21
  import {
21
22
  TRAINING_EVALUATION_SOURCE_PATH,
22
23
  TrainingCapabilitiesSchema,
23
24
  TrainingEvaluationSourceSchema,
25
+ TrainingPhysicalPlacementSchema,
24
26
  assertTrainingEvaluationIsolation,
25
27
  deterministicTrainingRewardSource,
26
28
  parseAndVerifyTrainingInputArtifactUpload,
@@ -28,11 +30,11 @@ import {
28
30
  trainingEvaluationSourceRef,
29
31
  trainingInputArtifactUploadHash,
30
32
  trainingJobSubmissionHash
31
- } from "./chunk-RRKRA237.js";
33
+ } from "./chunk-Z4XGSEKC.js";
32
34
  import {
33
35
  TrainingHandoffOriginSchema
34
- } from "./chunk-ZHQK3MOM.js";
35
- import "./chunk-WMIKJGXW.js";
36
+ } from "./chunk-LIMTJR3A.js";
37
+ import "./chunk-3VGTVZHL.js";
36
38
  import {
37
39
  HarnessSourceSelectionSchema,
38
40
  createAgentSnapshot,
@@ -41,10 +43,12 @@ import {
41
43
  validateHarnessSourcePackage
42
44
  } from "./chunk-Q4TKI2MV.js";
43
45
  import "./chunk-H3367ISL.js";
44
- import "./chunk-QRS7Y3EM.js";
45
- import "./chunk-VN5V2E2S.js";
46
- import "./chunk-U7XWIOSB.js";
47
- import "./chunk-HGXVOFCL.js";
46
+ import "./chunk-B2MKB7NB.js";
47
+ import "./chunk-HRZLFJXX.js";
48
+ import "./chunk-5T76GARR.js";
49
+ import {
50
+ TrainingGpuSelectionSchema
51
+ } from "./chunk-3SIGXGAE.js";
48
52
  import "./chunk-CL3IOOVL.js";
49
53
  import {
50
54
  ImmutableReleaseRefSchema,
@@ -367,6 +371,7 @@ async function prepareManagedTrainingSubmission(raw) {
367
371
  const manifest = HarnessRunManifestSchema.parse(input.manifest);
368
372
  const bundle = ResolvedTrainingBundleManifestSchema.parse(input.bundleManifest);
369
373
  const qualification = input.executionMode === "qualification";
374
+ const physicalPlacement = input.physicalPlacement ? TrainingPhysicalPlacementSchema.parse(input.physicalPlacement) : void 0;
370
375
  const qualificationGroupSize = manifest.qualificationSamples === void 0 ? null : z2.object({ rollout: z2.object({ groupSize: z2.number().int().min(2).max(32) }).passthrough() }).passthrough().parse(recipe).rollout.groupSize;
371
376
  if (manifest.qualificationSamples !== bundle.qualificationSamples || manifest.qualificationSamples !== void 0 && (!qualification || manifest.qualificationSamples > qualificationGroupSize)) {
372
377
  throw new Error("Qualification samples must be within the pinned rollout group and cannot be used for training.");
@@ -411,6 +416,7 @@ async function prepareManagedTrainingSubmission(raw) {
411
416
  schemaVersion: "openpond.managedRlPortableSubmission.v1",
412
417
  ...qualification ? { executionMode: "qualification" } : {},
413
418
  ...input.origin ? { origin: TrainingHandoffOriginSchema.parse(input.origin) } : {},
419
+ ...physicalPlacement ? { physicalPlacement } : {},
414
420
  sourceRunRef: `openpond:model-run:${manifest.id}`,
415
421
  name: `OpenPond Managed \xB7 ${project.id}`.slice(0, 191),
416
422
  idempotencyKey: input.idempotencyKey ?? `openpond-managed:${manifestHash}`.slice(0, 191),
@@ -475,6 +481,8 @@ async function prepareManagedTrainingSubmission(raw) {
475
481
  ...project.trainingSetup.managedGpuRequirement === "h100_hbm3" ? [{ id: "managed_rl.gpu.h100_hbm3", version: "1", required: true }] : []
476
482
  ],
477
483
  placementObjective: project.trainingSetup.managedGpuPlacementObjective,
484
+ ...input.gpuSelection ?? project.trainingSetup.managedGpuSelection ? { gpuSelection: TrainingGpuSelectionSchema.parse(input.gpuSelection ?? project.trainingSetup.managedGpuSelection) } : {},
485
+ ...physicalPlacement ? { physicalPlacement } : {},
478
486
  budget: {
479
487
  maximumSpendUsd: approval.maximumSpendUsd,
480
488
  maximumWallSeconds: Math.ceil(limits.wallTimeMs / 1e3)
@@ -598,6 +606,8 @@ function withAuthoritativeRecipeHashes(taskset, recipe) {
598
606
  const maxPromptTokens = positiveInteger(dataset.maxPromptTokens, 1);
599
607
  const maxSteps = positiveInteger(optimizer.maxSteps, 1);
600
608
  const optimizerIterations = positiveInteger(optimizer.iterations, 2);
609
+ const maxRollouts = positiveInteger(resourceLimits.maxRollouts, maxSteps * groupSize);
610
+ const maxTurns = positiveInteger(rollout.maxTurns, 1);
601
611
  return {
602
612
  ...candidate,
603
613
  resourceLimits: {
@@ -646,10 +656,12 @@ function withAuthoritativeRecipeHashes(taskset, recipe) {
646
656
  referenceConstraint: "fixed_reference"
647
657
  },
648
658
  budgets: {
649
- maxRollouts: positiveInteger(resourceLimits.maxRollouts, maxExamples * groupSize),
650
- maxEnvironmentExecutions: positiveInteger(resourceLimits.maxRollouts, maxExamples * groupSize),
651
- maxInputTokens: maxExamples * groupSize * maxPromptTokens,
652
- maxOutputTokens: maxExamples * groupSize * maxOutputTokens,
659
+ maxRollouts,
660
+ maxEnvironmentExecutions: maxRollouts,
661
+ // Tasks can be sampled over multiple groups, and every tool turn can
662
+ // generate another policy request within the same rollout.
663
+ maxInputTokens: maxRollouts * maxTurns * maxPromptTokens,
664
+ maxOutputTokens: maxRollouts * maxTurns * maxOutputTokens,
653
665
  maxOptimizerSteps: maxSteps * optimizerIterations,
654
666
  wallTimeMs: positiveInteger(resourceLimits.wallTimeMs, 18e4),
655
667
  maximumCostUsd: null
@@ -768,6 +780,48 @@ function asset(input) {
768
780
  // src/training-qualification-preparation.ts
769
781
  import { createRewardBinding, createRewardRelease, compileBoundGraders } from "@openpond/evals/rewards";
770
782
  import { LearningTextAssetSchema, sealLearningContent } from "@openpond/evals/learning";
783
+
784
+ // src/training-verifier-assets.ts
785
+ async function qualificationVerifierAssets(source, entry) {
786
+ const [{ isBuiltin }, { posix }, { build }] = await Promise.all([
787
+ import("node:module"),
788
+ import("node:path"),
789
+ import("esbuild")
790
+ ]);
791
+ const files = new Map(source.files.map((file) => [file.asset.path, file]));
792
+ const selected = /* @__PURE__ */ new Map();
793
+ await build({
794
+ entryPoints: [entry.path],
795
+ bundle: true,
796
+ write: false,
797
+ platform: "node",
798
+ format: "esm",
799
+ treeShaking: false,
800
+ logLevel: "silent",
801
+ plugins: [{ name: "qualification-private-modules", setup(builder) {
802
+ builder.onResolve({ filter: /.*/ }, (args) => {
803
+ if (args.kind !== "entry-point" && isBuiltin(args.path)) return { path: args.path, external: true };
804
+ if (args.kind !== "entry-point" && !args.path.startsWith("./") && !args.path.startsWith("../")) {
805
+ throw new Error(`Qualification verifier import must be a declared relative module or Node builtin: ${args.path}.`);
806
+ }
807
+ const path = args.kind === "entry-point" ? args.path : posix.normalize(posix.join(posix.dirname(args.importer), args.path));
808
+ const file = files.get(path);
809
+ if (!file || file.asset.visibility !== "verifier" || !/\.[cm]?js$/.test(path)) {
810
+ throw new Error(`Qualification verifier dependency requires a declared verifier-visible JavaScript asset: ${path}.`);
811
+ }
812
+ return { path, namespace: "qualification-private-modules" };
813
+ });
814
+ builder.onLoad({ filter: /.*/, namespace: "qualification-private-modules" }, (args) => {
815
+ const file = files.get(args.path);
816
+ selected.set(file.asset.id, file.asset);
817
+ return { contents: new TextDecoder("utf-8", { fatal: true }).decode(decodeTasksetPackageFile(file)), loader: "js" };
818
+ });
819
+ } }]
820
+ });
821
+ return [...selected.values()].sort((left, right) => left.path.localeCompare(right.path));
822
+ }
823
+
824
+ // src/training-qualification-preparation.ts
771
825
  async function prepareOrdinaryTasksetQualification(input) {
772
826
  const source = validateTasksetPackage(input.package);
773
827
  if (source.taskset.tasks.some((task) => task.requiredOutputs?.some((output) => output.submissionMode === "structured_json"))) {
@@ -782,7 +836,7 @@ async function prepareOrdinaryTasksetQualification(input) {
782
836
  if (source.taskset.tasks.some((task) => task.privilegedContextRef !== null || task.artifactRefs.some((asset2) => asset2.visibility !== "policy"))) {
783
837
  throw new Error("Qualification runtime requires private targets in expectedOutput and policy-only task assets.");
784
838
  }
785
- const rewards = source.taskset.graders.map((grader) => {
839
+ const rewards = await Promise.all(source.taskset.graders.map(async (grader) => {
786
840
  const { id, version, weight: _weight, hardGate: _gate, rewardEligible: _eligible, privileged: _private, taskIds: _tasks, ...implementation } = grader;
787
841
  const revision = Number(version);
788
842
  if (!Number.isSafeInteger(revision) || revision < 1 || String(revision) !== version || implementation.kind === "model_judge" || implementation.kind === "human") {
@@ -796,9 +850,9 @@ async function prepareOrdinaryTasksetQualification(input) {
796
850
  description: "Exact ordinary package grader for no-update qualification.",
797
851
  implementation,
798
852
  rawScore: { minimum: 0, maximum: 1 },
799
- assets: implementation.kind === "custom_verifier" ? [implementation.verifierRef] : []
853
+ assets: implementation.kind === "custom_verifier" ? await qualificationVerifierAssets(source, implementation.verifierRef) : []
800
854
  });
801
- });
855
+ }));
802
856
  const binding = createRewardBinding({
803
857
  schemaVersion: "openpond.rewardBinding.v1",
804
858
  id: `qualification-${source.contentHash.slice(0, 40)}`,
@@ -964,9 +1018,17 @@ function buildTasksetTrainingBundle(input) {
964
1018
  } else if (input.verifierAssets?.length) {
965
1019
  throw new Error("Private verifier assets require a published Reward binding.");
966
1020
  }
1021
+ const outputContract = taskset.metadata.tasksetOutputContract;
1022
+ if (outputContract && typeof outputContract === "object" && "responsePath" in outputContract) {
1023
+ TasksetDraftOutputContractSchema.parse({ jsonSchema: null, renderer: null, ...outputContract });
1024
+ }
967
1025
  addJsonAsset(assets, "environment.json", {
968
1026
  schemaVersion: "openpond.harnessEnvironment.v1",
969
- environment: qualification ? { ...taskset.environment, metadata: { ...taskset.environment.metadata, policySystemPrompt: taskset.objective } } : taskset.environment,
1027
+ // Authored instructions are part of every policy run. Qualification already
1028
+ // binds this value; training must not silently fall back to a generic prompt.
1029
+ // The objective owns this field, while selected Harness source remains a
1030
+ // separate immutable input composed by the runtime.
1031
+ environment: { ...taskset.environment, metadata: { ...taskset.environment.metadata, policySystemPrompt: taskset.objective } },
970
1032
  capabilities: taskset.capabilities,
971
1033
  policy: taskset.policy,
972
1034
  outputContract: taskset.metadata.tasksetOutputContract?.mode === "text" ? null : taskset.metadata.tasksetOutputContract ?? null