verifiers 0.3.2.dev189__tar.gz → 0.3.2.dev191__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 (228) hide show
  1. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/PKG-INFO +1 -1
  2. verifiers-0.3.2.dev191/verifiers/v1/cli/eval/resume.py +58 -0
  3. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/eval/runner.py +9 -15
  4. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/clients/base.py +6 -2
  5. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/clients/eval.py +6 -2
  6. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/client.py +30 -8
  7. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/gepa/reflection.py +2 -0
  8. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/interception/server.py +2 -1
  9. verifiers-0.3.2.dev191/verifiers/v1/utils/eval.py +36 -0
  10. verifiers-0.3.2.dev189/verifiers/v1/cli/eval/resume.py +0 -89
  11. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/.gitignore +0 -0
  12. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/LICENSE +0 -0
  13. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/README.md +0 -0
  14. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/pyproject.toml +0 -0
  15. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/conftest.py +0 -0
  16. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/agent_user_v1.py +0 -0
  17. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/counter_tool_v1.py +0 -0
  18. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/delivery_behaviors.py +0 -0
  19. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/duet_v1.py +0 -0
  20. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/echo_acp_resume_v1.py +0 -0
  21. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
  22. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/echo_tool_v1.py +0 -0
  23. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
  24. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/echo_v1.py +0 -0
  25. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/pyproject.toml +0 -0
  26. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
  27. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_color_codeword_tasks.py +0 -0
  28. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_configs.py +0 -0
  29. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_delivery_behaviors.py +0 -0
  30. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_e2e.py +0 -0
  31. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_envs.py +0 -0
  32. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_graph.py +0 -0
  33. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_judges.py +0 -0
  34. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_platform_run.py +0 -0
  35. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_scoring.py +0 -0
  36. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_serve_delta.py +0 -0
  37. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_taskset.py +0 -0
  38. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/tests/v1/test_trace.py +0 -0
  39. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/__init__.py +0 -0
  40. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/__init__.py +0 -0
  41. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/acp/__init__.py +0 -0
  42. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/acp/runner.py +0 -0
  43. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/agent.py +0 -0
  44. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/__init__.py +0 -0
  45. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/dashboard/__init__.py +0 -0
  46. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/dashboard/base.py +0 -0
  47. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/dashboard/eval.py +0 -0
  48. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/dashboard/replay.py +0 -0
  49. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/dashboard/validate.py +0 -0
  50. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/debug.py +0 -0
  51. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/eval/__init__.py +0 -0
  52. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/eval/hint.py +0 -0
  53. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/eval/main.py +0 -0
  54. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/gepa.py +0 -0
  55. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/init.py +0 -0
  56. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/output.py +0 -0
  57. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/replay.py +0 -0
  58. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/resolve.py +0 -0
  59. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/resume.py +0 -0
  60. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/cli/validate.py +0 -0
  61. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/clients/__init__.py +0 -0
  62. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/clients/client.py +0 -0
  63. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/clients/train.py +0 -0
  64. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/__init__.py +0 -0
  65. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/agent.py +0 -0
  66. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/cli/__init__.py +0 -0
  67. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/cli/debug.py +0 -0
  68. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/cli/env.py +0 -0
  69. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/cli/eval.py +0 -0
  70. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/cli/init.py +0 -0
  71. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/cli/replay.py +0 -0
  72. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/cli/validate.py +0 -0
  73. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/env.py +0 -0
  74. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/harness.py +0 -0
  75. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/judge.py +0 -0
  76. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/retries.py +0 -0
  77. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/runtime.py +0 -0
  78. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/select.py +0 -0
  79. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/serve.py +0 -0
  80. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/task.py +0 -0
  81. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/configs/taskset.py +0 -0
  82. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/dialects/__init__.py +0 -0
  83. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/dialects/anthropic.py +0 -0
  84. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/dialects/base.py +0 -0
  85. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/dialects/chat.py +0 -0
  86. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/dialects/responses.py +0 -0
  87. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/env.py +0 -0
  88. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/__init__.py +0 -0
  89. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
  90. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/agentic_judge/env.py +0 -0
  91. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
  92. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/best_of_n/env.py +0 -0
  93. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/isolated_verifier/__init__.py +0 -0
  94. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/isolated_verifier/env.py +0 -0
  95. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/shared_agentic_judge/__init__.py +0 -0
  96. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/single_agent/__init__.py +0 -0
  97. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/single_agent/env.py +0 -0
  98. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/user_sim/__init__.py +0 -0
  99. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/envs/user_sim/env.py +0 -0
  100. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/episode.py +0 -0
  101. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/errors.py +0 -0
  102. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/gepa/__init__.py +0 -0
  103. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/gepa/adapter.py +0 -0
  104. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/gepa/config.py +0 -0
  105. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/gepa/dataset.py +0 -0
  106. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/gepa/runner.py +0 -0
  107. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/graph.py +0 -0
  108. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harness.py +0 -0
  109. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/__init__.py +0 -0
  110. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/bash/__init__.py +0 -0
  111. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/bash/harness.py +0 -0
  112. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
  113. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
  114. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/browser_use/program.py +0 -0
  115. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
  116. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
  117. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/codex/__init__.py +0 -0
  118. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
  119. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/codex/harness.py +0 -0
  120. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
  121. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
  122. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
  123. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
  124. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
  125. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
  126. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
  127. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
  128. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/node.py +0 -0
  129. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/null/__init__.py +0 -0
  130. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/null/harness.py +0 -0
  131. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
  132. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
  133. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/pi/__init__.py +0 -0
  134. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
  135. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/pi/harness.py +0 -0
  136. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
  137. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
  138. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
  139. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/rlm/harness.py +0 -0
  140. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
  141. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
  142. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
  143. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/utils/__init__.py +0 -0
  144. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/utils/compaction.py +0 -0
  145. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/utils/core.py +0 -0
  146. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/utils/install.py +0 -0
  147. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/utils/launch.py +0 -0
  148. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/harnesses/utils/mcp.py +0 -0
  149. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/interception/__init__.py +0 -0
  150. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/interception/base.py +0 -0
  151. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/interception/pool.py +0 -0
  152. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/interception/tunnel/__init__.py +0 -0
  153. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/interception/tunnel/base.py +0 -0
  154. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/interception/tunnel/custom.py +0 -0
  155. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/interception/tunnel/prime.py +0 -0
  156. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/judge.py +0 -0
  157. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/judges/__init__.py +0 -0
  158. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/judges/decision.py +0 -0
  159. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/judges/reference.py +0 -0
  160. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/judges/reference.txt +0 -0
  161. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/judges/rubric.py +0 -0
  162. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/judges/rubric.txt +0 -0
  163. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/mcp/__init__.py +0 -0
  164. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/mcp/launch.py +0 -0
  165. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/mcp/server.py +0 -0
  166. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/mcp/toolset.py +0 -0
  167. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/rollout.py +0 -0
  168. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/__init__.py +0 -0
  169. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/apptainer.py +0 -0
  170. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/base.py +0 -0
  171. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/container.py +0 -0
  172. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/docker/__init__.py +0 -0
  173. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/docker/egress.py +0 -0
  174. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/e2b.py +0 -0
  175. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/limiters.py +0 -0
  176. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/modal.py +0 -0
  177. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/prime.py +0 -0
  178. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/runtimes/subprocess.py +0 -0
  179. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/semantic.py +0 -0
  180. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/serve/__init__.py +0 -0
  181. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/serve/client.py +0 -0
  182. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/serve/delta.py +0 -0
  183. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/serve/encoding.py +0 -0
  184. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/serve/pool.py +0 -0
  185. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/serve/server.py +0 -0
  186. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/serve/types.py +0 -0
  187. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/session.py +0 -0
  188. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/state.py +0 -0
  189. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/task.py +0 -0
  190. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/taskset.py +0 -0
  191. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/__init__.py +0 -0
  192. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
  193. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/harbor/compose.py +0 -0
  194. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/harbor/env.py +0 -0
  195. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
  196. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
  197. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
  198. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
  199. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
  200. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
  201. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
  202. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
  203. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
  204. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
  205. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
  206. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/trace.py +0 -0
  207. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/types.py +0 -0
  208. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/__init__.py +0 -0
  209. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/aio.py +0 -0
  210. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/artifacts.py +0 -0
  211. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/compile.py +0 -0
  212. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/decorators.py +0 -0
  213. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/format.py +0 -0
  214. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/generic.py +0 -0
  215. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/git.py +0 -0
  216. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/image.py +0 -0
  217. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/interrupt.py +0 -0
  218. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/loaders.py +0 -0
  219. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/logging.py +0 -0
  220. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/memory.py +0 -0
  221. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/paths.py +0 -0
  222. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/platform.py +0 -0
  223. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/prime.py +0 -0
  224. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/retries.py +0 -0
  225. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/scope.py +0 -0
  226. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/score.py +0 -0
  227. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/trace_store.py +0 -0
  228. {verifiers-0.3.2.dev189 → verifiers-0.3.2.dev191}/verifiers/v1/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: verifiers
