verifiers 0.1.15.dev427__tar.gz → 0.1.15.dev428__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 (417) hide show
  1. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/PKG-INFO +1 -1
  2. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_judges.py +78 -13
  3. verifiers-0.1.15.dev428/verifiers/v1/judges/rubric.py +330 -0
  4. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/judges/rubric.txt +2 -2
  5. verifiers-0.1.15.dev427/verifiers/v1/judges/rubric.py +0 -165
  6. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/.gitignore +0 -0
  7. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/LICENSE +0 -0
  8. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/README.md +0 -0
  9. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/pyproject.toml +0 -0
  10. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/AGENTS.md +0 -0
  11. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/README.md +0 -0
  12. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/__init__.py +0 -0
  13. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/conftest.py +0 -0
  14. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_browser_env.py +0 -0
  15. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_build_script.py +0 -0
  16. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_cli_agent_env.py +0 -0
  17. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_client_auth_errors.py +0 -0
  18. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_client_config.py +0 -0
  19. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_client_multimodal_types.py +0 -0
  20. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_composable_env.py +0 -0
  21. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_context_token_metrics.py +0 -0
  22. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_decorator_ranks.py +0 -0
  23. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_endpoint_registry.py +0 -0
  24. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_env_group.py +0 -0
  25. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_env_server.py +0 -0
  26. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_environment.py +0 -0
  27. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_environment_extra.py +0 -0
  28. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_envs.py +0 -0
  29. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_error_chain.py +0 -0
  30. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_eval_display.py +0 -0
  31. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_eval_utils.py +0 -0
  32. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_gepa_cli.py +0 -0
  33. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_gepa_utils.py +0 -0
  34. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_gym_env.py +0 -0
  35. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_harbor_env_mcp.py +0 -0
  36. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_imports.py +0 -0
  37. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_init_script.py +0 -0
  38. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_install_utils.py +0 -0
  39. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_interception_utils.py +0 -0
  40. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_logging.py +0 -0
  41. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_math_rubric.py +0 -0
  42. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_maybe_think_parser.py +0 -0
  43. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_message_utils.py +0 -0
  44. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_message_utils_multimodal.py +0 -0
  45. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_multiturn_env.py +0 -0
  46. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_nemorl_client.py +0 -0
  47. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_openai_chat_completions_token_client.py +0 -0
  48. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_openai_responses_client.py +0 -0
  49. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_opencode_rlm_env.py +0 -0
  50. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_openenv_client.py +0 -0
  51. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_parser.py +0 -0
  52. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_path_utils.py +0 -0
  53. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_per_turn_timing.py +0 -0
  54. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_pricing_utils.py +0 -0
  55. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_prime_plugin.py +0 -0
  56. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_renderer_client.py +0 -0
  57. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_renderer_e2e.py +0 -0
  58. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_rlm_composable_env.py +0 -0
  59. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_rubric.py +0 -0
  60. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_rubric_group.py +0 -0
  61. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_sandbox_debug_env.py +0 -0
  62. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_sandbox_env.py +0 -0
  63. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_sandbox_mixin.py +0 -0
  64. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_save_utils.py +0 -0
  65. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_setup_script.py +0 -0
  66. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_singleturn_env.py +0 -0
  67. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_stateful_tool_env.py +0 -0
  68. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_think_parser.py +0 -0
  69. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_tool_env.py +0 -0
  70. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_tool_utils.py +0 -0
  71. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_trajectory_processing.py +0 -0
  72. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_tui_info_formatting.py +0 -0
  73. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_types.py +0 -0
  74. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_wordle_env.py +0 -0
  75. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/test_xml_parser.py +0 -0
  76. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/conftest.py +0 -0
  77. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/counter_tool_v1.py +0 -0
  78. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
  79. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_multi_v0.py +0 -0
  80. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_tool_v1.py +0 -0
  81. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
  82. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_v0.py +0 -0
  83. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/echo_v1.py +0 -0
  84. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/pyproject.toml +0 -0
  85. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
  86. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_color_codeword_tasks.py +0 -0
  87. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_configs.py +0 -0
  88. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_e2e.py +0 -0
  89. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_envs.py +0 -0
  90. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_graph.py +0 -0
  91. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_legacy.py +0 -0
  92. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_scoring.py +0 -0
  93. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/tests/v1/test_trace.py +0 -0
  94. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/AGENTS.md +0 -0
  95. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/__init__.py +0 -0
  96. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/__init__.py +0 -0
  97. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/__init__.py +0 -0
  98. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/build.py +0 -0
  99. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/eval.py +0 -0
  100. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/gepa.py +0 -0
  101. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/init.py +0 -0
  102. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/install.py +0 -0
  103. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/commands/setup.py +0 -0
  104. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/plugins/__init__.py +0 -0
  105. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/plugins/prime.py +0 -0
  106. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/cli/tui.py +0 -0
  107. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/__init__.py +0 -0
  108. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/anthropic_messages_client.py +0 -0
  109. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/client.py +0 -0
  110. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/nemorl_chat_completions_client.py +0 -0
  111. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/openai_chat_completions_client.py +0 -0
  112. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/openai_chat_completions_token_client.py +0 -0
  113. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/openai_completions_client.py +0 -0
  114. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/openai_responses_client.py +0 -0
  115. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/clients/renderer_client.py +0 -0
  116. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/decorators.py +0 -0
  117. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/AGENTS.md +0 -0
  118. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/__init__.py +0 -0
  119. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/env_group.py +0 -0
  120. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/environment.py +0 -0
  121. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/README.md +0 -0
  122. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/__init__.py +0 -0
  123. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/cli_agent_env.py +0 -0
  124. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/README.md +0 -0
  125. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/__init__.py +0 -0
  126. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/_filter.py +0 -0
  127. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/composable_env.py +0 -0
  128. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harness.py +0 -0
  129. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harnesses/__init__.py +0 -0
  130. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harnesses/mini_swe_agent.py +0 -0
  131. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harnesses/opencode.py +0 -0
  132. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harnesses/prompt.txt +0 -0
  133. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/harnesses/rlm.py +0 -0
  134. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/sandbox_debug_env.py +0 -0
  135. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/swe_debug_env.py +0 -0
  136. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/task.py +0 -0
  137. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/__init__.py +0 -0
  138. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/cp/__init__.py +0 -0
  139. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/cp/cp_task.py +0 -0
  140. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/cp/test_utils.py +0 -0
  141. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/harbor/__init__.py +0 -0
  142. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/harbor/cli_gym.py +0 -0
  143. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/harbor/harbor.py +0 -0
  144. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/harbor/terminal_lego.py +0 -0
  145. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/math/__init__.py +0 -0
  146. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/math/math_task.py +0 -0
  147. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/README.md +0 -0
  148. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/__init__.py +0 -0
  149. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/openseeker/README.md +0 -0
  150. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/openseeker/__init__.py +0 -0
  151. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/openseeker/taskset.py +0 -0
  152. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/README.md +0 -0
  153. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/__init__.py +0 -0
  154. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/__init__.py +0 -0
  155. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/api_tools/__init__.py +0 -0
  156. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/api_tools/tool_pdf.py +0 -0
  157. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/eval_toolkit.py +0 -0
  158. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/evaluator.py +0 -0
  159. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/llm_client/__init__.py +0 -0
  160. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/llm_client/base_client.py +0 -0
  161. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/prompts/__init__.py +0 -0
  162. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/prompts/cache_prompts.py +0 -0
  163. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/__init__.py +0 -0
  164. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/cache_filesys.py +0 -0
  165. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/load_eval_script.py +0 -0
  166. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/misc.py +0 -0
  167. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/tool_visit.py +0 -0
  168. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/url_tools.py +0 -0
  169. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/verification_tree.py +0 -0
  170. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/open_ended.py +0 -0
  171. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/quest/taskset.py +0 -0
  172. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/README.md +0 -0
  173. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/__init__.py +0 -0
  174. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/taskset.py +0 -0
  175. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/search/search_tasksets.py +0 -0
  176. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/README.md +0 -0
  177. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/__init__.py +0 -0
  178. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/__init__.py +0 -0
  179. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/extract_fix_patch.sh +0 -0
  180. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/taskset.py +0 -0
  181. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/openswe/__init__.py +0 -0
  182. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/openswe/taskset.py +0 -0
  183. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/__init__.py +0 -0
  184. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/log_parser.py +0 -0
  185. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/taskset.py +0 -0
  186. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/__init__.py +0 -0
  187. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/taskset.py +0 -0
  188. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/shared/__init__.py +0 -0
  189. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/shared/test_patch.py +0 -0
  190. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/__init__.py +0 -0
  191. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/taskset.py +0 -0
  192. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/__init__.py +0 -0
  193. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/taskset.py +0 -0
  194. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/__init__.py +0 -0
  195. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/log_parsers.py +0 -0
  196. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/taskset.py +0 -0
  197. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/__init__.py +0 -0
  198. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/taskset.py +0 -0
  199. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/composable/tasksets/swe/swe_tasksets.py +0 -0
  200. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/gym_env.py +0 -0
  201. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/harbor_env/__init__.py +0 -0
  202. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/harbor_env/env.py +0 -0
  203. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/harbor_env/mcp.py +0 -0
  204. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/mcp_env.py +0 -0
  205. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/opencode_env.py +0 -0
  206. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/opencode_qa_env.py +0 -0
  207. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/opencode_rlm_env.py +0 -0
  208. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/sandbox_mixin.py +0 -0
  209. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/utils/__init__.py +0 -0
  210. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/utils/file_locks.py +0 -0
  211. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/experimental/utils/git_checkout_cache.py +0 -0
  212. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/README.md +0 -0
  213. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/__init__.py +0 -0
  214. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/README.md +0 -0
  215. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/__init__.py +0 -0
  216. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/browser_env.py +0 -0
  217. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/modes/__init__.py +0 -0
  218. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/modes/base.py +0 -0
  219. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/modes/cua_mode.py +0 -0
  220. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/browser_env/modes/dom_mode.py +0 -0
  221. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/openenv_env.py +0 -0
  222. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/reasoninggym_env.py +0 -0
  223. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/integrations/textarena_env.py +0 -0
  224. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/multiturn_env.py +0 -0
  225. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/python_env.py +0 -0
  226. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/sandbox_env.py +0 -0
  227. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/singleturn_env.py +0 -0
  228. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/stateful_tool_env.py +0 -0
  229. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/envs/tool_env.py +0 -0
  230. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/errors.py +0 -0
  231. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/gepa/__init__.py +0 -0
  232. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/gepa/adapter.py +0 -0
  233. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/gepa/config.py +0 -0
  234. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/gepa/display.py +0 -0
  235. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/gepa/gepa_utils.py +0 -0
  236. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/parsers/__init__.py +0 -0
  237. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/parsers/maybe_think_parser.py +0 -0
  238. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/parsers/parser.py +0 -0
  239. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/parsers/think_parser.py +0 -0
  240. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/parsers/xml_parser.py +0 -0
  241. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/README.md +0 -0
  242. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/__init__.py +0 -0
  243. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/inference/__init__.py +0 -0
  244. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/inference/client.py +0 -0
  245. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/inference/server.py +0 -0
  246. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/trainer/__init__.py +0 -0
  247. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/trainer/config.py +0 -0
  248. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/trainer/orchestrator.py +0 -0
  249. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/trainer/trainer.py +0 -0
  250. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rl/trainer/utils.py +0 -0
  251. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/__init__.py +0 -0
  252. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/experimental/hybrid_math_rubric.py +0 -0
  253. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/judge_rubric.py +0 -0
  254. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/math_rubric.py +0 -0
  255. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/rubric.py +0 -0
  256. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/rubrics/rubric_group.py +0 -0
  257. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/__init__.py +0 -0
  258. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/build.py +0 -0
  259. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/eval.py +0 -0
  260. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/gepa.py +0 -0
  261. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/init.py +0 -0
  262. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/install.py +0 -0
  263. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/rl.py +0 -0
  264. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/setup.py +0 -0
  265. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/train.py +0 -0
  266. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/tui.py +0 -0
  267. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/scripts/vllm.py +0 -0
  268. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/__init__.py +0 -0
  269. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/client/env_client.py +0 -0
  270. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/client/zmq_env_client.py +0 -0
  271. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/server/__init__.py +0 -0
  272. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/server/env_router.py +0 -0
  273. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/server/env_server.py +0 -0
  274. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/server/env_worker.py +0 -0
  275. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/server/zmq_env_server.py +0 -0
  276. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/serve/types.py +0 -0
  277. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/types.py +0 -0
  278. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/__init__.py +0 -0
  279. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/async_utils.py +0 -0
  280. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/client_utils.py +0 -0
  281. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/config_utils.py +0 -0
  282. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/data_utils.py +0 -0
  283. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/display_utils.py +0 -0
  284. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/env_config_utils.py +0 -0
  285. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/env_utils.py +0 -0
  286. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/error_utils.py +0 -0
  287. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/eval_display.py +0 -0
  288. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/eval_utils.py +0 -0
  289. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/heartbeat.py +0 -0
  290. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/import_utils.py +0 -0
  291. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/install_utils.py +0 -0
  292. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/interception_utils.py +0 -0
  293. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/logging_utils.py +0 -0
  294. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/message_utils.py +0 -0
  295. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/metric_utils.py +0 -0
  296. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/path_utils.py +0 -0
  297. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/pricing_utils.py +0 -0
  298. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/process_utils.py +0 -0
  299. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/response_utils.py +0 -0
  300. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/save_utils.py +0 -0
  301. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/serve_utils.py +0 -0
  302. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/thread_utils.py +0 -0
  303. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/threaded_sandbox_client.py +0 -0
  304. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/tool_utils.py +0 -0
  305. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/usage_utils.py +0 -0
  306. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/utils/version_utils.py +0 -0
  307. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/ARCHITECTURE.md +0 -0
  308. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/GUIDE.md +0 -0
  309. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/README.md +0 -0
  310. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/__init__.py +0 -0
  311. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/__init__.py +0 -0
  312. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/dashboard/__init__.py +0 -0
  313. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/dashboard/base.py +0 -0
  314. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/dashboard/eval.py +0 -0
  315. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/dashboard/replay.py +0 -0
  316. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/dashboard/validate.py +0 -0
  317. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/debug.py +0 -0
  318. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/eval/__init__.py +0 -0
  319. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/eval/main.py +0 -0
  320. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/eval/resume.py +0 -0
  321. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/eval/runner.py +0 -0
  322. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/init.py +0 -0
  323. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/output.py +0 -0
  324. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/replay.py +0 -0
  325. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/resolve.py +0 -0
  326. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/serve.py +0 -0
  327. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/cli/validate.py +0 -0
  328. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/clients/__init__.py +0 -0
  329. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/clients/client.py +0 -0
  330. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/clients/config.py +0 -0
  331. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/clients/eval.py +0 -0
  332. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/clients/train.py +0 -0
  333. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/__init__.py +0 -0
  334. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/debug.py +0 -0
  335. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/eval.py +0 -0
  336. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/init.py +0 -0
  337. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/replay.py +0 -0
  338. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/serve.py +0 -0
  339. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/configs/validate.py +0 -0
  340. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/decorators.py +0 -0
  341. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/dialects/__init__.py +0 -0
  342. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/dialects/anthropic.py +0 -0
  343. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/dialects/base.py +0 -0
  344. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/dialects/chat.py +0 -0
  345. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/dialects/responses.py +0 -0
  346. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/env.py +0 -0
  347. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/episode.py +0 -0
  348. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/errors.py +0 -0
  349. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/graph.py +0 -0
  350. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harness.py +0 -0
  351. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/__init__.py +0 -0
  352. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/codex/__init__.py +0 -0
  353. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/codex/harness.py +0 -0
  354. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/default/__init__.py +0 -0
  355. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/default/harness.py +0 -0
  356. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/default/program.py +0 -0
  357. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
  358. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
  359. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
  360. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
  361. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
  362. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/null/__init__.py +0 -0
  363. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/null/harness.py +0 -0
  364. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/null/program.py +0 -0
  365. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
  366. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/rlm/harness.py +0 -0
  367. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
  368. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
  369. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
  370. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/interception/__init__.py +0 -0
  371. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/interception/pool.py +0 -0
  372. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/interception/server.py +0 -0
  373. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/judge.py +0 -0
  374. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/judges/__init__.py +0 -0
  375. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/judges/reference.py +0 -0
  376. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/judges/reference.txt +0 -0
  377. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/legacy.py +0 -0
  378. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/loaders.py +0 -0
  379. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/mcp/__init__.py +0 -0
  380. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/mcp/launch.py +0 -0
  381. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/mcp/server.py +0 -0
  382. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/mcp/toolset.py +0 -0
  383. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/mcp/user.py +0 -0
  384. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/retries.py +0 -0
  385. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/rollout.py +0 -0
  386. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/__init__.py +0 -0
  387. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/base.py +0 -0
  388. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/docker.py +0 -0
  389. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/limiters.py +0 -0
  390. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/modal.py +0 -0
  391. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/prime.py +0 -0
  392. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/runtimes/subprocess.py +0 -0
  393. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/scoring.py +0 -0
  394. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/serve/__init__.py +0 -0
  395. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/serve/client.py +0 -0
  396. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/serve/pool.py +0 -0
  397. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/serve/server.py +0 -0
  398. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/serve/types.py +0 -0
  399. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/state.py +0 -0
  400. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/task.py +0 -0
  401. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/taskset.py +0 -0
  402. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/__init__.py +0 -0
  403. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
  404. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
  405. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/lean/__init__.py +0 -0
  406. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/lean/scoring.py +0 -0
  407. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/lean/taskset.py +0 -0
  408. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
  409. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
  410. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/trace.py +0 -0
  411. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/types.py +0 -0
  412. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/__init__.py +0 -0
  413. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/aio.py +0 -0
  414. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/format.py +0 -0
  415. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/install.py +0 -0
  416. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/logging.py +0 -0
  417. {verifiers-0.1.15.dev427 → verifiers-0.1.15.dev428}/verifiers/v1/utils/memory.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: verifiers
