@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,66 @@
1
+ import path from 'node:path'
2
+
3
+ import { InMemoryTraceStore } from '@tangle-network/agent-eval'
4
+
5
+ import { createPierCandidateRecoveryExecutor } from '../src/pier-agent'
6
+ import { FilePierCandidateTrialController } from '../src/pier-trial-controller'
7
+
8
+ const [directoryArg, executionId, executionPlanDigest, ...extra] = process.argv.slice(2)
9
+ if (!directoryArg || !executionId || !executionPlanDigest || extra.length > 0) {
10
+ throw new Error(
11
+ 'usage: terminate-pier-trial.mts <control-directory> <execution-id> <execution-plan-digest>',
12
+ )
13
+ }
14
+ if (!/^sha256:[a-f0-9]{64}$/.test(executionPlanDigest)) {
15
+ throw new Error('execution-plan-digest must be a SHA-256 digest')
16
+ }
17
+
18
+ const dockerConnectionId = process.env.PIER_DOCKER_CONNECTION_ID
19
+ const dockerEnvironmentNames = process.env.PIER_DOCKER_ENV_NAMES
20
+ if ((dockerConnectionId === undefined) !== (dockerEnvironmentNames === undefined)) {
21
+ throw new Error(
22
+ 'PIER_DOCKER_CONNECTION_ID and PIER_DOCKER_ENV_NAMES must be set together',
23
+ )
24
+ }
25
+ const dockerConnection = (() => {
26
+ if (dockerConnectionId === undefined || dockerEnvironmentNames === undefined) return undefined
27
+ const names = dockerEnvironmentNames
28
+ .split(',')
29
+ .map((name) => name.trim())
30
+ .filter(Boolean)
31
+ if (new Set(names).size !== names.length) {
32
+ throw new Error('PIER_DOCKER_ENV_NAMES must not contain duplicates')
33
+ }
34
+ const env: Record<string, string> = {}
35
+ for (const name of names) {
36
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(name)) {
37
+ throw new Error('PIER_DOCKER_ENV_NAMES contains an invalid environment name')
38
+ }
39
+ const value = process.env[name]
40
+ if (value === undefined) throw new Error(`required Docker environment variable ${name} is unset`)
41
+ env[name] = value
42
+ }
43
+ return { id: dockerConnectionId, env }
44
+ })()
45
+
46
+ const controller = new FilePierCandidateTrialController({
47
+ directory: path.resolve(directoryArg),
48
+ ...(dockerConnection ? { dockerConnection } : {}),
49
+ })
50
+ const executor = createPierCandidateRecoveryExecutor(controller)
51
+ const recovered = await executor.stop(
52
+ {
53
+ executionId,
54
+ executionPlanDigest: executionPlanDigest as `sha256:${string}`,
55
+ },
56
+ {
57
+ traceStore: new InMemoryTraceStore(),
58
+ reason: 'failed',
59
+ signal: new AbortController().signal,
60
+ deadlineAtMs: Date.now() + 30_000,
61
+ },
62
+ )
63
+ if (recovered.stopped !== true) throw new Error('Pier recovery executor did not stop the trial')
64
+ process.stdout.write(
65
+ `${JSON.stringify({ processExited: true, containersRemoved: true })}\n`,
66
+ )
@@ -0,0 +1,56 @@
1
+ # trata-hedge-bench — evaluating our system against an LLM-judge benchmark
2
+
3
+ [trata-hedge-bench](https://github.com/Trata-Inc/trata-hedge-bench) is a 102-task
4
+ financial-analyst benchmark (Harbor format): the agent reads a company's data corpus
5
+ (earnings calls, 10-K/10-Q, financials, press releases) and writes an analysis; the
6
+ verifier is a **Gemini-3.1-pro 3-task cascade** (hallucination-check → per-move-hit →
7
+ synthesis) that grades *concept match* against the expert analyst's documented moves
8
+ (`ground_truth.txt`). Graded `score` is 0–4 (themes fully covered); `reward.txt` is
9
+ sparse (1 iff all themes). No deployable ground-truth checker — it's an **oracle judge**.
10
+
11
+ ## What's admissible here (and what isn't)
12
+
13
+ - **NOT** the verifier-grounded selector gate (our HumanEval/commit0 headline). The only
14
+ checker is the judge itself, so selecting by it = selecting by the eval metric (an
15
+ oracle, a Goodhart trap). See `docs/results.md`.
16
+ - **IS** admissible: (1) more-compute headroom (pass@k), (2) the **improvement loop**
17
+ (`selfImprove`/GEPA optimizing the analyst directive *against this judge*, held-out
18
+ gated — the legitimate use of a judge domain), with the honest caveat that an
19
+ LLM-judge can be *gamed*, so a held-out lift means "higher judge score," which without
20
+ ground truth we can't independently certify as "better analysis."
21
+
22
+ ## Status (2026-06-06): pipeline PROVEN end-to-end
23
+
24
+ Our solver → their **real** Gemini-3.1-pro judge → a genuine graded result. Every link
25
+ works. The naive **single-shot** baseline (gpt-4o, ~3 of N corpus files in one context
26
+ window) scores **0/4** — a floor: it hit only 1/3 moves on a few themes with
27
+ hallucinations flagged, because it could not explore the full corpus. The bench is built
28
+ for **agentic** exploration; a fair baseline needs our sandbox runtime as the solver
29
+ (browse + cite selectively), like the commit0 gate — pending sandbox-gateway health.
30
+
31
+ ## Run it
32
+
33
+ ```bash
34
+ # clone the bench once (102 envs, ~580MB; or sparse-checkout one env)
35
+ git clone https://github.com/Trata-Inc/trata-hedge-bench /tmp/thb
36
+
37
+ dotenvx run -f ~/company/devops/secrets/.env.keys -f ~/company/devops/secrets/agent-state.env -- \
38
+ bash bench/scripts/trata-hedge/run.sh /tmp/thb/environments/<env-name> gpt-4o
39
+ ```
40
+
41
+ ## Gotchas (each cost a debugging cycle)
42
+
43
+ - **Use `GOOGLE_AI_KEY`, not `GEMINI_API_KEY`** — the latter in the secrets is
44
+ `API_KEY_INVALID`; `GOOGLE_AI_KEY` is the working Gemini key (`gemini-3.1-pro-preview`
45
+ returns 200). `run.sh` maps `GOOGLE_API_KEY=$GOOGLE_AI_KEY` for `grade.py`.
46
+ - The router is behind Cloudflare bot-fight: a default urllib User-Agent → 403 (CF 1010)
47
+ on large bodies; the solver sends a browser UA.
48
+ - `grade.py` hardcodes `/app/answer.txt` (only that path); `/app` is sudo-writable.
49
+ `DATA_DIR` / `GROUND_TRUTH_PATH` / `REWARD_PATH` / `DETAILS_PATH` are env-overridable, so
50
+ the grader runs **unmodified** (faithful).
51
+
52
+ ## Next steps
53
+
54
+ 1. Agentic solver: our sandbox runtime browses the corpus + cites (fair baseline).
55
+ 2. The improvement loop: `selfImprove` on the analyst directive vs this judge, held-out
56
+ gated, across the 102 tasks — with the judge-gaming caveat stated.
@@ -0,0 +1,60 @@
1
+ #!/bin/bash
2
+ # Evaluate our system against trata-hedge-bench's OWN Gemini-3.1-pro judge.
3
+ #
4
+ # Pipeline: our solver writes a cited analysis -> their grade.py (unmodified, a
5
+ # 3-task Gemini cascade: hallucination-check -> per-move-hit -> synthesis) scores it
6
+ # against the expert analyst's documented moves (ground_truth.txt).
7
+ #
8
+ # Prereqs (all present in this environment):
9
+ # - GOOGLE_AI_KEY — a VALID Gemini key (NOTE: GEMINI_API_KEY in the secrets is
10
+ # API_KEY_INVALID; GOOGLE_AI_KEY is the working one).
11
+ # - TANGLE_API_KEY — our router (the solver).
12
+ # - uv + Docker. /app is sudo-writable (grade.py hardcodes /app/answer.txt).
13
+ #
14
+ # Usage (wrap in dotenvx so the keys resolve):
15
+ # dotenvx run -f ~/company/devops/secrets/.env.keys -f ~/company/devops/secrets/agent-state.env -- \
16
+ # bash bench/scripts/trata-hedge/run.sh <path-to-trata-env-dir> [WORKER_MODEL]
17
+ set -euo pipefail
18
+
19
+ ENV="${1:?usage: run.sh <trata-env-dir> [model]}"
20
+ MODEL="${2:-${WORKER_MODEL:-gpt-4o}}"
21
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
22
+ ANS=/tmp/thb-answer.txt
23
+ REWARD=/tmp/thb-reward.txt
24
+ DETAILS=/tmp/thb-details.json
25
+
26
+ echo "[trata] solve: $ENV (model=$MODEL)"
27
+ WORKER_MODEL="$MODEL" python3 "$HERE/solve.py" "$ENV" "$ANS"
28
+
29
+ sudo -n mkdir -p /app && sudo -n cp "$ANS" /app/answer.txt && sudo -n chmod 644 /app/answer.txt
30
+
31
+ echo "[trata] grade: their grade.py (gemini-3.1-pro)"
32
+ GRADE_LOG=/tmp/thb-grade.log
33
+ # Fail loud: capture the grader's output; if it errors (bad key, import, network) or
34
+ # writes no details, surface ITS error rather than crashing the reporter cryptically.
35
+ set +e
36
+ ( cd "$ENV/tests" && \
37
+ GOOGLE_API_KEY="$GOOGLE_AI_KEY" \
38
+ DATA_DIR="$ENV/environment/data" \
39
+ GROUND_TRUTH_PATH="$ENV/tests/ground_truth.txt" \
40
+ REWARD_PATH="$REWARD" DETAILS_PATH="$DETAILS" \
41
+ uvx --with google-genai python3 grade.py ) >"$GRADE_LOG" 2>&1
42
+ grade_status=$?
43
+ set -e
44
+ if [ "$grade_status" -ne 0 ] || [ ! -f "$DETAILS" ]; then
45
+ echo "[trata] grade.py FAILED (exit $grade_status) — last output:" >&2
46
+ tail -n 15 "$GRADE_LOG" >&2
47
+ exit 1
48
+ fi
49
+
50
+ python3 - "$DETAILS" "$REWARD" <<'PY'
51
+ import json, sys
52
+ d = json.load(open(sys.argv[1]))
53
+ reward = open(sys.argv[2]).read().strip() if __import__("os").path.exists(sys.argv[2]) else "?"
54
+ print(f" sparse reward (1 iff all themes): {reward}")
55
+ print(f" graded score (0-4): {d.get('score')} | themes_covered: {d.get('themes_covered')}/{d.get('num_themes')} | hallucinations: {d.get('hallucinations_detected')}")
56
+ for t in d.get("themes_hit", []):
57
+ print(f" HIT : {t.get('label')}")
58
+ for t in d.get("themes_missed", []):
59
+ print(f" MISS: {t.get('label')} ({len(t.get('moves_hit',[]))}/{t.get('n_moves')} moves)")
60
+ PY
@@ -0,0 +1,83 @@
1
+ """trata-hedge-bench solver — our system's analyst, graded by THEIR Gemini judge.
2
+
3
+ Reads a task's instruction.md + data corpus, writes a cited analysis to answer.txt.
4
+ The corpus is large (~5MB/task), so a single-shot router call is a LOWER-BOUND
5
+ baseline (it sees only what fits in context) — the bench is built for agentic
6
+ exploration, which our sandbox runtime provides (see README; pending sandbox health).
7
+
8
+ Notes learned the hard way:
9
+ - router.tangle.tools is behind Cloudflare bot-fight: a default Python-urllib
10
+ User-Agent gets 403 (CF 1010) on large bodies → send a browser UA.
11
+ - gpt-4.1 is NOT keyed for direct router calls (403); gpt-4o / claude-sonnet-4-6 /
12
+ gpt-4o-mini are. Very large bodies (~350KB) can 503 — keep DATA_BUDGET in range.
13
+
14
+ WORKER_MODEL=gpt-4o DATA_BUDGET=160000 python3 solve.py <env-dir> <out.txt>
15
+ """
16
+ import json
17
+ import os
18
+ import sys
19
+ import urllib.request
20
+ from pathlib import Path
21
+
22
+ env = Path(sys.argv[1])
23
+ out = sys.argv[2] if len(sys.argv) > 2 else "/tmp/thb-answer.txt"
24
+ model = os.environ.get("WORKER_MODEL", "gpt-4o")
25
+ budget = int(os.environ.get("DATA_BUDGET", "160000"))
26
+ instruction = (env / "instruction.md").read_text()
27
+ data_dir = env / "environment" / "data"
28
+
29
+
30
+ def rank(p: Path) -> int:
31
+ s = str(p)
32
+ return (0 if "earnings_call" in s else 1 if "financials" in s else 2 if "company_profiles" in s
33
+ else 3 if "press_releases" in s else 4)
34
+
35
+
36
+ files = sorted((p for p in data_dir.rglob("*") if p.is_file()), key=rank)
37
+ blocks, used, cited = [], 0, []
38
+ for p in files:
39
+ rel = p.relative_to(data_dir)
40
+ try:
41
+ c = p.read_text(errors="replace")
42
+ except Exception:
43
+ continue
44
+ if used + len(c) > budget:
45
+ continue
46
+ used += len(c)
47
+ cited.append(str(rel))
48
+ blocks.append(f"\n=== FILE: data/{rel} ===\n{c}")
49
+ print(f"[solve] {len(cited)}/{len(files)} files in context ({used} chars)", file=sys.stderr)
50
+
51
+ prompt = (
52
+ instruction
53
+ + "\n\n--- AVAILABLE DATA (cite files by their `data/<path>` name inline) ---\n"
54
+ + "".join(blocks)
55
+ + "\n\n--- END DATA ---\nWrite ONLY the full analysis (no preamble). Inline-cite every claim with its `data/<path>`."
56
+ )
57
+
58
+ key = os.environ["TANGLE_API_KEY"]
59
+ base = os.environ.get("ROUTER_BASE", "https://router.tangle.tools/v1")
60
+ body = json.dumps({
61
+ "model": model,
62
+ "messages": [{"role": "user", "content": prompt}],
63
+ "temperature": float(os.environ.get("TEMPERATURE", "0.5")),
64
+ "max_tokens": int(os.environ.get("MAX_TOKENS", "6000")),
65
+ }).encode()
66
+ req = urllib.request.Request(
67
+ f"{base}/chat/completions", data=body,
68
+ headers={
69
+ "Authorization": f"Bearer {key}",
70
+ "Content-Type": "application/json",
71
+ # browser UA: router is behind Cloudflare bot-fight, default urllib UA → 403 on big bodies
72
+ "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36",
73
+ },
74
+ )
75
+ try:
76
+ with urllib.request.urlopen(req, timeout=300) as r:
77
+ resp = json.load(r)
78
+ except urllib.error.HTTPError as e:
79
+ print(f"[solve] HTTP {e.code}: {e.read().decode(errors='replace')[:400]}", file=sys.stderr)
80
+ raise
81
+ answer = resp["choices"][0]["message"]["content"]
82
+ Path(out).write_text(answer)
83
+ print(f"[solve] wrote {len(answer)} chars -> {out} (model={model})", file=sys.stderr)
@@ -0,0 +1,235 @@
1
+ import { execFile } from 'node:child_process'
2
+ import { mkdtemp, mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises'
3
+ import { tmpdir } from 'node:os'
4
+ import path from 'node:path'
5
+ import { fileURLToPath } from 'node:url'
6
+ import { promisify } from 'node:util'
7
+
8
+ const execFileAsync = promisify(execFile)
9
+ const benchDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
10
+ const repoRoot = path.resolve(benchDir, '..')
11
+ const scratch = await mkdtemp(path.join(tmpdir(), 'agent-bench-consumer-'))
12
+ const args = new Set(process.argv.slice(2))
13
+ const useLocalRuntime = args.delete('--local-runtime')
14
+ if (args.size > 0) throw new Error(`unknown arguments: ${[...args].join(', ')}`)
15
+
16
+ const TYPESCRIPT_5 = '5.9.3'
17
+ const TYPESCRIPT_6 = '6.0.3'
18
+
19
+ async function run(command, args, cwd, env = process.env) {
20
+ try {
21
+ return await execFileAsync(command, args, {
22
+ cwd,
23
+ env,
24
+ maxBuffer: 10 * 1024 * 1024,
25
+ timeout: 120_000,
26
+ })
27
+ } catch (error) {
28
+ if (error?.stdout) process.stdout.write(error.stdout)
29
+ if (error?.stderr) process.stderr.write(error.stderr)
30
+ const invocation = [command, ...args].join(' ')
31
+ const message = error instanceof Error ? error.message : String(error)
32
+ throw new Error(`${invocation} failed: ${message}`, { cause: error })
33
+ }
34
+ }
35
+
36
+ async function resolveRuntimePackage(packDir) {
37
+ if (process.env.AGENT_RUNTIME_PACKAGE) {
38
+ return path.resolve(process.env.AGENT_RUNTIME_PACKAGE)
39
+ }
40
+ if (!useLocalRuntime) return undefined
41
+ const manifest = JSON.parse(await readFile(path.join(repoRoot, 'package.json'), 'utf8'))
42
+ if (manifest.name !== '@tangle-network/agent-runtime') {
43
+ throw new Error('--local-runtime requires an agent-runtime source workspace')
44
+ }
45
+ await run('pnpm', ['pack', '--pack-destination', packDir], repoRoot)
46
+ const tarballs = (await readdir(packDir)).filter((name) => name.endsWith('.tgz'))
47
+ if (tarballs.length !== 1) {
48
+ throw new Error(`expected one packed agent-runtime tarball, found ${tarballs.length}`)
49
+ }
50
+ return path.join(packDir, tarballs[0])
51
+ }
52
+
53
+ try {
54
+ const packDir = path.join(scratch, 'pack')
55
+ const runtimePackDir = path.join(scratch, 'runtime-pack')
56
+ const consumerDir = path.join(scratch, 'consumer')
57
+ await mkdir(packDir)
58
+ await mkdir(runtimePackDir)
59
+ await mkdir(consumerDir)
60
+
61
+ // Build explicitly so verification cannot inherit a machine-level
62
+ // ignore-scripts setting and accidentally pack stale or missing output.
63
+ await run('pnpm', ['build'], benchDir)
64
+ await run('pnpm', ['pack', '--pack-destination', packDir], benchDir, {
65
+ ...process.env,
66
+ npm_config_ignore_scripts: 'true',
67
+ })
68
+ const packedFiles = (await readdir(packDir)).filter((name) => name.endsWith('.tgz'))
69
+ if (packedFiles.length !== 1) {
70
+ throw new Error(`expected one packed agent-bench tarball, found ${packedFiles.length}`)
71
+ }
72
+ const tarball = path.join(packDir, packedFiles[0])
73
+ const runtimePackage = await resolveRuntimePackage(runtimePackDir)
74
+ const manifest = JSON.parse(await readFile(path.join(benchDir, 'package.json'), 'utf8'))
75
+ const devDependencies = manifest.devDependencies
76
+ if (
77
+ typeof devDependencies?.['@types/node'] !== 'string' ||
78
+ typeof devDependencies.typescript !== 'string' ||
79
+ typeof devDependencies.tsx !== 'string' ||
80
+ !devDependencies['@types/node'] ||
81
+ !devDependencies.typescript ||
82
+ !devDependencies.tsx
83
+ ) {
84
+ throw new Error(
85
+ 'package verification requires @types/node, typescript, and tsx devDependencies',
86
+ )
87
+ }
88
+ const publicTsconfig = JSON.parse(
89
+ await readFile(path.join(benchDir, 'tsconfig.public.json'), 'utf8'),
90
+ )
91
+ if (!publicTsconfig.compilerOptions)
92
+ throw new Error('tsconfig.public.json must define compilerOptions')
93
+
94
+ await writeFile(
95
+ path.join(consumerDir, 'package.json'),
96
+ `${JSON.stringify(
97
+ {
98
+ name: 'agent-bench-package-verifier',
99
+ private: true,
100
+ type: 'module',
101
+ dependencies: {
102
+ '@tangle-network/agent-bench': `file:${tarball}`,
103
+ ...(runtimePackage
104
+ ? { '@tangle-network/agent-runtime': `file:${runtimePackage}` }
105
+ : {}),
106
+ },
107
+ devDependencies: {
108
+ '@types/node': devDependencies['@types/node'],
109
+ typescript: TYPESCRIPT_5,
110
+ tsx: devDependencies.tsx,
111
+ },
112
+ },
113
+ null,
114
+ 2,
115
+ )}\n`,
116
+ )
117
+ await writeFile(
118
+ path.join(consumerDir, 'index.ts'),
119
+ "import { createSweBenchAdapter, executePreparedPierCandidate, FilePierCandidateTrialController, resolveAdapter, runBenchmarks, runStagedJudge, StagedJudgeError, type BenchmarkAdapter, type JudgeArtifactReceipt, type PierCandidateTrialController, type PierCandidateTrialHandle, type PierDockerConnection, type StagedPierCandidateExecution } from '@tangle-network/agent-bench'\n\nconst adapter: BenchmarkAdapter = resolveAdapter('swe-bench')\nconst captureAdapter: BenchmarkAdapter = createSweBenchAdapter({ captureEvaluatorArtifacts: ({ taskId, attemptSequence }) => ({ destination: `/tmp/${taskId}/${attemptSequence}` }) })\nconst receipt = undefined as JudgeArtifactReceipt | undefined\nconst staged = undefined as StagedPierCandidateExecution | undefined\nconst trial = undefined as PierCandidateTrialHandle | undefined\nconst controller = undefined as PierCandidateTrialController | undefined\nconst dockerConnection = undefined as PierDockerConnection | undefined\nvoid adapter\nvoid captureAdapter\nvoid receipt\nvoid staged\nvoid trial\nvoid controller\nvoid dockerConnection\nvoid executePreparedPierCandidate\nvoid FilePierCandidateTrialController\nvoid runBenchmarks\nvoid runStagedJudge\nvoid StagedJudgeError\n",
120
+ )
121
+ await writeFile(
122
+ path.join(consumerDir, 'index.mjs'),
123
+ "import { resolveAdapter, runBenchmarks } from '@tangle-network/agent-bench'\nimport { ADAPTERS } from '@tangle-network/agent-bench/adapters'\nimport { createCragAdapter } from '@tangle-network/agent-bench/benchmarks/crag'\n\nif (typeof resolveAdapter !== 'function' || typeof runBenchmarks !== 'function') throw new Error('root exports are not executable')\nif (typeof ADAPTERS !== 'object' || typeof createCragAdapter !== 'function') throw new Error('subpath exports are not executable')\nif (resolveAdapter('crag').name !== 'crag') throw new Error('compiled adapter registry returned the wrong adapter')\n",
124
+ )
125
+ await writeFile(
126
+ path.join(consumerDir, 'tsconfig.json'),
127
+ `${JSON.stringify(
128
+ {
129
+ compilerOptions: publicTsconfig.compilerOptions,
130
+ files: ['index.ts'],
131
+ },
132
+ null,
133
+ 2,
134
+ )}\n`,
135
+ )
136
+ await writeFile(
137
+ path.join(consumerDir, 'verify_pier_payload.py'),
138
+ `import py_compile
139
+ from pathlib import Path
140
+
141
+ import pier_agents
142
+ from pier_agents import candidate_contract
143
+
144
+ root = Path(pier_agents.__file__).parent
145
+ expected = {
146
+ "__init__.py",
147
+ "candidate_contract.py",
148
+ "process_boundary.py",
149
+ "tangle_candidate.py",
150
+ "workspace_boundary.py",
151
+ }
152
+ observed = {path.name for path in root.glob("*.py")}
153
+ assert observed == expected, (observed, expected)
154
+ assert candidate_contract.PreparedCandidateContract.__module__ == "pier_agents.candidate_contract"
155
+ for name in sorted(expected):
156
+ py_compile.compile(root / name, doraise=True)
157
+ `,
158
+ )
159
+
160
+ // Intentionally resolve the declared ranges like a brand-new registry consumer.
161
+ // The preceding frozen install + public typecheck cover the exact bench lockfile.
162
+ await run(
163
+ 'npm',
164
+ ['install', '--ignore-scripts', '--no-audit', '--no-fund', '--package-lock=false'],
165
+ consumerDir,
166
+ )
167
+ await run('node', ['index.mjs'], consumerDir)
168
+ await run('npm', ['exec', '--', 'tsc', '-p', 'tsconfig.json'], consumerDir)
169
+ const typescript5 = await run('npm', ['exec', '--', 'tsc', '--version'], consumerDir)
170
+ if (typescript5.stdout.trim() !== `Version ${TYPESCRIPT_5}`) {
171
+ throw new Error(`expected TypeScript ${TYPESCRIPT_5}, received ${typescript5.stdout.trim()}`)
172
+ }
173
+ await run(
174
+ 'npm',
175
+ [
176
+ 'install',
177
+ '--ignore-scripts',
178
+ '--no-audit',
179
+ '--no-fund',
180
+ '--no-save',
181
+ '--package-lock=false',
182
+ `typescript@${TYPESCRIPT_6}`,
183
+ ],
184
+ consumerDir,
185
+ )
186
+ await run('npm', ['exec', '--', 'tsc', '-p', 'tsconfig.json'], consumerDir)
187
+ const typescript6 = await run('npm', ['exec', '--', 'tsc', '--version'], consumerDir)
188
+ if (typescript6.stdout.trim() !== `Version ${TYPESCRIPT_6}`) {
189
+ throw new Error(`expected TypeScript ${TYPESCRIPT_6}, received ${typescript6.stdout.trim()}`)
190
+ }
191
+ await run('npm', ['exec', '--', 'tsx', 'index.ts'], consumerDir)
192
+ const installedPackage = path.join(consumerDir, 'node_modules', '@tangle-network', 'agent-bench')
193
+ const prepared = await run(
194
+ 'npm',
195
+ [
196
+ 'exec',
197
+ '--',
198
+ 'tsx',
199
+ path.join(installedPackage, 'scripts', 'verify-pier-agent.mts'),
200
+ ],
201
+ consumerDir,
202
+ { ...process.env, PIER_PREPARE_ONLY: '1', PIER_PROOF_ARM: 'failure' },
203
+ )
204
+ const prepareProof = JSON.parse(prepared.stdout)
205
+ if (
206
+ prepareProof.prepared !== true ||
207
+ prepareProof.disposed !== true ||
208
+ !/^sha256:[a-f0-9]{64}$/.test(prepareProof.executionPlanDigest) ||
209
+ !/^sha256:[a-f0-9]{64}$/.test(prepareProof.graderDigest)
210
+ ) {
211
+ throw new Error(`packed consumer did not prepare a real candidate: ${prepared.stdout}`)
212
+ }
213
+ await run('python3', ['verify_pier_payload.py'], consumerDir, {
214
+ ...process.env,
215
+ PYTHONPATH: installedPackage,
216
+ })
217
+ let runtimeManifest
218
+ try {
219
+ runtimeManifest = JSON.parse(
220
+ await readFile(
221
+ path.join(consumerDir, 'node_modules/@tangle-network/agent-runtime/package.json'),
222
+ 'utf8',
223
+ ),
224
+ )
225
+ } catch (error) {
226
+ throw new Error('packed consumer did not install @tangle-network/agent-runtime', {
227
+ cause: error,
228
+ })
229
+ }
230
+ console.log(
231
+ `packed consumer verified: ${manifest.name}@${manifest.version} with @tangle-network/agent-runtime@${runtimeManifest.version}, TypeScript ${TYPESCRIPT_5} and ${TYPESCRIPT_6}; prepared ${prepareProof.executionPlanDigest}`,
232
+ )
233
+ } finally {
234
+ await rm(scratch, { recursive: true, force: true })
235
+ }