benchflow 0.5.3.dev976__tar.gz → 0.5.3.dev980__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.
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/PKG-INFO +1 -1
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/pyproject.toml +1 -1
- benchflow-0.5.3.dev980/src/benchflow/_utils/dataset_registry.py +216 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/cli/main.py +88 -3
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/evaluation.py +33 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rollout.py +30 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/check_results.py +107 -1
- benchflow-0.5.3.dev980/tests/test_dataset_registry.py +502 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_integration_check_results.py +254 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/.gitignore +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/CHANGELOG.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/LICENSE +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/README.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_dotenv.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_paths.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_run.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_types.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/benchmark_repos.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/config.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/evaluation_results.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/json_safe.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/learner_memory.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/result_metadata.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/reward_events.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/scoring.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/source_provenance.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/task_authoring.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/yaml_loader.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/client.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/container_transport.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/runtime.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/session.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/transport.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/types.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/harbor.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/inbound.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/inspect_ai.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/ors.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/terminal_bench.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/codex_config.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/credentials.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/env.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/errors.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/harvey_lab_acp_shim.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/install.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/openclaw_acp_shim.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/pi_acp_launcher.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/protocol.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/providers.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/registry.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/branch.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/cli/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/cli/continue_cmd.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/cli/trace_import.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/compat/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/compat/harbor_registry.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/batch.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/orchestrator.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/replay_proxy.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/run_folder.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/sandbox_proxy.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/contracts/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/contracts/planes.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/contracts/user.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/demo_task/environment/Dockerfile +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/demo_task/instruction.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/demo_task/task.toml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/demo_task/tests/test.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/diagnostics.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/environment/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/environment/manifest.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/environment/manifest_env.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/environment/protocol.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/environment/readiness.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/eval_sharding.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/eval_worker.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/experimental/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/experimental/mcp/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/experimental/mcp/hooks.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/experimental/mcp/reviewer_server.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/hosted_env.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/learner_skills.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/learner_store.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/metrics.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/models.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/monitor.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/litellm_bedrock_patch.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/litellm_bedrock_preflight.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/litellm_config.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/litellm_logging.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/litellm_runtime.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/runtime.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/py.typed +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/README.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/builtins.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/events.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/file_readers.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/llm.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/memory_scorer.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/node.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/protocol.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/rubric.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/rubric_config.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/validation.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rollout_branch.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rollout_planes.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/runtime.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_base.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_cache_reclaim.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_compose.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_compose_files/docker-compose-base.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_compose_files/docker-compose-build.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_compose_files/docker-compose-no-network.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_compose_files/docker-compose-prebuilt.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_sdk_ops.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/daytona.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/docker.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/lockdown.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/metadata.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/modal_impl.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/process.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/protocol.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/services.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/setup.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/snapshot.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/user.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/scenes.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sdk.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/self_gen.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skill_eval/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skill_eval/_core.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skill_eval/gepa_export.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skill_eval/schema.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skill_policy.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skills.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/config.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/env.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/paths.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/task.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/verifier.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/templates/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/templates/judge.py.tmpl +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/templates/test.sh.tmpl +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/huggingface.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/local.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/models.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/parsers.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/task_gen.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/_capture.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/export.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/metrics.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/otel.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/tree.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/types.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/viewer.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/usage_tracking.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/agents/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/agents/test_protocol.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/README.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/environment/Dockerfile +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/environment/docker-compose.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/environment/skills/conformance-writer/SKILL.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/instruction.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/solution/solve.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/task.toml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/tests/test.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/conformance-results.json +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/proof_multi_agent.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/proof_snapshot.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/run_conformance.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/self_gen_smoke_skills/skill-creator/SKILL.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conftest.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/_helpers.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/test_batch.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/test_orchestrator.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/test_replay_proxy.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/test_run_folder.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_chibench_manifest.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_clawsbench_manifest.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_manifest.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_manifest_env.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_protocol.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_readiness.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/hello-world-task/environment/Dockerfile +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/hello-world-task/instruction.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/hello-world-task/solution/solve.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/hello-world-task/task.toml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/hello-world-task/tests/test.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/environment/Dockerfile +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/instruction.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/solution/solve.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/task.toml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/tests/test.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/tests/test_state.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/test_claude.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/test_codex.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/test_codex_custom_provider.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/test_gemini.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/test_openclaw.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/traces/minimal-claude.jsonl +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/traces/minimal-opentraces.jsonl +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/README.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/alpha-task/environment/Dockerfile +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/alpha-task/instruction.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/alpha-task/task.toml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/alpha-task/tests/test.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/beta-task/data/empty.bin +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/beta-task/data/unicode.txt +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/beta-task/instruction.md +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/beta-task/task.toml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/not-a-task/notes.txt +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/mock_acp_agent.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/mock_acp_agent_interleaved.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/mock_acp_agent_multi_turn.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/mock_openai_responses_server.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/check_adapter_evidence.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/check_hosted_env_evidence.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/check_skillsbench_harbor_parity.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/check_trace_to_task_evidence.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/claude-agent-acp.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/codex-acp.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/gemini.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/harvey-lab-harness.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/openclaw.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/opencode.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/openhands.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/pi-acp.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/run.sh +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/run_suite.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/suites/release.yaml +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_acp.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_acp_capability_advertising.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_acp_model_config_dispatch.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_acp_pinned_protocol_guard.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_acp_setup_failure_propagation.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_adapter_scripts.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_adapters.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_cli.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_env_resolution.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_gemini_defaults.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_idle_timeout_cli.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_model_decouple.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_registry.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_setup.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_spec.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_base_install_imports.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_bedrock_thinking.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_branch.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_capture_trajectory.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_clawsbench_slice.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_cli_daytona.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_cli_docs_drift.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_cli_misc.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_compat_harbor_registry.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_config_redaction.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_connect_as_env.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_continuallearningbench_adapter.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_credential_env_scrub.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_daytona_key.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_no_host_paths.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_release_evidence.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_roadmap.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_symlink_ingestion.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_sync.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_daytona_command_polling.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_daytona_litellm_runtime.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_daytona_status.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_docker_prune_scoping.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_docker_uploads.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_docs_examples.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eng50_capabilities.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_env_setup.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_environment_manifest_controls.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_filters_applied.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_sharding.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_single_task_summary.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_source_provenance.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_worker_retry.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_zero_task_guard.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_evaluation_environment_manifest.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_exclude_tasks.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_experiments_status.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_harvey_lab_shim.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_hf_scores.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_hilbench_adapter.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_hosted_env.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_hosted_env_rollout_contract.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_inbound_adapter_manifest.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_inbound_adapters.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_integration_run_suite.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_internet_policy.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_job.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_job_sequential_shared.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_job_sequential_shared_resume.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_judge_symlink_ingestion.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_learner_skills.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_learner_skills_traversal.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_learner_store.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_learner_store_persistence.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_litellm_config.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_litellm_hardening.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_litellm_logging.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_litellm_runtime.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_litellm_smoke.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_llm_judge.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_llm_judge_event_tags.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_llm_judge_verifier.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_memory_scorer.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_metrics.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_mock_openai_responses_server.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_monitor_scaffold.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_native_acp_usage.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_no_cross_provider_fallback.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_notification_order_real.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_oracle.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_oracle_chokepoint.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_paths_safe.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_paths_symlink_helpers.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_pi_acp_launcher.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_process.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_provider_auth_detection.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_providers.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_reexport.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_registry_invariants.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_release_version.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_resolve_env_helpers.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_reward_node.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_reward_unified_contract.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rewards.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rewards_jsonl.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_architecture.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_branch.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_config_path_coercion.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_environment.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_import_no_side_effects.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_on_ask_user_wiring.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_probe_sandbox_health.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_upload.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rubric_config.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_runtime.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_runtime_config_wired.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_runtime_live_sandbox.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_exec_secret_handling.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_hardening.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_isolation_copy_traversal.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_multi_service.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_protocol.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_setup.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_snapshot_contract.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_upload_symlink.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_verifier_workspace.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_scene.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_scene_outbox_trial.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_scene_parallel_group.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_scene_result_aggregation.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_scoring.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sdk_internals.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sdk_lockdown.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_self_gen_cli.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_self_gen_export_error_channel.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_self_gen_export_failures.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_self_gen_orchestration.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_session_request_permission_dispatch.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_eval.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_eval_dryrun.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_eval_integration.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_eval_sweep.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_eval_traversal.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_invocation_artifacts.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_policy.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skills.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skills_dir_agent_home_link.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skillsbench_harbor_parity.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skillsbench_harbor_run_suite.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skillsbench_publish_scrub.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_smoke.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_subscription_auth.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_task_check_eval_consistency.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_task_config.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_task_digest.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_task_download.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_tasks.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_token_usage_normalization.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trace_import_cli.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trace_task_gen_traversal.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trace_to_task_evidence.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_traces_huggingface.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_traces_parsers.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_traces_task_gen.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_train_mode_artifact_emission.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trajectory_integration.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trajectory_streaming.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trial_agent_timeout_verify.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trial_install_agent_timeout.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trial_litellm_runtime.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_usage_litellm.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_usage_required.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_usage_tracking.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_user.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_verifier_multi_container.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_verifier_output.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_verifier_output_freshness.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_verify.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_workflow_action_pinning.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_yaml_config.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/__init__.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/test_export.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/test_export_nan_handling.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/test_redaction.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/test_step_granularity.py +0 -0
- {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/test_tree.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: benchflow
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev980
|
|
4
4
|
Summary: Multi-turn agent benchmarking with ACP — run any agent, any model, any provider.
|
|
5
5
|
Project-URL: Homepage, https://github.com/benchflow-ai/benchflow
|
|
6
6
|
Project-URL: Repository, https://github.com/benchflow-ai/benchflow
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""Dataset registry resolution — `bench eval create -d skillsbench@1.1`.
|
|
2
|
+
|
|
3
|
+
Resolves a published dataset version from the skillsbench registry
|
|
4
|
+
(``registry.json``, see ``docs/dataset-versioning.md`` in
|
|
5
|
+
benchflow-ai/skillsbench): clones the pinned snapshot, verifies every
|
|
6
|
+
task's content digest against the registry entry, and hands back the
|
|
7
|
+
task set plus source provenance for result stamping.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import posixpath
|
|
12
|
+
import re
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Any
|
|
16
|
+
from urllib.request import urlopen
|
|
17
|
+
|
|
18
|
+
from benchflow._utils import benchmark_repos
|
|
19
|
+
from benchflow._utils.task_authoring import task_digest
|
|
20
|
+
|
|
21
|
+
DEFAULT_REGISTRY_SOURCE = (
|
|
22
|
+
"https://raw.githubusercontent.com/benchflow-ai/skillsbench/main/registry.json"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
_GITHUB_URL_RE = re.compile(
|
|
26
|
+
r"^(?:https://|git@)github\.com[:/]([^/]+)/([^/]+?)(?:\.git)?/?$"
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class DatasetResolutionError(ValueError):
|
|
31
|
+
"""A dataset spec could not be resolved against the registry."""
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class DatasetDigestMismatchError(DatasetResolutionError):
|
|
35
|
+
"""Snapshot content does not match the registry's pinned digests."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class ResolvedDataset:
|
|
40
|
+
"""A registry entry resolved to verified task directories on disk."""
|
|
41
|
+
|
|
42
|
+
name: str
|
|
43
|
+
version: str
|
|
44
|
+
bench_version: str | None
|
|
45
|
+
tasks_dir: Path
|
|
46
|
+
task_names: set[str]
|
|
47
|
+
task_digests: dict[str, str]
|
|
48
|
+
provenance: dict[str, Any]
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def spec(self) -> str:
|
|
52
|
+
return f"{self.name}@{self.version}"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def parse_dataset_spec(spec: str) -> tuple[str, str]:
|
|
56
|
+
"""Split ``<name>@<version>`` — the version is mandatory.
|
|
57
|
+
|
|
58
|
+
Published versions are immutable, so there is no "latest" default: a
|
|
59
|
+
run must name the exact version it pins.
|
|
60
|
+
"""
|
|
61
|
+
name, sep, version = spec.partition("@")
|
|
62
|
+
if not sep or not name or not version:
|
|
63
|
+
raise DatasetResolutionError(
|
|
64
|
+
f"Invalid dataset spec {spec!r} — expected <name>@<version> "
|
|
65
|
+
f"(e.g. skillsbench@1.1)"
|
|
66
|
+
)
|
|
67
|
+
return name, version
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def load_registry(source: str) -> list[dict[str, Any]]:
|
|
71
|
+
"""Load a dataset registry from an HTTP(S) URL or a local file path."""
|
|
72
|
+
if source.startswith(("http://", "https://")):
|
|
73
|
+
with urlopen(source, timeout=30) as response:
|
|
74
|
+
raw = response.read().decode("utf-8")
|
|
75
|
+
else:
|
|
76
|
+
raw = Path(source).read_text()
|
|
77
|
+
registry = json.loads(raw)
|
|
78
|
+
if not isinstance(registry, list):
|
|
79
|
+
raise DatasetResolutionError(
|
|
80
|
+
f"Registry at {source} is not a list of dataset entries"
|
|
81
|
+
)
|
|
82
|
+
return registry
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def bench_version_issue(declared_range: str | None) -> str | None:
|
|
86
|
+
"""Warning text when the running bench falls outside the dataset's
|
|
87
|
+
validated ``bench_version`` range, else None. Advisory only — the
|
|
88
|
+
range records what the version was validated against, it is not a
|
|
89
|
+
hard gate."""
|
|
90
|
+
if not declared_range:
|
|
91
|
+
return None
|
|
92
|
+
from packaging.specifiers import InvalidSpecifier, SpecifierSet
|
|
93
|
+
from packaging.version import InvalidVersion, Version
|
|
94
|
+
|
|
95
|
+
from benchflow import __version__
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
specifier = SpecifierSet(declared_range)
|
|
99
|
+
except InvalidSpecifier:
|
|
100
|
+
return f"registry declares an unparseable bench_version {declared_range!r}"
|
|
101
|
+
try:
|
|
102
|
+
current = Version(__version__)
|
|
103
|
+
except InvalidVersion:
|
|
104
|
+
return (
|
|
105
|
+
f"cannot compare bench version {__version__!r} against the "
|
|
106
|
+
f"dataset's validated range {declared_range!r}"
|
|
107
|
+
)
|
|
108
|
+
if specifier.contains(current, prereleases=True):
|
|
109
|
+
return None
|
|
110
|
+
return (
|
|
111
|
+
f"bench {__version__} is outside the range this dataset was "
|
|
112
|
+
f"validated against ({declared_range}) — results may not be "
|
|
113
|
+
f"comparable with published runs"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def _github_org_repo(git_url: str) -> str:
|
|
118
|
+
match = _GITHUB_URL_RE.match(git_url)
|
|
119
|
+
if not match:
|
|
120
|
+
raise DatasetResolutionError(
|
|
121
|
+
f"Unsupported git_url {git_url!r} — expected a github.com repository"
|
|
122
|
+
)
|
|
123
|
+
return f"{match.group(1)}/{match.group(2)}"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def resolve_dataset(
|
|
127
|
+
spec: str, registry: str = DEFAULT_REGISTRY_SOURCE
|
|
128
|
+
) -> ResolvedDataset:
|
|
129
|
+
"""Resolve ``<name>@<version>`` to digest-verified task dirs on disk.
|
|
130
|
+
|
|
131
|
+
Clones the snapshot pinned by the registry entry (by commit id, so a
|
|
132
|
+
moved git tag cannot change what runs), then recomputes every task's
|
|
133
|
+
content digest and fails hard on any mismatch — a dataset version is
|
|
134
|
+
an immutable artifact and must byte-match its registry entry.
|
|
135
|
+
"""
|
|
136
|
+
name, version = parse_dataset_spec(spec)
|
|
137
|
+
entries = load_registry(registry)
|
|
138
|
+
entry = next(
|
|
139
|
+
(
|
|
140
|
+
e
|
|
141
|
+
for e in entries
|
|
142
|
+
if e.get("name") == name and str(e.get("version")) == version
|
|
143
|
+
),
|
|
144
|
+
None,
|
|
145
|
+
)
|
|
146
|
+
if entry is None:
|
|
147
|
+
available = (
|
|
148
|
+
", ".join(f"{e.get('name')}@{e.get('version')}" for e in entries) or "none"
|
|
149
|
+
)
|
|
150
|
+
raise DatasetResolutionError(
|
|
151
|
+
f"Dataset {spec!r} not found in registry (available: {available})"
|
|
152
|
+
)
|
|
153
|
+
tasks = entry.get("tasks") or []
|
|
154
|
+
if not tasks:
|
|
155
|
+
raise DatasetResolutionError(f"Dataset {spec!r} has no tasks in the registry")
|
|
156
|
+
|
|
157
|
+
snapshots = {(t["git_url"], t["git_commit_id"]) for t in tasks}
|
|
158
|
+
if len(snapshots) != 1:
|
|
159
|
+
raise DatasetResolutionError(
|
|
160
|
+
f"Dataset {spec!r} spans {len(snapshots)} git snapshots — "
|
|
161
|
+
f"only single-snapshot datasets are supported"
|
|
162
|
+
)
|
|
163
|
+
git_url, commit = next(iter(snapshots))
|
|
164
|
+
|
|
165
|
+
parents = {posixpath.dirname(t["path"].rstrip("/")) for t in tasks}
|
|
166
|
+
if len(parents) != 1:
|
|
167
|
+
raise DatasetResolutionError(
|
|
168
|
+
f"Dataset {spec!r} tasks live under {len(parents)} parent "
|
|
169
|
+
f"directories — only a single tasks directory is supported"
|
|
170
|
+
)
|
|
171
|
+
parent = next(iter(parents))
|
|
172
|
+
|
|
173
|
+
task_digests: dict[str, str] = {}
|
|
174
|
+
for t in tasks:
|
|
175
|
+
base = posixpath.basename(t["path"].rstrip("/"))
|
|
176
|
+
if base in task_digests:
|
|
177
|
+
raise DatasetResolutionError(
|
|
178
|
+
f"Dataset {spec!r} has two tasks named {base!r}"
|
|
179
|
+
)
|
|
180
|
+
task_digests[base] = t["digest"]
|
|
181
|
+
|
|
182
|
+
repo = _github_org_repo(git_url)
|
|
183
|
+
resolved = benchmark_repos.resolve_source_with_metadata(
|
|
184
|
+
repo, path=parent or None, ref=commit
|
|
185
|
+
)
|
|
186
|
+
resolved_sha = resolved.provenance.get("resolved_sha")
|
|
187
|
+
if resolved_sha != commit:
|
|
188
|
+
raise DatasetResolutionError(
|
|
189
|
+
f"Snapshot for {spec!r} resolved to {resolved_sha} but the "
|
|
190
|
+
f"registry pins {commit}"
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
mismatches = []
|
|
194
|
+
for base, expected in sorted(task_digests.items()):
|
|
195
|
+
candidate = resolved.path / base
|
|
196
|
+
if not candidate.is_dir():
|
|
197
|
+
mismatches.append(f"{base}: missing from snapshot")
|
|
198
|
+
continue
|
|
199
|
+
actual = task_digest(candidate)
|
|
200
|
+
if actual != expected:
|
|
201
|
+
mismatches.append(f"{base}: computed {actual}, registry pins {expected}")
|
|
202
|
+
if mismatches:
|
|
203
|
+
raise DatasetDigestMismatchError(
|
|
204
|
+
f"Dataset {spec!r} content does not match its registry digests:\n "
|
|
205
|
+
+ "\n ".join(mismatches)
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
return ResolvedDataset(
|
|
209
|
+
name=name,
|
|
210
|
+
version=version,
|
|
211
|
+
bench_version=entry.get("bench_version"),
|
|
212
|
+
tasks_dir=resolved.path,
|
|
213
|
+
task_names=set(task_digests),
|
|
214
|
+
task_digests=task_digests,
|
|
215
|
+
provenance=resolved.provenance,
|
|
216
|
+
)
|
|
@@ -1092,6 +1092,23 @@ def eval_create(
|
|
|
1092
1092
|
help="Skip these task names; repeatable (e.g. --exclude quantum-numerical-simulation)",
|
|
1093
1093
|
),
|
|
1094
1094
|
] = None,
|
|
1095
|
+
dataset: Annotated[
|
|
1096
|
+
str | None,
|
|
1097
|
+
typer.Option(
|
|
1098
|
+
"--dataset",
|
|
1099
|
+
"-d",
|
|
1100
|
+
help="Registry dataset to run, as <name>@<version> (e.g. skillsbench@1.1). "
|
|
1101
|
+
"Resolves the pinned snapshot and verifies task content digests.",
|
|
1102
|
+
),
|
|
1103
|
+
] = None,
|
|
1104
|
+
registry: Annotated[
|
|
1105
|
+
str | None,
|
|
1106
|
+
typer.Option(
|
|
1107
|
+
"--registry",
|
|
1108
|
+
help="Dataset registry JSON URL or local file "
|
|
1109
|
+
"(default: the skillsbench registry). Only valid with --dataset.",
|
|
1110
|
+
),
|
|
1111
|
+
] = None,
|
|
1095
1112
|
) -> None:
|
|
1096
1113
|
"""Run an evaluation — single task or batch.
|
|
1097
1114
|
|
|
@@ -1107,12 +1124,22 @@ def eval_create(
|
|
|
1107
1124
|
parsed_env = _parse_agent_env(agent_env)
|
|
1108
1125
|
include_tasks = set(include) if include else set()
|
|
1109
1126
|
exclude_tasks = set(exclude) if exclude else set()
|
|
1110
|
-
sources = [
|
|
1127
|
+
sources = [
|
|
1128
|
+
bool(config_file),
|
|
1129
|
+
bool(tasks_dir),
|
|
1130
|
+
bool(source_repo),
|
|
1131
|
+
bool(source_env),
|
|
1132
|
+
bool(dataset),
|
|
1133
|
+
]
|
|
1111
1134
|
if sum(sources) > 1:
|
|
1112
1135
|
console.print(
|
|
1113
|
-
"[red]Choose only one source: --config, --tasks-dir, --source-repo,
|
|
1136
|
+
"[red]Choose only one source: --config, --tasks-dir, --source-repo, "
|
|
1137
|
+
"--source-env, or --dataset[/red]"
|
|
1114
1138
|
)
|
|
1115
1139
|
raise typer.Exit(1)
|
|
1140
|
+
if registry and not dataset:
|
|
1141
|
+
console.print("[red]--registry requires --dataset[/red]")
|
|
1142
|
+
raise typer.Exit(1)
|
|
1116
1143
|
if worker_concurrency is not None and not (tasks_dir or source_repo):
|
|
1117
1144
|
console.print(
|
|
1118
1145
|
"[red]--worker-concurrency is supported for --tasks-dir and --source-repo batch runs[/red]"
|
|
@@ -1340,6 +1367,63 @@ def eval_create(
|
|
|
1340
1367
|
if run_result.error:
|
|
1341
1368
|
console.print(f"[red]Error:[/red] {run_result.error}")
|
|
1342
1369
|
raise typer.Exit(1)
|
|
1370
|
+
elif dataset:
|
|
1371
|
+
from benchflow._utils.dataset_registry import (
|
|
1372
|
+
DEFAULT_REGISTRY_SOURCE,
|
|
1373
|
+
DatasetResolutionError,
|
|
1374
|
+
bench_version_issue,
|
|
1375
|
+
resolve_dataset,
|
|
1376
|
+
)
|
|
1377
|
+
|
|
1378
|
+
registry_source = registry or DEFAULT_REGISTRY_SOURCE
|
|
1379
|
+
try:
|
|
1380
|
+
with console.status(f"Resolving dataset {dataset}…"):
|
|
1381
|
+
resolved_dataset = resolve_dataset(dataset, registry=registry_source)
|
|
1382
|
+
except DatasetResolutionError as e:
|
|
1383
|
+
console.print(f"[red]{e}[/red]")
|
|
1384
|
+
raise typer.Exit(1) from None
|
|
1385
|
+
version_issue = bench_version_issue(resolved_dataset.bench_version)
|
|
1386
|
+
if version_issue:
|
|
1387
|
+
console.print(f"[yellow]Warning:[/yellow] {version_issue}")
|
|
1388
|
+
console.print(
|
|
1389
|
+
f"[green]✓[/green] {resolved_dataset.spec}: "
|
|
1390
|
+
f"{len(resolved_dataset.task_names)} tasks, digests verified "
|
|
1391
|
+
f"({str(resolved_dataset.provenance.get('resolved_sha', ''))[:12]})"
|
|
1392
|
+
)
|
|
1393
|
+
dataset_include = (
|
|
1394
|
+
resolved_dataset.task_names & include_tasks
|
|
1395
|
+
if include_tasks
|
|
1396
|
+
else resolved_dataset.task_names
|
|
1397
|
+
)
|
|
1398
|
+
eff_model = effective_model(eval_agent, model)
|
|
1399
|
+
_run_batch_eval(
|
|
1400
|
+
resolved_dataset.tasks_dir,
|
|
1401
|
+
EvaluationConfig(
|
|
1402
|
+
agent=eval_agent,
|
|
1403
|
+
model=eff_model,
|
|
1404
|
+
reasoning_effort=eval_reasoning_effort,
|
|
1405
|
+
environment=eval_environment,
|
|
1406
|
+
concurrency=eval_concurrency,
|
|
1407
|
+
build_concurrency=build_concurrency,
|
|
1408
|
+
prompts=eval_prompts,
|
|
1409
|
+
agent_idle_timeout=eval_agent_idle_timeout,
|
|
1410
|
+
agent_env=parsed_env,
|
|
1411
|
+
sandbox_user=sandbox_user,
|
|
1412
|
+
sandbox_setup_timeout=sandbox_setup_timeout,
|
|
1413
|
+
skills_dir=str(skills_dir) if skills_dir else None,
|
|
1414
|
+
skill_mode=skill_mode,
|
|
1415
|
+
skill_creator_dir=str(skill_creator_dir) if skill_creator_dir else None,
|
|
1416
|
+
self_gen_no_internet=self_gen_no_internet,
|
|
1417
|
+
source_provenance=resolved_dataset.provenance,
|
|
1418
|
+
include_tasks=dataset_include,
|
|
1419
|
+
exclude_tasks=exclude_tasks,
|
|
1420
|
+
usage_tracking=eval_usage_tracking,
|
|
1421
|
+
environment_manifest=eval_env_manifest,
|
|
1422
|
+
dataset_name=resolved_dataset.name,
|
|
1423
|
+
dataset_version=resolved_dataset.version,
|
|
1424
|
+
dataset_task_digests=resolved_dataset.task_digests,
|
|
1425
|
+
),
|
|
1426
|
+
)
|
|
1343
1427
|
elif source_repo:
|
|
1344
1428
|
from benchflow._utils.benchmark_repos import resolve_source_with_metadata
|
|
1345
1429
|
|
|
@@ -1408,7 +1492,8 @@ def eval_create(
|
|
|
1408
1492
|
)
|
|
1409
1493
|
else:
|
|
1410
1494
|
console.print(
|
|
1411
|
-
"[red]Provide --config, --tasks-dir, --source-repo,
|
|
1495
|
+
"[red]Provide --config, --tasks-dir, --source-repo, --source-env, "
|
|
1496
|
+
"or --dataset[/red]"
|
|
1412
1497
|
)
|
|
1413
1498
|
raise typer.Exit(1)
|
|
1414
1499
|
|
|
@@ -267,6 +267,13 @@ class EvaluationConfig:
|
|
|
267
267
|
self_gen_no_internet: bool = False
|
|
268
268
|
job_mode: str = DEFAULT_JOB_MODE
|
|
269
269
|
source_provenance: dict[str, Any] | None = None
|
|
270
|
+
# Registry dataset identity (`bench eval create -d name@version`). When
|
|
271
|
+
# set, every result.json/config.json is stamped with dataset_name,
|
|
272
|
+
# dataset_version, and the task's registry content digest — see
|
|
273
|
+
# docs/dataset-versioning.md in benchflow-ai/skillsbench.
|
|
274
|
+
dataset_name: str | None = None
|
|
275
|
+
dataset_version: str | None = None
|
|
276
|
+
dataset_task_digests: dict[str, str] = field(default_factory=dict)
|
|
270
277
|
usage_tracking: UsageTrackingConfig = field(default_factory=UsageTrackingConfig)
|
|
271
278
|
# Environment-plane manifest applied to every rollout in the batch.
|
|
272
279
|
# When set, each task's RolloutConfig.environment_manifest is populated
|
|
@@ -817,6 +824,22 @@ class Evaluation:
|
|
|
817
824
|
from benchflow._utils.benchmark_repos import task_source_provenance
|
|
818
825
|
from benchflow.rollout import Rollout, RolloutConfig
|
|
819
826
|
|
|
827
|
+
dataset = None
|
|
828
|
+
if cfg.dataset_name:
|
|
829
|
+
dataset = {"name": cfg.dataset_name, "version": cfg.dataset_version}
|
|
830
|
+
task_digest_value = (
|
|
831
|
+
cfg.dataset_task_digests.get(task_dir.name) if cfg.dataset_name else None
|
|
832
|
+
)
|
|
833
|
+
if task_digest_value is None:
|
|
834
|
+
# Dev runs (--tasks-dir / --source-repo) stamp a live-computed
|
|
835
|
+
# digest so every trajectory stays attributable to the exact
|
|
836
|
+
# task content it ran, not just a directory name.
|
|
837
|
+
from benchflow._utils.task_authoring import task_digest
|
|
838
|
+
|
|
839
|
+
try:
|
|
840
|
+
task_digest_value = task_digest(task_dir)
|
|
841
|
+
except (OSError, ValueError, UnicodeError) as e:
|
|
842
|
+
logger.debug("Could not compute task digest for %s: %s", task_dir, e)
|
|
820
843
|
skills_dir = (
|
|
821
844
|
str(self._learner_skills_dir)
|
|
822
845
|
if self._learner_skills_dir is not None
|
|
@@ -855,6 +878,8 @@ class Evaluation:
|
|
|
855
878
|
self_gen_no_internet=cfg.self_gen_no_internet,
|
|
856
879
|
export_generated_skills_to=export_to,
|
|
857
880
|
source_provenance=task_source_provenance(cfg.source_provenance, task_dir),
|
|
881
|
+
dataset=dataset,
|
|
882
|
+
task_digest=task_digest_value,
|
|
858
883
|
usage_tracking=cfg.usage_tracking,
|
|
859
884
|
)
|
|
860
885
|
if skill_mode == SKILL_MODE_SELF_GEN:
|
|
@@ -1383,6 +1408,14 @@ class Evaluation:
|
|
|
1383
1408
|
**trajectory_step_summary(all_results),
|
|
1384
1409
|
**phase_timing_summary(all_results),
|
|
1385
1410
|
**summary_source_fields(cfg.source_provenance, all_results),
|
|
1411
|
+
**(
|
|
1412
|
+
{
|
|
1413
|
+
"dataset_name": cfg.dataset_name,
|
|
1414
|
+
"dataset_version": cfg.dataset_version,
|
|
1415
|
+
}
|
|
1416
|
+
if cfg.dataset_name
|
|
1417
|
+
else {}
|
|
1418
|
+
),
|
|
1386
1419
|
}
|
|
1387
1420
|
# Surface continual-learning provenance — generation, curve — so a
|
|
1388
1421
|
# resumed run can be audited end-to-end (#394).
|
|
@@ -525,6 +525,8 @@ def _write_config(
|
|
|
525
525
|
agent_idle_timeout: int | None = None,
|
|
526
526
|
scenes: list[Scene] | None = None,
|
|
527
527
|
source_provenance: dict[str, Any] | None = None,
|
|
528
|
+
dataset: dict[str, Any] | None = None,
|
|
529
|
+
task_digest: str | None = None,
|
|
528
530
|
) -> None:
|
|
529
531
|
"""Write config.json to rollout_dir with secrets filtered out."""
|
|
530
532
|
recorded_env = {
|
|
@@ -552,6 +554,11 @@ def _write_config(
|
|
|
552
554
|
config_data["usage_tracking"] = usage_tracking.to_config_artifact()
|
|
553
555
|
if source_provenance is not None:
|
|
554
556
|
config_data["source"] = source_provenance
|
|
557
|
+
if dataset is not None:
|
|
558
|
+
config_data["dataset_name"] = dataset.get("name")
|
|
559
|
+
config_data["dataset_version"] = dataset.get("version")
|
|
560
|
+
if task_digest is not None:
|
|
561
|
+
config_data["task_digest"] = task_digest
|
|
555
562
|
(rollout_dir / "config.json").write_text(json.dumps(config_data, indent=2))
|
|
556
563
|
|
|
557
564
|
|
|
@@ -616,6 +623,8 @@ def _build_rollout_result(
|
|
|
616
623
|
usage_tracking: dict[str, Any] | None = None,
|
|
617
624
|
evolved_skills: dict[str, str] | None = None,
|
|
618
625
|
source_provenance: dict[str, Any] | None = None,
|
|
626
|
+
dataset: dict[str, Any] | None = None,
|
|
627
|
+
task_digest: str | None = None,
|
|
619
628
|
diagnostics: RolloutDiagnostics | None = None,
|
|
620
629
|
skill_policy: TaskSkillPolicy | None = None,
|
|
621
630
|
sandbox_id: str | None = None,
|
|
@@ -743,6 +752,15 @@ def _build_rollout_result(
|
|
|
743
752
|
if source_provenance is not None
|
|
744
753
|
else {}
|
|
745
754
|
),
|
|
755
|
+
**(
|
|
756
|
+
{
|
|
757
|
+
"dataset_name": dataset.get("name"),
|
|
758
|
+
"dataset_version": dataset.get("version"),
|
|
759
|
+
}
|
|
760
|
+
if dataset is not None
|
|
761
|
+
else {}
|
|
762
|
+
),
|
|
763
|
+
**({"task_digest": task_digest} if task_digest is not None else {}),
|
|
746
764
|
"sandbox_id": sandbox_id,
|
|
747
765
|
},
|
|
748
766
|
indent=2,
|
|
@@ -1092,6 +1110,14 @@ class RolloutConfig:
|
|
|
1092
1110
|
skip_verify: bool = False
|
|
1093
1111
|
export_generated_skills_to: str | Path | None = None
|
|
1094
1112
|
source_provenance: dict[str, Any] | None = None
|
|
1113
|
+
# Registry dataset identity: {"name", "version"} — stamped into
|
|
1114
|
+
# config.json/result.json as dataset_name/dataset_version so published
|
|
1115
|
+
# runs declare the dataset version they ran (dataset-versioning plan).
|
|
1116
|
+
dataset: dict[str, Any] | None = None
|
|
1117
|
+
# Content digest of the task directory ("sha256:<hex>", the skillsbench
|
|
1118
|
+
# registry algorithm). Registry-pinned for dataset runs, computed live
|
|
1119
|
+
# for dev runs — every result stays attributable to exact task content.
|
|
1120
|
+
task_digest: str | None = None
|
|
1095
1121
|
planes: RolloutPlanes | None = field(default=None, repr=False, compare=False)
|
|
1096
1122
|
|
|
1097
1123
|
def __post_init__(self) -> None:
|
|
@@ -1540,6 +1566,8 @@ class Rollout:
|
|
|
1540
1566
|
agent_idle_timeout=cfg.agent_idle_timeout,
|
|
1541
1567
|
scenes=cfg.effective_scenes,
|
|
1542
1568
|
source_provenance=cfg.source_provenance,
|
|
1569
|
+
dataset=cfg.dataset,
|
|
1570
|
+
task_digest=cfg.task_digest,
|
|
1543
1571
|
)
|
|
1544
1572
|
|
|
1545
1573
|
self._phase = "setup"
|
|
@@ -2906,6 +2934,8 @@ class Rollout:
|
|
|
2906
2934
|
scenes=self._config.effective_scenes,
|
|
2907
2935
|
evolved_skills=self._evolved_skills,
|
|
2908
2936
|
source_provenance=self._config.source_provenance,
|
|
2937
|
+
dataset=self._config.dataset,
|
|
2938
|
+
task_digest=self._config.task_digest,
|
|
2909
2939
|
diagnostics=self._diagnostics,
|
|
2910
2940
|
usage_tracking=self._usage_tracking_metadata(),
|
|
2911
2941
|
skill_policy=getattr(self, "_task_skill_policy", None)
|
|
@@ -32,7 +32,11 @@ from benchflow._utils.scoring import (
|
|
|
32
32
|
classify_verifier_error,
|
|
33
33
|
count_result_outcomes,
|
|
34
34
|
)
|
|
35
|
-
from benchflow._utils.source_provenance import
|
|
35
|
+
from benchflow._utils.source_provenance import (
|
|
36
|
+
is_sha256_digest,
|
|
37
|
+
source_issues,
|
|
38
|
+
source_matches_parent,
|
|
39
|
+
)
|
|
36
40
|
from benchflow.trajectories.metrics import (
|
|
37
41
|
count_skill_invocations,
|
|
38
42
|
result_skill_invocations,
|
|
@@ -304,6 +308,73 @@ def _source_hash_truth_issues(source: object, label: str) -> list[str]:
|
|
|
304
308
|
return _source_git_truth_issues(source_dict, local_path, label)
|
|
305
309
|
|
|
306
310
|
|
|
311
|
+
# Dataset identity stamp (dataset-versioning plan: benchflow #690 + dev-run
|
|
312
|
+
# digest stamping follow-up). dataset_name/dataset_version mark registry
|
|
313
|
+
# dataset runs; task_digest pins the exact task content for every run.
|
|
314
|
+
_DATASET_STAMP_KEYS = ("dataset_name", "dataset_version", "task_digest")
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def _dataset_stamp_issues(artifact: object, label: str) -> list[str]:
|
|
318
|
+
"""Audit the dataset identity stamp on one result.json/config.json.
|
|
319
|
+
|
|
320
|
+
Rules: dataset_name and dataset_version travel together; a dataset run
|
|
321
|
+
must carry a task_digest; any task_digest must be ``sha256:<64 hex>``.
|
|
322
|
+
A bare task_digest without dataset fields is a dev run — allowed.
|
|
323
|
+
"""
|
|
324
|
+
if not isinstance(artifact, dict):
|
|
325
|
+
return []
|
|
326
|
+
artifact_dict = cast(dict[str, Any], artifact)
|
|
327
|
+
name = artifact_dict.get("dataset_name")
|
|
328
|
+
version = artifact_dict.get("dataset_version")
|
|
329
|
+
digest = artifact_dict.get("task_digest")
|
|
330
|
+
if name is None and version is None and digest is None:
|
|
331
|
+
return []
|
|
332
|
+
issues: list[str] = []
|
|
333
|
+
if (name is None) != (version is None):
|
|
334
|
+
issues.append(f"{label}: dataset_name and dataset_version must travel together")
|
|
335
|
+
for field_name, value in (("dataset_name", name), ("dataset_version", version)):
|
|
336
|
+
if value is not None and (not isinstance(value, str) or not value):
|
|
337
|
+
issues.append(f"{label}: {field_name} must be a non-empty string")
|
|
338
|
+
if name is not None and digest is None:
|
|
339
|
+
issues.append(f"{label}: dataset-stamped artifact missing task_digest")
|
|
340
|
+
if digest is not None and not is_sha256_digest(digest):
|
|
341
|
+
issues.append(f"{label}: task_digest must be 'sha256:<64 hex>'")
|
|
342
|
+
return issues
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def _task_digest_truth_issues(result: object, label: str) -> list[str]:
|
|
346
|
+
"""Recompute the task content digest when the task dir is still on disk.
|
|
347
|
+
|
|
348
|
+
Complements ``_source_hash_truth_issues``: ``source.file_hashes`` audits
|
|
349
|
+
per-file hashes, this audits the single registry-algorithm digest the
|
|
350
|
+
leaderboard pipeline keys on.
|
|
351
|
+
"""
|
|
352
|
+
if not isinstance(result, dict):
|
|
353
|
+
return []
|
|
354
|
+
result_dict = cast(dict[str, Any], result)
|
|
355
|
+
digest = result_dict.get("task_digest")
|
|
356
|
+
if not is_sha256_digest(digest):
|
|
357
|
+
return [] # absent or malformed — format issues reported elsewhere
|
|
358
|
+
source = result_dict.get("source")
|
|
359
|
+
if not isinstance(source, dict):
|
|
360
|
+
return []
|
|
361
|
+
local_path_raw = source.get("local_path")
|
|
362
|
+
if not isinstance(local_path_raw, str):
|
|
363
|
+
return []
|
|
364
|
+
local_path = Path(local_path_raw)
|
|
365
|
+
if not (local_path / "task.toml").exists():
|
|
366
|
+
return []
|
|
367
|
+
try:
|
|
368
|
+
from benchflow._utils.task_authoring import task_digest
|
|
369
|
+
|
|
370
|
+
actual = task_digest(local_path)
|
|
371
|
+
except Exception as e:
|
|
372
|
+
return [f"{label}: task_digest could not be recomputed: {e}"]
|
|
373
|
+
if actual != digest:
|
|
374
|
+
return [f"{label}: task_digest does not match local_path content"]
|
|
375
|
+
return []
|
|
376
|
+
|
|
377
|
+
|
|
307
378
|
def _git_stdout(cwd: Path, *args: str) -> str | None:
|
|
308
379
|
completed = subprocess.run(
|
|
309
380
|
["git", "-C", str(cwd), *args],
|
|
@@ -535,6 +606,18 @@ def check_agent(agent_dir: Path) -> dict:
|
|
|
535
606
|
if source_truth_issues:
|
|
536
607
|
findings["issues"].extend(source_truth_issues)
|
|
537
608
|
findings["ok"] = False
|
|
609
|
+
dataset_stamp_issues = _dataset_stamp_issues(
|
|
610
|
+
r, f"{r.get('task_name', '?')}: result.json"
|
|
611
|
+
)
|
|
612
|
+
if dataset_stamp_issues:
|
|
613
|
+
findings["issues"].extend(dataset_stamp_issues)
|
|
614
|
+
findings["ok"] = False
|
|
615
|
+
digest_truth_issues = _task_digest_truth_issues(
|
|
616
|
+
r, f"{r.get('task_name', '?')}: result.json"
|
|
617
|
+
)
|
|
618
|
+
if digest_truth_issues:
|
|
619
|
+
findings["issues"].extend(digest_truth_issues)
|
|
620
|
+
findings["ok"] = False
|
|
538
621
|
_config_path, config, config_error = _load_config(result_file)
|
|
539
622
|
if config_error:
|
|
540
623
|
findings["issues"].append(f"{r.get('task_name', '?')}: {config_error}")
|
|
@@ -639,6 +722,18 @@ def check_agent(agent_dir: Path) -> dict:
|
|
|
639
722
|
f"{r.get('task_name', '?')}: config.json source does not match result.json"
|
|
640
723
|
)
|
|
641
724
|
findings["ok"] = False
|
|
725
|
+
config_dataset_issues = _dataset_stamp_issues(
|
|
726
|
+
config, f"{r.get('task_name', '?')}: config.json"
|
|
727
|
+
)
|
|
728
|
+
if config_dataset_issues:
|
|
729
|
+
findings["issues"].extend(config_dataset_issues)
|
|
730
|
+
findings["ok"] = False
|
|
731
|
+
if any(config.get(k) != r.get(k) for k in _DATASET_STAMP_KEYS):
|
|
732
|
+
findings["issues"].append(
|
|
733
|
+
f"{r.get('task_name', '?')}: config.json dataset stamp "
|
|
734
|
+
f"does not match result.json"
|
|
735
|
+
)
|
|
736
|
+
findings["ok"] = False
|
|
642
737
|
|
|
643
738
|
# Infrastructure errors — driven from the central diagnostic registry
|
|
644
739
|
# so adding a new diagnostic kind doesn't require editing this file
|
|
@@ -768,6 +863,17 @@ def check_agent(agent_dir: Path) -> dict:
|
|
|
768
863
|
"summary.json missing source provenance and not all results have source"
|
|
769
864
|
)
|
|
770
865
|
findings["ok"] = False
|
|
866
|
+
# Dataset identity must agree across summary.json and every
|
|
867
|
+
# result.json — one leaderboard namespace per dataset version.
|
|
868
|
+
for dataset_key in ("dataset_name", "dataset_version"):
|
|
869
|
+
dataset_values = {r.get(dataset_key) for r in results}
|
|
870
|
+
dataset_values.add(summary.get(dataset_key))
|
|
871
|
+
if len(dataset_values) > 1:
|
|
872
|
+
findings["issues"].append(
|
|
873
|
+
f"summary.json {dataset_key} does not agree across "
|
|
874
|
+
f"summary and results: {sorted(map(repr, dataset_values))}"
|
|
875
|
+
)
|
|
876
|
+
findings["ok"] = False
|
|
771
877
|
expected_model = _expected(agent, "model")
|
|
772
878
|
expected_environment = _expected(agent, "environment")
|
|
773
879
|
expected_concurrency = _expected(agent, "concurrency")
|