verifiers 0.4.1.dev56__tar.gz → 0.4.1.dev58__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 (277) hide show
  1. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/PKG-INFO +1 -1
  2. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/pyproject.toml +2 -0
  3. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/__init__.py +2 -0
  4. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/envs/agentic_judge/env.py +9 -9
  5. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/errors.py +5 -0
  6. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/judges/rubric.py +69 -24
  7. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/rollout.py +17 -0
  8. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/.gitignore +0 -0
  9. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/LICENSE +0 -0
  10. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/README.md +0 -0
  11. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/conftest.py +0 -0
  12. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/agent_user.py +0 -0
  13. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/agent_user_harness.py +0 -0
  14. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/counter_tool.py +0 -0
  15. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/duet.py +0 -0
  16. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo.py +0 -0
  17. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_acp_resume.py +0 -0
  18. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_agentic.py +0 -0
  19. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_tool.py +0 -0
  20. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_tool_compose/docker-compose.yaml +0 -0
  21. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_user_sim.py +0 -0
  22. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/fetch_tool.py +0 -0
  23. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/network_policy.py +0 -0
  24. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/parallel.py +0 -0
  25. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/pyproject.toml +0 -0
  26. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/skill_codeword.py +0 -0
  27. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/skills/project-codeword/SKILL.md +0 -0
  28. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/fixtures/tool_response_image.py +0 -0
  29. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/grid.py +0 -0
  30. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_agent_user.py +0 -0
  31. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_agentic_judge.py +0 -0
  32. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_compose_scoring.py +0 -0
  33. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_examples.py +0 -0
  34. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_limits.py +0 -0
  35. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_multi_agent.py +0 -0
  36. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_multi_turn.py +0 -0
  37. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_multi_turn_tool.py +0 -0
  38. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_multimodal_tool.py +0 -0
  39. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_network_policy.py +0 -0
  40. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_parallel.py +0 -0
  41. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_resume_tool.py +0 -0
  42. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_rubric_judge.py +0 -0
  43. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_sampling.py +0 -0
  44. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_scoring_network.py +0 -0
  45. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_shared_tool.py +0 -0
  46. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_single_turn.py +0 -0
  47. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_skills.py +0 -0
  48. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_stateful_tool.py +0 -0
  49. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_tool_vms.py +0 -0
  50. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_user_echo.py +0 -0
  51. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/integration/test_user_sim.py +0 -0
  52. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/cli/test_replay.py +0 -0
  53. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/conftest.py +0 -0
  54. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/harnesses/test_core.py +0 -0
  55. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/harnesses/test_rlm.py +0 -0
  56. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/interception/test_tunnel.py +0 -0
  57. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/judges/conftest.py +0 -0
  58. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/judges/test_judge.py +0 -0
  59. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/judges/test_reference.py +0 -0
  60. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/judges/test_rubric.py +0 -0
  61. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/runtimes/test_private_network.py +0 -0
  62. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/serve/test_client.py +0 -0
  63. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/serve/test_delta.py +0 -0
  64. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/serve/test_pool.py +0 -0
  65. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/test_agent.py +0 -0
  66. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/test_dialects.py +0 -0
  67. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/test_graph.py +0 -0
  68. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/test_harbor_grading_network.py +0 -0
  69. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/test_runtimes.py +0 -0
  70. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/test_scoring_network.py +0 -0
  71. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/test_semantic.py +0 -0
  72. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/test_task.py +0 -0
  73. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/test_taskset.py +0 -0
  74. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/test_trace.py +0 -0
  75. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/utils/test_compile.py +0 -0
  76. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/utils/test_loaders.py +0 -0
  77. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/utils/test_platform.py +0 -0
  78. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/tests/unit/utils/test_score.py +0 -0
  79. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/__init__.py +0 -0
  80. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/acp/__init__.py +0 -0
  81. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/acp/runner.py +0 -0
  82. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/agent.py +0 -0
  83. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/__init__.py +0 -0
  84. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/dashboard/__init__.py +0 -0
  85. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/dashboard/base.py +0 -0
  86. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/dashboard/eval.py +0 -0
  87. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/dashboard/replay.py +0 -0
  88. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/dashboard/validate.py +0 -0
  89. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/debug.py +0 -0
  90. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/eval/__init__.py +0 -0
  91. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/eval/hint.py +0 -0
  92. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/eval/main.py +0 -0
  93. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/eval/resume.py +0 -0
  94. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/eval/runner.py +0 -0
  95. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/gepa.py +0 -0
  96. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/output.py +0 -0
  97. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/replay.py +0 -0
  98. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/resolve.py +0 -0
  99. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/resume.py +0 -0
  100. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/cli/validate.py +0 -0
  101. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/clients/__init__.py +0 -0
  102. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/clients/base.py +0 -0
  103. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/clients/client.py +0 -0
  104. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/clients/eval.py +0 -0
  105. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/clients/train.py +0 -0
  106. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/__init__.py +0 -0
  107. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/agent.py +0 -0
  108. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/__init__.py +0 -0
  109. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/debug.py +0 -0
  110. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/env.py +0 -0
  111. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/eval.py +0 -0
  112. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/replay.py +0 -0
  113. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/validate.py +0 -0
  114. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/client.py +0 -0
  115. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/env.py +0 -0
  116. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/harness.py +0 -0
  117. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/judge.py +0 -0
  118. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/retries.py +0 -0
  119. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/runtime.py +0 -0
  120. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/scoring.py +0 -0
  121. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/select.py +0 -0
  122. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/serve.py +0 -0
  123. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/task.py +0 -0
  124. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/configs/taskset.py +0 -0
  125. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/dialects/__init__.py +0 -0
  126. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/dialects/anthropic.py +0 -0
  127. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/dialects/base.py +0 -0
  128. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/dialects/chat.py +0 -0
  129. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/dialects/responses.py +0 -0
  130. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/env.py +0 -0
  131. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/envs/__init__.py +0 -0
  132. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
  133. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
  134. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/envs/best_of_n/env.py +0 -0
  135. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/envs/single_agent/__init__.py +0 -0
  136. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/envs/single_agent/env.py +0 -0
  137. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/envs/user_sim/__init__.py +0 -0
  138. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/envs/user_sim/env.py +0 -0
  139. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/episode.py +0 -0
  140. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/__init__.py +0 -0
  141. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/adapter.py +0 -0
  142. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/config.py +0 -0
  143. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/dataset.py +0 -0
  144. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/reflection.py +0 -0
  145. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/runner.py +0 -0
  146. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/grading.py +0 -0
  147. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/graph.py +0 -0
  148. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harness.py +0 -0
  149. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/__init__.py +0 -0
  150. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/bash/__init__.py +0 -0
  151. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/bash/harness.py +0 -0
  152. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
  153. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
  154. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/browser_use/program.py +0 -0
  155. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
  156. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
  157. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/codex/__init__.py +0 -0
  158. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
  159. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/codex/harness.py +0 -0
  160. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/deepseek/__init__.py +0 -0
  161. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/deepseek/gate.mjs +0 -0
  162. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/deepseek/harness.py +0 -0
  163. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/deepseek/usage.mjs +0 -0
  164. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
  165. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
  166. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
  167. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
  168. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
  169. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
  170. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
  171. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
  172. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/node.py +0 -0
  173. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/null/__init__.py +0 -0
  174. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/null/harness.py +0 -0
  175. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
  176. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
  177. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/opencode/__init__.py +0 -0
  178. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/opencode/harness.py +0 -0
  179. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/opencode/mcp-ready.js +0 -0
  180. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/pi/__init__.py +0 -0
  181. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
  182. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/pi/harness.py +0 -0
  183. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
  184. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
  185. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
  186. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/rlm/harness.py +0 -0
  187. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
  188. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
  189. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
  190. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/__init__.py +0 -0
  191. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/compaction.py +0 -0
  192. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/core.py +0 -0
  193. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/install.py +0 -0
  194. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/launch.py +0 -0
  195. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/mcp.py +0 -0
  196. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/replay.py +0 -0
  197. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/interception/__init__.py +0 -0
  198. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/interception/base.py +0 -0
  199. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/interception/pool.py +0 -0
  200. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/interception/server.py +0 -0
  201. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/interception/tunnel/__init__.py +0 -0
  202. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/interception/tunnel/base.py +0 -0
  203. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/interception/tunnel/custom.py +0 -0
  204. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/interception/tunnel/prime.py +0 -0
  205. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/judge.py +0 -0
  206. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/judges/__init__.py +0 -0
  207. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/judges/decision.py +0 -0
  208. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/judges/reference.py +0 -0
  209. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/judges/reference.txt +0 -0
  210. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/judges/rubric.txt +0 -0
  211. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/mcp/__init__.py +0 -0
  212. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/mcp/launch.py +0 -0
  213. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/mcp/server.py +0 -0
  214. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/mcp/toolset.py +0 -0
  215. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/__init__.py +0 -0
  216. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/backends/custom.py +0 -0
  217. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/backends/docker.py +0 -0
  218. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/backends/prime.py +0 -0
  219. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/backends/subprocess.py +0 -0
  220. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/base.py +0 -0
  221. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/compose.py +0 -0
  222. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/deployment.py +0 -0
  223. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/egress.py +0 -0
  224. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/limiters.py +0 -0
  225. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/private_network.py +0 -0
  226. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/runtime.py +0 -0
  227. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/strategies.py +0 -0
  228. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/semantic.py +0 -0
  229. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/serve/__init__.py +0 -0
  230. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/serve/client.py +0 -0
  231. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/serve/delta.py +0 -0
  232. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/serve/encoding.py +0 -0
  233. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/serve/pool.py +0 -0
  234. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/serve/server.py +0 -0
  235. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/serve/types.py +0 -0
  236. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/session.py +0 -0
  237. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/state.py +0 -0
  238. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/task.py +0 -0
  239. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/taskset.py +0 -0
  240. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/__init__.py +0 -0
  241. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
  242. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
  243. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
  244. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
  245. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
  246. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
  247. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
  248. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
  249. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
  250. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
  251. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
  252. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
  253. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/trace.py +0 -0
  254. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/types.py +0 -0
  255. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/__init__.py +0 -0
  256. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/aio.py +0 -0
  257. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/artifacts.py +0 -0
  258. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/compile.py +0 -0
  259. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/decorators.py +0 -0
  260. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/env.py +0 -0
  261. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/eval.py +0 -0
  262. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/format.py +0 -0
  263. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/generic.py +0 -0
  264. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/git.py +0 -0
  265. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/image.py +0 -0
  266. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/interrupt.py +0 -0
  267. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/loaders.py +0 -0
  268. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/logging.py +0 -0
  269. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/memory.py +0 -0
  270. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/paths.py +0 -0
  271. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/platform.py +0 -0
  272. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/prime.py +0 -0
  273. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/retries.py +0 -0
  274. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/scope.py +0 -0
  275. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/score.py +0 -0
  276. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/verifiers/v1/utils/trace_store.py +0 -0
  277. {verifiers-0.4.1.dev56 → verifiers-0.4.1.dev58}/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.dev56