3
- Version: 0.3.2.dev189
3
+ Version: 0.3.2.dev191
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
@@ -0,0 +1,58 @@
1
+ """Resume an interrupted eval: reload its finished rollouts and run only the rest.
2
+
3
+ `load` validates saved episodes, applies the environment's completion verdict, and
4
+ uses the shared rollout planner to retain only those matching the current tasks.
5
+ """
6
+
7
+ from collections.abc import Callable
8
+ from pathlib import Path
9
+
10
+ from pydantic_core import from_json
11
+
12
+ from verifiers.v1.episode import WireEpisode
13
+ from verifiers.v1.task import TaskT
14
+ from verifiers.v1.utils.eval import plan_rollouts
15
+ from verifiers.v1.utils.trace_store import TRACES_FILE
16
+
17
+
18
+ def load(
19
+ resume_dir: Path,
20
+ tasks: list[TaskT],
21
+ num_rollouts: int,
22
+ complete: Callable[[WireEpisode], bool] | None = None,
23
+ ) -> list[tuple[TaskT, list[WireEpisode], int]]:
24
+ """Plan the remaining rollouts and atomically rewrite the stream to kept rows.
25
+
26
+ ``complete`` is the keep-verdict (default ``episode.ok``). Torn or malformed
27
+ rows are discarded; retained rows preserve their original serialized fields.
28
+ """
29
+ path = resume_dir / TRACES_FILE
30
+ verdict = complete if complete is not None else (lambda episode: episode.ok)
31
+ episodes: list[WireEpisode] = []
32
+ lines: dict[str, bytes] = {}
33
+ if path.exists():
34
+ with path.open("rb") as results:
35
+ for line in results:
36
+ if not line.strip():
37
+ continue
38
+ try:
39
+ row = from_json(line)
40
+ if "traces" not in row:
41
+ continue
42
+ episode = WireEpisode.model_validate(row)
43
+ if not verdict(episode):
44
+ continue
45
+ # A malformed row from any task/episode plugin is owed again.
46
+ except Exception: # noqa: BLE001, S112
47
+ continue
48
+ episodes.append(episode)
49
+ lines.setdefault(
50
+ episode.id, line if line.endswith(b"\n") else line + b"\n"
51
+ )
52
+ plan = plan_rollouts(tasks, num_rollouts, episodes)
53
+ tmp = path.with_suffix(".jsonl.tmp")
54
+ tmp.write_bytes(
55
+ b"".join(lines[episode.id] for _, kept, _ in plan for episode in kept)
56
+ )
57
+ tmp.replace(path)
58
+ return plan
@@ -18,12 +18,12 @@ from verifiers.v1.cli.dashboard import dashboard
18
18
  from verifiers.v1.cli.eval import resume
