verifiers 0.3.2.dev46__tar.gz → 0.3.2.dev49__tar.gz

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 (215) hide show
  1. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/PKG-INFO +1 -1
  2. verifiers-0.3.2.dev49/verifiers/cli/commands/init.py +6 -0
  3. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/harness.py +4 -0
  4. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/claude_code/harness.py +11 -25
  5. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/codex/harness.py +11 -23
  6. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/hermes_agent/harness.py +4 -9
  7. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/kimi_code/harness.py +9 -13
  8. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/mini_swe_agent/harness.py +2 -4
  9. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/node.py +9 -14
  10. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/openclaw/harness.py +14 -30
  11. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/pi/harness.py +9 -20
  12. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/pool/harness.py +11 -14
  13. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/prime_agent/harness.py +8 -18
  14. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/rlm/harness.py +9 -7
  15. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/terminus_2/harness.py +2 -4
  16. verifiers-0.3.2.dev49/verifiers/v1/harnesses/utils/install.py +65 -0
  17. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/.gitignore +0 -0
  18. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/LICENSE +0 -0
  19. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/README.md +0 -0
  20. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/pyproject.toml +0 -0
  21. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/conftest.py +0 -0
  22. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/fixtures/counter_tool_v1.py +0 -0
  23. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/fixtures/duet_v1.py +0 -0
  24. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/fixtures/echo_acp_resume_v1.py +0 -0
  25. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
  26. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/fixtures/echo_tool_v1.py +0 -0
  27. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
  28. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/fixtures/echo_v1.py +0 -0
  29. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/fixtures/pyproject.toml +0 -0
  30. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
  31. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/test_color_codeword_tasks.py +0 -0
  32. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/test_configs.py +0 -0
  33. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/test_e2e.py +0 -0
  34. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/test_envs.py +0 -0
  35. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/test_graph.py +0 -0
  36. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/test_judges.py +0 -0
  37. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/test_scoring.py +0 -0
  38. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/test_taskset.py +0 -0
  39. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/tests/v1/test_trace.py +0 -0
  40. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/__init__.py +0 -0
  41. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/__init__.py +0 -0
  42. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/acp/__init__.py +0 -0
  43. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/acp/runner.py +0 -0
  44. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/agent.py +0 -0
  45. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/__init__.py +0 -0
  46. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/dashboard/__init__.py +0 -0
  47. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/dashboard/base.py +0 -0
  48. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/dashboard/eval.py +0 -0
  49. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/dashboard/replay.py +0 -0
  50. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/dashboard/validate.py +0 -0
  51. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/debug.py +0 -0
  52. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/eval/__init__.py +0 -0
  53. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/eval/main.py +0 -0
  54. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/eval/resume.py +0 -0
  55. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/eval/runner.py +0 -0
  56. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/gepa.py +0 -0
  57. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/init.py +0 -0
  58. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/output.py +0 -0
  59. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/replay.py +0 -0
  60. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/resolve.py +0 -0
  61. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/resume.py +0 -0
  62. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/cli/validate.py +0 -0
  63. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/clients/__init__.py +0 -0
  64. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/clients/base.py +0 -0
  65. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/clients/client.py +0 -0
  66. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/clients/eval.py +0 -0
  67. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/clients/train.py +0 -0
  68. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/__init__.py +0 -0
  69. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/agent.py +0 -0
  70. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/cli/__init__.py +0 -0
  71. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/cli/debug.py +0 -0
  72. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/cli/env.py +0 -0
  73. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/cli/eval.py +0 -0
  74. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/cli/init.py +0 -0
  75. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/cli/replay.py +0 -0
  76. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/cli/validate.py +0 -0
  77. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/client.py +0 -0
  78. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/env.py +0 -0
  79. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/judge.py +0 -0
  80. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/retries.py +0 -0
  81. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/runtime.py +0 -0
  82. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/serve.py +0 -0
  83. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/task.py +0 -0
  84. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/configs/taskset.py +0 -0
  85. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/dialects/__init__.py +0 -0
  86. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/dialects/anthropic.py +0 -0
  87. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/dialects/base.py +0 -0
  88. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/dialects/chat.py +0 -0
  89. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/dialects/responses.py +0 -0
  90. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/env.py +0 -0
  91. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/__init__.py +0 -0
  92. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
  93. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/agentic_judge/env.py +0 -0
  94. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
  95. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/best_of_n/env.py +0 -0
  96. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/isolated_verifier/__init__.py +0 -0
  97. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/isolated_verifier/env.py +0 -0
  98. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/shared_agentic_judge/__init__.py +0 -0
  99. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/single_agent/__init__.py +0 -0
  100. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/single_agent/env.py +0 -0
  101. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/user_sim/__init__.py +0 -0
  102. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/envs/user_sim/env.py +0 -0
  103. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/episode.py +0 -0
  104. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/errors.py +0 -0
  105. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/gepa/__init__.py +0 -0
  106. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/gepa/adapter.py +0 -0
  107. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/gepa/config.py +0 -0
  108. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/gepa/dataset.py +0 -0
  109. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/gepa/reflection.py +0 -0
  110. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/gepa/runner.py +0 -0
  111. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/graph.py +0 -0
  112. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harness.py +0 -0
  113. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/__init__.py +0 -0
  114. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/bash/__init__.py +0 -0
  115. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/bash/harness.py +0 -0
  116. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
  117. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
  118. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/browser_use/program.py +0 -0
  119. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
  120. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/codex/__init__.py +0 -0
  121. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
  122. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
  123. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
  124. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
  125. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
  126. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/null/__init__.py +0 -0
  127. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/null/harness.py +0 -0
  128. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
  129. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/pi/__init__.py +0 -0
  130. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/pool/__init__.py +0 -0
  131. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
  132. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
  133. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
  134. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
  135. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/utils/__init__.py +0 -0
  136. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/utils/compaction.py +0 -0
  137. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/utils/core.py +0 -0
  138. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/utils/launch.py +0 -0
  139. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/harnesses/utils/mcp.py +0 -0
  140. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/interception/__init__.py +0 -0
  141. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/interception/base.py +0 -0
  142. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/interception/pool.py +0 -0
  143. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/interception/server.py +0 -0
  144. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/interception/tool.py +0 -0
  145. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/interception/tunnel/__init__.py +0 -0
  146. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/interception/tunnel/base.py +0 -0
  147. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/interception/tunnel/custom.py +0 -0
  148. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/interception/tunnel/prime.py +0 -0
  149. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/judge.py +0 -0
  150. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/judges/__init__.py +0 -0
  151. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/judges/reference.py +0 -0
  152. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/judges/reference.txt +0 -0
  153. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/judges/rubric.py +0 -0
  154. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/judges/rubric.txt +0 -0
  155. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/mcp/__init__.py +0 -0
  156. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/mcp/launch.py +0 -0
  157. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/mcp/server.py +0 -0
  158. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/mcp/toolset.py +0 -0
  159. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/rollout.py +0 -0
  160. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/runtimes/__init__.py +0 -0
  161. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/runtimes/base.py +0 -0
  162. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/runtimes/docker/__init__.py +0 -0
  163. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/runtimes/docker/egress.py +0 -0
  164. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/runtimes/limiters.py +0 -0
  165. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/runtimes/modal.py +0 -0
  166. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/runtimes/prime.py +0 -0
  167. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/runtimes/subprocess.py +0 -0
  168. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/semantic.py +0 -0
  169. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/serve/__init__.py +0 -0
  170. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/serve/client.py +0 -0
  171. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/serve/encoding.py +0 -0
  172. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/serve/pool.py +0 -0
  173. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/serve/server.py +0 -0
  174. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/serve/types.py +0 -0
  175. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/session.py +0 -0
  176. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/state.py +0 -0
  177. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/task.py +0 -0
  178. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/taskset.py +0 -0
  179. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/__init__.py +0 -0
  180. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
  181. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/harbor/env.py +0 -0
  182. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
  183. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/lean/__init__.py +0 -0
  184. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/lean/scoring.py +0 -0
  185. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/lean/taskset.py +0 -0
  186. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
  187. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
  188. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
  189. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
  190. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
  191. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
  192. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
  193. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
  194. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
  195. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/trace.py +0 -0
  196. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/types.py +0 -0
  197. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/__init__.py +0 -0
  198. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/aio.py +0 -0
  199. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/artifacts.py +0 -0
  200. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/compile.py +0 -0
  201. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/decorators.py +0 -0
  202. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/format.py +0 -0
  203. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/generic.py +0 -0
  204. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/git.py +0 -0
  205. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/image.py +0 -0
  206. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/interrupt.py +0 -0
  207. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/loaders.py +0 -0
  208. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/logging.py +0 -0
  209. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/memory.py +0 -0
  210. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/paths.py +0 -0
  211. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/platform.py +0 -0
  212. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/prime.py +0 -0
  213. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/retries.py +0 -0
  214. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/score.py +0 -0
  215. {verifiers-0.3.2.dev46 → verifiers-0.3.2.dev49}/verifiers/v1/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: verifiers
