verifiers 0.4.1.dev54__tar.gz → 0.4.1.dev58__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/PKG-INFO +1 -1
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/pyproject.toml +2 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_compose_scoring.py +43 -9
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/test_runtimes.py +1 -1
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/__init__.py +2 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/envs/agentic_judge/env.py +9 -9
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/errors.py +5 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/rlm/harness.py +1 -1
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/judges/rubric.py +69 -24
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/rollout.py +17 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/compose.py +21 -2
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/strategies.py +24 -2
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/harbor/taskset.py +5 -1
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/.gitignore +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/LICENSE +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/README.md +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/conftest.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/agent_user.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/agent_user_harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/counter_tool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/duet.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_acp_resume.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_agentic.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_tool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_tool_compose/docker-compose.yaml +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_user_sim.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/fetch_tool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/network_policy.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/parallel.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/pyproject.toml +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/skill_codeword.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/skills/project-codeword/SKILL.md +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/tool_response_image.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/grid.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_agent_user.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_agentic_judge.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_examples.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_limits.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_multi_agent.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_multi_turn.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_multi_turn_tool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_multimodal_tool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_network_policy.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_parallel.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_resume_tool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_rubric_judge.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_sampling.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_scoring_network.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_shared_tool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_single_turn.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_skills.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_stateful_tool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_tool_vms.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_user_echo.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/test_user_sim.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/cli/test_replay.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/conftest.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/harnesses/test_core.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/harnesses/test_rlm.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/interception/test_tunnel.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/judges/conftest.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/judges/test_judge.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/judges/test_reference.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/judges/test_rubric.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/runtimes/test_private_network.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/serve/test_client.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/serve/test_delta.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/serve/test_pool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/test_agent.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/test_dialects.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/test_graph.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/test_harbor_grading_network.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/test_scoring_network.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/test_semantic.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/test_task.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/test_taskset.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/test_trace.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/utils/test_compile.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/utils/test_loaders.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/utils/test_platform.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/unit/utils/test_score.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/acp/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/acp/runner.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/agent.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/dashboard/eval.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/dashboard/replay.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/debug.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/eval/hint.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/eval/main.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/eval/resume.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/eval/runner.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/gepa.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/replay.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/resume.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/clients/base.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/agent.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/debug.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/env.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/eval.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/replay.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/cli/validate.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/client.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/env.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/judge.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/retries.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/runtime.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/scoring.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/select.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/task.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/configs/taskset.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/env.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/envs/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/envs/best_of_n/env.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/envs/single_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/envs/single_agent/env.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/envs/user_sim/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/envs/user_sim/env.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/episode.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/adapter.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/config.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/dataset.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/reflection.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/gepa/runner.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/grading.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/graph.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/bash/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/bash/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/browser_use/program.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/deepseek/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/deepseek/gate.mjs +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/deepseek/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/deepseek/usage.mjs +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/node.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/opencode/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/opencode/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/opencode/mcp-ready.js +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/pi/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/pi/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/compaction.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/core.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/install.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/launch.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/mcp.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/harnesses/utils/replay.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/interception/base.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/interception/server.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/interception/tunnel/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/interception/tunnel/base.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/interception/tunnel/custom.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/interception/tunnel/prime.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/judge.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/judges/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/judges/decision.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/judges/reference.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/judges/reference.txt +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/judges/rubric.txt +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/mcp/launch.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/mcp/server.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/mcp/toolset.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/backends/custom.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/backends/docker.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/backends/prime.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/backends/subprocess.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/deployment.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/egress.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/private_network.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/runtimes/runtime.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/semantic.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/serve/delta.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/serve/encoding.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/session.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/state.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/task.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/trace.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/types.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/aio.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/artifacts.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/compile.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/decorators.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/env.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/eval.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/generic.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/git.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/image.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/interrupt.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/loaders.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/memory.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/paths.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/platform.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/prime.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/retries.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/scope.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/score.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/trace_store.py +0 -0
- {verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/verifiers/v1/utils/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: verifiers
|
|
3
|
-
Version: 0.4.1.
|
|
3
|
+
Version: 0.4.1.dev58
|
|
4
4
|
Summary: Verifiers: Environments for LLM Reinforcement Learning
|
|
5
5
|
Project-URL: Homepage, https://github.com/primeintellect-ai/verifiers
|
|
6
6
|
Project-URL: Documentation, https://github.com/primeintellect-ai/verifiers
|
|
@@ -131,6 +131,8 @@ bash-interception = { path = "environments/bash_interception", editable = true }
|
|
|
131
131
|
web-search-interception = { path = "environments/web_search_interception", editable = true }
|
|
132
132
|
|
|
133
133
|
[tool.uv.exclude-newer-package]
|
|
134
|
+
# CA bundle: security fixes (e.g. 2026.10.19 for the eMudhra compromise) must not wait out the cooldown
|
|
135
|
+
certifi = false
|
|
134
136
|
# Bounded cutoffs for the explicitly requested tool upgrades.
|
|
135
137
|
# Full UTC timestamps: bare dates resolve to local-tz midnight and churn the
|
|
136
138
|
# lockfile across timezones.
|
|
@@ -42,6 +42,9 @@ services:
|
|
|
42
42
|
|
|
43
43
|
class ComposeHarness(vf.Harness):
|
|
44
44
|
async def launch(self, ctx, trace, runtime, endpoint, secret, mcp_urls, data):
|
|
45
|
+
if "build-main" in data.tags:
|
|
46
|
+
result = await runtime.run(["test", "-f", "/built-from-dockerfile"], {})
|
|
47
|
+
assert result.exit_code == 0, "workspace did not use its Dockerfile"
|
|
45
48
|
return await runtime.run(
|
|
46
49
|
[
|
|
47
50
|
"python",
|
|
@@ -65,6 +68,19 @@ class ComposeTask(HarborTask):
|
|
|
65
68
|
assert all(
|
|
66
69
|
backend._host_backend.stopped for backend in SOLVERS[trace.id]
|
|
67
70
|
), "solver services survived into grading"
|
|
71
|
+
if "build-main" in self.data.tags:
|
|
72
|
+
result = await runtime.run(
|
|
73
|
+
[
|
|
74
|
+
"sh",
|
|
75
|
+
"-c",
|
|
76
|
+
"test -f /built-from-dockerfile && test ! -e /app/answer",
|
|
77
|
+
],
|
|
78
|
+
{},
|
|
79
|
+
)
|
|
80
|
+
assert result.exit_code == 0, (
|
|
81
|
+
"verifier was not rebuilt from clean inputs"
|
|
82
|
+
)
|
|
83
|
+
trace.info["verifier_rebuilt_from_dockerfile"] = True
|
|
68
84
|
trace.info["solver_released_before_grading"] = True
|
|
69
85
|
|
|
70
86
|
async def finalize_services(self, trace, targets):
|
|
@@ -80,24 +96,30 @@ class ComposeTask(HarborTask):
|
|
|
80
96
|
|
|
81
97
|
|
|
82
98
|
@pytest.mark.parametrize(
|
|
83
|
-
("mode", "collect_fails", "scoring_timeout"),
|
|
99
|
+
("mode", "collect_fails", "scoring_timeout", "build_main"),
|
|
84
100
|
[
|
|
85
|
-
("shared", True, False),
|
|
86
|
-
("isolated", False, False),
|
|
87
|
-
("isolated", True, False),
|
|
88
|
-
("isolated", False, True),
|
|
101
|
+
("shared", True, False, False),
|
|
102
|
+
("isolated", False, False, False),
|
|
103
|
+
("isolated", True, False, False),
|
|
104
|
+
("isolated", False, True, False),
|
|
105
|
+
("shared", True, False, True),
|
|
106
|
+
("isolated", False, False, True),
|
|
89
107
|
],
|
|
90
108
|
ids=[
|
|
91
109
|
"shared-skips-sidecars",
|
|
92
110
|
"isolated-restores-sidecars",
|
|
93
111
|
"isolated-collect-failure",
|
|
94
112
|
"isolated-scoring-timeout",
|
|
113
|
+
"shared-builds-main",
|
|
114
|
+
"isolated-builds-main",
|
|
95
115
|
],
|
|
96
116
|
)
|
|
97
117
|
@pytest.mark.prime
|
|
98
118
|
@pytest.mark.skipif(not os.environ.get("PRIME_API_KEY"), reason="needs PRIME_API_KEY")
|
|
99
|
-
async def test_compose_scoring(
|
|
100
|
-
|
|
119
|
+
async def test_compose_scoring(
|
|
120
|
+
tmp_path, mode, collect_fails, scoring_timeout, build_main
|
|
121
|
+
):
|
|
122
|
+
task = compose_task(tmp_path, collect_fails, scoring_timeout, mode, build_main)
|
|
101
123
|
config = vf.AgentConfig(
|
|
102
124
|
model="unused",
|
|
103
125
|
runtime=vf.PrimeConfig(labels=["vf-ci"]),
|
|
@@ -128,12 +150,23 @@ async def test_compose_scoring(tmp_path, mode, collect_fails, scoring_timeout):
|
|
|
128
150
|
assert bool(trace.info.get("solver_released_before_grading")) == (
|
|
129
151
|
mode == "isolated"
|
|
130
152
|
)
|
|
153
|
+
assert bool(trace.info.get("verifier_rebuilt_from_dockerfile")) == (
|
|
154
|
+
mode == "isolated" and build_main
|
|
155
|
+
)
|
|
131
156
|
|
|
132
157
|
|
|
133
|
-
def compose_task(
|
|
158
|
+
def compose_task(
|
|
159
|
+
tmp_path, collect_fails: bool, scoring_timeout: bool, mode: str, build_main: bool
|
|
160
|
+
):
|
|
134
161
|
environment = tmp_path / "environment"
|
|
135
162
|
environment.mkdir()
|
|
136
|
-
|
|
163
|
+
compose = COMPOSE
|
|
164
|
+
if build_main:
|
|
165
|
+
compose = compose.replace(f" image: {IMAGE}\n", "", 1)
|
|
166
|
+
(environment / "Dockerfile").write_text(
|
|
167
|
+
f"FROM {IMAGE}\nRUN touch /built-from-dockerfile\n"
|
|
168
|
+
)
|
|
169
|
+
(environment / "docker-compose.yaml").write_text(compose)
|
|
137
170
|
tests = tmp_path / "tests"
|
|
138
171
|
tests.mkdir()
|
|
139
172
|
(tests / "test.sh").write_text(
|
|
@@ -146,6 +179,7 @@ def compose_task(tmp_path, collect_fails: bool, scoring_timeout: bool, mode: str
|
|
|
146
179
|
return ComposeTask(
|
|
147
180
|
HarborData(
|
|
148
181
|
prompt="Copy the sidecar answer",
|
|
182
|
+
tags=["build-main"] if build_main else [],
|
|
149
183
|
task_dir=str(tmp_path),
|
|
150
184
|
env={"COLLECTION_SCOPE": "workspace"},
|
|
151
185
|
# Exercise agent overrides in both directions, not just task defaults.
|
|
@@ -300,7 +300,7 @@ async def test_compose(runtime, tmp_path) -> None:
|
|
|
300
300
|
spec = ComposeSpec(directory=str(tmp_path), file="docker-compose.yaml")
|
|
301
301
|
async with (
|
|
302
302
|
asyncio.timeout(TIMEOUT),
|
|
303
|
-
compose_services(runtime, spec, {}, trust_compose=True) as (services, _, _),
|
|
303
|
+
compose_services(runtime, spec, {}, trust_compose=True) as (services, _, _, _),
|
|
304
304
|
):
|
|
305
305
|
assert set(services) == {"main", "sidecar"}
|
|
306
306
|
resolved = await services["main"].bind().run(["getent", "hosts", "sidecar"], {})
|
|
@@ -60,6 +60,7 @@ from verifiers.v1.errors import (
|
|
|
60
60
|
TaskError,
|
|
61
61
|
ToolsetError,
|
|
62
62
|
TunnelError,
|
|
63
|
+
UnscoredError,
|
|
63
64
|
)
|
|
64
65
|
from verifiers.v1.grading import grade_submission
|
|
65
66
|
from verifiers.v1.graph import MessageNode
|
|
@@ -283,6 +284,7 @@ __all__ = [ # noqa: RUF022 - grouped by public API area
|
|
|
283
284
|
"ToolsetError",
|
|
284
285
|
"SandboxError",
|
|
285
286
|
"TaskError",
|
|
287
|
+
"UnscoredError",
|
|
286
288
|
"InterceptionError",
|
|
287
289
|
"TunnelError",
|
|
288
290
|
# clients
|
|
@@ -18,8 +18,10 @@ from verifiers.v1.configs.scoring import resolve_scoring
|
|
|
18
18
|
from verifiers.v1.judges.rubric import (
|
|
19
19
|
Criterion,
|
|
20
20
|
RubricVerdicts,
|
|
21
|
+
criterion_metrics,
|
|
21
22
|
load_criteria,
|
|
22
23
|
score_verdicts,
|
|
24
|
+
weighted_score,
|
|
23
25
|
)
|
|
24
26
|
from verifiers.v1.utils.compile import validate_pairing
|
|
25
27
|
|
|
@@ -45,10 +47,7 @@ SOLVED = Criterion(
|
|
|
45
47
|
|
|
46
48
|
|
|
47
49
|
def _verdict_section(criteria: list[Criterion]) -> str:
|
|
48
|
-
listing = "\n".join(
|
|
49
|
-
f"- {c.name}: {c.text} (answer one of, worst to best: {', '.join(c.choices)})"
|
|
50
|
-
for c in criteria
|
|
51
|
-
)
|
|
50
|
+
listing = "\n".join(c.render() for c in criteria)
|
|
52
51
|
return f"""\
|
|
53
52
|
## Your verdict
|
|
54
53
|
|
|
@@ -300,15 +299,16 @@ class AgenticJudgeEnv(vf.Env[AgenticJudgeEnvConfig]):
|
|
|
300
299
|
verdicts = RubricVerdicts.model_validate(verdict.info.get("verdict")).verdicts
|
|
301
300
|
criteria = self.config.task.criteria()
|
|
302
301
|
scores = score_verdicts(verdicts, criteria, "the rubric's")
|
|
303
|
-
|
|
304
|
-
solution.record_metric(f"judge/{criterion.name}", scores[criterion.name])
|
|
302
|
+
solution.record_metrics(criterion_metrics("judge", verdicts, criteria, scores))
|
|
305
303
|
if self.config.score.task_weight != 1.0:
|
|
306
304
|
for reward in solution.rewards.values():
|
|
307
305
|
if reward is not None:
|
|
308
306
|
reward.weight *= self.config.score.task_weight
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
307
|
+
solution.record_reward(
|
|
308
|
+
"judge",
|
|
309
|
+
weighted_score(scores, criteria),
|
|
310
|
+
weight=self.config.score.judge_weight,
|
|
311
|
+
)
|
|
312
312
|
|
|
313
313
|
async def run(self, task: vf.Task, agents: vf.Agents) -> None:
|
|
314
314
|
policy = resolve_scoring(task.scoring, self.config.solver.scoring)
|
|
@@ -69,6 +69,11 @@ class TaskError(RolloutError):
|
|
|
69
69
|
"""Task-authored code raised — `setup`, `finalize`, or a `@reward`/`@metric`."""
|
|
70
70
|
|
|
71
71
|
|
|
72
|
+
class UnscoredError(RolloutError):
|
|
73
|
+
"""Scoring completed but a reward came out `nan`, e.g. a judge's answer that scores
|
|
74
|
+
nothing: the rollout carries no reward signal, so consumers drop it like a failure."""
|
|
75
|
+
|
|
76
|
+
|
|
72
77
|
class InterceptionError(RolloutError):
|
|
73
78
|
"""Communication with the host interception server failed."""
|
|
74
79
|
|
|
@@ -69,7 +69,7 @@ class CompactionConfig(BaseConfig):
|
|
|
69
69
|
class RLMHarnessConfig(HarnessConfig):
|
|
70
70
|
dialect: Literal["chat_completions"] = "chat_completions"
|
|
71
71
|
version: str = Field(
|
|
72
|
-
default="
|
|
72
|
+
default="4cd7f399f5ba79c350d693af63144e2609062235", min_length=1
|
|
73
73
|
)
|
|
74
74
|
"""Git ref (branch, tag, or commit) of nano-rlm to install. Must know every
|
|
75
75
|
field this harness puts on the wire, i.e. be at least the default ref."""
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import json
|
|
5
|
+
import math
|
|
5
6
|
import re
|
|
6
7
|
import tomllib
|
|
7
8
|
from functools import cached_property
|
|
@@ -35,10 +36,6 @@ JSON_SUFFIX = (
|
|
|
35
36
|
)
|
|
36
37
|
|
|
37
38
|
|
|
38
|
-
def normalize_choice(choice: str, choices: list[str]) -> float:
|
|
39
|
-
return choices.index(choice) / (len(choices) - 1)
|
|
40
|
-
|
|
41
|
-
|
|
42
39
|
def first_verdicts_object(text: str) -> dict | None:
|
|
43
40
|
"""The first balanced JSON object in `text` that carries a `verdicts` key. Scanning for the
|
|
44
41
|
key (not just the first `{`) skips prose and, crucially, an echoed format example — the one
|
|
@@ -63,17 +60,44 @@ class Criterion(BaseModel):
|
|
|
63
60
|
text: str
|
|
64
61
|
weight: CriterionWeight = 1.0
|
|
65
62
|
"""The criterion's share of the reward (overridable per name via `weights` in config)."""
|
|
66
|
-
choices: list[str]
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
choices: list[str] | dict[str, float] = Field(
|
|
64
|
+
default_factory=lambda: ["no", "yes"], min_length=2
|
|
65
|
+
)
|
|
66
|
+
"""Allowed answers. A list is ordered **worst → best**: the first scores 0.0, the last 1.0,
|
|
67
|
+
the rest evenly spaced by rank. A mapping gives each answer its own finite score, in any
|
|
68
|
+
order; `nan` scores nothing, which leaves the rollout unscored when the criterion
|
|
69
|
+
carries weight. Default `["no", "yes"]` is a binary check. Needs >= 2, no duplicates."""
|
|
69
70
|
|
|
70
71
|
@field_validator("choices")
|
|
71
72
|
@classmethod
|
|
72
|
-
def _check_choices(
|
|
73
|
-
|
|
73
|
+
def _check_choices(
|
|
74
|
+
cls, v: list[str] | dict[str, float]
|
|
75
|
+
) -> list[str] | dict[str, float]:
|
|
76
|
+
if isinstance(v, list) and len(set(v)) != len(v):
|
|
74
77
|
raise ValueError(f"`choices` has duplicate options: {v}")
|
|
78
|
+
if isinstance(v, dict) and any(math.isinf(score) for score in v.values()):
|
|
79
|
+
raise ValueError(f"`choices` scores must be finite or nan: {v}")
|
|
75
80
|
return v
|
|
76
81
|
|
|
82
|
+
def score(self, choice: str) -> float:
|
|
83
|
+
"""The score of `choice`, one of `choices`; `nan` when it scores nothing."""
|
|
84
|
+
if isinstance(self.choices, dict):
|
|
85
|
+
return self.choices[choice]
|
|
86
|
+
return self.choices.index(choice) / (len(self.choices) - 1)
|
|
87
|
+
|
|
88
|
+
def render(self) -> str:
|
|
89
|
+
"""The criterion as a prompt line, with its allowed answers."""
|
|
90
|
+
order = "" if isinstance(self.choices, dict) else ", worst to best"
|
|
91
|
+
return f"- {self.name}: {self.text} (answer one of{order}: {', '.join(self.choices)})"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def weighted_score(scores: dict[str, float], criteria: list[Criterion]) -> float:
|
|
95
|
+
"""The criteria's weighted mean score; `nan` when a weighted criterion scored nothing.
|
|
96
|
+
Zero-weight criteria never contribute, not even their `nan`."""
|
|
97
|
+
weighted = [c for c in criteria if c.weight]
|
|
98
|
+
total = sum(c.weight for c in weighted)
|
|
99
|
+
return sum(c.weight * scores[c.name] for c in weighted) / total
|
|
100
|
+
|
|
77
101
|
|
|
78
102
|
CRITERIA_ADAPTER = TypeAdapter(list[Criterion])
|
|
79
103
|
|
|
@@ -174,15 +198,38 @@ def score_verdicts(
|
|
|
174
198
|
)
|
|
175
199
|
scores: dict[str, float] = {}
|
|
176
200
|
for name, answer in answers.items():
|
|
177
|
-
|
|
178
|
-
if answer not in choices:
|
|
201
|
+
criterion = by_criterion[name]
|
|
202
|
+
if answer not in criterion.choices:
|
|
179
203
|
raise ValueError(
|
|
180
|
-
f"judge answered {answer!r} for '{name}', expected one of
|
|
204
|
+
f"judge answered {answer!r} for '{name}', expected one of "
|
|
205
|
+
f"{list(criterion.choices)}"
|
|
181
206
|
)
|
|
182
|
-
scores[name] =
|
|
207
|
+
scores[name] = criterion.score(answer)
|
|
183
208
|
return scores
|
|
184
209
|
|
|
185
210
|
|
|
211
|
+
def criterion_metrics(
|
|
212
|
+
prefix: str,
|
|
213
|
+
verdicts: list[CriterionVerdict],
|
|
214
|
+
criteria: list[Criterion],
|
|
215
|
+
scores: dict[str, float],
|
|
216
|
+
) -> dict[str, float]:
|
|
217
|
+
"""Each criterion's score as `<prefix>/<name>`, unless it scored nothing, and for a
|
|
218
|
+
criterion with scored choices (a mapping) an indicator per choice, `<prefix>/<name>/<choice>`,
|
|
219
|
+
since several choices can share a score."""
|
|
220
|
+
answers = {verdict.name: verdict.verdict for verdict in verdicts}
|
|
221
|
+
metrics: dict[str, float] = {}
|
|
222
|
+
for criterion in criteria:
|
|
223
|
+
if not math.isnan(scores[criterion.name]):
|
|
224
|
+
metrics[f"{prefix}/{criterion.name}"] = scores[criterion.name]
|
|
225
|
+
if isinstance(criterion.choices, dict):
|
|
226
|
+
for choice in criterion.choices:
|
|
227
|
+
metrics[f"{prefix}/{criterion.name}/{choice}"] = float(
|
|
228
|
+
answers[criterion.name] == choice
|
|
229
|
+
)
|
|
230
|
+
return metrics
|
|
231
|
+
|
|
232
|
+
|
|
186
233
|
class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
|
|
187
234
|
prompt = RUBRIC_PROMPT
|
|
188
235
|
schema = RubricVerdicts
|
|
@@ -194,9 +241,6 @@ class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
|
|
|
194
241
|
async def grade_batch(
|
|
195
242
|
self, task: TaskData, trace: Trace, batch: list[Criterion]
|
|
196
243
|
) -> dict[str, float]:
|
|
197
|
-
def render(c: Criterion) -> str:
|
|
198
|
-
return f"- {c.name}: {c.text} (answer one of, worst to best: {', '.join(c.choices)})"
|
|
199
|
-
|
|
200
244
|
reference = ""
|
|
201
245
|
if self.config.answer_field:
|
|
202
246
|
answer = getattr(task, self.config.answer_field, None)
|
|
@@ -222,7 +266,7 @@ class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
|
|
|
222
266
|
fields = {
|
|
223
267
|
"question": judge_question(task, self.config.question_field),
|
|
224
268
|
"response": judge_response(trace, self.config.view),
|
|
225
|
-
"criteria": "\n".join(render(
|
|
269
|
+
"criteria": "\n".join(c.render() for c in batch),
|
|
226
270
|
"reference": reference,
|
|
227
271
|
}
|
|
228
272
|
if self.config.structured_output:
|
|
@@ -238,7 +282,11 @@ class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
|
|
|
238
282
|
)
|
|
239
283
|
verdicts = RubricVerdicts.model_validate(obj).verdicts
|
|
240
284
|
# A malformed verdict is a judge failure and must error the rollout, not score the model.
|
|
241
|
-
|
|
285
|
+
scores = score_verdicts(verdicts, batch, "the batch's")
|
|
286
|
+
trace.record_metrics(
|
|
287
|
+
criterion_metrics(self.reward_name, verdicts, batch, scores)
|
|
288
|
+
)
|
|
289
|
+
return scores
|
|
242
290
|
|
|
243
291
|
async def score(self, task: TaskData, trace: Trace) -> float:
|
|
244
292
|
criteria = self.criteria
|
|
@@ -264,12 +312,7 @@ class RubricJudge(Judge[RubricVerdicts, RubricJudgeConfig]):
|
|
|
264
312
|
by_name: dict[str, float] = {}
|
|
265
313
|
for batch_verdicts in results:
|
|
266
314
|
by_name.update(batch_verdicts)
|
|
267
|
-
|
|
268
|
-
trace.record_metric(
|
|
269
|
-
f"{self.reward_name}/{criterion.name}", by_name[criterion.name]
|
|
270
|
-
)
|
|
271
|
-
total = sum(criterion.weight for criterion in criteria)
|
|
272
|
-
return sum(c.weight * by_name[c.name] for c in criteria) / total
|
|
315
|
+
return weighted_score(by_name, criteria)
|
|
273
316
|
|
|
274
317
|
|
|
275
318
|
__all__ = [
|
|
@@ -278,4 +321,6 @@ __all__ = [
|
|
|
278
321
|
"RubricJudge",
|
|
279
322
|
"RubricJudgeConfig",
|
|
280
323
|
"RubricVerdicts",
|
|
324
|
+
"criterion_metrics",
|
|
325
|
+
"weighted_score",
|
|
281
326
|
]
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import contextlib
|
|
5
5
|
import logging
|
|
6
|
+
import math
|
|
6
7
|
import time
|
|
7
8
|
from collections.abc import Awaitable, Callable
|
|
8
9
|
from contextlib import AsyncExitStack
|
|
@@ -19,6 +20,7 @@ from verifiers.v1.errors import (
|
|
|
19
20
|
SandboxError,
|
|
20
21
|
TaskError,
|
|
21
22
|
ToolsetError,
|
|
23
|
+
UnscoredError,
|
|
22
24
|
boundary,
|
|
23
25
|
)
|
|
24
26
|
from verifiers.v1.grading import (
|
|
@@ -908,6 +910,21 @@ class Rollout:
|
|
|
908
910
|
# the metrics read what it handed over and left behind.
|
|
909
911
|
await self._close_harness()
|
|
910
912
|
await self._score_harness(runtime, self._metrics_deadline())
|
|
913
|
+
# A nan reward scores nothing: keep it unscored (None) and fail the
|
|
914
|
+
# rollout after scoring, so it is never retried as a scoring failure.
|
|
915
|
+
unscored = [
|
|
916
|
+
name
|
|
917
|
+
for name, reward in trace.rewards.items()
|
|
918
|
+
if reward is not None and math.isnan(reward.score)
|
|
919
|
+
]
|
|
920
|
+
if unscored:
|
|
921
|
+
for name in unscored:
|
|
922
|
+
trace.rewards[name] = None
|
|
923
|
+
self.fail(
|
|
924
|
+
UnscoredError(
|
|
925
|
+
f"reward {', '.join(unscored)} scored nothing (nan)"
|
|
926
|
+
)
|
|
927
|
+
)
|
|
911
928
|
trace.timing.scoring.end = time.time()
|
|
912
929
|
trace.notify()
|
|
913
930
|
except Exception as e: # noqa: BLE001 - finalize boundary records every rollout failure
|
|
@@ -85,7 +85,12 @@ async def compose_services(
|
|
|
85
85
|
trust_compose: bool = False,
|
|
86
86
|
setup_timeout: float | None = None,
|
|
87
87
|
) -> AsyncIterator[
|
|
88
|
-
tuple[
|
|
88
|
+
tuple[
|
|
89
|
+
dict[str, DockerBackend],
|
|
90
|
+
Callable[[], Awaitable[str]],
|
|
91
|
+
RuntimeBackend | None,
|
|
92
|
+
str | None,
|
|
93
|
+
]
|
|
89
94
|
]:
|
|
90
95
|
"""Own one Compose attempt and lend its services until the context exits."""
|
|
91
96
|
local = isinstance(config, DockerConfig)
|
|
@@ -186,9 +191,20 @@ async def compose_services(
|
|
|
186
191
|
}
|
|
187
192
|
}
|
|
188
193
|
}
|
|
189
|
-
|
|
194
|
+
main = authored["services"].get(spec.workspace, {})
|
|
195
|
+
if {"image", "build"} & main.keys():
|
|
190
196
|
# A template default must not replace an authored image or skip its build.
|
|
191
197
|
del base["services"][spec.workspace]["image"]
|
|
198
|
+
elif (
|
|
199
|
+
not spec.image_override
|
|
200
|
+
and (
|
|
201
|
+
directory / "task" / Path(spec.file).parent / "Dockerfile"
|
|
202
|
+
).is_file()
|
|
203
|
+
):
|
|
204
|
+
main = base["services"][spec.workspace]
|
|
205
|
+
del main["image"]
|
|
206
|
+
main["build"] = {"context": "${CONTEXT_DIR}"}
|
|
207
|
+
main["pull_policy"] = "build"
|
|
192
208
|
(directory / "base.json").write_text(json.dumps(base))
|
|
193
209
|
(directory / "env.json").write_text(
|
|
194
210
|
json.dumps({"services": {spec.workspace: {"environment": environment}}})
|
|
@@ -334,6 +350,9 @@ async def compose_services(
|
|
|
334
350
|
backends,
|
|
335
351
|
partial(compose, "stop", spec.workspace, timeout=60),
|
|
336
352
|
host_backend,
|
|
353
|
+
backends[spec.workspace].config.image
|
|
354
|
+
if services[spec.workspace].get("build")
|
|
355
|
+
else None,
|
|
337
356
|
)
|
|
338
357
|
finally:
|
|
339
358
|
await run_shielded(stack.aclose())
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import logging
|
|
5
|
-
from contextlib import AsyncExitStack
|
|
5
|
+
from contextlib import AsyncExitStack, asynccontextmanager
|
|
6
6
|
from functools import partial
|
|
7
7
|
|
|
8
8
|
from verifiers.v1.runtimes.compose import compose_services
|
|
@@ -37,13 +37,19 @@ class _ContainerDeployment(_DeploymentStrategy):
|
|
|
37
37
|
if d.borrowed_runtime is not None:
|
|
38
38
|
raise ValueError("a composed deployment cannot borrow a single target")
|
|
39
39
|
self._services = await d.enter(AsyncExitStack())
|
|
40
|
-
|
|
40
|
+
(
|
|
41
|
+
services,
|
|
42
|
+
self._stop_main,
|
|
43
|
+
host,
|
|
44
|
+
built_image,
|
|
45
|
+
) = await self._services.enter_async_context(
|
|
41
46
|
compose_services(
|
|
42
47
|
d.backend.config, d.spec, d.env, trust_compose=d.config.trust_compose
|
|
43
48
|
)
|
|
44
49
|
)
|
|
45
50
|
d.target_backends = dict(services)
|
|
46
51
|
d.execution_backend = d.harness_backend = services[d.spec.workspace]
|
|
52
|
+
self._remote_built_image = built_image if host is not None else None
|
|
47
53
|
|
|
48
54
|
async def stop_execution(self, d):
|
|
49
55
|
await self._stop_main()
|
|
@@ -57,6 +63,22 @@ class _ContainerDeployment(_DeploymentStrategy):
|
|
|
57
63
|
"solver services teardown failed before grading", exc_info=True
|
|
58
64
|
)
|
|
59
65
|
|
|
66
|
+
@asynccontextmanager
|
|
67
|
+
async def verifier(self, deployment, config, env):
|
|
68
|
+
if self._remote_built_image is None or config.image != self._remote_built_image:
|
|
69
|
+
async with super().verifier(deployment, config, env) as backend:
|
|
70
|
+
yield backend
|
|
71
|
+
return
|
|
72
|
+
# Rebuild from trusted task inputs on a fresh host: the solver's Docker tag
|
|
73
|
+
# is local to its released VM, and its modified container must never travel.
|
|
74
|
+
async with compose_services(
|
|
75
|
+
config,
|
|
76
|
+
deployment.spec,
|
|
77
|
+
env,
|
|
78
|
+
trust_compose=deployment.config.trust_compose,
|
|
79
|
+
) as (services, _, _, _):
|
|
80
|
+
yield services[deployment.spec.workspace]
|
|
81
|
+
|
|
60
82
|
|
|
61
83
|
class _PrivateNetworkDeployment(_DeploymentStrategy):
|
|
62
84
|
async def start(self, d):
|
|
@@ -708,7 +708,11 @@ def resolve_image(
|
|
|
708
708
|
import yaml
|
|
709
709
|
|
|
710
710
|
main = yaml.safe_load(compose.read_text())["services"].get("main", {})
|
|
711
|
-
if
|
|
711
|
+
if (
|
|
712
|
+
main.get("image")
|
|
713
|
+
or "build" in main
|
|
714
|
+
or (task_dir / "environment/Dockerfile").is_file()
|
|
715
|
+
):
|
|
712
716
|
return None
|
|
713
717
|
section = "verifier.environment" if verifier else "environment"
|
|
714
718
|
dockerfile = "tests/Dockerfile" if verifier else "environment/Dockerfile"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/agent_user_harness.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/echo_acp_resume.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/network_policy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/skill_codeword.py
RENAMED
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev54 → verifiers-0.4.1.dev58}/tests/integration/fixtures/tool_response_image.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|