@tangle-network/agent-bench 0.1.0 → 0.3.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 (317) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/HARNESS.md +302 -0
  3. package/README.md +39 -2
  4. package/dist/adapters.d.ts +15 -0
  5. package/dist/adapters.js +43 -0
  6. package/dist/adapters.js.map +1 -0
  7. package/dist/benchmarks/_harness.d.ts +125 -0
  8. package/dist/benchmarks/_harness.js +33 -0
  9. package/dist/benchmarks/_harness.js.map +1 -0
  10. package/dist/benchmarks/aec-bench.d.ts +27 -0
  11. package/dist/benchmarks/aec-bench.js +8 -0
  12. package/dist/benchmarks/aec-bench.js.map +1 -0
  13. package/dist/benchmarks/agentbench.d.ts +16 -0
  14. package/dist/benchmarks/agentbench.js +10 -0
  15. package/dist/benchmarks/agentbench.js.map +1 -0
  16. package/dist/benchmarks/appworld.d.ts +37 -0
  17. package/dist/benchmarks/appworld.js +14 -0
  18. package/dist/benchmarks/appworld.js.map +1 -0
  19. package/dist/benchmarks/bfcl.d.ts +18 -0
  20. package/dist/benchmarks/bfcl.js +10 -0
  21. package/dist/benchmarks/bfcl.js.map +1 -0
  22. package/dist/benchmarks/cad-design.d.ts +45 -0
  23. package/dist/benchmarks/cad-design.js +7 -0
  24. package/dist/benchmarks/cad-design.js.map +1 -0
  25. package/dist/benchmarks/cadbench.d.ts +19 -0
  26. package/dist/benchmarks/cadbench.js +8 -0
  27. package/dist/benchmarks/cadbench.js.map +1 -0
  28. package/dist/benchmarks/cadgenbench.d.ts +22 -0
  29. package/dist/benchmarks/cadgenbench.js +8 -0
  30. package/dist/benchmarks/cadgenbench.js.map +1 -0
  31. package/dist/benchmarks/commit0.d.ts +31 -0
  32. package/dist/benchmarks/commit0.js +10 -0
  33. package/dist/benchmarks/commit0.js.map +1 -0
  34. package/dist/benchmarks/crag.d.ts +14 -0
  35. package/dist/benchmarks/crag.js +9 -0
  36. package/dist/benchmarks/crag.js.map +1 -0
  37. package/dist/benchmarks/dabstep.d.ts +18 -0
  38. package/dist/benchmarks/dabstep.js +10 -0
  39. package/dist/benchmarks/dabstep.js.map +1 -0
  40. package/dist/benchmarks/enterpriseops-gym.d.ts +38 -0
  41. package/dist/benchmarks/enterpriseops-gym.js +10 -0
  42. package/dist/benchmarks/enterpriseops-gym.js.map +1 -0
  43. package/dist/benchmarks/finresearchbench.d.ts +15 -0
  44. package/dist/benchmarks/finresearchbench.js +8 -0
  45. package/dist/benchmarks/finresearchbench.js.map +1 -0
  46. package/dist/benchmarks/finsearchcomp.d.ts +49 -0
  47. package/dist/benchmarks/finsearchcomp.js +7 -0
  48. package/dist/benchmarks/finsearchcomp.js.map +1 -0
  49. package/dist/benchmarks/frames.d.ts +59 -0
  50. package/dist/benchmarks/frames.js +13 -0
  51. package/dist/benchmarks/frames.js.map +1 -0
  52. package/dist/benchmarks/hotpotqa.d.ts +48 -0
  53. package/dist/benchmarks/hotpotqa.js +15 -0
  54. package/dist/benchmarks/hotpotqa.js.map +1 -0
  55. package/dist/benchmarks/humaneval.d.ts +53 -0
  56. package/dist/benchmarks/humaneval.js +15 -0
  57. package/dist/benchmarks/humaneval.js.map +1 -0
  58. package/dist/benchmarks/mind2web.d.ts +41 -0
  59. package/dist/benchmarks/mind2web.js +9 -0
  60. package/dist/benchmarks/mind2web.js.map +1 -0
  61. package/dist/benchmarks/nomiracl.d.ts +15 -0
  62. package/dist/benchmarks/nomiracl.js +9 -0
  63. package/dist/benchmarks/nomiracl.js.map +1 -0
  64. package/dist/benchmarks/open-rag-bench.d.ts +14 -0
  65. package/dist/benchmarks/open-rag-bench.js +9 -0
  66. package/dist/benchmarks/open-rag-bench.js.map +1 -0
  67. package/dist/benchmarks/programbench.d.ts +38 -0
  68. package/dist/benchmarks/programbench.js +10 -0
  69. package/dist/benchmarks/programbench.js.map +1 -0
  70. package/dist/benchmarks/rag-shared.d.ts +42 -0
  71. package/dist/benchmarks/rag-shared.js +39 -0
  72. package/dist/benchmarks/rag-shared.js.map +1 -0
  73. package/dist/benchmarks/ragbench.d.ts +16 -0
  74. package/dist/benchmarks/ragbench.js +9 -0
  75. package/dist/benchmarks/ragbench.js.map +1 -0
  76. package/dist/benchmarks/simpleqa.d.ts +64 -0
  77. package/dist/benchmarks/simpleqa.js +11 -0
  78. package/dist/benchmarks/simpleqa.js.map +1 -0
  79. package/dist/benchmarks/swe-bench.d.ts +56 -0
  80. package/dist/benchmarks/swe-bench.js +14 -0
  81. package/dist/benchmarks/swe-bench.js.map +1 -0
  82. package/dist/benchmarks/t2-ragbench.d.ts +14 -0
  83. package/dist/benchmarks/t2-ragbench.js +9 -0
  84. package/dist/benchmarks/t2-ragbench.js.map +1 -0
  85. package/dist/benchmarks/tau-bench-shared.d.ts +26 -0
  86. package/dist/benchmarks/tau-bench-shared.js +10 -0
  87. package/dist/benchmarks/tau-bench-shared.js.map +1 -0
  88. package/dist/benchmarks/tau2-bench.d.ts +7 -0
  89. package/dist/benchmarks/tau2-bench.js +11 -0
  90. package/dist/benchmarks/tau2-bench.js.map +1 -0
  91. package/dist/benchmarks/tau3-banking.d.ts +15 -0
  92. package/dist/benchmarks/tau3-banking.js +9 -0
  93. package/dist/benchmarks/tau3-banking.js.map +1 -0
  94. package/dist/benchmarks/terminal-bench.d.ts +24 -0
  95. package/dist/benchmarks/terminal-bench.js +8 -0
  96. package/dist/benchmarks/terminal-bench.js.map +1 -0
  97. package/dist/benchmarks/toollm.d.ts +16 -0
  98. package/dist/benchmarks/toollm.js +10 -0
  99. package/dist/benchmarks/toollm.js.map +1 -0
  100. package/dist/benchmarks/trata-hedge.d.ts +32 -0
  101. package/dist/benchmarks/trata-hedge.js +7 -0
  102. package/dist/benchmarks/trata-hedge.js.map +1 -0
  103. package/dist/benchmarks/types.d.ts +107 -0
  104. package/dist/benchmarks/types.js +1 -0
  105. package/dist/benchmarks/types.js.map +1 -0
  106. package/dist/benchmarks/webarena-verified.d.ts +16 -0
  107. package/dist/benchmarks/webarena-verified.js +10 -0
  108. package/dist/benchmarks/webarena-verified.js.map +1 -0
  109. package/dist/chunk-2PVVP7GN.js +197 -0
  110. package/dist/chunk-2PVVP7GN.js.map +1 -0
  111. package/dist/chunk-2XU6OGEN.js +170 -0
  112. package/dist/chunk-2XU6OGEN.js.map +1 -0
  113. package/dist/chunk-53UPUNBZ.js +325 -0
  114. package/dist/chunk-53UPUNBZ.js.map +1 -0
  115. package/dist/chunk-5SBJCB6W.js +144 -0
  116. package/dist/chunk-5SBJCB6W.js.map +1 -0
  117. package/dist/chunk-7WSD27QQ.js +118 -0
  118. package/dist/chunk-7WSD27QQ.js.map +1 -0
  119. package/dist/chunk-C7T7WEK2.js +103 -0
  120. package/dist/chunk-C7T7WEK2.js.map +1 -0
  121. package/dist/chunk-CKUVRZ2T.js +251 -0
  122. package/dist/chunk-CKUVRZ2T.js.map +1 -0
  123. package/dist/chunk-HBSWHQNJ.js +30 -0
  124. package/dist/chunk-HBSWHQNJ.js.map +1 -0
  125. package/dist/chunk-HHXFIHXC.js +116 -0
  126. package/dist/chunk-HHXFIHXC.js.map +1 -0
  127. package/dist/chunk-IFAV6KEM.js +276 -0
  128. package/dist/chunk-IFAV6KEM.js.map +1 -0
  129. package/dist/chunk-INNOYXCP.js +387 -0
  130. package/dist/chunk-INNOYXCP.js.map +1 -0
  131. package/dist/chunk-J3KDJNX2.js +182 -0
  132. package/dist/chunk-J3KDJNX2.js.map +1 -0
  133. package/dist/chunk-JRWWGMK7.js +148 -0
  134. package/dist/chunk-JRWWGMK7.js.map +1 -0
  135. package/dist/chunk-JTHWEDEW.js +32 -0
  136. package/dist/chunk-JTHWEDEW.js.map +1 -0
  137. package/dist/chunk-KDIKRJGB.js +120 -0
  138. package/dist/chunk-KDIKRJGB.js.map +1 -0
  139. package/dist/chunk-LRRD7NAG.js +301 -0
  140. package/dist/chunk-LRRD7NAG.js.map +1 -0
  141. package/dist/chunk-ODT47UAY.js +221 -0
  142. package/dist/chunk-ODT47UAY.js.map +1 -0
  143. package/dist/chunk-PA2ZKHJC.js +230 -0
  144. package/dist/chunk-PA2ZKHJC.js.map +1 -0
  145. package/dist/chunk-PPYSEKFM.js +182 -0
  146. package/dist/chunk-PPYSEKFM.js.map +1 -0
  147. package/dist/chunk-PUIRNYI7.js +189 -0
  148. package/dist/chunk-PUIRNYI7.js.map +1 -0
  149. package/dist/chunk-R36V2VP7.js +169 -0
  150. package/dist/chunk-R36V2VP7.js.map +1 -0
  151. package/dist/chunk-R67DFVLO.js +142 -0
  152. package/dist/chunk-R67DFVLO.js.map +1 -0
  153. package/dist/chunk-SEVJPLZC.js +260 -0
  154. package/dist/chunk-SEVJPLZC.js.map +1 -0
  155. package/dist/chunk-SYDW647C.js +318 -0
  156. package/dist/chunk-SYDW647C.js.map +1 -0
  157. package/dist/chunk-TBKU5XQI.js +228 -0
  158. package/dist/chunk-TBKU5XQI.js.map +1 -0
  159. package/dist/chunk-TSWPNOYM.js +147 -0
  160. package/dist/chunk-TSWPNOYM.js.map +1 -0
  161. package/dist/chunk-UAIOHCUK.js +27 -0
  162. package/dist/chunk-UAIOHCUK.js.map +1 -0
  163. package/dist/chunk-UPAMRDX4.js +233 -0
  164. package/dist/chunk-UPAMRDX4.js.map +1 -0
  165. package/dist/chunk-VQRS7VUC.js +342 -0
  166. package/dist/chunk-VQRS7VUC.js.map +1 -0
  167. package/dist/chunk-X3BTXCJ4.js +262 -0
  168. package/dist/chunk-X3BTXCJ4.js.map +1 -0
  169. package/dist/chunk-X5YKXC6V.js +211 -0
  170. package/dist/chunk-X5YKXC6V.js.map +1 -0
  171. package/dist/chunk-Y6O2OCUO.js +130 -0
  172. package/dist/chunk-Y6O2OCUO.js.map +1 -0
  173. package/dist/chunk-YCGY7UIZ.js +208 -0
  174. package/dist/chunk-YCGY7UIZ.js.map +1 -0
  175. package/dist/chunk-Z7ML6L77.js +162 -0
  176. package/dist/chunk-Z7ML6L77.js.map +1 -0
  177. package/dist/chunk-ZEWMTR5M.js +136 -0
  178. package/dist/chunk-ZEWMTR5M.js.map +1 -0
  179. package/dist/index.d.ts +355 -0
  180. package/dist/index.js +1908 -0
  181. package/dist/index.js.map +1 -0
  182. package/fixtures/aec-bench.json +18 -0
  183. package/fixtures/agentbench-dbbench.json +22 -0
  184. package/fixtures/bfcl.json +45 -0
  185. package/fixtures/commit0.json +72 -0
  186. package/fixtures/crag.json +10 -0
  187. package/fixtures/dabstep.json +22 -0
  188. package/fixtures/enterpriseops-gym.json +103 -0
  189. package/fixtures/finresearchbench.json +21 -0
  190. package/fixtures/finsearchcomp.json +66 -0
  191. package/fixtures/frames.json +26 -0
  192. package/fixtures/hotpotqa.json +182 -0
  193. package/fixtures/nomiracl.json +26 -0
  194. package/fixtures/open-rag-bench.json +16 -0
  195. package/fixtures/pier-agent/no-model-task/environment/Dockerfile +16 -0
  196. package/fixtures/pier-agent/no-model-task/environment/seed/src/status.txt +1 -0
  197. package/fixtures/pier-agent/no-model-task/instruction.md +6 -0
  198. package/fixtures/pier-agent/no-model-task/pre_artifacts.sh +6 -0
  199. package/fixtures/pier-agent/no-model-task/task.toml +35 -0
  200. package/fixtures/pier-agent/no-model-task/tests/Dockerfile +17 -0
  201. package/fixtures/pier-agent/no-model-task/tests/seed/src/status.txt +1 -0
  202. package/fixtures/pier-agent/no-model-task/tests/test.sh +19 -0
  203. package/fixtures/programbench.json +17 -0
  204. package/fixtures/ragbench.json +21 -0
  205. package/fixtures/simpleqa.json +121 -0
  206. package/fixtures/t2-ragbench.json +13 -0
  207. package/fixtures/tau2-bench.json +16 -0
  208. package/fixtures/tau3-banking.json +16 -0
  209. package/fixtures/toollm.json +28 -0
  210. package/fixtures/webarena-verified.json +20 -0
  211. package/package.json +60 -20
  212. package/pier_agents/__init__.py +18 -0
  213. package/pier_agents/candidate_contract.py +755 -0
  214. package/pier_agents/process_boundary.py +321 -0
  215. package/pier_agents/tangle_candidate.py +907 -0
  216. package/pier_agents/workspace_boundary.py +368 -0
  217. package/scripts/appworld_driver.py +359 -0
  218. package/scripts/cadbench_prepare.py +22 -0
  219. package/scripts/cadgenbench_hard_parts.py +48 -0
  220. package/scripts/clbench_codebase_judge.py +73 -0
  221. package/scripts/commit0_judge.py +170 -0
  222. package/scripts/dabstep_judge.py +42 -0
  223. package/scripts/enterpriseops_gym_judge.py +281 -0
  224. package/scripts/programbench_judge.py +120 -0
  225. package/scripts/render-gate-chart.mjs +176 -0
  226. package/scripts/run-package-tests.mjs +56 -0
  227. package/scripts/terminate-pier-trial.mts +66 -0
  228. package/scripts/trata-hedge/README.md +56 -0
  229. package/scripts/trata-hedge/run.sh +60 -0
  230. package/scripts/trata-hedge/solve.py +83 -0
  231. package/scripts/verify-packed-consumer.mjs +235 -0
  232. package/scripts/verify-pier-agent.mts +715 -0
  233. package/scripts/verify-pier-pair.mts +74 -0
  234. package/scripts/verify-pier-recovery.mts +139 -0
  235. package/src/adapters.ts +26 -0
  236. package/src/benchmarks/_harness.test.mts +178 -0
  237. package/src/benchmarks/_harness.ts +239 -16
  238. package/src/benchmarks/agentbench.ts +163 -0
  239. package/src/benchmarks/appworld.test.mts +15 -9
  240. package/src/benchmarks/bfcl.ts +346 -0
  241. package/src/benchmarks/crag.ts +137 -0
  242. package/src/benchmarks/dabstep.test.mts +70 -0
  243. package/src/benchmarks/dabstep.ts +212 -0
  244. package/src/benchmarks/external-adapters.test.mts +150 -0
  245. package/src/benchmarks/finresearchbench.ts +269 -0
  246. package/src/benchmarks/humaneval.ts +20 -8
  247. package/src/benchmarks/nomiracl.ts +180 -0
  248. package/src/benchmarks/open-rag-bench.ts +153 -0
  249. package/src/benchmarks/rag-benchmarks.test.mts +138 -0
  250. package/src/benchmarks/rag-shared.ts +327 -0
  251. package/src/benchmarks/ragbench.ts +171 -0
  252. package/src/benchmarks/swe-bench.test.mts +61 -0
  253. package/src/benchmarks/swe-bench.ts +201 -19
  254. package/src/benchmarks/t2-ragbench.ts +166 -0
  255. package/src/benchmarks/tau-bench-shared.ts +214 -0
  256. package/src/benchmarks/tau2-bench.ts +30 -0
  257. package/src/benchmarks/tau3-banking.ts +29 -0
  258. package/src/benchmarks/terminal-bench.test.mts +33 -0
  259. package/src/benchmarks/terminal-bench.ts +23 -8
  260. package/src/benchmarks/toollm.ts +254 -0
  261. package/src/benchmarks/types.ts +42 -0
  262. package/src/benchmarks/webarena-verified.ts +200 -0
  263. package/src/commit0-prereqs.sh +0 -0
  264. package/src/coordination-mcp-container-reach.mts +181 -0
  265. package/src/decoder-live.mts +1 -1
  266. package/src/examples/README.md +103 -39
  267. package/src/examples/benchmark-matrix.mts +101 -0
  268. package/src/examples/lean-proof-gate.README.md +77 -0
  269. package/src/examples/lean-proof-gate.mts +162 -0
  270. package/src/examples/lean-verify.ts +95 -0
  271. package/src/examples/lean.Dockerfile +12 -0
  272. package/src/examples/math-demo.mts +9 -7
  273. package/src/examples/strategy-demo.mts +10 -12
  274. package/src/gate.ts +3 -2
  275. package/src/hev-eval.mts +69 -0
  276. package/src/hev-improve.mts +169 -0
  277. package/src/hev-structural.mts +688 -0
  278. package/src/index.ts +73 -0
  279. package/src/mbpp-structural.mts +662 -0
  280. package/src/pier-agent.test-fixtures.mts +19 -0
  281. package/src/pier-agent.test.mts +363 -0
  282. package/src/pier-agent.ts +657 -0
  283. package/src/pier-result-grader.mjs +30 -0
  284. package/src/pier-result-grader.test.mts +62 -0
  285. package/src/pier-result-grader.ts +108 -0
  286. package/src/pier-task-outcome.test.mts +117 -0
  287. package/src/pier-task-outcome.ts +240 -0
  288. package/src/pier-trial-controller.test.mts +412 -0
  289. package/src/pier-trial-controller.ts +858 -0
  290. package/src/pier-trial-supervisor.mjs +352 -0
  291. package/src/resolve-client.ts +25 -2
  292. package/src/run-benchmarks-cli.mts +72 -0
  293. package/src/run-benchmarks-report.ts +66 -0
  294. package/src/run-benchmarks.test.mts +231 -0
  295. package/src/run-benchmarks.ts +589 -0
  296. package/src/smoke-structural-rollout.mts +393 -0
  297. package/src/swe-bench-env.test.ts +207 -0
  298. package/src/swe-bench-env.ts +554 -0
  299. package/src/swe-jail.ts +293 -0
  300. package/src/swe-self-improve.mts +84 -0
  301. package/src/swe-structural-judge-policy.test.ts +117 -0
  302. package/src/swe-structural-judge-policy.ts +133 -0
  303. package/src/swe-structural-policy.test.ts +124 -0
  304. package/src/swe-structural-policy.ts +132 -0
  305. package/src/swe-structural-provenance.test.ts +93 -0
  306. package/src/swe-structural-provenance.ts +138 -0
  307. package/src/swe-structural.mts +1260 -0
  308. package/src/swe-temp.ts +14 -0
  309. package/src/tb-container-executor.mts +234 -0
  310. package/src/tb-container-executor.test.mts +99 -0
  311. package/src/tb-supervisor-sidecar.mts +222 -0
  312. package/src/trata-gepa.mts +1 -1
  313. package/steerers/eops-itsm-population.json +1 -0
  314. package/tb_agents/opencode_refine_agent.py +117 -0
  315. package/tb_agents/opencode_router_agent.py +406 -0
  316. package/tb_agents/opencode_supervisor_agent.py +239 -0
  317. package/tb_agents/script_agent.py +66 -0