19
19
  from verifiers.v1.cli.eval.hint import PRIME_RL_HINT
20
20
  from verifiers.v1.cli.output import output_path, save_config
21
- from verifiers.v1.cli.resume import distribute
22
21
  from verifiers.v1.clients import ModelContext
23
22
  from verifiers.v1.configs.cli.eval import EvalConfig
24
23
  from verifiers.v1.env import Env, RunSlot
25
24
  from verifiers.v1.episode import Episode, EvalRunInfo
26
25
  from verifiers.v1.utils.aio import run_shielded
26
+ from verifiers.v1.utils.eval import plan_rollouts
27
27
  from verifiers.v1.utils.platform import (
28
28
  PushState,
29
29
  abort_run,
@@ -89,40 +89,34 @@ async def run_eval(config: EvalConfig) -> list[Episode]:
89
89
  )
90
90
  tasks = list(taskset)
91
91
  out = output_path(config)
92
- # One (task, rollouts-to-run) pair per selected task; resume shrinks the counts.
93
- plan = [(task, config.num_rollouts) for task in tasks]
94
- # Kept on-disk rollouts rejoin the run as finished episodes; only owed ones re-run.
95
- finished: list[Episode] = []
96
92
  if config.resume:
97
- keys = [task.hash for task in tasks]
98
93
  # the env's own keep-verdict decides what resumes
