verifiers 0.3.2.dev142__tar.gz → 0.3.2.dev144__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 (220) hide show
  1. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/PKG-INFO +1 -1
  2. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/__init__.py +10 -3
  3. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/cli/env.py +30 -4
  4. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/env.py +22 -13
  5. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/taskset.py +10 -4
  6. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/env.py +2 -0
  7. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/episode.py +3 -0
  8. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/errors.py +3 -2
  9. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/rollout.py +41 -22
  10. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/serve/delta.py +1 -0
  11. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/trace.py +13 -3
  12. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/.gitignore +0 -0
  13. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/LICENSE +0 -0
  14. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/README.md +0 -0
  15. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/pyproject.toml +0 -0
  16. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/conftest.py +0 -0
  17. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/fixtures/counter_tool_v1.py +0 -0
  18. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/fixtures/duet_v1.py +0 -0
  19. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/fixtures/echo_acp_resume_v1.py +0 -0
  20. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
  21. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/fixtures/echo_tool_v1.py +0 -0
  22. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
  23. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/fixtures/echo_v1.py +0 -0
  24. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/fixtures/pyproject.toml +0 -0
  25. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
  26. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_color_codeword_tasks.py +0 -0
  27. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_configs.py +0 -0
  28. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_e2e.py +0 -0
  29. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_envs.py +0 -0
  30. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_graph.py +0 -0
  31. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_judges.py +0 -0
  32. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_platform_run.py +0 -0
  33. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_scoring.py +0 -0
  34. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_serve_delta.py +0 -0
  35. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_taskset.py +0 -0
  36. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/tests/v1/test_trace.py +0 -0
  37. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/__init__.py +0 -0
  38. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/acp/__init__.py +0 -0
  39. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/acp/runner.py +0 -0
  40. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/agent.py +0 -0
  41. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/__init__.py +0 -0
  42. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/dashboard/__init__.py +0 -0
  43. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/dashboard/base.py +0 -0
  44. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/dashboard/eval.py +0 -0
  45. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/dashboard/replay.py +0 -0
  46. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/dashboard/validate.py +0 -0
  47. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/debug.py +0 -0
  48. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/eval/__init__.py +0 -0
  49. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/eval/hint.py +0 -0
  50. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/eval/main.py +0 -0
  51. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/eval/resume.py +0 -0
  52. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/eval/runner.py +0 -0
  53. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/gepa.py +0 -0
  54. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/init.py +0 -0
  55. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/output.py +0 -0
  56. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/replay.py +0 -0
  57. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/resolve.py +0 -0
  58. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/resume.py +0 -0
  59. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/cli/validate.py +0 -0
  60. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/clients/__init__.py +0 -0
  61. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/clients/base.py +0 -0
  62. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/clients/client.py +0 -0
  63. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/clients/eval.py +0 -0
  64. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/clients/train.py +0 -0
  65. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/__init__.py +0 -0
  66. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/agent.py +0 -0
  67. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/cli/__init__.py +0 -0
  68. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/cli/debug.py +0 -0
  69. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/cli/eval.py +0 -0
  70. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/cli/init.py +0 -0
  71. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/cli/replay.py +0 -0
  72. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/cli/validate.py +0 -0
  73. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/client.py +0 -0
  74. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/harness.py +0 -0
  75. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/judge.py +0 -0
  76. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/retries.py +0 -0
  77. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/runtime.py +0 -0
  78. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/serve.py +0 -0
  79. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/configs/task.py +0 -0
  80. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/dialects/__init__.py +0 -0
  81. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/dialects/anthropic.py +0 -0
  82. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/dialects/base.py +0 -0
  83. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/dialects/chat.py +0 -0
  84. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/dialects/responses.py +0 -0
  85. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/__init__.py +0 -0
  86. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
  87. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/agentic_judge/env.py +0 -0
  88. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
  89. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/best_of_n/env.py +0 -0
  90. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/isolated_verifier/__init__.py +0 -0
  91. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/isolated_verifier/env.py +0 -0
  92. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/shared_agentic_judge/__init__.py +0 -0
  93. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/single_agent/__init__.py +0 -0
  94. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/single_agent/env.py +0 -0
  95. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/user_sim/__init__.py +0 -0
  96. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/envs/user_sim/env.py +0 -0
  97. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/gepa/__init__.py +0 -0
  98. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/gepa/adapter.py +0 -0
  99. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/gepa/config.py +0 -0
  100. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/gepa/dataset.py +0 -0
  101. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/gepa/reflection.py +0 -0
  102. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/gepa/runner.py +0 -0
  103. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/graph.py +0 -0
  104. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harness.py +0 -0
  105. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/__init__.py +0 -0
  106. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/bash/__init__.py +0 -0
  107. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/bash/harness.py +0 -0
  108. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
  109. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
  110. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/browser_use/program.py +0 -0
  111. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
  112. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
  113. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/codex/__init__.py +0 -0
  114. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
  115. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/codex/harness.py +0 -0
  116. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
  117. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
  118. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
  119. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
  120. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
  121. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
  122. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
  123. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
  124. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/node.py +0 -0
  125. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/null/__init__.py +0 -0
  126. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/null/harness.py +0 -0
  127. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
  128. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
  129. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/pi/__init__.py +0 -0
  130. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
  131. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/pi/harness.py +0 -0
  132. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
  133. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
  134. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
  135. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/rlm/harness.py +0 -0
  136. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
  137. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
  138. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
  139. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/utils/__init__.py +0 -0
  140. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/utils/compaction.py +0 -0
  141. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/utils/core.py +0 -0
  142. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/utils/install.py +0 -0
  143. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/utils/launch.py +0 -0
  144. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/harnesses/utils/mcp.py +0 -0
  145. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/interception/__init__.py +0 -0
  146. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/interception/base.py +0 -0
  147. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/interception/pool.py +0 -0
  148. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/interception/server.py +0 -0
  149. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/interception/tunnel/__init__.py +0 -0
  150. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/interception/tunnel/base.py +0 -0
  151. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/interception/tunnel/custom.py +0 -0
  152. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/interception/tunnel/prime.py +0 -0
  153. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/judge.py +0 -0
  154. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/judges/__init__.py +0 -0
  155. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/judges/reference.py +0 -0
  156. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/judges/reference.txt +0 -0
  157. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/judges/rubric.py +0 -0
  158. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/judges/rubric.txt +0 -0
  159. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/mcp/__init__.py +0 -0
  160. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/mcp/launch.py +0 -0
  161. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/mcp/server.py +0 -0
  162. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/mcp/toolset.py +0 -0
  163. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/runtimes/__init__.py +0 -0
  164. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/runtimes/apptainer.py +0 -0
  165. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/runtimes/base.py +0 -0
  166. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/runtimes/container.py +0 -0
  167. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/runtimes/docker/__init__.py +0 -0
  168. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/runtimes/docker/egress.py +0 -0
  169. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/runtimes/limiters.py +0 -0
  170. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/runtimes/modal.py +0 -0
  171. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/runtimes/prime.py +0 -0
  172. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/runtimes/subprocess.py +0 -0
  173. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/semantic.py +0 -0
  174. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/serve/__init__.py +0 -0
  175. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/serve/client.py +0 -0
  176. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/serve/encoding.py +0 -0
  177. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/serve/pool.py +0 -0
  178. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/serve/server.py +0 -0
  179. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/serve/types.py +0 -0
  180. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/session.py +0 -0
  181. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/state.py +0 -0
  182. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/task.py +0 -0
  183. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/taskset.py +0 -0
  184. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/__init__.py +0 -0
  185. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
  186. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/harbor/compose.py +0 -0
  187. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/harbor/env.py +0 -0
  188. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
  189. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
  190. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
  191. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
  192. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
  193. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
  194. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
  195. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
  196. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
  197. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
  198. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
  199. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/types.py +0 -0
  200. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/__init__.py +0 -0
  201. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/aio.py +0 -0
  202. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/artifacts.py +0 -0
  203. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/compile.py +0 -0
  204. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/decorators.py +0 -0
  205. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/format.py +0 -0
  206. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/generic.py +0 -0
  207. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/git.py +0 -0
  208. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/image.py +0 -0
  209. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/interrupt.py +0 -0
  210. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/loaders.py +0 -0
  211. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/logging.py +0 -0
  212. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/memory.py +0 -0
  213. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/paths.py +0 -0
  214. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/platform.py +0 -0
  215. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/prime.py +0 -0
  216. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/retries.py +0 -0
  217. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/scope.py +0 -0
  218. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/score.py +0 -0
  219. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/verifiers/v1/utils/trace_store.py +0 -0
  220. {verifiers-0.3.2.dev142 → verifiers-0.3.2.dev144}/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.dev142