3
- Version: 0.1.15.dev427
3
+ Version: 0.1.15.dev428
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
@@ -29,9 +29,9 @@ class QATask(vf.Task):
29
29
  answer: str = ""
30
30
 
31
31
 
32
- def make_trace(reply: str = "It is Paris.") -> vf.Trace:
32
+ def make_trace(reply: str = "It is Paris.", answer: str = "Paris") -> vf.Trace:
33
33
  return vf.Trace(
34
- task=QATask(idx=0, prompt="Capital of France?", answer="Paris"),
34
+ task=QATask(idx=0, prompt="Capital of France?", answer=answer),
35
35
  nodes=[
36
36
  MessageNode(
37
37
  parent=None,
@@ -47,23 +47,31 @@ def make_trace(reply: str = "It is Paris.") -> vf.Trace:
47
47
 
48
48
  @pytest.fixture
49
49
  def fake_judge_model(monkeypatch):
50
- """Fake the judge's model call, recording each prompt for assertions. Text calls reply
51
- "yes" iff "Paris" appears in the response block of the rendered prompt; structured
52
- (`schema`) calls verdict each `- name: text` criteria line "yes" iff it mentions Paris."""
50
+ """Fake the judge's model call, recording each prompt for assertions. Rubric calls (a JSON
51
+ `verdicts` instruction or a `schema`) reply one reasoned verdict per `- name: text` criterion,
52
+ "yes" iff it mentions Paris; other judges reply plain "yes"/"no" by the response block."""
53
53
  prompts: list[str] = []
54
54
 
55
55
  async def fake_complete(
56
56
  self, messages, *, trace=None, schema=None, parse=None, **sampling
57
57
  ):
58
58
  prompts.append(messages)
59
- if schema is not None:
59
+ # Rubric calls carry criteria lines + a JSON `verdicts` instruction; reply one verdict per
60
+ # criterion (yes iff its text mentions Paris) with a reason. Other judges get plain yes/no.
61
+ if schema is not None or '"verdicts"' in messages:
60
62
  verdicts = [
61
- {"name": name, "verdict": "yes" if "Paris" in text else "no"}
63
+ {
64
+ "name": name,
65
+ "reason": "cites Paris" if "Paris" in text else "no Paris",
66
+ "verdict": "yes" if "Paris" in text else "no",
67
+ }
62
68
  for name, text in re.findall(r"^- ([^:]+): (.+)$", messages, re.M)
63
69
  ]
64
70
  response = JudgeResponse(
65
- text=json.dumps(verdicts),
66
- parsed=schema.model_validate({"verdicts": verdicts}),
71
+ text=json.dumps({"verdicts": verdicts}),
72
+ parsed=schema.model_validate({"verdicts": verdicts})
73
+ if schema
74
+ else None,
67
75
  )
68
76
  else:
69
77
  response = JudgeResponse(
@@ -501,7 +509,7 @@ def test_rubric_rejects_bad_files(tmp_path):
501
509
 
502
510
  async def test_rubric_score(tmp_path, fake_judge_model):
503
511
  # verdicts: mentions_paris=1 (w=3), is_polite=0 (w=1) -> weighted mean 0.75, from ONE
504
- # structured judge call; each verdict lands as a `<name>/<criterion>` metric.
512
+ # judge call; each verdict lands as a `<name>/<criterion>` metric.
505
513
  judge = rubric_judge(tmp_path)
506
514
  trace = make_trace()
507
515
  assert await judge.score(trace.task, trace) == 0.75
@@ -513,16 +521,73 @@ async def test_rubric_verdict_mismatch_raises(tmp_path, monkeypatch):
513
521
  # A reply that doesn't verdict exactly the rubric's criteria is a judge failure: raise
514
522
  # (-> rollout error), don't guess or silently score 0.
515
523
  async def wrong_names(self, messages, *, trace=None, schema=None, parse=None, **s):
516
- verdicts = {"verdicts": [{"name": "typo", "verdict": "yes"}]}
517
- return JudgeResponse(text="", parsed=schema.model_validate(verdicts))
524
+ verdicts = {"verdicts": [{"name": "typo", "reason": "x", "verdict": "yes"}]}
525
+ return JudgeResponse(text=json.dumps(verdicts), parsed=None)
518
526
 
519
527
  monkeypatch.setattr(Judge, "complete", wrong_names)
520
528
  judge = rubric_judge(tmp_path)
521
529
  trace = make_trace()
522
- with pytest.raises(ValueError, match="expected the rubric"):
530
+ with pytest.raises(ValueError, match="expected the batch"):
523
531
  await judge.score(trace.task, trace)
524
532
 
525
533
 
534
+ CHOICES_TOML = (
535
+ '[[criteria]]\nname = "depth"\ntext = "How thorough?"\n'
536
+ 'choices = ["none", "partial", "good"]\n'
537
+ )
538
+
539
+
540
+ async def test_rubric_choices_normalize(tmp_path, monkeypatch):
541
+ # Ordered choices (worst→best) score by rank: "partial" of ["none","partial","good"] -> 0.5.
542
+ async def graded(self, messages, *, trace=None, schema=None, parse=None, **s):
543
+ v = {"verdicts": [{"name": "depth", "reason": "r", "verdict": "partial"}]}
544
+ return JudgeResponse(text=json.dumps(v), parsed=None)
545
+
546
+ monkeypatch.setattr(Judge, "complete", graded)
547
+ judge = rubric_judge(tmp_path, body=CHOICES_TOML, name="q")
548
+ trace = make_trace()
549
+ assert await judge.score(trace.task, trace) == 0.5
550
+ assert trace.metrics == {"q/depth": 0.5}
551
+
552
+
553
+ async def test_rubric_off_menu_answer_raises(tmp_path, monkeypatch):
554
+ # A verdict that isn't one of the criterion's choices is a judge failure, not a 0.
555
+ async def off_menu(self, messages, *, trace=None, schema=None, parse=None, **s):
556
+ v = {"verdicts": [{"name": "depth", "reason": "r", "verdict": "maybe"}]}
557
+ return JudgeResponse(text=json.dumps(v), parsed=None)
558
+
559
+ monkeypatch.setattr(Judge, "complete", off_menu)
560
+ judge = rubric_judge(tmp_path, body=CHOICES_TOML)
561
+ trace = make_trace()
562
+ with pytest.raises(ValueError, match="expected one of"):
563
+ await judge.score(trace.task, trace)
564
+
565
+
566
+ def test_rubric_choices_validation(tmp_path):
567
+ with pytest.raises(ValueError, match="at least two"):
568
+ rubric_judge(
569
+ tmp_path, body='[[criteria]]\nname = "x"\ntext = "t"\nchoices = ["only"]\n'
570
+ ).criteria
571
+ with pytest.raises(ValueError, match="duplicate options"):
572
+ rubric_judge(
573
+ tmp_path,
574
+ body='[[criteria]]\nname = "x"\ntext = "t"\nchoices = ["a", "a"]\n',
575
+ ).criteria
576
+
577
+
578
+ async def test_rubric_reference_answer_optional(tmp_path, fake_judge_model):
579
+ # off by default: no reference block in the prompt.
580
+ t = make_trace()
581
+ await rubric_judge(tmp_path).score(t.task, t)
582
+ assert "Reference solution" not in fake_judge_model[-1]
583
+
584
+ # answer_field set: the task's gold answer is shown to the judge.
585
+ t = make_trace(answer="ZEBRA-GOLD")
586
+ await rubric_judge(tmp_path, answer_field="answer").score(t.task, t)
587
+ assert "Reference solution" in fake_judge_model[-1]
588
+ assert "ZEBRA-GOLD" in fake_judge_model[-1]
589
+
590
+
526
591
  # --- Taskset.score integration -------------------------------------------------------------
527
592
 
528
593
 
@@ -0,0 +1,330 @@
1
+ """rubric — an off-the-shelf rubric judge, plugged from config alone.
2
+
3
+ Reads a rubric — a list of criteria — from a JSON or TOML file and asks the judge model to grade
4
+ each by picking one of its ordered `choices` (default `["no", "yes"]`, a binary check), scored to
5
+ [0, 1] by rank — worst → best, so the first choice is 0.0 and the last 1.0 (all in one call by
6
+ default, or batched `max_criteria`-at-a-time). Grading uses plain-text JSON by default, or
7
+ structured output when `structured_output=true` (see `RubricJudgeConfig`). The reward is the
8
+ weighted mean of the per-criterion scores (`sum(w*v) / sum(w)`, so it stays in [0, 1]); each score
9
+ is also recorded as a `<name>/<criterion>` metric. Criterion weights come from the rubric file and
10
+ are overridable from config (`weights`); the aggregate weighs into `trace.reward` via the judge's
11
+ `weight`:
12
+
13
+ [[env.taskset.judges]]
14
+ id = "rubric"
15
+ path = "rubrics/quality.toml"
16
+ weight = 0.5
17
+ weights = { cites_sources = 2.0 } # override the file's per-criterion weight
18
+
19
+ with `rubrics/quality.toml` listing the criteria (JSON takes `{"criteria": [...]}` or a bare list):
20
+
21
+ [[criteria]]
22
+ name = "cites_sources"
23
+ text = "The response cites at least one specific source."
24
+ weight = 1.0
25
+ # choices default to ["no", "yes"]; give an ordered worst→best list for a graded criterion:
26
+ # choices = ["none", "partial", "thorough"] # -> 0.0, 0.5, 1.0
27
+ """
28
+
29
+ import asyncio
30
+ import json
31
+ import math
32
+ import re
33
+ import tomllib
34
+ from functools import cached_property
35
+ from pathlib import Path
36
+ from typing import cast
37
+
38
+ from pydantic import field_validator
39
+
40
+ from verifiers.v1.judge import (
41
+ Judge,
42
+ JudgeConfig,
43
+ JudgeView,
44
+ judge_question,
45
+ judge_response,
46
+ )
47
+ from verifiers.v1.task import Task
48
+ from verifiers.v1.trace import Trace
49
+ from verifiers.v1.types import ID, StrictBaseModel
50
+
51
+ # A sibling text file so it doubles as a starting point for a config `prompt_file`.
52
+ RUBRIC_PROMPT = (Path(__file__).resolve().parent / "rubric.txt").read_text(
53
+ encoding="utf-8"
54
+ )
55
+
56
+ # Appended to the prompt when `structured_output` is off, so the reply is JSON we can parse. Each
57
+ # criterion carries a one-sentence `reason` written *before* the verdict (chain-of-thought), so the
58
+ # verdict follows from it and the reasoning is auditable in `trace.info["judge"]`.
59
+ JSON_SUFFIX = (
60
+ "\n\nRespond with ONLY a JSON object and nothing else, in exactly this shape:\n"
61
+ '{"verdicts": [{"name": "<criterion name>", "reason": "<one sentence citing specific '
62
+ 'evidence from the response>", "verdict": "<answer>"}, ...]}\n'
63
+ "with one entry per criterion, using each criterion's exact name. For each, first write the "
64
+ "one-sentence reason grounded in the response, then set verdict to exactly one of the options "
65
+ "listed in parentheses after that criterion."
66
+ )
67
+
68
+
69
+ def normalize_choice(choice: str, choices: list[str]) -> float:
70
+ """Score a chosen option to [0, 1] by rank. `choices` are ordered worst → best, so the first
71
+ scores 0.0, the last 1.0, and the rest evenly spaced (`choices` always has >= 2 entries)."""
72
+ return choices.index(choice) / (len(choices) - 1)
73
+
74
+
75
+ def first_verdicts_object(text: str) -> dict | None:
76
+ """The first balanced JSON object in `text` that carries a `verdicts` key. Scanning for the
77
+ key (not just the first `{`) skips prose and, crucially, an echoed format example — the one
78
+ in `JSON_SUFFIX` fails to parse (its trailing `...` isn't JSON) and is passed over rather
79
+ than mistaken for the answer. Returns `None` if no such object is found."""
80
+ decoder = json.JSONDecoder()
81
+ idx = text.find("{")
82
+ while idx != -1:
83
+ try:
84
+ obj, _ = decoder.raw_decode(text[idx:])
85
+ except json.JSONDecodeError:
86
+ obj = None
87
+ if isinstance(obj, dict) and "verdicts" in obj:
88
+ return obj
89
+ idx = text.find("{", idx + 1)
90
+ return None
91
+
92
+
93
+ class Criterion(StrictBaseModel):
94
+ """One rubric entry the judge grades by picking one of `choices`, scored to [0, 1] by rank.
95
+ Defaults to a binary yes/no check (1/0)."""
96
+
97
+ name: str
98
+ """Key for the criterion's metric (`<judge name>/<name>`) and its `weights` override."""
99
+ text: str
100
+ """The check itself, phrased so the first (best) choice means satisfied."""
101
+ weight: float = 1.0
102
+ """The criterion's share of the reward (overridable per name via `weights` in config)."""
103
+ choices: list[str] = ["no", "yes"]
104
+ """Allowed answers, ordered **worst → best**: the first scores 0.0, the last 1.0, the rest
105
+ evenly spaced by rank. Default `["no", "yes"]` is a binary check. Needs >= 2, no duplicates."""
106
+
107
+ @field_validator("choices")
108
+ @classmethod
109
+ def _check_choices(cls, v: list[str]) -> list[str]:
110
+ if len(v) < 2:
111
+ raise ValueError(f"`choices` needs at least two options, got {v}")
112
+ if len(set(v)) != len(v):
113
+ raise ValueError(f"`choices` has duplicate options: {v}")
114
+ return v
115
+
116
+
117
+ class RubricJudgeConfig(JudgeConfig):
118
+ id: ID = "rubric"
119
+ """Pinned to the built-in, so a code-level default entry needs no explicit id."""
120
+ path: Path
121
+ """The rubric file (`.toml` or `.json`) listing the criteria — see the module docstring
122
+ for the shape. A relative path resolves against the eval's working directory."""
123
+ weights: dict[str, float] = {}
124
+ """Per-criterion weight overrides by criterion name (config wins over the file)."""
125
+ question_field: str = ""
126
+ """Task field to fill the prompt's `{question}`; empty = the task's prompt rendered as
127
+ text (`Task.prompt_text`)."""
128
+ answer_field: str = ""
129
+ """Optional task field holding a reference answer (e.g. a gold patch) to show the judge, like
130
+ the reference judge. Empty (default) shows none — `{reference}` renders blank. A list-valued
131
+ field is joined one item per line. Needs `{reference}` in the prompt (the built-in `rubric.txt`
132
+ has it)."""
133
+ view: JudgeView = "full_trace"
134
+ """How much of the rollout fills `{response}` (see `JudgeView`). Defaults to the whole
135
+ transcript — rubric criteria typically grade the process (tool use, citations,
136
+ intermediate steps), not just the final answer."""
137
+ max_criteria: int | None = None
138
+ """How many criteria to grade per judge call. `None` (default) grades all criteria in one
139
+ call. `1` sends one call per criterion (n independent judges); `k` batches them k-at-a-time.
140
+ Batches are graded concurrently and merged. Smaller batches trade more calls for focus/
141
+ robustness. Must be >= 1."""
142
+ structured_output: bool = False
143
+ """Grade via JSON-schema structured output (`response_format`) when `True`; grade via plain-text
144
+ output parsed as JSON when `False` (the default). Plain text is far more reliable on endpoints
145
+ whose structured decoding is flaky (e.g. GLM-5.2 and other non-OpenAI models on some providers
146
+ return empty completions for structured calls, especially over long transcripts); OpenAI models
147
+ handle either. Transient HTTP failures are already retried by the OpenAI client."""
148
+
149
+
150
+ class CriterionVerdict(StrictBaseModel):
151
+ """One criterion's reply, matched back to the rubric by `name`: a short `reason`
152
+ (chain-of-thought, always recorded for auditability in `trace.info["judge"]`) written *before*
153
+ the `verdict`, so the verdict follows from it. `verdict` is one of the criterion's `choices`
154
+ (validated per criterion in `grade_batch`, since choices vary by criterion)."""
155
+
156
+ name: str
157
+ reason: str
158
+ verdict: str
159
+
160
+
161
+ class RubricVerdicts(StrictBaseModel):
162
+ """The judge's reply: one reasoned verdict per rubric criterion."""
163
+
164
+ verdicts: list[CriterionVerdict]
165
+
166
+
167
+ class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
168
+ """Scores every rubric criterion 1/0 (in one judge call, or batched `max_criteria` at a
169
+ time) and rewards their weighted mean."""
170
+
171
+ prompt = RUBRIC_PROMPT
172
+ schema = RubricVerdicts
173
+
174
+ @cached_property
175
+ def criteria(self) -> list[Criterion]:
176
+ """The rubric, parsed once from `config.path` (TOML by suffix, else JSON) with the
177
+ config's `weights` overrides applied. Fails loudly on a missing/empty file, duplicate
178
+ criterion names, or an override naming no criterion."""
179
+ path = self.config.path
180
+ text = path.read_text(encoding="utf-8")
181
+ data = (
182
+ tomllib.loads(text) if path.suffix.lower() == ".toml" else json.loads(text)
183
+ )
184
+ items = data.get("criteria", []) if isinstance(data, dict) else data
185
+ criteria = [Criterion.model_validate(item) for item in items]
186
+ if not criteria:
187
+ raise ValueError(f"rubric file '{path}' lists no criteria")
188
+ names = [criterion.name for criterion in criteria]
189
+ if len(set(names)) != len(names):
190
+ raise ValueError(f"rubric file '{path}' has duplicate criterion names")
191
+ if unknown := set(self.config.weights) - set(names):
192
+ raise ValueError(
193
+ f"`weights` overrides name no criterion in '{path}': {sorted(unknown)}"
194
+ )
195
+ criteria = [
196
+ criterion.model_copy(
197
+ update={
198
+ "weight": self.config.weights.get(criterion.name, criterion.weight)
199
+ }
200
+ )
201
+ for criterion in criteria
202
+ ]
203
+ if bad := [c.name for c in criteria if not 0 <= c.weight < math.inf]:
204
+ # A negative weight would invert a criterion (pushing the reward out of [0, 1]);
205
+ # NaN/inf (which json.loads accepts) would corrupt the weighted mean.
206
+ raise ValueError(
207
+ f"rubric '{path}' has negative or non-finite criterion weights: {bad}"
208
+ )
209
+ if sum(criterion.weight for criterion in criteria) <= 0:
210
+ raise ValueError(f"rubric '{path}' has no positive criterion weight")
211
+ return criteria
212
+
213
+ async def grade_batch(
214
+ self, task: Task, trace: Trace, batch: list[Criterion]
215
+ ) -> dict[str, float]:
216
+ """Grade one batch of criteria in a single judge call — structured output, or plain-text
217
+ JSON when `structured_output` is off (which avoids flaky structured decoding). Returns
218
+ `{name: score}`, each the chosen option normalized to [0, 1] by rank (best → worst),
219
+ matched back to the batch by name. `score` fans this out per batch."""
220
+
221
+ def render(
222
+ c: Criterion,
223
+ ) -> str: # every criterion states its own allowed answers inline
224
+ return f"- {c.name}: {c.text} (answer one of, worst to best: {', '.join(c.choices)})"
225
+
226
+ reference = "" # optional gold answer shown to the judge; blank unless `answer_field` set
227
+ if self.config.answer_field:
228
+ answer = getattr(task, self.config.answer_field, None)
229
+ if answer is None:
230
+ raise ValueError(
231
+ f"rubric judge found no {self.config.answer_field!r} field on the task; "
232
+ "point `answer_field` at the task's reference-answer field or leave it empty"
233
+ )
234
+ if isinstance(answer, (list, tuple)):
235
+ answer = "\n".join(str(item) for item in answer)
236
+ # A clearly-announced section (leading blank separates it from the Task block; the
237
+ # template's newline before Response closes it). Absent when `answer_field` is unset.
238
+ # Fence longer than any backtick run in the answer, so a patch/markdown containing ```
239
+ # can't close it early and spill into the prompt as instructions.
240
+ fence = "`" * (
241
+ max((len(m) for m in re.findall(r"`+", answer)), default=2) + 1
242
+ )
243
+ reference = (
244
+ "\nReference solution (a correct implementation of this task, for comparison):\n"
245
+ f"{fence}\n{answer}\n{fence}\n"
246
+ )
247
+
248
+ fields = dict(
249
+ question=judge_question(task, self.config.question_field),
250
+ response=judge_response(trace, self.config.view),
251
+ criteria="\n".join(render(c) for c in batch),
252
+ reference=reference,
253
+ )
254
+ if self.config.structured_output:
255
+ result = await self.evaluate(trace=trace, **fields)
256
+ verdicts = cast(RubricVerdicts, result.parsed).verdicts
257
+ else:
258
+ messages = cast(str, self.build_messages(**fields)) + JSON_SUFFIX
259
+ result = await self.complete(
260
+ messages, trace=trace
261
+ ) # no schema -> plain text
262
+ obj = first_verdicts_object(result.text)
263
+ if obj is None:
264
+ raise ValueError(
265
+ f"judge returned no verdicts JSON object: {result.text!r}"
266
+ )
267
+ verdicts = RubricVerdicts.model_validate(obj).verdicts
268
+ # Exactly one verdict per criterion in the batch, matched by name — anything else is a
269
+ # judge failure and must error the rollout, not score the model (see `judge_verdict`).
270
+ by_criterion = {c.name: c for c in batch}
271
+ if sorted(v.name for v in verdicts) != sorted(by_criterion):
272
+ raise ValueError(
273
+ f"judge verdicts name {sorted(v.name for v in verdicts)}, expected the "
274
+ f"batch's {sorted(by_criterion)}"
275
+ )
276
+ scores: dict[str, float] = {}
277
+ for v in verdicts:
278
+ choices = by_criterion[v.name].choices
279
+ if (
280
+ v.verdict not in choices
281
+ ): # an off-menu answer is a judge failure, not a 0
282
+ raise ValueError(
283
+ f"judge answered {v.verdict!r} for '{v.name}', expected one of {choices}"
284
+ )
285
+ scores[v.name] = normalize_choice(v.verdict, choices)
286
+ return scores
287
+
288
+ async def score(self, task: Task, trace: Trace) -> float:
289
+ criteria = self.criteria
290
+ # Split into batches of `max_criteria` (None = one batch of all), then grade the batches
291
+ # concurrently (one judge call each) and merge.
292
+ k = self.config.max_criteria
293
+ if k is not None and k < 1:
294
+ raise ValueError(f"`max_criteria` must be >= 1 or None, got {k}")
295
+ batches = (
296
+ [criteria]
297
+ if k is None
298
+ else [criteria[i : i + k] for i in range(0, len(criteria), k)]
299
+ )
300
+ # Fan out one call per batch; if any fails, cancel the siblings so a judge failure
301
+ # doesn't keep billing the remaining batches.
302
+ tasks = [
303
+ asyncio.ensure_future(self.grade_batch(task, trace, batch))
304
+ for batch in batches
305
+ ]
306
+ try:
307
+ results = await asyncio.gather(*tasks)
308
+ except BaseException:
309
+ for t in tasks:
310
+ t.cancel()
311
+ await asyncio.gather(*tasks, return_exceptions=True)
312
+ raise
313
+ by_name: dict[str, float] = {}
314
+ for batch_verdicts in results:
315
+ by_name.update(batch_verdicts)
316
+ for criterion in criteria:
317
+ trace.record_metric(
318
+ f"{self.reward_name}/{criterion.name}", by_name[criterion.name]
319
+ )
320
+ total = sum(criterion.weight for criterion in criteria)
321
+ return sum(c.weight * by_name[c.name] for c in criteria) / total
322
+
323
+
324
+ __all__ = [
325
+ "Criterion",
326
+ "CriterionVerdict",
327
+ "RubricJudge",
328
+ "RubricJudgeConfig",
329
+ "RubricVerdicts",
330
+ ]
@@ -4,7 +4,7 @@ Task:
4
4
  ```
5
5
  {question}
6
6
  ```
7
-
7
+ {reference}
8
8
  Response:
9
9
  ```
10
10
  {response}
@@ -13,4 +13,4 @@ Response:
13
13
  Criteria:
14
14
  {criteria}
15
15
 
16
- For each criterion, give a "yes" or "no" verdict under its exact name.
16
+ For each criterion, answer under its exact name with exactly one of the options given in parentheses after it.
@@ -1,165 +0,0 @@
1
- """rubric — an off-the-shelf rubric judge, plugged from config alone.
2
-
3
- Reads a rubric — a list of yes/no criteria — from a JSON or TOML file and asks the judge model
4
- to grade all criteria in one structured-output call, scoring each 1/0. The reward is the weighted
5
- mean of the verdicts (`sum(w*v) / sum(w)`, so it stays in [0, 1]); each verdict is also recorded
6
- as a `<name>/<criterion>` metric. Criterion weights come from the rubric file and are overridable
7
- from config (`weights`); the aggregate weighs into `trace.reward` via the judge's `weight`:
8
-
9
- [[env.taskset.judges]]
10
- id = "rubric"
11
- path = "rubrics/quality.toml"
12
- weight = 0.5
13
- weights = { cites_sources = 2.0 } # override the file's per-criterion weight
14
-
15
- with `rubrics/quality.toml` listing the criteria (JSON takes `{"criteria": [...]}` or a bare list):
16
-
17
- [[criteria]]
18
- name = "cites_sources"
19
- text = "The response cites at least one specific source."
20
- weight = 1.0
21
- """
22
-
23
- import json
24
- import math
25
- import tomllib
26
- from functools import cached_property
27
- from pathlib import Path
28
- from typing import Literal, cast
29
-
30
- from verifiers.v1.judge import (
31
- Judge,
32
- JudgeConfig,
33
- JudgeView,
34
- judge_question,
35
- judge_response,
36
- )
37
- from verifiers.v1.task import Task
38
- from verifiers.v1.trace import Trace
39
- from verifiers.v1.types import ID, StrictBaseModel
40
-
41
- # A sibling text file so it doubles as a starting point for a config `prompt_file`.
42
- RUBRIC_PROMPT = (Path(__file__).resolve().parent / "rubric.txt").read_text(
43
- encoding="utf-8"
44
- )
45
-
46
-
47
- class Criterion(StrictBaseModel):
48
- """One rubric entry: a yes/no check the judge scores 1/0."""
49
-
50
- name: str
51
- """Key for the criterion's metric (`<judge name>/<name>`) and its `weights` override."""
52
- text: str
53
- """The check itself, phrased so "yes" means satisfied."""
54
- weight: float = 1.0
55
- """The criterion's share of the reward (overridable per name via `weights` in config)."""
56
-
57
-
58
- class RubricJudgeConfig(JudgeConfig):
59
- id: ID = "rubric"
60
- """Pinned to the built-in, so a code-level default entry needs no explicit id."""
61
- path: Path
62
- """The rubric file (`.toml` or `.json`) listing the criteria — see the module docstring
63
- for the shape. A relative path resolves against the eval's working directory."""
64
- weights: dict[str, float] = {}
65
- """Per-criterion weight overrides by criterion name (config wins over the file)."""
66
- question_field: str = ""
67
- """Task field to fill the prompt's `{question}`; empty = the task's prompt rendered as
68
- text (`Task.prompt_text`)."""
69
- view: JudgeView = "full_trace"
70
- """How much of the rollout fills `{response}` (see `JudgeView`). Defaults to the whole
71
- transcript — rubric criteria typically grade the process (tool use, citations,
72
- intermediate steps), not just the final answer."""
73
-
74
-
75
- class CriterionVerdict(StrictBaseModel):
76
- """One criterion's verdict in the judge's reply, matched back to the rubric by `name`."""
77
-
78
- name: str
79
- verdict: Literal["yes", "no"]
80
-
81
-
82
- class RubricVerdicts(StrictBaseModel):
83
- """The judge's structured reply: one verdict per rubric criterion."""
84
-
85
- verdicts: list[CriterionVerdict]
86
-
87
-
88
- class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
89
- """Scores every rubric criterion 1/0 in one structured judge call; rewards their
90
- weighted mean."""
91
-
92
- prompt = RUBRIC_PROMPT
93
- schema = RubricVerdicts
94
-
95
- @cached_property
96
- def criteria(self) -> list[Criterion]:
97
- """The rubric, parsed once from `config.path` (TOML by suffix, else JSON) with the
98
- config's `weights` overrides applied. Fails loudly on a missing/empty file, duplicate
99
- criterion names, or an override naming no criterion."""
100
- path = self.config.path
101
- text = path.read_text(encoding="utf-8")
102
- data = (
103
- tomllib.loads(text) if path.suffix.lower() == ".toml" else json.loads(text)
104
- )
105
- items = data.get("criteria", []) if isinstance(data, dict) else data
106
- criteria = [Criterion.model_validate(item) for item in items]
107
- if not criteria:
108
- raise ValueError(f"rubric file '{path}' lists no criteria")
109
- names = [criterion.name for criterion in criteria]
110
- if len(set(names)) != len(names):
111
- raise ValueError(f"rubric file '{path}' has duplicate criterion names")
112
- if unknown := set(self.config.weights) - set(names):
113
- raise ValueError(
114
- f"`weights` overrides name no criterion in '{path}': {sorted(unknown)}"
115
- )
116
- criteria = [
117
- criterion.model_copy(
118
- update={
119
- "weight": self.config.weights.get(criterion.name, criterion.weight)
120
- }
121
- )
122
- for criterion in criteria
123
- ]
124
- if bad := [c.name for c in criteria if not 0 <= c.weight < math.inf]:
125
- # A negative weight would invert a criterion (pushing the reward out of [0, 1]);
126
- # NaN/inf (which json.loads accepts) would corrupt the weighted mean.
127
- raise ValueError(
128
- f"rubric '{path}' has negative or non-finite criterion weights: {bad}"
129
- )
130
- if sum(criterion.weight for criterion in criteria) <= 0:
131
- raise ValueError(f"rubric '{path}' has no positive criterion weight")
132
- return criteria
133
-
134
- async def score(self, task: Task, trace: Trace) -> float:
135
- criteria = self.criteria
136
- result = await self.evaluate(
137
- trace=trace,
138
- question=judge_question(task, self.config.question_field),
139
- response=judge_response(trace, self.config.view),
140
- criteria="\n".join(f"- {c.name}: {c.text}" for c in criteria),
141
- )
142
- verdicts = cast(RubricVerdicts, result.parsed).verdicts
143
- # Exactly one verdict per criterion, matched by name — anything else is a judge
144
- # failure and must error the rollout, not score the model (see `judge_verdict`).
145
- if sorted(v.name for v in verdicts) != sorted(c.name for c in criteria):
146
- raise ValueError(
147
- f"judge verdicts name {sorted(v.name for v in verdicts)}, expected the "
148
- f"rubric's {sorted(c.name for c in criteria)}"
149
- )
150
- by_name = {v.name: float(v.verdict == "yes") for v in verdicts}
151
- for criterion in criteria:
152
- trace.record_metric(
153
- f"{self.reward_name}/{criterion.name}", by_name[criterion.name]
154
- )
155
- total = sum(criterion.weight for criterion in criteria)
156
- return sum(c.weight * by_name[c.name] for c in criteria) / total
157
-
158
-
159
- __all__ = [
160
- "Criterion",
161
- "CriterionVerdict",
162
- "RubricJudge",
163
- "RubricJudgeConfig",
164
- "RubricVerdicts",
165
- ]