@@ -0,0 +1,688 @@
1
+ /**
2
+ * HumanEval STRUCTURAL lever — best-of-k selection + self-repair grounded ONLY on the
3
+ * VISIBLE docstring `>>>` examples (the honest oracle), graded on the HIDDEN check()
4
+ * suite. This is the experiment the self-improvement push identified but never ran:
5
+ * the existing gates (`humaneval-gate.mts`, `humaneval-repair-gate.mts`) select/steer
6
+ * on the task's own grading test — defensible in a deployable-verifier framing, but
7
+ * NOT a benchmark-lift claim. Here the harness sees nothing the model can't already
8
+ * read in its prompt.
9
+ *
10
+ * Honesty by construction — two physically separated phases:
11
+ * Phase A (harness): k samples/task at one temperature → honest doctest score per
12
+ * sample (docker, --network=none) → argmax select → ≤R repair rounds steered by
13
+ * the doctest FAILURE OUTPUT → final artifact locked. No access to task.test.
14
+ * Phase B (grading): the hidden check() suite grades every sample and every locked
15
+ * final. Nothing from this phase flows back.
16
+ *
17
+ * Judge integrity (adversarially reviewed; both spoof channels closed):
18
+ * - both judges print a per-call random NONCE sentinel and the verdict is parsed
19
+ * from that exact nonce — a candidate printing a forged summary line cannot win;
20
+ * - the hidden judge requires the sentinel, not exit-0 — `sys.exit(0)` before
21
+ * check() is a FAIL, not a pass;
22
+ * - containers run under an in-container `timeout -s KILL` so a hung candidate
23
+ * cannot outlive a crashed harness; a process-exit reaper force-removes strays.
24
+ *
25
+ * Estimators (paired across the same tasks, same sample batch):
26
+ * blind1_mean — mean hidden-pass over ALL k samples = expected pass@1 at this
27
+ * temperature (a built-in k-rep baseline; the primary control)
28
+ * blind1_first — hidden-pass of sample 0 (single-rep reference only)
29
+ * selected@1 — hidden-pass of the honest-oracle argmax sample (selection value)
30
+ * repaired@1 — hidden-pass of the final after honest-grounded repair (full harness)
31
+ * oracle@k — any sample passes hidden (the pass@k ceiling)
32
+ * Every lift carries a 95% paired-bootstrap CI (B=10000, seeded) AND an exact
33
+ * two-sided sign test — the bootstrap alone is anticonservative when few tasks move.
34
+ *
35
+ * CALIBRATE=1 skips the model entirely: canonical solutions vs both judges →
36
+ * hidden-judge self-check (must be ~100%) + honest-oracle coverage & false-fail rate.
37
+ *
38
+ * TANGLE_API_KEY=… WORKER_MODEL=meta-llama/Meta-Llama-3-8B-Instruct-Lite \
39
+ * ROUTER_BASE=https://api.together.xyz/v1 HUMANEVAL_GZ=/abs/HumanEval.jsonl.gz \
40
+ * N=164 K=5 REPAIRS=2 TEMPERATURE=0.8 OUT=/abs/rows.jsonl tsx src/hev-structural.mts
41
+ */
42
+ import { execFile, execFileSync } from 'node:child_process'
43
+ import { randomBytes } from 'node:crypto'
44
+ import { appendFileSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
45
+ import { tmpdir } from 'node:os'
46
+ import { join } from 'node:path'
47
+ import { type HumanEvalTask, extractCode, loadHumanEval } from './benchmarks/humaneval'
48
+ import { composeStrategies } from './directives'
49
+ import { type PairedLift, pairedLift, pool } from './stats.mts'
50
+
51
+ const dockerImage = 'python:3.12-slim'
52
+ const dockerTimeoutMs = Number(process.env.DOCKER_TIMEOUT_MS ?? 20000)
53
+
54
+ const solveInstruction =
55
+ 'Complete the following Python function. Output the COMPLETE function definition (signature, docstring optional, body) inside a single ```python code block. Include any imports the function needs. Do not write tests or example calls.'
56
+
57
+ function must(name: string): string {
58
+ const v = process.env[name]
59
+ if (!v) throw new Error(`env ${name} is required`)
60
+ return v
61
+ }
62
+
63
+ // ---------- docker semaphore + jailed runner (shared by BOTH judges) ----------
64
+ // Phase A workers each run docker calls too, so the container count must be bounded
65
+ // by ONE global semaphore, not by whichever pool happens to wrap the caller.
66
+
67
+ let dockerSlots = 6
68
+ let dockerInFlight = 0
69
+ const dockerWaiters: Array<() => void> = []
70
+ async function withDockerSlot<T>(fn: () => Promise<T>): Promise<T> {
71
+ if (dockerInFlight >= dockerSlots) await new Promise<void>((r) => dockerWaiters.push(r))
72
+ dockerInFlight += 1
73
+ try {
74
+ return await fn()
75
+ } finally {
76
+ dockerInFlight -= 1
77
+ dockerWaiters.shift()?.()
78
+ }
79
+ }
80
+
81
+ const containerPrefix = `hevs-${process.pid}`
82
+ let containerSeq = 0
83
+
84
+ // Best-effort stray-container reap on any exit path (crash, SIGINT, clean end).
85
+ function reapContainers(): void {
86
+ try {
87
+ const ids = execFileSync('docker', ['ps', '-aq', '--filter', `name=${containerPrefix}`], { timeout: 10000 }).toString().trim()
88
+ if (ids) execFileSync('docker', ['rm', '-f', ...ids.split('\n')], { timeout: 15000 })
89
+ } catch {
90
+ /* reaper is best-effort by design */
91
+ }
92
+ }
93
+ process.on('SIGINT', () => {
94
+ reapContainers()
95
+ process.exit(130)
96
+ })
97
+ process.on('SIGTERM', () => {
98
+ reapContainers()
99
+ process.exit(143)
100
+ })
101
+
102
+ interface JailResult {
103
+ exitCode: number
104
+ stdout: string
105
+ stderr: string
106
+ }
107
+
108
+ /** Run one python program in the jail: --network=none, cpu/mem caps, an IN-CONTAINER
109
+ * `timeout -s KILL` (so a hung candidate's container self-terminates even if this
110
+ * process dies), a client timeout, and a backstop. Docker INFRA faults (daemon,
111
+ * image, permission) throw — a broken checker must fail loud, not score zeros. */
112
+ function runJailed(program: string): Promise<JailResult> {
113
+ return withDockerSlot(
114
+ () =>
115
+ new Promise<JailResult>((resolvePromise, reject) => {
116
+ const dir = mkdtempSync(join(tmpdir(), 'hevs-'))
117
+ writeFileSync(join(dir, 'p.py'), program)
118
+ const name = `${containerPrefix}-${containerSeq++}`
119
+ let settled = false
120
+ const cleanup = () => {
121
+ rmSync(dir, { recursive: true, force: true })
122
+ execFile('docker', ['rm', '-f', name], () => {})
123
+ }
124
+ const finish = (res: JailResult) => {
125
+ if (settled) return
126
+ settled = true
127
+ clearTimeout(backstop)
128
+ cleanup()
129
+ resolvePromise(res)
130
+ }
131
+ const fail = (e: Error) => {
132
+ if (settled) return
133
+ settled = true
134
+ clearTimeout(backstop)
135
+ cleanup()
136
+ reject(e)
137
+ }
138
+ const backstop = setTimeout(() => finish({ exitCode: 124, stdout: '', stderr: 'backstop timeout (no output)' }), dockerTimeoutMs + 5000)
139
+ const inContainerSecs = Math.ceil(dockerTimeoutMs / 1000) + 2
140
+ execFile(
141
+ 'docker',
142
+ [
143
+ 'run', '--rm', '--name', name, '--network=none', '--cpus=1', '--memory=512m',
144
+ '-v', `${dir}:/w:ro`, '-w', '/w', dockerImage,
145
+ 'timeout', '-s', 'KILL', String(inContainerSecs), 'python', '/w/p.py',
146
+ ],
147
+ { timeout: dockerTimeoutMs + 3000, killSignal: 'SIGKILL', maxBuffer: 4 * 1024 * 1024 },
148
+ (err, stdout, stderr) => {
149
+ if (err) {
150
+ const e = err as NodeJS.ErrnoException & { code?: number | string }
151
+ if (e.code === 'ENOENT') return fail(new Error('docker binary not found on PATH'))
152
+ const se = stderr ?? ''
153
+ if (/cannot connect to the docker daemon|is the docker daemon running|permission denied while trying to connect/i.test(se)) {
154
+ return fail(new Error(`docker daemon unreachable: ${se.slice(0, 200)}`))
155
+ }
156
+ if (/(unable to find image|pull access denied|manifest unknown|error response from daemon).*(pull|repository|registry)/i.test(se)) {
157
+ return fail(new Error(`docker image ${dockerImage} unavailable: ${se.slice(0, 200)}`))
158
+ }
159
+ const code = typeof e.code === 'number' ? e.code : 1
160
+ return finish({ exitCode: code, stdout: stdout ?? '', stderr: se })
161
+ }
162
+ finish({ exitCode: 0, stdout: stdout ?? '', stderr: stderr ?? '' })
163
+ },
164
+ )
165
+ }),
166
+ )
167
+ }
168
+
169
+ // ---------- the honest oracle: doctest over the VISIBLE docstring examples ----------
170
+
171
+ export interface HonestResult {
172
+ /** total visible checks: doctest examples + model-generated asserts (0 = no
173
+ * signal, -1 = the candidate crashed before the oracle could run) */
174
+ attempted: number
175
+ failed: number
176
+ /** doctest's failure report — the ONLY feedback the repair loop may see */
177
+ failureOutput: string
178
+ /** attempted > 0 && failed === 0 */
179
+ pass: boolean
180
+ /** split for post-hoc audit: doctest vs generated-assert counts */
181
+ dAttempted?: number
182
+ dFailed?: number
183
+ gAttempted?: number
184
+ gFailed?: number
185
+ }
186
+
187
+ /** The honest program: candidate executes (prompt header first, for its imports;
188
+ * candidate def shadows the stub), then doctest runs the examples taken from the
189
+ * STUB's `__doc__` (parsing the raw prompt text instead swallows the closing `"""`
190
+ * into the last example — caught by CALIBRATE=1). Verdict line carries a per-call
191
+ * NONCE so candidate-printed forgeries can't be parsed as the summary. task.test
192
+ * never appears here. */
193
+ function buildHonestProgram(task: HumanEvalTask, candidate: string, nonce: string, genTests: string[] = []): string {
194
+ const promptB64 = Buffer.from(task.prompt, 'utf8').toString('base64')
195
+ const entryB64 = Buffer.from(task.entryPoint, 'utf8').toString('base64')
196
+ const genB64 = Buffer.from(JSON.stringify(genTests), 'utf8').toString('base64')
197
+ return `${task.prompt}\n${candidate}\n
198
+ import ast as _ast, base64 as _b64, doctest as _doctest, io as _io, json as _json, sys as _sys
199
+ _prompt_text = _b64.b64decode("${promptB64}").decode("utf8")
200
+ _entry = _b64.b64decode("${entryB64}").decode("utf8")
201
+ _gen_tests = _json.loads(_b64.b64decode("${genB64}").decode("utf8"))
202
+ _stub_ns = {}
203
+ exec(_prompt_text, _stub_ns)
204
+ _doc = getattr(_stub_ns.get(_entry), "__doc__", None) or ""
205
+ try:
206
+ _examples = _doctest.DocTestParser().get_examples(_doc)
207
+ except ValueError:
208
+ _examples = [] # malformed docstring indentation -> no usable signal, not a crash
209
+
210
+ # Dataset-quirk normalizations, all decidable from VISIBLE output alone:
211
+ # assertion-style examples ("f(x) == 0" with no expected output) pass iff they print True;
212
+ # quote-style repr mismatches ("21" vs '21') compare by literal value.
213
+ class _Checker(_doctest.OutputChecker):
214
+ def check_output(self, want, got, optionflags):
215
+ if super().check_output(want, got, optionflags):
216
+ return True
217
+ if want.strip() == "" and got.strip() == "True":
218
+ return True
219
+ try:
220
+ return _ast.literal_eval(want.strip()) == _ast.literal_eval(got.strip())
221
+ except Exception:
222
+ return False
223
+
224
+ _test = _doctest.DocTest(_examples, globs=dict(globals()), name="visible", filename="p", lineno=0, docstring=_doc)
225
+ _runner = _doctest.DocTestRunner(checker=_Checker(), verbose=False, optionflags=_doctest.NORMALIZE_WHITESPACE | _doctest.IGNORE_EXCEPTION_DETAIL)
226
+ _buf = _io.StringIO()
227
+ _res = _runner.run(_test, out=_buf.write)
228
+
229
+ # Model-generated asserts (CodeT-style; written from the prompt BEFORE any candidate
230
+ # existed). Each runs individually so one malformed assert doesn't zero the rest.
231
+ _g_att, _g_fail = 0, 0
232
+ for _t in _gen_tests:
233
+ _g_att += 1
234
+ try:
235
+ exec(_t, dict(globals()))
236
+ except Exception as _e:
237
+ _g_fail += 1
238
+ _buf.write("GENTEST FAILED: %s -> %s: %s\\n" % (_t.strip()[:200], type(_e).__name__, str(_e)[:200]))
239
+
240
+ _att = _res.attempted + _g_att
241
+ _fail = _res.failed + _g_fail
242
+ print("HONEST-${nonce} attempted=%d failed=%d datt=%d dfail=%d gatt=%d gfail=%d" % (_att, _fail, _res.attempted, _res.failed, _g_att, _g_fail))
243
+ _sys.stdout.write(_buf.getvalue()[-1500:])
244
+ _sys.exit(0 if _att > 0 and _fail == 0 else 1)
245
+ `
246
+ }
247
+
248
+ export async function runHonestOracle(task: HumanEvalTask, candidate: string, genTests: string[] = []): Promise<HonestResult> {
249
+ const nonce = randomBytes(8).toString('hex')
250
+ const r = await runJailed(buildHonestProgram(task, candidate, nonce, genTests))
251
+ const summary = new RegExp(`HONEST-${nonce} attempted=(\\d+) failed=(\\d+) datt=(\\d+) dfail=(\\d+) gatt=(\\d+) gfail=(\\d+)`).exec(r.stdout)
252
+ if (!summary) {
253
+ // candidate crashed / hung before the oracle scaffold could report
254
+ const detail = (r.stderr || r.stdout).slice(-1500) || 'timed out (no output)'
255
+ return { attempted: -1, failed: -1, failureOutput: detail, pass: false }
256
+ }
257
+ const attempted = Number(summary[1])
258
+ const failed = Number(summary[2])
259
+ // Strip the sentinel line from the feedback shown to the repair loop — the model
260
+ // must never learn the summary format it could try to forge.
261
+ const failureOutput = r.stdout.replace(summary[0], '').slice(-1500)
262
+ return {
263
+ attempted,
264
+ failed,
265
+ failureOutput,
266
+ pass: attempted > 0 && failed === 0,
267
+ dAttempted: Number(summary[3]),
268
+ dFailed: Number(summary[4]),
269
+ gAttempted: Number(summary[5]),
270
+ gFailed: Number(summary[6]),
271
+ }
272
+ }
273
+
274
+ // ---------- CodeT-style test generation (visible info only, BEFORE any candidate) ----------
275
+
276
+ const testGenInstruction = (count: number, entry: string) =>
277
+ `Read the following Python function signature and docstring. Write exactly ${count} single-line assert statements that test the function \`${entry}\`, based ONLY on the behavior the docstring describes. Each assert must be one physical line of the form \`assert ${entry}(...) == expected\` (or a True/False check). Do NOT implement the function. Do NOT copy examples verbatim if you can test other cases too. Output ONLY the assert lines inside a single \`\`\`python code block.`
278
+
279
+ /** One LLM call per task, before sampling. Keeps only single-line, paren-balanced
280
+ * asserts that reference the entry point — malformed lines are dropped here rather
281
+ * than poisoning every candidate's score identically. */
282
+ async function generateTests(cfg: ClientCfg, task: HumanEvalTask, count: number): Promise<{ tests: string[]; completion: Completion }> {
283
+ const c = await complete(cfg, [
284
+ { role: 'user', content: `${testGenInstruction(count, task.entryPoint)}\n\n\`\`\`python\n${task.prompt}\`\`\`` },
285
+ ])
286
+ const block = extractCode(c.content)
287
+ const balanced = (s: string) => {
288
+ let d = 0
289
+ for (const ch of s) {
290
+ if (ch === '(' || ch === '[' || ch === '{') d += 1
291
+ else if (ch === ')' || ch === ']' || ch === '}') d -= 1
292
+ if (d < 0) return false
293
+ }
294
+ return d === 0
295
+ }
296
+ const tests = block
297
+ .split('\n')
298
+ .map((l) => l.trim())
299
+ .filter((l) => l.startsWith('assert ') && l.includes(task.entryPoint) && balanced(l))
300
+ .slice(0, count)
301
+ return { tests, completion: c }
302
+ }
303
+
304
+ /** Honest score for ranking: fraction of visible examples passed; a candidate that
305
+ * crashed before doctest ran ranks below one that ran and failed everything. */
306
+ function honestScore(h: HonestResult): number {
307
+ if (h.attempted <= 0) return h.attempted === 0 ? 0 : -1
308
+ return (h.attempted - h.failed) / h.attempted
309
+ }
310
+
311
+ // ---------- the hidden judge (Phase B / calibration ONLY) ----------
312
+ // Rig-local rather than the shared runChecker: pass requires the nonce sentinel that
313
+ // check() prints AFTER succeeding — exit-0-before-check (sys.exit(0) in a candidate)
314
+ // is a fail here, where trusting the exit code alone would score it a pass.
315
+
316
+ function buildHiddenProgram(task: HumanEvalTask, candidate: string, nonce: string): string {
317
+ return `${task.prompt}\n${candidate}\n\n${task.test}\n\ncheck(${task.entryPoint})\nprint("HIDDEN-${nonce} PASS")\n`
318
+ }
319
+
320
+ async function runHiddenJudge(task: HumanEvalTask, candidate: string): Promise<{ pass: number; detail?: string }> {
321
+ const nonce = randomBytes(8).toString('hex')
322
+ const r = await runJailed(buildHiddenProgram(task, candidate, nonce))
323
+ if (r.exitCode === 0 && r.stdout.includes(`HIDDEN-${nonce} PASS`)) return { pass: 1 }
324
+ return { pass: 0, detail: (r.stderr || r.stdout).slice(-600) || 'timed out (no output)' }
325
+ }
326
+
327
+ // ---------- model client (plain fetch; retries on transient HTTP + empty content) ----------
328
+
329
+ interface ClientCfg {
330
+ base: string
331
+ key: string
332
+ model: string
333
+ maxTokens: number
334
+ temperature: number
335
+ }
336
+
337
+ interface Completion {
338
+ content: string
339
+ attempts: number
340
+ tokensIn: number
341
+ tokensOut: number
342
+ }
343
+
344
+ async function complete(cfg: ClientCfg, messages: Array<{ role: string; content: string }>): Promise<Completion> {
345
+ let lastErr = ''
346
+ for (let attempt = 1; attempt <= 4; attempt += 1) {
347
+ if (attempt > 1) await new Promise((r) => setTimeout(r, 2000 * 2 ** attempt))
348
+ const ctl = new AbortController()
349
+ const timer = setTimeout(() => ctl.abort(), 240_000)
350
+ try {
351
+ const res = await fetch(`${cfg.base}/chat/completions`, {
352
+ method: 'POST',
353
+ headers: { Authorization: `Bearer ${cfg.key}`, 'Content-Type': 'application/json' },
354
+ body: JSON.stringify({ model: cfg.model, max_tokens: cfg.maxTokens, temperature: cfg.temperature, messages }),
355
+ signal: ctl.signal,
356
+ })
357
+ if (!res.ok) {
358
+ lastErr = `HTTP ${res.status}: ${(await res.text()).slice(0, 200)}`
359
+ continue
360
+ }
361
+ const d = (await res.json()) as {
362
+ choices?: Array<{ message?: { content?: string } }>
363
+ usage?: { prompt_tokens?: number; completion_tokens?: number }
364
+ }
365
+ const content = d.choices?.[0]?.message?.content ?? ''
366
+ // Reasoning models starve `content` when reasoning exhausts max_tokens — an
367
+ // empty reply is a transient fault to retry, not a candidate to score.
368
+ if (content.trim() === '') {
369
+ lastErr = 'empty content'
370
+ continue
371
+ }
372
+ return { content, attempts: attempt, tokensIn: d.usage?.prompt_tokens ?? 0, tokensOut: d.usage?.completion_tokens ?? 0 }
373
+ } catch (e) {
374
+ lastErr = e instanceof Error ? e.message : String(e)
375
+ } finally {
376
+ clearTimeout(timer)
377
+ }
378
+ }
379
+ throw new Error(`completion failed after retries: ${lastErr}`)
380
+ }
381
+
382
+ /** Repair replies often echo the failure report in a bare ``` block before the fixed
383
+ * code — first-fence extraction would grab the echo. Prefer the LAST fenced block
384
+ * that contains a `def`, else fall back to the shared extractor. Purely mechanical
385
+ * parsing of the model's own reply; no task information involved. */
386
+ function extractRepairCode(reply: string): string {
387
+ const fences = [...reply.matchAll(/```(?:python|py)?\s*\n([\s\S]*?)```/gi)].map((m) => (m[1] ?? '').trim())
388
+ for (let i = fences.length - 1; i >= 0; i -= 1) {
389
+ if (/(^|\n)\s*def\s+\w+/.test(fences[i] as string)) return fences[i] as string
390
+ }
391
+ return extractCode(reply)
392
+ }
393
+
394
+ // ---------- Phase A: the harness (sees ONLY visible information) ----------
395
+
396
+ interface HarnessOutcome {
397
+ taskId: string
398
+ samples: string[]
399
+ honest: HonestResult[]
400
+ selectedIdx: number
401
+ repairs: Array<{ code: string; honest: HonestResult }>
402
+ finalCode: string
403
+ /** 'already-passing' | 'no-signal' | 'repaired-pass' | 'rounds-exhausted' */
404
+ repairStop: string
405
+ /** model-generated asserts used as extra oracle signal ([] when TESTGEN off) */
406
+ genTests: string[]
407
+ llmCalls: number
408
+ llmAttempts: number
409
+ tokensIn: number
410
+ tokensOut: number
411
+ }
412
+
413
+ async function runHarnessForTask(cfg: ClientCfg, task: HumanEvalTask, k: number, maxRepairs: number, testGen: number, diverse: boolean): Promise<HarnessOutcome> {
414
+ const basePrompt = `${solveInstruction}\n\n\`\`\`python\n${task.prompt}\`\`\``
415
+ // DIVERSE mode: each sample slot gets a distinct strategy prefix — targets the
416
+ // all-k-samples-fail bucket, where iid resampling keeps drawing the same bug.
417
+ const slotPrompts = diverse ? composeStrategies(basePrompt, k) : Array.from({ length: k }, () => basePrompt)
418
+ let llmCalls = 0
419
+ let llmAttempts = 0
420
+ let tokensIn = 0
421
+ let tokensOut = 0
422
+ const track = (c: Completion) => {
423
+ llmCalls += 1
424
+ llmAttempts += c.attempts
425
+ tokensIn += c.tokensIn
426
+ tokensOut += c.tokensOut
427
+ }
428
+
429
+ // Generated tests come from the prompt alone, BEFORE any candidate exists, and
430
+ // are frozen for every sample and repair round of this task.
431
+ let genTests: string[] = []
432
+ if (testGen > 0) {
433
+ const g = await generateTests(cfg, task, testGen)
434
+ track(g.completion)
435
+ genTests = g.tests
436
+ }
437
+
438
+ const samples: string[] = []
439
+ for (let i = 0; i < k; i += 1) {
440
+ const c = await complete(cfg, [{ role: 'user', content: slotPrompts[i] as string }])
441
+ track(c)
442
+ samples.push(extractCode(c.content))
443
+ }
444
+ const honest: HonestResult[] = []
445
+ for (const s of samples) honest.push(await runHonestOracle(task, s, genTests))
446
+
447
+ // argmax by honest score, first index wins ties (deterministic; with zero
448
+ // coverage every sample ties at 0 → sample 0 = the blind pick)
449
+ let selectedIdx = 0
450
+ for (let i = 1; i < k; i += 1) {
451
+ if (honestScore(honest[i] as HonestResult) > honestScore(honest[selectedIdx] as HonestResult)) selectedIdx = i
452
+ }
453
+
454
+ const selHonest = honest[selectedIdx] as HonestResult
455
+ let best = { code: samples[selectedIdx] as string, honest: selHonest }
456
+ const repairs: HarnessOutcome['repairs'] = []
457
+ let repairStop = 'already-passing'
458
+ if (!selHonest.pass) {
459
+ if (selHonest.attempted === 0) {
460
+ repairStop = 'no-signal' // no visible examples → nothing honest to steer on
461
+ } else {
462
+ repairStop = 'rounds-exhausted'
463
+ let current = best
464
+ for (let r = 0; r < maxRepairs; r += 1) {
465
+ const repairPrompt = [
466
+ 'Your Python function failed some of the example checks shown in its own docstring.',
467
+ 'Here is the task again:',
468
+ '```python',
469
+ task.prompt.trimEnd(),
470
+ '```',
471
+ 'Your current attempt:',
472
+ '```python',
473
+ current.code,
474
+ '```',
475
+ 'Result of running the docstring examples against your attempt:',
476
+ '```',
477
+ current.honest.failureOutput.trim() || '(the code crashed before the examples could run)',
478
+ '```',
479
+ 'Fix the function so the docstring examples pass. Output the COMPLETE corrected function definition inside a single ```python code block. Do not write tests or example calls.',
480
+ ].join('\n')
481
+ const c = await complete(cfg, [{ role: 'user', content: repairPrompt }])
482
+ track(c)
483
+ const code = extractRepairCode(c.content)
484
+ const h = await runHonestOracle(task, code, genTests)
485
+ repairs.push({ code, honest: h })
486
+ if (honestScore(h) > honestScore(current.honest)) current = { code, honest: h }
487
+ if (honestScore(current.honest) > honestScore(best.honest)) best = current
488
+ if (h.pass) {
489
+ repairStop = 'repaired-pass'
490
+ break
491
+ }
492
+ }
493
+ }
494
+ }
495
+
496
+ return { taskId: task.taskId, samples, honest, selectedIdx, repairs, finalCode: best.code, repairStop, genTests, llmCalls, llmAttempts, tokensIn, tokensOut }
497
+ }
498
+
499
+ // ---------- statistics: exact sign test to pair with the bootstrap CI ----------
500
+ // The percentile bootstrap is anticonservative when few tasks move (4 improved / 0
501
+ // regressed at n=164 prints CI [+0.6, +4.9]pp while the exact test says p=0.125).
502
+ // The verdict requires BOTH.
503
+
504
+ function signTestP(deltas: number[]): { pos: number; neg: number; p: number } {
505
+ const pos = deltas.filter((d) => d > 1e-9).length
506
+ const neg = deltas.filter((d) => d < -1e-9).length
507
+ const m = pos + neg
508
+ if (m === 0) return { pos, neg, p: 1 }
509
+ // two-sided exact binomial(m, 0.5) tail from the observed extreme
510
+ const logC: number[] = [0]
511
+ for (let i = 1; i <= m; i += 1) logC.push((logC[i - 1] as number) + Math.log(m - i + 1) - Math.log(i))
512
+ const pmf = (x: number) => Math.exp((logC[x] as number) - m * Math.LN2)
513
+ const extreme = Math.max(pos, neg)
514
+ let p = 0
515
+ for (let x = extreme; x <= m; x += 1) p += pmf(x)
516
+ p *= 2
517
+ if (pos === neg) p = 1
518
+ return { pos, neg, p: Math.min(1, p) }
519
+ }
520
+
521
+ // ---------- calibration mode ----------
522
+
523
+ async function calibrate(tasks: HumanEvalTask[]): Promise<void> {
524
+ console.log(`=== CALIBRATION · canonical solutions vs both judges · n=${tasks.length} ===`)
525
+ const usable = tasks.filter((t) => t.canonicalSolution)
526
+ if (usable.length !== tasks.length) console.log(` WARNING: ${tasks.length - usable.length} task(s) missing canonical_solution`)
527
+ const rows = await pool(usable, 16, async (t) => {
528
+ const full = `${t.prompt}${t.canonicalSolution}`
529
+ const hidden = await runHiddenJudge(t, full)
530
+ const honest = await runHonestOracle(t, full)
531
+ return { id: t.taskId, hidden: hidden.pass, attempted: honest.attempted, failed: honest.failed, honestPass: honest.pass }
532
+ })
533
+ const hiddenPass = rows.filter((r) => r.hidden === 1)
534
+ const covered = rows.filter((r) => r.attempted > 0)
535
+ const falseFail = covered.filter((r) => !r.honestPass)
536
+ console.log(` hidden judge self-check: ${hiddenPass.length}/${rows.length} canonical solutions pass (must be ~100%)`)
537
+ if (hiddenPass.length < rows.length) console.log(` hidden FAILS: ${rows.filter((r) => r.hidden !== 1).map((r) => r.id).join(', ')}`)
538
+ console.log(` honest-oracle coverage: ${covered.length}/${rows.length} tasks have >=1 parseable docstring example`)
539
+ console.log(` zero-coverage tasks: ${rows.filter((r) => r.attempted === 0).map((r) => r.id).join(', ') || '(none)'}`)
540
+ console.log(` crashed-oracle tasks (attempted=-1): ${rows.filter((r) => r.attempted < 0).map((r) => r.id).join(', ') || '(none)'}`)
541
+ console.log(` honest-oracle false-fail on canonical: ${falseFail.length}/${covered.length} covered tasks`)
542
+ if (falseFail.length > 0) console.log(` false-fail ids: ${falseFail.map((r) => `${r.id}(${r.failed}/${r.attempted})`).join(', ')}`)
543
+ const examplesTotal = covered.reduce((s, r) => s + r.attempted, 0)
544
+ console.log(` examples per covered task: mean ${(examplesTotal / Math.max(1, covered.length)).toFixed(1)}`)
545
+ }
546
+
547
+ // ---------- main ----------
548
+
549
+ const pct = (x: number) => `${(x * 100).toFixed(1)}%`
550
+ const pp = (x: number) => `${x >= 0 ? '+' : ''}${(x * 100).toFixed(1)}pp`
551
+
552
+ interface GradedRow extends HarnessOutcome {
553
+ hiddenSamples: number[]
554
+ hiddenFinal: number
555
+ }
556
+
557
+ async function main(): Promise<void> {
558
+ const n = Number(process.env.N ?? 164)
559
+ const k = Number(process.env.K ?? 5)
560
+ const maxRepairs = Number(process.env.REPAIRS ?? 2)
561
+ const offset = Number(process.env.OFFSET ?? 0)
562
+ const temperature = Number(process.env.TEMPERATURE ?? 0.8)
563
+ const model = process.env.WORKER_MODEL ?? 'meta-llama/Meta-Llama-3-8B-Instruct-Lite'
564
+ const base = process.env.ROUTER_BASE ?? 'https://api.together.xyz/v1'
565
+ const solveConc = Number(process.env.CONCURRENCY ?? 6)
566
+ dockerSlots = Number(process.env.DOCKER_CONCURRENCY ?? 6)
567
+ const testGen = Number(process.env.TESTGEN ?? 0)
568
+ const diverse = process.env.DIVERSE === '1'
569
+ const out = process.env.OUT
570
+
571
+ const tasks = await loadHumanEval(n, offset)
572
+
573
+ if (process.env.CALIBRATE === '1') {
574
+ await calibrate(tasks)
575
+ return
576
+ }
577
+
578
+ const cfg: ClientCfg = { base, key: must('TANGLE_API_KEY'), model, maxTokens: Number(process.env.MAX_TOKENS ?? 2500), temperature }
579
+
580
+ console.log(`=== HumanEval STRUCTURAL lever · honest docstring oracle · n=${tasks.length} k=${k} repairs<=${maxRepairs} temp=${temperature} testgen=${testGen} diverse=${diverse ? 1 : 0} ===`)
581
+ console.log(` model=${model} base=${base} llm-conc=${solveConc} docker-conc=${dockerSlots} (global semaphore)`)
582
+ console.log(` Phase A (harness: sample->honest-select->honest-repair) then Phase B (hidden grading)`)
583
+
584
+ // Phase A — all harness decisions locked before any hidden grading. A per-task
585
+ // fault becomes an error row (persisted, excluded from stats), not a lost run;
586
+ // >15% error rate aborts loud since that means the harness itself is broken.
587
+ let done = 0
588
+ let errCount = 0
589
+ const outcomes = await pool(tasks, solveConc, async (task): Promise<HarnessOutcome | { taskId: string; error: string }> => {
590
+ try {
591
+ const o = await runHarnessForTask(cfg, task, k, maxRepairs, testGen, diverse)
592
+ done += 1
593
+ if (out) appendFileSync(`${out}.phaseA`, `${JSON.stringify({ model, temperature, k, maxRepairs, ...o })}\n`)
594
+ process.stderr.write(
595
+ ` [A ${done}/${tasks.length}] ${o.taskId}: sel=${o.selectedIdx} honest=${o.honest.map((h) => honestScore(h).toFixed(2)).join('/')} repairs=${o.repairs.length} stop=${o.repairStop}\n`,
596
+ )
597
+ return o
598
+ } catch (e) {
599
+ errCount += 1
600
+ const error = e instanceof Error ? e.message : String(e)
601
+ if (out) appendFileSync(`${out}.phaseA`, `${JSON.stringify({ model, taskId: task.taskId, error })}\n`)
602
+ process.stderr.write(` [A ERROR] ${task.taskId}: ${error.slice(0, 160)}\n`)
603
+ if (errCount > Math.max(3, 0.15 * tasks.length)) throw new Error(`aborting: ${errCount} task errors — harness-level fault, not task noise (last: ${error})`)
604
+ return { taskId: task.taskId, error }
605
+ }
606
+ })
607
+
608
+ const okOutcomes = outcomes.filter((o): o is HarnessOutcome => !('error' in o))
609
+ const okTasks = okOutcomes.map((o) => tasks.find((t) => t.taskId === o.taskId) as HumanEvalTask)
610
+ if (errCount > 0) console.log(` WARNING: ${errCount}/${tasks.length} task(s) errored in Phase A — excluded from stats, recorded in ${out ?? '(no OUT set)'}.phaseA`)
611
+
612
+ // Phase B — hidden grading of the locked artifacts.
613
+ console.log(`\n▶ Phase B: hidden grading (${okOutcomes.length} tasks × ${k} samples + finals)`)
614
+ const graded: GradedRow[] = await pool(okOutcomes, 16, async (o, ti) => {
615
+ const task = okTasks[ti] as HumanEvalTask
616
+ const hiddenSamples: number[] = []
617
+ for (const s of o.samples) hiddenSamples.push((await runHiddenJudge(task, s)).pass)
618
+ const finalIsSelected = o.finalCode === o.samples[o.selectedIdx]
619
+ const hiddenFinal = finalIsSelected ? (hiddenSamples[o.selectedIdx] as number) : (await runHiddenJudge(task, o.finalCode)).pass
620
+ const g: GradedRow = { ...o, hiddenSamples, hiddenFinal }
621
+ if (out) appendFileSync(out, `${JSON.stringify({ model, temperature, k, maxRepairs, ...g })}\n`)
622
+ return g
623
+ })
624
+ if (out) console.log(` raw rows appended to ${out} (phase-A rows incl. errors: ${out}.phaseA)`)
625
+
626
+ // Estimators (all paired over the same graded tasks).
627
+ const blind1First = graded.map((g) => g.hiddenSamples[0] as number)
628
+ const blind1Mean = graded.map((g) => g.hiddenSamples.reduce((s, x) => s + x, 0) / g.hiddenSamples.length)
629
+ const selected = graded.map((g) => g.hiddenSamples[g.selectedIdx] as number)
630
+ const repaired = graded.map((g) => g.hiddenFinal)
631
+ const oracleK = graded.map((g) => (g.hiddenSamples.some((x) => x === 1) ? 1 : 0))
632
+ // coverage is a task-level property; any non-crashed sample's oracle run proves it
633
+ const covered = graded.map((g) => (g.honest.some((h) => h.attempted > 0) ? 1 : 0))
634
+ const rate = (xs: number[]) => xs.reduce((s, x) => s + x, 0) / xs.length
635
+ const llmCallsTotal = graded.reduce((s, g) => s + g.llmCalls, 0)
636
+ const llmAttemptsTotal = graded.reduce((s, g) => s + g.llmAttempts, 0)
637
+ const tokensInTotal = graded.reduce((s, g) => s + g.tokensIn, 0)
638
+ const tokensOutTotal = graded.reduce((s, g) => s + g.tokensOut, 0)
639
+ const repairFired = graded.filter((g) => g.repairs.length > 0)
640
+
641
+ console.log(`\n${'='.repeat(78)}`)
642
+ console.log(`RESULTS · HumanEval structural lever · n=${graded.length} · k=${k} · repairs<=${maxRepairs} · temp=${temperature} · ${model}`)
643
+ console.log('='.repeat(78))
644
+ console.log(` honest-oracle coverage ${pct(rate(covered))} of tasks (>=1 docstring example)`)
645
+ console.log(` blind pass@1 (mean of k) ${pct(rate(blind1Mean))} [PRIMARY baseline — ${k}-rep estimator]`)
646
+ console.log(` blind pass@1 (first sample) ${pct(rate(blind1First))} [single-rep reference]`)
647
+ console.log(` selected@1 (honest argmax) ${pct(rate(selected))}`)
648
+ console.log(` repaired@1 (full harness) ${pct(rate(repaired))}`)
649
+ console.log(` oracle pass@${k} (ceiling) ${pct(rate(oracleK))}`)
650
+ console.log(
651
+ ` compute: ${llmCallsTotal} llm calls (${llmAttemptsTotal} incl. retries) = ${(llmCallsTotal / graded.length).toFixed(2)}/task; tokens in/out ${tokensInTotal}/${tokensOutTotal} (blind@1 spends 1 call/task)`,
652
+ )
653
+ console.log(` repair fired on ${repairFired.length}/${graded.length} tasks (stop: ${['already-passing', 'no-signal', 'repaired-pass', 'rounds-exhausted'].map((s) => `${s}=${graded.filter((g) => g.repairStop === s).length}`).join(', ')})`)
654
+
655
+ const row = (label: string, baseline: number[], treatment: number[]) => {
656
+ const l = pairedLift(baseline, treatment)
657
+ const st = signTestP(baseline.map((b, i) => (treatment[i] as number) - b))
658
+ console.log(
659
+ ` ${label.padEnd(36)} ${pp(l.point).padStart(7)} CI [${pp(l.low)}, ${pp(l.high)}] sign-test p=${st.p < 0.001 ? st.p.toExponential(1) : st.p.toFixed(3)} (+${st.pos}/−${st.neg}) (pairs ${l.pairs})`,
660
+ )
661
+ return { l, st }
662
+ }
663
+
664
+ console.log(`\n PAIRED LIFTS vs blind pass@1 (mean-of-${k}) · 95% bootstrap CI (B=10000) + exact sign test:`)
665
+ const sel = row('selected@1 − blind@1 (selection)', blind1Mean, selected)
666
+ const rep = row('repaired@1 − blind@1 (full harness)', blind1Mean, repaired)
667
+ row('repaired@1 − selected@1 (repair)', selected, repaired)
668
+ row(`oracle@${k} − repaired@1 (unrealized)`, repaired, oracleK)
669
+
670
+ // Subgroup views (report-only; the primary claim is the unconditional lift):
671
+ const coveredIdx = graded.map((_, i) => i).filter((i) => covered[i] === 1)
672
+ if (coveredIdx.length > 0 && coveredIdx.length < graded.length) {
673
+ const pick = (xs: number[]) => coveredIdx.map((i) => xs[i] as number)
674
+ console.log(`\n COVERED-ONLY subgroup (n=${coveredIdx.length} tasks with visible examples; oracle can only act here):`)
675
+ row(' selected@1 − blind@1', pick(blind1Mean), pick(selected))
676
+ row(' repaired@1 − blind@1', pick(blind1Mean), pick(repaired))
677
+ }
678
+
679
+ const verdict = (name: string, r: { l: PairedLift; st: { p: number } }) =>
680
+ `${name}: ${pp(r.l.point)} — ${r.l.low > 0 && r.st.p < 0.05 ? 'POSITIVE (CI excludes 0 AND sign-test p<0.05)' : r.l.high < 0 && r.st.p < 0.05 ? 'NEGATIVE' : 'n.s.'}`
681
+ console.log(`\n VERDICT: ${verdict('full harness', rep)}; ${verdict('selection alone', sel)}`)
682
+ }
683
+
684
+ main().catch((e) => {
685
+ reapContainers()
686
+ console.error(`hev-structural: ${e instanceof Error ? (e.stack ?? e.message) : String(e)}`)
687
+ process.exit(1)
688
+ })