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,799 @@
1
+ """Generic set-valued allocation over sealed consequence scenarios.
2
+
3
+ The application core does not interpret objective names, directions, forecast
4
+ quantiles, workloads, models, providers, or configuration fields. An injected
5
+ projection binds every materialized action to one or more named hypothetical
6
+ objective points plus a bounded reliability. An injected archive-utility port
7
+ owns normalization, objective senses, reference points, and exact joint set
8
+ value.
9
+
10
+ This separation lets one sealed proposal market expose several complete policy
11
+ arms (central, optimistic, reliability-adjusted, or risk-adjusted) to the
12
+ precommitted portfolio race without granting any arm current-outcome access.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import hashlib
18
+ import json
19
+ import math
20
+ import re
21
+ from dataclasses import dataclass, field
22
+ from enum import Enum
23
+ from typing import Protocol, runtime_checkable
24
+
25
+ from agent_evolve.application.agentic_evolution import EvolutionCandidate
26
+ from agent_evolve.application.candidate_archive_consequence import (
27
+ CandidateArchivePortfolioConsequenceUtilityPort,
28
+ validate_candidate_archive_portfolio_consequence_utility,
29
+ )
30
+ from agent_evolve.application.materialized_action_broker import (
31
+ MaterializedActionAllocationRequirement,
32
+ MaterializedActionDescriptor,
33
+ )
34
+ from agent_evolve.application.residual_portfolio_evolution import (
35
+ MaterializedActionProposalBatch,
36
+ ResidualPortfolioDecisionRequest,
37
+ )
38
+ from agent_evolve.domain.patch import require_sha256
39
+ from agent_evolve.domain.typed_json import (
40
+ FrozenJsonObject,
41
+ freeze_json,
42
+ thaw_json,
43
+ typed_json_sha256,
44
+ )
45
+ from agent_evolve.ports.hard_feasibility import (
46
+ HardFeasibilityDecision,
47
+ HardFeasibilityPort,
48
+ HardFeasibilityRequest,
49
+ HardFeasibilityVerdict,
50
+ assess_hard_feasibility,
51
+ hard_feasibility_decision_batch_sha256,
52
+ validate_hard_feasibility_port,
53
+ )
54
+
55
+
56
+ FORECAST_GEOMETRY_PORTFOLIO_POLICY_ID = "forecast_geometry_portfolio"
57
+ FORECAST_GEOMETRY_PORTFOLIO_POLICY_VERSION = 1
58
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
59
+ _MEMBER_DOMAIN = b"agent-evolve:forecast-geometry-member:v1\x00"
60
+ _BATCH_DOMAIN = b"agent-evolve:forecast-geometry-batch:v1\x00"
61
+ _POLICY_DOMAIN = b"agent-evolve:forecast-geometry-policy:v1\x00"
62
+ _PRIOR_DOMAIN = b"agent-evolve:forecast-geometry-prior:v1\x00"
63
+
64
+
65
+ def _canonical_json(value: object) -> bytes:
66
+ return json.dumps(
67
+ value,
68
+ allow_nan=False,
69
+ ensure_ascii=True,
70
+ separators=(",", ":"),
71
+ sort_keys=True,
72
+ ).encode("ascii", errors="strict")
73
+
74
+
75
+ def _hash(domain: bytes, value: object) -> str:
76
+ return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
77
+
78
+
79
+ def _require_token(value: str, *, name: str) -> None:
80
+ if type(value) is not str or _TOKEN.fullmatch(value) is None:
81
+ raise ValueError(f"{name} must use the closed token grammar")
82
+
83
+
84
+ def _projection_identity(
85
+ value: "MaterializedForecastGeometryProjectionPort",
86
+ ) -> tuple[str, int, str]:
87
+ if not isinstance(value, MaterializedForecastGeometryProjectionPort):
88
+ raise TypeError("projection must implement its application port")
89
+ identity = (
90
+ getattr(value, "projection_id", None),
91
+ getattr(value, "projection_version", None),
92
+ getattr(value, "definition_sha256", None),
93
+ )
94
+ _require_token(identity[0], name="projection_id")
95
+ if type(identity[1]) is not int or identity[1] <= 0:
96
+ raise ValueError("projection_version must be positive")
97
+ require_sha256(identity[2], "projection definition_sha256")
98
+ return identity # type: ignore[return-value]
99
+
100
+
101
+ @dataclass(frozen=True, slots=True)
102
+ class ForecastGeometryScenario:
103
+ """One named, raw objective point authored before evaluation."""
104
+
105
+ scenario_id: str
106
+ objective_point: tuple[tuple[str, float], ...]
107
+
108
+ def __post_init__(self) -> None:
109
+ _require_token(self.scenario_id, name="scenario_id")
110
+ if (
111
+ type(self.objective_point) is not tuple
112
+ or not self.objective_point
113
+ or self.objective_point
114
+ != tuple(sorted(self.objective_point))
115
+ ):
116
+ raise ValueError(
117
+ "objective_point must be non-empty and canonical"
118
+ )
119
+ metric_ids: list[str] = []
120
+ for metric_id, value in self.objective_point:
121
+ _require_token(metric_id, name="metric_id")
122
+ if type(value) is not float or not math.isfinite(value):
123
+ raise TypeError(
124
+ "objective-point values must be finite exact floats"
125
+ )
126
+ metric_ids.append(metric_id)
127
+ if len(metric_ids) != len(set(metric_ids)):
128
+ raise ValueError("objective_point repeats a metric")
129
+
130
+ def as_mapping(self) -> dict[str, float]:
131
+ self.__post_init__()
132
+ return dict(self.objective_point)
133
+
134
+ def to_record(self) -> dict[str, object]:
135
+ self.__post_init__()
136
+ return {
137
+ "scenario_id": self.scenario_id,
138
+ "objective_point": [
139
+ {"metric_id": metric_id, "value_hex": value.hex()}
140
+ for metric_id, value in self.objective_point
141
+ ],
142
+ }
143
+
144
+
145
+ @dataclass(frozen=True, slots=True)
146
+ class MaterializedForecastGeometryMember:
147
+ """All pre-evaluation scenario geometry for one materialized action."""
148
+
149
+ action_sha256: str
150
+ phenotype_identity_sha256: str
151
+ reliability: float
152
+ scenarios: tuple[ForecastGeometryScenario, ...]
153
+ source_evidence_sha256: str
154
+ member_sha256: str = field(init=False)
155
+
156
+ def __post_init__(self) -> None:
157
+ require_sha256(self.action_sha256, "action_sha256")
158
+ require_sha256(
159
+ self.phenotype_identity_sha256,
160
+ "phenotype_identity_sha256",
161
+ )
162
+ require_sha256(
163
+ self.source_evidence_sha256,
164
+ "source_evidence_sha256",
165
+ )
166
+ if (
167
+ type(self.reliability) is not float
168
+ or not math.isfinite(self.reliability)
169
+ or not 0.0 <= self.reliability <= 1.0
170
+ ):
171
+ raise ValueError("reliability must lie in [0, 1]")
172
+ if (
173
+ type(self.scenarios) is not tuple
174
+ or not self.scenarios
175
+ or any(
176
+ type(value) is not ForecastGeometryScenario
177
+ for value in self.scenarios
178
+ )
179
+ ):
180
+ raise TypeError("scenarios must contain exact scenario values")
181
+ for value in self.scenarios:
182
+ value.__post_init__()
183
+ scenario_ids = tuple(value.scenario_id for value in self.scenarios)
184
+ if scenario_ids != tuple(sorted(set(scenario_ids))):
185
+ raise ValueError("scenario IDs must be unique and canonical")
186
+ metric_frames = {
187
+ tuple(metric_id for metric_id, _value in scenario.objective_point)
188
+ for scenario in self.scenarios
189
+ }
190
+ if len(metric_frames) != 1:
191
+ raise ValueError("all scenarios must use one objective frame")
192
+ object.__setattr__(
193
+ self,
194
+ "member_sha256",
195
+ _hash(_MEMBER_DOMAIN, self._unsigned_record()),
196
+ )
197
+
198
+ def scenario(self, scenario_id: str) -> ForecastGeometryScenario:
199
+ _require_token(scenario_id, name="scenario_id")
200
+ matches = tuple(
201
+ value
202
+ for value in self.scenarios
203
+ if value.scenario_id == scenario_id
204
+ )
205
+ if len(matches) != 1:
206
+ raise ValueError("member omits the requested scenario")
207
+ return matches[0]
208
+
209
+ def _unsigned_record(self) -> dict[str, object]:
210
+ return {
211
+ "schema_version": 1,
212
+ "action_sha256": self.action_sha256,
213
+ "phenotype_identity_sha256": self.phenotype_identity_sha256,
214
+ "reliability_hex": self.reliability.hex(),
215
+ "scenarios": [value.to_record() for value in self.scenarios],
216
+ "source_evidence_sha256": self.source_evidence_sha256,
217
+ "candidate_outcomes_observed": False,
218
+ }
219
+
220
+ def to_record(self) -> dict[str, object]:
221
+ self.__post_init__()
222
+ return {**self._unsigned_record(), "member_sha256": self.member_sha256}
223
+
224
+
225
+ @dataclass(frozen=True, slots=True)
226
+ class MaterializedForecastGeometryBatch:
227
+ """Authenticated geometry covering one complete sealed proposal market."""
228
+
229
+ projection_id: str
230
+ projection_version: int
231
+ projection_definition_sha256: str
232
+ residual_request_sha256: str
233
+ proposal_sha256s: tuple[str, ...]
234
+ members: tuple[MaterializedForecastGeometryMember, ...]
235
+ candidate_outcomes_observed: bool
236
+ evidence: FrozenJsonObject
237
+ batch_sha256: str = field(init=False)
238
+
239
+ def __post_init__(self) -> None:
240
+ _require_token(self.projection_id, name="projection_id")
241
+ if type(self.projection_version) is not int or self.projection_version <= 0:
242
+ raise ValueError("projection_version must be positive")
243
+ require_sha256(
244
+ self.projection_definition_sha256,
245
+ "projection_definition_sha256",
246
+ )
247
+ require_sha256(
248
+ self.residual_request_sha256,
249
+ "residual_request_sha256",
250
+ )
251
+ if (
252
+ type(self.proposal_sha256s) is not tuple
253
+ or not self.proposal_sha256s
254
+ or self.proposal_sha256s
255
+ != tuple(sorted(set(self.proposal_sha256s)))
256
+ ):
257
+ raise ValueError("proposal hashes must be non-empty and canonical")
258
+ for value in self.proposal_sha256s:
259
+ require_sha256(value, "proposal_sha256")
260
+ if (
261
+ type(self.members) is not tuple
262
+ or not self.members
263
+ or any(
264
+ type(value) is not MaterializedForecastGeometryMember
265
+ for value in self.members
266
+ )
267
+ ):
268
+ raise TypeError("members must contain exact forecast geometry")
269
+ for value in self.members:
270
+ value.__post_init__()
271
+ action_ids = tuple(value.action_sha256 for value in self.members)
272
+ if action_ids != tuple(sorted(set(action_ids))):
273
+ raise ValueError("members must be unique and canonical")
274
+ if type(self.candidate_outcomes_observed) is not bool:
275
+ raise TypeError("candidate_outcomes_observed must be exact")
276
+ if self.candidate_outcomes_observed:
277
+ raise ValueError("forecast geometry cannot observe current outcomes")
278
+ if (
279
+ type(self.evidence) is not FrozenJsonObject
280
+ or freeze_json(self.evidence) is not self.evidence
281
+ ):
282
+ raise TypeError("batch evidence must be a frozen object")
283
+ object.__setattr__(
284
+ self,
285
+ "batch_sha256",
286
+ _hash(_BATCH_DOMAIN, self._unsigned_record()),
287
+ )
288
+
289
+ def _unsigned_record(self) -> dict[str, object]:
290
+ return {
291
+ "schema_version": 1,
292
+ "projection": {
293
+ "projection_id": self.projection_id,
294
+ "projection_version": self.projection_version,
295
+ "definition_sha256": self.projection_definition_sha256,
296
+ },
297
+ "residual_request_sha256": self.residual_request_sha256,
298
+ "proposal_sha256s": list(self.proposal_sha256s),
299
+ "member_sha256s": [
300
+ value.member_sha256 for value in self.members
301
+ ],
302
+ "candidate_outcomes_observed": self.candidate_outcomes_observed,
303
+ "evidence_sha256": typed_json_sha256(self.evidence),
304
+ }
305
+
306
+ def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
307
+ self.__post_init__()
308
+ record = {
309
+ **self._unsigned_record(),
310
+ "members": [value.to_record() for value in self.members],
311
+ "batch_sha256": self.batch_sha256,
312
+ }
313
+ if include_evidence:
314
+ record["evidence"] = thaw_json(self.evidence)
315
+ return record
316
+
317
+
318
+ @runtime_checkable
319
+ class MaterializedForecastGeometryProjectionPort(Protocol):
320
+ """Project a sealed materialized market into named consequence scenarios."""
321
+
322
+ projection_id: str
323
+ projection_version: int
324
+ definition_sha256: str
325
+
326
+ async def project(
327
+ self,
328
+ request: ResidualPortfolioDecisionRequest,
329
+ proposals: tuple[MaterializedActionProposalBatch, ...],
330
+ ) -> MaterializedForecastGeometryBatch: ...
331
+
332
+
333
+ class ForecastGeometryPortfolioMode(str, Enum):
334
+ SCENARIO = "scenario"
335
+ RELIABILITY_ADJUSTED_SCENARIO = "reliability_adjusted_scenario"
336
+ RISK_ADJUSTED_SCENARIO = "risk_adjusted_scenario"
337
+
338
+
339
+ def _prior_sha256(
340
+ candidates: tuple[EvolutionCandidate, ...],
341
+ ) -> str:
342
+ return _hash(
343
+ _PRIOR_DOMAIN,
344
+ [
345
+ {
346
+ "candidate_id": value.candidate_id.value,
347
+ "configuration_sha256": value.occurrence.configuration_hash,
348
+ "generation": value.generation,
349
+ "valid": value.valid,
350
+ "operator_compliant": value.operator_compliant,
351
+ "evidence_compliant": value.evidence_compliant,
352
+ "objectives": [
353
+ {"metric_id": metric_id, "value_hex": number.hex()}
354
+ for metric_id, number in value.objectives
355
+ ],
356
+ }
357
+ for value in candidates
358
+ ],
359
+ )
360
+
361
+
362
+ @dataclass(frozen=True, slots=True)
363
+ class ForecastGeometryPortfolioPolicy:
364
+ """Greedy exact-K joint archive allocation for one typed scenario arm."""
365
+
366
+ prior_candidates: tuple[EvolutionCandidate, ...]
367
+ projection: MaterializedForecastGeometryProjectionPort = field(
368
+ repr=False,
369
+ compare=False,
370
+ )
371
+ archive_utility: CandidateArchivePortfolioConsequenceUtilityPort = field(
372
+ repr=False,
373
+ compare=False,
374
+ )
375
+ mode: ForecastGeometryPortfolioMode
376
+ scenario_id: str
377
+ adverse_scenario_id: str | None = None
378
+ risk_aversion: float = 0.0
379
+ max_exact_reliability_members: int = 8
380
+ hard_feasibility: HardFeasibilityPort | None = field(
381
+ default=None,
382
+ repr=False,
383
+ compare=False,
384
+ )
385
+ policy_id: str = FORECAST_GEOMETRY_PORTFOLIO_POLICY_ID
386
+ policy_version: int = FORECAST_GEOMETRY_PORTFOLIO_POLICY_VERSION
387
+ definition_sha256: str = field(init=False)
388
+
389
+ def __post_init__(self) -> None:
390
+ if (
391
+ type(self.prior_candidates) is not tuple
392
+ or not self.prior_candidates
393
+ or any(
394
+ type(value) is not EvolutionCandidate
395
+ for value in self.prior_candidates
396
+ )
397
+ ):
398
+ raise TypeError("prior_candidates must be non-empty exact candidates")
399
+ for value in self.prior_candidates:
400
+ value.__post_init__()
401
+ candidate_ids = tuple(
402
+ value.candidate_id for value in self.prior_candidates
403
+ )
404
+ if len(candidate_ids) != len(set(candidate_ids)):
405
+ raise ValueError("prior candidate IDs must be unique")
406
+ projection_identity = _projection_identity(self.projection)
407
+ utility_identity = (
408
+ validate_candidate_archive_portfolio_consequence_utility(
409
+ self.archive_utility
410
+ )
411
+ )
412
+ if type(self.mode) is not ForecastGeometryPortfolioMode:
413
+ raise TypeError("mode must be an exact forecast geometry mode")
414
+ _require_token(self.scenario_id, name="scenario_id")
415
+ if self.mode is ForecastGeometryPortfolioMode.RISK_ADJUSTED_SCENARIO:
416
+ if self.adverse_scenario_id is None:
417
+ raise ValueError("risk-adjusted mode requires an adverse scenario")
418
+ _require_token(
419
+ self.adverse_scenario_id,
420
+ name="adverse_scenario_id",
421
+ )
422
+ elif self.adverse_scenario_id is not None:
423
+ raise ValueError("only risk-adjusted mode accepts an adverse scenario")
424
+ if (
425
+ type(self.risk_aversion) is not float
426
+ or not math.isfinite(self.risk_aversion)
427
+ or self.risk_aversion < 0.0
428
+ ):
429
+ raise ValueError("risk_aversion must be finite and non-negative")
430
+ if (
431
+ self.mode is not ForecastGeometryPortfolioMode.RISK_ADJUSTED_SCENARIO
432
+ and self.risk_aversion != 0.0
433
+ ):
434
+ raise ValueError("risk_aversion applies only to risk-adjusted mode")
435
+ if (
436
+ type(self.max_exact_reliability_members) is not int
437
+ or not 1 <= self.max_exact_reliability_members <= 16
438
+ ):
439
+ raise ValueError(
440
+ "max_exact_reliability_members must lie in [1, 16]"
441
+ )
442
+ feasibility_identity = (
443
+ None
444
+ if self.hard_feasibility is None
445
+ else validate_hard_feasibility_port(self.hard_feasibility)
446
+ )
447
+ _require_token(self.policy_id, name="policy_id")
448
+ if self.policy_id != FORECAST_GEOMETRY_PORTFOLIO_POLICY_ID:
449
+ raise ValueError("policy_id is immutable")
450
+ if self.policy_version != FORECAST_GEOMETRY_PORTFOLIO_POLICY_VERSION:
451
+ raise ValueError("policy_version is immutable")
452
+ object.__setattr__(
453
+ self,
454
+ "definition_sha256",
455
+ _hash(
456
+ _POLICY_DOMAIN,
457
+ {
458
+ "schema_version": 1,
459
+ "policy_id": self.policy_id,
460
+ "policy_version": self.policy_version,
461
+ "projection": {
462
+ "projection_id": projection_identity[0],
463
+ "projection_version": projection_identity[1],
464
+ "definition_sha256": projection_identity[2],
465
+ },
466
+ "archive_utility": {
467
+ "utility_id": utility_identity[0],
468
+ "utility_version": utility_identity[1],
469
+ "definition_sha256": utility_identity[2],
470
+ },
471
+ "mode": self.mode.value,
472
+ "scenario_id": self.scenario_id,
473
+ "adverse_scenario_id": self.adverse_scenario_id,
474
+ "risk_aversion_hex": self.risk_aversion.hex(),
475
+ "max_exact_reliability_members": (
476
+ self.max_exact_reliability_members
477
+ ),
478
+ "allocation": (
479
+ "greedy_joint_marginal_archive_utility_exact_k"
480
+ ),
481
+ "reliability": (
482
+ "exact_independent_bernoulli_set_expectation"
483
+ ),
484
+ "hard_feasibility": (
485
+ None
486
+ if feasibility_identity is None
487
+ else {
488
+ "policy_id": feasibility_identity[0],
489
+ "policy_version": feasibility_identity[1],
490
+ "definition_sha256": feasibility_identity[2],
491
+ }
492
+ ),
493
+ "candidate_outcomes_observed": False,
494
+ "workload_model_provider_branches": False,
495
+ },
496
+ ),
497
+ )
498
+
499
+ def _joint_gain(
500
+ self,
501
+ members: tuple[MaterializedForecastGeometryMember, ...],
502
+ scenario_id: str,
503
+ cache: dict[tuple[str, tuple[str, ...]], float],
504
+ ) -> float:
505
+ key = (
506
+ scenario_id,
507
+ tuple(sorted(value.action_sha256 for value in members)),
508
+ )
509
+ cached = cache.get(key)
510
+ if cached is not None:
511
+ return cached
512
+ result = self.archive_utility.portfolio_marginal_utility(
513
+ self.prior_candidates,
514
+ tuple(
515
+ value.scenario(scenario_id).as_mapping()
516
+ for value in members
517
+ ),
518
+ )
519
+ if type(result) is not float or not math.isfinite(result) or result < 0.0:
520
+ raise ValueError(
521
+ "joint archive utility must be finite and non-negative"
522
+ )
523
+ cache[key] = result
524
+ return result
525
+
526
+ def _portfolio_value(
527
+ self,
528
+ members: tuple[MaterializedForecastGeometryMember, ...],
529
+ cache: dict[tuple[str, tuple[str, ...]], float],
530
+ ) -> float:
531
+ if self.mode is ForecastGeometryPortfolioMode.SCENARIO:
532
+ return self._joint_gain(members, self.scenario_id, cache)
533
+ if (
534
+ self.mode
535
+ is ForecastGeometryPortfolioMode.RISK_ADJUSTED_SCENARIO
536
+ ):
537
+ central = self._joint_gain(
538
+ members,
539
+ self.scenario_id,
540
+ cache,
541
+ )
542
+ assert self.adverse_scenario_id is not None
543
+ adverse = self._joint_gain(
544
+ members,
545
+ self.adverse_scenario_id,
546
+ cache,
547
+ )
548
+ return central - self.risk_aversion * max(
549
+ 0.0,
550
+ central - adverse,
551
+ )
552
+ if len(members) > self.max_exact_reliability_members:
553
+ raise ValueError(
554
+ "reliability-adjusted portfolio exceeds exact integration limit"
555
+ )
556
+ expected = 0.0
557
+ for mask in range(1 << len(members)):
558
+ probability = 1.0
559
+ admitted: list[MaterializedForecastGeometryMember] = []
560
+ for index, member in enumerate(members):
561
+ if mask & (1 << index):
562
+ probability *= member.reliability
563
+ admitted.append(member)
564
+ else:
565
+ probability *= 1.0 - member.reliability
566
+ if probability:
567
+ expected += probability * self._joint_gain(
568
+ tuple(admitted),
569
+ self.scenario_id,
570
+ cache,
571
+ )
572
+ if not math.isfinite(expected) or expected < 0.0:
573
+ raise RuntimeError("expected joint archive utility became invalid")
574
+ return expected
575
+
576
+ async def require(
577
+ self,
578
+ request: ResidualPortfolioDecisionRequest,
579
+ proposals: tuple[MaterializedActionProposalBatch, ...],
580
+ ) -> MaterializedActionAllocationRequirement:
581
+ self.__post_init__()
582
+ if type(request) is not ResidualPortfolioDecisionRequest:
583
+ raise TypeError("request must be exact")
584
+ request.__post_init__()
585
+ if any(
586
+ value.generation >= request.decision_index
587
+ for value in self.prior_candidates
588
+ ):
589
+ raise ValueError("prior candidates cross the current cutoff")
590
+ if type(proposals) is not tuple or not proposals:
591
+ raise ValueError("proposals must be a non-empty exact tuple")
592
+ actions: list[MaterializedActionDescriptor] = []
593
+ for proposal in proposals:
594
+ if type(proposal) is not MaterializedActionProposalBatch:
595
+ raise TypeError("proposals must contain exact batches")
596
+ proposal.__post_init__()
597
+ proposal.require_request(request)
598
+ actions.extend(proposal.actions)
599
+ action_by_sha256 = {
600
+ value.action_sha256: value for value in actions
601
+ }
602
+ if len(action_by_sha256) != len(actions):
603
+ raise ValueError("proposal market repeats an action identity")
604
+ proposal_sha256s = tuple(
605
+ sorted(value.proposal_sha256 for value in proposals)
606
+ )
607
+ batch = await self.projection.project(request, proposals)
608
+ if type(batch) is not MaterializedForecastGeometryBatch:
609
+ raise TypeError("projection returned a foreign geometry batch")
610
+ batch.__post_init__()
611
+ if (
612
+ (
613
+ batch.projection_id,
614
+ batch.projection_version,
615
+ batch.projection_definition_sha256,
616
+ )
617
+ != _projection_identity(self.projection)
618
+ or batch.residual_request_sha256 != request.request_sha256
619
+ or batch.proposal_sha256s != proposal_sha256s
620
+ or tuple(value.action_sha256 for value in batch.members)
621
+ != tuple(sorted(action_by_sha256))
622
+ ):
623
+ raise ValueError("forecast geometry differs from the sealed market")
624
+ member_by_action = {
625
+ value.action_sha256: value for value in batch.members
626
+ }
627
+ if any(
628
+ member_by_action[action_id].phenotype_identity_sha256
629
+ != action.phenotype_identity_sha256
630
+ for action_id, action in action_by_sha256.items()
631
+ ):
632
+ raise ValueError("forecast geometry changes phenotype identity")
633
+ required_scenarios = {
634
+ self.scenario_id,
635
+ *(
636
+ ()
637
+ if self.adverse_scenario_id is None
638
+ else (self.adverse_scenario_id,)
639
+ ),
640
+ }
641
+ if any(
642
+ not required_scenarios.issubset(
643
+ {scenario.scenario_id for scenario in member.scenarios}
644
+ )
645
+ for member in batch.members
646
+ ):
647
+ raise ValueError("forecast geometry omits a policy scenario")
648
+
649
+ infeasible: set[str] = set()
650
+ feasibility_decisions: list[
651
+ tuple[str, HardFeasibilityDecision]
652
+ ] = []
653
+ if self.hard_feasibility is not None:
654
+ for action_sha256 in sorted(action_by_sha256):
655
+ decision = assess_hard_feasibility(
656
+ self.hard_feasibility,
657
+ HardFeasibilityRequest(
658
+ campaign_scope_sha256=request.campaign_scope_sha256,
659
+ cutoff_index=request.decision_index,
660
+ configuration=action_by_sha256[
661
+ action_sha256
662
+ ].configuration,
663
+ ),
664
+ )
665
+ feasibility_decisions.append((action_sha256, decision))
666
+ if decision.verdict is HardFeasibilityVerdict.INFEASIBLE:
667
+ infeasible.add(action_sha256)
668
+ admissible = tuple(
669
+ sorted(
670
+ (
671
+ value
672
+ for value in batch.members
673
+ if value.action_sha256 not in infeasible
674
+ ),
675
+ key=lambda value: value.action_sha256,
676
+ )
677
+ )
678
+ if len(
679
+ {
680
+ value.phenotype_identity_sha256
681
+ for value in admissible
682
+ }
683
+ ) < request.evaluation_slots:
684
+ raise ValueError("forecast market cannot fill unique-phenotype K")
685
+ if (
686
+ self.mode
687
+ is ForecastGeometryPortfolioMode.RELIABILITY_ADJUSTED_SCENARIO
688
+ and request.evaluation_slots > self.max_exact_reliability_members
689
+ ):
690
+ raise ValueError("evaluation K exceeds exact reliability limit")
691
+
692
+ selected: list[MaterializedForecastGeometryMember] = []
693
+ phenotypes: set[str] = set()
694
+ trace: list[dict[str, object]] = []
695
+ cache: dict[tuple[str, tuple[str, ...]], float] = {}
696
+ candidate_evaluations = 0
697
+ previous = self._portfolio_value((), cache)
698
+ for ordinal in range(1, request.evaluation_slots + 1):
699
+ candidates = tuple(
700
+ value
701
+ for value in admissible
702
+ if value.phenotype_identity_sha256 not in phenotypes
703
+ )
704
+ scored = []
705
+ for candidate in candidates:
706
+ value = self._portfolio_value(
707
+ tuple((*selected, candidate)),
708
+ cache,
709
+ )
710
+ candidate_evaluations += 1
711
+ scored.append((value, candidate))
712
+ if not scored:
713
+ raise RuntimeError("forecast geometry cannot close exact K")
714
+ value, winner = min(
715
+ scored,
716
+ key=lambda item: (
717
+ -item[0],
718
+ action_by_sha256[item[1].action_sha256].native_rank,
719
+ item[1].action_sha256,
720
+ ),
721
+ )
722
+ selected.append(winner)
723
+ phenotypes.add(winner.phenotype_identity_sha256)
724
+ trace.append(
725
+ {
726
+ "ordinal": ordinal,
727
+ "allocation_kind": "forecast_geometry_joint_greedy",
728
+ "score_lane": (
729
+ f"forecast_geometry.{self.mode.value}."
730
+ f"{self.scenario_id}"
731
+ ),
732
+ "action_sha256": winner.action_sha256,
733
+ "portfolio_value_before_hex": previous.hex(),
734
+ "portfolio_value_after_hex": value.hex(),
735
+ "marginal_portfolio_value_hex": (value - previous).hex(),
736
+ "member_reliability_hex": winner.reliability.hex(),
737
+ "candidate_outcomes_observed": False,
738
+ }
739
+ )
740
+ previous = value
741
+
742
+ feasibility_record = {
743
+ "enabled": self.hard_feasibility is not None,
744
+ "decision_batch_sha256": (
745
+ None
746
+ if not feasibility_decisions
747
+ else hard_feasibility_decision_batch_sha256(
748
+ tuple(
749
+ value.decision_sha256
750
+ for _action_sha256, value in feasibility_decisions
751
+ )
752
+ )
753
+ ),
754
+ "rejected_action_sha256s": sorted(infeasible),
755
+ "unknown_actions_remain_eligible": True,
756
+ "candidate_outcomes_observed": False,
757
+ }
758
+ return MaterializedActionAllocationRequirement(
759
+ policy_id=self.policy_id,
760
+ policy_version=self.policy_version,
761
+ policy_definition_sha256=self.definition_sha256,
762
+ residual_request_sha256=request.request_sha256,
763
+ proposal_sha256s=proposal_sha256s,
764
+ required_action_sha256s=tuple(
765
+ sorted(value.action_sha256 for value in selected)
766
+ ),
767
+ candidate_outcomes_observed=False,
768
+ evidence=freeze_json(
769
+ {
770
+ "forecast_geometry_batch_sha256": batch.batch_sha256,
771
+ "prior_candidate_set_sha256": _prior_sha256(
772
+ self.prior_candidates
773
+ ),
774
+ "mode": self.mode.value,
775
+ "scenario_id": self.scenario_id,
776
+ "adverse_scenario_id": self.adverse_scenario_id,
777
+ "risk_aversion_hex": self.risk_aversion.hex(),
778
+ "final_portfolio_value_hex": previous.hex(),
779
+ "candidate_portfolio_evaluations": candidate_evaluations,
780
+ "selection_trace": trace,
781
+ "hard_feasibility": feasibility_record,
782
+ "joint_set_value_not_member_score_sum": True,
783
+ "candidate_outcomes_observed": False,
784
+ "workload_model_provider_branches": False,
785
+ }
786
+ ),
787
+ )
788
+
789
+
790
+ __all__ = [
791
+ "FORECAST_GEOMETRY_PORTFOLIO_POLICY_ID",
792
+ "FORECAST_GEOMETRY_PORTFOLIO_POLICY_VERSION",
793
+ "ForecastGeometryPortfolioMode",
794
+ "ForecastGeometryPortfolioPolicy",
795
+ "ForecastGeometryScenario",
796
+ "MaterializedForecastGeometryBatch",
797
+ "MaterializedForecastGeometryMember",
798
+ "MaterializedForecastGeometryProjectionPort",
799
+ ]