verifiers 0.4.2.dev27__tar.gz → 0.4.2.dev29__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.2.dev27 → verifiers-0.4.2.dev29}/PKG-INFO +1 -1
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_taskset.py +10 -0
- verifiers-0.4.2.dev29/tests/unit/utils/test_artifacts.py +114 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/select.py +29 -1
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/harbor/taskset.py +5 -1
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/artifacts.py +52 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/.gitignore +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/LICENSE +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/README.md +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/pyproject.toml +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/conftest.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/agent_user.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/agent_user_harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/counter_tool.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/duet.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/echo.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/echo_acp_resume.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/echo_agentic.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/echo_tool.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/echo_user_sim.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/fetch_tool.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/network_policy.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/parallel.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/pyproject.toml +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/skill_codeword.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/skills/project-codeword/SKILL.md +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/tool_error.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/tool_response_image.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/grid.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_agent_user.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_agentic_judge.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_examples.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_limits.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_mounts.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_multi_agent.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_multi_turn.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_multi_turn_tool.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_multimodal_tool.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_native_compose.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_network_policy.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_parallel.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_resume_tool.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_rubric_judge.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_sampling.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_scoring_network.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_service_scoring.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_shared_tool.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_single_turn.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_skills.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_stateful_tool.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_tool_vms.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_user_echo.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/test_user_sim.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/conftest.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/harnesses/test_core.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/harnesses/test_rlm.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/interception/test_tunnel.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/judges/conftest.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/judges/test_judge.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/judges/test_reference.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/judges/test_rubric.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/runtimes/test_private_network.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_agent.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_api.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_best_of_n_judge.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_delta.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_dialects.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_graph.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_harbor_grading_network.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_retry_ids.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_runtimes.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_scoring_network.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_semantic.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_task.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_token_arrays.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/test_trace.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/utils/test_compile.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/utils/test_loaders.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/unit/utils/test_score.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/acp/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/acp/runner.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/agent.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/cli/debug.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/cli/gepa.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/cli/resume.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/cli/run.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/clients/base.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/agent.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/cli/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/cli/debug.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/cli/env.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/cli/run.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/cli/validate.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/client.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/deployment.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/env.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/interception.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/judge.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/retries.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/runtime.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/sampling.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/scoring.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/task.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/configs/taskset.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/delta.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/env.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/agentic_judge/env.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/best_of_n/env.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/best_of_n_judge/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/best_of_n_judge/env.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/single_agent/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/single_agent/env.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/user_sim/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/user_sim/env.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/episode.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/errors.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/gepa/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/gepa/adapter.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/gepa/config.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/gepa/dataset.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/gepa/reflection.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/gepa/runner.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/grading.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/graph.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/bash/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/bash/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/browser_use/program.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/deepseek/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/deepseek/gate.mjs +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/deepseek/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/deepseek/usage.mjs +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/node.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/opencode/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/opencode/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/opencode/mcp-ready.js +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/pi/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/pi/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/stirrup/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/stirrup/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/stirrup/program.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/utils/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/utils/compaction.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/utils/core.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/utils/install.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/utils/launch.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/utils/mcp.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/harnesses/utils/replay.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/interception/base.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/interception/server.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/interception/tunnel/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/interception/tunnel/base.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/interception/tunnel/custom.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/interception/tunnel/prime.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/judge.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/judges/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/judges/decision.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/judges/reference.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/judges/reference.txt +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/judges/rubric.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/judges/rubric.txt +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/mcp/launch.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/mcp/server.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/mcp/toolset.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/rollout.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/backends/custom.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/backends/docker.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/backends/prime.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/backends/subprocess.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/compose.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/deployment.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/egress.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/native_compose.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/private_network.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/runtime.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/runtimes/strategies.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/semantic.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/session.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/state.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/task.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/trace.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/types.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/aio.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/compile.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/decorators.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/env.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/eval.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/generic.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/git.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/image.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/interrupt.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/loaders.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/memory.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/network.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/paths.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/prime.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/retries.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/scope.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/score.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/utils/trace_store.py +0 -0
- {verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/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.2.
|
|
3
|
+
Version: 0.4.2.dev29
|
|
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
|
|
@@ -102,6 +102,16 @@ def test_exclude_drops_tasks_that_any_list_names() -> None:
|
|
|
102
102
|
assert idxs(finite().exclude(idx=":7", names=["t8"])) == [7, 9]
|
|
103
103
|
|
|
104
104
|
|
|
105
|
+
def test_match_lists_extend_from_files(tmp_path) -> None:
|
|
106
|
+
(tmp_path / "idx.txt").write_text("0:2\n\n5\n")
|
|
107
|
+
(tmp_path / "names.txt").write_text(" t8 \nt9\n")
|
|
108
|
+
files = {"idx": tmp_path / "idx.txt", "names": tmp_path / "names.txt"}
|
|
109
|
+
assert idxs(finite().include(idx=[3], files=files)) == [0, 1, 3, 5, 8, 9]
|
|
110
|
+
config = vf.SelectConfig(exclude={"files": {"names": tmp_path / "names.txt"}})
|
|
111
|
+
assert config.exclude.names == ["t8", "t9"] and config.exclude.files.names is None
|
|
112
|
+
assert idxs(finite().select(config)) == list(range(8))
|
|
113
|
+
|
|
114
|
+
|
|
105
115
|
def test_unmatched_entries_warn(caplog) -> None:
|
|
106
116
|
with caplog.at_level(logging.WARNING):
|
|
107
117
|
assert idxs(finite().include(names=["t1", "typo"], idx=[42])) == [1]
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"""Artifact restore: the grading box extracts only what host-side validation read."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import io
|
|
5
|
+
import shutil
|
|
6
|
+
import subprocess
|
|
7
|
+
import tarfile
|
|
8
|
+
from types import SimpleNamespace
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from verifiers.v1.utils.artifacts import restore
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class RecordingRuntime:
|
|
16
|
+
"""Records the archives `restore` sends and accepts every command."""
|
|
17
|
+
|
|
18
|
+
def __init__(self) -> None:
|
|
19
|
+
self.config = SimpleNamespace(type="docker", mounts={}, workdir="/app")
|
|
20
|
+
self.written: list[bytes] = []
|
|
21
|
+
|
|
22
|
+
async def write(self, path: str, data: bytes) -> None:
|
|
23
|
+
self.written.append(data)
|
|
24
|
+
|
|
25
|
+
async def run(self, argv, env):
|
|
26
|
+
return SimpleNamespace(exit_code=0, stdout="", stderr="")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def make_archive(build) -> bytes:
|
|
30
|
+
buffer = io.BytesIO()
|
|
31
|
+
with tarfile.open(fileobj=buffer, mode="w:", format=tarfile.GNU_FORMAT) as tar:
|
|
32
|
+
build(tar)
|
|
33
|
+
return buffer.getvalue()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def add_file(tar: tarfile.TarFile, name: str, data: bytes, **fields) -> None:
|
|
37
|
+
info = tarfile.TarInfo(name)
|
|
38
|
+
info.size = len(data)
|
|
39
|
+
for key, value in fields.items():
|
|
40
|
+
setattr(info, key, value)
|
|
41
|
+
tar.addfile(info, io.BytesIO(data))
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def restored(archive: bytes, root: str = "/app/results") -> bytes:
|
|
45
|
+
runtime = RecordingRuntime()
|
|
46
|
+
asyncio.run(restore(runtime, {root: archive}))
|
|
47
|
+
assert len(runtime.written) == 1
|
|
48
|
+
return runtime.written[0]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_restore_keeps_owners_and_drops_special_mode_bits() -> None:
|
|
52
|
+
def build(tar):
|
|
53
|
+
directory = tarfile.TarInfo("app/results")
|
|
54
|
+
directory.type, directory.mode, directory.uid = tarfile.DIRTYPE, 0o1777, 1000
|
|
55
|
+
tar.addfile(directory)
|
|
56
|
+
add_file(
|
|
57
|
+
tar, "app/results/run", b"#!/bin/sh\n", mode=0o4755, uid=1000, gid=1000
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
with tarfile.open(fileobj=io.BytesIO(restored(make_archive(build)))) as tar:
|
|
61
|
+
members = {m.name: m for m in tar.getmembers()}
|
|
62
|
+
|
|
63
|
+
assert members["app/results"].mode == 0o777
|
|
64
|
+
assert members["app/results/run"].mode == 0o755
|
|
65
|
+
assert (members["app/results/run"].uid, members["app/results/run"].gid) == (
|
|
66
|
+
1000,
|
|
67
|
+
1000,
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@pytest.mark.skipif(shutil.which("tar") is None, reason="needs a system tar")
|
|
72
|
+
def test_system_tar_lists_exactly_what_python_read() -> None:
|
|
73
|
+
long_name = "app/results/" + "nested/" * 20 + "phase_map.csv"
|
|
74
|
+
|
|
75
|
+
def build(tar):
|
|
76
|
+
add_file(tar, "app/results/a.txt", b"a")
|
|
77
|
+
add_file(tar, long_name, b"b")
|
|
78
|
+
link = tarfile.TarInfo("app/results/link")
|
|
79
|
+
link.type, link.linkname = tarfile.SYMTYPE, "a.txt"
|
|
80
|
+
tar.addfile(link)
|
|
81
|
+
hard = tarfile.TarInfo("app/results/hard")
|
|
82
|
+
hard.type, hard.linkname = tarfile.LNKTYPE, "app/results/a.txt"
|
|
83
|
+
tar.addfile(hard)
|
|
84
|
+
|
|
85
|
+
original = make_archive(build)
|
|
86
|
+
with tarfile.open(fileobj=io.BytesIO(original)) as tar:
|
|
87
|
+
python_names = [m.name for m in tar.getmembers()]
|
|
88
|
+
|
|
89
|
+
listing = subprocess.run(
|
|
90
|
+
["tar", "-tf", "-"],
|
|
91
|
+
input=restored(original),
|
|
92
|
+
capture_output=True,
|
|
93
|
+
check=True,
|
|
94
|
+
).stdout.decode()
|
|
95
|
+
|
|
96
|
+
assert listing.splitlines() == python_names
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def test_restore_refuses_sparse_members() -> None:
|
|
100
|
+
# A few header bytes declare a terabyte: rebuilding it would fill host memory.
|
|
101
|
+
header = tarfile.TarInfo("app/results/hole")
|
|
102
|
+
header.type = tarfile.GNUTYPE_SPARSE
|
|
103
|
+
block = bytearray(header.tobuf(format=tarfile.GNU_FORMAT))
|
|
104
|
+
block[386:398] = b"00000000000\0" # first sparse entry: offset 0
|
|
105
|
+
block[398:410] = b"00000000000\0" # ... holding 0 bytes of data
|
|
106
|
+
block[483:495] = b"%011o\0" % (1 << 40) # real size
|
|
107
|
+
block[148:156] = b" " * 8
|
|
108
|
+
block[148:156] = b"%06o\0 " % sum(block)
|
|
109
|
+
archive = bytes(block) + bytes(2 * tarfile.BLOCKSIZE)
|
|
110
|
+
|
|
111
|
+
runtime = RecordingRuntime()
|
|
112
|
+
with pytest.raises(RuntimeError, match="sparse"):
|
|
113
|
+
asyncio.run(restore(runtime, {"/app/results": archive}))
|
|
114
|
+
assert runtime.written == []
|
|
@@ -3,13 +3,24 @@
|
|
|
3
3
|
|
|
4
4
|
import re
|
|
5
5
|
import sys
|
|
6
|
+
from pathlib import Path
|
|
6
7
|
|
|
7
|
-
from pydantic import AliasChoices, Field, field_validator
|
|
8
|
+
from pydantic import AliasChoices, Field, field_validator, model_validator
|
|
8
9
|
from pydantic_config import BaseConfig
|
|
9
10
|
|
|
10
11
|
IDX_RANGE = re.compile(r"(\d*):(\d*)(?::(\d*))?")
|
|
11
12
|
|
|
12
13
|
|
|
14
|
+
class TaskMatchFilesConfig(BaseConfig):
|
|
15
|
+
"""Newline-delimited text files with more entries for each `TaskMatchConfig`
|
|
16
|
+
list, one entry per line. Blank lines are skipped."""
|
|
17
|
+
|
|
18
|
+
idx: Path | None = None
|
|
19
|
+
ids: Path | None = None
|
|
20
|
+
keys: Path | None = None
|
|
21
|
+
names: Path | None = None
|
|
22
|
+
|
|
23
|
+
|
|
13
24
|
class TaskMatchConfig(BaseConfig):
|
|
14
25
|
"""Tasks named by position or identity; a task matches when any list names it."""
|
|
15
26
|
|
|
@@ -24,6 +35,10 @@ class TaskMatchConfig(BaseConfig):
|
|
|
24
35
|
"""`Task.key` values, as recorded on each trace (`task.key`)."""
|
|
25
36
|
names: list[str] = Field(default_factory=list)
|
|
26
37
|
"""`TaskData.name` values."""
|
|
38
|
+
files: TaskMatchFilesConfig = TaskMatchFilesConfig()
|
|
39
|
+
"""Files whose lines extend the lists above, for selections too long to write
|
|
40
|
+
inline (`files.ids = "ids.txt"`). Validation reads them into the lists and
|
|
41
|
+
resets `files`."""
|
|
27
42
|
|
|
28
43
|
@field_validator("idx", mode="before")
|
|
29
44
|
@classmethod
|
|
@@ -36,6 +51,19 @@ class TaskMatchConfig(BaseConfig):
|
|
|
36
51
|
items.extend(_parse_idx_item(part) for part in parts)
|
|
37
52
|
return items
|
|
38
53
|
|
|
54
|
+
@model_validator(mode="after")
|
|
55
|
+
def _read_files(self):
|
|
56
|
+
for field, path in self.files:
|
|
57
|
+
if path is None:
|
|
58
|
+
continue
|
|
59
|
+
lines = [line.strip() for line in path.read_text().splitlines()]
|
|
60
|
+
entries = [line for line in lines if line]
|
|
61
|
+
if field == "idx":
|
|
62
|
+
entries = [_parse_idx_item(entry) for entry in entries]
|
|
63
|
+
getattr(self, field).extend(entries)
|
|
64
|
+
self.files = TaskMatchFilesConfig()
|
|
65
|
+
return self
|
|
66
|
+
|
|
39
67
|
@property
|
|
40
68
|
def empty(self) -> bool:
|
|
41
69
|
return not (self.idx or self.ids or self.keys or self.names)
|
|
@@ -410,7 +410,10 @@ class HarborTask(Task[HarborData, State, HarborTaskConfig]):
|
|
|
410
410
|
"mkdir -p /tests && tar -xzf /tmp/tests.tgz -C /tests"
|
|
411
411
|
)
|
|
412
412
|
# Verifier subprocesses can use different users; opening their log directory
|
|
413
|
-
# requires its owner or root, even when it is already writable.
|
|
413
|
+
# requires its owner or root, even when it is already writable. A grading box
|
|
414
|
+
# of its own starts with an empty log directory: anything already there came
|
|
415
|
+
# from the image or from the agent's restored artifacts, not from this grader.
|
|
416
|
+
isolated = wipe or self.scoring.mode == "isolated"
|
|
414
417
|
setup = (
|
|
415
418
|
runtime.with_user("root")
|
|
416
419
|
if runtime.backend.SUPPORTS_USER_SWITCHING
|
|
@@ -420,6 +423,7 @@ class HarborTask(Task[HarborData, State, HarborTaskConfig]):
|
|
|
420
423
|
(
|
|
421
424
|
setup,
|
|
422
425
|
(
|
|
426
|
+
f"{'rm -rf /logs/verifier && ' if isolated else ''}"
|
|
423
427
|
f"mkdir -p /logs/verifier {ARTIFACTS_DIR} && "
|
|
424
428
|
f"chmod 777 /logs/verifier {ARTIFACTS_DIR}"
|
|
425
429
|
),
|
|
@@ -341,6 +341,10 @@ async def restore(runtime: Runtime, collected: dict[str, bytes | None]) -> None:
|
|
|
341
341
|
)
|
|
342
342
|
for root, archive in collected.items():
|
|
343
343
|
_validate_restore(root, archive)
|
|
344
|
+
collected = {
|
|
345
|
+
root: None if archive is None else _rebuild(archive)
|
|
346
|
+
for root, archive in collected.items()
|
|
347
|
+
}
|
|
344
348
|
# Clear every root up front, not per entry: a later nested root would otherwise
|
|
345
349
|
# delete content an earlier one just restored. Clearing also drops any file or
|
|
346
350
|
# symlink the image left at the target.
|
|
@@ -425,6 +429,45 @@ def _drop_special_files(archive: bytes) -> tuple[bytes, list[str]]:
|
|
|
425
429
|
return out.getvalue(), dropped
|
|
426
430
|
|
|
427
431
|
|
|
432
|
+
def _rebuild(archive: bytes) -> bytes:
|
|
433
|
+
"""Write a fresh archive holding exactly the members Python's tarfile reads.
|
|
434
|
+
|
|
435
|
+
Validation reads archives with Python's tarfile, but the grading box extracts
|
|
436
|
+
them with its own tar. An agent controls the archive bytes, and two tar parsers
|
|
437
|
+
can disagree about the same bytes, so the box only ever extracts an archive
|
|
438
|
+
written here from the members validation saw. Owners and permission bits are
|
|
439
|
+
kept (tasks rely on ownership, e.g. git's safe.directory check); setuid,
|
|
440
|
+
setgid and sticky bits are not.
|
|
441
|
+
"""
|
|
442
|
+
out = io.BytesIO()
|
|
443
|
+
with (
|
|
444
|
+
tarfile.open(fileobj=io.BytesIO(archive), mode="r:") as source,
|
|
445
|
+
tarfile.open(fileobj=out, mode="w:", format=tarfile.PAX_FORMAT) as target,
|
|
446
|
+
):
|
|
447
|
+
for member in source:
|
|
448
|
+
info = tarfile.TarInfo(member.name)
|
|
449
|
+
info.mode = member.mode & 0o777
|
|
450
|
+
info.uid, info.gid = member.uid, member.gid
|
|
451
|
+
info.uname, info.gname = member.uname, member.gname
|
|
452
|
+
info.mtime = member.mtime
|
|
453
|
+
content = None
|
|
454
|
+
if member.isfile():
|
|
455
|
+
info.type = tarfile.REGTYPE
|
|
456
|
+
info.size = member.size
|
|
457
|
+
content = source.extractfile(member)
|
|
458
|
+
elif member.isdir():
|
|
459
|
+
info.type = tarfile.DIRTYPE
|
|
460
|
+
elif member.issym() or member.islnk():
|
|
461
|
+
info.type = tarfile.SYMTYPE if member.issym() else tarfile.LNKTYPE
|
|
462
|
+
info.linkname = member.linkname
|
|
463
|
+
else:
|
|
464
|
+
raise RuntimeError(
|
|
465
|
+
f"artifact member {member.name!r} is a link or special file"
|
|
466
|
+
)
|
|
467
|
+
target.addfile(info, content)
|
|
468
|
+
return out.getvalue()
|
|
469
|
+
|
|
470
|
+
|
|
428
471
|
def _validate_restore(root: str, archive: bytes | None) -> None:
|
|
429
472
|
"""Reject archive content that could restore outside its declared root."""
|
|
430
473
|
root_path = PurePosixPath(root)
|
|
@@ -482,6 +525,15 @@ def _validate_restore(root: str, archive: bytes | None) -> None:
|
|
|
482
525
|
raise RuntimeError(
|
|
483
526
|
f"artifact member {member.name!r} is a link or special file"
|
|
484
527
|
)
|
|
528
|
+
if member.issparse():
|
|
529
|
+
# A sparse member declares its full size in a few header bytes,
|
|
530
|
+
# and rebuilding the archive on the host would write every hole
|
|
531
|
+
# out as zeros. GNU tar only writes these with --sparse; bsdtar
|
|
532
|
+
# writes them for any file with holes.
|
|
533
|
+
raise RuntimeError(
|
|
534
|
+
f"artifact member {member.name!r} is a sparse file, which "
|
|
535
|
+
"cannot be restored"
|
|
536
|
+
)
|
|
485
537
|
if member.isfile():
|
|
486
538
|
regular_files.add(member_path)
|
|
487
539
|
# Check after reading the whole archive, so a later symlink cannot
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/agent_user_harness.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/echo_acp_resume.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/network_policy.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/tests/integration/fixtures/skill_codeword.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/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
|
|
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
|
|
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
|
|
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
|
{verifiers-0.4.2.dev27 → verifiers-0.4.2.dev29}/verifiers/v1/envs/best_of_n_judge/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|