verifiers 0.4.1.dev14__tar.gz → 0.4.1.dev19__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 (265) hide show
  1. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/PKG-INFO +1 -1
  2. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/grid.py +3 -3
  3. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_agentic_judge.py +5 -5
  4. verifiers-0.4.1.dev19/tests/integration/test_compose_scoring.py +169 -0
  5. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/test_agent.py +1 -0
  6. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/utils/test_loaders.py +1 -3
  7. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/__init__.py +18 -0
  8. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/agent.py +58 -8
  9. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/debug.py +8 -7
  10. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/validate.py +6 -5
  11. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/agent.py +27 -3
  12. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/retries.py +2 -2
  13. verifiers-0.4.1.dev19/verifiers/v1/configs/scoring.py +55 -0
  14. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/envs/agentic_judge/__init__.py +2 -2
  15. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/envs/agentic_judge/env.py +70 -75
  16. verifiers-0.4.1.dev19/verifiers/v1/grading.py +205 -0
  17. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harness.py +7 -3
  18. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/rlm/harness.py +1 -1
  19. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/interception/__init__.py +1 -1
  20. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/mcp/launch.py +23 -14
  21. verifiers-0.4.1.dev19/verifiers/v1/rollout.py +897 -0
  22. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/__init__.py +50 -36
  23. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/apptainer.py +5 -3
  24. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/base.py +49 -162
  25. {verifiers-0.4.1.dev14/verifiers/v1/tasksets/harbor → verifiers-0.4.1.dev19/verifiers/v1/runtimes}/compose.py +120 -74
  26. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/container.py +69 -53
  27. verifiers-0.4.1.dev19/verifiers/v1/runtimes/deployment.py +202 -0
  28. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/docker/__init__.py +58 -51
  29. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/docker/egress.py +3 -3
  30. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/e2b.py +37 -27
  31. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/modal.py +24 -17
  32. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/prime.py +29 -22
  33. verifiers-0.4.1.dev19/verifiers/v1/runtimes/runtime.py +223 -0
  34. verifiers-0.4.1.dev19/verifiers/v1/runtimes/strategies.py +64 -0
  35. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/subprocess.py +22 -13
  36. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/serve/client.py +24 -18
  37. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/task.py +54 -11
  38. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/harbor/__init__.py +0 -3
  39. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/harbor/taskset.py +76 -24
  40. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/nemo_gym/taskset.py +4 -4
  41. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/artifacts.py +3 -1
  42. verifiers-0.4.1.dev19/verifiers/v1/utils/env.py +31 -0
  43. verifiers-0.4.1.dev14/verifiers/v1/envs/isolated_verifier/__init__.py +0 -7
  44. verifiers-0.4.1.dev14/verifiers/v1/envs/isolated_verifier/env.py +0 -182
  45. verifiers-0.4.1.dev14/verifiers/v1/envs/shared_agentic_judge/__init__.py +0 -6
  46. verifiers-0.4.1.dev14/verifiers/v1/rollout.py +0 -667
  47. verifiers-0.4.1.dev14/verifiers/v1/tasksets/harbor/env.py +0 -138
  48. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/.gitignore +0 -0
  49. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/LICENSE +0 -0
  50. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/README.md +0 -0
  51. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/pyproject.toml +0 -0
  52. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/conftest.py +0 -0
  53. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/agent_user_harness_v1.py +0 -0
  54. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/agent_user_v1.py +0 -0
  55. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/counter_tool_v1.py +0 -0
  56. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/duet_v1.py +0 -0
  57. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/echo_acp_resume_v1.py +0 -0
  58. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/echo_agentic_v1.py +0 -0
  59. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/echo_tool_v1.py +0 -0
  60. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/echo_user_sim_v1.py +0 -0
  61. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/echo_v1.py +0 -0
  62. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/network_policy_v1.py +0 -0
  63. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/pyproject.toml +0 -0
  64. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/skill_codeword_v1.py +0 -0
  65. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/skills/project-codeword/SKILL.md +0 -0
  66. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/fixtures/tool_response_image_v1.py +0 -0
  67. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_agent_user.py +0 -0
  68. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_examples.py +0 -0
  69. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_limits.py +0 -0
  70. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_multi_agent.py +0 -0
  71. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_multi_turn.py +0 -0
  72. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_multi_turn_tool.py +0 -0
  73. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_multimodal_tool.py +0 -0
  74. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_network_policy.py +0 -0
  75. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_resume_tool.py +0 -0
  76. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_rubric_judge.py +0 -0
  77. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_shared_tool.py +0 -0
  78. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_single_turn.py +0 -0
  79. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_skills.py +0 -0
  80. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_stateful_tool.py +0 -0
  81. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_user_echo.py +0 -0
  82. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/integration/test_user_sim.py +0 -0
  83. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/cli/test_replay.py +0 -0
  84. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/conftest.py +0 -0
  85. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/harnesses/test_core.py +0 -0
  86. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/harnesses/test_rlm.py +0 -0
  87. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/interception/test_tunnel.py +0 -0
  88. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/judges/conftest.py +0 -0
  89. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/judges/test_judge.py +0 -0
  90. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/judges/test_reference.py +0 -0
  91. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/judges/test_rubric.py +0 -0
  92. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/runtimes/test_e2b.py +0 -0
  93. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/serve/test_client.py +0 -0
  94. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/serve/test_delta.py +0 -0
  95. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/serve/test_pool.py +0 -0
  96. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/test_graph.py +0 -0
  97. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/test_semantic.py +0 -0
  98. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/test_task.py +0 -0
  99. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/test_taskset.py +0 -0
  100. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/test_trace.py +0 -0
  101. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/utils/test_compile.py +0 -0
  102. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/utils/test_platform.py +0 -0
  103. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/tests/unit/utils/test_score.py +0 -0
  104. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/__init__.py +0 -0
  105. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/acp/__init__.py +0 -0
  106. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/acp/runner.py +0 -0
  107. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/__init__.py +0 -0
  108. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/dashboard/__init__.py +0 -0
  109. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/dashboard/base.py +0 -0
  110. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/dashboard/eval.py +0 -0
  111. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/dashboard/replay.py +0 -0
  112. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/dashboard/validate.py +0 -0
  113. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/eval/__init__.py +0 -0
  114. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/eval/hint.py +0 -0
  115. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/eval/main.py +0 -0
  116. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/eval/resume.py +0 -0
  117. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/eval/runner.py +0 -0
  118. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/gepa.py +0 -0
  119. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/output.py +0 -0
  120. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/replay.py +0 -0
  121. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/resolve.py +0 -0
  122. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/cli/resume.py +0 -0
  123. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/clients/__init__.py +0 -0
  124. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/clients/base.py +0 -0
  125. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/clients/client.py +0 -0
  126. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/clients/eval.py +0 -0
  127. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/clients/train.py +0 -0
  128. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/__init__.py +0 -0
  129. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/cli/__init__.py +0 -0
  130. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/cli/debug.py +0 -0
  131. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/cli/env.py +0 -0
  132. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/cli/eval.py +0 -0
  133. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/cli/replay.py +0 -0
  134. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/cli/validate.py +0 -0
  135. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/client.py +0 -0
  136. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/env.py +0 -0
  137. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/harness.py +0 -0
  138. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/judge.py +0 -0
  139. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/runtime.py +0 -0
  140. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/select.py +0 -0
  141. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/serve.py +0 -0
  142. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/task.py +0 -0
  143. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/configs/taskset.py +0 -0
  144. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/dialects/__init__.py +0 -0
  145. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/dialects/anthropic.py +0 -0
  146. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/dialects/base.py +0 -0
  147. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/dialects/chat.py +0 -0
  148. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/dialects/responses.py +0 -0
  149. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/env.py +0 -0
  150. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/envs/__init__.py +0 -0
  151. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
  152. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/envs/best_of_n/env.py +0 -0
  153. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/envs/single_agent/__init__.py +0 -0
  154. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/envs/single_agent/env.py +0 -0
  155. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/envs/user_sim/__init__.py +0 -0
  156. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/envs/user_sim/env.py +0 -0
  157. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/episode.py +0 -0
  158. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/errors.py +0 -0
  159. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/gepa/__init__.py +0 -0
  160. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/gepa/adapter.py +0 -0
  161. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/gepa/config.py +0 -0
  162. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/gepa/dataset.py +0 -0
  163. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/gepa/reflection.py +0 -0
  164. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/gepa/runner.py +0 -0
  165. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/graph.py +0 -0
  166. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/__init__.py +0 -0
  167. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/bash/__init__.py +0 -0
  168. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/bash/harness.py +0 -0
  169. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
  170. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
  171. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/browser_use/program.py +0 -0
  172. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
  173. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
  174. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/codex/__init__.py +0 -0
  175. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
  176. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/codex/harness.py +0 -0
  177. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
  178. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
  179. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
  180. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
  181. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
  182. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
  183. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
  184. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
  185. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/node.py +0 -0
  186. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/null/__init__.py +0 -0
  187. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/null/harness.py +0 -0
  188. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
  189. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
  190. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/pi/__init__.py +0 -0
  191. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
  192. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/pi/harness.py +0 -0
  193. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
  194. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
  195. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
  196. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
  197. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
  198. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
  199. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/utils/__init__.py +0 -0
  200. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/utils/compaction.py +0 -0
  201. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/utils/core.py +0 -0
  202. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/utils/install.py +0 -0
  203. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/utils/launch.py +0 -0
  204. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/harnesses/utils/mcp.py +0 -0
  205. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/interception/base.py +0 -0
  206. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/interception/pool.py +0 -0
  207. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/interception/server.py +0 -0
  208. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/interception/tunnel/__init__.py +0 -0
  209. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/interception/tunnel/base.py +0 -0
  210. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/interception/tunnel/custom.py +0 -0
  211. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/interception/tunnel/prime.py +0 -0
  212. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/judge.py +0 -0
  213. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/judges/__init__.py +0 -0
  214. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/judges/decision.py +0 -0
  215. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/judges/reference.py +0 -0
  216. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/judges/reference.txt +0 -0
  217. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/judges/rubric.py +0 -0
  218. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/judges/rubric.txt +0 -0
  219. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/mcp/__init__.py +0 -0
  220. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/mcp/server.py +0 -0
  221. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/mcp/toolset.py +0 -0
  222. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/runtimes/limiters.py +0 -0
  223. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/semantic.py +0 -0
  224. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/serve/__init__.py +0 -0
  225. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/serve/delta.py +0 -0
  226. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/serve/encoding.py +0 -0
  227. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/serve/pool.py +0 -0
  228. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/serve/server.py +0 -0
  229. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/serve/types.py +0 -0
  230. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/session.py +0 -0
  231. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/state.py +0 -0
  232. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/taskset.py +0 -0
  233. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/__init__.py +0 -0
  234. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
  235. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
  236. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
  237. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
  238. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
  239. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
  240. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
  241. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
  242. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
  243. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/trace.py +0 -0
  244. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/types.py +0 -0
  245. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/__init__.py +0 -0
  246. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/aio.py +0 -0
  247. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/compile.py +0 -0
  248. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/decorators.py +0 -0
  249. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/eval.py +0 -0
  250. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/format.py +0 -0
  251. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/generic.py +0 -0
  252. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/git.py +0 -0
  253. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/image.py +0 -0
  254. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/interrupt.py +0 -0
  255. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/loaders.py +0 -0
  256. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/logging.py +0 -0
  257. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/memory.py +0 -0
  258. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/paths.py +0 -0
  259. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/platform.py +0 -0
  260. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/prime.py +0 -0
  261. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/retries.py +0 -0
  262. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/scope.py +0 -0
  263. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/score.py +0 -0
  264. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/trace_store.py +0 -0
  265. {verifiers-0.4.1.dev14 → verifiers-0.4.1.dev19}/verifiers/v1/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: verifiers
