agentevolve-optimizer 0.5.0__py3-none-any.whl

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 (414) hide show
  1. agent_evolve/__init__.py +722 -0
  2. agent_evolve/agentic.py +2800 -0
  3. agent_evolve/api.py +767 -0
  4. agent_evolve/application/__init__.py +1580 -0
  5. agent_evolve/application/action_allocation.py +744 -0
  6. agent_evolve/application/action_allocation_frame.py +347 -0
  7. agent_evolve/application/action_allocation_frame_commit.py +185 -0
  8. agent_evolve/application/action_allocation_frame_commit_v3.py +184 -0
  9. agent_evolve/application/action_allocation_frame_v3.py +338 -0
  10. agent_evolve/application/action_archive_value.py +497 -0
  11. agent_evolve/application/action_evidence_consistency.py +455 -0
  12. agent_evolve/application/action_forecast_partitioning.py +1471 -0
  13. agent_evolve/application/action_metric_projection.py +211 -0
  14. agent_evolve/application/action_role_value.py +680 -0
  15. agent_evolve/application/action_score_authorities.py +363 -0
  16. agent_evolve/application/action_structural_signature.py +116 -0
  17. agent_evolve/application/action_target_realization.py +402 -0
  18. agent_evolve/application/agentic_evolution.py +7734 -0
  19. agent_evolve/application/agentic_portfolio_residual_expert.py +835 -0
  20. agent_evolve/application/anchor_residual_identification.py +463 -0
  21. agent_evolve/application/archive_conditioned_action_target.py +208 -0
  22. agent_evolve/application/artifact_journal.py +246 -0
  23. agent_evolve/application/artifact_replay.py +347 -0
  24. agent_evolve/application/budgeted_optimizer.py +1828 -0
  25. agent_evolve/application/calibrated_campaign.py +485 -0
  26. agent_evolve/application/calibrated_current_prefix_forecast_opportunity.py +322 -0
  27. agent_evolve/application/calibrated_positive_gain_opportunity.py +1581 -0
  28. agent_evolve/application/campaign_capacity_recourse.py +254 -0
  29. agent_evolve/application/campaign_contextual_outcomes.py +119 -0
  30. agent_evolve/application/campaign_diagnostic_blocks.py +930 -0
  31. agent_evolve/application/campaign_evidence_registry.py +262 -0
  32. agent_evolve/application/campaign_execution.py +2537 -0
  33. agent_evolve/application/campaign_generation_audit.py +942 -0
  34. agent_evolve/application/campaign_learning.py +1812 -0
  35. agent_evolve/application/campaign_learning_runtime.py +1977 -0
  36. agent_evolve/application/campaign_search_phase.py +227 -0
  37. agent_evolve/application/campaign_selector_context_extension.py +220 -0
  38. agent_evolve/application/campaign_variation_envelope.py +649 -0
  39. agent_evolve/application/campaign_variation_trace.py +451 -0
  40. agent_evolve/application/candidate_archive_consequence.py +128 -0
  41. agent_evolve/application/causal_opportunity_portfolio_gate.py +385 -0
  42. agent_evolve/application/composite_outcome_updater.py +145 -0
  43. agent_evolve/application/composition_portfolio_selection.py +363 -0
  44. agent_evolve/application/concurrent_stage.py +144 -0
  45. agent_evolve/application/contextual_action_allocation.py +181 -0
  46. agent_evolve/application/contextual_campaign_outcomes.py +267 -0
  47. agent_evolve/application/contextual_campaign_planning.py +1366 -0
  48. agent_evolve/application/contextual_delayed_credit.py +651 -0
  49. agent_evolve/application/contextual_search_controller.py +2374 -0
  50. agent_evolve/application/current_prefix_forecast_opportunity.py +714 -0
  51. agent_evolve/application/decision_metric_projection.py +112 -0
  52. agent_evolve/application/derived_action_semantics.py +129 -0
  53. agent_evolve/application/detailed_evaluation.py +449 -0
  54. agent_evolve/application/earned_lineage.py +1011 -0
  55. agent_evolve/application/effective_choice_audit.py +484 -0
  56. agent_evolve/application/empirical_consequence_calibration.py +908 -0
  57. agent_evolve/application/evaluation_accounting.py +325 -0
  58. agent_evolve/application/evaluation_cache.py +199 -0
  59. agent_evolve/application/evaluation_escrow.py +547 -0
  60. agent_evolve/application/evaluation_recourse.py +253 -0
  61. agent_evolve/application/event_recorder.py +151 -0
  62. agent_evolve/application/evolution_campaign.py +1840 -0
  63. agent_evolve/application/executable_hypothesis.py +323 -0
  64. agent_evolve/application/factorial_branch_pilot.py +772 -0
  65. agent_evolve/application/finite_acquisition_capacity_recourse.py +672 -0
  66. agent_evolve/application/finite_acquisition_residual_expert.py +373 -0
  67. agent_evolve/application/finite_acquisition_variation_envelope.py +802 -0
  68. agent_evolve/application/finite_action_hypothesis_semantics.py +446 -0
  69. agent_evolve/application/finite_action_selection.py +188 -0
  70. agent_evolve/application/finite_action_set.py +306 -0
  71. agent_evolve/application/finite_action_transition.py +537 -0
  72. agent_evolve/application/finite_variation_eligibility.py +296 -0
  73. agent_evolve/application/forecast_geometry_portfolio.py +799 -0
  74. agent_evolve/application/forecast_opportunity_shadow_calibration.py +316 -0
  75. agent_evolve/application/front_proximity_admission.py +311 -0
  76. agent_evolve/application/front_proximity_parent_basis.py +458 -0
  77. agent_evolve/application/frozen_hurdle_score.py +659 -0
  78. agent_evolve/application/g3_causal_screen.py +2257 -0
  79. agent_evolve/application/g3_causal_validation.py +1046 -0
  80. agent_evolve/application/g3_postseal_curation.py +818 -0
  81. agent_evolve/application/gated_agentic_generator.py +205 -0
  82. agent_evolve/application/generation_feedback.py +293 -0
  83. agent_evolve/application/generative_proposal_journal.py +185 -0
  84. agent_evolve/application/geometry_conditional_elasticity.py +453 -0
  85. agent_evolve/application/global_wave_action_allocation.py +1151 -0
  86. agent_evolve/application/head_mass_conditional_seat.py +268 -0
  87. agent_evolve/application/identifiable_reflection_evidence.py +1147 -0
  88. agent_evolve/application/identifiable_reflection_learning.py +395 -0
  89. agent_evolve/application/identifiable_reflection_request.py +364 -0
  90. agent_evolve/application/in_memory_residual_archive.py +341 -0
  91. agent_evolve/application/insight_memory.py +1804 -0
  92. agent_evolve/application/live_runtime_manifest.py +758 -0
  93. agent_evolve/application/llm_task_queue.py +769 -0
  94. agent_evolve/application/matched_finite_action_block.py +409 -0
  95. agent_evolve/application/materialized_action_broker.py +2328 -0
  96. agent_evolve/application/materialized_action_constraints.py +83 -0
  97. agent_evolve/application/materialized_variation.py +211 -0
  98. agent_evolve/application/multi_option_evolution.py +1536 -0
  99. agent_evolve/application/outcome_adaptive_action_racing.py +2827 -0
  100. agent_evolve/application/outcome_adaptive_residual_campaign_runtime.py +580 -0
  101. agent_evolve/application/outcome_adaptive_residual_portfolio_evolution.py +3671 -0
  102. agent_evolve/application/outcome_conditioned_portfolio_selection.py +1374 -0
  103. agent_evolve/application/outcome_relation.py +193 -0
  104. agent_evolve/application/paired_allocation_comparison.py +241 -0
  105. agent_evolve/application/paired_block_schedule.py +127 -0
  106. agent_evolve/application/parent_measurement.py +226 -0
  107. agent_evolve/application/pareto_archive.py +811 -0
  108. agent_evolve/application/portfolio_campaign_runtime.py +4739 -0
  109. agent_evolve/application/portfolio_evolution.py +2950 -0
  110. agent_evolve/application/portfolio_hypothesis_observations.py +814 -0
  111. agent_evolve/application/portfolio_memory_attribution.py +581 -0
  112. agent_evolve/application/portfolio_memory_dose.py +788 -0
  113. agent_evolve/application/portfolio_memory_matched_control.py +938 -0
  114. agent_evolve/application/portfolio_memory_transfer.py +297 -0
  115. agent_evolve/application/portfolio_optimization_memory.py +363 -0
  116. agent_evolve/application/portfolio_outcome_feedback.py +1613 -0
  117. agent_evolve/application/portfolio_projection.py +335 -0
  118. agent_evolve/application/portfolio_recombination.py +2032 -0
  119. agent_evolve/application/post_evolution_reflection.py +834 -0
  120. agent_evolve/application/postcommit_rank_authority.py +245 -0
  121. agent_evolve/application/precommitted_portfolio_racing.py +2762 -0
  122. agent_evolve/application/prequential_archive_opportunity_calibration.py +1154 -0
  123. agent_evolve/application/prequential_residual_exploration.py +343 -0
  124. agent_evolve/application/prequential_score_portfolio.py +954 -0
  125. agent_evolve/application/projections.py +292 -0
  126. agent_evolve/application/protected_action_committee.py +1027 -0
  127. agent_evolve/application/protected_branch_pilot.py +376 -0
  128. agent_evolve/application/protected_current_prefix_forecast_opportunity.py +552 -0
  129. agent_evolve/application/provider_replay.py +910 -0
  130. agent_evolve/application/rank_balanced_causal_pilot.py +1372 -0
  131. agent_evolve/application/recombination_residual_expert.py +403 -0
  132. agent_evolve/application/reflection_workflow.py +571 -0
  133. agent_evolve/application/region_conditional_credit.py +911 -0
  134. agent_evolve/application/residual_campaign_runtime.py +531 -0
  135. agent_evolve/application/residual_headroom_campaign_runtime.py +459 -0
  136. agent_evolve/application/residual_headroom_ledger.py +1544 -0
  137. agent_evolve/application/residual_learning_transaction.py +396 -0
  138. agent_evolve/application/residual_portfolio_evolution.py +1228 -0
  139. agent_evolve/application/residual_reachability.py +749 -0
  140. agent_evolve/application/residual_stage_credit.py +499 -0
  141. agent_evolve/application/same_prefix_paired_audit.py +1580 -0
  142. agent_evolve/application/semantic_coverage_score_portfolio.py +838 -0
  143. agent_evolve/application/sequential_lineage_allocation.py +1017 -0
  144. agent_evolve/application/sequential_market_replay.py +1395 -0
  145. agent_evolve/application/sequential_residual_campaign_runtime.py +305 -0
  146. agent_evolve/application/sequential_residual_portfolio_evolution.py +940 -0
  147. agent_evolve/application/single_score_action_allocation.py +299 -0
  148. agent_evolve/application/source_exposure_allocation.py +906 -0
  149. agent_evolve/application/staged_memory.py +210 -0
  150. agent_evolve/application/stratified_cold_start_allocation.py +732 -0
  151. agent_evolve/application/support_guarded_hurdle_score.py +549 -0
  152. agent_evolve/application/target_conditioned_action_forecast.py +595 -0
  153. agent_evolve/application/target_conditioned_campaign.py +566 -0
  154. agent_evolve/application/treatment_assignment.py +201 -0
  155. agent_evolve/application/trusted_objective_evidence.py +217 -0
  156. agent_evolve/application/two_stage_action_evolution.py +1131 -0
  157. agent_evolve/application/v8lite_allocation_policy.py +1083 -0
  158. agent_evolve/application/v9_candidate_policy.py +1303 -0
  159. agent_evolve/bootstrap.py +108 -0
  160. agent_evolve/campaign_presets.py +517 -0
  161. agent_evolve/campaign_profiles.py +452 -0
  162. agent_evolve/campaign_variation_topology.py +288 -0
  163. agent_evolve/campaign_workload.py +950 -0
  164. agent_evolve/cli.py +797 -0
  165. agent_evolve/contract.py +241 -0
  166. agent_evolve/core/__init__.py +91 -0
  167. agent_evolve/core/action_semantics.py +411 -0
  168. agent_evolve/core/authored.py +105 -0
  169. agent_evolve/core/formatting.py +286 -0
  170. agent_evolve/core/optimization_semantics.py +324 -0
  171. agent_evolve/core/problem.py +167 -0
  172. agent_evolve/core/results.py +323 -0
  173. agent_evolve/core/stats.py +70 -0
  174. agent_evolve/core/telemetry.py +100 -0
  175. agent_evolve/domain/__init__.py +89 -0
  176. agent_evolve/domain/artifact.py +162 -0
  177. agent_evolve/domain/durable_text.py +68 -0
  178. agent_evolve/domain/event.py +1454 -0
  179. agent_evolve/domain/finite_action_set.py +426 -0
  180. agent_evolve/domain/finite_variation.py +526 -0
  181. agent_evolve/domain/generative_emission.py +559 -0
  182. agent_evolve/domain/ids.py +163 -0
  183. agent_evolve/domain/inline_text.py +106 -0
  184. agent_evolve/domain/insight.py +27 -0
  185. agent_evolve/domain/lineage.py +737 -0
  186. agent_evolve/domain/llm_task_queue.py +960 -0
  187. agent_evolve/domain/outcome.py +96 -0
  188. agent_evolve/domain/patch.py +854 -0
  189. agent_evolve/domain/typed_json.py +542 -0
  190. agent_evolve/domain/variation_space.py +158 -0
  191. agent_evolve/driver.py +1014 -0
  192. agent_evolve/harness/__init__.py +29 -0
  193. agent_evolve/harness/base.py +242 -0
  194. agent_evolve/harness/directives.py +163 -0
  195. agent_evolve/harness/generative_seal.py +479 -0
  196. agent_evolve/harness/registry.py +41 -0
  197. agent_evolve/infrastructure/__init__.py +39 -0
  198. agent_evolve/infrastructure/artifacts/__init__.py +6 -0
  199. agent_evolve/infrastructure/artifacts/_verification.py +67 -0
  200. agent_evolve/infrastructure/artifacts/filesystem.py +343 -0
  201. agent_evolve/infrastructure/artifacts/in_memory.py +73 -0
  202. agent_evolve/infrastructure/asyncio_runtime.py +109 -0
  203. agent_evolve/infrastructure/authored_runtime.py +188 -0
  204. agent_evolve/infrastructure/authored_worker.py +171 -0
  205. agent_evolve/infrastructure/clock.py +53 -0
  206. agent_evolve/infrastructure/events/__init__.py +6 -0
  207. agent_evolve/infrastructure/events/_validation.py +89 -0
  208. agent_evolve/infrastructure/events/in_memory.py +56 -0
  209. agent_evolve/infrastructure/events/jsonl.py +193 -0
  210. agent_evolve/infrastructure/exception_provenance.py +215 -0
  211. agent_evolve/infrastructure/ids.py +118 -0
  212. agent_evolve/infrastructure/lineage_codec.py +1836 -0
  213. agent_evolve/infrastructure/outcome_adaptive_phase_journal.py +170 -0
  214. agent_evolve/infrastructure/residual_headroom_journal.py +221 -0
  215. agent_evolve/infrastructure/resource_lease.py +370 -0
  216. agent_evolve/infrastructure/sanitization/__init__.py +8 -0
  217. agent_evolve/infrastructure/sanitization/strict_json.py +484 -0
  218. agent_evolve/infrastructure/sequential_phase_journal.py +170 -0
  219. agent_evolve/infrastructure/stream_liveness.py +383 -0
  220. agent_evolve/infrastructure/subprocess_boundary.py +136 -0
  221. agent_evolve/integrations/__init__.py +1 -0
  222. agent_evolve/integrations/botorch/__init__.py +28 -0
  223. agent_evolve/integrations/botorch/finite_qlognehvi.py +190 -0
  224. agent_evolve/integrations/botorch/finite_qlognehvi_batch.py +155 -0
  225. agent_evolve/integrations/botorch/finite_qlognehvi_batch_identity.py +20 -0
  226. agent_evolve/integrations/botorch/finite_qlognehvi_batch_worker.py +55 -0
  227. agent_evolve/integrations/botorch/finite_qlognehvi_identity.py +22 -0
  228. agent_evolve/integrations/botorch/finite_qlognehvi_worker.py +55 -0
  229. agent_evolve/integrations/botorch/subprocess_qlognehvi.py +261 -0
  230. agent_evolve/integrations/botorch/subprocess_qlognehvi_batch.py +273 -0
  231. agent_evolve/integrations/completion.py +242 -0
  232. agent_evolve/integrations/pydantic_ai/__init__.py +441 -0
  233. agent_evolve/integrations/pydantic_ai/action_forecast.py +1068 -0
  234. agent_evolve/integrations/pydantic_ai/agentic_generator.py +2308 -0
  235. agent_evolve/integrations/pydantic_ai/async_generator.py +1604 -0
  236. agent_evolve/integrations/pydantic_ai/boundary_codec.py +1526 -0
  237. agent_evolve/integrations/pydantic_ai/calibrated_portfolio_campaign.py +756 -0
  238. agent_evolve/integrations/pydantic_ai/calibrated_portfolio_selection.py +7537 -0
  239. agent_evolve/integrations/pydantic_ai/campaign_acquisition.py +609 -0
  240. agent_evolve/integrations/pydantic_ai/execution_binding.py +138 -0
  241. agent_evolve/integrations/pydantic_ai/forecast_geometry_action_committee.py +217 -0
  242. agent_evolve/integrations/pydantic_ai/harness.py +159 -0
  243. agent_evolve/integrations/pydantic_ai/heterogeneous_model_execution.py +306 -0
  244. agent_evolve/integrations/pydantic_ai/hierarchical_residual_adaptive_semantic_view.py +179 -0
  245. agent_evolve/integrations/pydantic_ai/json_schema_dialect.py +108 -0
  246. agent_evolve/integrations/pydantic_ai/materialized_hierarchical_residual_expert.py +952 -0
  247. agent_evolve/integrations/pydantic_ai/materialized_portfolio_judge.py +520 -0
  248. agent_evolve/integrations/pydantic_ai/model_execution_profile.py +659 -0
  249. agent_evolve/integrations/pydantic_ai/outbound_request_manifest.py +1170 -0
  250. agent_evolve/integrations/pydantic_ai/portable_residual_consequence_features.py +575 -0
  251. agent_evolve/integrations/pydantic_ai/portfolio_selection.py +422 -0
  252. agent_evolve/integrations/pydantic_ai/progress_aware_openrouter.py +416 -0
  253. agent_evolve/integrations/pydantic_ai/provider_attempt_join.py +1523 -0
  254. agent_evolve/integrations/pydantic_ai/provider_free_calibrated_runner.py +607 -0
  255. agent_evolve/integrations/pydantic_ai/queued_runner.py +2634 -0
  256. agent_evolve/integrations/pydantic_ai/reconciled_residual_reachability.py +1417 -0
  257. agent_evolve/integrations/pydantic_ai/residual_forecast_geometry.py +445 -0
  258. agent_evolve/integrations/pydantic_ai/residual_reachability.py +674 -0
  259. agent_evolve/integrations/pydantic_ai/residual_semantic_cells.py +239 -0
  260. agent_evolve/integrations/pydantic_ai/sealed_output_replay.py +1068 -0
  261. agent_evolve/integrations/pydantic_ai/semantic_coverage_residual_portfolio.py +770 -0
  262. agent_evolve/integrations/pydantic_ai/semantic_decision_replay.py +383 -0
  263. agent_evolve/integrations/pydantic_ai/support_adaptive_residual_portfolio.py +135 -0
  264. agent_evolve/integrations/pydantic_ai/trusted_residual_prompt_context.py +143 -0
  265. agent_evolve/integrations/pydantic_ai/validated_openrouter_model.py +107 -0
  266. agent_evolve/integrations/pymoo_adapter.py +242 -0
  267. agent_evolve/policies/__init__.py +17 -0
  268. agent_evolve/policies/check.py +469 -0
  269. agent_evolve/policies/emit_scaffold.py +451 -0
  270. agent_evolve/policies/feedback/__init__.py +37 -0
  271. agent_evolve/policies/feedback/held_out_asn.py +1325 -0
  272. agent_evolve/policies/genetic.py +607 -0
  273. agent_evolve/policies/llm_backoff.py +183 -0
  274. agent_evolve/policies/llm_chooser.py +226 -0
  275. agent_evolve/policies/llm_generator.py +1760 -0
  276. agent_evolve/policies/llm_init.py +267 -0
  277. agent_evolve/policies/llm_operator.py +109 -0
  278. agent_evolve/policies/llm_prior.py +194 -0
  279. agent_evolve/policies/llm_surrogate.py +334 -0
  280. agent_evolve/policies/measurement_evidence.py +704 -0
  281. agent_evolve/policies/memory/__init__.py +223 -0
  282. agent_evolve/policies/memory/balanced_subset_blocks.py +707 -0
  283. agent_evolve/policies/memory/compatibility_matching.py +593 -0
  284. agent_evolve/policies/memory/global_falsification.py +1841 -0
  285. agent_evolve/policies/memory/prompt_shape.py +503 -0
  286. agent_evolve/policies/memory/randomized_subset.py +714 -0
  287. agent_evolve/policies/memory/staged_causal.py +1270 -0
  288. agent_evolve/policies/memory/treatment_compliance.py +759 -0
  289. agent_evolve/policies/objective_resolution/__init__.py +17 -0
  290. agent_evolve/policies/objective_resolution/fixed_grid.py +364 -0
  291. agent_evolve/policies/operator_portfolio.py +407 -0
  292. agent_evolve/policies/reguidance.py +1133 -0
  293. agent_evolve/policies/reward/__init__.py +83 -0
  294. agent_evolve/policies/reward/affine_candidate_consequence.py +156 -0
  295. agent_evolve/policies/reward/affine_candidate_consequence_3d.py +159 -0
  296. agent_evolve/policies/reward/affine_hypervolume.py +490 -0
  297. agent_evolve/policies/reward/affine_hypervolume_3d.py +567 -0
  298. agent_evolve/policies/reward/contextual_marginal_utility.py +318 -0
  299. agent_evolve/policies/reward/frozen_archive.py +360 -0
  300. agent_evolve/policies/reward/frozen_wave_archive.py +368 -0
  301. agent_evolve/policies/search_state.py +208 -0
  302. agent_evolve/policies/selection/__init__.py +345 -0
  303. agent_evolve/policies/selection/acquisition_certified_slate.py +684 -0
  304. agent_evolve/policies/selection/affine_frontier_context.py +330 -0
  305. agent_evolve/policies/selection/affine_frontier_target.py +473 -0
  306. agent_evolve/policies/selection/archive_elite.py +1346 -0
  307. agent_evolve/policies/selection/calibrated_portfolio_binding.py +640 -0
  308. agent_evolve/policies/selection/calibrated_slate.py +1394 -0
  309. agent_evolve/policies/selection/calibrated_slate_codec.py +579 -0
  310. agent_evolve/policies/selection/common_candidate_pool.py +685 -0
  311. agent_evolve/policies/selection/diagnostic_sampling.py +319 -0
  312. agent_evolve/policies/selection/disjoint_pairs.py +479 -0
  313. agent_evolve/policies/selection/elite_explorer.py +719 -0
  314. agent_evolve/policies/selection/finite_action.py +187 -0
  315. agent_evolve/policies/selection/finite_option_prompt_projection.py +377 -0
  316. agent_evolve/policies/selection/finite_palette_evidence.py +247 -0
  317. agent_evolve/policies/selection/forecast_calibration.py +922 -0
  318. agent_evolve/policies/selection/frontier_probe_slate.py +814 -0
  319. agent_evolve/policies/selection/frozen_archive_pairs.py +762 -0
  320. agent_evolve/policies/selection/full_support_slate.py +91 -0
  321. agent_evolve/policies/selection/meaningful_direction.py +240 -0
  322. agent_evolve/policies/selection/memory_dose_feasibility.py +259 -0
  323. agent_evolve/policies/selection/model_anchored_slate.py +826 -0
  324. agent_evolve/policies/selection/phenotype_recourse.py +979 -0
  325. agent_evolve/policies/selection/proposal_support.py +368 -0
  326. agent_evolve/policies/selection/random_portfolio.py +254 -0
  327. agent_evolve/policies/selection/regret_bounded_slate.py +1084 -0
  328. agent_evolve/policies/selection/residual_frontier.py +463 -0
  329. agent_evolve/policies/selection/residual_frontier_target.py +605 -0
  330. agent_evolve/policies/selection/structural_posterior_slate.py +1571 -0
  331. agent_evolve/policies/selection/target_conditioned_allocator.py +648 -0
  332. agent_evolve/policies/selection/target_conditioned_features.py +812 -0
  333. agent_evolve/policies/selection/target_conditioned_prequential.py +1527 -0
  334. agent_evolve/policies/selection/task_keyed_palette.py +906 -0
  335. agent_evolve/policies/semantics.py +147 -0
  336. agent_evolve/policies/structure.py +362 -0
  337. agent_evolve/policies/structured_output_budget.py +62 -0
  338. agent_evolve/policies/surrogate.py +696 -0
  339. agent_evolve/policies/variation/__init__.py +1 -0
  340. agent_evolve/policies/variation/compositional_finite_catalog.py +426 -0
  341. agent_evolve/policies/variation/crossover_inheritance.py +575 -0
  342. agent_evolve/policies/variation/disjoint_recombination.py +611 -0
  343. agent_evolve/policies/variation/exact_composition_capacity.py +214 -0
  344. agent_evolve/policies/variation/exact_parent_crossover.py +950 -0
  345. agent_evolve/policies/variation/multiscale_restart_catalog.py +372 -0
  346. agent_evolve/policies/variation/source_union_finite_catalog.py +403 -0
  347. agent_evolve/policies/variation/typed_patch.py +1981 -0
  348. agent_evolve/policies/weighted_prior.py +394 -0
  349. agent_evolve/ports/__init__.py +383 -0
  350. agent_evolve/ports/action_allocation.py +733 -0
  351. agent_evolve/ports/action_allocation_frame.py +1153 -0
  352. agent_evolve/ports/action_allocation_frame_commit.py +294 -0
  353. agent_evolve/ports/action_allocation_frame_commit_v3.py +432 -0
  354. agent_evolve/ports/action_allocation_frame_v3.py +995 -0
  355. agent_evolve/ports/action_forecast.py +1568 -0
  356. agent_evolve/ports/action_metric_projection.py +165 -0
  357. agent_evolve/ports/agentic_generator.py +1561 -0
  358. agent_evolve/ports/archive_context.py +136 -0
  359. agent_evolve/ports/artifact_sanitizer.py +44 -0
  360. agent_evolve/ports/artifact_store.py +225 -0
  361. agent_evolve/ports/clock.py +13 -0
  362. agent_evolve/ports/contextual_search_allocation.py +827 -0
  363. agent_evolve/ports/decision_metric_projection.py +258 -0
  364. agent_evolve/ports/event_store.py +55 -0
  365. agent_evolve/ports/executable_hypothesis.py +557 -0
  366. agent_evolve/ports/finite_acquisition.py +377 -0
  367. agent_evolve/ports/finite_acquisition_batch.py +296 -0
  368. agent_evolve/ports/finite_acquisition_batch_json.py +164 -0
  369. agent_evolve/ports/finite_acquisition_json.py +247 -0
  370. agent_evolve/ports/finite_acquisition_space.py +168 -0
  371. agent_evolve/ports/finite_action_selection.py +348 -0
  372. agent_evolve/ports/finite_action_set.py +256 -0
  373. agent_evolve/ports/frontier_target.py +396 -0
  374. agent_evolve/ports/generation_failure.py +43 -0
  375. agent_evolve/ports/hard_feasibility.py +233 -0
  376. agent_evolve/ports/id_factory.py +34 -0
  377. agent_evolve/ports/llm_task_queue.py +93 -0
  378. agent_evolve/ports/objective_resolution.py +419 -0
  379. agent_evolve/ports/paired_allocation_comparison.py +401 -0
  380. agent_evolve/ports/paired_block_schedule.py +475 -0
  381. agent_evolve/ports/parent_measurement.py +336 -0
  382. agent_evolve/ports/portfolio_memory_dose.py +643 -0
  383. agent_evolve/ports/portfolio_selection.py +3169 -0
  384. agent_evolve/ports/postcommit_rank_authority.py +467 -0
  385. agent_evolve/ports/presented_action_evidence.py +794 -0
  386. agent_evolve/ports/resource_lease.py +162 -0
  387. agent_evolve/ports/structured_generator.py +734 -0
  388. agent_evolve/ports/structured_output_budget.py +120 -0
  389. agent_evolve/ports/subprocess_boundary.py +138 -0
  390. agent_evolve/ports/treatment_assignment.py +466 -0
  391. agent_evolve/ports/variation_catalog.py +76 -0
  392. agent_evolve/ports/variation_source.py +226 -0
  393. agent_evolve/proposal_mode.py +157 -0
  394. agent_evolve/proposers/__init__.py +10 -0
  395. agent_evolve/proposers/random_proposer.py +188 -0
  396. agent_evolve/provider_accounting.py +163 -0
  397. agent_evolve/py.typed +0 -0
  398. agent_evolve/reference_method.py +1570 -0
  399. agent_evolve/session/__init__.py +11 -0
  400. agent_evolve/session/authorship.py +864 -0
  401. agent_evolve/session/evaluate.py +236 -0
  402. agent_evolve/session/fidelity.py +237 -0
  403. agent_evolve/session/genetic_loop.py +742 -0
  404. agent_evolve/session/loop.py +803 -0
  405. agent_evolve/session/screening.py +671 -0
  406. agent_evolve/settings.py +376 -0
  407. agent_evolve/workload_kit.py +368 -0
  408. agent_evolve/workload_prompt.py +398 -0
  409. agentevolve_optimizer-0.5.0.dist-info/METADATA +599 -0
  410. agentevolve_optimizer-0.5.0.dist-info/RECORD +414 -0
  411. agentevolve_optimizer-0.5.0.dist-info/WHEEL +5 -0
  412. agentevolve_optimizer-0.5.0.dist-info/entry_points.txt +2 -0
  413. agentevolve_optimizer-0.5.0.dist-info/licenses/LICENSE +21 -0
  414. agentevolve_optimizer-0.5.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,469 @@
