verifiers 0.4.1.dev51__tar.gz → 0.4.1.dev54__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 (283) hide show
  1. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/PKG-INFO +1 -5
  2. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/pyproject.toml +0 -12
  3. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/conftest.py +5 -5
  4. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/agent_user.py +1 -1
  5. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/grid.py +85 -91
  6. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_agentic_judge.py +3 -3
  7. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_compose_scoring.py +51 -54
  8. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_limits.py +2 -2
  9. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_multi_turn.py +5 -5
  10. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_multi_turn_tool.py +2 -2
  11. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_multimodal_tool.py +1 -1
  12. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_network_policy.py +1 -3
  13. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_rubric_judge.py +1 -1
  14. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_sampling.py +1 -3
  15. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_scoring_network.py +1 -1
  16. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_shared_tool.py +2 -2
  17. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_single_turn.py +2 -2
  18. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_tool_vms.py +1 -1
  19. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/conftest.py +8 -0
  20. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/runtimes/test_private_network.py +4 -4
  21. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/test_agent.py +50 -17
  22. verifiers-0.4.1.dev54/tests/unit/test_runtimes.py +543 -0
  23. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/test_scoring_network.py +1 -1
  24. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/utils/test_compile.py +1 -1
  25. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/__init__.py +4 -4
  26. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/acp/__init__.py +1 -5
  27. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/agent.py +11 -12
  28. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/clients/train.py +8 -0
  29. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/grading.py +6 -3
  30. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/graph.py +41 -14
  31. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/mini_swe_agent/harness.py +1 -1
  32. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/terminus_2/harness.py +1 -1
  33. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/utils/launch.py +1 -1
  34. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/interception/tunnel/prime.py +1 -2
  35. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/mcp/launch.py +22 -6
  36. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/mcp/toolset.py +3 -3
  37. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/rollout.py +9 -6
  38. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/runtimes/__init__.py +32 -56
  39. verifiers-0.4.1.dev54/verifiers/v1/runtimes/backends/custom.py +93 -0
  40. verifiers-0.4.1.dev54/verifiers/v1/runtimes/backends/docker.py +874 -0
  41. {verifiers-0.4.1.dev51/verifiers/v1/runtimes → verifiers-0.4.1.dev54/verifiers/v1/runtimes/backends}/prime.py +13 -16
  42. {verifiers-0.4.1.dev51/verifiers/v1/runtimes → verifiers-0.4.1.dev54/verifiers/v1/runtimes/backends}/subprocess.py +23 -37
  43. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/runtimes/base.py +87 -63
  44. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/runtimes/compose.py +53 -56
  45. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/runtimes/deployment.py +1 -3
  46. {verifiers-0.4.1.dev51/verifiers/v1/runtimes/docker → verifiers-0.4.1.dev54/verifiers/v1/runtimes}/egress.py +0 -25
  47. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/runtimes/limiters.py +2 -2
  48. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/runtimes/private_network.py +1 -1
  49. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/runtimes/runtime.py +21 -26
  50. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/runtimes/strategies.py +6 -4
  51. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/task.py +1 -1
  52. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/trace.py +20 -0
  53. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/types.py +39 -0
  54. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/compile.py +22 -35
  55. verifiers-0.4.1.dev51/tests/unit/runtimes/test_e2b.py +0 -79
  56. verifiers-0.4.1.dev51/verifiers/v1/runtimes/apptainer.py +0 -216
  57. verifiers-0.4.1.dev51/verifiers/v1/runtimes/container.py +0 -336
  58. verifiers-0.4.1.dev51/verifiers/v1/runtimes/docker/__init__.py +0 -589
  59. verifiers-0.4.1.dev51/verifiers/v1/runtimes/e2b.py +0 -724
  60. verifiers-0.4.1.dev51/verifiers/v1/runtimes/modal.py +0 -443
  61. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/.gitignore +0 -0
  62. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/LICENSE +0 -0
  63. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/README.md +0 -0
  64. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/agent_user_harness.py +0 -0
  65. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/counter_tool.py +0 -0
  66. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/duet.py +0 -0
  67. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/echo.py +0 -0
  68. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/echo_acp_resume.py +0 -0
  69. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/echo_agentic.py +0 -0
  70. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/echo_tool.py +0 -0
  71. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/echo_tool_compose/docker-compose.yaml +0 -0
  72. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/echo_user_sim.py +0 -0
  73. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/fetch_tool.py +0 -0
  74. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/network_policy.py +0 -0
  75. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/parallel.py +0 -0
  76. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/pyproject.toml +0 -0
  77. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/skill_codeword.py +0 -0
  78. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/skills/project-codeword/SKILL.md +0 -0
  79. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/fixtures/tool_response_image.py +0 -0
  80. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_agent_user.py +0 -0
  81. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_examples.py +0 -0
  82. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_multi_agent.py +0 -0
  83. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_parallel.py +0 -0
  84. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_resume_tool.py +0 -0
  85. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_skills.py +0 -0
  86. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_stateful_tool.py +0 -0
  87. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_user_echo.py +0 -0
  88. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/integration/test_user_sim.py +0 -0
  89. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/cli/test_replay.py +0 -0
  90. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/harnesses/test_core.py +0 -0
  91. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/harnesses/test_rlm.py +0 -0
  92. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/interception/test_tunnel.py +0 -0
  93. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/judges/conftest.py +0 -0
  94. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/judges/test_judge.py +0 -0
  95. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/judges/test_reference.py +0 -0
  96. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/judges/test_rubric.py +0 -0
  97. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/serve/test_client.py +0 -0
  98. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/serve/test_delta.py +0 -0
  99. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/serve/test_pool.py +0 -0
  100. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/test_dialects.py +0 -0
  101. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/test_graph.py +0 -0
  102. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/test_harbor_grading_network.py +0 -0
  103. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/test_semantic.py +0 -0
  104. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/test_task.py +0 -0
  105. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/test_taskset.py +0 -0
  106. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/test_trace.py +0 -0
  107. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/utils/test_loaders.py +0 -0
  108. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/utils/test_platform.py +0 -0
  109. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/tests/unit/utils/test_score.py +0 -0
  110. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/__init__.py +0 -0
  111. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/acp/runner.py +0 -0
  112. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/__init__.py +0 -0
  113. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/dashboard/__init__.py +0 -0
  114. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/dashboard/base.py +0 -0
  115. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/dashboard/eval.py +0 -0
  116. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/dashboard/replay.py +0 -0
  117. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/dashboard/validate.py +0 -0
  118. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/debug.py +0 -0
  119. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/eval/__init__.py +0 -0
  120. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/eval/hint.py +0 -0
  121. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/eval/main.py +0 -0
  122. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/eval/resume.py +0 -0
  123. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/eval/runner.py +0 -0
  124. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/gepa.py +0 -0
  125. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/output.py +0 -0
  126. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/replay.py +0 -0
  127. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/resolve.py +0 -0
  128. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/resume.py +0 -0
  129. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/cli/validate.py +0 -0
  130. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/clients/__init__.py +0 -0
  131. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/clients/base.py +0 -0
  132. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/clients/client.py +0 -0
  133. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/clients/eval.py +0 -0
  134. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/__init__.py +0 -0
  135. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/agent.py +0 -0
  136. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/cli/__init__.py +0 -0
  137. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/cli/debug.py +0 -0
  138. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/cli/env.py +0 -0
  139. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/cli/eval.py +0 -0
  140. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/cli/replay.py +0 -0
  141. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/cli/validate.py +0 -0
  142. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/client.py +0 -0
  143. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/env.py +0 -0
  144. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/harness.py +0 -0
  145. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/judge.py +0 -0
  146. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/retries.py +0 -0
  147. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/runtime.py +0 -0
  148. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/scoring.py +0 -0
  149. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/select.py +0 -0
  150. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/serve.py +0 -0
  151. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/task.py +0 -0
  152. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/configs/taskset.py +0 -0
  153. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/dialects/__init__.py +0 -0
  154. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/dialects/anthropic.py +0 -0
  155. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/dialects/base.py +0 -0
  156. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/dialects/chat.py +0 -0
  157. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/dialects/responses.py +0 -0
  158. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/env.py +0 -0
  159. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/envs/__init__.py +0 -0
  160. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
  161. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/envs/agentic_judge/env.py +0 -0
  162. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
  163. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/envs/best_of_n/env.py +0 -0
  164. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/envs/single_agent/__init__.py +0 -0
  165. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/envs/single_agent/env.py +0 -0
  166. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/envs/user_sim/__init__.py +0 -0
  167. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/envs/user_sim/env.py +0 -0
  168. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/episode.py +0 -0
  169. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/errors.py +0 -0
  170. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/gepa/__init__.py +0 -0
  171. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/gepa/adapter.py +0 -0
  172. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/gepa/config.py +0 -0
  173. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/gepa/dataset.py +0 -0
  174. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/gepa/reflection.py +0 -0
  175. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/gepa/runner.py +0 -0
  176. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harness.py +0 -0
  177. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/__init__.py +0 -0
  178. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/bash/__init__.py +0 -0
  179. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/bash/harness.py +0 -0
  180. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
  181. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
  182. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/browser_use/program.py +0 -0
  183. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
  184. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
  185. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/codex/__init__.py +0 -0
  186. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
  187. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/codex/harness.py +0 -0
  188. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/deepseek/__init__.py +0 -0
  189. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/deepseek/gate.mjs +0 -0
  190. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/deepseek/harness.py +0 -0
  191. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/deepseek/usage.mjs +0 -0
  192. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
  193. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
  194. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
  195. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
  196. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
  197. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
  198. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
  199. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/node.py +0 -0
  200. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/null/__init__.py +0 -0
  201. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/null/harness.py +0 -0
  202. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
  203. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
  204. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/opencode/__init__.py +0 -0
  205. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/opencode/harness.py +0 -0
  206. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/opencode/mcp-ready.js +0 -0
  207. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/pi/__init__.py +0 -0
  208. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
  209. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/pi/harness.py +0 -0
  210. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
  211. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
  212. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
  213. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/rlm/harness.py +0 -0
  214. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
  215. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
  216. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/utils/__init__.py +0 -0
  217. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/utils/compaction.py +0 -0
  218. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/utils/core.py +0 -0
  219. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/utils/install.py +0 -0
  220. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/utils/mcp.py +0 -0
  221. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/harnesses/utils/replay.py +0 -0
  222. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/interception/__init__.py +0 -0
  223. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/interception/base.py +0 -0
  224. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/interception/pool.py +0 -0
  225. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/interception/server.py +0 -0
  226. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/interception/tunnel/__init__.py +0 -0
  227. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/interception/tunnel/base.py +0 -0
  228. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/interception/tunnel/custom.py +0 -0
  229. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/judge.py +0 -0
  230. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/judges/__init__.py +0 -0
  231. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/judges/decision.py +0 -0
  232. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/judges/reference.py +0 -0
  233. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/judges/reference.txt +0 -0
  234. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/judges/rubric.py +0 -0
  235. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/judges/rubric.txt +0 -0
  236. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/mcp/__init__.py +0 -0
  237. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/mcp/server.py +0 -0
  238. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/semantic.py +0 -0
  239. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/serve/__init__.py +0 -0
  240. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/serve/client.py +0 -0
  241. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/serve/delta.py +0 -0
  242. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/serve/encoding.py +0 -0
  243. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/serve/pool.py +0 -0
  244. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/serve/server.py +0 -0
  245. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/serve/types.py +0 -0
  246. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/session.py +0 -0
  247. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/state.py +0 -0
  248. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/taskset.py +0 -0
  249. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/__init__.py +0 -0
  250. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
  251. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
  252. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
  253. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
  254. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
  255. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
  256. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
  257. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
  258. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
  259. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
  260. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
  261. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
  262. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/__init__.py +0 -0
  263. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/aio.py +0 -0
  264. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/artifacts.py +0 -0
  265. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/decorators.py +0 -0
  266. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/env.py +0 -0
  267. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/eval.py +0 -0
  268. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/format.py +0 -0
  269. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/generic.py +0 -0
  270. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/git.py +0 -0
  271. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/image.py +0 -0
  272. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/interrupt.py +0 -0
  273. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/loaders.py +0 -0
  274. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/logging.py +0 -0
  275. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/memory.py +0 -0
  276. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/paths.py +0 -0
  277. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/platform.py +0 -0
  278. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/prime.py +0 -0
  279. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/retries.py +0 -0
  280. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/scope.py +0 -0
  281. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/score.py +0 -0
  282. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/verifiers/v1/utils/trace_store.py +0 -0
  283. {verifiers-0.4.1.dev51 → verifiers-0.4.1.dev54}/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.dev51