3
- Version: 0.4.1.dev14
3
+ Version: 0.4.1.dev19
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
@@ -12,7 +12,7 @@ capability the code declares, never from a list of names, so the grid follows th
12
12
  - `Harness.EXECUTES_CODE`, `SUPPORTS_MCP`, `SUPPORTS_SKILLS`, resume support
13
13
  (`SUPPORTS_RESUME` or a native session): the behavior needs a shell, MCP tools,
14
14
  skills, or a resumable exchange
15
- - `Runtime.supports_user`, `Runtime.supports_expose`, `NetworkPolicyConfig`: the
15
+ - `RuntimeBackend.supports_user`, `RuntimeBackend.supports_expose`, `NetworkPolicyConfig`: the
16
16
  behavior needs a user switch, a tool server reachable from another runtime, or a
17
17
  network policy
18
18
  - `podman` / `apptainer` need their engine on the host
@@ -39,7 +39,7 @@ from pydantic import TypeAdapter
39
39
  import verifiers.v1 as vf
40
40
  from verifiers.v1.configs.runtime import NetworkPolicyConfig
41
41
  from verifiers.v1.harness import Harness
42
- from verifiers.v1.runtimes import RuntimeConfig, _runtime_cls
42
+ from verifiers.v1.runtimes import RuntimeConfig, _backend_cls
43
43
  from verifiers.v1.utils.loaders import harness_class
