verifiers 0.3.2.dev106__tar.gz → 0.3.2.dev108__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 (221) hide show
  1. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/PKG-INFO +1 -1
  2. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/pyproject.toml +2 -0
  3. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/conftest.py +1 -1
  4. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_e2e.py +28 -0
  5. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/__init__.py +4 -0
  6. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/agent.py +9 -2
  7. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/agent.py +1 -1
  8. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/harness.py +13 -5
  9. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harness.py +49 -20
  10. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/browser_use/harness.py +14 -1
  11. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/claude_code/harness.py +1 -2
  12. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/codex/harness.py +1 -2
  13. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/kimi_code/harness.py +7 -4
  14. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/openclaw/harness.py +1 -26
  15. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/pi/harness.py +8 -6
  16. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/prime_agent/harness.py +4 -4
  17. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/rlm/harness.py +15 -4
  18. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/mcp/launch.py +14 -15
  19. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/rollout.py +12 -5
  20. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/runtimes/__init__.py +39 -10
  21. verifiers-0.3.2.dev108/verifiers/v1/runtimes/apptainer.py +214 -0
  22. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/runtimes/base.py +14 -13
  23. verifiers-0.3.2.dev108/verifiers/v1/runtimes/container.py +249 -0
  24. verifiers-0.3.2.dev108/verifiers/v1/runtimes/docker/__init__.py +490 -0
  25. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/runtimes/docker/egress.py +233 -39
  26. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/task.py +5 -1
  27. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/harbor/taskset.py +3 -3
  28. verifiers-0.3.2.dev106/verifiers/v1/runtimes/docker/__init__.py +0 -599
  29. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/.gitignore +0 -0
  30. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/LICENSE +0 -0
  31. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/README.md +0 -0
  32. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/fixtures/counter_tool_v1.py +0 -0
  33. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/fixtures/duet_v1.py +0 -0
  34. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/fixtures/echo_acp_resume_v1.py +0 -0
  35. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
  36. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/fixtures/echo_tool_v1.py +0 -0
  37. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
  38. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/fixtures/echo_v1.py +0 -0
  39. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/fixtures/pyproject.toml +0 -0
  40. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
  41. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_color_codeword_tasks.py +0 -0
  42. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_configs.py +0 -0
  43. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_envs.py +0 -0
  44. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_graph.py +0 -0
  45. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_judges.py +0 -0
  46. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_platform_run.py +0 -0
  47. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_scoring.py +0 -0
  48. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_serve_delta.py +0 -0
  49. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_taskset.py +0 -0
  50. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/tests/v1/test_trace.py +0 -0
  51. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/__init__.py +0 -0
  52. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/cli/commands/init.py +0 -0
  53. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/acp/__init__.py +0 -0
  54. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/acp/runner.py +0 -0
  55. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/__init__.py +0 -0
  56. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/dashboard/__init__.py +0 -0
  57. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/dashboard/base.py +0 -0
  58. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/dashboard/eval.py +0 -0
  59. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/dashboard/replay.py +0 -0
  60. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/dashboard/validate.py +0 -0
  61. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/debug.py +0 -0
  62. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/eval/__init__.py +0 -0
  63. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/eval/hint.py +0 -0
  64. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/eval/main.py +0 -0
  65. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/eval/resume.py +0 -0
  66. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/eval/runner.py +0 -0
  67. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/gepa.py +0 -0
  68. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/init.py +0 -0
  69. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/output.py +0 -0
  70. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/replay.py +0 -0
  71. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/resolve.py +0 -0
  72. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/resume.py +0 -0
  73. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/cli/validate.py +0 -0
  74. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/clients/__init__.py +0 -0
  75. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/clients/base.py +0 -0
  76. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/clients/client.py +0 -0
  77. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/clients/eval.py +0 -0
  78. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/clients/train.py +0 -0
  79. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/__init__.py +0 -0
  80. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/cli/__init__.py +0 -0
  81. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/cli/debug.py +0 -0
  82. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/cli/env.py +0 -0
  83. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/cli/eval.py +0 -0
  84. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/cli/init.py +0 -0
  85. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/cli/replay.py +0 -0
  86. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/cli/validate.py +0 -0
  87. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/client.py +0 -0
  88. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/env.py +0 -0
  89. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/judge.py +0 -0
  90. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/retries.py +0 -0
  91. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/runtime.py +0 -0
  92. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/serve.py +0 -0
  93. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/task.py +0 -0
  94. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/configs/taskset.py +0 -0
  95. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/dialects/__init__.py +0 -0
  96. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/dialects/anthropic.py +0 -0
  97. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/dialects/base.py +0 -0
  98. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/dialects/chat.py +0 -0
  99. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/dialects/responses.py +0 -0
  100. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/env.py +0 -0
  101. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/__init__.py +0 -0
  102. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
  103. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/agentic_judge/env.py +0 -0
  104. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
  105. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/best_of_n/env.py +0 -0
  106. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/isolated_verifier/__init__.py +0 -0
  107. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/isolated_verifier/env.py +0 -0
  108. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/shared_agentic_judge/__init__.py +0 -0
  109. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/single_agent/__init__.py +0 -0
  110. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/single_agent/env.py +0 -0
  111. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/user_sim/__init__.py +0 -0
  112. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/envs/user_sim/env.py +0 -0
  113. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/episode.py +0 -0
  114. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/errors.py +0 -0
  115. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/gepa/__init__.py +0 -0
  116. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/gepa/adapter.py +0 -0
  117. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/gepa/config.py +0 -0
  118. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/gepa/dataset.py +0 -0
  119. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/gepa/reflection.py +0 -0
  120. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/gepa/runner.py +0 -0
  121. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/graph.py +0 -0
  122. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/__init__.py +0 -0
  123. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/bash/__init__.py +0 -0
  124. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/bash/harness.py +0 -0
  125. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
  126. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/browser_use/program.py +0 -0
  127. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
  128. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/codex/__init__.py +0 -0
  129. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
  130. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
  131. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
  132. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
  133. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
  134. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
  135. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
  136. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/node.py +0 -0
  137. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/null/__init__.py +0 -0
  138. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/null/harness.py +0 -0
  139. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
  140. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/pi/__init__.py +0 -0
  141. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
  142. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
  143. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
  144. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
  145. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
  146. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/utils/__init__.py +0 -0
  147. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/utils/compaction.py +0 -0
  148. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/utils/core.py +0 -0
  149. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/utils/install.py +0 -0
  150. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/utils/launch.py +0 -0
  151. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/harnesses/utils/mcp.py +0 -0
  152. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/interception/__init__.py +0 -0
  153. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/interception/base.py +0 -0
  154. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/interception/pool.py +0 -0
  155. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/interception/server.py +0 -0
  156. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/interception/tool.py +0 -0
  157. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/interception/tunnel/__init__.py +0 -0
  158. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/interception/tunnel/base.py +0 -0
  159. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/interception/tunnel/custom.py +0 -0
  160. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/interception/tunnel/prime.py +0 -0
  161. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/judge.py +0 -0
  162. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/judges/__init__.py +0 -0
  163. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/judges/reference.py +0 -0
  164. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/judges/reference.txt +0 -0
  165. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/judges/rubric.py +0 -0
  166. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/judges/rubric.txt +0 -0
  167. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/mcp/__init__.py +0 -0
  168. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/mcp/server.py +0 -0
  169. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/mcp/toolset.py +0 -0
  170. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/runtimes/limiters.py +0 -0
  171. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/runtimes/modal.py +0 -0
  172. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/runtimes/prime.py +0 -0
  173. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/runtimes/subprocess.py +0 -0
  174. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/semantic.py +0 -0
  175. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/serve/__init__.py +0 -0
  176. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/serve/client.py +0 -0
  177. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/serve/delta.py +0 -0
  178. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/serve/encoding.py +0 -0
  179. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/serve/pool.py +0 -0
  180. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/serve/server.py +0 -0
  181. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/serve/types.py +0 -0
  182. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/session.py +0 -0
  183. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/state.py +0 -0
  184. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/taskset.py +0 -0
  185. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/__init__.py +0 -0
  186. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
  187. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/harbor/env.py +0 -0
  188. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
  189. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/lean/__init__.py +0 -0
  190. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/lean/scoring.py +0 -0
  191. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/lean/taskset.py +0 -0
  192. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
  193. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
  194. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
  195. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
  196. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
  197. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
  198. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
  199. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
  200. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
  201. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/trace.py +0 -0
  202. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/types.py +0 -0
  203. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/__init__.py +0 -0
  204. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/aio.py +0 -0
  205. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/artifacts.py +0 -0
  206. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/compile.py +0 -0
  207. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/decorators.py +0 -0
  208. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/format.py +0 -0
  209. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/generic.py +0 -0
  210. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/git.py +0 -0
  211. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/image.py +0 -0
  212. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/interrupt.py +0 -0
  213. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/loaders.py +0 -0
  214. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/logging.py +0 -0
  215. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/memory.py +0 -0
  216. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/paths.py +0 -0
  217. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/platform.py +0 -0
  218. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/prime.py +0 -0
  219. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/retries.py +0 -0
  220. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/score.py +0 -0
  221. {verifiers-0.3.2.dev106 → verifiers-0.3.2.dev108}/verifiers/v1/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: verifiers