3
- Version: 0.3.2.dev46
3
+ Version: 0.3.2.dev49
4
4
  Summary: Verifiers: Environments for LLM Reinforcement Learning
5
5
  Project-URL: Homepage, https://github.com/primeintellect-ai/verifiers
6
6
  Project-URL: Documentation, https://github.com/primeintellect-ai/verifiers
@@ -0,0 +1,6 @@
1
+ """Environment initialization command module for external hosts."""
2
+
3
+ from verifiers.v1.cli.init import main
4
+
5
+ if __name__ == "__main__":
6
+ main()
@@ -4,12 +4,16 @@ from __future__ import annotations
4
4
 
5
5
  import os
6
6
  from pathlib import Path
7
+ from typing import Annotated
7
8
 
8
9
  from pydantic import ConfigDict, Field, FiniteFloat
9
10
  from pydantic_config import BaseConfig
10
11
 
11
12
  from verifiers.v1.types import ID
12
13
 
14
+ PinnedVersion = Annotated[str, Field(pattern=r"^[A-Za-z0-9._+-]+$")]
15
+ """A release/tag a harness pins its program install to."""
16
+
13
17
 
14
18
  class HarnessConfig(BaseConfig):
15
19
  id: ID = "bash"
@@ -1,13 +1,10 @@
1
1
  """Run Claude Code through the Claude Agent SDK ACP adapter."""