3
+ Version: 0.3.2.dev144
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
@@ -14,8 +14,12 @@ from verifiers.v1.clients import (
14
14
  resolve_client,
15
15
  )
16
16
  from verifiers.v1.configs.agent import AgentConfig
17
- from verifiers.v1.configs.cli.env import narrowed_env_annotation, resolve_env_field
18
- from verifiers.v1.configs.env import EnvConfig, default_agent_harness
17
+ from verifiers.v1.configs.cli.env import (
18
+ merge_env_defaults,
19
+ narrowed_env_annotation,
20
+ resolve_env_field,
21
+ )
22
+ from verifiers.v1.configs.env import EnvConfig, SharedEnvConfig, default_agent_harness
19
23
  from verifiers.v1.configs.harness import HarnessConfig
20
24
  from verifiers.v1.configs.judge import JudgeConfig, Judges
21
25
  from verifiers.v1.configs.retries import RetryConfig
@@ -30,7 +34,7 @@ from verifiers.v1.configs.task import (
30
34
  RewardFunctionConfig,
31
35
  TaskConfig,
32
36
  )
33
- from verifiers.v1.configs.taskset import TasksetConfig
37
+ from verifiers.v1.configs.taskset import SharedTasksetConfig, TasksetConfig
34
38
  from verifiers.v1.env import Env