99
- loaded, owed = resume.load(
94
+ plan = resume.load(
100
95
  out,
101
- keys,
96
+ tasks,
102
97
  config.num_rollouts,
103
98
  lambda episode: env.complete(cast(Episode, episode)),
104
99
  )
105
- finished = [cast(Episode, episode) for episode in loaded]
106
- if not owed: # already complete - report it and exit successfully
100
+ if not any(n for _, _, n in plan):
107
101
  print(
108
102
  f"nothing to resume in {out}: all {len(tasks)}x{config.num_rollouts} "
109
103
  "rollouts already completed without error"
110
104
  )
111
105
  raise SystemExit(0)
112
- counts = distribute(keys, owed, config.num_rollouts)
113
- plan = [(task, n) for task, n in zip(tasks, counts) if n]
114
106
  logger.info(
115
107
  "resuming %s: %d task(s), %d rollout(s) owed",
116
108
  out,
117
- len(plan),
118
- sum(owed.values()),
109
+ sum(n > 0 for _, _, n in plan),
110
+ sum(n for _, _, n in plan),
119
111
  )
120
112
  else:
113
+ plan = plan_rollouts(tasks, config.num_rollouts)
121
114
  save_config(config, out)
122
115
  logger.info(
123
116
  "running %dx%d rollouts on %s", len(plan), config.num_rollouts, config.model
124
117
  )
125
118
  logger.info(PRIME_RL_HINT)
119
+ finished = [cast(Episode, episode) for _, kept, _ in plan for episode in kept]
126
120
  start = time.time()
127
121
  logger.info("results: %s", out)
128
122
 
@@ -148,7 +142,7 @@ async def run_eval(config: EvalConfig) -> list[Episode]:
148
142
  try:
149
143
  async with _in_process(env, config, semaphore, on_complete) as run_slot:
150
144
  # the env's own slots: it fills their live traces as the rollouts run
151
- planned = [slot for task, n in plan for slot in env.slots(task, n)]
145
+ planned = [slot for task, _, n in plan if n for slot in env.slots(task, n)]
152
146
  slots = [RunSlot.finished(episode) for episode in finished] + planned
153
147
  display = (
154
148
  dashboard(slots, config, start, push=push_state)
@@ -5,7 +5,11 @@ import re
5
5
  import httpx
6
6
  from openai import AsyncOpenAI
7
7
 
8
- from verifiers.v1.configs.client import BaseClientConfig, resolve_api_key
8
+ from verifiers.v1.configs.client import (
9
+ BaseClientConfig,
10
+ resolve_api_key,
11
+ resolve_headers,
12
+ )
9
13
 
10
14
  DEFAULT_LIMITS = httpx.Limits(max_connections=1000, max_keepalive_connections=100)
11
15
  MAX_RETRIES = 0
@@ -27,7 +31,7 @@ def build_async_openai(config: BaseClientConfig) -> AsyncOpenAI:
27
31
  return AsyncOpenAI(
28
32
  base_url=config.base_url,
29
33
  api_key=resolve_api_key(config),
30
- default_headers=config.headers or None,
34
+ default_headers=resolve_headers(config) or None,
31
35
  max_retries=MAX_RETRIES,
32
36
  http_client=build_async_httpx(config),
33
37
  )
@@ -9,7 +9,11 @@ from pydantic_core import from_json, to_json
9
9
 
10
10
  from verifiers.v1.clients.base import build_async_httpx, join_url
11
11
  from verifiers.v1.clients.client import SESSION_ID_HEADER, Client, RelayReply
12
- from verifiers.v1.configs.client import BaseClientConfig, resolve_api_key
12
+ from verifiers.v1.configs.client import (
13
+ BaseClientConfig,
14
+ resolve_api_key,
15
+ resolve_headers,
16
+ )
13
17
  from verifiers.v1.dialects import Dialect
14
18
  from verifiers.v1.errors import model_error
15
19
  from verifiers.v1.graph import PendingTurn
@@ -67,7 +71,7 @@ class EvalClient(Client):
67
71
  self.api_key = resolve_api_key(config)
68
72
  # Keep endpoint headers separate so they can override intercepted request headers before
69
73
  # the dialect's provider authentication is applied.
70
- self.headers = dict(config.headers or {})
74
+ self.headers = resolve_headers(config)
71
75
  self.client = build_async_httpx(config)
72
76
 
73
77
  async def get_response(
@@ -11,6 +11,7 @@ build clients from these. `ClientConfig` is the CLI-selectable discriminated uni
11
11
  """
12
12
 
13
13
  import os
14
+ from itertools import chain
14
15
  from typing import Annotated, Literal
15
16
  from urllib.parse import urlparse
16
17
 
@@ -48,6 +49,9 @@ class BaseClientConfig(BaseConfig):
48
49
  api_key_var: str = "PRIME_API_KEY"
49
50
  headers: dict[str, str] = Field(default_factory=dict)
50
51
  """Extra HTTP headers sent on every request."""
52
+ headers_from_env: dict[str, str] = Field(default_factory=dict)
53
+ """Header names mapped to environment variables, resolved when building a client.
54
+ Set environment values override static headers."""
51
55
  timeout: ClientTimeoutConfig = ClientTimeoutConfig()
52
56
 
53
57
  @model_validator(mode="after")
@@ -65,14 +69,6 @@ class BaseClientConfig(BaseConfig):
65
69
  and self.base_url == DEFAULT_PRIME_INFERENCE_URL
66
70
  ):
67
71
  self.base_url = prime_base_url
68
- host = urlparse(self.base_url).hostname or ""
69
- if host != PRIME_INFERENCE_HOST and not host.endswith(
70
- f".{PRIME_INFERENCE_HOST}"
71
- ):
72
- return self
73
- team_id = os.environ.get("PRIME_TEAM_ID") or prime_config.get("team_id")
74
- if team_id:
75
- self.headers.setdefault(PRIME_TEAM_ID_HEADER, team_id)
76
72
  return self
77
73
 
78
74
 
@@ -121,3 +117,29 @@ def resolve_api_key(config: BaseClientConfig) -> str:
121
117
  ):
122
118
  api_key = load_prime_config().get("api_key")
123
119
  return api_key or "EMPTY"
120
+
121
+
122
+ def resolve_headers(config: BaseClientConfig) -> dict[str, str]:
123
+ """Resolve request headers for this destination without storing credentials in config."""
124
+ # Keep original spelling for SDKs that merge default headers case-sensitively.
125
+ names: dict[str, str] = {}
126
+ headers: dict[str, str] = {}
127
+ for name, value in chain(
128
+ config.headers.items(),
129
+ (
130
+ (name, value)
131
+ for name, variable in config.headers_from_env.items()
132
+ if (value := os.environ.get(variable)) is not None
133
+ ),
134
+ ):
135
+ headers[names.setdefault(name.lower(), name)] = value
136
+ host = urlparse(config.base_url).hostname or ""
137
+ if (
138
+ config.api_key_var == "PRIME_API_KEY"
139
+ and (host == PRIME_INFERENCE_HOST or host.endswith(f".{PRIME_INFERENCE_HOST}"))
140
+ and PRIME_TEAM_ID_HEADER.lower() not in names
141
+ ):
142
+ team_id = os.environ.get("PRIME_TEAM_ID") or load_prime_config().get("team_id")
143
+ if team_id:
144
+ headers[PRIME_TEAM_ID_HEADER] = team_id
145
+ return headers
@@ -20,6 +20,8 @@ def build_reflection_lm(config: GEPAConfig) -> Callable[[str], str]:
20
20
  base_url=client.base_url,
21
21
  api_key_var=client.api_key_var,
22
22
  headers=client.headers,
23
+ headers_from_env=client.headers_from_env,
24
+ timeout=client.timeout,
23
25
  )
24
26
  )
25
27
 
@@ -45,6 +45,7 @@ from verifiers.v1.configs.client import (
45
45
  BaseClientConfig,
46
46
  TrainClientConfig,
47
47
  resolve_api_key,
48
+ resolve_headers,
48
49
  )
49
50
  from verifiers.v1.dialects import DIALECTS, Dialect
50
51
  from verifiers.v1.dialects.base import (
@@ -962,7 +963,7 @@ class InterceptionServer(Interception):
962
963
  session.adopt(asyncio.current_task())
963
964
  logger.debug("intercept models: id=%s", session.trace.id)
964
965
  config = session.ctx.client
965
- headers = dict(config.headers or {})
966
+ headers = httpx.Headers(resolve_headers(config))
966
967
  headers.update(dialect.auth_headers(resolve_api_key(config)))
967
968
  try:
968
969
  # Finite read timeout: a hung provider must not stall threshold discovery
@@ -0,0 +1,36 @@
1
+ """Rollout planning shared by in-process and served evaluations."""
2
+
3
+ from collections import defaultdict, deque
4
+ from collections.abc import Iterable
5
+
6
+ from verifiers.v1.episode import WireEpisode
7
+ from verifiers.v1.task import Task, TaskT
8
+
9
+
10
+ def plan_rollouts(
11
+ tasks: Iterable[TaskT],
12
+ num_rollouts: int,
13
+ completed: Iterable[WireEpisode] = (),
14
+ ) -> list[tuple[TaskT, list[WireEpisode], int]]:
15
+ """Assign distinct accepted episodes to selected task occurrences by content hash.
16
+
17
+ Each occurrence gets up to ``num_rollouts`` saved episodes and the count still
18
+ missing. Call separately per evaluation source; callers own acceptance and I/O.
19
+ """
20
+ saved: dict[str, deque[WireEpisode]] = defaultdict(deque)
21
+ seen: set[str] = set()
22
+ for episode in completed:
23
+ if episode.id in seen:
24
+ continue
25
+ seen.add(episode.id)
26
+ key = episode.task.hash
27
+ if key is None:
28
+ key = Task(episode.task.data).hash
29
+ saved[key].append(episode)
30
+
31
+ plan = []
32
+ for task in tasks:
33
+ episodes = saved[task.hash]
34
+ kept = [episodes.popleft() for _ in range(min(num_rollouts, len(episodes)))]
35
+ plan.append((task, kept, num_rollouts - len(kept)))
36
+ return plan
@@ -1,89 +0,0 @@
1
- """Resume an interrupted eval: reload its finished rollouts and run only the rest.
2
-
3
- `--resume` re-enters the run dir the resolved config points at and writes back into
4
- it. `load` keeps the good saved rollouts and re-runs what's owed: missing rollouts
5
- (never written) and errored ones (dropped and redone).
6
-
7
- A saved episode is matched to a selected task by its persisted `episode.task.hash`,
8
- falling back to hashing `episode.task.data` for older rows without one. Tasks with
9
- identical data are interchangeable, a task whose data changed since the interrupted
10
- run re-runs, and nothing depends on `data.idx`.
11
- """
12
-
13
- from collections import Counter, defaultdict
14
- from collections.abc import Callable
15
- from pathlib import Path
16
-
17
- from pydantic_core import from_json
18
-
19
- from verifiers.v1.episode import WireEpisode
20
- from verifiers.v1.task import task_key
21
- from verifiers.v1.utils.trace_store import TRACES_FILE
22
-
23
-
24
- def load(
25
- resume_dir: Path,
26
- selected_keys: list[str],
27
- num_rollouts: int,
28
- complete: Callable[[WireEpisode], bool] | None = None,
29
- ) -> tuple[list[WireEpisode], dict[str, int]]:
30
- """Load the good saved rollouts and diff them against the run's target: returns
31
- (kept episodes, rollouts owed per task key). `selected_keys` is one key per
32
- selected task (duplicates allowed — a key selected k times is owed up to
33
- `k * num_rollouts`; spread back over the tasks with `distribute`). `complete`
34
- is the keep-verdict (default `episode.ok`). Rewrites `traces.jsonl` to the
35
- kept rows via a temp file + atomic rename; a torn or malformed row is owed
36
- again, never a crash."""
37
- path = resume_dir / TRACES_FILE
38
- targets = {
39
- key: count * num_rollouts for key, count in Counter(selected_keys).items()
40
- }
41
-
42
- verdict = complete if complete is not None else (lambda episode: episode.ok)
43
- good: dict[str, list[tuple[bytes, WireEpisode]]] = defaultdict(list)
44
- if path.exists():
45
- with path.open("rb") as results:
46
- for line in results:
47
- if not line.strip():
48
- continue
49
- try:
50
- row = from_json(line)
51
- if "traces" not in row:
52
- continue
53
- task = row["task"]
54
- if not isinstance(task, dict):
55
- continue
56
- key = task.get("hash")
57
- if key is None:
58
- key = task_key(task["data"])
59
- except (ValueError, KeyError, IndexError, TypeError):
60
- # A torn final line (the run died mid-write) or a foreign shape
61
- # is not a keepable rollout — it's owed again, never a crash.
62
- continue
63
- if not isinstance(key, str):
64
- continue
65
- if key not in targets or len(good[key]) >= targets[key]:
66
- continue
67
- try:
68
- episode = WireEpisode.model_validate(row)
69
- if not verdict(episode):
70
- continue
71
- # A malformed row from any task/episode plugin is owed again.
72
- except Exception: # noqa: BLE001, S112
73
- continue
74
- good[key].append(
75
- (line if line.endswith(b"\n") else line + b"\n", episode)
76
- )
77
- keep: list[bytes] = []
78
- episodes: list[WireEpisode] = []
79
- owed: dict[str, int] = {}
80
- for key, target in targets.items():
81
- rows = good.get(key, [])
82
- keep.extend(line for line, _ in rows)
83
- episodes.extend(episode for _, episode in rows)
84
- if missing := target - len(rows):
85
- owed[key] = missing
86
- tmp = path.with_suffix(".jsonl.tmp")
87
- tmp.write_bytes(b"".join(keep))
88
- tmp.replace(path)
89
- return episodes, owed