2
2
 
3
- import shlex
4
-
5
- from pydantic import Field
6
-
7
3
  from verifiers.v1.acp import ACPConfig, ACPHarness
8
4
  from verifiers.v1.clients import ModelContext
9
- from verifiers.v1.configs.harness import HarnessConfig
5
+ from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
10
6
  from verifiers.v1.harnesses.node import NODE_BIN_DIR, ensure_node
7
+ from verifiers.v1.harnesses.utils.install import ensure_installed, remove_dir
11
8
  from verifiers.v1.runtimes import Runtime
12
9
  from verifiers.v1.task import TaskData
13
10
  from verifiers.v1.trace import Trace
@@ -32,7 +29,7 @@ touch {ready}
32
29
 
33
30
 
34
31
  class ClaudeCodeHarnessConfig(HarnessConfig):
35
- version: str = Field(default="2.1.232", pattern=r"^[A-Za-z0-9._+-]+$")
32
+ version: PinnedVersion = "2.1.232"
36
33
  """Claude Code release to install, pinned for reproducibility."""
37
34
 
38
35
 
@@ -51,25 +48,18 @@ class ClaudeCodeHarness(ACPHarness[ClaudeCodeHarnessConfig]):
51
48
  acp_bin = ACP_BIN.format(**versions)
52
49
  ready = f"{directory}/.ready"
53
50
  script = ACP_INSTALL.replace("{packages}", packages).replace("{ready}", ready)