44
44
 
45
45
  HARNESSES: list[str | dict] = [
@@ -92,7 +92,7 @@ def runtime_config(runtime: str, harness: str | dict | None = None) -> dict:
92
92
 
93
93
 
94
94
  def runtime_cls(runtime: str) -> type:
95
- return _runtime_cls(TypeAdapter(RuntimeConfig).validate_python({"type": runtime}))
95
+ return _backend_cls(TypeAdapter(RuntimeConfig).validate_python({"type": runtime}))
96
96
 
97
97
 
98
98
  def runtime_supports_user(runtime: str) -> bool:
@@ -1,9 +1,7 @@
1
- """The agentic judge envs verify a solver empirically in a sandbox: `shared-agentic-judge`
2
- reuses the solver's restricted box, `agentic-judge` restores the solver's artifact in a
3
- fresh box."""
1
+ """Agentic judging uses shared or isolated scoring to verify a solver in a sandbox."""
4
2
 
5
3
 
6
- async def test_env_id_shared_agentic_judge(run, tmp_path):
4
+ async def test_agentic_judge_shared_verifier(run, tmp_path):
7
5
  """The shared agentic judge provisions one restricted solver-owned box and
8
6
  safely reuses it for the judge's empirical verification."""
9
7
  policy = tmp_path / "judge_policy.txt"
@@ -12,10 +10,11 @@ async def test_env_id_shared_agentic_judge(run, tmp_path):
12
10
  "echo-v1",
13
11
  harness=None,
14
12
  env={
15
- "id": "shared-agentic-judge",
13
+ "id": "agentic-judge",
16
14
  "solver": {
17
15
  "harness": {"id": "bash"},
18
16
  "runtime": {"type": "docker", "block": ["example.com"]},
17
+ "scoring": {"mode": "shared"},
19
18
  },
20
19
  "judge": {
21
20
  "harness": {"id": "bash"},
@@ -60,6 +59,7 @@ async def test_env_id_agentic_judge(run, tmp_path):
60
59
  "solver": {
61
60
  "harness": {"id": "bash"},
62
61
  "runtime": {"type": "docker", "block": ["example.com"]},
62
+ "scoring": {"mode": "isolated"},
63
63
  },
64
64
  "judge": {
65
65
  "harness": {"id": "bash"},
@@ -0,0 +1,169 @@
1
+ """Compose scoring uses live shared services or a released, collected submission."""
2
+
3
+ import shutil
4
+
5
+ import pytest
6
+
7
+ import verifiers.v1 as vf
8
+ from verifiers.v1.configs.agent import TimeoutConfig
9
+ from verifiers.v1.runtimes.container import cli
10
+ from verifiers.v1.tasksets.harbor.taskset import (
11
+ CollectHook,
12
+ HarborArtifact,
13
+ HarborData,
14
+ HarborTask,
15
+ )
16
+
17
+ pytestmark = [
18
+ pytest.mark.docker,
19
+ pytest.mark.skipif(not shutil.which("docker"), reason="needs Docker"),
20
+ ]
21
+
22
+ IMAGE = "python:3.11-slim"
23
+ COMPOSE = f"""
24
+ services:
25
+ main:
26
+ image: {IMAGE}
27
+ working_dir: /app
28
+ command: [sleep, infinity]
29
+ depends_on:
30
+ sidecar:
31
+ condition: service_healthy
32
+ sidecar:
33
+ environment:
34
+ COLLECTION_SCOPE: sidecar
35
+ image: {IMAGE}
36
+ command: [sh, -c, "mkdir -p /srv /evidence; echo 42 > /srv/answer; cd /srv; exec python -m http.server 8000"]
37
+ healthcheck:
38
+ test: [CMD, python, -c, "import urllib.request; urllib.request.urlopen('http://localhost:8000/answer')"]
39
+ interval: 1s
40
+ timeout: 2s
41
+ retries: 30
42
+ """
43
+
44
+
45
+ class ComposeHarness(vf.Harness):
46
+ async def launch(self, ctx, trace, runtime, endpoint, secret, mcp_urls, data):
47
+ return await runtime.run_program(
48
+ [
49
+ "python",
50
+ "-c",
51
+ (
52
+ "import urllib.request; "
53
+ "open('/app/answer', 'wb').write(urllib.request.urlopen('http://sidecar:8000/answer').read())"
54
+ ),
55
+ ],
56
+ {},
57
+ )
58
+
59
+
60
+ class ComposeTask(HarborTask):
61
+ async def setup(self, trace, runtime, deployment=None):
62
+ await super().setup(runtime)
63
+ if deployment is not None:
64
+ trace.info["solver_containers"] = [
65
+ runtime.info.id for runtime in deployment.target_backends.values()
66
+ ]
67
+ else:
68
+ # Fresh verifier setup happens only after the solver project is removed.
69
+ for container in trace.info["solver_containers"]:
70
+ result = await cli("docker", "inspect", container)
71
+ assert result.exit_code != 0, "solver service survived into grading"
72
+ trace.info["solver_released_before_grading"] = True
73
+
74
+ async def finalize_services(self, trace, targets):
75
+ result = await cli(
76
+ "docker",
77
+ "inspect",
78
+ "--format",
79
+ "{{.State.Running}}",
80
+ targets["main"].info.id,
81
+ )
82
+ assert result.stdout.strip() == "false", (
83
+ "workspace must stop before sidecar collection"
84
+ )
85
+ trace.info["collected_sidecars"] = True
86
+ await super().finalize_services(trace, targets)
87
+
88
+
89
+ @pytest.mark.parametrize(
90
+ ("mode", "collect_fails", "scoring_timeout"),
91
+ [
92
+ ("shared", True, False),
93
+ ("isolated", False, False),
94
+ ("isolated", True, False),
95
+ ("isolated", False, True),
96
+ ],
97
+ ids=[
98
+ "shared-skips-sidecars",
99
+ "isolated-restores-sidecars",
100
+ "isolated-collect-failure",
101
+ "isolated-scoring-timeout",
102
+ ],
103
+ )
104
+ async def test_compose_scoring(tmp_path, mode, collect_fails, scoring_timeout):
105
+ environment = tmp_path / "environment"
106
+ environment.mkdir()
107
+ (environment / "docker-compose.yaml").write_text(COMPOSE)
108
+ tests = tmp_path / "tests"
109
+ tests.mkdir()
110
+ (tests / "test.sh").write_text(
111
+ "set -eu\n"
112
+ 'test "$(cat /app/answer)" = 42\n'
113
+ 'if [ "$EXPECT_SIDECAR" = 1 ]; then test "$(cat /evidence/result)" = 42; fi\n'
114
+ + ("sleep 30\n" if scoring_timeout else "")
115
+ + "echo 1 > /logs/verifier/reward.txt\n"
116
+ )
117
+ task = ComposeTask(
118
+ HarborData(
119
+ prompt="Copy the sidecar answer",
120
+ task_dir=str(tmp_path),
121
+ env={"COLLECTION_SCOPE": "workspace"},
122
+ # Exercise agent overrides in both directions, not just task defaults.
123
+ scoring=vf.ScoringConfig(mode="isolated" if mode == "shared" else "shared"),
124
+ artifacts=[
125
+ HarborArtifact(source="/app/answer"),
126
+ HarborArtifact(source="/evidence/result", service="sidecar"),
127
+ ],
128
+ collect=[
129
+ CollectHook(
130
+ service="sidecar",
131
+ command="exit 17"
132
+ if collect_fails
133
+ else 'test "$COLLECTION_SCOPE" = sidecar && cp /srv/answer /evidence/result',
134
+ )
135
+ ],
136
+ )
137
+ )
138
+ config = vf.AgentConfig(
139
+ model="unused",
140
+ runtime=vf.DockerConfig(),
141
+ deployment=vf.DeploymentConfig(trust_compose=True),
142
+ scoring=vf.ScoringConfig(
143
+ mode=mode,
144
+ env={"EXPECT_SIDECAR": "1" if mode == "isolated" else "0"},
145
+ retries=vf.RetryConfig(max_retries=0),
146
+ ),
147
+ timeout=TimeoutConfig(
148
+ setup=180, finalize=30, scoring=1 if scoring_timeout else 30
149
+ ),
150
+ )
151
+ async with vf.Agent(config) as agent:
152
+ agent.harness = ComposeHarness(vf.HarnessConfig())
153
+ trace = await agent.run(task)
154
+ for container in trace.info.get("solver_containers", []):
155
+ assert (await cli("docker", "inspect", container)).exit_code != 0
156
+ if mode == "isolated" and collect_fails:
157
+ assert not trace.ok
158
+ assert "collect hook failed" in str(trace.errors)
159
+ assert "solver_released_before_grading" not in trace.info
160
+ elif scoring_timeout:
161
+ assert trace.ok and trace.is_timeout and not trace.errors
162
+ assert trace.stop_condition == "scoring_timeout"
163
+ assert all(reward is None for reward in trace.rewards.values())
164
+ else:
165
+ assert trace.ok and trace.reward == 1, trace.errors
166
+ assert bool(trace.info.get("collected_sidecars")) == (mode == "isolated")
167
+ assert bool(trace.info.get("solver_released_before_grading")) == (
168
+ mode == "isolated"
169
+ )
@@ -53,6 +53,7 @@ async def test_failed_segment_does_not_reuse_prior_root_reply():
53
53
  run._agent_time_remaining = None
54
54
  run._timeouts = RolloutTimeouts()
55
55
  run._harness_session = FailingSession()
56
+ run.deployment = SimpleNamespace(run=lambda turn: turn)
56
57
  run._session = SimpleNamespace(
57
58
  request_interceptors=[],
58
59
  error=None,
@@ -40,9 +40,7 @@ def test_unknown_harness_names_the_builtins() -> None:
40
40
  harness_class("no-such-harness")
41
41
 
42
42
 
43
- @pytest.mark.parametrize(
44
- "env_id", ["best-of-n", "user-sim", "agentic-judge", "shared-agentic-judge"]
45
- )
43
+ @pytest.mark.parametrize("env_id", ["best-of-n", "user-sim", "agentic-judge"])
46
44
  def test_bundled_envs_load_with_a_role_typed_config(env_id: str) -> None:
47
45
  cls = environment_class("", env_id)
48
46
  assert issubclass(cls, vf.Env)
@@ -61,6 +61,7 @@ from verifiers.v1.errors import (
61
61
  ToolsetError,
62
62
  TunnelError,
63
63
  )
64
+ from verifiers.v1.grading import grade_submission
64
65
  from verifiers.v1.graph import MessageNode
65
66
  from verifiers.v1.harness import Harness, HarnessSession
66
67
  from verifiers.v1.judge import Judge, JudgeResponse, JudgeView
@@ -371,6 +372,7 @@ __all__ = [ # noqa: RUF022 - grouped by public API area
371
372
  "PATCH_CAP_BYTES",
372
373
  "capture_patch",
373
374
  "resolve_head",
375
+ "grade_submission",
374
376
  # grading artifacts
375
377
  "ARTIFACTS_DIR",
376
378
  "Artifact",
@@ -396,3 +398,19 @@ __all__ = [ # noqa: RUF022 - grouped by public API area
396
398
  # silent until an app opts in: a NullHandler on the package root absorbs records
397
399
  # so nothing is emitted (and no "no handler" warning) unless handlers are added.
398
400
  _logging.getLogger(__name__).addHandler(_logging.NullHandler())
401
+
402
+ from verifiers.v1.runtimes.compose import ComposeSpec
403
+ from verifiers.v1.runtimes.deployment import (
404
+ Deployment,
405
+ DeploymentConfig,
406
+ )
407
+
408
+ __all__ += [
409
+ "ComposeSpec",
410
+ "Deployment",
411
+ "DeploymentConfig",
412
+ ]
413
+
414
+ from verifiers.v1.configs.scoring import ScoringConfig
415
+
416
+ __all__ += ["ScoringConfig"]
@@ -9,8 +9,9 @@ server; un-entered, each run brings its own."""
9
9
 
10
10
  import asyncio
11
11
  import logging
12
- from collections.abc import AsyncIterator, Callable, Mapping
12
+ from collections.abc import AsyncIterator, Awaitable, Callable, Mapping
13
13
  from contextlib import asynccontextmanager, nullcontext
14
+ from contextvars import ContextVar
14
15
  from dataclasses import dataclass, field, replace
15
16
  from typing import Generic, Literal, Self, cast
16
17
  from weakref import WeakValueDictionary
@@ -37,7 +38,7 @@ from verifiers.v1.runtimes import (
37
38
  Runtime,
38
39
  RuntimeConfig,
39
40
  SubprocessConfig,
40
- provision_runtime,
41
+ provision_backend,
41
42
  runtime_is_local,
42
43
  )
43
44
  from verifiers.v1.session import RolloutLimits
@@ -61,6 +62,11 @@ __all__ = ["Agent", "AgentConfig", "Agents", "TimeoutConfig", "make_agent"]
61
62
 
62
63
  logger = logging.getLogger(__name__)
63
64
 
65
+ # Only nested runs in this scoring attempt participate in its rollback.
66
+ _scoring_runs: ContextVar[list[tuple["_EpisodeAgent", Trace]] | None] = ContextVar(
67
+ "scoring_runs", default=None
68
+ )
69
+
64
70
 
65
71
  def resolve_rollout_timeouts(timeout: TimeoutConfig, task: Task) -> RolloutTimeouts:
66
72
  """Apply an agent's stage-timeout precedence to one task."""
@@ -657,6 +663,7 @@ class Agent:
657
663
  tools: Mapping[str, SharedToolServer] | None = None,
658
664
  on_trace: Callable[[Trace], None] | None = None,
659
665
  collect_artifacts: bool = False,
666
+ on_score: Callable[[Trace, Runtime], Awaitable[None]] | None = None,
660
667
  ) -> Trace:
661
668
  """Run this agent on `task` once and return the trace: one segment — the
662
669
  program runs on the task's prompt until it exits (a multi-turn exchange
@@ -667,7 +674,8 @@ class Agent:
667
674
  declared artifacts after its finalizer while its container runtime is still
668
675
  alive. Retries whole while the trace ends with a retryable error
669
676
  (`config.retries`) — never into a borrowed box; the final trace keeps earlier
670
- attempts' errors."""
677
+ attempts' errors. `on_score(trace, runtime)` runs after task scoring in
678
+ the selected verifier workspace, inside its timeout and retry boundary."""
671
679
  if self._closed:
672
680
  raise RuntimeError("Agent is closed; create a new agent")
673
681
  retry = self.config.retries
@@ -675,7 +683,7 @@ class Agent:
675
683
  history: list = []
676
684
  for attempt in range(retry_state.max_retries + 1):
677
685
  trace = await self._run_once(
678
- task, runtime, tools, on_trace, collect_artifacts
686
+ task, runtime, tools, on_trace, collect_artifacts, on_score
679
687
  )
680
688
  if attempt == retry_state.max_retries or trace.ok:
681
689
  break
@@ -711,6 +719,7 @@ class Agent:
711
719
  shared_tools: Mapping[str, SharedToolServer] | None,
712
720
  on_trace: Callable[[Trace], None] | None,
713
721
  collect_artifacts: bool,
722
+ on_score: Callable[[Trace, Runtime], Awaitable[None]] | None,
714
723
  ) -> Trace:
715
724
  params = self._rollout_params(task, runtime, dict(shared_tools or {}))
716
725
  if collect_artifacts and isinstance(params["runtime_config"], SubprocessConfig):
@@ -722,6 +731,7 @@ class Agent:
722
731
  task=task,
723
732
  on_trace=on_trace,
724
733
  collect_artifacts=collect_artifacts,
734
+ on_score=on_score,
725
735
  **params,
726
736
  )
727
737
  try:
@@ -850,16 +860,16 @@ class Agent:
850
860
  @asynccontextmanager
851
861
  async def provision(self, task: Task | None = None) -> AsyncIterator[Runtime]:
852
862
  """Provision (and on exit tear down) a box from this agent's runtime
853
- policy, resolved for `task` when given; share it via `run(..., runtime=box)`."""
863
+ policy, resolved for `task` when given; share it via `run(..., runtime=runtime)`."""
854
864
  config = (
855
865
  resolve_runtime_config(self.runtime_config, task, self._warned_resources)
856
866
  if task is not None
857
867
  else self.runtime_config
858
868
  )
859
- async with provision_runtime(config) as runtime:
869
+ async with provision_backend(config) as backend:
860
870
  # Keep sandbox startup task-neutral: this box may later host another task.
861
- runtime.env = dict(task.runtime_env()) if task is not None else {}
862
- yield runtime
871
+ backend.env = dict(task.runtime_env()) if task is not None else {}
872
+ yield backend.bind()
863
873
 
864
874
 
865
875
  class _EpisodeAgent(Agent):
@@ -914,6 +924,8 @@ class _EpisodeAgent(Agent):
914
924
  if last is not None and self._on_discard is not None:
915
925
  self._on_discard(last)
916
926
  last = trace
927
+ if (runs := _scoring_runs.get()) is not None:
928
+ runs.append((self, trace))
917
929
  if self._on_trace is not None:
918
930
  self._on_trace(trace)
919
931
  if on_trace is not None:
@@ -921,6 +933,42 @@ class _EpisodeAgent(Agent):
921
933
 
922
934
  return watch
923
935
 
936
+ def _scoring_callback(self, callback):
937
+ if callback is None:
938
+ return None
939
+
940
+ async def score(trace, runtime):
941
+ parent_runs = _scoring_runs.get()
942
+ runs = []
943
+ token = _scoring_runs.set(runs)
944
+ # The solver is idle while an Env runs a judge. Release its permit
945
+ # so a one-agent episode can enter the nested judge rollout.
946
+ if self._gate is not None:
947
+ self._gate.release()
948
+ try:
949
+ try:
950
+ await callback(trace, runtime)
951
+ finally:
952
+ _scoring_runs.reset(token)
953
+ if self._gate is not None:
954
+ await run_shielded(self._gate.acquire())
955
+ except BaseException:
956
+ for agent, child in runs:
957
+ agent._completed[:] = [
958
+ t for t in agent._completed if t is not child
959
+ ]
960
+ if agent._on_discard is not None:
961
+ agent._on_discard(child)
962
+ if child.usage is not None:
963
+ trace.extra_usage.append(child.usage)
964
+ trace.extra_usage.extend(child.extra_usage)
965
+ raise
966
+ else:
967
+ if parent_runs is not None:
968
+ parent_runs.extend(runs)
969
+
970
+ return score
971
+
924
972
  async def run(
925
973
  self,
926
974
  task: Task,
@@ -929,6 +977,7 @@ class _EpisodeAgent(Agent):
929
977
  tools: Mapping[str, SharedToolServer] | None = None,
930
978
  on_trace: Callable[[Trace], None] | None = None,
931
979
  collect_artifacts: bool = False,
980
+ on_score: Callable[[Trace, Runtime], Awaitable[None]] | None = None,
932
981
  ) -> Trace:
933
982
  async with self._gate or nullcontext():
934
983
  trace = await super().run(
@@ -937,6 +986,7 @@ class _EpisodeAgent(Agent):
937
986
  tools=tools if tools is not None else self._shared_for(task),
938
987
  on_trace=self._watch(on_trace),
939
988
  collect_artifacts=collect_artifacts,
989
+ on_score=self._scoring_callback(on_score),
940
990
  )
941
991
  self._completed.append(trace)
942
992
  return trace
@@ -26,7 +26,7 @@ from verifiers.v1.cli.resolve import (
26
26
  with_positional_taskset,
27
27
  )
28
28
  from verifiers.v1.configs.cli.debug import DebugConfig
29
- from verifiers.v1.runtimes import ProgramResult, Runtime, make_runtime
29
+ from verifiers.v1.runtimes import ProgramResult, Runtime, make_backend
30
30
  from verifiers.v1.state import state_cls
31
31
  from verifiers.v1.task import Task
32
32
  from verifiers.v1.trace import AgentInfo, Error, Trace, TraceTask
@@ -216,20 +216,21 @@ async def debug_task(task: Task, config: DebugConfig) -> tuple[Trace, bool]:
216
216
  "reason": "not_run",
217
217
  }
218
218
  cancelled = False
219
- runtime = make_runtime(
219
+ backend = make_backend(
220
220
  resolve_runtime_config(config.runtime, task),
221
221
  name=f"debug-{task.data.idx}-{uuid4().hex[:8]}",
222
222
  )
223
- trace.agent.runtime = runtime.info
223
+ trace.agent.runtime = backend.info
224
224
  setup_timeout = (
225
225
  config.timeout.setup
226
226
  if config.timeout.setup is not None
227
227
  else task.data.timeout.setup
228
228
  )
229
229
  try:
230
- runtime.env = dict(task.runtime_env())
230
+ backend.env = dict(task.runtime_env())
231
231
  trace.timing.boot.start = time.time()
232
- await runtime.start()
232
+ await backend.start()
233
+ runtime = backend.bind()
233
234
  now = time.time()
234
235
  trace.timing.boot.end = now
235
236
  trace.timing.setup.start = now
@@ -237,7 +238,7 @@ async def debug_task(task: Task, config: DebugConfig) -> tuple[Trace, bool]:
237
238
  invoke(task.setup, {"trace": trace, "runtime": runtime}),
238
239
  setup_timeout,
239
240
  )
240
- await runtime.prepare_execution([])
241
+ await backend.prepare_execution([])
241
242
  trace.timing.setup.end = time.time()
242
243
 
243
244
  trace.timing.agent.start = time.time()
@@ -256,7 +257,7 @@ async def debug_task(task: Task, config: DebugConfig) -> tuple[Trace, bool]:
256
257
  trace.split_agent_time()
257
258
  trace.info["debug"] = debug
258
259
  try:
259
- await runtime.stop()
260
+ await backend.stop()
260
261
  except asyncio.CancelledError:
261
262
  # a task cancellation delivered mid-stop would abort before the caller can
262
263
  # persist the trace — absorb it here; the caller re-raises after appending
@@ -31,7 +31,7 @@ from verifiers.v1.cli.resolve import (
31
31
  from verifiers.v1.cli.resume import distribute
32
32
  from verifiers.v1.configs.cli.validate import ValidateConfig
33
33
  from verifiers.v1.errors import TaskError, boundary
34
- from verifiers.v1.runtimes import make_runtime
34
+ from verifiers.v1.runtimes import make_backend
35
35
  from verifiers.v1.state import state_cls
36
36
  from verifiers.v1.task import Task
37
37
  from verifiers.v1.trace import Trace, TraceTask
@@ -266,7 +266,7 @@ CHECKS = {"setup": _setup_only, "gold": _gold, "noop": _score_untouched}
266
266
 
267
267
  async def _run_check(task: Task, config: ValidateConfig, mode: str) -> ResultRow:
268
268
  start = time.time()
269
- runtime = make_runtime(
269
+ backend = make_backend(
270
270
  resolve_runtime_config(config.runtime, task),
271
271
  name=f"validate-{mode}-{task.data.idx}-{uuid4().hex[:8]}",
272
272
  )
@@ -279,7 +279,7 @@ async def _run_check(task: Task, config: ValidateConfig, mode: str) -> ResultRow
279
279
  exc = None
280
280
  trace: Trace | None = None
281
281
  try:
282
- runtime.env = dict(task.runtime_env())
282
+ backend.env = dict(task.runtime_env())
283
283
  trace = Trace(
284
284
  task=TraceTask(
285
285
  type=type(task).__name__, data=task.data, key=task.key, hash=task.hash
@@ -292,7 +292,8 @@ async def _run_check(task: Task, config: ValidateConfig, mode: str) -> ResultRow
292
292
  trainable=False,
293
293
  ),
294
294
  )
295
- await runtime.start()
295
+ await backend.start()
296
+ runtime = backend.bind()
296
297
  await asyncio.wait_for(
297
298
  invoke(task.setup, {"trace": trace, "runtime": runtime}),
298
299
  setup_timeout,
@@ -304,7 +305,7 @@ async def _run_check(task: Task, config: ValidateConfig, mode: str) -> ResultRow
304
305
  exc = e
305
306
  finally:
306
307
  try:
307
- await runtime.stop()
308
+ await backend.stop()
308
309
  except Exception:
309
310
  logger.warning(
310
311
  "runtime teardown failed (task %s)", task.data.idx, exc_info=True
@@ -2,13 +2,22 @@
2
2
 
3
3
  from typing import Any
4
4
 
5
- from pydantic import BaseModel, Field, SerializeAsAny, field_serializer, model_validator
5
+ from pydantic import (
6
+ BaseModel,
7
+ Field,
8
+ SerializationInfo,
9
+ SerializeAsAny,
10
+ field_serializer,
11
+ model_validator,
12
+ )
6
13
  from pydantic_config import BaseConfig
7
14
 
8
15
  from verifiers.v1.clients import ClientConfig
9
16
  from verifiers.v1.configs.harness import HarnessConfig, WireHarnessConfig
10
17
  from verifiers.v1.configs.retries import RetryConfig
18
+ from verifiers.v1.configs.scoring import ScoringConfig
11
19
  from verifiers.v1.runtimes import PrimeConfig, RuntimeConfig
20
+ from verifiers.v1.runtimes.deployment import DeploymentConfig
12
21
  from verifiers.v1.types import SamplingConfig
13
22
  from verifiers.v1.utils.generic import merge_defaults
14
23
 
@@ -25,16 +34,23 @@ class TimeoutConfig(BaseConfig):
25
34
  finalize: float | None = Field(None, gt=0)
26
35
  """Timeout (in seconds) for the task + harness finalize hooks."""
27
36
  scoring: float | None = Field(None, gt=0)
28
- """Timeout (in seconds) for the task + harness metrics + scoring hooks."""
37
+ """Combined budget (in seconds) for harness metrics and task scoring, including
38
+ isolated verifier setup and retries. Finalization has its own budget."""
29
39
 
30
40
 
31
41
  class AgentConfig(BaseConfig):
32
42
  harness: SerializeAsAny[HarnessConfig] | None = None
33
43
  """The agent's program (None = the taskset's default harness)."""
34
44
  runtime: RuntimeConfig = PrimeConfig()
35
- """Runtime for the harness program — the policy each run provisions its box
45
+ """Runtime configuration for the harness program — the policy each run provisions its box
36
46
  from; tool servers choose their placement separately."""
37
47
 
48
+ scoring: ScoringConfig = ScoringConfig()
49
+ """Scoring overrides; unset fields inherit the task’s scoring defaults."""
50
+
51
+ deployment: DeploymentConfig = DeploymentConfig()
52
+ """Workspace and service placement, including trust for local Compose tasks."""
53
+
38
54
  model: str | None = None
39
55
  """Model id (None = the run's model, i.e. the policy under evaluation/training)."""
40
56
  client: ClientConfig | None = None
@@ -57,6 +73,14 @@ class AgentConfig(BaseConfig):
57
73
  network_notice: bool = True
58
74
  """Include the runtime's network restrictions in the agent's prompt."""
59
75
 
76
+ @field_serializer("scoring")
77
+ def _scoring_overrides(
78
+ self, scoring: ScoringConfig, info: SerializationInfo
79
+ ) -> dict:
80
+ # Preserve unset fields across env-server and trace roundtrips so they
81
+ # continue to inherit from the task instead of becoming explicit overrides.
82
+ return scoring.model_dump(mode=info.mode, exclude_unset=True)
83
+
60
84
  @field_serializer("sampling")
61
85
  def _sampling_overrides(self, sampling: SamplingConfig | None) -> dict | None:
62
86
  # An unresolved agent carries only overrides across env-server boundaries.
@@ -1,4 +1,4 @@
1
- """Whole-rollout retry rules — each agent's own and the env's episode fallback."""
1
+ """Retry rules shared by episode, agent rollout, and isolated scoring boundaries."""
2
2
 
3
3
  import re
4
4
  from typing import Annotated, Literal
@@ -36,7 +36,7 @@ class RetryRule(BaseConfig):
36
36
 
37
37
 
38
38
  class RetryConfig(BaseConfig):
39
- """Ordered rules for opt-in whole-rollout retries.
39
+ """Ordered rules for retries at the owning config’s execution boundary.
40
40
 
41
41
  Fields within a rule are ANDed. An exhausted rule never falls through to a
42
42
  later rule for that error; another captured error can still trigger a retry.