3
+ Version: 0.4.1.dev54
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
@@ -46,12 +46,8 @@ Requires-Dist: tenacity>=8.5.0
46
46
  Requires-Dist: tomli-w>=1.0.0
47
47
  Requires-Dist: typing-extensions>=4.12.2
48
48
  Requires-Dist: uvicorn>=0.52.0
49
- Provides-Extra: e2b
50
- Requires-Dist: e2b<3,>=2.35.0; extra == 'e2b'
51
49
  Provides-Extra: harbor
52
50
  Requires-Dist: harbor==0.24.0; (python_full_version >= '3.12') and extra == 'harbor'
53
- Provides-Extra: modal
54
- Requires-Dist: modal>=1.5.4; extra == 'modal'
55
51
  Provides-Extra: openenv
56
52
  Requires-Dist: openenv>=0.4.1; extra == 'openenv'
57
53
  Provides-Extra: ta
@@ -96,14 +96,6 @@ harbor = [
96
96
  # Harbor currently publishes Python 3.12+ packages; keep core verifiers installable on 3.11.
97
97
  "harbor==0.24.0 ; python_full_version >= '3.12'",
98
98
  ]
99
- modal = [
100
- "modal>=1.5.4",
101
- ]
102
- e2b = [
103
- # <3: the runtime swaps the SDK command handle's private stream decoders for
104
- # byte-accurate live output (see runtimes/e2b.py _byte_handle).
105
- "e2b>=2.35.0,<3",
106
- ]
107
99
  openenv = [
108
100
  "openenv>=0.4.1",
109
101
  ]