54
- ensure = shlex.quote(
55
- f"[ -f {ready} ] && [ -x {claude_bin} ] && [ -x {acp_bin} ] || ({script})"
56
- )
57
- acp_guarded = (
58
- f"mkdir -p {directory} && "
59
- f'"$(command -v flock || command -v lockf)" {directory}/install.lock '
60
- f"sh -c {ensure}"
61
- )
62
- acp_result = await runtime.run(
63
- ["sh", "-c", acp_guarded],
64
- {
51
+ await ensure_installed(
52
+ runtime,
53
+ directory=directory,
54
+ ready=f"[ -f {ready} ] && [ -x {claude_bin} ] && [ -x {acp_bin} ]",
55
+ install=script,
56
+ env={
65
57
  **self.config.resolved_env,
66
58
  "VF_CLAUDE_CODE_VERSION": self.config.version,
67
59
  "VF_CLAUDE_ACP_VERSION": ACP_VERSION,
68
60
  },
61
+ label="Claude Agent ACP",
69
62
  )
70
- if acp_result.exit_code != 0:
71
- detail = (acp_result.stderr or acp_result.stdout).strip()[-500:]
72
- raise RuntimeError(f"Claude Agent ACP install failed: {detail}")
73
63
  await super().setup(runtime)
74
64
 
75
65
  async def prepare_acp(
@@ -113,11 +103,7 @@ class ClaudeCodeHarness(ACPHarness[ClaudeCodeHarnessConfig]):
113
103
  )
114
104
 
115
105
  async def cleanup(self, trace: Trace, runtime: Runtime) -> None:
116
- result = await runtime.run(["rm", "-rf", self.config_dir(trace)], {})
117
- if result.exit_code != 0:
118
- raise RuntimeError(
119
- f"failed to clean up Claude config: {result.stderr.strip()[-500:]}"
120
- )
106
+ await remove_dir(runtime, self.config_dir(trace), "Claude config")
121
107
 
122
108
  @staticmethod
123
109
  def config_dir(trace: Trace) -> str:
@@ -4,15 +4,13 @@ import hashlib
4
4
  import json
5
5
  import logging
6
6
  import re
7
- import shlex
8
7
  from collections import Counter
9
8
 
10
- from pydantic import Field
11
-
12
9
  from verifiers.v1.acp import ACPConfig, ACPHarness
13
10
  from verifiers.v1.clients import ModelContext
14
- from verifiers.v1.configs.harness import HarnessConfig
11
+ from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
15
12
  from verifiers.v1.harnesses.node import NODE_BIN_DIR, ensure_node
13
+ from verifiers.v1.harnesses.utils.install import ensure_installed, remove_dir
16
14
  from verifiers.v1.runtimes import Runtime
17
15
  from verifiers.v1.task import TaskData
18
16
  from verifiers.v1.trace import Trace
@@ -38,7 +36,7 @@ touch {ready}
38
36
 
39
37
 
40
38
  class CodexHarnessConfig(HarnessConfig):
41
- version: str = Field(default="0.147.0", pattern=r"^[A-Za-z0-9._+-]+$")
39
+ version: PinnedVersion = "0.147.0"
42
40
  """Codex release to install, pinned for reproducibility."""
43
41
  multi_agent: bool = False
44
42
  """Enable Codex's native multi-agent v2 tools."""
@@ -64,24 +62,18 @@ class CodexHarness(ACPHarness[CodexHarnessConfig]):
64
62
  acp_bin = ACP_BIN.format(**versions)
65
63
  ready = f"{directory}/.ready"
66
64
  script = INSTALL.replace("{packages}", packages).replace("{ready}", ready)
67
- ensure = shlex.quote(
68
- f"[ -f {ready} ] && [ -x {codex_bin} ] && [ -x {acp_bin} ] || ({script})"
69
- )
70
- guarded = (
71
- f"mkdir -p {directory} && "
72
- f'"$(command -v flock || command -v lockf)" {directory}/install.lock '
73
- f"sh -c {ensure}"
74
- )
75
- install = await runtime.run(
76
- ["sh", "-c", guarded],
77
- {
65
+ await ensure_installed(
66
+ runtime,
67
+ directory=directory,
68
+ ready=f"[ -f {ready} ] && [ -x {codex_bin} ] && [ -x {acp_bin} ]",
69
+ install=script,
70
+ env={
78
71
  **self.config.resolved_env,
79
72
  "VF_CODEX_VERSION": self.config.version,
80
73
  "VF_CODEX_ACP_VERSION": ACP_VERSION,
81
74
  },
75
+ label="codex",
82
76
  )
83
- if install.exit_code != 0:
84
- raise RuntimeError(f"codex install failed: {install.stderr.strip()[-500:]}")
85
77
  await super().setup(runtime)
86
78
 
87
79
  async def prepare_acp(
@@ -112,11 +104,7 @@ class CodexHarness(ACPHarness[CodexHarnessConfig]):
112
104
  )
113
105
 
114
106
  async def cleanup(self, trace: Trace, runtime: Runtime) -> None:
115
- result = await runtime.run(["rm", "-rf", self.trace_home(trace)], {})
116
- if result.exit_code != 0:
117
- raise RuntimeError(
118
- f"failed to clean up Codex home: {result.stderr.strip()[-500:]}"
119
- )
107
+ await remove_dir(runtime, self.trace_home(trace), "Codex home")
120
108
 
121
109
  @staticmethod
122
110
  def trace_home(trace: Trace) -> str:
@@ -3,11 +3,10 @@
3
3
  import json
4
4
  from pathlib import Path
5
5
 
6
- from pydantic import Field
7
-
8
6
  from verifiers.v1.acp import ACPConfig, ACPHarness
9
7
  from verifiers.v1.clients import ModelContext
10
- from verifiers.v1.configs.harness import HarnessConfig
8
+ from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
9
+ from verifiers.v1.harnesses.utils.install import remove_dir
11
10
  from verifiers.v1.runtimes import Runtime
12
11
  from verifiers.v1.task import TaskData
13
12
  from verifiers.v1.trace import Trace
@@ -16,7 +15,7 @@ PROGRAM_SOURCE = (Path(__file__).resolve().parent / "program.py").read_text()
16
15
 
17
16
 
18
17
  class HermesAgentHarnessConfig(HarnessConfig):
19
- version: str = Field(default="0.19.0", pattern=r"^[A-Za-z0-9._+-]+$")
18
+ version: PinnedVersion = "0.19.0"
20
19
  """Hermes Agent release to install, pinned for reproducibility."""
21
20
  use_bundled_skill: bool = False
22
21
  """Enable Hermes Agent's bundled skill catalog in addition to uploaded skills."""
@@ -96,8 +95,4 @@ class HermesAgentHarness(ACPHarness[HermesAgentHarnessConfig]):
96
95
  )
97
96
 
98
97
  async def cleanup(self, trace: Trace, runtime: Runtime) -> None:
99
- result = await runtime.run(["rm", "-rf", f"/tmp/vf-hermes/{trace.id}"], {})
100
- if result.exit_code:
101
- raise RuntimeError(
102
- f"failed to clean up Hermes home: {result.stderr.strip()[-500:]}"
103
- )
98
+ await remove_dir(runtime, f"/tmp/vf-hermes/{trace.id}", "Hermes home")
@@ -1,15 +1,14 @@
1
1
  """Run Kimi Code's native ACP server against interception."""
2
2
 
3
3
  import logging
4
- import shlex
5
4
  from typing import Literal
6
5
 
7
6
  import tomli_w
8
- from pydantic import Field
9
7
 
10
8
  from verifiers.v1.acp import ACPConfig, ACPHarness
11
9
  from verifiers.v1.clients import ModelContext
12
- from verifiers.v1.configs.harness import HarnessConfig
10
+ from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
11
+ from verifiers.v1.harnesses.utils.install import ensure_installed
13
12
  from verifiers.v1.runtimes import Runtime
14
13
  from verifiers.v1.task import TaskData
15
14
  from verifiers.v1.trace import Trace
@@ -39,7 +38,7 @@ env \
39
38
 
40
39
 
41
40
  class KimiCodeHarnessConfig(HarnessConfig):
42
- version: str = Field(default="0.36.0", pattern=r"^[A-Za-z0-9._+-]+$")
41
+ version: PinnedVersion = "0.36.0"
43
42
  """Kimi Code release to install, pinned for reproducibility."""
44
43
  transport: Literal["chat_completions", "responses", "anthropic_messages"] = (
45
44
  "chat_completions"
@@ -58,16 +57,13 @@ class KimiCodeHarness(ACPHarness[KimiCodeHarnessConfig]):
58
57
  "kimi-code: ensuring Kimi Code %s is installed", self.config.version
59
58
  )
60
59
  script = INSTALL.replace("{version}", self.config.version)
61
- guarded = (
62
- "mkdir -p /tmp/vf-kimi-code && "
63
- '"$(command -v flock || command -v lockf)" '
64
- f"/tmp/vf-kimi-code/install.lock sh -c {shlex.quote(script)}"
60
+ await ensure_installed(
61
+ runtime,
62
+ directory="/tmp/vf-kimi-code",
63
+ install=script,
64
+ env={},
65
+ label="Kimi Code",
65
66
  )
66
- install = await runtime.run(["sh", "-c", guarded], {})
67
- if install.exit_code != 0:
68
- raise RuntimeError(
69
- f"Kimi Code install failed: {install.stderr.strip()[-500:]}"
70
- )
71
67
  await super().setup(runtime)
72
68
 
73
69
  async def prepare_acp(
@@ -1,9 +1,7 @@
1
1
  from pathlib import Path
2
2
 
3
- from pydantic import Field
4
-
5
3
  from verifiers.v1.clients import ModelContext
6
- from verifiers.v1.configs.harness import HarnessConfig
4
+ from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
7
5
  from verifiers.v1.harness import Harness
8
6
  from verifiers.v1.runtimes import ProgramResult, Runtime
9
7
  from verifiers.v1.task import TaskData
@@ -13,7 +11,7 @@ PROGRAM_SOURCE = (Path(__file__).resolve().parent / "program.py").read_text()
13
11
 
14
12
 
15
13
  class MiniSWEAgentHarnessConfig(HarnessConfig):
16
- version: str = Field(default="2.4.6", pattern=r"^[A-Za-z0-9._+-]+$")
14
+ version: PinnedVersion = "2.4.6"
17
15
  """mini-swe-agent release to install, pinned for reproducibility."""
18
16
 
19
17
 
@@ -1,5 +1,4 @@
1
- import shlex
2
-
1
+ from verifiers.v1.harnesses.utils.install import ensure_installed
3
2
  from verifiers.v1.runtimes import Runtime
4
3
 
5
4
  NODE_DIR = "/var/tmp/vf-node"
@@ -39,16 +38,12 @@ node_ok || { echo "ACP adapters require Node.js 22.19 or newer" >&2; exit 1; }
39
38
 
40
39
  async def ensure_node(runtime: Runtime) -> None:
41
40
  """Install the shared Node runtime used by ACP adapter harnesses."""
42
- lock = f"{NODE_DIR}.install.lock"
43
- guarded = (
44
- f'until ln -s "$$" {lock} 2>/dev/null; do '
45
- f"owner=$(readlink {lock}); "
46
- f'if ! kill -0 "$owner" 2>/dev/null; then '
47
- f'[ "$(readlink {lock})" != "$owner" ] || rm -f {lock}; fi; '
48
- f"sleep 0.1; done; "
49
- f'trap \'[ "$(readlink {lock})" != "$$" ] || rm -f {lock}\' EXIT; '
50
- f"sh -c {shlex.quote(INSTALL)}"
41
+ # The install replaces NODE_DIR wholesale, so the lock lives beside it.
42
+ await ensure_installed(
43
+ runtime,
44
+ directory=NODE_DIR,
45
+ lock=f"{NODE_DIR}.install.lock",
46
+ install=INSTALL,
47
+ env={"VF_NODE_VERSION": NODE_VERSION},
48
+ label="Node.js",
51
49
  )
52
- result = await runtime.run(["sh", "-c", guarded], {"VF_NODE_VERSION": NODE_VERSION})
53
- if result.exit_code != 0:
54
- raise RuntimeError(f"Node.js install failed: {result.stderr.strip()[-500:]}")
@@ -4,13 +4,11 @@ import asyncio
4
4
  import json
5
5
  import logging
6
6
  import secrets
7
- import shlex
8
-
9
- from pydantic import Field
10
7
 
11
8
  from verifiers.v1.acp import ACPConfig, ACPHarness
12
9
  from verifiers.v1.clients import ModelContext
13
- from verifiers.v1.configs.harness import HarnessConfig
10
+ from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
11
+ from verifiers.v1.harnesses.utils.install import ensure_installed, remove_dir
14
12
  from verifiers.v1.runtimes import Runtime
15
13
  from verifiers.v1.task import TaskData
16
14
  from verifiers.v1.trace import Trace
@@ -120,7 +118,7 @@ wait "$acp_pid"
120
118
 
121
119
 
122
120
  class OpenClawHarnessConfig(HarnessConfig):
123
- version: str = Field(default="2026.8.1", pattern=r"^[A-Za-z0-9._+-]+$")
121
+ version: PinnedVersion = "2026.8.1"
124
122
  """OpenClaw release to install, pinned for reproducibility."""
125
123
  use_bundled_skill: bool = True
126
124
  """Enable OpenClaw's bundled skill catalog in addition to uploaded harness skills."""
@@ -143,39 +141,29 @@ class OpenClawHarness(ACPHarness[OpenClawHarnessConfig]):
143
141
  ready_path = f"{self._staged_skills_dir}/.ready"
144
142
  ready = await runtime.run(["test", "-f", ready_path], {})
145
143
  if ready.exit_code != 0:
146
- cleared = await runtime.run(
147
- ["rm", "-rf", self._staged_skills_dir], {}
144
+ await remove_dir(
145
+ runtime, self._staged_skills_dir, "OpenClaw skills"
148
146
  )
149
- if cleared.exit_code != 0:
150
- raise RuntimeError(
151
- "failed to clear OpenClaw skills: "
152
- f"{cleared.stderr.strip()[-500:]}"
153
- )
154
147
  await self.install_skills(runtime, self._staged_skills_dir)
155
148
  await runtime.write(ready_path, b"")
156
149
  directory = OPENCLAW_DIR.format(version=self.config.version)
157
150
  binary = OPENCLAW_BIN.format(version=self.config.version)
151
+ logger.info("openclaw: ensuring OpenClaw %s is installed", self.config.version)
158
152
  # Borrowed runtimes can share this cache, so one filesystem lock owns both
159
153
  # installation and the transcript adjustment.
160
- guarded = (
161
- f"mkdir -p {shlex.quote(directory)} && "
162
- f'"$(command -v flock || command -v lockf)" '
163
- f"{shlex.quote(f'{directory}/install.lock')} "
164
- f"bash -o pipefail -c {shlex.quote(SETUP)}"
165
- )
166
- logger.info("openclaw: ensuring OpenClaw %s is installed", self.config.version)
167
- result = await runtime.run(
168
- ["sh", "-c", guarded],
169
- {
154
+ await ensure_installed(
155
+ runtime,
156
+ directory=directory,
157
+ install=SETUP,
158
+ env={
170
159
  **self.config.resolved_env,
171
160
  "VF_OPENCLAW_BIN": binary,
172
161
  "VF_OPENCLAW_DIR": directory,
173
162
  "VF_OPENCLAW_VERSION": self.config.version,
174
163
  },
164
+ label="OpenClaw",
165
+ shell=("bash", "-o", "pipefail", "-c"),
175
166
  )
176
- if result.exit_code != 0:
177
- detail = (result.stderr or result.stdout).strip()[-500:]
178
- raise RuntimeError(f"OpenClaw setup failed: {detail}")
179
167
  await super().setup(runtime)
180
168
 
181
169
  async def prepare_acp(
@@ -277,8 +265,4 @@ class OpenClawHarness(ACPHarness[OpenClawHarnessConfig]):
277
265
 
278
266
  async def cleanup(self, trace: Trace, runtime: Runtime) -> None:
279
267
  state_dir = f".vf-openclaw/{trace.id}"
280
- result = await runtime.run(["rm", "-rf", state_dir], {})
281
- if result.exit_code != 0:
282
- raise RuntimeError(
283
- f"failed to clean up OpenClaw state: {result.stderr.strip()[-500:]}"
284
- )
268
+ await remove_dir(runtime, state_dir, "OpenClaw state")
@@ -5,12 +5,11 @@ import logging
5
5
  import shlex
6
6
  from typing import Literal
7
7
 
8
- from pydantic import Field
9
-
10
8
  from verifiers.v1.acp import ACPConfig, ACPHarness
11
9
  from verifiers.v1.clients import ModelContext
12
- from verifiers.v1.configs.harness import HarnessConfig
10
+ from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
13
11
  from verifiers.v1.harnesses.node import NODE_BIN_DIR, ensure_node
12
+ from verifiers.v1.harnesses.utils.install import ensure_installed
14
13
  from verifiers.v1.runtimes import Runtime
15
14
  from verifiers.v1.task import TaskData
16
15
  from verifiers.v1.trace import Trace
@@ -46,7 +45,7 @@ fi
46
45
 
47
46
 
48
47
  class PiHarnessConfig(HarnessConfig):
49
- version: str = Field(default="0.84.1", pattern=r"^[A-Za-z0-9._+-]+$")
48
+ version: PinnedVersion = "0.84.1"
50
49
  """Pi release to install, pinned for reproducibility."""
51
50
  transport: Literal["chat_completions", "responses", "anthropic_messages"] = (
52
51
  "chat_completions"
@@ -69,27 +68,17 @@ class PiHarness(ACPHarness[PiHarnessConfig]):
69
68
  self.config.version,
70
69
  ACP_VERSION,
71
70
  )
72
- lock = f"{PI_DIR}/install.lock"
73
- guarded = (
74
- f"mkdir -p {PI_DIR} && "
75
- f'until ln -s "$$" {lock} 2>/dev/null; do '
76
- f"owner=$(readlink {lock}); "
77
- f'if ! kill -0 "$owner" 2>/dev/null; then '
78
- f'[ "$(readlink {lock})" != "$owner" ] || rm -f {lock}; fi; '
79
- f"sleep 0.1; done; "
80
- f'trap \'[ "$(readlink {lock})" != "$$" ] || rm -f {lock}\' EXIT; '
81
- f"sh -c {shlex.quote(INSTALL)}"
82
- )
83
- install = await runtime.run(
84
- ["sh", "-c", guarded],
85
- {
71
+ await ensure_installed(
72
+ runtime,
73
+ directory=PI_DIR,
74
+ install=INSTALL,
75
+ env={
86
76
  "VF_PI_VERSION": self.config.version,
87
77
  "VF_PI_MCP_VERSION": MCP_VERSION,
88
78
  "VF_PI_ACP_VERSION": ACP_VERSION,
89
79
  },
80
+ label="pi",
90
81
  )
91
- if install.exit_code != 0:
92
- raise RuntimeError(f"pi install failed: {install.stderr.strip()[-500:]}")
93
82
  await super().setup(runtime)
94
83
 
95
84
  async def prepare_acp(
@@ -3,11 +3,10 @@
3
3
  import json
4
4
  import shlex
5
5
 
6
- from pydantic import Field
7
-
8
6
  from verifiers.v1.acp import ACPConfig, ACPHarness
9
7
  from verifiers.v1.clients import ModelContext
10
- from verifiers.v1.configs.harness import HarnessConfig
8
+ from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
9
+ from verifiers.v1.harnesses.utils.install import ensure_installed
11
10
  from verifiers.v1.runtimes import Runtime
12
11
  from verifiers.v1.task import TaskData
13
12
  from verifiers.v1.trace import Trace
@@ -28,7 +27,7 @@ chmod +x "{dir}/pool"
28
27
 
29
28
 
30
29
  class PoolHarnessConfig(HarnessConfig):
31
- version: str = Field(default="1.0.15", pattern=r"^[A-Za-z0-9._+-]+$")
30
+ version: PinnedVersion = "1.0.15"
32
31
  """Pool release to install, pinned for reproducibility."""
33
32
 
34
33
 
@@ -44,17 +43,15 @@ class PoolHarness(ACPHarness[PoolHarnessConfig]):
44
43
  script = INSTALL.replace("{version}", self.config.version).replace(
45
44
  "{dir}", directory
46
45
  )
47
- ensure = shlex.quote(f"[ -x {binary} ] || ({script})")
48
- # Cache the pinned binary across local rollouts; Linux has flock, macOS has lockf.
49
- guarded = (
50
- f"mkdir -p {directory} && "
51
- f'"$(command -v flock || command -v lockf)" {directory}/install.lock '
52
- f"bash -o pipefail -c {ensure}"
46
+ await ensure_installed(
47
+ runtime,
48
+ directory=directory,
49
+ ready=f"[ -x {binary} ]",
50
+ install=script,
51
+ env=self.config.resolved_env,
52
+ label="Pool",
53
+ shell=("bash", "-o", "pipefail", "-c"),
53
54
  )
54
- result = await runtime.run(["sh", "-c", guarded], self.config.resolved_env)
55
- if result.exit_code != 0:
56
- detail = (result.stderr or result.stdout).strip()[-500:]
57
- raise RuntimeError(f"Pool install failed: {detail}")
58
55
  await super().setup(runtime)
59
56
 
60
57
  async def prepare_acp(
@@ -10,6 +10,7 @@ from verifiers.v1.acp import ACPConfig, ACPHarness, ACPTurn
10
10
  from verifiers.v1.clients import ModelContext
11
11
  from verifiers.v1.configs.harness import HarnessConfig
12
12
  from verifiers.v1.harnesses.node import NODE_BIN_DIR, ensure_node
13
+ from verifiers.v1.harnesses.utils.install import ensure_installed, remove_dir
13
14
  from verifiers.v1.runtimes import Runtime
14
15
  from verifiers.v1.task import TaskData
15
16
  from verifiers.v1.trace import Trace
@@ -157,26 +158,19 @@ class PrimeAgentHarness(ACPHarness[PrimeAgentHarnessConfig]):
157
158
  await self.install_skills(runtime, SKILLS_DIR)
158
159
  await ensure_node(runtime)
159
160
  logger.info("prime-agent: ensuring commit %s is installed", self.config.commit)
160
- lock = f"{PRIME_AGENT_DIR}/install.lock"
161
- guarded = (
162
- f"mkdir -p {PRIME_AGENT_DIR} && "
163
- f'"$(command -v flock || command -v lockf)" {lock} '
164
- f"sh -c {shlex.quote(INSTALL)}"
165
- )
166
- result = await runtime.run(
167
- ["sh", "-c", guarded],
168
- {
161
+ await ensure_installed(
162
+ runtime,
163
+ directory=PRIME_AGENT_DIR,
164
+ install=INSTALL,
165
+ env={
169
166
  **self.config.resolved_env,
170
167
  "VF_PRIME_AGENT_DIR": PRIME_AGENT_DIR,
171
168
  "VF_PRIME_AGENT_GITHUB_RELEASE_URL": GITHUB_RELEASE_URL,
172
169
  "PRIME_AGENT_COMMIT": self.config.commit,
173
170
  "PRIME_AGENT_RELEASE_VERSION": PRIME_AGENT_VERSION,
174
171
  },
172
+ label="prime-agent",
175
173
  )
176
- if result.exit_code != 0:
177
- raise RuntimeError(
178
- f"prime-agent install failed: {result.stderr.strip()[-500:]}"
179
- )
180
174
  await super().setup(runtime)
181
175
 
182
176
  async def prepare_acp(
@@ -285,11 +279,7 @@ class PrimeAgentHarness(ACPHarness[PrimeAgentHarnessConfig]):
285
279
 
286
280
  async def cleanup(self, trace: Trace, runtime: Runtime) -> None:
287
281
  root = self._root(trace)
288
- removed = await runtime.run(["rm", "-rf", root], {})
289
- if removed.exit_code != 0:
290
- raise RuntimeError(
291
- f"prime-agent state cleanup failed: {removed.stderr.strip()[-500:]}"
292
- )
282
+ await remove_dir(runtime, root, "prime-agent state")
293
283
 
294
284
  def _bin(self) -> str:
295
285
  return f"{PRIME_AGENT_DIR}/{self.config.commit}/bin/prime-agent"
@@ -18,6 +18,7 @@ from pydantic_config import BaseConfig
18
18
  from verifiers.v1.acp import ACPConfig, ACPHarness, ACPTurn, JsonObject
19
19
  from verifiers.v1.clients import ModelContext
20
20
  from verifiers.v1.configs.harness import HarnessConfig
21
+ from verifiers.v1.harnesses.utils.install import ensure_installed
21
22
  from verifiers.v1.runtimes import Runtime
22
23
  from verifiers.v1.task import TaskData
23
24
  from verifiers.v1.trace import Trace
@@ -130,16 +131,17 @@ class RLMHarness(ACPHarness[RLMHarnessConfig]):
130
131
  f"touch {ready})"
131
132
  )
132
133
  logger.info("rlm: ensuring rlm is installed (version=%s)", self.config.version)
133
- ensure = shlex.quote(f"[ -f {ready} ] && [ -x {binary} ] || ({install})")
134
- guarded = (
135
- f"mkdir -p {directory} && flock {directory}/install.lock sh -c {ensure}"
136
- )
137
134
  env = self.config.resolved_env.copy()
138
135
  extra_uv_args = env.get("RLM_EXTRA_UV_ARGS", "")
139
136
  env["RLM_EXTRA_UV_ARGS"] = f"{extra_uv_args} --with mcp~=1.28".strip()
140
- result = await runtime.run(["sh", "-c", guarded], env)
141
- if result.exit_code != 0:
142
- raise RuntimeError(f"rlm install failed: {result.stderr.strip()[-500:]}")
137
+ await ensure_installed(
138
+ runtime,
139
+ directory=directory,
140
+ ready=f"[ -f {ready} ] && [ -x {binary} ]",
141
+ install=install,
142
+ env=env,
143
+ label="rlm",
144
+ )
143
145
  await super().setup(runtime)
144
146
 
145
147
  def _runtime_metadata(
@@ -1,10 +1,8 @@
1
1
  import logging
2
2
  from pathlib import Path
3
3
 
4
- from pydantic import Field
5
-
6
4
  from verifiers.v1.clients import ModelContext
7
- from verifiers.v1.configs.harness import HarnessConfig
5
+ from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
8
6
  from verifiers.v1.harness import Harness
9
7
  from verifiers.v1.runtimes import ProgramResult, Runtime
10
8
  from verifiers.v1.task import TaskData
@@ -15,7 +13,7 @@ logger = logging.getLogger(__name__)
15
13
 
16
14
 
17
15
  class Terminus2HarnessConfig(HarnessConfig):
18
- version: str = Field(default="0.21.0", pattern=r"^[A-Za-z0-9._+-]+$")
16
+ version: PinnedVersion = "0.21.0"
19
17
  """Harbor release to install, pinned for reproducibility."""
20
18
 
21
19