3
- Version: 0.3.2.dev106
3
+ Version: 0.3.2.dev108
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
@@ -227,6 +227,8 @@ markers = [
227
227
  # per axis, so it matches every case touching that value on any axis.
228
228
  "subprocess: v1 e2e cases touching the subprocess (host) runtime",
229
229
  "docker: v1 e2e cases touching the docker runtime",
230
+ "podman: v1 e2e cases touching the podman runtime",
231
+ "apptainer: v1 e2e cases touching the apptainer runtime",
230
232
  "prime: v1 e2e cases touching the prime runtime (real sandbox + tunnel; local-only, excluded in CI)",
231
233
  "modal: v1 e2e cases touching the modal runtime (local-only setup; excluded in CI)",
232
234
  "colocated: v1 e2e cases with a user/tool server colocated in the harness runtime",
@@ -24,7 +24,7 @@ Every combination carries its axes' pytest marks, so subsets select with `-m`:
24
24
  uv run pytest tests/v1 -n auto -m prime # only prime (real sandboxes; local)
25
25
  uv run pytest tests/v1 -n auto -m modal # only modal (needs local setup)
26
26
 
27
- Marks: runtimes `subprocess` / `docker` / `prime` / `modal`, placement `colocated`,
27
+ Marks: runtimes `subprocess` / `docker` / `podman` / `apptainer` / `prime` / `modal`, placement `colocated`,
28
28
  harnesses `null` / `bash` / `rlm` / `kimi_code` / `pi` / `openclaw` / `codex` /
29
29
  `claude_code` / `hermes_agent`.
30
30
  A mark is applied per axis, so it selects every case touching that value on ANY axis; for one exact
@@ -5,6 +5,7 @@ combinations a test runs — every axis value at least once plus the cross-bound
5
5
  with distinct networking — instead of fanning the full cross product. prime/modal rows
6
6
  are local-only (their marks are excluded in CI)."""
7
7
 
8
+ import shutil
8
9
  import subprocess
9
10
  import sys
10
11
 
@@ -115,6 +116,15 @@ CHAT_PLACEMENTS = [
115
116
  # remote row per provider.
116
117
  AGENTIC_PLACEMENTS = [
117
118
  pair("bash", "subprocess", "bash-harness-in-subprocess"),
119
+ *[
120
+ pair(
121
+ "bash",
122
+ engine,
123
+ f"bash-harness-in-{engine}",
124
+ mark.skipif(shutil.which(engine) is None, reason=f"needs {engine}"),
125
+ )
126
+ for engine in ("podman", "apptainer")
127
+ ],
118
128
  pair("rlm", "docker", "rlm-harness-in-docker"),
119
129
  pytest.param(
120
130
  {"id": "kimi-code", "transport": "responses"},
@@ -148,6 +158,15 @@ USER_RUNTIMES = [
148
158
  # retain MCP access after resuming. Cover every harness in the local container runtime,
149
159
  # plus remote placements for the sandbox/tunnel and native-process boundaries.
150
160
  ACP_RESUME_PLACEMENTS = [
161
+ *[
162
+ pair(
163
+ "rlm",
164
+ engine,
165
+ f"rlm-acp-in-{engine}",
166
+ mark.skipif(shutil.which(engine) is None, reason=f"needs {engine}"),
167
+ )
168
+ for engine in ("podman", "apptainer")
169
+ ],
151
170
  pair("codex", "docker", "codex-acp-in-docker"),
152
171
  pair("claude-code", "docker", "claude-code-acp-in-docker"),
153
172
  pair("hermes-agent", "docker", "hermes-agent-acp-in-docker"),
@@ -178,6 +197,15 @@ ACP_RESUME_PLACEMENTS = [
178
197
  # (harness and tool in separate docker boxes) and a prime-colocated row (a tool in its
179
198
  # OWN prime sandbox needs port exposure; colocated rides the harness's box).
180
199
  TOOL_PLACEMENTS = [
200
+ *[
201
+ pair(
202
+ "subprocess",
203
+ engine,
204
+ f"harness-in-subprocess-with-tool-in-{engine}",
205
+ mark.skipif(shutil.which(engine) is None, reason=f"needs {engine}"),
206
+ )
207
+ for engine in ("podman", "apptainer")
208
+ ],
181
209
  pair("subprocess", "colocated", "harness-in-subprocess-with-tool-colocated"),
182
210
  pair("docker", "colocated", "harness-in-docker-with-tool-colocated"),
183
211
  pair("subprocess", "docker", "harness-in-subprocess-with-tool-in-docker"),
@@ -73,7 +73,9 @@ from verifiers.v1.mcp import (
73
73
  ToolsetConfig,
74
74
  )
75
75
  from verifiers.v1.runtimes import (
76
+ ApptainerConfig,
76
77
  DockerConfig,
78
+ PodmanConfig,
77
79
  PrimeConfig,
78
80
  ProgramResult,
79
81
  Runtime,
@@ -301,6 +303,8 @@ __all__ = [ # noqa: RUF022 - grouped by public API area
301
303
  "ProgramResult",
302
304
  "SubprocessConfig",
303
305
  "DockerConfig",
306
+ "PodmanConfig",
307
+ "ApptainerConfig",
304
308
  "PrimeConfig",
305
309
  "Env",
306
310
  "SingleAgentEnv",
@@ -540,6 +540,13 @@ class Agent:
540
540
  ) -> dict:
541
541
  """Resolve one run's runtime config, pairing checks, timeouts,
542
542
  interception — shared by `run` and `interaction`."""
543
+ harness = self.harness
544
+ skills = [*task.data.skills, *harness.config.skills]
545
+ if skills:
546
+ # Skill installations can hold run-specific state, such as RLM's package environment.
547
+ harness = type(harness)(
548
+ harness.config.model_copy(update={"skills": skills})
549
+ )
543
550
  if runtime is not None:
544
551
  _check_borrowed_placement(task, runtime, self.runtime_config)
545
552
  runtime_config = runtime.config
@@ -550,7 +557,7 @@ class Agent:
550
557
  )
551
558
  run_is_local = runtime_is_local(runtime_config)
552
559
  validate_pairing(
553
- self.harness,
560
+ harness,
554
561
  type(task),
555
562
  runtime_config,
556
563
  tools=[*task.toolsets(task.config), *shared_tools.values()],
@@ -558,7 +565,7 @@ class Agent:
558
565
  timeouts = resolve_rollout_timeouts(self.timeout, task)
559
566
  return {
560
567
  "agent_config": self.config,
561
- "harness": self.harness,
568
+ "harness": harness,
562
569
  "ctx": self.ctx,
563
570
  "runtime_config": runtime_config,
564
571
  "timeouts": replace(
@@ -14,7 +14,7 @@ class TimeoutConfig(BaseConfig):
14
14
  """Timeout (in seconds) for different phases of an agent's run."""
15
15
 
16
16
  setup: float | None = None # one shared budget: task setup + provisioning
17
- """Timeout (in seconds) for the task + harness setup hooks."""
17
+ """Timeout (in seconds) for task/harness setup through session preparation."""
18
18
  rollout: float | None = None
19
19
  """Timeout (in seconds) for the agent's solve attempt. Unset: the task's own
20
20
  timeout, else 4 hours. `0` disables the timeout."""
@@ -4,7 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  import os
6
6
  from pathlib import Path
7
- from typing import Annotated
7
+ from typing import Annotated, Literal
8
8
 
9
9
  from pydantic import ConfigDict, Field, FiniteFloat
10
10
  from pydantic_config import BaseConfig
@@ -15,6 +15,14 @@ PinnedVersion = Annotated[str, Field(pattern=r"^[A-Za-z0-9._+-]+$")]
15
15
  """A release/tag a harness pins its program install to."""
16
16
 
17
17
 
18
+ SkillSource = Path | Annotated[dict[Literal["runtime"], str], Field(min_length=1)]
19
+
20
+
21
+ def skill_destination(skill: SkillSource, dest: str) -> str:
22
+ """Runtime roots merge into `dest`; host folders keep their resolved name."""
23
+ return dest if isinstance(skill, dict) else f"{dest}/{skill.resolve().name}"
24
+
25
+
18
26
  class HarnessConfig(BaseConfig):
19
27
  id: ID = "bash"
20
28
  """Installed harness package, set through the seat's
@@ -44,10 +52,10 @@ class HarnessConfig(BaseConfig):
44
52
  tool_timeout: FiniteFloat = Field(600.0, gt=0)
45
53
  """Seconds a single MCP tool call may take; raise it for tools that boot a VM."""
46
54
  disabled_tools: list[str] | None = None
47
- skills: list[Path] = Field(default_factory=list)
48
- """Skill folders to upload into the program's skill discovery directory — each
49
- lands at `<skills dir>/<folder name>`. Only harnesses whose program discovers
50
- skills natively (`SUPPORTS_SKILLS`) accept them."""
55
+ skills: list[SkillSource] = Field(default_factory=list)
56
+ """Host skill folders or `{runtime: path}` roots of skills inside the runtime.
57
+ Sources are installed in order; later files override matching earlier files.
58
+ Only harnesses with native skill support (`SUPPORTS_SKILLS`) accept them."""
51
59
 
52
60
  @property
53
61
  def name(self) -> str:
@@ -8,7 +8,7 @@ from collections.abc import Mapping
8
8
  from typing import TYPE_CHECKING, ClassVar, Generic, TypeVar
9
9
 
10
10
  from verifiers.v1.clients import ModelContext
11
- from verifiers.v1.configs.harness import HarnessConfig
11
+ from verifiers.v1.configs.harness import HarnessConfig, skill_destination
12
12
  from verifiers.v1.errors import HarnessError, SandboxError, boundary
13
13
  from verifiers.v1.runtimes import ProgramResult, Runtime
14
14
  from verifiers.v1.task import TaskData
@@ -45,8 +45,8 @@ class Harness(ABC, Generic[ConfigT]):
45
45
  where model-directed execution changes the rules: the subprocess-on-host
46
46
  warning, the judge env's sandbox requirement."""
47
47
  SUPPORTS_SKILLS: ClassVar[bool] = False
48
- """Whether the program discovers SKILL.md skills — its `setup` calls
49
- `install_skills` with the program's fixed discovery location; configuring
48
+ """Whether the program discovers SKILL.md skills — it calls
49
+ `install_skills` with a run-scoped discovery location; configuring
50
50
  `skills` on a harness without support is rejected up front."""
51
51
  NEEDS_CONTAINER: ClassVar[bool] = True
52
52
  """Whether the program must run in a container runtime: True for every harness
@@ -97,35 +97,64 @@ class Harness(ABC, Generic[ConfigT]):
97
97
  """Provision this harness in `runtime` before its execution timeout starts."""
98
98
 
99
99
  async def install_skills(self, runtime: Runtime, dest: str) -> None:
100
- """Upload each `config.skills` folder into `runtime` at `dest/<folder name>` —
101
- the program's fixed skill discovery location, which a supporting harness's
102
- `setup` passes."""
103
- uploads = []
104
- executables = []
100
+ """Install `config.skills` in the program's discovery directory.
101
+ Runtime roots are copied in place; host skill folders are uploaded."""
105
102
  for skill in self.config.skills:
103
+ target_dir = skill_destination(skill, dest)
104
+ if isinstance(skill, dict):
105
+ result = await runtime.run(
106
+ [
107
+ "bash",
108
+ "-e",
109
+ "-o",
110
+ "pipefail",
111
+ "-c",
112
+ r"""
113
+ [ -d "$1" ]
114
+ source=$(CDPATH= cd -- "$1/." && pwd -P)
115
+ mkdir -p -- "$2"
116
+ target=$(CDPATH= cd -- "$2/." && pwd -P)
117
+ [ "$source" != "$target" ] || exit 0
118
+ # A source such as "." must not copy the destination back into itself.
119
+ exclude=$(printf '%s' "./${target#"${source%/}/"}" | sed 's/[][\\*?]/\\&/g')
120
+ tar -C "$source" --exclude="$exclude" -cf - . | tar -xpf - -C "$target"
121
+ """,
122
+ "vf-skills",
123
+ skill["runtime"],
124
+ target_dir,
125
+ ],
126
+ {},
127
+ )
128
+ if result.exit_code:
129
+ raise RuntimeError(
130
+ f"installing runtime skills from {skill['runtime']!r} failed: {result.stderr}"
131
+ )
132
+ continue
106
133
  # Resolve so `.`/`..` entries get their real folder name (and can't
107
134
  # place files outside `dest`).
108
135
  skill = skill.resolve()
109
136
  if not skill.is_dir():
110
137
  raise ValueError(f"skill {str(skill)!r} is not a folder")
138
+ uploads = []
139
+ executables = []
111
140
  for file in skill.rglob("*"):
112
141
  if not file.is_file():
113
142
  continue
114
- target = f"{dest}/{skill.name}/{file.relative_to(skill).as_posix()}"
143
+ target = f"{target_dir}/{file.relative_to(skill).as_posix()}"
115
144
  uploads.append((target, file.read_bytes()))
116
145
  if os.access(file, os.X_OK):
117
146
  executables.append(target)
118
- # Settle every upload before returning or surfacing an error.
119
- results = await asyncio.gather(
120
- *(runtime.write(target, data) for target, data in uploads),
121
- return_exceptions=True,
122
- )
123
- for result in results:
124
- if isinstance(result, BaseException):
125
- raise result
126
- if executables:
127
- # `write` moves bytes, not modes; restore the execute bits scripts need.
128
- await runtime.run(["chmod", "+x", *executables], {})
147
+ # Finish this source before the next one overwrites matching files.
148
+ results = await asyncio.gather(
149
+ *(runtime.write(target, data) for target, data in uploads),
150
+ return_exceptions=True,
151
+ )
152
+ for result in results:
153
+ if isinstance(result, BaseException):
154
+ raise result
155
+ if executables:
156
+ # `write` moves bytes, not modes; restore the execute bits scripts need.
157
+ await runtime.run(["chmod", "+x", *executables], {})
129
158
 
130
159
  async def _check_result(
131
160
  self, trace: Trace, runtime: Runtime, result: ProgramResult
@@ -1,6 +1,8 @@
1
1
  from pathlib import Path
2
2
  from typing import Literal
3
+ from urllib.parse import urlsplit
3
4
 
5
+ import httpx
4
6
  from pydantic import model_validator
5
7
 
6
8
  from verifiers.v1.clients import ModelContext
@@ -92,7 +94,18 @@ class BrowserUseHarness(Harness[BrowserUseHarnessConfig]):
92
94
  f"--state-dir={state}",
93
95
  ]
94
96
  if self.config.cdp_url:
95
- args.append(f"--cdp-url={self.config.cdp_url}")
97
+ cdp_url = runtime.host_url(self.config.cdp_url)
98
+ if cdp_url != self.config.cdp_url and urlsplit(
99
+ self.config.cdp_url
100
+ ).scheme in ("http", "https"):
101
+ # CDP discovery returns a host-side WebSocket URL; translate that too.
102
+ async with httpx.AsyncClient() as client:
103
+ response = await client.get(
104
+ f"{self.config.cdp_url.rstrip('/')}/json/version"
105
+ )
106
+ response.raise_for_status()
107
+ cdp_url = runtime.host_url(response.json()["webSocketDebuggerUrl"])
108
+ args.append(f"--cdp-url={cdp_url}")
96
109
  return await launch_chat_program(
97
110
  PROGRAM_SOURCE,
98
111
  self.config,
@@ -15,7 +15,6 @@ ACP_VERSION = "0.67.0"
15
15
  CLAUDE_BIN = f"{PACKAGES_DIR}/node_modules/.bin/claude"
16
16
  ACP_BIN = f"{PACKAGES_DIR}/node_modules/.bin/claude-agent-acp"
17
17
  CLAUDE_CONFIG_ROOT = ".vf-claude"
18
- SKILLS_DIR = ".claude/skills"
19
18
  ACP_INSTALL = r"""
20
19
  set -e
21
20
  export PATH="/var/tmp/vf-node/bin:$PATH"
@@ -39,7 +38,6 @@ class ClaudeCodeHarness(ACPHarness[ClaudeCodeHarnessConfig]):
39
38
  SUPPORTS_SKILLS = True
40
39
 
41
40
  async def setup(self, runtime: Runtime) -> None:
42
- await self.install_skills(runtime, SKILLS_DIR)
43
41
  await ensure_node(runtime)
44
42
  versions = {"version": self.config.version, "acp_version": ACP_VERSION}
45
43
  directory = CLAUDE_ACP_DIR.format(**versions)
@@ -74,6 +72,7 @@ class ClaudeCodeHarness(ACPHarness[ClaudeCodeHarnessConfig]):
74
72
  ) -> ACPConfig:
75
73
  system_prompt, prompt = self.resolve_prompt(data)
76
74
  config_dir = self.config_dir(trace)
75
+ await self.install_skills(runtime, f"{config_dir}/skills")
77
76
  versions = {"version": self.config.version, "acp_version": ACP_VERSION}
78
77
  session_meta = {
79
78
  "claudeCode": {
@@ -22,7 +22,6 @@ PACKAGES_DIR = f"{CODEX_DIR}/acp"
22
22
  ACP_VERSION = "1.2.0"
23
23
  CODEX_BIN = f"{PACKAGES_DIR}/node_modules/.bin/codex"
24
24
  ACP_BIN = f"{PACKAGES_DIR}/node_modules/.bin/codex-acp"
25
- SKILLS_DIR = ".agents/skills"
26
25
  INSTALL = r"""
27
26
  set -e
28
27
  export PATH="/var/tmp/vf-node/bin:$PATH"
@@ -58,7 +57,6 @@ class CodexHarness(ACPHarness[CodexHarnessConfig]):
58
57
  raise RuntimeError(f"Codex {failure['category']}: {failure['safeMessage']}")
59
58
 
60
59
  async def setup(self, runtime: Runtime) -> None:
61
- await self.install_skills(runtime, SKILLS_DIR)
62
60
  await ensure_node(runtime)
63
61
  logger.info(
64
62
  "codex: ensuring Codex %s and codex-acp %s are installed",
@@ -137,6 +135,7 @@ class CodexHarness(ACPHarness[CodexHarnessConfig]):
137
135
  mcp_urls: dict[str, str],
138
136
  ) -> dict[str, str]:
139
137
  home = self.trace_home(trace)
138
+ await self.install_skills(runtime, f"{home}/skills")
140
139
  mcp_config = "features={mcp_2026_07_28=true}\n" + (
141
140
  "mcp_servers={"
142
141
  + ",".join(
@@ -8,7 +8,7 @@ import tomli_w
8
8
  from verifiers.v1.acp import ACPConfig, ACPHarness
9
9
  from verifiers.v1.clients import ModelContext
10
10
  from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
11
- from verifiers.v1.harnesses.utils.install import ensure_installed
11
+ from verifiers.v1.harnesses.utils.install import ensure_installed, remove_dir
12
12
  from verifiers.v1.runtimes import Runtime
13
13
  from verifiers.v1.task import TaskData
14
14
  from verifiers.v1.trace import Trace
@@ -18,7 +18,6 @@ logger = logging.getLogger(__name__)
18
18
  BINARY = "/tmp/vf-kimi-code/bin/kimi"
19
19
  KIMI_HOME = ".vf-kimi-code"
20
20
  ACP_COMMAND = [BINARY, "acp"]
21
- SKILLS_DIR = f"{KIMI_HOME}/skills"
22
21
 
23
22
  INSTALL = r"""
24
23
  set -e
@@ -52,7 +51,6 @@ class KimiCodeHarness(ACPHarness[KimiCodeHarnessConfig]):
52
51
  SUPPORTS_SKILLS = True
53
52
 
54
53
  async def setup(self, runtime: Runtime) -> None:
55
- await self.install_skills(runtime, SKILLS_DIR)
56
54
  logger.info(
57
55
  "kimi-code: ensuring Kimi Code %s is installed", self.config.version
58
56
  )
@@ -77,6 +75,8 @@ class KimiCodeHarness(ACPHarness[KimiCodeHarnessConfig]):
77
75
  data: TaskData,
78
76
  ) -> ACPConfig:
79
77
  kimi_home = f"{KIMI_HOME}/{trace.id}"
78
+ skills_dir = f"{kimi_home}/skills"
79
+ await self.install_skills(runtime, skills_dir)
80
80
  provider_type = {
81
81
  "chat_completions": "openai",
82
82
  "responses": "openai_responses",
@@ -88,7 +88,7 @@ class KimiCodeHarness(ACPHarness[KimiCodeHarnessConfig]):
88
88
  else endpoint
89
89
  )
90
90
  config = {
91
- "extra_skill_dirs": [SKILLS_DIR] if self.config.skills else [],
91
+ "extra_skill_dirs": [skills_dir] if self.config.skills else [],
92
92
  **(
93
93
  {
94
94
  "permission": {
@@ -125,3 +125,6 @@ class KimiCodeHarness(ACPHarness[KimiCodeHarnessConfig]):
125
125
  prompt=prompt,
126
126
  system_prompt=system_prompt,
127
127
  )
128
+
129
+ async def cleanup(self, trace: Trace, runtime: Runtime) -> None:
130
+ await remove_dir(runtime, f"{KIMI_HOME}/{trace.id}", "Kimi Code state")
@@ -1,9 +1,7 @@
1
1
  """Run OpenClaw's Gateway-backed ACP agent against interception."""
2
2
 
3
- import asyncio
4
3
  import json
5
4
  import logging
6
- import secrets
7
5
 
8
6
  from verifiers.v1.acp import ACPConfig, ACPHarness
9
7
  from verifiers.v1.clients import ModelContext
@@ -130,22 +128,6 @@ class OpenClawHarness(ACPHarness[OpenClawHarnessConfig]):
130
128
  SUPPORTS_SKILLS = True
131
129
 
132
130
  async def setup(self, runtime: Runtime) -> None:
133
- if not hasattr(self, "_staged_skills_dir"):
134
- self._staged_skills_dir = (
135
- f".vf-openclaw/staged-skills-{secrets.token_hex(8)}"
136
- )
137
- self._skills_setup_lock = asyncio.Lock()
138
- if self.config.skills:
139
- async with self._skills_setup_lock:
140
- # A complete tree is immutable, so concurrent setups can safely reuse it.
141
- ready_path = f"{self._staged_skills_dir}/.ready"
142
- ready = await runtime.run(["test", "-f", ready_path], {})
143
- if ready.exit_code != 0:
144
- await remove_dir(
145
- runtime, self._staged_skills_dir, "OpenClaw skills"
146
- )
147
- await self.install_skills(runtime, self._staged_skills_dir)
148
- await runtime.write(ready_path, b"")
149
131
  directory = OPENCLAW_DIR.format(version=self.config.version)
150
132
  binary = OPENCLAW_BIN.format(version=self.config.version)
151
133
  logger.info("openclaw: ensuring OpenClaw %s is installed", self.config.version)
@@ -233,14 +215,7 @@ class OpenClawHarness(ACPHarness[OpenClawHarnessConfig]):
233
215
  # OpenClaw treats an empty allowlist as all; a no-match key disables the catalog.
234
216
  config.setdefault("skills", {})["allowBundled"] = ["__none__"]
235
217
  await runtime.write(config_path, json.dumps(config).encode())
236
- if self.config.skills:
237
- copied = await runtime.run(
238
- ["cp", "-R", self._staged_skills_dir, skills_dir], {}
239
- )
240
- if copied.exit_code != 0:
241
- raise RuntimeError(
242
- f"failed to isolate OpenClaw skills: {copied.stderr.strip()[-500:]}"
243
- )
218
+ await self.install_skills(runtime, skills_dir)
244
219
 
245
220
  env = {
246
221
  **self.config.resolved_env,
@@ -7,9 +7,9 @@ from typing import Literal
7
7
 
8
8
  from verifiers.v1.acp import ACPConfig, ACPHarness
9
9
  from verifiers.v1.clients import ModelContext
10
- from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion
10
+ from verifiers.v1.configs.harness import HarnessConfig, PinnedVersion, skill_destination
11
11
  from verifiers.v1.harnesses.node import NODE_BIN_DIR, ensure_node
12
- from verifiers.v1.harnesses.utils.install import ensure_installed
12
+ from verifiers.v1.harnesses.utils.install import ensure_installed, remove_dir
13
13
  from verifiers.v1.runtimes import Runtime
14
14
  from verifiers.v1.task import TaskData
15
15
  from verifiers.v1.trace import Trace
@@ -21,7 +21,6 @@ KEY_VAR = "PI_INTERCEPT_KEY"
21
21
  PI_DIR = "/var/tmp/vf-pi"
22
22
  PACKAGES_DIR = f"{PI_DIR}/mcp"
23
23
  PI_BIN = f"{PACKAGES_DIR}/node_modules/.bin/pi"
24
- SKILLS_DIR = ".agents/skills"
25
24
  MCP_VERSION = "2.28.0"
26
25
  ACP_VERSION = "0.0.33"
27
26
  MCP_ADAPTER = f"{PACKAGES_DIR}/node_modules/pi-mcp-adapter/index.ts"
@@ -61,7 +60,6 @@ class PiHarness(ACPHarness[PiHarnessConfig]):
61
60
  SUPPORTS_SKILLS = True
62
61
 
63
62
  async def setup(self, runtime: Runtime) -> None:
64
- await self.install_skills(runtime, SKILLS_DIR)
65
63
  await ensure_node(runtime)
66
64
  logger.info(
67
65
  "pi: ensuring Pi %s and pi-acp %s are installed",
@@ -93,6 +91,8 @@ class PiHarness(ACPHarness[PiHarnessConfig]):
93
91
  ) -> ACPConfig:
94
92
  system_prompt, prompt = self.resolve_prompt(data)
95
93
  agent_dir = f".vf-pi-agent-{trace.id}"
94
+ skills_dir = f"{agent_dir}/skills"
95
+ await self.install_skills(runtime, skills_dir)
96
96
  reasoning = ctx.sampling.reasoning_effort not in (
97
97
  None,
98
98
  "none",
@@ -159,8 +159,7 @@ class PiHarness(ACPHarness[PiHarnessConfig]):
159
159
  skill_args = [
160
160
  arg
161
161
  for skill in self.config.skills
162
- # Resolve like `install_skills` so the path matches what it wrote.
163
- for arg in ("--skill", f"{SKILLS_DIR}/{skill.resolve().name}")
162
+ for arg in ("--skill", skill_destination(skill, skills_dir))
164
163
  ]
165
164
  pi_args = [
166
165
  PI_BIN,
@@ -190,3 +189,6 @@ class PiHarness(ACPHarness[PiHarnessConfig]):
190
189
  # Pi's extension owns the task-scoped MCP configuration.
191
190
  mcp_urls={},
192
191
  )
192
+
193
+ async def cleanup(self, trace: Trace, runtime: Runtime) -> None:
194
+ await remove_dir(runtime, f".vf-pi-agent-{trace.id}", "Pi state")
@@ -7,7 +7,7 @@ from typing import Literal
7
7
 
8
8
  from verifiers.v1.acp import ACPConfig, ACPHarness, ACPTurn
9
9
  from verifiers.v1.clients import ModelContext
10
- from verifiers.v1.configs.harness import HarnessConfig
10
+ from verifiers.v1.configs.harness import HarnessConfig, skill_destination
11
11
  from verifiers.v1.harnesses.node import NODE_BIN_DIR, ensure_node
12
12
  from verifiers.v1.harnesses.utils.install import ensure_installed, remove_dir
13
13
  from verifiers.v1.runtimes import Runtime
@@ -25,7 +25,6 @@ PRIME_AGENT_COMMIT: Literal["81ae3cb34d27d38ee37f9e205a1e73694993b344"] = (
25
25
  PRIME_AGENT_VERSION = "0.9.1"
26
26
  PRIME_AGENT_DIR = "/var/tmp/vf-prime-agent"
27
27
  STATE_ROOT = "/tmp/vf-prime-agent-runs"
28
- SKILLS_DIR = ".agents/skills"
29
28
  PROVIDER = "intercept"
30
29
  LIFECYCLE_META_NAMESPACE = "ai.primeintellect.prime-agent"
31
30
  KEY_VAR = "PRIME_AGENT_INTERCEPT_KEY"
@@ -155,7 +154,6 @@ class PrimeAgentHarness(ACPHarness[PrimeAgentHarnessConfig]):
155
154
  statuses.append(status)
156
155
 
157
156
  async def setup(self, runtime: Runtime) -> None:
158
- await self.install_skills(runtime, SKILLS_DIR)
159
157
  await ensure_node(runtime)
160
158
  logger.info("prime-agent: ensuring commit %s is installed", self.config.commit)
161
159
  await ensure_installed(
@@ -191,6 +189,7 @@ class PrimeAgentHarness(ACPHarness[PrimeAgentHarnessConfig]):
191
189
 
192
190
  root = self._root(trace)
193
191
  agent_dir = f"{root}/agent"
192
+ skills_dir = f"{agent_dir}/skills"
194
193
  created = await runtime.run(
195
194
  [
196
195
  "mkdir",
@@ -207,6 +206,7 @@ class PrimeAgentHarness(ACPHarness[PrimeAgentHarnessConfig]):
207
206
  raise RuntimeError(
208
207
  f"prime-agent state directory failed: {created.stderr.strip()[-500:]}"
209
208
  )
209
+ await self.install_skills(runtime, skills_dir)
210
210
  reasoning = ctx.sampling.reasoning_effort not in (
211
211
  None,
212
212
  "none",
@@ -251,7 +251,7 @@ class PrimeAgentHarness(ACPHarness[PrimeAgentHarnessConfig]):
251
251
  if self.config.autonomous:
252
252
  args.append("--autonomous")
253
253
  for skill in self.config.skills:
254
- args += ["--skill", f"{SKILLS_DIR}/{skill.resolve().name}"]
254
+ args += ["--skill", skill_destination(skill, skills_dir)]
255
255
  if system_prompt:
256
256
  args += ["--append-system-prompt", system_prompt]
257
257
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import hashlib
4
4
  import logging
5
+ import secrets
5
6
  import shlex
6
7
  from typing import Any, Literal
7
8
 
@@ -18,7 +19,7 @@ from pydantic_config import BaseConfig
18
19
  from verifiers.v1.acp import ACPConfig, ACPHarness, ACPTurn, JsonObject
19
20
  from verifiers.v1.clients import ModelContext
20
21
  from verifiers.v1.configs.harness import HarnessConfig
21
- from verifiers.v1.harnesses.utils.install import ensure_installed
22
+ from verifiers.v1.harnesses.utils.install import ensure_installed, remove_dir
22
23
  from verifiers.v1.runtimes import Runtime
23
24
  from verifiers.v1.task import TaskData
24
25
  from verifiers.v1.trace import Trace
@@ -140,11 +141,15 @@ class RLMHarness(ACPHarness[RLMHarnessConfig]):
140
141
  APPENDS_SYSTEM_PROMPT = True
141
142
  SUPPORTS_MCP = True
142
143
  SUPPORTS_SKILLS = True
144
+ _skills_install_dir: str | None = None
143
145
 
144
146
  async def setup(self, runtime: Runtime) -> None:
145
- # Before the installer: install.sh packages the skills it finds.
146
- await self.install_skills(runtime, SKILLS_DIR)
147
+ if self.config.skills:
148
+ # Editable skill packages and uv's tool environment must belong to this run.
149
+ self._skills_install_dir = f"{RLM_CACHE_DIR}-skills-{secrets.token_hex(16)}"
147
150
  directory = self._install_dir()
151
+ skills_dir = f"{directory}/skills" if self.config.skills else SKILLS_DIR
152
+ await self.install_skills(runtime, skills_dir)
148
153
  binary = f"{directory}/bin/rlm"
149
154
  checkout = f"{directory}/checkout"
150
155
  ready = f"{directory}/.ready"
@@ -155,7 +160,9 @@ class RLMHarness(ACPHarness[RLMHarnessConfig]):
155
160
  "{ apt-get update -qq && apt-get install -y -qq git; } && "
156
161
  f"rm -rf {checkout} && git clone https://{RLM_REPO} {checkout} && "
157
162
  f"git -C {checkout} checkout {shlex.quote(self.config.version)} && "
163
+ f"sed -i 's|/task/rlm-skills|{skills_dir}|g' {checkout}/install.sh && "
158
164
  f"UV_INSTALL_DIR={directory}/bin UV_TOOL_BIN_DIR={directory}/bin "
165
+ f"UV_TOOL_DIR={directory}/tools "
159
166
  f"RLM_CHECKOUT_PATH={checkout} bash {checkout}/install.sh && "
160
167
  f"touch {ready})"
161
168
  )
@@ -279,6 +286,10 @@ class RLMHarness(ACPHarness[RLMHarnessConfig]):
279
286
 
280
287
  async def cleanup(self, trace: Trace, runtime: Runtime) -> None:
281
288
  await runtime.run(["rm", "-rf", f"{RLM_STATE_DIR}/{trace.id}"], {})
289
+ if self._skills_install_dir is not None:
290
+ await remove_dir(
291
+ runtime, self._skills_install_dir, "RLM skill installation"
292
+ )
282
293
 
283
294
  @staticmethod
284
295
  def _home(trace: Trace) -> str:
@@ -286,4 +297,4 @@ class RLMHarness(ACPHarness[RLMHarnessConfig]):
286
297
 
287
298
  def _install_dir(self) -> str:
288
299
  cache_key = hashlib.sha256(self.config.version.encode()).hexdigest()
289
- return f"{RLM_CACHE_DIR}-{cache_key}"
300
+ return self._skills_install_dir or f"{RLM_CACHE_DIR}-{cache_key}"