agent-hitch 0.2.6 → 0.2.8

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 (562) hide show
  1. package/README.md +30 -3
  2. package/README.zh-CN.md +14 -2
  3. package/dist/bin/hitch.js +25 -3
  4. package/dist/bin/hitch.js.map +1 -1
  5. package/dist/scripts/canary-benchmark.js +54 -0
  6. package/dist/scripts/canary-benchmark.js.map +1 -0
  7. package/dist/scripts/canary-buildkit-secrets.js +166 -0
  8. package/dist/scripts/canary-buildkit-secrets.js.map +1 -0
  9. package/dist/scripts/canary-collision-domains.js +77 -0
  10. package/dist/scripts/canary-collision-domains.js.map +1 -0
  11. package/dist/scripts/canary-docker-image-observation.js +181 -0
  12. package/dist/scripts/canary-docker-image-observation.js.map +1 -0
  13. package/dist/scripts/canary-eval-scheduler-throughput.js +47 -0
  14. package/dist/scripts/canary-eval-scheduler-throughput.js.map +1 -0
  15. package/dist/scripts/canary-gpu-hardware.js +95 -0
  16. package/dist/scripts/canary-gpu-hardware.js.map +1 -0
  17. package/dist/scripts/canary-harbor-load.js +365 -0
  18. package/dist/scripts/canary-harbor-load.js.map +1 -0
  19. package/dist/scripts/canary-packaged-harness.js +75 -0
  20. package/dist/scripts/canary-packaged-harness.js.map +1 -0
  21. package/dist/scripts/canary-resource-load.js +188 -0
  22. package/dist/scripts/canary-resource-load.js.map +1 -0
  23. package/dist/scripts/check-architecture.js +10 -5
  24. package/dist/scripts/check-architecture.js.map +1 -1
  25. package/dist/scripts/docker-reaper-crash-child.js +21 -0
  26. package/dist/scripts/docker-reaper-crash-child.js.map +1 -0
  27. package/dist/src/adapters/catalog.js +3 -1
  28. package/dist/src/adapters/catalog.js.map +1 -1
  29. package/dist/src/adapters/discovery.js +1 -1
  30. package/dist/src/adapters/discovery.js.map +1 -1
  31. package/dist/src/adapters/providers/claude.js +6 -0
  32. package/dist/src/adapters/providers/claude.js.map +1 -1
  33. package/dist/src/adapters/providers/codex-auth.js +29 -0
  34. package/dist/src/adapters/providers/codex-auth.js.map +1 -0
  35. package/dist/src/adapters/providers/codex.js +29 -6
  36. package/dist/src/adapters/providers/codex.js.map +1 -1
  37. package/dist/src/adapters/providers/deepseek.js +6 -0
  38. package/dist/src/adapters/providers/deepseek.js.map +1 -1
  39. package/dist/src/adapters/providers/model-call.js +26 -0
  40. package/dist/src/adapters/providers/model-call.js.map +1 -0
  41. package/dist/src/adapters/providers/opencode.js +6 -0
  42. package/dist/src/adapters/providers/opencode.js.map +1 -1
  43. package/dist/src/adapters/providers/pi.js +6 -0
  44. package/dist/src/adapters/providers/pi.js.map +1 -1
  45. package/dist/src/artifacts/index.js +1 -0
  46. package/dist/src/artifacts/index.js.map +1 -1
  47. package/dist/src/artifacts/preparer.js +7 -2
  48. package/dist/src/artifacts/preparer.js.map +1 -1
  49. package/dist/src/backends/harbor/agent-budget.js +31 -0
  50. package/dist/src/backends/harbor/agent-budget.js.map +1 -0
  51. package/dist/src/backends/harbor/backend.js +59 -107
  52. package/dist/src/backends/harbor/backend.js.map +1 -1
  53. package/dist/src/backends/harbor/environment-config.js +92 -0
  54. package/dist/src/backends/harbor/environment-config.js.map +1 -0
  55. package/dist/src/backends/harbor/index.js +6 -1
  56. package/dist/src/backends/harbor/index.js.map +1 -1
  57. package/dist/src/backends/harbor/model-proxy-config.js +23 -0
  58. package/dist/src/backends/harbor/model-proxy-config.js.map +1 -0
  59. package/dist/src/backends/harbor/process.js +177 -0
  60. package/dist/src/backends/harbor/process.js.map +1 -0
  61. package/dist/src/backends/harbor/regrade.js +77 -0
  62. package/dist/src/backends/harbor/regrade.js.map +1 -0
  63. package/dist/src/backends/harbor/runtime-toolchain.js +30 -0
  64. package/dist/src/backends/harbor/runtime-toolchain.js.map +1 -0
  65. package/dist/src/backends/harbor/supervisor.js +74 -0
  66. package/dist/src/backends/harbor/supervisor.js.map +1 -0
  67. package/dist/src/backends/harbor/task-resources.js +206 -0
  68. package/dist/src/backends/harbor/task-resources.js.map +1 -0
  69. package/dist/src/backends/harbor/tools.js +6 -29
  70. package/dist/src/backends/harbor/tools.js.map +1 -1
  71. package/dist/src/backends/index.js +5 -1
  72. package/dist/src/backends/index.js.map +1 -1
  73. package/dist/src/benchmarks/index.js +3 -0
  74. package/dist/src/benchmarks/index.js.map +1 -0
  75. package/dist/src/benchmarks/loader.js +271 -0
  76. package/dist/src/benchmarks/loader.js.map +1 -0
  77. package/dist/src/benchmarks/metrics.js +16 -0
  78. package/dist/src/benchmarks/metrics.js.map +1 -0
  79. package/dist/src/benchmarks/toml.js +13 -0
  80. package/dist/src/benchmarks/toml.js.map +1 -0
  81. package/dist/src/benchmarks/validation.js +242 -0
  82. package/dist/src/benchmarks/validation.js.map +1 -0
  83. package/dist/src/cli/arguments.js +6 -4
  84. package/dist/src/cli/arguments.js.map +1 -1
  85. package/dist/src/cli/commands/benchmark.js +22 -0
  86. package/dist/src/cli/commands/benchmark.js.map +1 -0
  87. package/dist/src/cli/commands/capabilities.js +18 -0
  88. package/dist/src/cli/commands/capabilities.js.map +1 -0
  89. package/dist/src/cli/commands/daemon.js +135 -8
  90. package/dist/src/cli/commands/daemon.js.map +1 -1
  91. package/dist/src/cli/commands/eval.js +228 -6
  92. package/dist/src/cli/commands/eval.js.map +1 -1
  93. package/dist/src/cli/commands/images.js +40 -0
  94. package/dist/src/cli/commands/images.js.map +1 -0
  95. package/dist/src/cli/commands/run.js +42 -17
  96. package/dist/src/cli/commands/run.js.map +1 -1
  97. package/dist/src/cli/commands/runs.js +25 -3
  98. package/dist/src/cli/commands/runs.js.map +1 -1
  99. package/dist/src/cli/commands/trajectory.js +96 -5
  100. package/dist/src/cli/commands/trajectory.js.map +1 -1
  101. package/dist/src/cli/commands/verifier.js +36 -0
  102. package/dist/src/cli/commands/verifier.js.map +1 -0
  103. package/dist/src/cli/commands/worker.js +79 -0
  104. package/dist/src/cli/commands/worker.js.map +1 -0
  105. package/dist/src/cli/main.js +10 -0
  106. package/dist/src/cli/main.js.map +1 -1
  107. package/dist/src/cli/output.js +84 -4
  108. package/dist/src/cli/output.js.map +1 -1
  109. package/dist/src/control-plane/build-admission.js +69 -0
  110. package/dist/src/control-plane/build-admission.js.map +1 -0
  111. package/dist/src/control-plane/build-records.js +6 -0
  112. package/dist/src/control-plane/build-records.js.map +1 -0
  113. package/dist/src/control-plane/collisions.js +40 -0
  114. package/dist/src/control-plane/collisions.js.map +1 -0
  115. package/dist/src/control-plane/eval-control-state.js +22 -0
  116. package/dist/src/control-plane/eval-control-state.js.map +1 -0
  117. package/dist/src/control-plane/eval-control-work.js +44 -0
  118. package/dist/src/control-plane/eval-control-work.js.map +1 -0
  119. package/dist/src/control-plane/eval-image-resolution.js +52 -0
  120. package/dist/src/control-plane/eval-image-resolution.js.map +1 -0
  121. package/dist/src/control-plane/eval-image-services.js +30 -0
  122. package/dist/src/control-plane/eval-image-services.js.map +1 -0
  123. package/dist/src/control-plane/eval-records.js +252 -0
  124. package/dist/src/control-plane/eval-records.js.map +1 -0
  125. package/dist/src/control-plane/eval-recovery.js +181 -0
  126. package/dist/src/control-plane/eval-recovery.js.map +1 -0
  127. package/dist/src/control-plane/eval-scheduler.js +450 -0
  128. package/dist/src/control-plane/eval-scheduler.js.map +1 -0
  129. package/dist/src/control-plane/index.js +20 -0
  130. package/dist/src/control-plane/index.js.map +1 -0
  131. package/dist/src/control-plane/local-worker.js +49 -0
  132. package/dist/src/control-plane/local-worker.js.map +1 -0
  133. package/dist/src/control-plane/model-capture-planning.js +12 -0
  134. package/dist/src/control-plane/model-capture-planning.js.map +1 -0
  135. package/dist/src/control-plane/remote-result-transport.js +175 -0
  136. package/dist/src/control-plane/remote-result-transport.js.map +1 -0
  137. package/dist/src/control-plane/remote-work-coordinator.js +333 -0
  138. package/dist/src/control-plane/remote-work-coordinator.js.map +1 -0
  139. package/dist/src/control-plane/remote-work-inputs.js +266 -0
  140. package/dist/src/control-plane/remote-work-inputs.js.map +1 -0
  141. package/dist/src/control-plane/remote-work-item.js +62 -0
  142. package/dist/src/control-plane/remote-work-item.js.map +1 -0
  143. package/dist/src/control-plane/remote-work-recovery.js +220 -0
  144. package/dist/src/control-plane/remote-work-recovery.js.map +1 -0
  145. package/dist/src/control-plane/remote-worker-artifacts.js +135 -0
  146. package/dist/src/control-plane/remote-worker-artifacts.js.map +1 -0
  147. package/dist/src/control-plane/remote-worker-client.js +202 -0
  148. package/dist/src/control-plane/remote-worker-client.js.map +1 -0
  149. package/dist/src/control-plane/remote-worker-configuration.js +34 -0
  150. package/dist/src/control-plane/remote-worker-configuration.js.map +1 -0
  151. package/dist/src/control-plane/remote-worker-credentials.js +58 -0
  152. package/dist/src/control-plane/remote-worker-credentials.js.map +1 -0
  153. package/dist/src/control-plane/remote-worker-protocol.js +489 -0
  154. package/dist/src/control-plane/remote-worker-protocol.js.map +1 -0
  155. package/dist/src/control-plane/remote-worker-runner.js +214 -0
  156. package/dist/src/control-plane/remote-worker-runner.js.map +1 -0
  157. package/dist/src/control-plane/remote-workers.js +377 -0
  158. package/dist/src/control-plane/remote-workers.js.map +1 -0
  159. package/dist/src/control-plane/rerun-scheduler.js +448 -0
  160. package/dist/src/control-plane/rerun-scheduler.js.map +1 -0
  161. package/dist/src/control-plane/rerun-submission.js +62 -0
  162. package/dist/src/control-plane/rerun-submission.js.map +1 -0
  163. package/dist/src/control-plane/resources.js +182 -0
  164. package/dist/src/control-plane/resources.js.map +1 -0
  165. package/dist/src/control-plane/scheduler-eval-entry.js +32 -0
  166. package/dist/src/control-plane/scheduler-eval-entry.js.map +1 -0
  167. package/dist/src/control-plane/synthetic-result.js +21 -0
  168. package/dist/src/control-plane/synthetic-result.js.map +1 -0
  169. package/dist/src/control-plane/work-admission.js +23 -0
  170. package/dist/src/control-plane/work-admission.js.map +1 -0
  171. package/dist/src/control-plane/work-dispatcher.js +237 -0
  172. package/dist/src/control-plane/work-dispatcher.js.map +1 -0
  173. package/dist/src/controller-runtime/hash.js +19 -3
  174. package/dist/src/controller-runtime/hash.js.map +1 -1
  175. package/dist/src/controller-runtime/index.js +1 -1
  176. package/dist/src/controller-runtime/index.js.map +1 -1
  177. package/dist/src/controller-runtime/store.js +15 -6
  178. package/dist/src/controller-runtime/store.js.map +1 -1
  179. package/dist/src/daemon/auth.js +5 -0
  180. package/dist/src/daemon/auth.js.map +1 -1
  181. package/dist/src/daemon/client.js.map +1 -1
  182. package/dist/src/daemon/event-stream.js +46 -0
  183. package/dist/src/daemon/event-stream.js.map +1 -0
  184. package/dist/src/daemon/health.js +66 -0
  185. package/dist/src/daemon/health.js.map +1 -0
  186. package/dist/src/daemon/launcher.js +28 -1
  187. package/dist/src/daemon/launcher.js.map +1 -1
  188. package/dist/src/daemon/logging.js +23 -0
  189. package/dist/src/daemon/logging.js.map +1 -0
  190. package/dist/src/daemon/scheduler.js +26 -5
  191. package/dist/src/daemon/scheduler.js.map +1 -1
  192. package/dist/src/daemon/server.js +255 -98
  193. package/dist/src/daemon/server.js.map +1 -1
  194. package/dist/src/daemon/telemetry.js +163 -0
  195. package/dist/src/daemon/telemetry.js.map +1 -0
  196. package/dist/src/daemon/worker-routes.js +219 -0
  197. package/dist/src/daemon/worker-routes.js.map +1 -0
  198. package/dist/src/domain/benchmarks.js +2 -0
  199. package/dist/src/domain/benchmarks.js.map +1 -0
  200. package/dist/src/domain/bundles.js +2 -0
  201. package/dist/src/domain/bundles.js.map +1 -0
  202. package/dist/src/domain/control-plane.js +2 -0
  203. package/dist/src/domain/control-plane.js.map +1 -0
  204. package/dist/src/domain/execution-evidence.js +2 -0
  205. package/dist/src/domain/execution-evidence.js.map +1 -0
  206. package/dist/src/domain/execution-plan.js +2 -0
  207. package/dist/src/domain/execution-plan.js.map +1 -0
  208. package/dist/src/domain/images.js +2 -0
  209. package/dist/src/domain/images.js.map +1 -0
  210. package/dist/src/domain/index.js +13 -0
  211. package/dist/src/domain/index.js.map +1 -1
  212. package/dist/src/domain/interactions.js +2 -0
  213. package/dist/src/domain/interactions.js.map +1 -0
  214. package/dist/src/domain/providers.js +2 -0
  215. package/dist/src/domain/providers.js.map +1 -0
  216. package/dist/src/domain/resources.js +2 -0
  217. package/dist/src/domain/resources.js.map +1 -0
  218. package/dist/src/domain/runs.js.map +1 -1
  219. package/dist/src/domain/validation.js +11 -4
  220. package/dist/src/domain/validation.js.map +1 -1
  221. package/dist/src/domain/verifier-evidence-validation.js +214 -0
  222. package/dist/src/domain/verifier-evidence-validation.js.map +1 -0
  223. package/dist/src/domain/verifier-evidence.js +3 -0
  224. package/dist/src/domain/verifier-evidence.js.map +1 -0
  225. package/dist/src/domain/verifier-score-contract.js +232 -0
  226. package/dist/src/domain/verifier-score-contract.js.map +1 -0
  227. package/dist/src/domain/workers.js +2 -0
  228. package/dist/src/domain/workers.js.map +1 -0
  229. package/dist/src/evals/benchmark-adapter-manifest.js +219 -0
  230. package/dist/src/evals/benchmark-adapter-manifest.js.map +1 -0
  231. package/dist/src/evals/benchmark-candidate.js +36 -0
  232. package/dist/src/evals/benchmark-candidate.js.map +1 -0
  233. package/dist/src/evals/benchmark-run.js +166 -0
  234. package/dist/src/evals/benchmark-run.js.map +1 -0
  235. package/dist/src/evals/collect-only-rerun.js +183 -0
  236. package/dist/src/evals/collect-only-rerun.js.map +1 -0
  237. package/dist/src/evals/directory.js +30 -0
  238. package/dist/src/evals/directory.js.map +1 -0
  239. package/dist/src/evals/docker-engine-stats.js +89 -0
  240. package/dist/src/evals/docker-engine-stats.js.map +1 -0
  241. package/dist/src/evals/docker-ownership.js +51 -0
  242. package/dist/src/evals/docker-ownership.js.map +1 -0
  243. package/dist/src/evals/docker-reaper.js +144 -0
  244. package/dist/src/evals/docker-reaper.js.map +1 -0
  245. package/dist/src/evals/docker-resource-observer.js +207 -0
  246. package/dist/src/evals/docker-resource-observer.js.map +1 -0
  247. package/dist/src/evals/duration-estimator.js +126 -0
  248. package/dist/src/evals/duration-estimator.js.map +1 -0
  249. package/dist/src/evals/environment-image-planning.js +164 -0
  250. package/dist/src/evals/environment-image-planning.js.map +1 -0
  251. package/dist/src/evals/eval-artifact-planning.js +56 -0
  252. package/dist/src/evals/eval-artifact-planning.js.map +1 -0
  253. package/dist/src/evals/eval-finalization.js +10 -0
  254. package/dist/src/evals/eval-finalization.js.map +1 -0
  255. package/dist/src/evals/eval-lifecycle-events.js +29 -0
  256. package/dist/src/evals/eval-lifecycle-events.js.map +1 -0
  257. package/dist/src/evals/eval-logical-plan.js +51 -0
  258. package/dist/src/evals/eval-logical-plan.js.map +1 -0
  259. package/dist/src/evals/eval-result-builder.js +81 -0
  260. package/dist/src/evals/eval-result-builder.js.map +1 -0
  261. package/dist/src/evals/events.js +53 -5
  262. package/dist/src/evals/events.js.map +1 -1
  263. package/dist/src/evals/evolution-baseline.js +191 -0
  264. package/dist/src/evals/evolution-baseline.js.map +1 -0
  265. package/dist/src/evals/execution-evidence.js +116 -0
  266. package/dist/src/evals/execution-evidence.js.map +1 -0
  267. package/dist/src/evals/execution-leases.js +342 -0
  268. package/dist/src/evals/execution-leases.js.map +1 -0
  269. package/dist/src/evals/execution-plan-artifacts.js +72 -0
  270. package/dist/src/evals/execution-plan-artifacts.js.map +1 -0
  271. package/dist/src/evals/execution-plan-images.js +69 -0
  272. package/dist/src/evals/execution-plan-images.js.map +1 -0
  273. package/dist/src/evals/execution-plan-resources.js +174 -0
  274. package/dist/src/evals/execution-plan-resources.js.map +1 -0
  275. package/dist/src/evals/execution-plan.js +451 -0
  276. package/dist/src/evals/execution-plan.js.map +1 -0
  277. package/dist/src/evals/failure-classifier.js +61 -0
  278. package/dist/src/evals/failure-classifier.js.map +1 -0
  279. package/dist/src/evals/harbor-artifact-builder-image.js +99 -0
  280. package/dist/src/evals/harbor-artifact-builder-image.js.map +1 -0
  281. package/dist/src/evals/harbor-artifact-builder.js +358 -0
  282. package/dist/src/evals/harbor-artifact-builder.js.map +1 -0
  283. package/dist/src/evals/harbor-bridge-error.js +58 -3
  284. package/dist/src/evals/harbor-bridge-error.js.map +1 -1
  285. package/dist/src/evals/harbor-node-runtime.js +146 -0
  286. package/dist/src/evals/harbor-node-runtime.js.map +1 -0
  287. package/dist/src/evals/harbor-phase-timings.js +60 -0
  288. package/dist/src/evals/harbor-phase-timings.js.map +1 -0
  289. package/dist/src/evals/index.js +40 -2
  290. package/dist/src/evals/index.js.map +1 -1
  291. package/dist/src/evals/infrastructure-retry.js +208 -84
  292. package/dist/src/evals/infrastructure-retry.js.map +1 -1
  293. package/dist/src/evals/interaction-capture-import.js +49 -0
  294. package/dist/src/evals/interaction-capture-import.js.map +1 -0
  295. package/dist/src/evals/local-docker-provider.js +372 -0
  296. package/dist/src/evals/local-docker-provider.js.map +1 -0
  297. package/dist/src/evals/local-eval-planning.js +80 -0
  298. package/dist/src/evals/local-eval-planning.js.map +1 -0
  299. package/dist/src/evals/model-capture-plan.js +22 -0
  300. package/dist/src/evals/model-capture-plan.js.map +1 -0
  301. package/dist/src/evals/model-capture-runtime.js +114 -0
  302. package/dist/src/evals/model-capture-runtime.js.map +1 -0
  303. package/dist/src/evals/model-proxy-runtime-state.js +53 -0
  304. package/dist/src/evals/model-proxy-runtime-state.js.map +1 -0
  305. package/dist/src/evals/native-phase-evidence.js +440 -0
  306. package/dist/src/evals/native-phase-evidence.js.map +1 -0
  307. package/dist/src/evals/physical-retry-work.js +31 -0
  308. package/dist/src/evals/physical-retry-work.js.map +1 -0
  309. package/dist/src/evals/planned-execution-support.js +66 -0
  310. package/dist/src/evals/planned-execution-support.js.map +1 -0
  311. package/dist/src/evals/planned-execution.js +469 -0
  312. package/dist/src/evals/planned-execution.js.map +1 -0
  313. package/dist/src/evals/planned-progress-publisher.js +62 -0
  314. package/dist/src/evals/planned-progress-publisher.js.map +1 -0
  315. package/dist/src/evals/planned-remote-execution.js +40 -0
  316. package/dist/src/evals/planned-remote-execution.js.map +1 -0
  317. package/dist/src/evals/planned-retry-execution.js +174 -0
  318. package/dist/src/evals/planned-retry-execution.js.map +1 -0
  319. package/dist/src/evals/planned-retry-lifecycle.js +188 -0
  320. package/dist/src/evals/planned-retry-lifecycle.js.map +1 -0
  321. package/dist/src/evals/preparation-rerun.js +225 -0
  322. package/dist/src/evals/preparation-rerun.js.map +1 -0
  323. package/dist/src/evals/prepared-harness.js +76 -0
  324. package/dist/src/evals/prepared-harness.js.map +1 -0
  325. package/dist/src/evals/progress.js +52 -12
  326. package/dist/src/evals/progress.js.map +1 -1
  327. package/dist/src/evals/records.js +20 -3
  328. package/dist/src/evals/records.js.map +1 -1
  329. package/dist/src/evals/recovery.js +242 -0
  330. package/dist/src/evals/recovery.js.map +1 -0
  331. package/dist/src/evals/regrade-evidence.js +77 -0
  332. package/dist/src/evals/regrade-evidence.js.map +1 -0
  333. package/dist/src/evals/remote-infrastructure-retry.js +165 -0
  334. package/dist/src/evals/remote-infrastructure-retry.js.map +1 -0
  335. package/dist/src/evals/request.js +21 -3
  336. package/dist/src/evals/request.js.map +1 -1
  337. package/dist/src/evals/rerun-inputs.js +108 -0
  338. package/dist/src/evals/rerun-inputs.js.map +1 -0
  339. package/dist/src/evals/rerun-slots.js +4 -3
  340. package/dist/src/evals/rerun-slots.js.map +1 -1
  341. package/dist/src/evals/rerun-types.js +45 -0
  342. package/dist/src/evals/rerun-types.js.map +1 -0
  343. package/dist/src/evals/rerun.js +133 -88
  344. package/dist/src/evals/rerun.js.map +1 -1
  345. package/dist/src/evals/result-helpers.js +78 -0
  346. package/dist/src/evals/result-helpers.js.map +1 -0
  347. package/dist/src/evals/resume-state.js +36 -0
  348. package/dist/src/evals/resume-state.js.map +1 -0
  349. package/dist/src/evals/retry-backoff.js +20 -0
  350. package/dist/src/evals/retry-backoff.js.map +1 -0
  351. package/dist/src/evals/retry-state.js +195 -0
  352. package/dist/src/evals/retry-state.js.map +1 -0
  353. package/dist/src/evals/scheduler-metrics.js +95 -0
  354. package/dist/src/evals/scheduler-metrics.js.map +1 -0
  355. package/dist/src/evals/scheduler-trace-replay.js +107 -0
  356. package/dist/src/evals/scheduler-trace-replay.js.map +1 -0
  357. package/dist/src/evals/service-types.js +2 -0
  358. package/dist/src/evals/service-types.js.map +1 -0
  359. package/dist/src/evals/service.js +331 -347
  360. package/dist/src/evals/service.js.map +1 -1
  361. package/dist/src/evals/task-resources.js +209 -0
  362. package/dist/src/evals/task-resources.js.map +1 -0
  363. package/dist/src/evals/trial-environment-evidence.js +87 -0
  364. package/dist/src/evals/trial-environment-evidence.js.map +1 -0
  365. package/dist/src/evals/trial-execution-evidence.js +13 -0
  366. package/dist/src/evals/trial-execution-evidence.js.map +1 -0
  367. package/dist/src/evals/trial-import-identity.js +31 -0
  368. package/dist/src/evals/trial-import-identity.js.map +1 -0
  369. package/dist/src/evals/trial-import.js +183 -188
  370. package/dist/src/evals/trial-import.js.map +1 -1
  371. package/dist/src/evals/trial-publication-recovery.js +144 -0
  372. package/dist/src/evals/trial-publication-recovery.js.map +1 -0
  373. package/dist/src/evals/trial-publication.js +25 -0
  374. package/dist/src/evals/trial-publication.js.map +1 -0
  375. package/dist/src/evals/trial-reference-validation.js +49 -0
  376. package/dist/src/evals/trial-reference-validation.js.map +1 -0
  377. package/dist/src/evals/verifier-artifacts.js +317 -0
  378. package/dist/src/evals/verifier-artifacts.js.map +1 -0
  379. package/dist/src/evals/verifier-eligibility.js +25 -0
  380. package/dist/src/evals/verifier-eligibility.js.map +1 -0
  381. package/dist/src/evals/verifier-only-rerun.js +210 -0
  382. package/dist/src/evals/verifier-only-rerun.js.map +1 -0
  383. package/dist/src/evals/verifier-runtime.js +61 -0
  384. package/dist/src/evals/verifier-runtime.js.map +1 -0
  385. package/dist/src/evals/verifier-score-artifacts.js +119 -0
  386. package/dist/src/evals/verifier-score-artifacts.js.map +1 -0
  387. package/dist/src/evals/work-item-artifacts.js +23 -0
  388. package/dist/src/evals/work-item-artifacts.js.map +1 -0
  389. package/dist/src/foundation/config.js +17 -0
  390. package/dist/src/foundation/config.js.map +1 -1
  391. package/dist/src/foundation/contained-file.js +85 -0
  392. package/dist/src/foundation/contained-file.js.map +1 -0
  393. package/dist/src/foundation/credential-redaction.js +162 -0
  394. package/dist/src/foundation/credential-redaction.js.map +1 -0
  395. package/dist/src/foundation/environment-image-references.js +59 -0
  396. package/dist/src/foundation/environment-image-references.js.map +1 -0
  397. package/dist/src/foundation/executable.js +45 -5
  398. package/dist/src/foundation/executable.js.map +1 -1
  399. package/dist/src/foundation/fs.js +2 -1
  400. package/dist/src/foundation/fs.js.map +1 -1
  401. package/dist/src/foundation/index.js +6 -2
  402. package/dist/src/foundation/index.js.map +1 -1
  403. package/dist/src/foundation/process-identity.js +69 -0
  404. package/dist/src/foundation/process-identity.js.map +1 -0
  405. package/dist/src/images/context.js +47 -0
  406. package/dist/src/images/context.js.map +1 -0
  407. package/dist/src/images/docker-buildkit.js +137 -0
  408. package/dist/src/images/docker-buildkit.js.map +1 -0
  409. package/dist/src/images/dockerfile.js +67 -0
  410. package/dist/src/images/dockerfile.js.map +1 -0
  411. package/dist/src/images/gc.js +261 -0
  412. package/dist/src/images/gc.js.map +1 -0
  413. package/dist/src/images/index.js +10 -0
  414. package/dist/src/images/index.js.map +1 -0
  415. package/dist/src/images/manifest.js +109 -0
  416. package/dist/src/images/manifest.js.map +1 -0
  417. package/dist/src/images/ownership.js +5 -0
  418. package/dist/src/images/ownership.js.map +1 -0
  419. package/dist/src/images/records.js +32 -0
  420. package/dist/src/images/records.js.map +1 -0
  421. package/dist/src/images/registry.js +154 -0
  422. package/dist/src/images/registry.js.map +1 -0
  423. package/dist/src/images/service.js +224 -0
  424. package/dist/src/images/service.js.map +1 -0
  425. package/dist/src/model-access/capture.js +255 -0
  426. package/dist/src/model-access/capture.js.map +1 -0
  427. package/dist/src/model-access/index.js +5 -0
  428. package/dist/src/model-access/index.js.map +1 -0
  429. package/dist/src/model-access/policy.js +49 -0
  430. package/dist/src/model-access/policy.js.map +1 -0
  431. package/dist/src/model-access/proxy.js +336 -0
  432. package/dist/src/model-access/proxy.js.map +1 -0
  433. package/dist/src/model-access/records.js +167 -0
  434. package/dist/src/model-access/records.js.map +1 -0
  435. package/dist/src/runs/adapter-process.js +12 -0
  436. package/dist/src/runs/adapter-process.js.map +1 -0
  437. package/dist/src/runs/bundle.js +450 -0
  438. package/dist/src/runs/bundle.js.map +1 -0
  439. package/dist/src/runs/events.js +12 -1
  440. package/dist/src/runs/events.js.map +1 -1
  441. package/dist/src/runs/executor.js +46 -45
  442. package/dist/src/runs/executor.js.map +1 -1
  443. package/dist/src/runs/finalizer.js +17 -0
  444. package/dist/src/runs/finalizer.js.map +1 -1
  445. package/dist/src/runs/index.js +8 -1
  446. package/dist/src/runs/index.js.map +1 -1
  447. package/dist/src/runs/manifest.js +5 -5
  448. package/dist/src/runs/manifest.js.map +1 -1
  449. package/dist/src/runs/phase-bundle.js +86 -0
  450. package/dist/src/runs/phase-bundle.js.map +1 -0
  451. package/dist/src/runs/phase-cancellation.js +107 -0
  452. package/dist/src/runs/phase-cancellation.js.map +1 -0
  453. package/dist/src/runs/phase-group.js +113 -0
  454. package/dist/src/runs/phase-group.js.map +1 -0
  455. package/dist/src/runs/query.js +1 -1
  456. package/dist/src/runs/query.js.map +1 -1
  457. package/dist/src/runs/records.js +3 -0
  458. package/dist/src/runs/records.js.map +1 -1
  459. package/dist/src/runs/request.js +10 -3
  460. package/dist/src/runs/request.js.map +1 -1
  461. package/dist/src/runs/training-candidate.js +161 -0
  462. package/dist/src/runs/training-candidate.js.map +1 -0
  463. package/dist/src/runs/verifier-evidence-redaction.js +61 -0
  464. package/dist/src/runs/verifier-evidence-redaction.js.map +1 -0
  465. package/dist/src/runs/verifier-evidence.js +459 -0
  466. package/dist/src/runs/verifier-evidence.js.map +1 -0
  467. package/dist/src/runs/verifier-structured-evidence.js +83 -0
  468. package/dist/src/runs/verifier-structured-evidence.js.map +1 -0
  469. package/dist/src/trajectories/analysis.js +288 -0
  470. package/dist/src/trajectories/analysis.js.map +1 -0
  471. package/dist/src/trajectories/chunk-projection.js +148 -0
  472. package/dist/src/trajectories/chunk-projection.js.map +1 -0
  473. package/dist/src/trajectories/content-projection.js +389 -0
  474. package/dist/src/trajectories/content-projection.js.map +1 -0
  475. package/dist/src/trajectories/dsh-chunk-contract.js +176 -0
  476. package/dist/src/trajectories/dsh-chunk-contract.js.map +1 -0
  477. package/dist/src/trajectories/dsh-contract.js +284 -0
  478. package/dist/src/trajectories/dsh-contract.js.map +1 -0
  479. package/dist/src/trajectories/events-chunk-drill.js +95 -0
  480. package/dist/src/trajectories/events-chunk-drill.js.map +1 -0
  481. package/dist/src/trajectories/events-page.js +367 -0
  482. package/dist/src/trajectories/events-page.js.map +1 -0
  483. package/dist/src/trajectories/index.js +3 -0
  484. package/dist/src/trajectories/index.js.map +1 -1
  485. package/dist/src/trajectories/provider-capture.js +15 -24
  486. package/dist/src/trajectories/provider-capture.js.map +1 -1
  487. package/dist/src/trajectories/providers/deepseek.js +3 -3
  488. package/dist/src/trajectories/providers/deepseek.js.map +1 -1
  489. package/dist/src/trajectories/request-attempt.js +47 -0
  490. package/dist/src/trajectories/request-attempt.js.map +1 -0
  491. package/dist/src/trajectories/stream-reader.js +311 -0
  492. package/dist/src/trajectories/stream-reader.js.map +1 -0
  493. package/dist/src/trajectories/surface-fold.js +126 -0
  494. package/dist/src/trajectories/surface-fold.js.map +1 -0
  495. package/dist/src/workers/index.js +3 -0
  496. package/dist/src/workers/index.js.map +1 -0
  497. package/dist/src/workers/remote-harbor-work-spec.js +97 -0
  498. package/dist/src/workers/remote-harbor-work-spec.js.map +1 -0
  499. package/dist/src/workers/remote-harbor-worker.js +223 -0
  500. package/dist/src/workers/remote-harbor-worker.js.map +1 -0
  501. package/docs/schemas/benchmark-hook-request-v1.schema.json +65 -0
  502. package/docs/schemas/benchmark-hook-response-v1.schema.json +75 -0
  503. package/docs/schemas/benchmark-hook-v1.schema.json +33 -0
  504. package/docs/schemas/benchmark-lock-v1.schema.json +351 -0
  505. package/docs/schemas/benchmark-metric-v1.schema.json +37 -0
  506. package/docs/schemas/benchmark-package-v1.schema.json +167 -0
  507. package/docs/schemas/benchmark-phase-group.schema.json +41 -0
  508. package/docs/schemas/benchmark-profile-v1.schema.json +141 -0
  509. package/docs/schemas/benchmark-task-v1.schema.json +384 -0
  510. package/docs/schemas/benchmark-tool-result-v1.schema.json +30 -0
  511. package/docs/schemas/environment-build-index.schema.json +13 -0
  512. package/docs/schemas/environment-build-record.schema.json +25 -0
  513. package/docs/schemas/environment-image-manifest.schema.json +62 -0
  514. package/docs/schemas/error.schema.json +22 -0
  515. package/docs/schemas/eval-control.schema.json +36 -0
  516. package/docs/schemas/eval-execution-plan.schema.json +216 -0
  517. package/docs/schemas/eval-progress.schema.json +1 -15
  518. package/docs/schemas/eval-rerun-result.schema.json +58 -0
  519. package/docs/schemas/eval-rerun-state.schema.json +61 -0
  520. package/docs/schemas/eval-rerun-submission.schema.json +60 -0
  521. package/docs/schemas/eval-result.schema.json +32 -13
  522. package/docs/schemas/eval-submission-input.schema.json +14 -0
  523. package/docs/schemas/eval-submission.schema.json +68 -0
  524. package/docs/schemas/eval-trial-publication.schema.json +15 -0
  525. package/docs/schemas/eval-trial-reference.schema.json +129 -0
  526. package/docs/schemas/execution-evidence.schema.json +96 -0
  527. package/docs/schemas/execution-lease.schema.json +50 -0
  528. package/docs/schemas/execution-provider-status.schema.json +65 -0
  529. package/docs/schemas/execution-worker.schema.json +53 -0
  530. package/docs/schemas/harbor-process-exit.schema.json +14 -0
  531. package/docs/schemas/interaction-capture-ref.schema.json +45 -0
  532. package/docs/schemas/local-provider-execution.schema.json +33 -0
  533. package/docs/schemas/model-interaction.schema.json +41 -0
  534. package/docs/schemas/regrade-assessment-reference.schema.json +11 -0
  535. package/docs/schemas/remote-result-envelope.schema.json +32 -0
  536. package/docs/schemas/remote-tree-envelope.schema.json +25 -0
  537. package/docs/schemas/remote-work-offer.schema.json +58 -0
  538. package/docs/schemas/remote-work-receipt.schema.json +50 -0
  539. package/docs/schemas/remote-worker-artifact.schema.json +17 -0
  540. package/docs/schemas/remote-worker-event.schema.json +18 -0
  541. package/docs/schemas/remote-worker-heartbeat.schema.json +37 -0
  542. package/docs/schemas/remote-worker-registration.schema.json +52 -0
  543. package/docs/schemas/result-bundle-index.schema.json +133 -0
  544. package/docs/schemas/run-context.schema.json +15 -0
  545. package/docs/schemas/run-environment-images.schema.json +39 -0
  546. package/docs/schemas/run-manifest.schema.json +4 -0
  547. package/docs/schemas/run-request.schema.json +4 -0
  548. package/docs/schemas/training-data-candidate.schema.json +46 -0
  549. package/docs/schemas/trajectory-analysis.schema.json +258 -0
  550. package/docs/schemas/trajectory-events-page.schema.json +40 -0
  551. package/docs/schemas/verifier-assessment.schema.json +77 -0
  552. package/docs/schemas/verifier-evidence.schema.json +276 -0
  553. package/integrations/harbor/hitch_benchmark.py +252 -0
  554. package/integrations/harbor/hitch_candidate_recycle.py +262 -0
  555. package/integrations/harbor/hitch_harbor_agent.py +698 -568
  556. package/integrations/harbor/hitch_harbor_environment.py +469 -0
  557. package/integrations/harbor/hitch_harbor_task_resources.py +275 -0
  558. package/integrations/harbor/hitch_harbor_verifier.py +83 -2
  559. package/integrations/harbor/hitch_phase_supervisor.py +452 -0
  560. package/integrations/harbor/hitch_tool_client.mjs +91 -0
  561. package/integrations/model-call/cli.js +57 -0
  562. package/package.json +30 -6