@@ -225,11 +217,7 @@ markers = [
225
217
  # is applied per axis, so it matches every cell touching that value on any axis.
226
218
  "subprocess: integration cells touching the subprocess (host) runtime",
227
219
  "docker: integration cells touching the docker runtime",
228
- "podman: integration cells touching the podman runtime (needs the engine on the host; local-only)",
229
- "apptainer: integration cells touching the apptainer runtime (needs the engine on the host; local-only)",
230
220
  "prime: integration cells touching the prime runtime (real sandbox + tunnel)",
231
- "modal: integration cells touching the modal runtime (external sandbox; local-only, excluded in CI)",
232
- "e2b: integration cells touching the e2b runtime (external sandbox; local-only, excluded in CI)",
233
221
  "colocated: integration cells with a tool server colocated in the harness runtime",
234
222
  "service: integration cells with a tool server in a Compose service beside the harness",
235
223
  "null: integration cells on the null harness",
@@ -5,8 +5,8 @@ model-driven tests skip.
5
5
 
6
6
  Each behavior module fixes one task and fans it across the harness x runtime grid in
7
7
  `grid.py`, which also says why a cell is skipped. `run` drives the `Env` API in-process,
8
- the calls the eval CLI makes. The placement fixtures below are indirect-only: they translate a parametrized value, and using one without
9
- `indirect=True` fails loudly.
8
+ the calls the eval CLI makes. The placement fixtures below are indirect-only: they
9
+ translate a parametrized value, and using one without `indirect=True` fails loudly.
10
10
  """
11
11
 
12
12
  import asyncio
@@ -54,7 +54,7 @@ def tool_runtime(request) -> dict:
54
54
  return {"service": "tools"}
55
55
  if request.param == "service-vm":
56
56
  return {"service": "tools-vm"}
57
- return {"runtime": {"type": request.param}}
57
+ return {"runtime": runtime_config(request.param)}
58
58
 
59
59
 
60
60
  # Built-in harnesses are bundled in the `harnesses` package; the agent CLIs (`rlm` /
@@ -180,7 +180,7 @@ def run():
180
180
  makes (`serving`, `slots`, `run_slot`, retries included), without its run
181
181
  directory, platform push, or dashboard. The Examples job covers that CLI layer."""
182
182
 
183
- async def _run(taskset: str, **kwargs) -> list[Episode]:
183
+ async def _episodes(taskset: str, **kwargs) -> list[Episode]:
184
184
  config = _eval_config(taskset, **kwargs)
185
185
  env = load_environment(config.env)
186
186
  tasks = list(env.taskset.select(config.select))
@@ -198,7 +198,7 @@ def run():
198
198
  )
