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.
Files changed (427) hide show
  1. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/PKG-INFO +1 -1
  2. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/pyproject.toml +1 -1
  3. benchflow-0.5.3.dev980/src/benchflow/_utils/dataset_registry.py +216 -0
  4. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/cli/main.py +88 -3
  5. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/evaluation.py +33 -0
  6. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rollout.py +30 -0
  7. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/check_results.py +107 -1
  8. benchflow-0.5.3.dev980/tests/test_dataset_registry.py +502 -0
  9. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_integration_check_results.py +254 -0
  10. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/.gitignore +0 -0
  11. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/CHANGELOG.md +0 -0
  12. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/LICENSE +0 -0
  13. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/README.md +0 -0
  14. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/__init__.py +0 -0
  15. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_dotenv.py +0 -0
  16. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_paths.py +0 -0
  17. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_run.py +0 -0
  18. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_types.py +0 -0
  19. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/__init__.py +0 -0
  20. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/benchmark_repos.py +0 -0
  21. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/config.py +0 -0
  22. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/evaluation_results.py +0 -0
  23. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/json_safe.py +0 -0
  24. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/learner_memory.py +0 -0
  25. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/result_metadata.py +0 -0
  26. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/reward_events.py +0 -0
  27. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/scoring.py +0 -0
  28. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/source_provenance.py +0 -0
  29. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/task_authoring.py +0 -0
  30. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/_utils/yaml_loader.py +0 -0
  31. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/__init__.py +0 -0
  32. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/client.py +0 -0
  33. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/container_transport.py +0 -0
  34. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/runtime.py +0 -0
  35. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/session.py +0 -0
  36. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/transport.py +0 -0
  37. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/acp/types.py +0 -0
  38. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/__init__.py +0 -0
  39. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/harbor.py +0 -0
  40. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/inbound.py +0 -0
  41. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/inspect_ai.py +0 -0
  42. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/ors.py +0 -0
  43. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/adapters/terminal_bench.py +0 -0
  44. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/__init__.py +0 -0
  45. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/codex_config.py +0 -0
  46. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/credentials.py +0 -0
  47. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/env.py +0 -0
  48. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/errors.py +0 -0
  49. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/harvey_lab_acp_shim.py +0 -0
  50. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/install.py +0 -0
  51. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/openclaw_acp_shim.py +0 -0
  52. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/pi_acp_launcher.py +0 -0
  53. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/protocol.py +0 -0
  54. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/providers.py +0 -0
  55. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/agents/registry.py +0 -0
  56. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/branch.py +0 -0
  57. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/cli/__init__.py +0 -0
  58. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/cli/continue_cmd.py +0 -0
  59. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/cli/trace_import.py +0 -0
  60. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/compat/__init__.py +0 -0
  61. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/compat/harbor_registry.py +0 -0
  62. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/__init__.py +0 -0
  63. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/batch.py +0 -0
  64. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/orchestrator.py +0 -0
  65. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/replay_proxy.py +0 -0
  66. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/run_folder.py +0 -0
  67. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/continue_run/sandbox_proxy.py +0 -0
  68. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/contracts/__init__.py +0 -0
  69. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/contracts/planes.py +0 -0
  70. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/contracts/user.py +0 -0
  71. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/demo_task/environment/Dockerfile +0 -0
  72. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/demo_task/instruction.md +0 -0
  73. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/demo_task/task.toml +0 -0
  74. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/demo_task/tests/test.sh +0 -0
  75. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/diagnostics.py +0 -0
  76. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/environment/__init__.py +0 -0
  77. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/environment/manifest.py +0 -0
  78. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/environment/manifest_env.py +0 -0
  79. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/environment/protocol.py +0 -0
  80. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/environment/readiness.py +0 -0
  81. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/eval_sharding.py +0 -0
  82. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/eval_worker.py +0 -0
  83. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/experimental/__init__.py +0 -0
  84. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/experimental/mcp/__init__.py +0 -0
  85. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/experimental/mcp/hooks.py +0 -0
  86. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/experimental/mcp/reviewer_server.py +0 -0
  87. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/hosted_env.py +0 -0
  88. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/learner_skills.py +0 -0
  89. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/learner_store.py +0 -0
  90. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/metrics.py +0 -0
  91. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/models.py +0 -0
  92. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/monitor.py +0 -0
  93. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/__init__.py +0 -0
  94. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/litellm_bedrock_patch.py +0 -0
  95. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/litellm_bedrock_preflight.py +0 -0
  96. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/litellm_config.py +0 -0
  97. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/litellm_logging.py +0 -0
  98. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/litellm_runtime.py +0 -0
  99. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/providers/runtime.py +0 -0
  100. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/py.typed +0 -0
  101. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/README.md +0 -0
  102. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/__init__.py +0 -0
  103. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/builtins.py +0 -0
  104. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/events.py +0 -0
  105. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/file_readers.py +0 -0
  106. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/llm.py +0 -0
  107. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/memory_scorer.py +0 -0
  108. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/node.py +0 -0
  109. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/protocol.py +0 -0
  110. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/rubric.py +0 -0
  111. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/rubric_config.py +0 -0
  112. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rewards/validation.py +0 -0
  113. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rollout_branch.py +0 -0
  114. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/rollout_planes.py +0 -0
  115. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/runtime.py +0 -0
  116. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/__init__.py +0 -0
  117. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_base.py +0 -0
  118. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_cache_reclaim.py +0 -0
  119. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_compose.py +0 -0
  120. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_compose_files/docker-compose-base.yaml +0 -0
  121. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_compose_files/docker-compose-build.yaml +0 -0
  122. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_compose_files/docker-compose-no-network.yaml +0 -0
  123. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_compose_files/docker-compose-prebuilt.yaml +0 -0
  124. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/_sdk_ops.py +0 -0
  125. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/daytona.py +0 -0
  126. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/docker.py +0 -0
  127. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/lockdown.py +0 -0
  128. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/metadata.py +0 -0
  129. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/modal_impl.py +0 -0
  130. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/process.py +0 -0
  131. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/protocol.py +0 -0
  132. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/services.py +0 -0
  133. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/setup.py +0 -0
  134. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/snapshot.py +0 -0
  135. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sandbox/user.py +0 -0
  136. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/scenes.py +0 -0
  137. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/sdk.py +0 -0
  138. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/self_gen.py +0 -0
  139. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skill_eval/__init__.py +0 -0
  140. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skill_eval/_core.py +0 -0
  141. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skill_eval/gepa_export.py +0 -0
  142. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skill_eval/schema.py +0 -0
  143. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skill_policy.py +0 -0
  144. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/skills.py +0 -0
  145. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/__init__.py +0 -0
  146. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/config.py +0 -0
  147. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/env.py +0 -0
  148. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/paths.py +0 -0
  149. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/task.py +0 -0
  150. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/task/verifier.py +0 -0
  151. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/templates/__init__.py +0 -0
  152. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/templates/judge.py.tmpl +0 -0
  153. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/templates/test.sh.tmpl +0 -0
  154. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/__init__.py +0 -0
  155. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/huggingface.py +0 -0
  156. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/local.py +0 -0
  157. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/models.py +0 -0
  158. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/parsers.py +0 -0
  159. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/traces/task_gen.py +0 -0
  160. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/__init__.py +0 -0
  161. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/_capture.py +0 -0
  162. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/export.py +0 -0
  163. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/metrics.py +0 -0
  164. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/otel.py +0 -0
  165. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/tree.py +0 -0
  166. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/types.py +0 -0
  167. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/trajectories/viewer.py +0 -0
  168. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/src/benchflow/usage_tracking.py +0 -0
  169. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/__init__.py +0 -0
  170. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/agents/__init__.py +0 -0
  171. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/agents/test_protocol.py +0 -0
  172. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/README.md +0 -0
  173. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/environment/Dockerfile +0 -0
  174. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/environment/docker-compose.yaml +0 -0
  175. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/environment/skills/conformance-writer/SKILL.md +0 -0
  176. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/instruction.md +0 -0
  177. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/solution/solve.sh +0 -0
  178. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/task.toml +0 -0
  179. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/acp_smoke/tests/test.sh +0 -0
  180. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/conformance-results.json +0 -0
  181. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/proof_multi_agent.py +0 -0
  182. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/proof_snapshot.py +0 -0
  183. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/run_conformance.py +0 -0
  184. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conformance/self_gen_smoke_skills/skill-creator/SKILL.md +0 -0
  185. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/conftest.py +0 -0
  186. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/__init__.py +0 -0
  187. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/_helpers.py +0 -0
  188. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/test_batch.py +0 -0
  189. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/test_orchestrator.py +0 -0
  190. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/test_replay_proxy.py +0 -0
  191. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/continue_run/test_run_folder.py +0 -0
  192. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/__init__.py +0 -0
  193. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_chibench_manifest.py +0 -0
  194. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_clawsbench_manifest.py +0 -0
  195. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_manifest.py +0 -0
  196. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_manifest_env.py +0 -0
  197. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_protocol.py +0 -0
  198. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/environment/test_readiness.py +0 -0
  199. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/hello-world-task/environment/Dockerfile +0 -0
  200. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/hello-world-task/instruction.md +0 -0
  201. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/hello-world-task/solution/solve.sh +0 -0
  202. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/hello-world-task/task.toml +0 -0
  203. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/hello-world-task/tests/test.sh +0 -0
  204. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/environment/Dockerfile +0 -0
  205. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/instruction.md +0 -0
  206. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/solution/solve.sh +0 -0
  207. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/task.toml +0 -0
  208. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/tests/test.sh +0 -0
  209. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/terminal-bench-smoke-task/tests/test_state.py +0 -0
  210. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/test_claude.sh +0 -0
  211. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/test_codex.sh +0 -0
  212. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/test_codex_custom_provider.sh +0 -0
  213. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/test_gemini.sh +0 -0
  214. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/test_openclaw.sh +0 -0
  215. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/traces/minimal-claude.jsonl +0 -0
  216. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/examples/traces/minimal-opentraces.jsonl +0 -0
  217. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/README.md +0 -0
  218. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/alpha-task/environment/Dockerfile +0 -0
  219. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/alpha-task/instruction.md +0 -0
  220. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/alpha-task/task.toml +0 -0
  221. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/alpha-task/tests/test.sh +0 -0
  222. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/beta-task/data/empty.bin +0 -0
  223. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/beta-task/data/unicode.txt +0 -0
  224. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/beta-task/instruction.md +0 -0
  225. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/beta-task/task.toml +0 -0
  226. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/digest/not-a-task/notes.txt +0 -0
  227. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/mock_acp_agent.py +0 -0
  228. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/mock_acp_agent_interleaved.py +0 -0
  229. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/mock_acp_agent_multi_turn.py +0 -0
  230. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/fixtures/mock_openai_responses_server.py +0 -0
  231. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/check_adapter_evidence.py +0 -0
  232. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/check_hosted_env_evidence.py +0 -0
  233. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/check_skillsbench_harbor_parity.py +0 -0
  234. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/check_trace_to_task_evidence.py +0 -0
  235. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/claude-agent-acp.yaml +0 -0
  236. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/codex-acp.yaml +0 -0
  237. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/gemini.yaml +0 -0
  238. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/harvey-lab-harness.yaml +0 -0
  239. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/openclaw.yaml +0 -0
  240. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/opencode.yaml +0 -0
  241. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/openhands.yaml +0 -0
  242. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/configs/pi-acp.yaml +0 -0
  243. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/run.sh +0 -0
  244. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/run_suite.py +0 -0
  245. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/integration/suites/release.yaml +0 -0
  246. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_acp.py +0 -0
  247. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_acp_capability_advertising.py +0 -0
  248. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_acp_model_config_dispatch.py +0 -0
  249. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_acp_pinned_protocol_guard.py +0 -0
  250. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_acp_setup_failure_propagation.py +0 -0
  251. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_adapter_scripts.py +0 -0
  252. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_adapters.py +0 -0
  253. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_cli.py +0 -0
  254. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_env_resolution.py +0 -0
  255. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_gemini_defaults.py +0 -0
  256. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_idle_timeout_cli.py +0 -0
  257. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_model_decouple.py +0 -0
  258. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_registry.py +0 -0
  259. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_setup.py +0 -0
  260. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_agent_spec.py +0 -0
  261. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_base_install_imports.py +0 -0
  262. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_bedrock_thinking.py +0 -0
  263. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_branch.py +0 -0
  264. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_capture_trajectory.py +0 -0
  265. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_clawsbench_slice.py +0 -0
  266. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_cli_daytona.py +0 -0
  267. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_cli_docs_drift.py +0 -0
  268. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_cli_misc.py +0 -0
  269. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_compat_harbor_registry.py +0 -0
  270. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_config_redaction.py +0 -0
  271. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_connect_as_env.py +0 -0
  272. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_continuallearningbench_adapter.py +0 -0
  273. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_credential_env_scrub.py +0 -0
  274. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_daytona_key.py +0 -0
  275. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_no_host_paths.py +0 -0
  276. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_release_evidence.py +0 -0
  277. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_roadmap.py +0 -0
  278. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_symlink_ingestion.py +0 -0
  279. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_dashboard_sync.py +0 -0
  280. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_daytona_command_polling.py +0 -0
  281. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_daytona_litellm_runtime.py +0 -0
  282. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_daytona_status.py +0 -0
  283. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_docker_prune_scoping.py +0 -0
  284. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_docker_uploads.py +0 -0
  285. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_docs_examples.py +0 -0
  286. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eng50_capabilities.py +0 -0
  287. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_env_setup.py +0 -0
  288. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_environment_manifest_controls.py +0 -0
  289. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_filters_applied.py +0 -0
  290. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_sharding.py +0 -0
  291. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_single_task_summary.py +0 -0
  292. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_source_provenance.py +0 -0
  293. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_worker_retry.py +0 -0
  294. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_eval_zero_task_guard.py +0 -0
  295. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_evaluation_environment_manifest.py +0 -0
  296. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_exclude_tasks.py +0 -0
  297. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_experiments_status.py +0 -0
  298. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_harvey_lab_shim.py +0 -0
  299. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_hf_scores.py +0 -0
  300. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_hilbench_adapter.py +0 -0
  301. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_hosted_env.py +0 -0
  302. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_hosted_env_rollout_contract.py +0 -0
  303. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_inbound_adapter_manifest.py +0 -0
  304. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_inbound_adapters.py +0 -0
  305. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_integration_run_suite.py +0 -0
  306. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_internet_policy.py +0 -0
  307. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_job.py +0 -0
  308. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_job_sequential_shared.py +0 -0
  309. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_job_sequential_shared_resume.py +0 -0
  310. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_judge_symlink_ingestion.py +0 -0
  311. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_learner_skills.py +0 -0
  312. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_learner_skills_traversal.py +0 -0
  313. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_learner_store.py +0 -0
  314. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_learner_store_persistence.py +0 -0
  315. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_litellm_config.py +0 -0
  316. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_litellm_hardening.py +0 -0
  317. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_litellm_logging.py +0 -0
  318. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_litellm_runtime.py +0 -0
  319. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_litellm_smoke.py +0 -0
  320. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_llm_judge.py +0 -0
  321. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_llm_judge_event_tags.py +0 -0
  322. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_llm_judge_verifier.py +0 -0
  323. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_memory_scorer.py +0 -0
  324. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_metrics.py +0 -0
  325. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_mock_openai_responses_server.py +0 -0
  326. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_monitor_scaffold.py +0 -0
  327. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_native_acp_usage.py +0 -0
  328. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_no_cross_provider_fallback.py +0 -0
  329. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_notification_order_real.py +0 -0
  330. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_oracle.py +0 -0
  331. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_oracle_chokepoint.py +0 -0
  332. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_paths_safe.py +0 -0
  333. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_paths_symlink_helpers.py +0 -0
  334. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_pi_acp_launcher.py +0 -0
  335. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_process.py +0 -0
  336. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_provider_auth_detection.py +0 -0
  337. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_providers.py +0 -0
  338. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_reexport.py +0 -0
  339. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_registry_invariants.py +0 -0
  340. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_release_version.py +0 -0
  341. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_resolve_env_helpers.py +0 -0
  342. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_reward_node.py +0 -0
  343. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_reward_unified_contract.py +0 -0
  344. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rewards.py +0 -0
  345. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rewards_jsonl.py +0 -0
  346. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_architecture.py +0 -0
  347. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_branch.py +0 -0
  348. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_config_path_coercion.py +0 -0
  349. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_environment.py +0 -0
  350. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_import_no_side_effects.py +0 -0
  351. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_on_ask_user_wiring.py +0 -0
  352. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_probe_sandbox_health.py +0 -0
  353. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rollout_upload.py +0 -0
  354. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_rubric_config.py +0 -0
  355. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_runtime.py +0 -0
  356. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_runtime_config_wired.py +0 -0
  357. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_runtime_live_sandbox.py +0 -0
  358. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox.py +0 -0
  359. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_exec_secret_handling.py +0 -0
  360. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_hardening.py +0 -0
  361. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_isolation_copy_traversal.py +0 -0
  362. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_multi_service.py +0 -0
  363. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_protocol.py +0 -0
  364. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_setup.py +0 -0
  365. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_snapshot_contract.py +0 -0
  366. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_upload_symlink.py +0 -0
  367. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sandbox_verifier_workspace.py +0 -0
  368. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_scene.py +0 -0
  369. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_scene_outbox_trial.py +0 -0
  370. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_scene_parallel_group.py +0 -0
  371. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_scene_result_aggregation.py +0 -0
  372. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_scoring.py +0 -0
  373. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sdk_internals.py +0 -0
  374. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_sdk_lockdown.py +0 -0
  375. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_self_gen_cli.py +0 -0
  376. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_self_gen_export_error_channel.py +0 -0
  377. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_self_gen_export_failures.py +0 -0
  378. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_self_gen_orchestration.py +0 -0
  379. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_session_request_permission_dispatch.py +0 -0
  380. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_eval.py +0 -0
  381. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_eval_dryrun.py +0 -0
  382. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_eval_integration.py +0 -0
  383. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_eval_sweep.py +0 -0
  384. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_eval_traversal.py +0 -0
  385. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_invocation_artifacts.py +0 -0
  386. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skill_policy.py +0 -0
  387. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skills.py +0 -0
  388. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skills_dir_agent_home_link.py +0 -0
  389. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skillsbench_harbor_parity.py +0 -0
  390. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skillsbench_harbor_run_suite.py +0 -0
  391. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_skillsbench_publish_scrub.py +0 -0
  392. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_smoke.py +0 -0
  393. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_subscription_auth.py +0 -0
  394. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_task_check_eval_consistency.py +0 -0
  395. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_task_config.py +0 -0
  396. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_task_digest.py +0 -0
  397. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_task_download.py +0 -0
  398. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_tasks.py +0 -0
  399. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_token_usage_normalization.py +0 -0
  400. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trace_import_cli.py +0 -0
  401. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trace_task_gen_traversal.py +0 -0
  402. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trace_to_task_evidence.py +0 -0
  403. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_traces_huggingface.py +0 -0
  404. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_traces_parsers.py +0 -0
  405. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_traces_task_gen.py +0 -0
  406. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_train_mode_artifact_emission.py +0 -0
  407. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trajectory_integration.py +0 -0
  408. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trajectory_streaming.py +0 -0
  409. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trial_agent_timeout_verify.py +0 -0
  410. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trial_install_agent_timeout.py +0 -0
  411. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_trial_litellm_runtime.py +0 -0
  412. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_usage_litellm.py +0 -0
  413. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_usage_required.py +0 -0
  414. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_usage_tracking.py +0 -0
  415. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_user.py +0 -0
  416. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_verifier_multi_container.py +0 -0
  417. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_verifier_output.py +0 -0
  418. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_verifier_output_freshness.py +0 -0
  419. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_verify.py +0 -0
  420. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_workflow_action_pinning.py +0 -0
  421. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/test_yaml_config.py +0 -0
  422. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/__init__.py +0 -0
  423. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/test_export.py +0 -0
  424. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/test_export_nan_handling.py +0 -0
  425. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/test_redaction.py +0 -0
  426. {benchflow-0.5.3.dev976 → benchflow-0.5.3.dev980}/tests/trajectories/test_step_granularity.py +0 -0
  427. {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.dev976
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "benchflow"
3
- version = "0.5.3.dev976"
3
+ version = "0.5.3.dev980"
4
4
  description = "Multi-turn agent benchmarking with ACP — run any agent, any model, any provider."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -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 = [bool(config_file), bool(tasks_dir), bool(source_repo), bool(source_env)]
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, or --source-env[/red]"
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, or --source-env[/red]"
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 source_issues, source_matches_parent
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")