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,1374 @@
1
+ """All-action, outcome-conditioned portfolio selection for real campaigns.
2
+
3
+ The policy is an adapter between the campaign's stable
4
+ ``PortfolioSelectionPolicy`` port and the generic action-forecast/allocation
5
+ ports. It asks a model to forecast every action in a sealed, outcome-blind
6
+ candidate-pool projection (or the complete contract when no projection is
7
+ bound), optionally
8
+ overlays evaluator-independent exact metric projections, and lets trusted code
9
+ construct the final hard-feasible set. Workload adapters may enrich action
10
+ semantics or exact cheap metric cells, but never rank or select actions.
11
+
12
+ The implementation also reconciles the existing bounded memory-dose contract:
13
+ memory-supported options become explicit hard requirements, while a sealed
14
+ proposal witness is extended only as far as necessary to preserve the original
15
+ proposal/evaluation join. This keeps memory attribution causal and makes the
16
+ new selector usable in later generations rather than only in memory-free
17
+ assays.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import hashlib
23
+ import itertools
24
+ import json
25
+ import math
26
+ import time
27
+ from dataclasses import dataclass
28
+ from decimal import Decimal
29
+ from typing import Callable
30
+
31
+ from agent_evolve.application.action_forecast_partitioning import (
32
+ PartitionedActionForecastPolicy,
33
+ ResolvedActionForecastHealthAssessment,
34
+ assess_resolved_action_forecast_health,
35
+ build_action_forecast_partition_layout,
36
+ lenient_action_forecast_health_policy,
37
+ )
38
+ from agent_evolve.application.action_metric_projection import (
39
+ ActionMetricProjectionOverlayResult,
40
+ apply_exact_action_metric_projections,
41
+ )
42
+ from agent_evolve.application.campaign_search_phase import (
43
+ resolve_campaign_search_phase_context,
44
+ )
45
+ from agent_evolve.application.campaign_variation_trace import (
46
+ project_finite_contract_proposal_topology,
47
+ )
48
+ from agent_evolve.application.contextual_action_allocation import (
49
+ contextual_action_arm_count_constraints,
50
+ contextual_allocation_realization,
51
+ selected_variation_source_ids,
52
+ )
53
+ from agent_evolve.application.empirical_consequence_calibration import (
54
+ ActionConsequenceCalibrationPolicy,
55
+ ActionConsequenceCalibrationResult,
56
+ )
57
+ from agent_evolve.application.global_wave_action_allocation import (
58
+ GlobalWaveActionAllocationCoordinator,
59
+ GlobalWaveActionAllocationLane,
60
+ GlobalWaveActionAllocationLaneResult,
61
+ RoleSlots,
62
+ )
63
+ from agent_evolve.application.target_conditioned_action_forecast import (
64
+ TargetConditionedActionForecastPlan,
65
+ allocate_target_conditioned_actions,
66
+ audit_target_conditioned_role_allocation,
67
+ build_target_conditioned_action_forecast_plan,
68
+ )
69
+ from agent_evolve.core.action_semantics import ActionSpaceSemantics
70
+ from agent_evolve.core.optimization_semantics import OptimizationSemantics
71
+ from agent_evolve.domain.finite_variation import FiniteVariationContract
72
+ from agent_evolve.domain.ids import LLMCallId
73
+ from agent_evolve.domain.typed_json import FrozenJsonObject, freeze_json, thaw_json
74
+ from agent_evolve.ports.action_allocation import ActionAllocationResult
75
+ from agent_evolve.ports.action_forecast import (
76
+ ActionForecastEvidenceMode,
77
+ ActionForecastPartitionPolicyBinding,
78
+ ResolvedActionForecast,
79
+ ResolvedActionForecastBatch,
80
+ )
81
+ from agent_evolve.ports.action_metric_projection import (
82
+ ActionMetricProjector,
83
+ ExactActionMetricProjectionBatch,
84
+ )
85
+ from agent_evolve.ports.contextual_search_allocation import (
86
+ ContextualPortfolioAllocationContract,
87
+ ContextualPortfolioAllocationRealization,
88
+ )
89
+ from agent_evolve.ports.agentic_generator import (
90
+ AgenticCallTelemetry,
91
+ MetricEffectDirection,
92
+ MetricEffectPrediction,
93
+ )
94
+ from agent_evolve.ports.portfolio_memory_dose import (
95
+ PortfolioMemoryDoseAssessment,
96
+ PortfolioMemoryDoseMember,
97
+ assess_evaluated_portfolio_memory_dose,
98
+ assess_proposed_portfolio_memory_dose,
99
+ )
100
+ from agent_evolve.ports.portfolio_selection import (
101
+ PortfolioMemberDraft,
102
+ PortfolioSelectionRequest,
103
+ PortfolioSelectionResult,
104
+ PortfolioSelectionSupplementalAudit,
105
+ resolve_ranked_portfolio_decision,
106
+ )
107
+ from agent_evolve.policies.selection.forecast_calibration import (
108
+ ForecastCalibrationScope,
109
+ ForecastConfidenceBin,
110
+ ForecastPredictionReceipt,
111
+ )
112
+ from agent_evolve.policies.selection.common_candidate_pool import (
113
+ CommonCandidatePoolDecision,
114
+ )
115
+
116
+
117
+ OUTCOME_CONDITIONED_PORTFOLIO_POLICY_ID = "outcome_conditioned_expert_portfolio"
118
+ OUTCOME_CONDITIONED_PORTFOLIO_POLICY_VERSION = 8
119
+ OUTCOME_CONDITIONED_PORTFOLIO_POLICY_DEFINITION_SHA256 = hashlib.sha256(
120
+ b"agent-evolve:outcome-conditioned-expert-portfolio:v8;"
121
+ b"proposal-universe=full-sealed-contract-with-outcome-blind-authenticated-"
122
+ b"candidate-pool-forecast-projection;"
123
+ b"consequence-source=partitioned-llm-plus-prior-only-calibration-port;"
124
+ b"optional-authority=evaluator-independent-exact-metric-projection;"
125
+ b"bootstrap-acquisition=target-closure-when-residual-cell-unidentified;"
126
+ b"nonterminal-residual-acquisition=role-factorized-exploit-bridge-probe;"
127
+ b"terminal-residual-acquisition=reliability-adjusted-expected-hypervolume;"
128
+ b"hard-constraints=family-patch-required-option-memory-dose-contextual-"
129
+ b"source-and-operator-marginals;"
130
+ b"forecast-health=model-authoritative-unprojected-cells-only;"
131
+ b"model-authors-consequences-not-selection;"
132
+ b"optional-wave-authority=global-role-budget-and-cross-lane-diversity;"
133
+ b"audit-proposal-topology=engine-authenticated-forecast-contract;"
134
+ b"workload-branches=false;real-current-future-outcomes=false"
135
+ ).hexdigest()
136
+ _FORECAST_CALL_DOMAIN = b"agent-evolve:outcome-conditioned-forecast-call:v1\x00"
137
+ _BOUND_POLICY_DOMAIN = b"agent-evolve:outcome-conditioned-policy-binding:v1\x00"
138
+
139
+
140
+ ActionSemanticsFactory = Callable[[FiniteVariationContract], ActionSpaceSemantics]
141
+ ContextualAllocationProvider = Callable[
142
+ [PortfolioSelectionRequest], ContextualPortfolioAllocationContract | None
143
+ ]
144
+ CandidatePoolProvider = Callable[
145
+ [PortfolioSelectionRequest], CommonCandidatePoolDecision | None
146
+ ]
147
+
148
+
149
+ def _forecast_contract_projection(
150
+ request: PortfolioSelectionRequest,
151
+ decision: CommonCandidatePoolDecision | None,
152
+ ) -> tuple[FiniteVariationContract, dict[str, object]]:
153
+ """Project the expensive forecast surface without hiding union support."""
154
+
155
+ source = request.finite_variation_contract
156
+ if decision is None:
157
+ return source, {
158
+ "mode": "complete_finite_contract",
159
+ "source_contract_sha256": source.identity_sha256,
160
+ "forecast_contract_sha256": source.identity_sha256,
161
+ "source_option_count": len(source.options),
162
+ "forecast_option_count": len(source.options),
163
+ "common_candidate_pool_decision_sha256": None,
164
+ }
165
+ if type(decision) is not CommonCandidatePoolDecision:
166
+ raise TypeError("candidate-pool provider returned a foreign decision")
167
+ decision.__post_init__()
168
+ if (
169
+ decision.finite_contract_sha256 != source.identity_sha256
170
+ or decision.parent_configuration_sha256
171
+ != source.parent_configuration_sha256
172
+ or decision.evaluation_size != request.portfolio_size
173
+ ):
174
+ raise ValueError("candidate-pool decision differs from the selection request")
175
+ options = {value.option_id: value for value in source.options}
176
+ try:
177
+ projected_options = tuple(options[value] for value in decision.option_ids)
178
+ except KeyError as error: # pragma: no cover - decision validation closes this.
179
+ raise ValueError("candidate-pool option escapes the source contract") from error
180
+ projected = FiniteVariationContract(
181
+ catalog_id=source.catalog_id,
182
+ catalog_version=source.catalog_version,
183
+ catalog_definition_sha256=source.catalog_definition_sha256,
184
+ parent_configuration=source.parent_configuration,
185
+ options=projected_options,
186
+ )
187
+ return projected, {
188
+ "mode": "authenticated_outcome_blind_candidate_pool",
189
+ "source_contract_sha256": source.identity_sha256,
190
+ "forecast_contract_sha256": projected.identity_sha256,
191
+ "source_option_count": len(source.options),
192
+ "forecast_option_count": len(projected.options),
193
+ "common_candidate_pool_decision_sha256": decision.decision_sha256,
194
+ "common_candidate_pool_state_identity_sha256": (
195
+ decision.state_identity_sha256
196
+ ),
197
+ "common_candidate_pool_task_identity_sha256": decision.task_identity_sha256,
198
+ "forecast_option_ids": list(decision.option_ids),
199
+ "outcomes_consulted": False,
200
+ "model_or_provider_fields_consulted": False,
201
+ }
202
+
203
+
204
+ def _identified_outcome_conditioned_acquisition(
205
+ *,
206
+ residual_cell_identified: bool,
207
+ terminal: bool,
208
+ ) -> tuple[str, str]:
209
+ """Choose only an acquisition whose geometric estimand is identified."""
210
+
211
+ if type(residual_cell_identified) is not bool or type(terminal) is not bool:
212
+ raise TypeError("acquisition evidence flags must be exact bools")
213
+ if not residual_cell_identified:
214
+ return "target_closure", "directional_affine_bootstrap"
215
+ if terminal:
216
+ return (
217
+ "reliability_adjusted_expected_hypervolume",
218
+ "residual_frontier_cell",
219
+ )
220
+ return "role_factorized", "residual_frontier_cell"
221
+
222
+
223
+ def _canonical_json(value: object) -> bytes:
224
+ return json.dumps(
225
+ value,
226
+ allow_nan=False,
227
+ ensure_ascii=True,
228
+ separators=(",", ":"),
229
+ sort_keys=True,
230
+ ).encode("ascii", errors="strict")
231
+
232
+
233
+ def _object(value: dict[str, object]) -> FrozenJsonObject:
234
+ frozen = freeze_json(value)
235
+ if type(frozen) is not FrozenJsonObject: # pragma: no cover - closed root.
236
+ raise AssertionError("selector audit did not freeze to an object")
237
+ return frozen
238
+
239
+
240
+ def _plain_global_allocation_audit(
241
+ value: GlobalWaveActionAllocationLaneResult | None,
242
+ ) -> dict[str, object] | None:
243
+ """Cross the immutable typed-JSON boundary exactly once for nesting."""
244
+
245
+ if value is None:
246
+ return None
247
+ if type(value) is not GlobalWaveActionAllocationLaneResult:
248
+ raise TypeError("global allocation must be an exact lane result or None")
249
+ value.__post_init__()
250
+ record = thaw_json(value.audit)
251
+ if type(record) is not dict: # pragma: no cover - frozen root is closed.
252
+ raise AssertionError("global allocation audit did not thaw to an object")
253
+ return record
254
+
255
+
256
+ def _forecast_call_id(request: PortfolioSelectionRequest) -> LLMCallId:
257
+ digest = hashlib.sha256(
258
+ _FORECAST_CALL_DOMAIN + bytes.fromhex(request.request_sha256)
259
+ ).hexdigest()
260
+ return LLMCallId(f"call_outcome_forecast_{digest[:40]}")
261
+
262
+
263
+ def _resolve_model_authority_health(
264
+ *,
265
+ request_forecasts: ResolvedActionForecastBatch,
266
+ health: ResolvedActionForecastHealthAssessment,
267
+ exact_projections: ExactActionMetricProjectionBatch | None,
268
+ ) -> tuple[bool, dict[str, object]]:
269
+ """Apply collapse gates only where the model retains metric authority.
270
+
271
+ A complete exact projection removes the language model's decision
272
+ authority for one metric. Collapsed raw values for that metric remain in
273
+ the audit but cannot veto the wave. A partial projection grants no such
274
+ exemption.
275
+ """
276
+
277
+ if type(request_forecasts) is not ResolvedActionForecastBatch:
278
+ raise TypeError("request_forecasts must be an exact resolved batch")
279
+ request_forecasts.__post_init__()
280
+ if type(health) is not ResolvedActionForecastHealthAssessment:
281
+ raise TypeError("health must be an exact resolved assessment")
282
+ health.__post_init__()
283
+ option_ids = {value.option_id for value in request_forecasts.forecasts}
284
+ projected_by_metric: dict[str, set[str]] = {}
285
+ if exact_projections is not None:
286
+ if type(exact_projections) is not ExactActionMetricProjectionBatch:
287
+ raise TypeError("exact_projections must be an exact batch or None")
288
+ exact_projections.__post_init__()
289
+ for value in exact_projections.projections:
290
+ projected_by_metric.setdefault(value.metric_id, set()).add(value.option_id)
291
+ fully_projected = tuple(
292
+ sorted(
293
+ metric_id
294
+ for metric_id, projected_options in projected_by_metric.items()
295
+ if projected_options == option_ids
296
+ )
297
+ )
298
+ assessment_by_metric = {
299
+ value.metric_id: value for value in health.metric_assessments
300
+ }
301
+ authoritative = tuple(sorted(set(assessment_by_metric).difference(fully_projected)))
302
+ unresolved_failed = tuple(
303
+ metric_id
304
+ for metric_id in authoritative
305
+ if not assessment_by_metric[metric_id].passes
306
+ )
307
+ signatures: set[tuple[object, ...]] = set()
308
+ if authoritative:
309
+ for forecast in request_forecasts.forecasts:
310
+ metrics = {value.metric_id: value for value in forecast.metric_forecasts}
311
+ signatures.add(
312
+ (
313
+ forecast.probability_valid.hex(),
314
+ *(
315
+ (
316
+ metrics[metric_id].p10_delta.hex(),
317
+ metrics[metric_id].p50_delta.hex(),
318
+ metrics[metric_id].p90_delta.hex(),
319
+ metrics[metric_id].confidence.hex(),
320
+ )
321
+ for metric_id in authoritative
322
+ ),
323
+ )
324
+ )
325
+ threshold_applied = (
326
+ len(request_forecasts.forecasts) >= health.health_policy.minimum_rows
327
+ )
328
+ signature_passes = (
329
+ not authoritative
330
+ or not threshold_applied
331
+ or len(signatures) >= health.health_policy.minimum_distinct_signatures
332
+ )
333
+ passes = signature_passes and not unresolved_failed
334
+ return passes, {
335
+ "schema_version": 1,
336
+ "raw_health_passes": health.passes,
337
+ "fully_projected_metric_ids": list(fully_projected),
338
+ "model_authoritative_metric_ids": list(authoritative),
339
+ "unresolved_failed_metric_ids": list(unresolved_failed),
340
+ "model_authoritative_distinct_row_signature_count": len(signatures),
341
+ "threshold_applied": threshold_applied,
342
+ "signature_gate_passes": signature_passes,
343
+ "passes": passes,
344
+ }
345
+
346
+
347
+ def _evidence_mode(request: PortfolioSelectionRequest) -> ActionForecastEvidenceMode:
348
+ if (
349
+ request.source_registry is not None
350
+ and request.experimental_view_receipt is not None
351
+ and all(card.source_binding is not None for card in request.cards)
352
+ and any(card.finite_action_evidence for card in request.cards)
353
+ ):
354
+ return ActionForecastEvidenceMode.GROUNDED
355
+ return ActionForecastEvidenceMode.CATALOG_ONLY
356
+
357
+
358
+ def _telemetry_record(value: AgenticCallTelemetry) -> dict[str, object]:
359
+ value.__post_init__()
360
+ return {
361
+ "requested_model": value.requested_model,
362
+ "resolved_model": value.resolved_model,
363
+ "resolved_provider": value.resolved_provider,
364
+ "provider_response_id": value.provider_response_id,
365
+ "finish_reason": value.finish_reason,
366
+ "input_tokens": value.input_tokens,
367
+ "output_tokens": value.output_tokens,
368
+ "reasoning_tokens": value.reasoning_tokens,
369
+ "cache_read_tokens": value.cache_read_tokens,
370
+ "cache_write_tokens": value.cache_write_tokens,
371
+ "cost_usd": None if value.cost_usd is None else str(value.cost_usd),
372
+ "latency_ns": value.latency_ns,
373
+ "attempt_count": value.attempt_count,
374
+ }
375
+
376
+
377
+ def _aggregate_telemetry(
378
+ values: tuple[AgenticCallTelemetry, ...],
379
+ *,
380
+ wall_latency_ns: int,
381
+ ) -> AgenticCallTelemetry:
382
+ if not values:
383
+ raise ValueError("partitioned portfolio selection requires call telemetry")
384
+ for value in values:
385
+ value.__post_init__()
386
+ requested_models = {value.requested_model for value in values}
387
+ resolved_models = {value.resolved_model for value in values}
388
+ resolved_providers = {value.resolved_provider for value in values}
389
+ if (
390
+ len(requested_models) != 1
391
+ or len(resolved_models) != 1
392
+ or len(resolved_providers) != 1
393
+ ):
394
+ raise ValueError("physical forecast blocks resolved to heterogeneous models")
395
+ costs = tuple(value.cost_usd for value in values)
396
+ cost: Decimal | None
397
+ if any(value is None for value in costs):
398
+ cost = None
399
+ else:
400
+ cost = sum((value for value in costs if value is not None), Decimal(0))
401
+ finish_reasons = {value.finish_reason for value in values}
402
+ return AgenticCallTelemetry(
403
+ requested_model=next(iter(requested_models)),
404
+ resolved_model=next(iter(resolved_models)),
405
+ resolved_provider=next(iter(resolved_providers)),
406
+ provider_response_id=None,
407
+ finish_reason=(
408
+ next(iter(finish_reasons)) if len(finish_reasons) == 1 else None
409
+ ),
410
+ input_tokens=sum(value.input_tokens for value in values),
411
+ output_tokens=sum(value.output_tokens for value in values),
412
+ reasoning_tokens=sum(value.reasoning_tokens for value in values),
413
+ cache_read_tokens=sum(value.cache_read_tokens for value in values),
414
+ cache_write_tokens=sum(value.cache_write_tokens for value in values),
415
+ cost_usd=cost,
416
+ latency_ns=wall_latency_ns,
417
+ # Physical block count is recorded separately. ``attempt_count`` keeps
418
+ # its established retry meaning for the logical receipt.
419
+ attempt_count=max(value.attempt_count for value in values),
420
+ )
421
+
422
+
423
+ def _direction(metric: object) -> MetricEffectDirection:
424
+ p10 = getattr(metric, "p10_delta")
425
+ p50 = getattr(metric, "p50_delta")
426
+ p90 = getattr(metric, "p90_delta")
427
+ if any(
428
+ type(value) is not float or not math.isfinite(value)
429
+ for value in (p10, p50, p90)
430
+ ):
431
+ raise TypeError("resolved forecast deltas must be finite exact floats")
432
+ if p10 == p50 == p90 == 0.0:
433
+ return MetricEffectDirection.UNCHANGED
434
+ if p90 < 0.0:
435
+ return MetricEffectDirection.DECREASE
436
+ if p10 > 0.0:
437
+ return MetricEffectDirection.INCREASE
438
+ return MetricEffectDirection.UNKNOWN
439
+
440
+
441
+ def _selected_card_keys(forecast: ResolvedActionForecast) -> tuple[str, ...]:
442
+ return tuple(
443
+ sorted(
444
+ {
445
+ citation.card_key
446
+ for metric in forecast.metric_forecasts
447
+ for citation in metric.citations
448
+ }
449
+ )
450
+ )
451
+
452
+
453
+ def _preference_scores(
454
+ plan: TargetConditionedActionForecastPlan,
455
+ forecasts: ResolvedActionForecastBatch,
456
+ ) -> dict[str, float]:
457
+ """Cheap deterministic ordering for memory witnesses and proposal padding."""
458
+
459
+ scores: dict[str, float] = {}
460
+ for value in plan.assess(forecasts):
461
+ p50 = value.scenarios[1]
462
+ score = value.probability_valid * p50.shortfall_reduction_l1
463
+ if not math.isfinite(score): # pragma: no cover - typed inputs close this.
464
+ raise RuntimeError("target preference score became non-finite")
465
+ scores[value.option_id] = float(score)
466
+ return scores
467
+
468
+
469
+ def _memory_assignment_candidates(
470
+ request: PortfolioSelectionRequest,
471
+ *,
472
+ preference: dict[str, float],
473
+ max_options_per_card: int,
474
+ max_assignments: int,
475
+ ) -> tuple[dict[str, str], ...]:
476
+ """Enumerate bounded card-to-distinct-option matchings, best first."""
477
+
478
+ dose = request.memory_dose_contract
479
+ if dose is None:
480
+ return ({},)
481
+ dose.__post_init__()
482
+ if dose.maximum_cards_per_member < 1:
483
+ raise ValueError("memory dose cannot attribute any selected member")
484
+ supports = dose.card_supports
485
+ evaluated_lower, evaluated_upper = dose.evaluated_supported_member_bounds
486
+ proposed_lower, proposed_upper = dose.proposed_supported_member_bounds
487
+ if dose.require_every_assigned_card:
488
+ subset_sizes = (len(supports),)
489
+ else:
490
+ low = max(evaluated_lower, proposed_lower)
491
+ high = min(evaluated_upper, proposed_upper, len(supports))
492
+ subset_sizes = tuple(range(low, high + 1))
493
+ results: list[dict[str, str]] = []
494
+ for size in subset_sizes:
495
+ if (
496
+ not evaluated_lower <= size <= evaluated_upper
497
+ or not proposed_lower <= size <= proposed_upper
498
+ or request.portfolio_size - size
499
+ < dose.minimum_unattributed_evaluated_members
500
+ ):
501
+ continue
502
+ for selected_supports in itertools.combinations(supports, size):
503
+ option_lists = tuple(
504
+ tuple(
505
+ option_id
506
+ for option_id, _identity in sorted(
507
+ support.compatible_options,
508
+ key=lambda item: (
509
+ -preference.get(item[0], float("-inf")),
510
+ item[1],
511
+ item[0],
512
+ ),
513
+ )[:max_options_per_card]
514
+ )
515
+ for support in selected_supports
516
+ )
517
+ for option_ids in itertools.product(*option_lists):
518
+ if len(set(option_ids)) != len(option_ids):
519
+ continue
520
+ results.append(
521
+ {
522
+ option_id: support.card_key
523
+ for support, option_id in zip(
524
+ selected_supports,
525
+ option_ids,
526
+ strict=True,
527
+ )
528
+ }
529
+ )
530
+ if len(results) >= max_assignments:
531
+ return tuple(results)
532
+ if not results:
533
+ raise ValueError("bounded memory dose has no candidate attribution matching")
534
+ return tuple(results)
535
+
536
+
537
+ def _memory_assessments(
538
+ request: PortfolioSelectionRequest,
539
+ *,
540
+ allocation: ActionAllocationResult,
541
+ card_by_option: dict[str, str],
542
+ preference: dict[str, float],
543
+ ) -> tuple[
544
+ dict[str, tuple[str, ...]],
545
+ PortfolioMemoryDoseAssessment | None,
546
+ PortfolioMemoryDoseAssessment | None,
547
+ ]:
548
+ selected = allocation.decision.members
549
+ selected_support = {
550
+ value.option_id: (
551
+ ()
552
+ if value.option_id not in card_by_option
553
+ else (card_by_option[value.option_id],)
554
+ )
555
+ for value in selected
556
+ }
557
+ dose = request.memory_dose_contract
558
+ if dose is None:
559
+ return selected_support, None, None
560
+ supported_count = sum(bool(value) for value in selected_support.values())
561
+ proposed_size = max(
562
+ request.portfolio_size,
563
+ supported_count + dose.minimum_unattributed_proposed_members,
564
+ )
565
+ contract = request.finite_variation_contract
566
+ if proposed_size > len(contract.options):
567
+ raise ValueError("memory-dose proposal witness exceeds the finite contract")
568
+ selected_ids = {value.option_id for value in selected}
569
+ extras = sorted(
570
+ (value for value in contract.options if value.option_id not in selected_ids),
571
+ key=lambda value: (
572
+ -preference.get(value.option_id, float("-inf")),
573
+ value.identity_sha256,
574
+ value.option_id,
575
+ ),
576
+ )[: proposed_size - len(selected)]
577
+ identities = {value.option_id: value.identity_sha256 for value in contract.options}
578
+ proposal_ids = tuple(value.option_id for value in selected) + tuple(
579
+ value.option_id for value in extras
580
+ )
581
+ proposed_members = tuple(
582
+ PortfolioMemoryDoseMember(
583
+ rank=rank,
584
+ option_id=option_id,
585
+ option_identity_sha256=identities[option_id],
586
+ supporting_card_keys=selected_support.get(option_id, ()),
587
+ )
588
+ for rank, option_id in enumerate(proposal_ids, start=1)
589
+ )
590
+ proposed = assess_proposed_portfolio_memory_dose(dose, proposed_members)
591
+ if not proposed.passed:
592
+ raise ValueError("constructed all-action proposal violates memory dose")
593
+ evaluated_members = tuple(
594
+ PortfolioMemoryDoseMember(
595
+ rank=rank,
596
+ option_id=value.option_id,
597
+ option_identity_sha256=value.option_identity_sha256,
598
+ supporting_card_keys=selected_support[value.option_id],
599
+ )
600
+ for rank, value in enumerate(selected, start=1)
601
+ )
602
+ evaluated = assess_evaluated_portfolio_memory_dose(
603
+ dose,
604
+ evaluated_members,
605
+ proposal_assessment=proposed,
606
+ )
607
+ if not evaluated.passed:
608
+ raise ValueError("allocated all-action portfolio violates memory dose")
609
+ return selected_support, proposed, evaluated
610
+
611
+
612
+ def _bound_policy_definition(
613
+ *,
614
+ plan: TargetConditionedActionForecastPlan,
615
+ partition_policy: ActionForecastPartitionPolicyBinding,
616
+ consequence_calibration: ActionConsequenceCalibrationResult | None,
617
+ metric_projection: ActionMetricProjectionOverlayResult | None,
618
+ risk_aversion: float,
619
+ diversity_weight: float,
620
+ beam_width: int,
621
+ global_allocation_receipt_sha256: str | None,
622
+ contextual_allocation_contract_sha256: str | None,
623
+ common_candidate_pool_decision_sha256: str | None,
624
+ ) -> str:
625
+ return hashlib.sha256(
626
+ _BOUND_POLICY_DOMAIN
627
+ + _canonical_json(
628
+ {
629
+ "base_definition_sha256": (
630
+ OUTCOME_CONDITIONED_PORTFOLIO_POLICY_DEFINITION_SHA256
631
+ ),
632
+ "optimization_semantics_definition_sha256": (
633
+ plan.request.optimization_semantics.definition_sha256
634
+ ),
635
+ "action_semantics_definition_sha256": (
636
+ plan.request.action_semantics.definition_sha256
637
+ ),
638
+ "partition_policy_sha256": partition_policy.binding_sha256,
639
+ "consequence_calibration_receipt_sha256": (
640
+ None
641
+ if consequence_calibration is None
642
+ else consequence_calibration.receipt_sha256
643
+ ),
644
+ "metric_projection_receipt_sha256": (
645
+ None
646
+ if metric_projection is None
647
+ else metric_projection.projection_receipt_sha256
648
+ ),
649
+ "risk_aversion_hex": risk_aversion.hex(),
650
+ "diversity_weight_hex": diversity_weight.hex(),
651
+ "beam_width": beam_width,
652
+ "global_allocation_receipt_sha256": (global_allocation_receipt_sha256),
653
+ "contextual_allocation_contract_sha256": (
654
+ contextual_allocation_contract_sha256
655
+ ),
656
+ "common_candidate_pool_decision_sha256": (
657
+ common_candidate_pool_decision_sha256
658
+ ),
659
+ }
660
+ )
661
+ ).hexdigest()
662
+
663
+
664
+ def _confidence_bin(value: float) -> ForecastConfidenceBin:
665
+ if type(value) is not float or not math.isfinite(value):
666
+ raise TypeError("forecast confidence must be a finite exact float")
667
+ if value >= 0.75:
668
+ return ForecastConfidenceBin.HIGH
669
+ if value >= 0.4:
670
+ return ForecastConfidenceBin.MEDIUM
671
+ if value > 0.0:
672
+ return ForecastConfidenceBin.LOW
673
+ return ForecastConfidenceBin.UNKNOWN
674
+
675
+
676
+ def outcome_conditioned_selected_predictions(
677
+ *,
678
+ scope: ForecastCalibrationScope,
679
+ wave: object,
680
+ result: object,
681
+ ) -> tuple[ForecastPredictionReceipt, ...]:
682
+ """Decode selected categorical forecasts without integration-specific state."""
683
+
684
+ from agent_evolve.application.portfolio_evolution import (
685
+ PortfolioVariationWaveRequest,
686
+ PortfolioVariationWaveResult,
687
+ )
688
+
689
+ if type(scope) is not ForecastCalibrationScope:
690
+ raise TypeError("scope must be an exact ForecastCalibrationScope")
691
+ scope.revalidate()
692
+ if type(wave) is not PortfolioVariationWaveRequest:
693
+ raise TypeError("wave must be an exact PortfolioVariationWaveRequest")
694
+ wave.__post_init__()
695
+ if type(result) is not PortfolioVariationWaveResult:
696
+ raise TypeError("result must be an exact PortfolioVariationWaveResult")
697
+ result.__post_init__()
698
+ if (
699
+ result.receipt.request_sha256 != wave.selection_request.request_sha256
700
+ or result.selection_decision.decision_sha256 != result.receipt.decision_sha256
701
+ ):
702
+ raise ValueError("portfolio result differs from its selection wave")
703
+ audit = result.supplemental_selection_audit
704
+ if (
705
+ audit is None
706
+ or audit.audit_kind != "outcome_conditioned_expert_portfolio"
707
+ or audit.request_sha256 != wave.selection_request.request_sha256
708
+ or audit.decision_sha256 != result.selection_decision.decision_sha256
709
+ ):
710
+ raise ValueError("portfolio result omits its outcome-conditioned audit")
711
+ payload = thaw_json(audit.payload)
712
+ if type(payload) is not dict: # pragma: no cover - frozen root is closed.
713
+ raise AssertionError("outcome-conditioned audit did not thaw to an object")
714
+ aliases_raw = payload.get("metric_aliases")
715
+ selected_raw = payload.get("selected_forecasts")
716
+ if type(aliases_raw) is not list or type(selected_raw) is not list:
717
+ raise TypeError("outcome-conditioned audit omits forecast decoding data")
718
+ alias_by_target: dict[str, str] = {}
719
+ for row in aliases_raw:
720
+ if type(row) is not dict:
721
+ raise TypeError("metric alias audit rows must be objects")
722
+ values = row
723
+ target_id = values.get("target_metric_id")
724
+ forecast_id = values.get("forecast_metric_id")
725
+ if type(target_id) is not str or type(forecast_id) is not str:
726
+ raise TypeError("metric alias audit row is malformed")
727
+ alias_by_target[target_id] = forecast_id
728
+ selected_confidence: dict[tuple[str, str], float] = {}
729
+ for row in selected_raw:
730
+ if type(row) is not dict:
731
+ raise TypeError("selected forecast audit rows must be objects")
732
+ values = row
733
+ option_id = values.get("option_id")
734
+ metrics = values.get("metric_forecasts")
735
+ if type(option_id) is not str or type(metrics) is not list:
736
+ raise TypeError("selected forecast audit row is malformed")
737
+ for metric in metrics:
738
+ if type(metric) is not dict:
739
+ raise TypeError("selected metric audit row must be an object")
740
+ metric_values = metric
741
+ metric_id = metric_values.get("metric_id")
742
+ confidence_hex = metric_values.get("confidence_hex")
743
+ if type(metric_id) is not str or type(confidence_hex) is not str:
744
+ raise TypeError("selected metric audit row is malformed")
745
+ confidence = float.fromhex(confidence_hex)
746
+ if not math.isfinite(confidence):
747
+ raise ValueError("selected metric confidence is non-finite")
748
+ selected_confidence[(option_id, metric_id)] = confidence
749
+ predictions: list[ForecastPredictionReceipt] = []
750
+ for member in result.selection_decision.members:
751
+ effects = {value.metric_id: value for value in member.effect_predictions}
752
+ for target_metric_id in wave.selection_request.required_metric_ids:
753
+ effect = effects[target_metric_id]
754
+ forecast_metric_id = alias_by_target[target_metric_id]
755
+ confidence = selected_confidence[(member.option_id, forecast_metric_id)]
756
+ predictions.append(
757
+ ForecastPredictionReceipt(
758
+ scope=scope,
759
+ wave_index=wave.generation,
760
+ selector_decision_sha256=(
761
+ result.selection_decision.decision_sha256
762
+ ),
763
+ parent_candidate_identity_sha256=(
764
+ wave.parent.occurrence.configuration_hash
765
+ ),
766
+ option_id=member.option_id,
767
+ option_identity_sha256=member.option_identity_sha256,
768
+ family=member.family,
769
+ metric_id=target_metric_id,
770
+ asserted_direction=effect.direction,
771
+ confidence=_confidence_bin(confidence),
772
+ )
773
+ )
774
+ return tuple(predictions)
775
+
776
+
777
+ def outcome_conditioned_selected_source_ids(
778
+ *,
779
+ wave: object,
780
+ result: object,
781
+ ) -> tuple[str, ...]:
782
+ """Decode evaluated proposal-source arms from sealed finite metadata."""
783
+
784
+ from agent_evolve.application.portfolio_evolution import (
785
+ PortfolioVariationWaveRequest,
786
+ PortfolioVariationWaveResult,
787
+ )
788
+
789
+ if type(wave) is not PortfolioVariationWaveRequest:
790
+ raise TypeError("wave must be an exact PortfolioVariationWaveRequest")
791
+ wave.__post_init__()
792
+ if type(result) is not PortfolioVariationWaveResult:
793
+ raise TypeError("result must be an exact PortfolioVariationWaveResult")
794
+ result.__post_init__()
795
+ if (
796
+ result.receipt.request_sha256 != wave.selection_request.request_sha256
797
+ or result.selection_decision.decision_sha256 != result.receipt.decision_sha256
798
+ ):
799
+ raise ValueError("portfolio result differs from its selection wave")
800
+ return selected_variation_source_ids(
801
+ finite_contract=wave.selection_request.finite_variation_contract,
802
+ selected_option_ids=tuple(
803
+ value.option_id for value in result.selection_decision.members
804
+ ),
805
+ )
806
+
807
+
808
+ def outcome_conditioned_contextual_allocation_realization(
809
+ *,
810
+ allocation: ContextualPortfolioAllocationContract | None,
811
+ wave: object,
812
+ result: object,
813
+ ) -> ContextualPortfolioAllocationRealization | None:
814
+ """Decode exact requested-to-realized source/operator exposure evidence."""
815
+
816
+ from agent_evolve.application.portfolio_evolution import (
817
+ PortfolioVariationWaveRequest,
818
+ PortfolioVariationWaveResult,
819
+ )
820
+
821
+ if type(wave) is not PortfolioVariationWaveRequest:
822
+ raise TypeError("wave must be an exact PortfolioVariationWaveRequest")
823
+ wave.__post_init__()
824
+ if type(result) is not PortfolioVariationWaveResult:
825
+ raise TypeError("result must be an exact PortfolioVariationWaveResult")
826
+ result.__post_init__()
827
+ if (
828
+ result.receipt.request_sha256 != wave.selection_request.request_sha256
829
+ or result.selection_decision.decision_sha256 != result.receipt.decision_sha256
830
+ ):
831
+ raise ValueError("portfolio result differs from its selection wave")
832
+ return contextual_allocation_realization(
833
+ finite_contract=wave.selection_request.finite_variation_contract,
834
+ allocation=allocation,
835
+ selected_option_ids=tuple(
836
+ value.option_id for value in result.selection_decision.members
837
+ ),
838
+ )
839
+
840
+
841
+ @dataclass(slots=True)
842
+ class OutcomeConditionedPortfolioSelectionPolicy:
843
+ """Portable all-action selector implementing the campaign selection port."""
844
+
845
+ forecaster: PartitionedActionForecastPolicy
846
+ optimization_semantics: OptimizationSemantics
847
+ partition_policy: ActionForecastPartitionPolicyBinding
848
+ action_semantics_factory: ActionSemanticsFactory | None = None
849
+ consequence_calibrator: ActionConsequenceCalibrationPolicy | None = None
850
+ metric_projector: ActionMetricProjector | None = None
851
+ wave_action_coordinator: GlobalWaveActionAllocationCoordinator | None = None
852
+ contextual_allocation_provider: ContextualAllocationProvider | None = None
853
+ candidate_pool_provider: CandidatePoolProvider | None = None
854
+ risk_aversion: float = 0.5
855
+ diversity_weight: float = 0.05
856
+ beam_width: int = 256
857
+ require_healthy_forecast: bool = True
858
+ max_memory_options_per_card: int = 16
859
+ max_memory_assignment_trials: int = 128
860
+
861
+ def __post_init__(self) -> None:
862
+ if not callable(getattr(self.forecaster, "forecast_partitioned", None)):
863
+ raise TypeError("forecaster must satisfy PartitionedActionForecastPolicy")
864
+ if type(self.optimization_semantics) is not OptimizationSemantics:
865
+ raise TypeError("optimization_semantics must be exact")
866
+ self.optimization_semantics.__post_init__()
867
+ if type(self.partition_policy) is not ActionForecastPartitionPolicyBinding:
868
+ raise TypeError("partition_policy must be exact")
869
+ self.partition_policy.__post_init__()
870
+ if self.action_semantics_factory is not None and not callable(
871
+ self.action_semantics_factory
872
+ ):
873
+ raise TypeError("action_semantics_factory must be callable or None")
874
+ if self.consequence_calibrator is not None and not isinstance(
875
+ self.consequence_calibrator,
876
+ ActionConsequenceCalibrationPolicy,
877
+ ):
878
+ raise TypeError(
879
+ "consequence_calibrator must satisfy the calibration port or be None"
880
+ )
881
+ if self.metric_projector is not None and not callable(
882
+ getattr(self.metric_projector, "project", None)
883
+ ):
884
+ raise TypeError("metric_projector must expose project or be None")
885
+ if self.wave_action_coordinator is not None and not isinstance(
886
+ self.wave_action_coordinator,
887
+ GlobalWaveActionAllocationCoordinator,
888
+ ):
889
+ raise TypeError(
890
+ "wave_action_coordinator must satisfy the global allocation port"
891
+ )
892
+ if self.contextual_allocation_provider is not None and not callable(
893
+ self.contextual_allocation_provider
894
+ ):
895
+ raise TypeError("contextual_allocation_provider must be callable or None")
896
+ if self.candidate_pool_provider is not None and not callable(
897
+ self.candidate_pool_provider
898
+ ):
899
+ raise TypeError("candidate_pool_provider must be callable or None")
900
+ for name in ("risk_aversion", "diversity_weight"):
901
+ value = getattr(self, name)
902
+ if type(value) is not float or not math.isfinite(value) or value < 0.0:
903
+ raise ValueError(f"{name} must be a finite non-negative float")
904
+ for name in (
905
+ "beam_width",
906
+ "max_memory_options_per_card",
907
+ "max_memory_assignment_trials",
908
+ ):
909
+ value = getattr(self, name)
910
+ if type(value) is not int or value <= 0:
911
+ raise ValueError(f"{name} must be a positive exact integer")
912
+ if type(self.require_healthy_forecast) is not bool:
913
+ raise TypeError("require_healthy_forecast must be exact bool")
914
+
915
+ def render(self, request: PortfolioSelectionRequest) -> str:
916
+ """Render the logical request audited above its physical block calls."""
917
+
918
+ self.__post_init__()
919
+ if type(request) is not PortfolioSelectionRequest:
920
+ raise TypeError("request must be an exact PortfolioSelectionRequest")
921
+ request.__post_init__()
922
+ return (
923
+ "OUTCOME-CONDITIONED ALL-ACTION PORTFOLIO REQUEST\n"
924
+ "The model forecasts every sealed action in bounded physical blocks; "
925
+ "trusted code performs hard-feasible set allocation.\n"
926
+ + json.dumps(
927
+ {
928
+ "selection_request": request.to_record(),
929
+ "partition_policy": self.partition_policy.to_record(),
930
+ "base_policy_definition_sha256": (
931
+ OUTCOME_CONDITIONED_PORTFOLIO_POLICY_DEFINITION_SHA256
932
+ ),
933
+ },
934
+ allow_nan=False,
935
+ ensure_ascii=True,
936
+ separators=(",", ":"),
937
+ sort_keys=True,
938
+ )
939
+ )
940
+
941
+ async def select(
942
+ self,
943
+ request: PortfolioSelectionRequest,
944
+ ) -> PortfolioSelectionResult:
945
+ self.__post_init__()
946
+ if type(request) is not PortfolioSelectionRequest:
947
+ raise TypeError("request must be an exact PortfolioSelectionRequest")
948
+ request.__post_init__()
949
+ phase = resolve_campaign_search_phase_context(request.context)
950
+ contextual_allocation = (
951
+ None
952
+ if self.contextual_allocation_provider is None
953
+ else self.contextual_allocation_provider(request)
954
+ )
955
+ if contextual_allocation is not None:
956
+ if type(contextual_allocation) is not (
957
+ ContextualPortfolioAllocationContract
958
+ ):
959
+ raise TypeError(
960
+ "contextual allocation provider returned a foreign contract"
961
+ )
962
+ contextual_allocation.__post_init__()
963
+ if (
964
+ contextual_allocation.campaign_generation != phase.campaign_generation
965
+ or contextual_allocation.evaluation_slots != request.portfolio_size
966
+ ):
967
+ raise ValueError(
968
+ "contextual allocation differs from the selection wave"
969
+ )
970
+ candidate_pool = (
971
+ None
972
+ if self.candidate_pool_provider is None
973
+ else self.candidate_pool_provider(request)
974
+ )
975
+ forecast_contract, forecast_universe_projection = (
976
+ _forecast_contract_projection(request, candidate_pool)
977
+ )
978
+ exact_arm_count_constraints = contextual_action_arm_count_constraints(
979
+ finite_contract=forecast_contract,
980
+ allocation=contextual_allocation,
981
+ portfolio_size=request.portfolio_size,
982
+ )
983
+ action_semantics = (
984
+ None
985
+ if self.action_semantics_factory is None
986
+ else self.action_semantics_factory(forecast_contract)
987
+ )
988
+ plan = build_target_conditioned_action_forecast_plan(
989
+ selection_request=request,
990
+ optimization_semantics=self.optimization_semantics,
991
+ call_id=_forecast_call_id(request),
992
+ forecast_contract=forecast_contract,
993
+ action_semantics=action_semantics,
994
+ evidence_mode=_evidence_mode(request),
995
+ max_output_tokens=request.max_output_tokens,
996
+ temperature=request.temperature,
997
+ )
998
+ if (
999
+ contextual_allocation is not None
1000
+ and contextual_allocation.slice_id != plan.campaign_target.lane_id
1001
+ ):
1002
+ raise ValueError("contextual allocation differs from the target lane")
1003
+ layout = build_action_forecast_partition_layout(
1004
+ plan.request,
1005
+ self.partition_policy,
1006
+ )
1007
+ started_ns = time.perf_counter_ns()
1008
+ partitioned = await self.forecaster.forecast_partitioned(
1009
+ plan.request,
1010
+ layout,
1011
+ )
1012
+ wall_latency_ns = time.perf_counter_ns() - started_ns
1013
+ physical_telemetry = tuple(
1014
+ value.telemetry
1015
+ for value in partitioned.block_results
1016
+ if value.telemetry is not None
1017
+ )
1018
+ telemetry = _aggregate_telemetry(
1019
+ physical_telemetry,
1020
+ wall_latency_ns=wall_latency_ns,
1021
+ )
1022
+ health = assess_resolved_action_forecast_health(
1023
+ plan.request,
1024
+ partitioned.forecasts,
1025
+ member_id="outcome_conditioned_selector",
1026
+ health_policy=lenient_action_forecast_health_policy(),
1027
+ )
1028
+ consequence_calibration = None
1029
+ metric_projection = None
1030
+ exact_projections = None
1031
+ decision_forecasts = partitioned.forecasts
1032
+ if self.consequence_calibrator is not None:
1033
+ consequence_calibration = self.consequence_calibrator.calibrate(
1034
+ request=plan.request,
1035
+ forecasts=partitioned.forecasts,
1036
+ cutoff_wave_index_exclusive=phase.campaign_generation,
1037
+ metric_aliases=plan.aliases,
1038
+ )
1039
+ if type(consequence_calibration) is not ActionConsequenceCalibrationResult:
1040
+ raise TypeError("consequence calibrator returned a foreign result type")
1041
+ decision_forecasts = consequence_calibration.forecasts
1042
+ if self.metric_projector is not None:
1043
+ exact_projections = self.metric_projector.project(plan.request)
1044
+ metric_projection = apply_exact_action_metric_projections(
1045
+ request=plan.request,
1046
+ forecasts=decision_forecasts,
1047
+ projections=exact_projections,
1048
+ )
1049
+ decision_forecasts = metric_projection.forecasts
1050
+ health_passes, health_resolution = _resolve_model_authority_health(
1051
+ request_forecasts=partitioned.forecasts,
1052
+ health=health,
1053
+ exact_projections=exact_projections,
1054
+ )
1055
+ if self.require_healthy_forecast and not health_passes:
1056
+ failed = health_resolution["unresolved_failed_metric_ids"]
1057
+ raise ValueError(
1058
+ "all-action forecast failed its model-authority health gate; "
1059
+ f"unresolved_metrics={failed}"
1060
+ )
1061
+
1062
+ utility_mode, target_kind = _identified_outcome_conditioned_acquisition(
1063
+ residual_cell_identified=plan.residual_cell is not None,
1064
+ terminal=phase.terminal,
1065
+ )
1066
+ preference = _preference_scores(plan, decision_forecasts)
1067
+ memory_candidates = _memory_assignment_candidates(
1068
+ request,
1069
+ preference=preference,
1070
+ max_options_per_card=self.max_memory_options_per_card,
1071
+ max_assignments=self.max_memory_assignment_trials,
1072
+ )
1073
+ global_allocation: GlobalWaveActionAllocationLaneResult | None = None
1074
+ role_slots: RoleSlots | None = None
1075
+ if self.wave_action_coordinator is not None:
1076
+ global_allocation = await self.wave_action_coordinator.allocate(
1077
+ GlobalWaveActionAllocationLane(
1078
+ generation=phase.campaign_generation,
1079
+ request=request,
1080
+ plan=plan,
1081
+ forecasts=decision_forecasts,
1082
+ utility_mode=utility_mode,
1083
+ target_kind=target_kind,
1084
+ memory_assignments=tuple(
1085
+ tuple(sorted(value.items())) for value in memory_candidates
1086
+ ),
1087
+ risk_aversion=self.risk_aversion,
1088
+ diversity_weight=self.diversity_weight,
1089
+ beam_width=self.beam_width,
1090
+ contextual_allocation=contextual_allocation,
1091
+ )
1092
+ )
1093
+ allocation = global_allocation.allocation
1094
+ card_by_option = dict(global_allocation.memory_assignment)
1095
+ role_slots = global_allocation.role_slots
1096
+ else:
1097
+ best: tuple[ActionAllocationResult, dict[str, str]] | None = None
1098
+ failures: list[str] = []
1099
+ for card_by_option in memory_candidates:
1100
+ required = tuple(
1101
+ sorted(
1102
+ {
1103
+ *request.candidate_pool_required_option_ids,
1104
+ *card_by_option,
1105
+ }
1106
+ )
1107
+ )
1108
+ try:
1109
+ allocation = allocate_target_conditioned_actions(
1110
+ plan=plan,
1111
+ forecasts=decision_forecasts,
1112
+ portfolio_size=request.portfolio_size,
1113
+ risk_aversion=self.risk_aversion,
1114
+ diversity_weight=self.diversity_weight,
1115
+ beam_width=self.beam_width,
1116
+ utility_mode=utility_mode,
1117
+ required_option_ids=required,
1118
+ exact_arm_count_constraints=(exact_arm_count_constraints),
1119
+ minimum_single_path_interventions=(
1120
+ 0
1121
+ if contextual_allocation is None
1122
+ else contextual_allocation.minimum_single_path_interventions
1123
+ ),
1124
+ minimum_disjoint_parent_patch_pairs=(
1125
+ 0
1126
+ if contextual_allocation is None
1127
+ else contextual_allocation.minimum_disjoint_parent_patch_pairs
1128
+ ),
1129
+ )
1130
+ except (TypeError, ValueError, RuntimeError) as error:
1131
+ failures.append(f"{type(error).__name__}:{error}")
1132
+ continue
1133
+ if best is None or allocation.decision.final_score.total_utility > (
1134
+ best[0].decision.final_score.total_utility
1135
+ ):
1136
+ best = allocation, card_by_option
1137
+ if best is None:
1138
+ detail = "; ".join(failures[:4])
1139
+ raise ValueError(
1140
+ "no hard-feasible outcome-conditioned memory assignment"
1141
+ + ("; " + detail if detail else "")
1142
+ )
1143
+ allocation, card_by_option = best
1144
+ selected_support, proposed_dose, evaluated_dose = _memory_assessments(
1145
+ request,
1146
+ allocation=allocation,
1147
+ card_by_option=card_by_option,
1148
+ preference=preference,
1149
+ )
1150
+ selected_required_option_ids = tuple(
1151
+ sorted(
1152
+ {
1153
+ *request.candidate_pool_required_option_ids,
1154
+ *card_by_option,
1155
+ }
1156
+ )
1157
+ )
1158
+
1159
+ forecast_by_id = {
1160
+ value.option_id: value for value in decision_forecasts.forecasts
1161
+ }
1162
+ alias_by_target = {
1163
+ value.target_metric_id: value.forecast_metric_id for value in plan.aliases
1164
+ }
1165
+ role_audit = (
1166
+ ()
1167
+ if utility_mode != "role_factorized"
1168
+ else audit_target_conditioned_role_allocation(
1169
+ plan=plan,
1170
+ forecasts=decision_forecasts,
1171
+ decision=allocation.decision,
1172
+ eligible_option_ids=(
1173
+ None
1174
+ if global_allocation is None
1175
+ else global_allocation.eligible_option_ids
1176
+ ),
1177
+ role_slots=role_slots,
1178
+ exact_arm_count_constraints=exact_arm_count_constraints,
1179
+ required_option_ids=selected_required_option_ids,
1180
+ minimum_single_path_interventions=(
1181
+ 0
1182
+ if contextual_allocation is None
1183
+ else contextual_allocation.minimum_single_path_interventions
1184
+ ),
1185
+ minimum_disjoint_parent_patch_pairs=(
1186
+ 0
1187
+ if contextual_allocation is None
1188
+ else contextual_allocation.minimum_disjoint_parent_patch_pairs
1189
+ ),
1190
+ )
1191
+ )
1192
+ role_by_option: dict[str, str] = {}
1193
+ if role_audit:
1194
+ p50 = role_audit[1]
1195
+ role_by_option = {
1196
+ value.option_id: value.role.value for value in p50.assignments
1197
+ }
1198
+
1199
+ drafts: list[PortfolioMemberDraft] = []
1200
+ for member in allocation.decision.members:
1201
+ forecast = forecast_by_id[member.option_id]
1202
+ supporting = selected_support[member.option_id]
1203
+ if request.memory_dose_contract is None:
1204
+ supporting = _selected_card_keys(forecast)
1205
+ if request.require_supporting_cards and not supporting:
1206
+ raise ValueError(
1207
+ "grounded all-action selection produced an uncited member"
1208
+ )
1209
+ metrics = {value.metric_id: value for value in forecast.metric_forecasts}
1210
+ effects = tuple(
1211
+ MetricEffectPrediction(
1212
+ metric_id=target_metric_id,
1213
+ direction=_direction(metrics[alias_by_target[target_metric_id]]),
1214
+ )
1215
+ for target_metric_id in request.required_metric_ids
1216
+ )
1217
+ fallback_role = (
1218
+ "directional_bootstrap"
1219
+ if utility_mode == "target_closure"
1220
+ else "terminal_exploit"
1221
+ )
1222
+ role = role_by_option.get(member.option_id, fallback_role)
1223
+ drafts.append(
1224
+ PortfolioMemberDraft(
1225
+ option_id=member.option_id,
1226
+ supporting_card_keys=supporting,
1227
+ effect_predictions=effects,
1228
+ design_rationale=(
1229
+ f"Trusted outcome-conditioned allocation role={role}; "
1230
+ f"utility={utility_mode}; rank={member.rank}; "
1231
+ "numeric consequences were forecast for the sealed action "
1232
+ "and selection was performed by hard-feasible trusted code."
1233
+ ),
1234
+ )
1235
+ )
1236
+
1237
+ policy_definition_sha256 = _bound_policy_definition(
1238
+ plan=plan,
1239
+ partition_policy=self.partition_policy,
1240
+ consequence_calibration=consequence_calibration,
1241
+ metric_projection=metric_projection,
1242
+ risk_aversion=self.risk_aversion,
1243
+ diversity_weight=self.diversity_weight,
1244
+ beam_width=self.beam_width,
1245
+ global_allocation_receipt_sha256=(
1246
+ None
1247
+ if global_allocation is None
1248
+ else global_allocation.global_receipt_sha256
1249
+ ),
1250
+ contextual_allocation_contract_sha256=(
1251
+ None
1252
+ if contextual_allocation is None
1253
+ else contextual_allocation.contract_sha256
1254
+ ),
1255
+ common_candidate_pool_decision_sha256=(
1256
+ None if candidate_pool is None else candidate_pool.decision_sha256
1257
+ ),
1258
+ )
1259
+ decision = resolve_ranked_portfolio_decision(
1260
+ request,
1261
+ tuple(drafts),
1262
+ policy_id=OUTCOME_CONDITIONED_PORTFOLIO_POLICY_ID,
1263
+ policy_version=OUTCOME_CONDITIONED_PORTFOLIO_POLICY_VERSION,
1264
+ policy_definition_sha256=policy_definition_sha256,
1265
+ memory_dose_assessment=evaluated_dose,
1266
+ )
1267
+ selected_ids = {value.option_id for value in allocation.decision.members}
1268
+ contextual_realization = contextual_allocation_realization(
1269
+ finite_contract=request.finite_variation_contract,
1270
+ allocation=contextual_allocation,
1271
+ selected_option_ids=tuple(
1272
+ value.option_id for value in allocation.decision.members
1273
+ ),
1274
+ )
1275
+ selected_forecasts = tuple(
1276
+ value.to_record()
1277
+ for value in decision_forecasts.forecasts
1278
+ if value.option_id in selected_ids
1279
+ )
1280
+ audit = PortfolioSelectionSupplementalAudit(
1281
+ audit_kind="outcome_conditioned_expert_portfolio",
1282
+ request_sha256=request.request_sha256,
1283
+ decision_sha256=decision.decision_sha256,
1284
+ payload=_object(
1285
+ {
1286
+ "schema_version": 2,
1287
+ "phase": phase.to_record(),
1288
+ "evidence_mode": plan.request.evidence_mode.value,
1289
+ "forecast_request_sha256": plan.request.request_sha256,
1290
+ "forecast_universe_projection": forecast_universe_projection,
1291
+ "proposal_topology": project_finite_contract_proposal_topology(
1292
+ source_contract=request.finite_variation_contract,
1293
+ proposal_contract=forecast_contract,
1294
+ ),
1295
+ "partitioned_forecast": partitioned.to_record(),
1296
+ "physical_call_count": len(partitioned.block_results),
1297
+ "physical_call_telemetry": [
1298
+ _telemetry_record(value) for value in physical_telemetry
1299
+ ],
1300
+ "forecast_health": health.to_record(),
1301
+ "forecast_health_authority_resolution": health_resolution,
1302
+ "raw_forecast_receipt_sha256": (
1303
+ partitioned.forecasts.receipt_sha256
1304
+ ),
1305
+ "decision_forecast_receipt_sha256": (
1306
+ decision_forecasts.receipt_sha256
1307
+ ),
1308
+ "consequence_calibration": (
1309
+ None
1310
+ if consequence_calibration is None
1311
+ else consequence_calibration.to_record()
1312
+ ),
1313
+ "metric_projection": (
1314
+ None
1315
+ if metric_projection is None
1316
+ else metric_projection.to_record()
1317
+ ),
1318
+ "utility_mode": utility_mode,
1319
+ "target_kind": target_kind,
1320
+ "allocation": allocation.decision.to_record(),
1321
+ "global_wave_allocation": _plain_global_allocation_audit(
1322
+ global_allocation
1323
+ ),
1324
+ "contextual_allocation": (
1325
+ None
1326
+ if contextual_allocation is None
1327
+ else contextual_allocation.to_record()
1328
+ ),
1329
+ "contextual_allocation_realization": (
1330
+ None
1331
+ if contextual_realization is None
1332
+ else contextual_realization.to_record()
1333
+ ),
1334
+ "role_assignment_audits": [
1335
+ value.to_record() for value in role_audit
1336
+ ],
1337
+ "selected_forecasts": list(selected_forecasts),
1338
+ "metric_aliases": [
1339
+ {
1340
+ "target_metric_id": value.target_metric_id,
1341
+ "forecast_metric_id": value.forecast_metric_id,
1342
+ }
1343
+ for value in plan.aliases
1344
+ ],
1345
+ "required_option_ids": list(selected_required_option_ids),
1346
+ "memory_card_by_option": dict(sorted(card_by_option.items())),
1347
+ "proposed_memory_dose_assessment": (
1348
+ None if proposed_dose is None else proposed_dose.to_record()
1349
+ ),
1350
+ "evaluated_memory_dose_assessment": (
1351
+ None if evaluated_dose is None else evaluated_dose.to_record()
1352
+ ),
1353
+ "policy_definition_sha256": policy_definition_sha256,
1354
+ }
1355
+ ),
1356
+ )
1357
+ return PortfolioSelectionResult(
1358
+ decision=decision,
1359
+ telemetry=telemetry,
1360
+ supplemental_audit=audit,
1361
+ )
1362
+
1363
+
1364
+ __all__ = [
1365
+ "OUTCOME_CONDITIONED_PORTFOLIO_POLICY_DEFINITION_SHA256",
1366
+ "OUTCOME_CONDITIONED_PORTFOLIO_POLICY_ID",
1367
+ "OUTCOME_CONDITIONED_PORTFOLIO_POLICY_VERSION",
1368
+ "ActionSemanticsFactory",
1369
+ "ContextualAllocationProvider",
1370
+ "OutcomeConditionedPortfolioSelectionPolicy",
1371
+ "outcome_conditioned_contextual_allocation_realization",
1372
+ "outcome_conditioned_selected_predictions",
1373
+ "outcome_conditioned_selected_source_ids",
1374
+ ]