199
199
  )
200
200
 
201
- return _run
201
+ return _episodes
202
202
 
203
203
 
204
204
  @pytest.fixture
@@ -90,7 +90,7 @@ class ScriptedAgentUserHarness(Harness[HarnessConfig]):
90
90
  "uv_script": script[-1],
91
91
  "read_secret_api": read_api,
92
92
  }
93
- return await runtime.run_program(["sh", "-c", PROBE], {})
93
+ return await runtime.run(["sh", "-c", PROBE], {})
94
94
 
95
95
 
96
96
  class AgentUserData(vf.TaskData):
@@ -2,35 +2,31 @@
2
2
  cell is skipped.
3
3
 
4
4
  Each behavior module fixes one task and fans it over `grid(...)`: every bundled harness
5
- x every runtime kind. The harness grid runs one local container engine (`docker`);
6
- `podman` / `apptainer` share its container runtime code and are exercised by the
7
- runtime-only grids (`placements`, `runtimes_grid`), where the harness is fixed. A cell
8
- the stack cannot run is collected as a skip with its reason. Every reason derives from a
9
- capability the code declares, never from a list of names, so the grid follows the code:
10
-
11
- - `Harness.NEEDS_CONTAINER`: the harness never runs on the host (`subprocess`)
12
- - `Harness.EXECUTES_CODE`, `SUPPORTS_MCP`, `SUPPORTS_SKILLS`, resume support
13
- (`SUPPORTS_RESUME` or a native session): the behavior needs a shell, MCP tools,
14
- skills, or a resumable exchange
15
- - `RuntimeBackend.supports_user`, `RuntimeBackend.supports_expose`, `NetworkPolicyConfig`: the
16
- behavior needs a user switch, a tool server reachable from another runtime, or a
17
- network policy
18
- - `podman` / `apptainer` need their engine on the host
19
-
20
- CI deselects `podman`, `apptainer`, `modal` and `e2b` by mark: local engines and external
21
- sandboxes.
5
+ on Prime, the production runtime. The basic single- and multi-turn behaviors also run
6
+ on the host (`DEBUG_RUNTIMES`), which needs no container. Docker cells run on the CI
7
+ runner itself and make the jobs too slow, so the Docker runtime is covered by
8
+ `tests/unit/test_runtimes.py` instead. Every reason a cell cannot run derives
9
+ from a capability the code declares, never from a list of names, so the grid follows
10
+ the code.
11
+
12
+ A harness without a capability the behavior needs is collected as a skip with its
13
+ reason (`Harness.EXECUTES_CODE`, `SUPPORTS_MCP`, `SUPPORTS_SKILLS`, resume support via
14
+ `SUPPORTS_RESUME` or a native session).
15
+
16
+ A runtime without a feature the behavior needs (`RuntimeBackend.SUPPORTS_*`, or a
17
+ `NetworkPolicyConfig` for a network policy) skips the cell the same way. That a runtime
18
+ refuses an undeclared feature, with a message naming it, is tested in
19
+ `tests/unit/test_runtimes.py`.
22
20
 
23
21
  Every cell carries its axes' marks, so `-m` selects subsets:
24
22
 
25
- uv run pytest tests/integration -n 8 -m "not podman and not apptainer and not modal and not e2b" # CI
26
- uv run pytest tests/integration -n 8 -m "docker and codex"
27
- uv run pytest tests/integration -n 8 -m e2b # local
23
+ uv run pytest tests/integration -n 8 -m "prime and codex"
24
+ uv run pytest tests/integration -n 8 -m prime
28
25
 
29
26
  `terminus-2` (drives the host tmux) and `browser-use` (needs its Playwright image, which
30
27
  prime cannot pull) stay outside the grid.