35
39
  from verifiers.v1.envs.single_agent import SingleAgentEnv, SingleAgentEnvConfig
36
40
  from verifiers.v1.episode import (
@@ -286,6 +290,7 @@ __all__ = [ # noqa: RUF022 - grouped by public API area
286
290
  "Taskset",
287
291
  "TaskConfig",
288
292
  "TasksetConfig",
293
+ "SharedTasksetConfig",
289
294
  "DecoratedFunctionConfig",
290
295
  "RewardFunctionConfig",
291
296
  "BaseConfig",
@@ -309,8 +314,10 @@ __all__ = [ # noqa: RUF022 - grouped by public API area
309
314
  "Env",
310
315
  "SingleAgentEnv",
311
316
  "EnvConfig",
317
+ "SharedEnvConfig",
312
318
  "ServeConfig",
313
319
  "resolve_env_field",
320
+ "merge_env_defaults",
314
321
  "narrowed_env_annotation",
315
322
  "SingleAgentEnvConfig",
316
323
  "AgentConfig",
@@ -1,5 +1,5 @@
1
1
  """Run-config plumbing around the `[env]` block: narrowing the `env` field of
2
- every config that owns one.
2
+ every config that owns one, and layering shared env defaults under it.
3
3
 
4
4
  A run composes the blocks it needs — `[env]` (what runs, `configs/env.py`),
5
5
  `[serve]` (how it's hosted, `configs/serve.py`) — plus its own fields. Nothing here is a base class: the eval
@@ -10,11 +10,11 @@ single_agent_env_config)`. The `SerializeAsAny` is load-bearing: pydantic serial
10
10
  by declared type, so a plain `EnvConfig` silently drops a narrowed subclass's agents
11
11
  and knobs from `model_dump()` — the env-server wire's payload."""
12
12
 
13
- from pydantic import ValidationError
13
+ from pydantic import BaseModel, ValidationError
14
14
  from pydantic_config import BaseConfig
15
15
 
16
- from verifiers.v1.configs.env import EnvConfig
17
- from verifiers.v1.utils.generic import prefix_validation_error
16
+ from verifiers.v1.configs.env import EnvConfig, SharedEnvConfig
17
+ from verifiers.v1.utils.generic import deep_merge, prefix_validation_error
18
18
 
19
19
 
20
20
  def resolve_env_field(data: dict, narrowed: "type[EnvConfig] | None" = None) -> dict:
@@ -45,6 +45,32 @@ def resolve_env_field(data: dict, narrowed: "type[EnvConfig] | None" = None) ->
45
45
  return data
46
46
 
47
47
 
48
+ def merge_env_defaults(defaults: SharedEnvConfig, env: dict | None) -> dict:
49
+ """A raw `env` block over `defaults`, the knobs that several envs of one run share
50
+ (e.g. the retries of every eval source). Only the fields set in `defaults` apply,
51
+ and the env's own values win. A subtree whose `id`/`type` differs from the
52
+ default's is the env's alone, so one plugin's knobs never leak into another's."""
53
+ return deep_merge(_dump_set(defaults), env or {})
54
+
55
+
56
+ def _dump_set(config: BaseModel) -> dict:
57
+ """`config`'s set fields, including those set on a sub-config after construction
58
+ (which leaves the parent's field unmarked). Each dumped sub-config keeps its
59
+ `id`/`type` even at the default: `deep_merge` detects a plugin switch only when
60
+ both sides name it."""
61
+ dump = {}
62
+ for name in type(config).model_fields:
63
+ value = getattr(config, name)
64
+ if isinstance(value, BaseModel):
65
+ nested = _dump_set(value)
66
+ if nested or name in config.model_fields_set:
67
+ keys = [k for k in ("id", "type") if k in type(value).model_fields]
68
+ dump[name] = {**{k: getattr(value, k) for k in keys}, **nested}
69
+ elif name in config.model_fields_set:
70
+ dump[name] = config.model_dump(include={name})[name]
71
+ return dump
72
+
73
+
48
74
  def narrowed_env_annotation(cls) -> "type[EnvConfig] | None":
49
75
  """The env field's annotation when the CLI pre-narrowed it (`narrow_config`
50
76
  swaps in a concrete subclass). The base declaration reads as `EnvConfig` itself
@@ -1,5 +1,6 @@
1
1
  """An environment's config — the run's single `[env]` block: the seed taskset,
2
- each role as an `AgentConfig` field, and the env-level knobs."""
2
+ each role as an `AgentConfig` field, and the env-level knobs. `SharedEnvConfig` is
3
+ the part every env has."""
3
4
 
4
5
  from typing import get_args
5
6
 
@@ -13,7 +14,7 @@ from verifiers.v1.configs.agent import (
13
14
  )
14
15
  from verifiers.v1.configs.harness import HarnessConfig
15
16
  from verifiers.v1.configs.retries import RetryConfig
16
- from verifiers.v1.configs.taskset import TasksetConfig
17
+ from verifiers.v1.configs.taskset import SharedTasksetConfig, TasksetConfig
17
18
  from verifiers.v1.interception import ElasticInterceptionPoolConfig, InterceptionConfig
18
19
  from verifiers.v1.types import ID
19
20
 
@@ -34,18 +35,12 @@ def _mentions_agent_config(annotation) -> bool:
34
35
  return any(_mentions_agent_config(arg) for arg in get_args(annotation))
35
36
 
36
37
 
37
- class EnvConfig(BaseConfig):
38
- """An environment's config — the run's single `[env]` block, one subclass per
39
- `Env` class (bound via `Env[YourConfig]`): each role is an
40
- `AgentConfig` field with a default instance, plus env-level knobs. The run's `env`
41
- field narrows to it by env `id` (else taskset id) — `--env.<role>.model` addressing."""
38
+ class SharedEnvConfig(BaseConfig):
39
+ """The env knobs every env has, whatever its id and agents — what several envs of
40
+ one run can share. `EnvConfig` adds the env `id`, the taskset `id`, and the agents."""
42
41
 
43
- id: ID = ""
44
- """Which `Env` runs. Empty = the taskset's own, else `SingleAgentEnv`; set
45
- to pair a reusable env with any taskset (an explicit id wins over the bundled)."""
46
- # SerializeAsAny: the env-server wire needs the resolved subclass's fields.
47
- taskset: SerializeAsAny[TasksetConfig] = TasksetConfig()
48
- """The seed taskset — the rows every rollout starts from (`--env.taskset.id`)."""
42
+ taskset: SharedTasksetConfig = SharedTasksetConfig()
43
+ """The taskset knobs every taskset has."""
49
44
  timeout: TimeoutConfig = TimeoutConfig()
50
45
  retries: RetryConfig = RetryConfig()
51
46
  """Whole-EPISODE retries — the coarse fallback for faults no agent owns; a
@@ -63,6 +58,20 @@ class EnvConfig(BaseConfig):
63
58
  interception: InterceptionConfig = ElasticInterceptionPoolConfig()
64
59
  """The interception shape: `elastic` (default), `server`, or `static`."""
65
60
 
61
+
62
+ class EnvConfig(SharedEnvConfig):
63
+ """An environment's config — the run's single `[env]` block, one subclass per
64
+ `Env` class (bound via `Env[YourConfig]`): each role is an
65
+ `AgentConfig` field with a default instance, plus env-level knobs. The run's `env`
66
+ field narrows to it by env `id` (else taskset id) — `--env.<role>.model` addressing."""
67
+
68
+ id: ID = ""
69
+ """Which `Env` runs. Empty = the taskset's own, else `SingleAgentEnv`; set
70
+ to pair a reusable env with any taskset (an explicit id wins over the bundled)."""
71
+ # SerializeAsAny: the env-server wire needs the resolved subclass's fields.
72
+ taskset: SerializeAsAny[TasksetConfig] = TasksetConfig()
73
+ """The seed taskset — the rows every rollout starts from (`--env.taskset.id`)."""
74
+
66
75
  @property
67
76
  def env_id(self) -> str:
68
77
  """The taskset id, prefixed by the paired env id (`best-of-n+gsm8k-v1`)."""
@@ -9,16 +9,22 @@ from verifiers.v1.configs.task import TaskConfig
9
9
  from verifiers.v1.types import ID
10
10
 
11
11
 
12
- class TasksetConfig(BaseConfig):
13
- id: ID = ""
14
- """Installed taskset package, set with `--env.taskset.id` (or the
15
- positional `eval <taskset-id>`)."""
12
+ class SharedTasksetConfig(BaseConfig):
13
+ """The knobs every taskset has, whatever its id — what several tasksets of one run
14
+ can share."""
15
+
16
16
  task: SerializeAsAny[TaskConfig] = TaskConfig()
17
17
  """Config passed to each task, under `--env.taskset.task.*`."""
18
18
  system_prompt: Path | None = None
19
19
  """File whose text overrides each task's `TaskData.system_prompt` on
20
20
  iteration (e.g. a GEPA `best_system_prompt.txt`)."""
21
21
 
22
+
23
+ class TasksetConfig(SharedTasksetConfig):
24
+ id: ID = ""
25
+ """Installed taskset package, set with `--env.taskset.id` (or the
26
+ positional `eval <taskset-id>`)."""
27
+
22
28
  @property
23
29
  def name(self) -> str:
24
30
  return self.id
@@ -272,6 +272,7 @@ class Env(ABC, Generic[ConfigT]):
272
272
  f"{type(self).__name__}.run() exceeded its "
273
273
  f"{self.config.timeout.episode:g}s deadline (--env.timeout.episode)"
274
274
  )
275
+ episode.is_timeout = True
275
276
  episode.errors.append(_as_error(e))
276
277
  # The completed subset is the crash-safe episode; ok stays False.
277
278
  return episode
@@ -286,6 +287,7 @@ class Env(ABC, Generic[ConfigT]):
286
287
  f"{type(self).__name__}.finalize() exceeded its "
287
288
  f"{self.config.timeout.finalize:g}s deadline (--env.timeout.finalize)"
288
289
  )
290
+ episode.is_timeout = True
289
291
  episode.errors.append(_as_error(e))
290
292
  return episode
291
293
  # Both hooks and every trace concluded — stamp the attempt's verdict
@@ -99,6 +99,9 @@ class Episode(BaseModel, Generic[DataT, StateT, AgentConfigT]):
99
99
  """The run this episode belongs to, consumer-stamped."""
100
100
  ok: bool = False
101
101
  """Whether the episode completed successfully."""
102
+ is_timeout: bool = False
103
+ """Whether the env's own `run()`/`finalize()` deadline expired; a per-agent
104
+ stage deadline flags its trace (`Trace.is_timeout`)."""
102
105
  errors: list[Error] = Field(default_factory=list)
103
106
  """Every error captured across attempts, oldest to newest."""
104
107
  traces: list[Trace[DataT, StateT, AgentConfigT]] = Field(default_factory=list)
@@ -77,8 +77,9 @@ async def boundary(error_cls: type[RolloutError], what: str) -> AsyncIterator[No
77
77
  """Run a framework→code boundary, attributing any error escaping it to `error_cls`. An
78
78
  already-typed `RolloutError` passes through unchanged — it crossed a more specific boundary
79
79
  first (e.g. a `SandboxError` from `runtime.run` inside a reward stays a `SandboxError`). A
80
- `TimeoutError` (the stage exceeded its budget) becomes `error_cls` too. `what` names the
81
- boundary in the error message."""
80
+ `TimeoutError` the code raises itself (its own I/O) becomes `error_cls` too; a stage
81
+ deadline wraps the boundary from outside, so its expiry is a timeout, not an error.
82
+ `what` names the boundary in the error message."""
82
83
  try:
83
84
  yield
84
85
  except RolloutError:
@@ -174,6 +174,12 @@ class Rollout:
174
174
  self._failure = error
175
175
  self.trace.record_error(error)
176
176
 
177
+ def timeout(self, stage: str) -> None:
178
+ """Record `stage`'s expired deadline as this rollout's outcome: a stop, not
179
+ a failure — no further segments run, but finalize and scoring still do."""
180
+ logger.info("rollout %s: %s timeout", self.trace.id, stage)
181
+ self.trace.record_timeout(stage)
182
+
177
183
  async def open(self) -> bool:
178
184
  """Boot the rollout's world up to the point where segments can run: start
179
185
  (or borrow) the runtime, run task + harness setup, bring up the
@@ -202,6 +208,8 @@ class Rollout:
202
208
  self.harness.config.name,
203
209
  self.runtime_config.type,
204
210
  )
211
+ loop = asyncio.get_running_loop()
212
+ setup_deadline: float | None = None
205
213
  try:
206
214
  runtime_env = dict(self.task.runtime_env())
207
215
  if self._borrowed_runtime is None:
@@ -226,16 +234,16 @@ class Rollout:
226
234
  setup_deadline = (
227
235
  None
228
236
  if self._timeouts.setup is None
229
- else asyncio.get_running_loop().time() + self._timeouts.setup
237
+ else loop.time() + self._timeouts.setup
230
238
  )
231
239
  async with (
232
- boundary(TaskError, "task setup"),
233
240
  asyncio.timeout_at(setup_deadline),
241
+ boundary(TaskError, "task setup"),
234
242
  ):
235
243
  await invoke(self.task.setup, {"trace": self.trace, "runtime": runtime})
236
244
  async with (
237
- boundary(HarnessError, "harness setup"),
238
245
  asyncio.timeout_at(setup_deadline),
246
+ boundary(HarnessError, "harness setup"),
239
247
  ):
240
248
  await self.harness.setup(runtime)
241
249
  async with boundary(ToolsetError, "building tool servers"):
@@ -273,8 +281,8 @@ class Rollout:
273
281
  # execution policy while preserving the framework routes the agent uses.
274
282
  await runtime.prepare_execution([self._endpoint, *self._urls.values()])
275
283
  async with (
276
- boundary(HarnessError, "opening harness session"),
277
284
  asyncio.timeout_at(setup_deadline),
285
+ boundary(HarnessError, "opening harness session"),
278
286
  ):
279
287
  harness_data = self.trace.task.data
280
288
  if (
@@ -340,6 +348,14 @@ class Rollout:
340
348
  harness_data,
341
349
  **session_kwargs,
342
350
  )
351
+ except TimeoutError as e:
352
+ # The setup deadline's own expiry is a timeout; a TimeoutError with no
353
+ # expired deadline (a runtime's own I/O) stays the raw failure.
354
+ if setup_deadline is not None and loop.time() >= setup_deadline:
355
+ self.timeout("setup")
356
+ else:
357
+ self.fail(e)
358
+ return False
343
359
  except Exception as e: # noqa: BLE001 - setup boundary records every rollout failure
344
360
  self.fail(e)
345
361
  return False
@@ -390,16 +406,11 @@ class Rollout:
390
406
  return False
391
407
  await self._harness_session.turn(messages)
392
408
  except TimeoutError as e:
393
- # An expired rollout deadline is the agent breaking its time budget —
394
- # an agent failure, never a clean stop. A TimeoutError from the
395
- # harness's own I/O with no expired deadline stays the raw failure.
409
+ # An expired rollout deadline is the agent breaking its time budget: a
410
+ # timeout stop. A TimeoutError from the harness's own I/O with no
411
+ # expired deadline stays the raw failure.
396
412
  if self.deadline_at is not None and (loop.time() >= self.deadline_at):
397
- self.fail(
398
- HarnessError(
399
- f"agent timeout: rollout exceeded its "
400
- f"{self._timeouts.agent:g}s budget"
401
- )
402
- )
413
+ self.timeout("agent")
403
414
  else:
404
415
  self.fail(e)
405
416
  return False
@@ -479,8 +490,11 @@ class Rollout:
479
490
  if not self._failed and self._opened:
480
491
  assert runtime is not None
481
492
  trace.timing.finalize.start = time.time()
482
- async with boundary(TaskError, "task finalize"):
483
- async with asyncio.timeout(self._timeouts.finalize):
493
+ try:
494
+ async with (
495
+ asyncio.timeout(self._timeouts.finalize),
496
+ boundary(TaskError, "task finalize"),
497
+ ):
484
498
  await invoke(
485
499
  self.task.finalize, {"trace": trace, "runtime": runtime}
486
500
  )
@@ -490,19 +504,24 @@ class Rollout:
490
504
  self.task.data.artifacts,
491
505
  max_bytes=self.task.data.artifact_max_bytes,
492
506
  )
507
+ except TimeoutError:
508
+ self.timeout("finalize")
493
509
  now = time.time()
494
510
  trace.timing.finalize.end = now
495
511
  trace.timing.scoring.start = now
496
512
  trace.notify()
497
- async with boundary(TaskError, "scoring"):
498
- # Cross-trace judgement runs later, after the runtime is gone.
499
- await asyncio.wait_for(
500
- asyncio.gather(
513
+ try:
514
+ async with (
515
+ asyncio.timeout(self._timeouts.scoring),
516
+ boundary(TaskError, "scoring"),
517
+ ):
518
+ # Cross-trace judgement runs later, after the runtime is gone.
519
+ await asyncio.gather(
501
520
  self.task.score(trace, runtime),
502
521
  self.harness.score(trace, runtime),
503
- ),
504
- self._timeouts.scoring,
505
- )
522
+ )
523
+ except TimeoutError:
524
+ self.timeout("scoring")
506
525
  trace.timing.scoring.end = time.time()
507
526
  trace.notify()
508
527
  except Exception as e: # noqa: BLE001 - finalize boundary records every rollout failure
@@ -64,6 +64,7 @@ SCALAR_FIELDS = (
64
64
  "is_completed",
65
65
  "ok",
66
66
  "stop_condition",
67
+ "is_timeout",
67
68
  "timing",
68
69
  "num_input_tokens",
69
70
  "num_output_tokens",
@@ -444,6 +444,8 @@ class Trace(BaseModel, Generic[DataT, StateT, AgentConfigT]):
444
444
  """Whether the trace completed successfully."""
445
445
  stop_condition: str | None = None
446
446
  """What stopped the trace."""
447
+ is_timeout: bool = False
448
+ """Whether a stage deadline (setup, agent, finalize, or scoring) expired."""
447
449
  errors: list[Error] = Field(default_factory=list)
448
450
  """Every error captured across attempts, oldest to newest."""
449
451
  timing: Timing = Field(default_factory=Timing)
@@ -755,10 +757,11 @@ class Trace(BaseModel, Generic[DataT, StateT, AgentConfigT]):
755
757
  if response.usage is not None:
756
758
  self.extra_usage.append(response.usage)
757
759
 
758
- def stop(self, condition: str) -> None:
759
- """Stop the trace, optionally with a stop condition."""
760
+ def stop(self, condition: str, override: bool = False) -> None:
761
+ """Stop the trace with a stop condition. The first condition wins unless
762
+ `override` replaces it."""
760
763
  self.is_completed = True
761
- if self.stop_condition is None:
764
+ if override or self.stop_condition is None:
762
765
  self.stop_condition = condition
763
766
 
764
767
  def split_agent_time(self) -> None:
@@ -770,6 +773,13 @@ class Trace(BaseModel, Generic[DataT, StateT, AgentConfigT]):
770
773
  span.model.duration = min(model, span.duration)
771
774
  span.harness.duration = span.duration - span.model.duration
772
775
 
776
+ def record_timeout(self, stage: str) -> None:
777
+ """Record a stage deadline's expiry, and stop the trace as `<stage>_timeout`.
778
+ The deadline is what ended the trace, so it replaces any earlier stop
779
+ condition (a finalize deadline can expire after `agent_completed`)."""
780
+ self.is_timeout = True
781
+ self.stop(f"{stage}_timeout", override=True)
782
+
773
783
  def record_error(self, error: Exception) -> None:
774
784
  """Record an error, and stop the trace as failed."""
775
785
  self.errors.append(