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,385 @@
1
+ """Opportunity-aware routing over frozen residual portfolio continuations.
2
+
3
+ The existing portfolio-race gate estimates which precommitted completion best
4
+ matches the observed pilot lanes. This decorator adds a separate question:
5
+ did the pilot expose enough absolute opportunity to keep spending on the
6
+ current market at all?
7
+
8
+ All candidate branches still exist before current outcomes are observed. A
9
+ weak pilot can therefore hand off only to a pre-generated renewal branch; it
10
+ cannot trigger an unlogged provider call or outcome-conditioned candidate
11
+ construction. Later campaign stages may use the resulting authenticated
12
+ evidence to open a fresh proposal market through the ordinary expert ports.
13
+
14
+ The policy is workload-, objective-, model-, provider-, prompt-, and
15
+ configuration-blind. Its absolute gain reference must be bound to an
16
+ authenticated prior-evidence digest so that a caller cannot silently tune the
17
+ threshold after seeing the current pilot.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import hashlib
23
+ import json
24
+ import math
25
+ import re
26
+ from dataclasses import dataclass, field
27
+
28
+ from agent_evolve.application.precommitted_portfolio_racing import (
29
+ EvidenceAdaptivePortfolioRaceGate,
30
+ PortfolioRaceGateDecision,
31
+ PrecommittedPortfolioRacePlan,
32
+ )
33
+ from agent_evolve.application.sequential_lineage_allocation import (
34
+ SequentialAllocationGateDecisionPort,
35
+ SequentialAllocationPlanPort,
36
+ SequentialPilotOutcomeBatch,
37
+ )
38
+ from agent_evolve.domain.patch import require_sha256
39
+ from agent_evolve.domain.typed_json import freeze_json, thaw_json
40
+
41
+
42
+ CAUSAL_OPPORTUNITY_PORTFOLIO_GATE_ID = (
43
+ "causal_opportunity_portfolio_race_gate"
44
+ )
45
+ CAUSAL_OPPORTUNITY_PORTFOLIO_GATE_VERSION = 2
46
+
47
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
48
+ _DEFINITION_DOMAIN = (
49
+ b"agent-evolve:causal-opportunity-portfolio-race-gate:v2\x00"
50
+ )
51
+
52
+
53
+ def _canonical_json(value: object) -> bytes:
54
+ return json.dumps(
55
+ value,
56
+ allow_nan=False,
57
+ ensure_ascii=True,
58
+ separators=(",", ":"),
59
+ sort_keys=True,
60
+ ).encode("ascii", errors="strict")
61
+
62
+
63
+ def _hash(domain: bytes, value: object) -> str:
64
+ return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
65
+
66
+
67
+ def _require_token(value: str, *, name: str) -> None:
68
+ if type(value) is not str or _TOKEN.fullmatch(value) is None:
69
+ raise ValueError(f"{name} must use the closed token grammar")
70
+
71
+
72
+ def _resolve_frozen_route(
73
+ plan: PrecommittedPortfolioRacePlan,
74
+ requested_branch_id: str,
75
+ ) -> tuple[str, tuple[str, ...]]:
76
+ """Resolve a configured source branch to its frozen equivalent.
77
+
78
+ A disagreement planner may outcome-blindly collapse source branches that
79
+ produce the same complete action slate, either before or after the common
80
+ pilot is inserted. The planner authenticates that exact equivalence in
81
+ ``outcome_blind_route_resolution``. The gate may consume that proof, but
82
+ it must never guess a substitute for a non-equivalent missing route.
83
+ """
84
+
85
+ _require_token(requested_branch_id, name="requested_branch_id")
86
+ if requested_branch_id in plan.frozen_branch_ids:
87
+ return requested_branch_id, ("identity",)
88
+ raw_plan_evidence = thaw_json(plan.evidence)
89
+ if type(raw_plan_evidence) is not dict:
90
+ raise TypeError("portfolio plan evidence must have an object root")
91
+ raw_design = raw_plan_evidence.get("disagreement_design")
92
+ if type(raw_design) is not dict:
93
+ raise ValueError(
94
+ "configured route is absent and the plan has no disagreement proof"
95
+ )
96
+ raw_design_evidence = raw_design.get("evidence")
97
+ if type(raw_design_evidence) is not dict:
98
+ raise ValueError(
99
+ "configured route is absent and disagreement evidence is missing"
100
+ )
101
+ raw_rows = raw_design_evidence.get(
102
+ "outcome_blind_route_resolution"
103
+ )
104
+ if type(raw_rows) is not list:
105
+ raise ValueError(
106
+ "configured route is absent and has no authenticated resolution"
107
+ )
108
+ matches = tuple(
109
+ value
110
+ for value in raw_rows
111
+ if type(value) is dict
112
+ and value.get("source_branch_id") == requested_branch_id
113
+ )
114
+ if len(matches) != 1:
115
+ raise ValueError(
116
+ "configured route lacks one unambiguous authenticated resolution"
117
+ )
118
+ row = matches[0]
119
+ representative = row.get("representative_branch_id")
120
+ raw_path = row.get("equivalence_path")
121
+ if type(representative) is not str:
122
+ raise TypeError("resolved representative_branch_id must be a string")
123
+ _require_token(representative, name="representative_branch_id")
124
+ if (
125
+ type(raw_path) is not list
126
+ or not raw_path
127
+ or any(type(value) is not str for value in raw_path)
128
+ ):
129
+ raise ValueError("route resolution needs an equivalence proof path")
130
+ path = tuple(raw_path)
131
+ allowed = {
132
+ "identity",
133
+ "identical_complete_action_set_before_pilot",
134
+ "identical_complete_action_set_after_frozen_pilot",
135
+ }
136
+ if any(value not in allowed for value in path):
137
+ raise ValueError("route resolution uses an unknown equivalence proof")
138
+ if representative not in plan.frozen_branch_ids:
139
+ raise ValueError(
140
+ "authenticated route representative is absent from the frozen plan"
141
+ )
142
+ return representative, path
143
+
144
+
145
+ @dataclass(frozen=True, slots=True)
146
+ class CausalOpportunityPortfolioRaceGate:
147
+ """Route weak, sparse, and productive pilots to frozen continuations.
148
+
149
+ ``reference_gain_scale`` is a robust positive-gain scale derived only from
150
+ strictly prior authenticated outcomes. ``minimum_peak_gain_ratio`` tests
151
+ whether the best pilot clears a declared fraction of that scale.
152
+ ``minimum_positive_fraction`` separates a sparse market from a productive
153
+ one after the absolute opportunity check passes.
154
+
155
+ The productive route delegates to the existing lane-aware race gate. The
156
+ weak and sparse routes select explicit precommitted branch IDs. This
157
+ separation is intentional: opportunity detection and within-market
158
+ conversion are different control problems.
159
+ """
160
+
161
+ renewal_branch_id: str
162
+ exploration_branch_id: str
163
+ reference_gain_scale: float
164
+ reference_gain_evidence_sha256: str
165
+ minimum_peak_gain_ratio: float = 0.5
166
+ minimum_positive_fraction: float = 0.5
167
+ minimum_pilot_count: int = 2
168
+ base_gate: EvidenceAdaptivePortfolioRaceGate = field(
169
+ default_factory=EvidenceAdaptivePortfolioRaceGate,
170
+ repr=False,
171
+ compare=False,
172
+ )
173
+ gate_id: str = CAUSAL_OPPORTUNITY_PORTFOLIO_GATE_ID
174
+ gate_version: int = CAUSAL_OPPORTUNITY_PORTFOLIO_GATE_VERSION
175
+ definition_sha256: str = field(init=False)
176
+
177
+ def __post_init__(self) -> None:
178
+ _require_token(self.renewal_branch_id, name="renewal_branch_id")
179
+ _require_token(
180
+ self.exploration_branch_id,
181
+ name="exploration_branch_id",
182
+ )
183
+ if self.renewal_branch_id == self.exploration_branch_id:
184
+ raise ValueError(
185
+ "renewal and exploration branches must be distinct"
186
+ )
187
+ if (
188
+ type(self.reference_gain_scale) is not float
189
+ or not math.isfinite(self.reference_gain_scale)
190
+ or self.reference_gain_scale <= 0.0
191
+ ):
192
+ raise ValueError(
193
+ "reference_gain_scale must be finite and positive"
194
+ )
195
+ require_sha256(
196
+ self.reference_gain_evidence_sha256,
197
+ "reference_gain_evidence_sha256",
198
+ )
199
+ if (
200
+ type(self.minimum_peak_gain_ratio) is not float
201
+ or not math.isfinite(self.minimum_peak_gain_ratio)
202
+ or self.minimum_peak_gain_ratio < 0.0
203
+ ):
204
+ raise ValueError(
205
+ "minimum_peak_gain_ratio must be finite and non-negative"
206
+ )
207
+ if (
208
+ type(self.minimum_positive_fraction) is not float
209
+ or not math.isfinite(self.minimum_positive_fraction)
210
+ or not 0.0 <= self.minimum_positive_fraction <= 1.0
211
+ ):
212
+ raise ValueError(
213
+ "minimum_positive_fraction must lie in [0, 1]"
214
+ )
215
+ if (
216
+ type(self.minimum_pilot_count) is not int
217
+ or self.minimum_pilot_count <= 0
218
+ ):
219
+ raise ValueError("minimum_pilot_count must be positive")
220
+ if type(self.base_gate) is not EvidenceAdaptivePortfolioRaceGate:
221
+ raise TypeError("base_gate must be an exact evidence-adaptive gate")
222
+ self.base_gate.__post_init__()
223
+ _require_token(self.gate_id, name="gate_id")
224
+ if self.gate_version != CAUSAL_OPPORTUNITY_PORTFOLIO_GATE_VERSION:
225
+ raise ValueError("gate_version is immutable")
226
+ object.__setattr__(
227
+ self,
228
+ "definition_sha256",
229
+ _hash(
230
+ _DEFINITION_DOMAIN,
231
+ {
232
+ "schema_version": 1,
233
+ "gate_id": self.gate_id,
234
+ "gate_version": self.gate_version,
235
+ "renewal_branch_id": self.renewal_branch_id,
236
+ "exploration_branch_id": self.exploration_branch_id,
237
+ "reference_gain_scale_hex": (
238
+ self.reference_gain_scale.hex()
239
+ ),
240
+ "reference_gain_evidence_sha256": (
241
+ self.reference_gain_evidence_sha256
242
+ ),
243
+ "minimum_peak_gain_ratio_hex": (
244
+ self.minimum_peak_gain_ratio.hex()
245
+ ),
246
+ "minimum_positive_fraction_hex": (
247
+ self.minimum_positive_fraction.hex()
248
+ ),
249
+ "minimum_pilot_count": self.minimum_pilot_count,
250
+ "base_gate": {
251
+ "gate_id": self.base_gate.gate_id,
252
+ "gate_version": self.base_gate.gate_version,
253
+ "definition_sha256": (
254
+ self.base_gate.definition_sha256
255
+ ),
256
+ },
257
+ "routing_order": (
258
+ "insufficient_pilot_then_weak_absolute_opportunity_"
259
+ "then_sparse_positive_support_then_lane_adaptation"
260
+ ),
261
+ "missing_route_resolution": (
262
+ "authenticated_exact_action_set_equivalence_only"
263
+ ),
264
+ "candidate_branches_frozen_before_outcomes": True,
265
+ "outcome_conditioned_regeneration": False,
266
+ "only_pilot_outcomes_observed": True,
267
+ "workload_model_provider_branches": False,
268
+ },
269
+ ),
270
+ )
271
+
272
+ def decide(
273
+ self,
274
+ plan: SequentialAllocationPlanPort,
275
+ outcomes: SequentialPilotOutcomeBatch,
276
+ ) -> SequentialAllocationGateDecisionPort:
277
+ self.__post_init__()
278
+ if type(plan) is not PrecommittedPortfolioRacePlan:
279
+ raise TypeError(
280
+ "causal opportunity gate requires an exact portfolio plan"
281
+ )
282
+ plan.__post_init__()
283
+ if type(outcomes) is not SequentialPilotOutcomeBatch:
284
+ raise TypeError("outcomes must be exact")
285
+ outcomes.__post_init__()
286
+
287
+ base_decision = self.base_gate.decide(plan, outcomes)
288
+ if type(base_decision) is not PortfolioRaceGateDecision:
289
+ raise TypeError("base gate returned a foreign decision")
290
+ base_decision.__post_init__()
291
+
292
+ pilot_count = len(outcomes.outcomes)
293
+ positive_count = sum(
294
+ value.positive_marginal_utility
295
+ for value in outcomes.outcomes
296
+ )
297
+ maximum_gain = max(
298
+ (
299
+ value.marginal_archive_gain
300
+ for value in outcomes.outcomes
301
+ ),
302
+ default=0.0,
303
+ )
304
+ peak_gain_ratio = maximum_gain / self.reference_gain_scale
305
+ positive_fraction = (
306
+ 0.0 if pilot_count == 0 else positive_count / pilot_count
307
+ )
308
+
309
+ if pilot_count < self.minimum_pilot_count:
310
+ requested_branch_id = base_decision.selected_branch_id
311
+ route = "insufficient_pilot_base_gate"
312
+ elif (
313
+ positive_count == 0
314
+ or peak_gain_ratio < self.minimum_peak_gain_ratio
315
+ ):
316
+ requested_branch_id = self.renewal_branch_id
317
+ route = "weak_opportunity_renewal"
318
+ elif positive_fraction < self.minimum_positive_fraction:
319
+ requested_branch_id = self.exploration_branch_id
320
+ route = "sparse_opportunity_exploration"
321
+ else:
322
+ requested_branch_id = base_decision.selected_branch_id
323
+ route = "productive_market_lane_adaptation"
324
+
325
+ selected_branch_id, route_equivalence_path = _resolve_frozen_route(
326
+ plan,
327
+ requested_branch_id,
328
+ )
329
+ selected = plan.branch_for(selected_branch_id)
330
+ return PortfolioRaceGateDecision(
331
+ gate_id=self.gate_id,
332
+ gate_version=self.gate_version,
333
+ gate_definition_sha256=self.definition_sha256,
334
+ plan_sha256=plan.plan_sha256,
335
+ pilot_outcome_batch_sha256=outcomes.batch_sha256,
336
+ selected_branch_id=selected_branch_id,
337
+ selected_requirement_sha256=(
338
+ selected.requirement.requirement_sha256
339
+ ),
340
+ positive_pilot_count=positive_count,
341
+ pilot_count=pilot_count,
342
+ branch_scores=base_decision.branch_scores,
343
+ evidence=freeze_json(
344
+ {
345
+ "route": route,
346
+ "requested_branch_id": requested_branch_id,
347
+ "resolved_branch_id": selected_branch_id,
348
+ "route_equivalence_path": list(
349
+ route_equivalence_path
350
+ ),
351
+ "maximum_pilot_marginal_gain_hex": maximum_gain.hex(),
352
+ "reference_gain_scale_hex": (
353
+ self.reference_gain_scale.hex()
354
+ ),
355
+ "reference_gain_evidence_sha256": (
356
+ self.reference_gain_evidence_sha256
357
+ ),
358
+ "peak_gain_ratio_hex": peak_gain_ratio.hex(),
359
+ "minimum_peak_gain_ratio_hex": (
360
+ self.minimum_peak_gain_ratio.hex()
361
+ ),
362
+ "positive_pilot_count": positive_count,
363
+ "pilot_count": pilot_count,
364
+ "positive_fraction_hex": positive_fraction.hex(),
365
+ "minimum_positive_fraction_hex": (
366
+ self.minimum_positive_fraction.hex()
367
+ ),
368
+ "minimum_pilot_count": self.minimum_pilot_count,
369
+ "base_gate_decision": base_decision.to_record(
370
+ include_evidence=True
371
+ ),
372
+ "selected_branch_frozen_before_pilot": True,
373
+ "outcome_conditioned_regeneration": False,
374
+ "only_pilot_outcomes_observed": True,
375
+ "workload_model_provider_branches": False,
376
+ }
377
+ ),
378
+ )
379
+
380
+
381
+ __all__ = [
382
+ "CAUSAL_OPPORTUNITY_PORTFOLIO_GATE_ID",
383
+ "CAUSAL_OPPORTUNITY_PORTFOLIO_GATE_VERSION",
384
+ "CausalOpportunityPortfolioRaceGate",
385
+ ]
@@ -0,0 +1,145 @@
1
+ """Transactional composition for independent campaign outcome projections."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass, field
6
+
7
+ from agent_evolve.application.campaign_execution import CampaignStageRequest
8
+ from agent_evolve.application.portfolio_campaign_runtime import (
9
+ CampaignPortfolioOutcomePreparation,
10
+ CampaignPortfolioOutcomeUpdater,
11
+ )
12
+ from agent_evolve.application.portfolio_evolution import (
13
+ PortfolioVariationWaveRequest,
14
+ PortfolioVariationWaveResult,
15
+ )
16
+ from agent_evolve.domain.typed_json import (
17
+ FrozenJsonObject,
18
+ freeze_json,
19
+ typed_json_sha256,
20
+ )
21
+
22
+
23
+ def _object(value: dict[str, object]) -> FrozenJsonObject:
24
+ result = freeze_json(value)
25
+ if type(result) is not FrozenJsonObject: # pragma: no cover - closed root.
26
+ raise AssertionError("composite outcome evidence did not freeze to an object")
27
+ return result
28
+
29
+
30
+ @dataclass(slots=True)
31
+ class CompositeCampaignPortfolioOutcomeUpdater:
32
+ """Stage several zero-call updaters behind one atomic runtime port.
33
+
34
+ Each component receives the memory projection produced by its predecessor.
35
+ No component is published until every preparation succeeds. Abort proceeds
36
+ in reverse order; commit proceeds in declaration order.
37
+ """
38
+
39
+ updaters: tuple[CampaignPortfolioOutcomeUpdater, ...]
40
+ _prepared: dict[
41
+ str,
42
+ tuple[
43
+ CampaignPortfolioOutcomePreparation,
44
+ tuple[
45
+ tuple[
46
+ CampaignPortfolioOutcomeUpdater,
47
+ CampaignPortfolioOutcomePreparation,
48
+ ],
49
+ ...,
50
+ ],
51
+ ],
52
+ ] = field(init=False, default_factory=dict, repr=False)
53
+
54
+ def __post_init__(self) -> None:
55
+ if type(self.updaters) is not tuple or len(self.updaters) < 2:
56
+ raise ValueError("composite outcome updater requires at least two components")
57
+ if any(
58
+ not isinstance(value, CampaignPortfolioOutcomeUpdater)
59
+ for value in self.updaters
60
+ ):
61
+ raise TypeError("every component must implement the outcome updater port")
62
+
63
+ async def prepare_update(
64
+ self,
65
+ request: CampaignStageRequest,
66
+ waves: tuple[PortfolioVariationWaveRequest, ...],
67
+ results: tuple[PortfolioVariationWaveResult, ...],
68
+ prior_memory: FrozenJsonObject,
69
+ ) -> CampaignPortfolioOutcomePreparation:
70
+ self.__post_init__()
71
+ staged: list[
72
+ tuple[CampaignPortfolioOutcomeUpdater, CampaignPortfolioOutcomePreparation]
73
+ ] = []
74
+ memory = prior_memory
75
+ try:
76
+ for updater in self.updaters:
77
+ preparation = await updater.prepare_update(
78
+ request,
79
+ waves,
80
+ results,
81
+ memory,
82
+ )
83
+ if type(preparation) is not CampaignPortfolioOutcomePreparation:
84
+ raise TypeError(
85
+ "composite component returned a foreign preparation"
86
+ )
87
+ preparation.__post_init__()
88
+ staged.append((updater, preparation))
89
+ memory = preparation.updated_memory
90
+ except BaseException:
91
+ for updater, preparation in reversed(staged):
92
+ updater.abort_update(preparation)
93
+ raise
94
+ outer = CampaignPortfolioOutcomePreparation(
95
+ request_sha256=request.request_sha256,
96
+ generation=request.step.generation,
97
+ wave_request_sha256s=tuple(
98
+ value.selection_request.request_sha256 for value in waves
99
+ ),
100
+ result_receipt_sha256s=tuple(
101
+ value.receipt.receipt_sha256 for value in results
102
+ ),
103
+ prior_memory_sha256=typed_json_sha256(prior_memory),
104
+ updated_memory=memory,
105
+ evidence=_object(
106
+ {
107
+ "schema_version": 1,
108
+ "composition": "sequential_prepare_atomic_publish",
109
+ "component_preparations": [
110
+ value.to_record() for _updater, value in staged
111
+ ],
112
+ "component_count": len(staged),
113
+ "provider_calls": 0,
114
+ }
115
+ ),
116
+ )
117
+ if outer.preparation_sha256 in self._prepared:
118
+ for updater, preparation in reversed(staged):
119
+ updater.abort_update(preparation)
120
+ raise ValueError("composite outcome preparation is already pending")
121
+ self._prepared[outer.preparation_sha256] = (outer, tuple(staged))
122
+ return outer
123
+
124
+ def commit_update(self, preparation: CampaignPortfolioOutcomePreparation) -> None:
125
+ if type(preparation) is not CampaignPortfolioOutcomePreparation:
126
+ raise TypeError("preparation must be exact")
127
+ preparation.__post_init__()
128
+ pending = self._prepared.pop(preparation.preparation_sha256, None)
129
+ if pending is None or pending[0] != preparation:
130
+ raise ValueError("composite outcome preparation is foreign or not pending")
131
+ for updater, component in pending[1]:
132
+ updater.commit_update(component)
133
+
134
+ def abort_update(self, preparation: CampaignPortfolioOutcomePreparation) -> None:
135
+ if type(preparation) is not CampaignPortfolioOutcomePreparation:
136
+ raise TypeError("preparation must be exact")
137
+ preparation.__post_init__()
138
+ pending = self._prepared.pop(preparation.preparation_sha256, None)
139
+ if pending is None or pending[0] != preparation:
140
+ raise ValueError("composite outcome preparation is foreign or not pending")
141
+ for updater, component in reversed(pending[1]):
142
+ updater.abort_update(component)
143
+
144
+
145
+ __all__ = ["CompositeCampaignPortfolioOutcomeUpdater"]