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,363 @@
1
+ """Composition portfolio selection: span the proposal sources, choose within at random.
2
+
3
+ This is a *product* policy, not an experiment arm. It replaces the calibrated
4
+ score, the tie-break cascade and the forecast channel with one rule:
5
+
6
+ spend the budget so that it spans the proposal sources, and pick uniformly
7
+ inside each source.
8
+
9
+ The evidence for that rule, in one line: enforcing the family composition the
10
+ allocator was already under captures 0.801 of a clairvoyant oracle while the
11
+ model's own top-k captures 0.748, measured over 36 waves with every 4-subset of
12
+ 8 enumerated exactly; and the two proposal sources are complementary in kind --
13
+ the model supplies hit rate, the numerical engine supplies the rare large hit
14
+ that carries a heavy-tailed total. What makes a slate good is that it spans the
15
+ sources, not that it is ordered well within them.
16
+
17
+ Two properties this policy deliberately has
18
+ -------------------------------------------
19
+ **It makes no provider call.** Selection is arithmetic over the sealed finite
20
+ contract. A campaign running this policy spends model budget on *generation*
21
+ only.
22
+
23
+ **Its composition is derived, never hard-coded.** Baking in the family mix
24
+ observed on five research domains would ship a constant fitted to those domains
25
+ and call it general. Instead the caller injects
26
+ :class:`CompositionObservationSource`, which supplies realized family shares
27
+ from prior sealed campaigns; the policy apportions the budget to those shares by
28
+ largest remainder. With no observations it falls back to *spanning*, which has
29
+ no parameters at all: one seat per distinct family before any family repeats.
30
+ Replay evidence that this transfers rather than overfits: proportions estimated
31
+ leave-one-market-out scored 0.22815 against 0.23202 for proportions taken from
32
+ the market's own realized multiset.
33
+
34
+ Determinism
35
+ -----------
36
+ "Uniform within" is drawn from a generator seeded by the request's own identity
37
+ (the finite contract identity and the call id), so a decision is reproducible
38
+ from receipts and two runs of the same campaign make the same choice. The
39
+ policy is a pure function of its inputs; it holds no mutable state.
40
+ """
41
+
42
+ from __future__ import annotations
43
+
44
+ import hashlib
45
+ import random
46
+ from dataclasses import dataclass
47
+ from typing import Protocol, runtime_checkable
48
+
49
+ from agent_evolve.domain.finite_variation import FiniteVariationOption
50
+ from agent_evolve.ports.agentic_generator import (
51
+ MetricEffectDirection,
52
+ MetricEffectPrediction,
53
+ )
54
+ from agent_evolve.ports.portfolio_selection import (
55
+ PortfolioMemberDraft,
56
+ PortfolioSelectionRequest,
57
+ PortfolioSelectionResult,
58
+ pairwise_disjoint_parent_patch_witness,
59
+ resolve_ranked_portfolio_decision,
60
+ )
61
+
62
+ COMPOSITION_PORTFOLIO_POLICY_ID = "composition_spanning_portfolio"
63
+ COMPOSITION_PORTFOLIO_POLICY_VERSION = 1
64
+
65
+ # The identity a receipt pins. It covers the rule, not the observations: the
66
+ # same policy fed different receipt-derived shares is the same policy.
67
+ COMPOSITION_PORTFOLIO_POLICY_DEFINITION_SHA256 = hashlib.sha256(
68
+ b"agent-evolve:composition-spanning-portfolio:v1\x00"
69
+ b"rule=span-sources-then-uniform-within;"
70
+ b"apportionment=largest-remainder;"
71
+ b"shares=injected-observations-or-uniform-spanning;"
72
+ b"provider-calls=0"
73
+ ).hexdigest()
74
+
75
+
76
+ @runtime_checkable
77
+ class CompositionObservationSource(Protocol):
78
+ """Realized family shares observed in prior sealed campaigns.
79
+
80
+ The contract is deliberately minimal: a mapping from family token to a
81
+ non-negative weight. Weights need not sum to one; only their ratios matter.
82
+ An empty mapping means "no observations", and the policy falls back to
83
+ parameter-free spanning rather than inventing a mix.
84
+ """
85
+
86
+ def family_shares(self) -> dict[str, float]: ...
87
+
88
+
89
+ @dataclass(frozen=True, slots=True)
90
+ class FrozenCompositionObservations:
91
+ """A concrete observation source, e.g. built leave-one-campaign-out."""
92
+
93
+ shares: tuple[tuple[str, float], ...] = ()
94
+
95
+ def __post_init__(self) -> None:
96
+ if type(self.shares) is not tuple:
97
+ raise TypeError("shares must be an exact tuple")
98
+ seen = set()
99
+ for entry in self.shares:
100
+ if type(entry) is not tuple or len(entry) != 2:
101
+ raise TypeError("each share must be an exact (family, weight) pair")
102
+ family, weight = entry
103
+ if type(family) is not str or not family:
104
+ raise ValueError("family must be non-empty text")
105
+ if type(weight) is not float or weight < 0.0 or weight != weight:
106
+ raise ValueError("weight must be a non-negative finite float")
107
+ if family in seen:
108
+ raise ValueError("shares repeat a family")
109
+ seen.add(family)
110
+
111
+ def family_shares(self) -> dict[str, float]:
112
+ return {family: weight for family, weight in self.shares}
113
+
114
+
115
+ def _seat_apportionment(
116
+ families: list[str],
117
+ shares: dict[str, float],
118
+ budget: int,
119
+ capacity: dict[str, int],
120
+ ) -> dict[str, int]:
121
+ """Largest-remainder apportionment of `budget` seats over `families`.
122
+
123
+ Deterministic given the inputs. Never assigns a family more seats than it
124
+ has options, and never leaves the budget unfilled while capacity remains.
125
+ """
126
+
127
+ weights = {f: max(float(shares.get(f, 0.0)), 0.0) for f in families}
128
+ total = sum(weights.values())
129
+ if total <= 0.0:
130
+ # no usable observations: spanning, i.e. every family weighted alike
131
+ weights = {f: 1.0 for f in families}
132
+ total = float(len(families))
133
+
134
+ quota = {f: budget * weights[f] / total for f in families}
135
+ seats = {f: min(int(quota[f]), capacity[f]) for f in families}
136
+
137
+ # distribute the remainder by largest fractional part, then by family token
138
+ # so the result cannot depend on dict ordering
139
+ while sum(seats.values()) < budget:
140
+ eligible = [f for f in families if seats[f] < capacity[f]]
141
+ if not eligible:
142
+ break
143
+ eligible.sort(key=lambda f: (-(quota[f] - seats[f]), f))
144
+ seats[eligible[0]] += 1
145
+ return seats
146
+
147
+
148
+ def _spanning_order(
149
+ families: list[str],
150
+ capacity: dict[str, int],
151
+ budget: int,
152
+ rng: random.Random,
153
+ ) -> dict[str, int]:
154
+ """One seat per distinct family before any family repeats. No parameters."""
155
+
156
+ order = sorted(families)
157
+ rng.shuffle(order)
158
+ seats = {f: 0 for f in families}
159
+ while sum(seats.values()) < budget:
160
+ progressed = False
161
+ for family in order:
162
+ if sum(seats.values()) >= budget:
163
+ break
164
+ if seats[family] < capacity[family]:
165
+ seats[family] += 1
166
+ progressed = True
167
+ if not progressed:
168
+ break
169
+ return seats
170
+
171
+
172
+ def _declined_predictions(
173
+ metric_ids: tuple[str, ...],
174
+ ) -> tuple[MetricEffectPrediction, ...]:
175
+ """An explicit non-forecast for every metric the port requires.
176
+
177
+ The port's schema mandates a prediction per required metric. This policy has
178
+ no forecast channel, so it declines rather than inventing a direction:
179
+ every prediction is UNKNOWN. That is deliberate and is what makes the
180
+ absence of a forecast channel visible in the receipt instead of hidden.
181
+ """
182
+
183
+ return tuple(
184
+ MetricEffectPrediction(
185
+ metric_id=metric_id,
186
+ direction=MetricEffectDirection.UNKNOWN,
187
+ )
188
+ for metric_id in metric_ids
189
+ )
190
+
191
+
192
+ @dataclass(frozen=True, slots=True)
193
+ class CompositionPortfolioSelectionPolicy:
194
+ """Span the proposal sources; choose uniformly within them.
195
+
196
+ ``observations`` is optional. Supplied, the budget is apportioned to the
197
+ observed family shares; omitted, the policy spans families evenly, which is
198
+ parameter-free.
199
+ """
200
+
201
+ observations: CompositionObservationSource | None = None
202
+
203
+ def _rng(self, request: PortfolioSelectionRequest) -> random.Random:
204
+ seed = hashlib.sha256(
205
+ b"agent-evolve:composition-portfolio-draw:v1\x00"
206
+ + request.finite_variation_contract.identity_sha256.encode("ascii")
207
+ + b"\x00"
208
+ + request.call_id.value.encode("ascii")
209
+ ).digest()
210
+ return random.Random(int.from_bytes(seed[:16], "big"))
211
+
212
+ def _choose(
213
+ self, request: PortfolioSelectionRequest
214
+ ) -> tuple[FiniteVariationOption, ...]:
215
+ contract = request.finite_variation_contract
216
+ budget = request.portfolio_size
217
+ rng = self._rng(request)
218
+
219
+ by_family: dict[str, list[FiniteVariationOption]] = {}
220
+ for option in contract.options:
221
+ by_family.setdefault(option.family, []).append(option)
222
+ for options in by_family.values():
223
+ options.sort(key=lambda o: o.option_id)
224
+ families = sorted(by_family)
225
+ capacity = {f: len(by_family[f]) for f in families}
226
+
227
+ chosen: list[FiniteVariationOption] = []
228
+ taken: set[str] = set()
229
+
230
+ # options the engine requires in the pool are honoured first: the
231
+ # policy adds composition, it does not override a hard constraint
232
+ required = set(request.candidate_pool_required_option_ids)
233
+ for option in contract.options:
234
+ if option.option_id in required and len(chosen) < budget:
235
+ chosen.append(option)
236
+ taken.add(option.option_id)
237
+
238
+ remaining = budget - len(chosen)
239
+ if remaining > 0:
240
+ free_capacity = {
241
+ f: sum(1 for o in by_family[f] if o.option_id not in taken)
242
+ for f in families
243
+ }
244
+ shares = self.observations.family_shares() if self.observations else {}
245
+ usable = {f: w for f, w in shares.items() if f in free_capacity}
246
+ if usable and sum(usable.values()) > 0.0:
247
+ seats = _seat_apportionment(
248
+ families, usable, remaining, free_capacity
249
+ )
250
+ else:
251
+ seats = _spanning_order(families, free_capacity, remaining, rng)
252
+
253
+ for family in sorted(families):
254
+ pool = [o for o in by_family[family] if o.option_id not in taken]
255
+ take = min(seats.get(family, 0), len(pool))
256
+ if take <= 0:
257
+ continue
258
+ for option in rng.sample(pool, take):
259
+ chosen.append(option)
260
+ taken.add(option.option_id)
261
+
262
+ # top up if apportionment could not fill the budget (small catalogs)
263
+ if len(chosen) < budget:
264
+ pool = [o for o in contract.options if o.option_id not in taken]
265
+ rng.shuffle(pool)
266
+ for option in pool[: budget - len(chosen)]:
267
+ chosen.append(option)
268
+ taken.add(option.option_id)
269
+
270
+ if len(chosen) != budget:
271
+ raise ValueError(
272
+ "composition policy could not fill the portfolio from the contract"
273
+ )
274
+
275
+ if request.require_pairwise_disjoint_parent_patches:
276
+ chosen = self._project_to_legal(request, chosen)
277
+ return tuple(chosen)
278
+
279
+ @staticmethod
280
+ def _project_to_legal(
281
+ request: PortfolioSelectionRequest,
282
+ chosen: list[FiniteVariationOption],
283
+ ) -> list[FiniteVariationOption]:
284
+ """Restrict the slate to one the port will accept.
285
+
286
+ LEGALITY ONLY. The witness is the port's own feasibility search over the
287
+ sealed parent-relative patches; the port documents it as a structural
288
+ decoding aid that "proves how to satisfy the hard combinatorial contract
289
+ without ranking an option by objective quality". The composition order
290
+ is handed to it as ``preferred_option_ids``, so the projection keeps as
291
+ much of the composition as legality allows and changes nothing else.
292
+
293
+ This is not a quality heuristic and must never become one: the deployed
294
+ allocator is already subject to this same rule, and adding anything that
295
+ also picks better would change the treatment.
296
+ """
297
+
298
+ contract = request.finite_variation_contract
299
+ witness = pairwise_disjoint_parent_patch_witness(
300
+ contract,
301
+ tuple(option.option_id for option in contract.options),
302
+ portfolio_size=request.portfolio_size,
303
+ min_distinct_families=request.min_distinct_families,
304
+ preferred_option_ids=tuple(option.option_id for option in chosen),
305
+ required_option_ids=tuple(request.candidate_pool_required_option_ids),
306
+ )
307
+ if witness is None:
308
+ raise ValueError(
309
+ "the finite contract admits no pairwise-disjoint portfolio of "
310
+ "the requested size"
311
+ )
312
+ by_id = {option.option_id: option for option in contract.options}
313
+ return [by_id[option_id] for option_id in witness]
314
+
315
+ async def select(
316
+ self, request: PortfolioSelectionRequest
317
+ ) -> PortfolioSelectionResult:
318
+ if type(request) is not PortfolioSelectionRequest:
319
+ raise TypeError("request must be an exact PortfolioSelectionRequest")
320
+ request.__post_init__()
321
+
322
+ options = self._choose(request)
323
+ card_keys = tuple(sorted({card.card_key for card in request.cards}))
324
+ supporting = card_keys[:1] if request.require_supporting_cards else ()
325
+
326
+ drafts = tuple(
327
+ PortfolioMemberDraft(
328
+ option_id=option.option_id,
329
+ supporting_card_keys=supporting,
330
+ effect_predictions=_declined_predictions(
331
+ request.required_metric_ids
332
+ ),
333
+ design_rationale=(
334
+ "composition policy: seat apportioned to proposal source "
335
+ f"{option.family!r}, member drawn uniformly within it; no "
336
+ "score, no tie-break, no forecast"
337
+ ),
338
+ )
339
+ for option in options
340
+ )
341
+ decision = resolve_ranked_portfolio_decision(
342
+ request,
343
+ drafts,
344
+ policy_id=COMPOSITION_PORTFOLIO_POLICY_ID,
345
+ policy_version=COMPOSITION_PORTFOLIO_POLICY_VERSION,
346
+ policy_definition_sha256=COMPOSITION_PORTFOLIO_POLICY_DEFINITION_SHA256,
347
+ )
348
+ # provider_free is asserted, not left to be inferred from a missing
349
+ # telemetry field. The runtime verifies the assertion against the
350
+ # outbound journals and fails the wave if any call was observed.
351
+ return PortfolioSelectionResult(
352
+ decision=decision, telemetry=None, provider_free=True
353
+ )
354
+
355
+
356
+ __all__ = [
357
+ "COMPOSITION_PORTFOLIO_POLICY_DEFINITION_SHA256",
358
+ "COMPOSITION_PORTFOLIO_POLICY_ID",
359
+ "COMPOSITION_PORTFOLIO_POLICY_VERSION",
360
+ "CompositionObservationSource",
361
+ "CompositionPortfolioSelectionPolicy",
362
+ "FrozenCompositionObservations",
363
+ ]
@@ -0,0 +1,144 @@
1
+ """Failure-contained execution for one concurrent application stage.
2
+
3
+ ``asyncio.gather`` propagates the first child failure without cancelling the
4
+ remaining children. That behavior is unsafe at an application-stage
5
+ boundary: a failed model arm can leave sibling provider calls running after
6
+ the campaign has started finalization. This module owns the generic policy
7
+ for fail-fast sibling cancellation and bounded terminal-state retrieval.
8
+
9
+ The helper is deliberately workload- and transport-neutral. Child
10
+ coroutines remain responsible for retiring resources they own when cancelled;
11
+ the barrier guarantees that cancellation is delivered and that every child
12
+ which reaches a terminal state is observed before the stage exception exits.
13
+ Cancellation-resistant children are observed by a terminal callback after the
14
+ bounded drain interval, so their later exception can never become an
15
+ unretrieved task exception.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import asyncio
21
+ from collections.abc import Awaitable, Iterable
22
+ from contextlib import suppress
23
+ from typing import TypeVar
24
+
25
+
26
+ StageResultT = TypeVar("StageResultT")
27
+
28
+ NANOSECONDS_PER_SECOND = 1_000_000_000
29
+ DEFAULT_CONCURRENT_STAGE_CANCEL_DRAIN_TIMEOUT_NS = 5 * NANOSECONDS_PER_SECOND
30
+
31
+
32
+ def _consume_terminal(task: "asyncio.Future[object]") -> None:
33
+ """Retrieve a terminal child's exception without retaining its content."""
34
+
35
+ if not task.done(): # pragma: no cover - callback/validated caller contract.
36
+ return
37
+ with suppress(BaseException):
38
+ task.exception()
39
+
40
+
41
+ async def _cancel_and_drain(
42
+ tasks: tuple["asyncio.Future[object]", ...],
43
+ *,
44
+ timeout_ns: int,
45
+ ) -> None:
46
+ """Cancel live children and observe them for at most ``timeout_ns``."""
47
+
48
+ for task in tasks:
49
+ if not task.done():
50
+ task.cancel()
51
+ if not tasks:
52
+ return
53
+ done, pending = await asyncio.wait(
54
+ tasks,
55
+ timeout=timeout_ns / NANOSECONDS_PER_SECOND,
56
+ return_when=asyncio.ALL_COMPLETED,
57
+ )
58
+ for task in done:
59
+ _consume_terminal(task)
60
+ for task in pending:
61
+ # A transport stack can resist cancellation while it retires a socket.
62
+ # Do not let that defeat the campaign cleanup bound, but retain explicit
63
+ # ownership of its eventual terminal state.
64
+ task.add_done_callback(_consume_terminal)
65
+
66
+
67
+ async def gather_concurrent_stage(
68
+ awaitables: Iterable[Awaitable[StageResultT]],
69
+ *,
70
+ cancel_drain_timeout_ns: int = (
71
+ DEFAULT_CONCURRENT_STAGE_CANCEL_DRAIN_TIMEOUT_NS
72
+ ),
73
+ ) -> tuple[StageResultT, ...]:
74
+ """Return ordered results or fail after cancelling and draining siblings.
75
+
76
+ Success preserves input ordering. On the first observed child failure,
77
+ every still-live sibling is cancelled and terminal states are retrieved
78
+ before that failure is re-raised. Drain time is bounded because provider
79
+ cancellation must never hold campaign finalization hostage indefinitely.
80
+
81
+ If the caller itself is cancelled, the same cancel-and-drain law is applied
82
+ before ``CancelledError`` propagates.
83
+ """
84
+
85
+ if (
86
+ type(cancel_drain_timeout_ns) is not int
87
+ or cancel_drain_timeout_ns <= 0
88
+ ):
89
+ raise ValueError("cancel_drain_timeout_ns must be a positive exact integer")
90
+ tasks = tuple(asyncio.ensure_future(awaitable) for awaitable in awaitables)
91
+ if not tasks:
92
+ return ()
93
+
94
+ pending = set(tasks)
95
+ try:
96
+ while pending:
97
+ done, pending = await asyncio.wait(
98
+ pending,
99
+ return_when=asyncio.FIRST_COMPLETED,
100
+ )
101
+ failed = tuple(
102
+ task
103
+ for task in tasks
104
+ if task in done
105
+ and (
106
+ task.cancelled()
107
+ or task.exception() is not None
108
+ )
109
+ )
110
+ if not failed:
111
+ continue
112
+
113
+ primary = failed[0]
114
+ primary_error: BaseException
115
+ if primary.cancelled():
116
+ primary_error = asyncio.CancelledError()
117
+ else:
118
+ observed = primary.exception()
119
+ assert observed is not None
120
+ primary_error = observed
121
+
122
+ # Retrieve every failure that completed in the same event-loop
123
+ # turn, not only the deterministic first one.
124
+ for task in done:
125
+ _consume_terminal(task)
126
+ await _cancel_and_drain(
127
+ tuple(task for task in tasks if task not in done),
128
+ timeout_ns=cancel_drain_timeout_ns,
129
+ )
130
+ raise primary_error
131
+ except asyncio.CancelledError:
132
+ await _cancel_and_drain(
133
+ tasks,
134
+ timeout_ns=cancel_drain_timeout_ns,
135
+ )
136
+ raise
137
+
138
+ return tuple(task.result() for task in tasks)
139
+
140
+
141
+ __all__ = [
142
+ "DEFAULT_CONCURRENT_STAGE_CANCEL_DRAIN_TIMEOUT_NS",
143
+ "gather_concurrent_stage",
144
+ ]
@@ -0,0 +1,181 @@
1
+ """Lower prior-only contextual decisions into generic allocator constraints.
2
+
3
+ This bridge deliberately knows only the sealed finite variation contract and
4
+ the generic source/operator attribution ports. It is the single seam between
5
+ the adaptive search controller and any trusted action allocator; no workload,
6
+ model, provider, prompt, or objective branch is permitted here.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from agent_evolve.application.action_structural_signature import (
12
+ parent_relative_changed_paths_by_option,
13
+ )
14
+ from agent_evolve.domain.finite_variation import FiniteVariationContract
15
+ from agent_evolve.ports.action_allocation import ExactActionArmCountConstraint
16
+ from agent_evolve.ports.portfolio_selection import (
17
+ pairwise_disjoint_parent_patch_pairs,
18
+ )
19
+ from agent_evolve.ports.contextual_search_allocation import (
20
+ ContextualPortfolioAllocationContract,
21
+ ContextualPortfolioAllocationRealization,
22
+ )
23
+ from agent_evolve.ports.variation_source import (
24
+ finite_variation_operator_id,
25
+ finite_variation_source_id,
26
+ )
27
+
28
+
29
+ def contextual_action_arm_count_constraints(
30
+ *,
31
+ finite_contract: FiniteVariationContract,
32
+ allocation: ContextualPortfolioAllocationContract | None,
33
+ portfolio_size: int,
34
+ ) -> tuple[ExactActionArmCountConstraint, ...]:
35
+ """Return exact source/operator marginals for one finite action request."""
36
+
37
+ if type(finite_contract) is not FiniteVariationContract:
38
+ raise TypeError("finite_contract must be an exact FiniteVariationContract")
39
+ finite_contract.__post_init__()
40
+ if type(portfolio_size) is not int or portfolio_size <= 0:
41
+ raise ValueError("portfolio_size must be a positive exact integer")
42
+ if allocation is None:
43
+ return ()
44
+ if type(allocation) is not ContextualPortfolioAllocationContract:
45
+ raise TypeError("allocation must be an exact contextual contract or None")
46
+ allocation.__post_init__()
47
+ if allocation.evaluation_slots != portfolio_size:
48
+ raise ValueError("contextual allocation differs from portfolio capacity")
49
+
50
+ source_rows = tuple(
51
+ sorted(
52
+ (option.option_id, finite_variation_source_id(option))
53
+ for option in finite_contract.options
54
+ )
55
+ )
56
+ operator_rows = tuple(
57
+ sorted(
58
+ (option.option_id, finite_variation_operator_id(option))
59
+ for option in finite_contract.options
60
+ )
61
+ )
62
+ constraints = (
63
+ ExactActionArmCountConstraint(
64
+ constraint_id="operator",
65
+ option_arm_ids=operator_rows,
66
+ target_counts=allocation.operator_target_counts,
67
+ ),
68
+ ExactActionArmCountConstraint(
69
+ constraint_id="source",
70
+ option_arm_ids=source_rows,
71
+ target_counts=allocation.source_target_counts,
72
+ ),
73
+ )
74
+ return tuple(sorted(constraints, key=lambda value: value.constraint_id))
75
+
76
+
77
+ def contextual_allocation_realization(
78
+ *,
79
+ finite_contract: FiniteVariationContract,
80
+ allocation: ContextualPortfolioAllocationContract | None,
81
+ selected_option_ids: tuple[str, ...],
82
+ ) -> ContextualPortfolioAllocationRealization | None:
83
+ """Project selected sealed actions into objective-blind controller credit."""
84
+
85
+ if type(finite_contract) is not FiniteVariationContract:
86
+ raise TypeError("finite_contract must be an exact FiniteVariationContract")
87
+ finite_contract.__post_init__()
88
+ if allocation is None:
89
+ return None
90
+ if type(allocation) is not ContextualPortfolioAllocationContract:
91
+ raise TypeError("allocation must be an exact contextual contract or None")
92
+ allocation.__post_init__()
93
+ if (
94
+ type(selected_option_ids) is not tuple
95
+ or len(selected_option_ids) != allocation.evaluation_slots
96
+ or selected_option_ids != tuple(dict.fromkeys(selected_option_ids))
97
+ ):
98
+ raise ValueError("selected_option_ids must be an exact unique K-tuple")
99
+ by_id = {value.option_id: value for value in finite_contract.options}
100
+ if not set(selected_option_ids).issubset(by_id):
101
+ raise ValueError("selected option escapes the finite variation contract")
102
+
103
+ def realized(
104
+ target: tuple[tuple[str, int], ...],
105
+ projector,
106
+ ) -> tuple[tuple[str, int], ...]:
107
+ counts = {arm_id: 0 for arm_id, _ in target}
108
+ for option_id in selected_option_ids:
109
+ arm_id = projector(by_id[option_id])
110
+ if arm_id not in counts:
111
+ raise ValueError("selected option carries an unrequested arm")
112
+ counts[arm_id] += 1
113
+ return tuple(sorted(counts.items()))
114
+
115
+ receipt = ContextualPortfolioAllocationRealization(
116
+ campaign_scope_sha256=allocation.campaign_scope_sha256,
117
+ query_sha256=allocation.query_sha256,
118
+ decision_sha256=allocation.decision_sha256,
119
+ contract_sha256=allocation.contract_sha256,
120
+ controller_wave_index=allocation.controller_wave_index,
121
+ slice_id=allocation.slice_id,
122
+ requested_source_target_counts=allocation.source_target_counts,
123
+ requested_operator_target_counts=allocation.operator_target_counts,
124
+ realized_source_target_counts=realized(
125
+ allocation.source_target_counts,
126
+ finite_variation_source_id,
127
+ ),
128
+ realized_operator_target_counts=realized(
129
+ allocation.operator_target_counts,
130
+ finite_variation_operator_id,
131
+ ),
132
+ requested_minimum_single_path_interventions=(
133
+ allocation.minimum_single_path_interventions
134
+ ),
135
+ realized_single_path_interventions=sum(
136
+ len(paths) == 1
137
+ for option_id, paths in parent_relative_changed_paths_by_option(
138
+ finite_contract
139
+ ).items()
140
+ if option_id in selected_option_ids
141
+ ),
142
+ requested_minimum_disjoint_parent_patch_pairs=(
143
+ allocation.minimum_disjoint_parent_patch_pairs
144
+ ),
145
+ realized_disjoint_parent_patch_pairs=len(
146
+ pairwise_disjoint_parent_patch_pairs(
147
+ finite_contract,
148
+ selected_option_ids,
149
+ )
150
+ ),
151
+ )
152
+ receipt.require_contract(allocation)
153
+ return receipt
154
+
155
+
156
+ def selected_variation_source_ids(
157
+ *,
158
+ finite_contract: FiniteVariationContract,
159
+ selected_option_ids: tuple[str, ...],
160
+ ) -> tuple[str, ...]:
161
+ """Return sealed proposal-source labels in evaluated member order."""
162
+
163
+ if type(finite_contract) is not FiniteVariationContract:
164
+ raise TypeError("finite_contract must be an exact FiniteVariationContract")
165
+ finite_contract.__post_init__()
166
+ if type(selected_option_ids) is not tuple:
167
+ raise TypeError("selected_option_ids must be an exact tuple")
168
+ by_id = {value.option_id: value for value in finite_contract.options}
169
+ if not set(selected_option_ids).issubset(by_id):
170
+ raise ValueError("selected option escapes the finite variation contract")
171
+ return tuple(
172
+ finite_variation_source_id(by_id[option_id])
173
+ for option_id in selected_option_ids
174
+ )
175
+
176
+
177
+ __all__ = [
178
+ "contextual_action_arm_count_constraints",
179
+ "contextual_allocation_realization",
180
+ "selected_variation_source_ids",
181
+ ]