31
28
  """
32
29
 
33
- import shutil
34
30
  from collections.abc import Sequence
35
31
  from typing import get_args
36
32
 
@@ -40,7 +36,7 @@ from pydantic import TypeAdapter
40
36
  import verifiers.v1 as vf
41
37
  from verifiers.v1.configs.runtime import NetworkPolicyConfig
42
38
  from verifiers.v1.harness import Harness
43
- from verifiers.v1.runtimes import RuntimeConfig, _backend_cls
39
+ from verifiers.v1.runtimes import RuntimeConfig, backend_cls
44
40
  from verifiers.v1.utils.loaders import harness_class, harness_config_type
45
41
 
46
42
  HARNESSES: list[str | dict] = [
@@ -58,11 +54,17 @@ HARNESSES: list[str | dict] = [
58
54
  "mini-swe-agent",
59
55
  "prime-agent",
60
56
  ]
61
- RUNTIMES = ["subprocess", "docker", "podman", "apptainer", "prime", "modal", "e2b"]
62
- ENGINES = ("podman", "apptainer")
63
- HARNESS_RUNTIMES = [runtime for runtime in RUNTIMES if runtime not in ENGINES]
64
- # Runtimes whose VMs run a task's Compose services.
65
- COMPOSE_VMS = ("prime", "modal")
57
+ DEBUG_RUNTIMES = ("subprocess",)
58
+ RUNTIMES = (*DEBUG_RUNTIMES, "prime")
59
+
60
+ # The runtime features a behavior can need, as `needs` names them.
61
+ RUNTIME_FEATURES = {
62
+ "container": "task images",
63
+ "user": "running as another user",
64
+ "network": "network policies",
65
+ "expose": "port exposure",
66
+ "compose": "Compose services",
67
+ }
66
68
 
67
69
  # Harnesses that cannot run against the CI model yet.
68
70
  # TODO: drop each entry once its fix lands.
@@ -116,26 +118,31 @@ def mark(name: str) -> pytest.MarkDecorator:
116
118
  def runtime_config(runtime: str, harness: str | dict | None = None) -> dict:
117
119
  config: dict = {"type": runtime}
118
120
  program = harness is not None and harness_class(harness_id(harness)).NEEDS_CONTAINER
119
- # The default sandboxes are too small to install and run an agent CLI: e2b's box
120
- # starves rlm's ACP startup, and prime's 1 CPU / 2 GB gets openclaw terminated.
121
- if runtime == "e2b":
122
- config["memory"] = 2.0
121
+ # Prime's default 1 CPU / 2 GB is too small to install and run an agent CLI.
123
122
  if runtime == "prime" and program:
124
123
  config.update(cpu=2.0, memory=4.0)
125
124
  return config
126
125
 
127
126
 
128
127
  def runtime_cls(runtime: str) -> type:
129
- return _backend_cls(TypeAdapter(RuntimeConfig).validate_python({"type": runtime}))
130
-
131
-
132
- def runtime_supports_user(runtime: str) -> bool:
133
- return runtime_cls(runtime).supports_user
128
+ return backend_cls(
129
+ TypeAdapter(RuntimeConfig).validate_python(runtime_config(runtime))
130
+ )
134
131
 
135
132
 
136
- def runtime_supports_network_policy(runtime: str) -> bool:
137
- config = TypeAdapter(RuntimeConfig).validate_python({"type": runtime})
138
- return isinstance(config, NetworkPolicyConfig)
133
+ def supports(runtime: str, feature: str) -> bool:
134
+ """Whether the runtime declares `feature`: a backend flag, or, for a network policy,
135
+ a config that inherits `NetworkPolicyConfig`."""
136
+ if feature == "network":
137
+ config = TypeAdapter(RuntimeConfig).validate_python(runtime_config(runtime))
138
+ return isinstance(config, NetworkPolicyConfig)
139
+ flag = {
140
+ "container": "SUPPORTS_TASK_IMAGES",
141
+ "user": "SUPPORTS_USER_SWITCHING",
142
+ "expose": "SUPPORTS_PORT_EXPOSURE",
143
+ "compose": "SUPPORTS_COMPOSE",
144
+ }[feature]
145
+ return getattr(runtime_cls(runtime), flag)
139
146
 
140
147
 
141
148
  def resumes(cls: type[Harness]) -> bool:
@@ -151,13 +158,10 @@ def resumes(cls: type[Harness]) -> bool:
151
158
  def unsupported(
152
159
  harness: str | dict, runtime: str, needs: tuple[str, ...]
153
160
  ) -> str | None:
154
- """Why this cell cannot run, or None when it can."""
161
+ """Why this cell cannot run, or None when it can: a capability the behavior needs
162
+ that the harness or the runtime does not declare."""
155
163
  name = harness_id(harness)
156
164
  cls = harness_class(name)
157
- if runtime in ENGINES and shutil.which(runtime) is None:
158
- return f"needs {runtime} on the host"
159
- if runtime == "subprocess" and cls.NEEDS_CONTAINER:
160
- return f"{name} needs a container runtime"
161
165
  if "shell" in needs and not cls.EXECUTES_CODE:
162
166
  return f"{name} gives the model no shell"
163
167
  if "mcp" in needs and not cls.SUPPORTS_MCP:
@@ -166,43 +170,48 @@ def unsupported(
166
170
  return f"{name} has no native skill support"
167
171
  if "resume" in needs and not resumes(cls):
168
172
  return f"{name} cannot resume an exchange"
169
- if "user" in needs and not runtime_supports_user(runtime):
170
- return f"{runtime} cannot run commands as another user"
171
- if "network" in needs and not runtime_supports_network_policy(runtime):
172
- return f"{runtime} has no network policy"
173
- return None
173
+ runtime_needs = (*(("container",) if cls.NEEDS_CONTAINER else ()), *needs)
174
+ for feature in runtime_needs:
175
+ if feature in RUNTIME_FEATURES and not supports(runtime, feature):
176
+ return f"{runtime} does not support {RUNTIME_FEATURES[feature]}"
177
+ return CI_MODEL_GAPS.get(name)
178
+
179
+
180
+ def cell_marks(
181
+ harness: str | dict, runtime: str, needs: tuple[str, ...]
182
+ ) -> list[pytest.MarkDecorator]:
183
+ if reason := unsupported(harness, runtime, needs):
184
+ return [pytest.mark.skip(reason=reason)]
185
+ return []
174
186
 
175
187
 
176
188
  def runtimes_grid(
177
- runtimes: Sequence[str] = RUNTIMES, *, needs: tuple[str, ...] = ()
189
+ runtimes: Sequence[str] = ("prime",), *, needs: tuple[str, ...] = ()
178
190
  ) -> list:
179
191
  """`harness_runtime` cells for a behavior with no harness axis."""
180
192
  cells = []
181
193
  for runtime in runtimes:
182
- marks = [mark(runtime)]
183
- if reason := unsupported("null", runtime, needs):
184
- marks.append(pytest.mark.skip(reason=reason))
194
+ marks = [mark(runtime), *cell_marks("null", runtime, needs)]
185
195
  cells.append(pytest.param(runtime, marks=marks, id=f"harness-in-{runtime}"))
186
196
  return cells
187
197
 
188
198
 
189
199
  def grid(
190
200
  harnesses: Sequence[str | dict] = HARNESSES,
191
- runtimes: Sequence[str] = HARNESS_RUNTIMES,
201
+ runtimes: Sequence[str] = ("prime",),
192
202
  *,
193
203
  needs: tuple[str, ...] = (),
194
204
  ) -> list:
195
- """`(harness, harness_runtime)` cells, each marked by its axes and skipped with a
196
- reason where the behavior's `needs` or the runtime rule it out."""
205
+ """`(harness, harness_runtime)` cells, each marked by its axes, skipped where the
206
+ harness or the runtime rules the behavior out."""
197
207
  cells = []