3
+ Version: 0.4.1.dev58
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
@@ -131,6 +131,8 @@ bash-interception = { path = "environments/bash_interception", editable = true }
131
131
  web-search-interception = { path = "environments/web_search_interception", editable = true }
132
132
 
133
133
  [tool.uv.exclude-newer-package]
134
+ # CA bundle: security fixes (e.g. 2026.10.19 for the eMudhra compromise) must not wait out the cooldown
135
+ certifi = false
134
136
  # Bounded cutoffs for the explicitly requested tool upgrades.
135
137
  # Full UTC timestamps: bare dates resolve to local-tz midnight and churn the
136
138
  # lockfile across timezones.
@@ -60,6 +60,7 @@ from verifiers.v1.errors import (
60
60
  TaskError,
61
61
  ToolsetError,
62
62
  TunnelError,
63
+ UnscoredError,
63
64
  )
64
65
  from verifiers.v1.grading import grade_submission
65
66
  from verifiers.v1.graph import MessageNode
@@ -283,6 +284,7 @@ __all__ = [ # noqa: RUF022 - grouped by public API area
283
284
  "ToolsetError",
284
285
  "SandboxError",
285
286
  "TaskError",
287
+ "UnscoredError",
286
288
  "InterceptionError",
287
289
  "TunnelError",
288
290
  # clients
@@ -18,8 +18,10 @@ from verifiers.v1.configs.scoring import resolve_scoring
18
18
  from verifiers.v1.judges.rubric import (
19
19
  Criterion,
20
20
  RubricVerdicts,
21
+ criterion_metrics,
21
22
  load_criteria,
22
23
  score_verdicts,
24
+ weighted_score,
23
25
  )
24
26
  from verifiers.v1.utils.compile import validate_pairing
25
27
 
@@ -45,10 +47,7 @@ SOLVED = Criterion(
45
47
 
46
48
 
47
49
  def _verdict_section(criteria: list[Criterion]) -> str:
48
- listing = "\n".join(
49
- f"- {c.name}: {c.text} (answer one of, worst to best: {', '.join(c.choices)})"
50
- for c in criteria
51
- )
50
+ listing = "\n".join(c.render() for c in criteria)
52
51
  return f"""\
53
52
  ## Your verdict
54
53
 
@@ -300,15 +299,16 @@ class AgenticJudgeEnv(vf.Env[AgenticJudgeEnvConfig]):
300
299
  verdicts = RubricVerdicts.model_validate(verdict.info.get("verdict")).verdicts
301
300
  criteria = self.config.task.criteria()
302
301
  scores = score_verdicts(verdicts, criteria, "the rubric's")
303
- for criterion in criteria:
304
- solution.record_metric(f"judge/{criterion.name}", scores[criterion.name])
302
+ solution.record_metrics(criterion_metrics("judge", verdicts, criteria, scores))
305
303
  if self.config.score.task_weight != 1.0:
306
304
  for reward in solution.rewards.values():
307
305
  if reward is not None:
308
306
  reward.weight *= self.config.score.task_weight
309
- total = sum(criterion.weight for criterion in criteria)
310
- reward = sum(c.weight * scores[c.name] for c in criteria) / total
311
- solution.record_reward("judge", reward, weight=self.config.score.judge_weight)
307
+ solution.record_reward(
308
+ "judge",
309
+ weighted_score(scores, criteria),
310
+ weight=self.config.score.judge_weight,
311
+ )
312
312
 
313
313
  async def run(self, task: vf.Task, agents: vf.Agents) -> None:
314
314
  policy = resolve_scoring(task.scoring, self.config.solver.scoring)
@@ -69,6 +69,11 @@ class TaskError(RolloutError):
69
69
  """Task-authored code raised — `setup`, `finalize`, or a `@reward`/`@metric`."""
70
70
 
71
71
 
72
+ class UnscoredError(RolloutError):
73
+ """Scoring completed but a reward came out `nan`, e.g. a judge's answer that scores
74
+ nothing: the rollout carries no reward signal, so consumers drop it like a failure."""
75
+
76
+
72
77
  class InterceptionError(RolloutError):
73
78
  """Communication with the host interception server failed."""
74
79
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  import asyncio
4
4
  import json
5
+ import math
5
6
  import re
6
7
  import tomllib
7
8
  from functools import cached_property
@@ -35,10 +36,6 @@ JSON_SUFFIX = (
35
36
  )
36
37
 
37
38
 
38
- def normalize_choice(choice: str, choices: list[str]) -> float:
39
- return choices.index(choice) / (len(choices) - 1)
40
-
41
-
42
39
  def first_verdicts_object(text: str) -> dict | None:
43
40
  """The first balanced JSON object in `text` that carries a `verdicts` key. Scanning for the
44
41
  key (not just the first `{`) skips prose and, crucially, an echoed format example — the one
@@ -63,17 +60,44 @@ class Criterion(BaseModel):
63
60
  text: str
64
61
  weight: CriterionWeight = 1.0
65
62
  """The criterion's share of the reward (overridable per name via `weights` in config)."""
66
- choices: list[str] = Field(default_factory=lambda: ["no", "yes"], min_length=2)
67
- """Allowed answers, ordered **worst → best**: the first scores 0.0, the last 1.0, the rest
68
- evenly spaced by rank. Default `["no", "yes"]` is a binary check. Needs >= 2, no duplicates."""
63
+ choices: list[str] | dict[str, float] = Field(
64
+ default_factory=lambda: ["no", "yes"], min_length=2
65
+ )
66
+ """Allowed answers. A list is ordered **worst → best**: the first scores 0.0, the last 1.0,
67
+ the rest evenly spaced by rank. A mapping gives each answer its own finite score, in any
68
+ order; `nan` scores nothing, which leaves the rollout unscored when the criterion
69
+ carries weight. Default `["no", "yes"]` is a binary check. Needs >= 2, no duplicates."""
69
70
 
70
71
  @field_validator("choices")
71
72
  @classmethod
72
- def _check_choices(cls, v: list[str]) -> list[str]:
73
- if len(set(v)) != len(v):
73
+ def _check_choices(
74
+ cls, v: list[str] | dict[str, float]
75
+ ) -> list[str] | dict[str, float]:
76
+ if isinstance(v, list) and len(set(v)) != len(v):
74
77
  raise ValueError(f"`choices` has duplicate options: {v}")
78
+ if isinstance(v, dict) and any(math.isinf(score) for score in v.values()):
79
+ raise ValueError(f"`choices` scores must be finite or nan: {v}")
75
80
  return v
76
81
 
82
+ def score(self, choice: str) -> float:
83
+ """The score of `choice`, one of `choices`; `nan` when it scores nothing."""
84
+ if isinstance(self.choices, dict):
85
+ return self.choices[choice]
86
+ return self.choices.index(choice) / (len(self.choices) - 1)
87
+
88
+ def render(self) -> str:
89
+ """The criterion as a prompt line, with its allowed answers."""
90
+ order = "" if isinstance(self.choices, dict) else ", worst to best"
91
+ return f"- {self.name}: {self.text} (answer one of{order}: {', '.join(self.choices)})"
92
+
93
+
94
+ def weighted_score(scores: dict[str, float], criteria: list[Criterion]) -> float:
95
+ """The criteria's weighted mean score; `nan` when a weighted criterion scored nothing.
96
+ Zero-weight criteria never contribute, not even their `nan`."""
97
+ weighted = [c for c in criteria if c.weight]
98
+ total = sum(c.weight for c in weighted)
99
+ return sum(c.weight * scores[c.name] for c in weighted) / total
100
+
77
101
 
78
102
  CRITERIA_ADAPTER = TypeAdapter(list[Criterion])
79
103
 
@@ -174,15 +198,38 @@ def score_verdicts(
174
198
  )
175
199
  scores: dict[str, float] = {}
176
200
  for name, answer in answers.items():
177
- choices = by_criterion[name].choices
178
- if answer not in choices:
201
+ criterion = by_criterion[name]
202
+ if answer not in criterion.choices:
179
203
  raise ValueError(
180
- f"judge answered {answer!r} for '{name}', expected one of {choices}"
204
+ f"judge answered {answer!r} for '{name}', expected one of "
205
+ f"{list(criterion.choices)}"
181
206
  )
182
- scores[name] = normalize_choice(answer, choices)
207
+ scores[name] = criterion.score(answer)
183
208
  return scores
184
209
 
185
210
 
211
+ def criterion_metrics(
212
+ prefix: str,
213
+ verdicts: list[CriterionVerdict],
214
+ criteria: list[Criterion],
215
+ scores: dict[str, float],
216
+ ) -> dict[str, float]:
217
+ """Each criterion's score as `<prefix>/<name>`, unless it scored nothing, and for a
218
+ criterion with scored choices (a mapping) an indicator per choice, `<prefix>/<name>/<choice>`,
219
+ since several choices can share a score."""
220
+ answers = {verdict.name: verdict.verdict for verdict in verdicts}
221
+ metrics: dict[str, float] = {}
222
+ for criterion in criteria:
223
+ if not math.isnan(scores[criterion.name]):
224
+ metrics[f"{prefix}/{criterion.name}"] = scores[criterion.name]
225
+ if isinstance(criterion.choices, dict):
226
+ for choice in criterion.choices:
227
+ metrics[f"{prefix}/{criterion.name}/{choice}"] = float(
228
+ answers[criterion.name] == choice
229
+ )
230
+ return metrics
231
+
232
+
186
233
  class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
187
234
  prompt = RUBRIC_PROMPT
188
235
  schema = RubricVerdicts
@@ -194,9 +241,6 @@ class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
194
241
  async def grade_batch(
195
242
  self, task: TaskData, trace: Trace, batch: list[Criterion]
196
243
  ) -> dict[str, float]:
197
- def render(c: Criterion) -> str:
198
- return f"- {c.name}: {c.text} (answer one of, worst to best: {', '.join(c.choices)})"
199
-
200
244
  reference = ""
201
245
  if self.config.answer_field:
202
246
  answer = getattr(task, self.config.answer_field, None)
@@ -222,7 +266,7 @@ class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
222
266
  fields = {
223
267
  "question": judge_question(task, self.config.question_field),
224
268
  "response": judge_response(trace, self.config.view),
225
- "criteria": "\n".join(render(c) for c in batch),
269
+ "criteria": "\n".join(c.render() for c in batch),
226
270
  "reference": reference,
227
271
  }
228
272
  if self.config.structured_output:
@@ -238,7 +282,11 @@ class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
238
282
  )
239
283
  verdicts = RubricVerdicts.model_validate(obj).verdicts
240
284
  # A malformed verdict is a judge failure and must error the rollout, not score the model.
241
- return score_verdicts(verdicts, batch, "the batch's")
285
+ scores = score_verdicts(verdicts, batch, "the batch's")
286
+ trace.record_metrics(
287
+ criterion_metrics(self.reward_name, verdicts, batch, scores)
288
+ )
289
+ return scores
242
290
 
243
291
  async def score(self, task: TaskData, trace: Trace) -> float:
244
292
  criteria = self.criteria
@@ -264,12 +312,7 @@ class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
264
312
  by_name: dict[str, float] = {}
265
313
  for batch_verdicts in results:
266
314
  by_name.update(batch_verdicts)
267
- for criterion in criteria:
268
- trace.record_metric(
269
- f"{self.reward_name}/{criterion.name}", by_name[criterion.name]
270
- )
271
- total = sum(criterion.weight for criterion in criteria)
272
- return sum(c.weight * by_name[c.name] for c in criteria) / total
315
+ return weighted_score(by_name, criteria)
273
316
 
274
317
 
275
318
  __all__ = [
@@ -278,4 +321,6 @@ __all__ = [
278
321
  "RubricJudge",
279
322
  "RubricJudgeConfig",
280
323
  "RubricVerdicts",
324
+ "criterion_metrics",
325
+ "weighted_score",
281
326
  ]
@@ -3,6 +3,7 @@
3
3
  import asyncio
4
4
  import contextlib
5
5
  import logging
6
+ import math
6
7
  import time
7
8
  from collections.abc import Awaitable, Callable
8
9
  from contextlib import AsyncExitStack
@@ -19,6 +20,7 @@ from verifiers.v1.errors import (
19
20
  SandboxError,
20
21
  TaskError,
21
22
  ToolsetError,
23
+ UnscoredError,
22
24
  boundary,
23
25
  )
24
26
  from verifiers.v1.grading import (
@@ -908,6 +910,21 @@ class Rollout:
908
910
  # the metrics read what it handed over and left behind.
909
911
  await self._close_harness()
910
912
  await self._score_harness(runtime, self._metrics_deadline())
913
+ # A nan reward scores nothing: keep it unscored (None) and fail the
914
+ # rollout after scoring, so it is never retried as a scoring failure.
915
+ unscored = [
916
+ name
917
+ for name, reward in trace.rewards.items()
918
+ if reward is not None and math.isnan(reward.score)
919
+ ]
920
+ if unscored:
921
+ for name in unscored:
922
+ trace.rewards[name] = None
923
+ self.fail(
924
+ UnscoredError(
925
+ f"reward {', '.join(unscored)} scored nothing (nan)"
926
+ )
927
+ )
911
928
  trace.timing.scoring.end = time.time()
912
929
  trace.notify()
913
930
  except Exception as e: # noqa: BLE001 - finalize boundary records every rollout failure
File without changes