1
+ """Pre-flight problem diagnostic: ``check(problem, budget) -> CheckReport``.
2
+
3
+ Before any optimizer -- model-guided or not -- is credited with anything on a
4
+ problem, two questions have answers the problem itself can give:
5
+
6
+ 1. **What is the search space, actually?** How many heritable loci does a
7
+ candidate carry, how many values does the schema declare at each, and which
8
+ loci declare none (those an uninformed sampler cannot vary at all)? A locus
9
+ whose values are a finite projection of a declared *range* is marked
10
+ ``(projected)``: it is searchable, but on its grid rather than its
11
+ continuum, and a reader who cannot tell the two apart will over-read the
12
+ count.
13
+
14
+ 2. **Is there anything to win at this budget?** If the best value a broad
15
+ uniform probe can find is within noise of what ``budget`` random draws are
16
+ expected to reach anyway, then *no optimizer can demonstrate an advantage
17
+ here at this budget* -- not because optimizers are useless, but because the
18
+ measurement cannot separate one from chance. This project has been burned by
19
+ exactly that: on one benchmark a single median random draw already carried
20
+ roughly 80 percent of the final hypervolume.
21
+
22
+ The probe draws ``probe`` schema-uniform candidates (via
23
+ :func:`agent_evolve.policies.genetic.uniform_candidate`, so only declared
24
+ domains are sampled and nothing is invented) and pushes each through the
25
+ problem's own ``validate -> materialize -> evaluate`` pipeline, recording
26
+ failures at every stage and the wall-clock cost of ``evaluate``.
27
+
28
+ **What is spent.** The probe costs at most ``probe`` evaluations -- ``budget``
29
+ is the optimizer budget *being assessed*, not the probe's spend, exactly as
30
+ ``agent_evolve check`` spends ``repeats x budget`` evaluations to assess one
31
+ budget. A probe larger than the budget is the informative regime: it looks
32
+ further than the budget can, and asks whether the extra looking found anything
33
+ the budget would miss.
34
+
35
+ **The headroom estimate.** For each objective, the best value seen anywhere in
36
+ the probe is compared with the distribution of the best of ``budget`` uniform
37
+ redraws from the probe's own empirical values. That distribution is computed in
38
+ closed form (the exact bootstrap, not a Monte Carlo approximation of it), so
39
+ the reported noise is the sampling noise of a ``budget``-draw run with nothing
40
+ added by the estimator. Headroom at or below that noise means chance already
41
+ covers everything the probe found.
42
+
43
+ Everything here is workload-agnostic and credential-free: no model, no
44
+ provider, no network. The loci, domains and objective directions all come from
45
+ the problem's own declarations.
46
+ """
47
+
48
+ from __future__ import annotations
49
+
50
+ import math
51
+ import random
52
+ import statistics
53
+ import textwrap
54
+ import time
55
+ from dataclasses import dataclass
56
+ from typing import Any, Mapping, Optional, Sequence
57
+
58
+ from agent_evolve.contract import as_problem
59
+ from agent_evolve.core.problem import normalize_objective_values
60
+ from agent_evolve.policies.genetic import (
61
+ loci_of,
62
+ locus_domain,
63
+ locus_is_projected,
64
+ uniform_candidate,
65
+ )
66
+
67
+ __all__ = [
68
+ "check",
69
+ "CheckReport",
70
+ "LocusDomain",
71
+ "ObjectiveSpread",
72
+ "ObjectiveHeadroom",
73
+ ]
74
+
75
+ #: The plain-language conclusion for a problem/budget pair on which the probe
76
+ #: found nothing that chance at the same budget would not also find. Tests and
77
+ #: callers match on this exact sentence, so it is a named constant.
78
+ NO_HEADROOM_VERDICT = "no optimizer can demonstrate an advantage here at this budget"
79
+
80
+
81
+ @dataclass(frozen=True, slots=True)
82
+ class LocusDomain:
83
+ """One heritable position and how many values the schema declares for it."""
84
+
85
+ locus: str
86
+ domain_size: int #: 0 means the schema declares no finite set here.
87
+ #: True when the values are a finite projection of a declared *range*
88
+ #: rather than a set the schema enumerated. Such a locus is searchable, but
89
+ #: only on its grid: the report says so instead of letting a reader mistake
90
+ #: a projected 16 for an enumerated 16.
91
+ projected: bool = False
92
+
93
+ @property
94
+ def declared(self) -> bool:
95
+ return self.domain_size > 0
96
+
97
+
98
+ @dataclass(frozen=True, slots=True)
99
+ class ObjectiveSpread:
100
+ """How one objective varied over the probe's successful evaluations."""
101
+
102
+ objective: str
103
+ goal: str
104
+ count: int
105
+ minimum: float
106
+ maximum: float
107
+ mean: float
108
+ stdev: float
109
+
110
+
111
+ @dataclass(frozen=True, slots=True)
112
+ class ObjectiveHeadroom:
113
+ """Best-of-probe against the exact best-of-budget bootstrap, one objective."""
114
+
115
+ objective: str
116
+ goal: str
117
+ best_of_probe: float
118
+ #: Expected best of ``budget`` uniform redraws from the probe's values.
119
+ best_of_budget: float
120
+ #: Standard deviation of that best-of-budget distribution -- the noise a
121
+ #: single budget-sized random run carries.
122
+ noise: float
123
+ #: Improvement still on the table beyond expected chance, in the improving
124
+ #: direction (always >= 0).
125
+ headroom: float
126
+ below_noise: bool
127
+
128
+
129
+ @dataclass(frozen=True, slots=True)
130
+ class CheckReport:
131
+ """Everything :func:`check` measured, plus the plain-language verdict."""
132
+
133
+ problem: str
134
+ budget: int
135
+ probe: int
136
+ draws: int
137
+ evaluated: int
138
+ loci: tuple[LocusDomain, ...]
139
+ undeclared_loci: tuple[str, ...]
140
+ validate_failures: int
141
+ materialize_failures: int
142
+ evaluate_failures: int
143
+ failure_rate: float
144
+ failure_examples: tuple[str, ...]
145
+ eval_seconds_median: float
146
+ spread: tuple[ObjectiveSpread, ...]
147
+ headroom: tuple[ObjectiveHeadroom, ...]
148
+ verdict: str
149
+
150
+ @property
151
+ def locus_count(self) -> int:
152
+ return len(self.loci)
153
+
154
+ def render(self) -> str:
155
+ """The report as plain text, in the same voice as the CLI."""
156
+ lines: list[str] = [f"problem check: {self.problem}"]
157
+ lines.append(f" budget assessed {self.budget} evaluations")
158
+ lines.append(
159
+ f" probe spent {self.draws} draws, {self.evaluated} evaluated"
160
+ f" (failure rate {self.failure_rate:.0%})"
161
+ )
162
+ lines.append("")
163
+ lines.append(f" search space ({self.locus_count} loci)")
164
+ shown = self.loci[:24]
165
+ entries = " ".join(
166
+ f"{d.locus}:{d.domain_size}(projected)" if d.declared and d.projected
167
+ else f"{d.locus}:{d.domain_size if d.declared else '?'}"
168
+ for d in shown
169
+ )
170
+ tail = f" (+{len(self.loci) - len(shown)} more)" if len(self.loci) > len(shown) else ""
171
+ for row in textwrap.wrap(entries + tail, width=74) or ["(no loci)"]:
172
+ lines.append(f" {row}")
173
+ undeclared = ", ".join(self.undeclared_loci) if self.undeclared_loci else "none"
174
+ for row in textwrap.wrap(f"undeclared domains: {undeclared}", width=74):
175
+ lines.append(f" {row}")
176
+ lines.append("")
177
+ lines.append(" probe pipeline")
178
+ lines.append(
179
+ f" failures validate {self.validate_failures}, "
180
+ f"materialize {self.materialize_failures}, "
181
+ f"evaluate {self.evaluate_failures}"
182
+ )
183
+ for message in self.failure_examples:
184
+ for row in textwrap.wrap(f"e.g. {message}", width=70):
185
+ lines.append(f" {row}")
186
+ lines.append(f" eval seconds median {self.eval_seconds_median:.6g}")
187
+ lines.append("")
188
+ lines.append(f" objective spread (over {self.evaluated} evaluations)")
189
+ if not self.spread:
190
+ lines.append(" (nothing was successfully evaluated)")
191
+ for s in self.spread:
192
+ lines.append(
193
+ f" {s.objective} ({s.goal}) min {s.minimum:g} max {s.maximum:g}"
194
+ f" mean {s.mean:g} sd {s.stdev:g}"
195
+ )
196
+ lines.append("")
197
+ lines.append(f" headroom at budget {self.budget}")
198
+ if not self.headroom:
199
+ lines.append(" (no measurements to estimate from)")
200
+ for h in self.headroom:
201
+ flag = "below noise" if h.below_noise else "ABOVE noise"
202
+ lines.append(
203
+ f" {h.objective} ({h.goal}) best of probe {h.best_of_probe:g}"
204
+ f" expected best of {self.budget} random {h.best_of_budget:g}"
205
+ f" +/- {h.noise:g} headroom {h.headroom:g} [{flag}]"
206
+ )
207
+ lines.append("")
208
+ lines.append(" verdict")
209
+ for row in textwrap.wrap(self.verdict, width=72):
210
+ lines.append(f" {row}")
211
+ return "\n".join(lines)
212
+
213
+
214
+ def _template_of(problem: Any) -> dict[str, Any]:
215
+ """The configuration whose shape defines the probe's loci.
216
+
217
+ A seed is the problem's own statement of what a candidate looks like, so it
218
+ is preferred; ``example_config`` and an all-defaults ``candidate_model``
219
+ construction are accepted in that order for problems that declare no seed.
220
+ """
221
+ seeds = tuple(problem.seeds())
222
+ if seeds:
223
+ return dict(seeds[0])
224
+ example = getattr(problem, "example_config", None)
225
+ if isinstance(example, Mapping) and example:
226
+ return dict(example)
227
+ model = getattr(problem, "candidate_model", None)
228
+ if model is not None:
229
+ try:
230
+ return dict(model().model_dump())
231
+ except Exception:
232
+ pass
233
+ raise ValueError(
234
+ "check() needs one configuration to shape the probe. Give the problem "
235
+ "a seed (Problem.seeds()), an example_config, or a candidate_model "
236
+ "whose fields all carry defaults."
237
+ )
238
+
239
+
240
+ def _best_of_budget(values: Sequence[float], budget: int, goal: str) -> tuple[float, float]:
241
+ """Mean and standard deviation of the best of *budget* uniform redraws.
242
+
243
+ This is the exact bootstrap: with the probe's values sorted so the best
244
+ under *goal* comes last, the best of ``k`` redraws lands at rank ``i`` with
245
+ probability ``(i/n)**k - ((i-1)/n)**k``. Summing over ranks gives the
246
+ distribution in closed form, so the returned noise is purely the sampling
247
+ noise of a budget-sized random run -- no Monte Carlo error rides on top.
248
+ """
249
+ n = len(values)
250
+ ordered = sorted(values, reverse=(goal == "min")) # best is last either way
251
+ mean = 0.0
252
+ second = 0.0
253
+ previous = 0.0
254
+ for rank, value in enumerate(ordered, start=1):
255
+ prefix = (rank / n) ** budget
256
+ p = prefix - previous
257
+ previous = prefix
258
+ mean += p * value
259
+ second += p * value * value
260
+ return mean, math.sqrt(max(0.0, second - mean * mean))
261
+
262
+
263
+ def _verdict(
264
+ *,
265
+ budget: int,
266
+ draws: int,
267
+ evaluated: int,
268
+ validate_failures: int,
269
+ materialize_failures: int,
270
+ evaluate_failures: int,
271
+ failure_rate: float,
272
+ headroom: Sequence[ObjectiveHeadroom],
273
+ loci: Sequence[LocusDomain],
274
+ undeclared: Sequence[str],
275
+ ) -> str:
276
+ if evaluated == 0:
277
+ base = (
278
+ f"Every one of the {draws} probe draws failed before producing a "
279
+ f"measurement (validate {validate_failures}, materialize "
280
+ f"{materialize_failures}, evaluate {evaluate_failures}). Headroom "
281
+ "cannot be assessed; fix the failures this report names before "
282
+ "spending anything on optimization."
283
+ )
284
+ return base
285
+ above = [h.objective for h in headroom if not h.below_noise]
286
+ below = [h.objective for h in headroom if h.below_noise]
287
+ if not above:
288
+ base = (
289
+ f"The best value the probe found on every objective is within "
290
+ f"noise of what {budget} random draws are expected to reach: "
291
+ f"{NO_HEADROOM_VERDICT}. Raise the budget, or reshape the search "
292
+ "space, before crediting any optimizer with a win."
293
+ )
294
+ elif not below:
295
+ base = (
296
+ f"Every objective carries headroom above noise at budget {budget}: "
297
+ f"the probe found values that {budget} random draws would "
298
+ "typically miss. That gap is what an optimizer has to close to "
299
+ "earn its cost."
300
+ )
301
+ else:
302
+ base = (
303
+ f"Headroom above noise on {', '.join(above)}; none on "
304
+ f"{', '.join(below)}. At this budget an optimizer can only "
305
+ "demonstrate an advantage on the former."
306
+ )
307
+ notes: list[str] = []
308
+ if undeclared:
309
+ named = ", ".join(list(undeclared)[:6])
310
+ more = ", ..." if len(undeclared) > 6 else ""
311
+ notes.append(
312
+ f"Note: {len(undeclared)} of {len(loci)} loci declare no finite "
313
+ f"domain ({named}{more}), so the probe could not vary them and any "
314
+ "headroom along those axes is invisible to this check."
315
+ )
316
+ if failure_rate >= 0.5:
317
+ notes.append(
318
+ f"{failure_rate:.0%} of draws failed before measurement; the "
319
+ f"estimate rests on only {evaluated} evaluations."
320
+ )
321
+ return " ".join([base, *notes])
322
+
323
+
324
+ def check(
325
+ problem: Any,
326
+ budget: int,
327
+ *,
328
+ probe: int = 120,
329
+ seed: Optional[int] = None,
330
+ ) -> CheckReport:
331
+ """Probe *problem* and report whether *budget* can show anything at all.
332
+
333
+ *budget* is the optimizer budget under assessment. The probe itself spends
334
+ at most *probe* evaluations (schema-uniform draws through the problem's own
335
+ ``validate -> materialize -> evaluate``), needs no model, no credentials
336
+ and no network, and is deterministic given *seed*.
337
+ """
338
+ if not isinstance(budget, int) or isinstance(budget, bool) or budget < 1:
339
+ raise ValueError(f"budget must be a positive integer, got {budget!r}")
340
+ if not isinstance(probe, int) or isinstance(probe, bool) or probe < 1:
341
+ raise ValueError(f"probe must be a positive integer, got {probe!r}")
342
+
343
+ name = type(problem).__name__
344
+ bound = as_problem(problem)
345
+ objectives = list(bound.objectives)
346
+ model = getattr(bound, "candidate_model", None)
347
+ template = _template_of(bound)
348
+
349
+ loci = loci_of(template)
350
+ domains = tuple(
351
+ LocusDomain(
352
+ locus=str(locus),
353
+ domain_size=len(locus_domain(model, locus)),
354
+ projected=locus_is_projected(model, locus),
355
+ )
356
+ for locus in loci
357
+ )
358
+ undeclared = tuple(d.locus for d in domains if not d.declared)
359
+
360
+ rng = random.Random(seed)
361
+ validate_failures = 0
362
+ materialize_failures = 0
363
+ evaluate_failures = 0
364
+ failure_examples: list[str] = []
365
+ eval_seconds: list[float] = []
366
+ rows: list[Mapping[str, float]] = []
367
+
368
+ def note_failure(message: str) -> None:
369
+ if message and message not in failure_examples and len(failure_examples) < 3:
370
+ failure_examples.append(message)
371
+
372
+ for _ in range(probe):
373
+ config = uniform_candidate(template, model, rng=rng)
374
+ try:
375
+ outcome = bound.validate(config)
376
+ ok = bool(getattr(outcome, "ok", outcome))
377
+ message = getattr(outcome, "message", None) or "validate() rejected the draw"
378
+ except Exception as error: # noqa: BLE001 - a diagnostic records, it does not crash
379
+ ok, message = False, f"validate raised {type(error).__name__}: {error}"
380
+ if not ok:
381
+ validate_failures += 1
382
+ note_failure(f"validate: {message}")
383
+ continue
384
+ try:
385
+ artifact = bound.materialize(config)
386
+ except Exception as error: # noqa: BLE001
387
+ materialize_failures += 1
388
+ note_failure(f"materialize raised {type(error).__name__}: {error}")
389
+ continue
390
+ started = time.perf_counter()
391
+ try:
392
+ values = bound.evaluate(artifact)
393
+ elapsed = time.perf_counter() - started
394
+ rows.append(normalize_objective_values(values, objectives))
395
+ except Exception as error: # noqa: BLE001
396
+ evaluate_failures += 1
397
+ note_failure(f"evaluate raised {type(error).__name__}: {error}")
398
+ continue
399
+ eval_seconds.append(elapsed)
400
+
401
+ draws = probe
402
+ evaluated = len(rows)
403
+ failures = validate_failures + materialize_failures + evaluate_failures
404
+ failure_rate = failures / draws if draws else 0.0
405
+
406
+ spread: list[ObjectiveSpread] = []
407
+ headroom: list[ObjectiveHeadroom] = []
408
+ for spec in objectives:
409
+ values = [row[spec.name] for row in rows]
410
+ if not values:
411
+ continue
412
+ spread.append(
413
+ ObjectiveSpread(
414
+ objective=spec.name,
415
+ goal=spec.goal,
416
+ count=len(values),
417
+ minimum=min(values),
418
+ maximum=max(values),
419
+ mean=statistics.fmean(values),
420
+ stdev=statistics.pstdev(values),
421
+ )
422
+ )
423
+ best_of_probe = max(values) if spec.goal == "max" else min(values)
424
+ expected, noise = _best_of_budget(values, budget, spec.goal)
425
+ gap = (best_of_probe - expected) if spec.goal == "max" else (expected - best_of_probe)
426
+ gap = max(0.0, gap)
427
+ headroom.append(
428
+ ObjectiveHeadroom(
429
+ objective=spec.name,
430
+ goal=spec.goal,
431
+ best_of_probe=best_of_probe,
432
+ best_of_budget=expected,
433
+ noise=noise,
434
+ headroom=gap,
435
+ below_noise=gap <= noise,
436
+ )
437
+ )
438
+
439
+ verdict = _verdict(
440
+ budget=budget,
441
+ draws=draws,
442
+ evaluated=evaluated,
443
+ validate_failures=validate_failures,
444
+ materialize_failures=materialize_failures,
445
+ evaluate_failures=evaluate_failures,
446
+ failure_rate=failure_rate,
447
+ headroom=headroom,
448
+ loci=domains,
449
+ undeclared=undeclared,
450
+ )
451
+
452
+ return CheckReport(
453
+ problem=name,
454
+ budget=budget,
455
+ probe=probe,
456
+ draws=draws,
457
+ evaluated=evaluated,
458
+ loci=domains,
459
+ undeclared_loci=undeclared,
460
+ validate_failures=validate_failures,
461
+ materialize_failures=materialize_failures,
462
+ evaluate_failures=evaluate_failures,
463
+ failure_rate=failure_rate,
464
+ failure_examples=tuple(failure_examples),
465
+ eval_seconds_median=statistics.median(eval_seconds) if eval_seconds else 0.0,
466
+ spread=tuple(spread),
467
+ headroom=tuple(headroom),
468
+ verdict=verdict,
469
+ )