198
208
  for harness in harnesses:
199
209
  for runtime in runtimes:
200
- marks = [mark(harness_id(harness)), mark(runtime)]
201
- reason = unsupported(harness, runtime, needs) or CI_MODEL_GAPS.get(
202
- harness_id(harness)
203
- )
204
- if reason:
205
- marks.append(pytest.mark.skip(reason=reason))
210
+ marks = [
211
+ mark(harness_id(harness)),
212
+ mark(runtime),
213
+ *cell_marks(harness, runtime, needs),
214
+ ]
206
215
  cells.append(
207
216
  pytest.param(
208
217
  harness,
@@ -261,45 +270,30 @@ def skip_harness(cells: list, harness: str, reason: str) -> list:
261
270
 
262
271
 
263
272
  def placements(
264
- harness_runtimes: tuple[str, ...] = tuple(RUNTIMES),
265
- tool_runtimes: tuple[str, ...] = ("colocated", *RUNTIMES),
273
+ harness_runtimes: tuple[str, ...] = ("prime",),
274
+ tool_runtimes: tuple[str, ...] = ("colocated", "subprocess", "prime"),
266
275
  *,
267
276
  shared: bool = False,
268
277
  ) -> list:
269
278
  """`(harness_runtime, tool_runtime)` cells for a tool server placed colocated in the
270
279
  harness's box, in a Compose service beside it (`service`), or in its own runtime
271
- (on Prime beside a Prime harness, a VM on the rollout's private network). A `shared`
272
- server runs once per eval, so it joins no rollout's network."""
280
+ (on Prime beside a Prime harness, a VM on the rollout's private network). A
281
+ `subprocess` tool runtime is a server on the host, reached from the sandbox through
282
+ the tunnel. A `shared` server runs once per eval, so it joins no rollout's network."""
273
283
  cells = []
274
284
  for harness_runtime in harness_runtimes:
275
285
  for tool_runtime in tool_runtimes:
276
286
  marks = [mark(harness_runtime), mark(tool_runtime)]
277
- missing = [
278
- engine
279
- for engine in {harness_runtime, tool_runtime} & set(ENGINES)
280
- if shutil.which(engine) is None
281
- ]
282
- if missing:
283
- marks.append(pytest.mark.skip(reason=f"needs {missing[0]} on the host"))
284
- elif tool_runtime == "service" and harness_runtime not in COMPOSE_VMS:
285
- marks.append(
286
- pytest.mark.skip(
287
- reason="a tool server in a Compose service needs Compose on a "
288
- "Prime or Modal VM"
289
- )
290
- )
291
- elif (
292
- tool_runtime not in ("colocated", "service")
293
- and not runtime_cls(tool_runtime).supports_expose
294
- # Beside a Prime harness, a rollout's Prime server joins its private network.
295
- and not (not shared and tool_runtime == harness_runtime == "prime")
287
+ reason = None
288
+ if tool_runtime == "service":
289
+ reason = unsupported("null", harness_runtime, ("compose",))
290
+ # Beside a Prime harness, a rollout's Prime server joins its private network.
291
+ elif tool_runtime != "colocated" and not (
292
+ not shared and tool_runtime == harness_runtime == "prime"
296
293
  ):
297
- marks.append(
298
- pytest.mark.skip(
299
- reason=f"{tool_runtime} cannot expose a port; a tool server "
300
- "there is reachable only colocated"
301
- )
302
- )
294
+ reason = unsupported("null", tool_runtime, ("expose",))
295
+ if reason:
296
+ marks.append(pytest.mark.skip(reason=reason))
303
297
  cells.append(
304
298
  pytest.param(
305
299
  harness_runtime,
@@ -13,7 +13,7 @@ async def test_agentic_judge_shared_verifier(run, tmp_path):
13
13
  "id": "agentic-judge",
14
14
  "solver": {
15
15
  "harness": {"id": "bash"},
16
- "runtime": {"type": "docker", "block": ["example.com"]},
16
+ "runtime": {"type": "prime", "block": ["example.com"]},
17
17
  "scoring": {"mode": "shared"},
18
18
  },
19
19
  "judge": {
@@ -59,7 +59,7 @@ async def test_env_id_agentic_judge(run, tmp_path):
59
59
  "id": "agentic-judge",
60
60
  "solver": {
61
61
  "harness": {"id": "bash"},
62
- "runtime": {"type": "docker", "block": ["example.com"]},
62
+ "runtime": {"type": "prime", "block": ["example.com"]},
63
63
  "scoring": {"mode": "isolated"},
64
64
  },
65
65
  "judge": {
@@ -84,7 +84,7 @@ async def test_env_id_agentic_judge(run, tmp_path):
84
84
  assert judge.agent.trainable is False
85
85
  assert solver.agent.runtime is not None and judge.agent.runtime is not None
86
86
  assert solver.agent.runtime.id != judge.agent.runtime.id
87
- assert solver.agent.runtime.type == judge.agent.runtime.type == "docker"
87
+ assert solver.agent.runtime.type == judge.agent.runtime.type == "prime"
88
88
  assert "/app/answer.txt" in solver.state.artifacts
89
89
  assert solver.rewards["wrote_phrase"].score == 1.0
90
90
  assert solver.rewards["wrote_phrase"].weight == 0.5
@@ -1,12 +1,12 @@
1
- """Compose scoring uses live shared services or a released, collected submission."""
1
+ """Compose scoring uses live shared services or a released, collected submission, on
2
+ a Prime VM."""
2
3
 
3
- import shutil
4
+ import os
4
5
 
5
6
  import pytest
6
7
 
7
8
  import verifiers.v1 as vf
8
9
  from verifiers.v1.configs.agent import TimeoutConfig
9
- from verifiers.v1.runtimes.container import cli
10
10
  from verifiers.v1.tasksets.harbor.taskset import (
11
11
  CollectHook,
12
12
  HarborArtifact,
@@ -14,10 +14,8 @@ from verifiers.v1.tasksets.harbor.taskset import (
14
14
  HarborTask,
15
15
  )
16
16
 
17
- pytestmark = [
18
- pytest.mark.docker,
19
- pytest.mark.skipif(not shutil.which("docker"), reason="needs Docker"),
20
- ]
17
+ # Solver service backends by trace id, to check their VM is gone before grading.
18
+ SOLVERS: dict[str, list] = {}
21
19
 
22
20
  IMAGE = "python:3.11-slim"
23
21
  COMPOSE = f"""
@@ -44,7 +42,7 @@ services:
44
42
 
45
43
  class ComposeHarness(vf.Harness):
46
44
  async def launch(self, ctx, trace, runtime, endpoint, secret, mcp_urls, data):
47
- return await runtime.run_program(
45
+ return await runtime.run(
48
46
  [
49
47
  "python",
50
48
  "-c",
@@ -61,23 +59,18 @@ class ComposeTask(HarborTask):
61
59
  async def setup(self, trace, runtime, deployment=None):
62
60
  await super().setup(runtime)
63
61
  if deployment is not None:
64
- trace.info["solver_containers"] = [
65
- runtime.info.id for runtime in deployment.target_backends.values()
66
- ]
62
+ SOLVERS[trace.id] = list(deployment.target_backends.values())
67
63
  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"
64
+ # Fresh verifier setup happens only after the solver VM is removed.
65
+ assert all(
66
+ backend._host_backend.stopped for backend in SOLVERS[trace.id]
67
+ ), "solver services survived into grading"
72
68
  trace.info["solver_released_before_grading"] = True
73
69
 
74
70
  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,
71
+ main = targets["main"].backend
72
+ result = await main._run_host(
73
+ "docker", "inspect", "--format", "{{.State.Running}}", main._container
81
74
  )
82
75
  assert result.stdout.strip() == "false", (
83
76
  "workspace must stop before sidecar collection"
@@ -101,7 +94,43 @@ class ComposeTask(HarborTask):
101
94
  "isolated-scoring-timeout",
102
95
  ],
103
96
  )
97
+ @pytest.mark.prime
98
+ @pytest.mark.skipif(not os.environ.get("PRIME_API_KEY"), reason="needs PRIME_API_KEY")
104
99
  async def test_compose_scoring(tmp_path, mode, collect_fails, scoring_timeout):
100
+ task = compose_task(tmp_path, collect_fails, scoring_timeout, mode)
101
+ config = vf.AgentConfig(
102
+ model="unused",
103
+ runtime=vf.PrimeConfig(labels=["vf-ci"]),
104
+ scoring=vf.ScoringConfig(
105
+ mode=mode,
106
+ env={"EXPECT_SIDECAR": "1" if mode == "isolated" else "0"},
107
+ retries=vf.RetryConfig(max_retries=0),
108
+ ),
109
+ timeout=TimeoutConfig(
110
+ setup=600, finalize=60, scoring=1 if scoring_timeout else 120
111
+ ),
112
+ )
113
+ async with vf.Agent(config) as agent:
114
+ agent.harness = ComposeHarness(vf.HarnessConfig())
115
+ trace = await agent.run(task)
116
+ assert all(backend._host_backend.stopped for backend in SOLVERS.pop(trace.id, []))
117
+ if mode == "isolated" and collect_fails:
118
+ assert not trace.ok
119
+ assert "collect hook failed" in str(trace.errors)
120
+ assert "solver_released_before_grading" not in trace.info
121
+ elif scoring_timeout:
122
+ assert trace.ok and trace.is_timeout and not trace.errors
123
+ assert trace.stop_condition == "scoring_timeout"
124
+ assert all(reward is None for reward in trace.rewards.values())
125
+ else:
126
+ assert trace.ok and trace.reward == 1, trace.errors
127
+ assert bool(trace.info.get("collected_sidecars")) == (mode == "isolated")
128
+ assert bool(trace.info.get("solver_released_before_grading")) == (
129
+ mode == "isolated"
130
+ )
131
+
132
+
133
+ def compose_task(tmp_path, collect_fails: bool, scoring_timeout: bool, mode: str):
105
134
  environment = tmp_path / "environment"
106
135
  environment.mkdir()
107
136
  (environment / "docker-compose.yaml").write_text(COMPOSE)
@@ -114,7 +143,7 @@ async def test_compose_scoring(tmp_path, mode, collect_fails, scoring_timeout):
114
143
  + ("sleep 30\n" if scoring_timeout else "")
115
144
  + "echo 1 > /logs/verifier/reward.txt\n"
116
145
  )
117
- task = ComposeTask(
146
+ return ComposeTask(
118
147
  HarborData(
119
148
  prompt="Copy the sidecar answer",
120
149
  task_dir=str(tmp_path),
@@ -135,35 +164,3 @@ async def test_compose_scoring(tmp_path, mode, collect_fails, scoring_timeout):
135
164
  ],
136
165
  )
137
166
  )
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
- )
@@ -19,7 +19,7 @@ async def test_cap(run, cap, stop_condition):
19
19
  (episode,) = await run(
20
20
  "counter-tool",
21
21
  harness="null",
22
- runtime={"type": "subprocess"},
22
+ runtime={"type": "prime"},
23
23
  env={"agent": cap},
24
24
  )
25
25
  (trace,) = episode.traces
@@ -33,7 +33,7 @@ async def test_rollout_timeout(run):
33
33
  (episode,) = await run(
34
34
  "counter-tool",
35
35
  harness="null",
36
- runtime={"type": "subprocess"},
36
+ runtime={"type": "prime"},
37
37
  rollout_timeout=1,
38
38
  )
39
39
  (trace,) = episode.traces
@@ -4,16 +4,16 @@ every other `dialect` a harness config can select. A turn the harness re-sends
4
4
  differently, beyond what its `replay_view` declares, forks the trace."""
5
5
 
6
6
  import pytest
7
- from grid import assert_one_branch, dialect_grid, grid, mark
7
+ from grid import RUNTIMES, assert_one_branch, dialect_grid, grid, mark
8
8
 
9
9
  MULTI_TURN = [
10
- *grid(needs=("shell",)),
10
+ *grid(runtimes=RUNTIMES, needs=("shell",)),
11
11
  *dialect_grid(needs=("shell",)),
12
12
  pytest.param(
13
13
  "bash",
14
- {"type": "modal", "allow": []},
15
- marks=[mark("bash"), mark("modal")],
16
- id="bash-in-modal-framework-only",
14
+ {"type": "prime", "allow": []},
15
+ marks=[mark("bash"), mark("prime")],
16
+ id="bash-in-prime-framework-only",
17
17
  ),
18
18
  ]
19
19
 
@@ -5,7 +5,7 @@ placements (colocated in the harness's box, in a Compose service beside it, or i
5
5
  runtime) on the runtime x runtime grid."""
6
6
 
7
7
  import pytest
8
- from grid import RUNTIMES, assert_one_branch, grid, placements
8
+ from grid import assert_one_branch, grid, placements
9
9
 
10
10
  import verifiers.v1 as vf
11
11
 
@@ -37,7 +37,7 @@ async def test_tool(run, harness, harness_runtime):
37
37
 
38
38
  @pytest.mark.parametrize(
39
39
  "harness_runtime,tool_runtime",
40
- placements(tool_runtimes=("colocated", "service", *RUNTIMES)),
40
+ placements(tool_runtimes=("colocated", "service", "subprocess", "prime")),
41
41
  indirect=True,
42
42
  )
43
43
  async def test_tool_placement(run, harness_runtime, tool_runtime):
@@ -7,7 +7,7 @@ async def test_multimodal_tool(run):
7
7
  (episode,) = await run(
8
8
  "tool-response-image",
9
9
  harness="null",
10
- runtime={"type": "subprocess"},
10
+ runtime={"type": "prime"},
11
11
  reasoning_effort="none",
12
12
  max_turns=4,
13
13
  )
@@ -37,9 +37,7 @@ def prompt_text(trace) -> str:
37
37
 
38
38
 
39
39
  @pytest.mark.parametrize("notice", [True, False], ids=["notice-on", "notice-off"])
40
- @pytest.mark.parametrize(
41
- "harness,harness_runtime", grid(runtimes=["prime"]), indirect=True
42
- )
40
+ @pytest.mark.parametrize("harness,harness_runtime", grid(), indirect=True)
43
41
  async def test_network_policy(run, harness, harness_runtime, notice):
44
42
  episodes = await run(
45
43
  "network-policy",
@@ -26,7 +26,7 @@ async def test_rubric_judge(run, tmp_path, judge_id):
26
26
  (episode,) = await run(
27
27
  "echo",
28
28
  harness="null",
29
- runtime={"type": "subprocess"},
29
+ runtime={"type": "prime"},
30
30
  taskset_overrides={"task": {"judges": [judge]}},
31
31
  max_turns=2,
32
32
  )