@@ -0,0 +1,275 @@
1
+ """Inspect Harbor task and Compose resource declarations without starting Docker."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import re
7
+ import sys
8
+ import tomllib
9
+ from decimal import Decimal, InvalidOperation
10
+ from pathlib import Path
11
+ from typing import Any
12
+
13
+ import yaml
14
+ from harbor.models.task.config import TaskConfig, VerifierEnvironmentMode
15
+
16
+
17
+ def inspect_task(task_dir: Path) -> dict[str, Any]:
18
+ task_file = task_dir / "task.toml"
19
+ if not task_file.is_file():
20
+ raise ValueError(f"task.toml is missing: {task_file}")
21
+ with task_file.open("rb") as handle:
22
+ config = TaskConfig.model_validate(tomllib.load(handle))
23
+ services = _compose_services(task_dir / "environment" / "docker-compose.yaml")
24
+ runtime_platform = _compose_runtime_platform(
25
+ task_dir / "environment" / "docker-compose.yaml"
26
+ )
27
+ if "main" not in {service["name"] for service in services}:
28
+ services.append({"name": "main", "replicas": 1})
29
+ services.sort(key=lambda service: service["name"].encode("utf-8"))
30
+
31
+ verifier_mode = config.verifier.environment_mode
32
+ separate = verifier_mode == VerifierEnvironmentMode.SEPARATE or (
33
+ verifier_mode is None and config.verifier.environment is not None
34
+ )
35
+ verifier_environment = config.verifier.environment
36
+ if separate and verifier_environment is None:
37
+ verifier_environment = config.environment
38
+ main_egress = config.environment.os.value == "linux" and any(
39
+ mode is not None and mode.value != "public"
40
+ for mode in (
41
+ config.environment.network_mode,
42
+ config.agent.network_mode,
43
+ None if separate else config.verifier.network_mode,
44
+ )
45
+ )
46
+ verifier_egress = bool(
47
+ separate
48
+ and verifier_environment is not None
49
+ and verifier_environment.os.value == "linux"
50
+ and any(
51
+ mode is not None and mode.value != "public"
52
+ for mode in (verifier_environment.network_mode, config.verifier.network_mode)
53
+ )
54
+ )
55
+ images, fallbacks, builds = _environment_images(
56
+ config.environment, "task", task_dir / "environment"
57
+ )
58
+ if separate and verifier_environment is not None:
59
+ verifier_images, verifier_fallbacks, verifier_builds = _environment_images(
60
+ verifier_environment, "verifier", None
61
+ )
62
+ images.extend(verifier_images)
63
+ fallbacks.extend(verifier_fallbacks)
64
+ builds.extend(verifier_builds)
65
+ compose_images, compose_fallbacks = _compose_images(
66
+ task_dir / "environment" / "docker-compose.yaml"
67
+ )
68
+ images.extend(compose_images)
69
+ fallbacks.extend(compose_fallbacks)
70
+ return {
71
+ "schema_version": "1",
72
+ **({"runtime_platform": runtime_platform} if runtime_platform is not None else {}),
73
+ "task": _environment_resources(config.environment),
74
+ "verifier": {
75
+ "separate": separate,
76
+ **({"environment": _environment_resources(verifier_environment)} if verifier_environment is not None else {}),
77
+ },
78
+ "compose_services": services,
79
+ "provider_sidecars": {
80
+ "main_egress": main_egress,
81
+ "verifier_egress": verifier_egress,
82
+ },
83
+ "environment_images": sorted(
84
+ images, key=lambda entry: (entry["source"], entry["service"])
85
+ ),
86
+ "environment_image_fallbacks": sorted(
87
+ fallbacks, key=lambda entry: (entry["source"], entry["service"])
88
+ ),
89
+ "environment_builds": sorted(
90
+ builds, key=lambda entry: (entry["source"], entry["service"])
91
+ ),
92
+ }
93
+
94
+
95
+ def _compose_runtime_platform(compose_file: Path) -> str | None:
96
+ if not compose_file.exists():
97
+ return None
98
+ document = yaml.safe_load(compose_file.read_text(encoding="utf-8"))
99
+ if not isinstance(document, dict):
100
+ return None
101
+ services = document.get("services")
102
+ main = services.get("main") if isinstance(services, dict) else None
103
+ raw = main.get("platform") if isinstance(main, dict) else None
104
+ if raw is None:
105
+ return None
106
+ if not isinstance(raw, str):
107
+ raise ValueError("Compose main platform must be a string")
108
+ normalized = {
109
+ "linux/x86_64": "linux/amd64",
110
+ "linux/aarch64": "linux/arm64",
111
+ }.get(raw.strip().lower(), raw.strip().lower())
112
+ if normalized not in {"linux/amd64", "linux/arm64"}:
113
+ raise ValueError(f"Compose main platform is unsupported: {raw}")
114
+ return normalized
115
+
116
+
117
+ def _environment_resources(environment: Any) -> dict[str, Any]:
118
+ return {
119
+ **({"cpu_millis": environment.cpus * 1000} if environment.cpus is not None else {}),
120
+ **({"memory_bytes": environment.memory_mb * 1024 * 1024} if environment.memory_mb is not None else {}),
121
+ }
122
+
123
+
124
+ def _environment_images(
125
+ environment: Any, source: str, context_dir: Path | None
126
+ ) -> tuple[list[dict[str, str]], list[dict[str, str]], list[dict[str, str]]]:
127
+ reference = getattr(environment, "docker_image", None)
128
+ if reference is None:
129
+ if context_dir is not None and (context_dir / "Dockerfile").is_file():
130
+ return [], [], [{
131
+ "source": source,
132
+ "service": "main",
133
+ "context": "environment",
134
+ "dockerfile": "Dockerfile",
135
+ }]
136
+ return [], [{"source": source, "service": "main", "code": "backend-build"}], []
137
+ if not isinstance(reference, str) or not reference or "$" in reference:
138
+ return [], [{"source": source, "service": "main", "code": "dynamic-image"}], []
139
+ return [{"source": source, "service": "main", "reference": reference}], [], []
140
+
141
+
142
+ def _compose_images(
143
+ compose_file: Path,
144
+ ) -> tuple[list[dict[str, str]], list[dict[str, str]]]:
145
+ if not compose_file.exists():
146
+ return [], []
147
+ document = yaml.safe_load(compose_file.read_text(encoding="utf-8"))
148
+ if document is None or not isinstance(document, dict):
149
+ return [], []
150
+ raw_services = document.get("services")
151
+ if not isinstance(raw_services, dict):
152
+ return [], []
153
+ images: list[dict[str, str]] = []
154
+ fallbacks: list[dict[str, str]] = []
155
+ for name, raw in raw_services.items():
156
+ if not isinstance(name, str) or not isinstance(raw, dict):
157
+ continue
158
+ reference = raw.get("image")
159
+ if raw.get("build") is not None:
160
+ fallbacks.append({"source": "compose", "service": name, "code": "backend-build"})
161
+ elif isinstance(reference, str) and reference and "$" not in reference:
162
+ images.append({"source": "compose", "service": name, "reference": reference})
163
+ elif reference is not None:
164
+ fallbacks.append({"source": "compose", "service": name, "code": "dynamic-image"})
165
+ return images, fallbacks
166
+
167
+
168
+ def _compose_services(compose_file: Path) -> list[dict[str, Any]]:
169
+ if not compose_file.exists():
170
+ return []
171
+ document = yaml.safe_load(compose_file.read_text(encoding="utf-8"))
172
+ if document is None:
173
+ return []
174
+ if not isinstance(document, dict) or "include" in document:
175
+ raise ValueError("Compose resource discovery requires one mapping without include")
176
+ raw_services = document.get("services")
177
+ if not isinstance(raw_services, dict):
178
+ raise ValueError("Compose services must be a mapping")
179
+ result: list[dict[str, Any]] = []
180
+ for name, raw in raw_services.items():
181
+ if not isinstance(name, str) or not name or not isinstance(raw, dict):
182
+ raise ValueError("Compose service declaration is invalid")
183
+ if raw.get("profiles") or raw.get("extends"):
184
+ raise ValueError(f"Compose resource discovery does not support profiles/extends: {name}")
185
+ deploy = raw.get("deploy") if isinstance(raw.get("deploy"), dict) else {}
186
+ deploy_resources = deploy.get("resources") if isinstance(deploy.get("resources"), dict) else {}
187
+ limits = deploy_resources.get("limits") if isinstance(deploy_resources.get("limits"), dict) else {}
188
+ reservations = deploy_resources.get("reservations") if isinstance(deploy_resources.get("reservations"), dict) else {}
189
+ cpu_values = [_cpu_millis(value, name) for value in (raw.get("cpus"), limits.get("cpus")) if value is not None]
190
+ memory_values = [_memory_bytes(value, name) for value in (raw.get("mem_limit"), limits.get("memory")) if value is not None]
191
+ gpu_values = [_gpu_count(value, name) for value in (raw.get("gpus"), reservations.get("devices")) if value is not None]
192
+ replicas = raw.get("scale", deploy.get("replicas", 1))
193
+ if isinstance(replicas, bool) or not isinstance(replicas, int) or replicas < 1:
194
+ raise ValueError(f"Compose service replicas must be a positive integer: {name}")
195
+ result.append({
196
+ "name": name,
197
+ "replicas": replicas,
198
+ **({"cpu_millis": max(cpu_values)} if cpu_values else {}),
199
+ **({"memory_bytes": max(memory_values)} if memory_values else {}),
200
+ **({"gpu_count": max(gpu_values)} if gpu_values else {}),
201
+ })
202
+ return result
203
+
204
+
205
+ def _gpu_count(value: Any, service: str) -> int:
206
+ if value == "all":
207
+ raise ValueError(f"Compose GPU request must use a fixed count: {service}")
208
+ if not isinstance(value, list) or not value:
209
+ raise ValueError(f"Compose GPU request is invalid: {service}")
210
+ total = 0
211
+ for request in value:
212
+ if not isinstance(request, dict):
213
+ raise ValueError(f"Compose GPU request is invalid: {service}")
214
+ capabilities = request.get("capabilities")
215
+ if not isinstance(capabilities, list) or "gpu" not in capabilities:
216
+ continue
217
+ count = request.get("count")
218
+ device_ids = request.get("device_ids")
219
+ if count is not None and device_ids is not None:
220
+ raise ValueError(f"Compose GPU request cannot set count and device_ids: {service}")
221
+ if device_ids is not None:
222
+ if not isinstance(device_ids, list) or not device_ids or any(not isinstance(item, str) or not item for item in device_ids):
223
+ raise ValueError(f"Compose GPU device_ids are invalid: {service}")
224
+ total += len(device_ids)
225
+ elif isinstance(count, int) and not isinstance(count, bool) and count > 0:
226
+ total += count
227
+ else:
228
+ raise ValueError(f"Compose GPU request must use a fixed count: {service}")
229
+ if total < 1:
230
+ raise ValueError(f"Compose GPU request has no gpu capability: {service}")
231
+ return total
232
+
233
+
234
+ def _cpu_millis(value: Any, service: str) -> int:
235
+ if isinstance(value, bool) or not isinstance(value, (int, float, str)):
236
+ raise ValueError(f"Compose CPU limit is not numeric: {service}")
237
+ try:
238
+ decimal = Decimal(str(value).strip()) * 1000
239
+ except InvalidOperation as error:
240
+ raise ValueError(f"Compose CPU limit is not numeric: {service}") from error
241
+ if decimal != decimal.to_integral_value() or decimal <= 0:
242
+ raise ValueError(f"Compose CPU limit must be positive whole millicores: {service}")
243
+ return int(decimal)
244
+
245
+
246
+ def _memory_bytes(value: Any, service: str) -> int:
247
+ if isinstance(value, bool):
248
+ raise ValueError(f"Compose memory limit is invalid: {service}")
249
+ if isinstance(value, int):
250
+ if value <= 0:
251
+ raise ValueError(f"Compose memory limit must be positive: {service}")
252
+ return value
253
+ if not isinstance(value, str):
254
+ raise ValueError(f"Compose memory limit is invalid: {service}")
255
+ match = re.fullmatch(r"\s*([0-9]+(?:\.[0-9]+)?)\s*([kmgtpe]?i?b?)?\s*", value, re.IGNORECASE)
256
+ if not match:
257
+ raise ValueError(f"Compose memory limit is not a fixed size: {service}")
258
+ unit = (match.group(2) or "b").lower()
259
+ powers = {"b": 0, "k": 1, "kb": 1, "ki": 1, "kib": 1, "m": 2, "mb": 2, "mi": 2, "mib": 2,
260
+ "g": 3, "gb": 3, "gi": 3, "gib": 3, "t": 4, "tb": 4, "ti": 4, "tib": 4,
261
+ "p": 5, "pb": 5, "pi": 5, "pib": 5, "e": 6, "eb": 6, "ei": 6, "eib": 6}
262
+ bytes_value = Decimal(match.group(1)) * (1024 ** powers[unit])
263
+ if bytes_value != bytes_value.to_integral_value() or bytes_value <= 0:
264
+ raise ValueError(f"Compose memory limit is not a whole positive byte size: {service}")
265
+ return int(bytes_value)
266
+
267
+
268
+ def main() -> None:
269
+ if len(sys.argv) != 2:
270
+ raise SystemExit("usage: hitch_harbor_task_resources.py <task-directory>")
271
+ print(json.dumps(inspect_task(Path(sys.argv[1]).resolve()), separators=(",", ":"), sort_keys=True))
272
+
273
+
274
+ if __name__ == "__main__":
275
+ main()
@@ -11,7 +11,9 @@ import asyncio
11
11
  import json
12
12
  import re
13
13
  import shutil
14
+ import time
14
15
  from dataclasses import dataclass
16
+ from datetime import datetime, timezone
15
17
  from pathlib import Path
16
18
  from typing import Any
17
19
 
@@ -21,9 +23,15 @@ from harbor.verifier.verifier import Verifier
21
23
 
22
24
 
23
25
  MAX_LOG_BYTES = 256 * 1024
26
+ HITCH_AGENT_OUTCOME_NAME = "hitch-agent-outcome.json"
24
27
  LOG_NAMES = ("test-stdout.txt", "test-stderr.txt", "stdout.txt", "stderr.txt")
25
- OUTPUT_NAMES = (*LOG_NAMES, "reward.txt", "reward.json", "ctrf.json")
26
- CONTROL_NAMES = ("infrastructure-error.json", "infrastructure-retry-history.json")
28
+ OUTPUT_NAMES = (*LOG_NAMES, "reward.txt", "reward.json", "process.json", "feedback.json", "ctrf.json")
29
+ CONTROL_NAMES = (
30
+ "infrastructure-error.json",
31
+ "infrastructure-retry-history.json",
32
+ "candidate-ineligible.json",
33
+ "eligibility-gate.json",
34
+ )
27
35
 
28
36
  INFRASTRUCTURE_PATTERNS: tuple[tuple[str, tuple[re.Pattern[str], ...]], ...] = (
29
37
  (
@@ -117,8 +125,35 @@ class HitchRetryingVerifier(Verifier):
117
125
  self.infrastructure_retry_backoff_ms = infrastructure_retry_backoff_ms
118
126
 
119
127
  async def verify(self) -> VerifierResult:
128
+ started_ns = time.monotonic_ns()
129
+ try:
130
+ return await self._verify_with_retries()
131
+ finally:
132
+ self._write_phase_timing(started_ns)
133
+
134
+ async def _verify_with_retries(self) -> VerifierResult:
135
+ directory = getattr(getattr(getattr(self, "task", None), "paths", None), "environment_dir", None)
136
+ if directory and (directory.parent / ".hitch-benchmark.json").is_file():
137
+ from hitch_benchmark import restore_final_response, validate_collected_submission
138
+ validate_collected_submission(self)
139
+ await restore_final_response(self)
120
140
  # Do not trust a control file left by the candidate or a prior phase.
121
141
  await self._remove_files(CONTROL_NAMES)
142
+ eligibility = self._read_trusted_agent_outcome()
143
+ if eligibility is None:
144
+ self._write_json("eligibility-gate.json", {
145
+ "schema_version": "1", "status": "unavailable", "verifier_executed": True,
146
+ })
147
+ elif eligibility["gradeability"] == "ungradeable":
148
+ self._write_json("candidate-ineligible.json", {
149
+ "schema_version": "1",
150
+ "code": "candidate_evidence_unavailable",
151
+ "run_id": eligibility["run_id"],
152
+ "candidate_bundle": eligibility["candidate_bundle"],
153
+ "reason_code": eligibility.get("reason_code", "candidate_evidence_unavailable"),
154
+ "verifier_executed": False,
155
+ })
156
+ return VerifierResult(rewards={"reward": 0})
122
157
  attempts: list[dict[str, Any]] = []
123
158
  for attempt in range(1, self.infrastructure_retries + 2):
124
159
  result: VerifierResult | None = None
@@ -143,6 +178,10 @@ class HitchRetryingVerifier(Verifier):
143
178
  if attempts:
144
179
  self._write_history("recovered", attempts)
145
180
  assert result is not None
181
+ directory = getattr(getattr(getattr(self, "task", None), "paths", None), "environment_dir", None)
182
+ if directory and (directory.parent / ".hitch-benchmark.json").is_file():
183
+ from hitch_benchmark import normalize_rewards
184
+ return normalize_rewards(self, result)
146
185
  return result
147
186
 
148
187
  attempts.append(
@@ -179,6 +218,48 @@ class HitchRetryingVerifier(Verifier):
179
218
 
180
219
  raise AssertionError("unreachable verifier retry state")
181
220
 
221
+ def _read_trusted_agent_outcome(self) -> dict[str, Any] | None:
222
+ source = self.trial_paths.verifier_dir.parent / "agent" / HITCH_AGENT_OUTCOME_NAME
223
+ try:
224
+ if not source.is_file() or source.stat().st_size <= 0 or source.stat().st_size > 16 * 1024:
225
+ return None
226
+ value = json.loads(source.read_text(encoding="utf-8"))
227
+ except (OSError, UnicodeError, json.JSONDecodeError):
228
+ return None
229
+ if not isinstance(value, dict) or set(value) - {
230
+ "schema_version", "run_id", "status", "candidate_bundle", "submission_snapshot", "gradeability", "reason_code",
231
+ }:
232
+ return None
233
+ if value.get("schema_version") != "1" or re.fullmatch(r"run_[a-f0-9]{32}", str(value.get("run_id", ""))) is None:
234
+ return None
235
+ if value.get("status") not in {"succeeded", "failed", "timed_out", "cancelled"}:
236
+ return None
237
+ if value.get("candidate_bundle") not in {"complete", "missing", "invalid"}:
238
+ return None
239
+ if value.get("submission_snapshot") not in {"complete", "missing", "not-required"}:
240
+ return None
241
+ if value.get("gradeability") not in {"gradeable", "ungradeable"}:
242
+ return None
243
+ if value["gradeability"] == "gradeable" and value["candidate_bundle"] != "complete":
244
+ return None
245
+ if "reason_code" in value and (not isinstance(value["reason_code"], str) or not value["reason_code"]):
246
+ return None
247
+ return value
248
+
249
+ def _write_phase_timing(self, started_ns: int) -> None:
250
+ self._write_json(
251
+ "hitch-phase-timings.json",
252
+ {
253
+ "schema_version": "1",
254
+ "phases": {
255
+ "verifier": {
256
+ "duration_ms": max(0, (time.monotonic_ns() - started_ns) // 1_000_000),
257
+ "completed_at": datetime.now(timezone.utc).isoformat(),
258
+ }
259
+ },
260
+ },
261
+ )
262
+
182
263
  async def _clear_outputs(self) -> None:
183
264
  await self._remove_files(OUTPUT_NAMES)
184
265