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,954 @@
1
+ """Outcome-blind composition of heterogeneous action consequence scores.
2
+
3
+ The optimizer must not silently treat one fallible consequence estimator as
4
+ ground truth. This module gives the application core a workload-neutral seam
5
+ for composing multiple pre-evaluation score authorities:
6
+
7
+ * every scorer authenticates the exact residual request and sealed proposal
8
+ universe that it inspected;
9
+ * scorers may be learned models, calibrated proposer forecasts, numerical
10
+ acquisitions, or deterministic audit policies;
11
+ * the core allocates an explicit quota to each scorer and de-duplicates exact
12
+ materialized phenotypes while walking that scorer's ranking; and
13
+ * any evaluator capacity not nominated by the portfolio remains available to
14
+ the downstream empirical broker.
15
+
16
+ Scores are intentionally opaque. Workload adapters own feature projection and
17
+ model fitting; this core owns only information-boundary validation, identity,
18
+ quota composition, and durable evidence. No current candidate outcome is
19
+ available at this boundary.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import asyncio
25
+ import hashlib
26
+ import json
27
+ import math
28
+ import re
29
+ from dataclasses import dataclass, field
30
+ from typing import ClassVar, Protocol, runtime_checkable
31
+
32
+ from agent_evolve.application.materialized_action_broker import (
33
+ MaterializedActionAllocationRequirement,
34
+ )
35
+ from agent_evolve.application.residual_portfolio_evolution import (
36
+ MaterializedActionProposalBatch,
37
+ ResidualPortfolioDecisionRequest,
38
+ )
39
+ from agent_evolve.domain.patch import require_sha256
40
+ from agent_evolve.domain.typed_json import freeze_json
41
+ from agent_evolve.ports.hard_feasibility import (
42
+ HardFeasibilityDecision,
43
+ HardFeasibilityPort,
44
+ HardFeasibilityRequest,
45
+ HardFeasibilityVerdict,
46
+ assess_hard_feasibility,
47
+ hard_feasibility_decision_batch_sha256,
48
+ validate_hard_feasibility_port,
49
+ )
50
+
51
+
52
+ PREQUENTIAL_SCORE_PORTFOLIO_POLICY_ID = (
53
+ "prequential_quota_score_portfolio_allocator"
54
+ )
55
+ PREQUENTIAL_SCORE_PORTFOLIO_POLICY_VERSION = 1
56
+ PREQUENTIAL_SCORE_PORTFOLIO_POLICY_DEFINITION_SHA256 = hashlib.sha256(
57
+ b"agent-evolve:prequential-quota-score-portfolio:v1;"
58
+ b"input=prior-cutoff-request+complete-sealed-proposal-union;"
59
+ b"score-semantics=opaque-injected-authorities;"
60
+ b"composition=canonical-round-robin-explicit-quota;"
61
+ b"within-authority=descending-finite-score+action-sha256-tie-break;"
62
+ b"collision=skip-exact-materialized-phenotype-and-continue;"
63
+ b"unreserved-capacity=downstream-empirical-broker;"
64
+ b"candidate-outcomes=false;async=true;"
65
+ b"workload-model-provider-branches=false"
66
+ ).hexdigest()
67
+
68
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
69
+ _SCORE_BATCH_DOMAIN = b"agent-evolve:materialized-action-score-batch:v1\x00"
70
+ _RELIABILITY_EVIDENCE_DOMAIN = (
71
+ b"agent-evolve:materialized-action-score-reliability:v1\x00"
72
+ )
73
+ _ADAPTIVE_POLICY_DOMAIN = (
74
+ b"agent-evolve:reliability-adaptive-score-portfolio:v1\x00"
75
+ )
76
+ RELIABILITY_ADAPTIVE_SCORE_PORTFOLIO_POLICY_ID = (
77
+ "reliability_adaptive_score_portfolio_allocator"
78
+ )
79
+ RELIABILITY_ADAPTIVE_SCORE_PORTFOLIO_POLICY_VERSION = 2
80
+
81
+
82
+ def _canonical_json(value: object) -> bytes:
83
+ return json.dumps(
84
+ value,
85
+ allow_nan=False,
86
+ ensure_ascii=True,
87
+ separators=(",", ":"),
88
+ sort_keys=True,
89
+ ).encode("ascii", errors="strict")
90
+
91
+
92
+ def _hash(domain: bytes, value: object) -> str:
93
+ return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
94
+
95
+
96
+ def _require_token(value: str, *, name: str) -> None:
97
+ if type(value) is not str or _TOKEN.fullmatch(value) is None:
98
+ raise ValueError(f"{name} must use the closed token grammar")
99
+
100
+
101
+ def _scorer_identity(
102
+ scorer: "MaterializedActionScorePort",
103
+ ) -> tuple[str, int, str]:
104
+ if not isinstance(scorer, MaterializedActionScorePort):
105
+ raise TypeError("scorer must implement MaterializedActionScorePort")
106
+ identity = (
107
+ getattr(scorer, "scorer_id", None),
108
+ getattr(scorer, "scorer_version", None),
109
+ getattr(scorer, "definition_sha256", None),
110
+ )
111
+ _require_token(identity[0], name="scorer_id")
112
+ if type(identity[1]) is not int or identity[1] <= 0:
113
+ raise ValueError("scorer_version must be positive")
114
+ require_sha256(identity[2], "scorer definition_sha256")
115
+ return identity # type: ignore[return-value]
116
+
117
+
118
+ @dataclass(frozen=True, slots=True)
119
+ class MaterializedActionScore:
120
+ """One opaque, finite, pre-evaluation score for one materialized action."""
121
+
122
+ action_sha256: str
123
+ value: float
124
+
125
+ def __post_init__(self) -> None:
126
+ require_sha256(self.action_sha256, "action_sha256")
127
+ if type(self.value) is not float or not math.isfinite(self.value):
128
+ raise ValueError("score value must be a finite exact float")
129
+
130
+ def to_record(self) -> dict[str, object]:
131
+ self.__post_init__()
132
+ return {
133
+ "action_sha256": self.action_sha256,
134
+ "value_hex": self.value.hex(),
135
+ }
136
+
137
+
138
+ @dataclass(frozen=True, slots=True)
139
+ class MaterializedActionScoreBatch:
140
+ """Authenticated complete scoring of one sealed proposal universe."""
141
+
142
+ scorer_id: str
143
+ scorer_version: int
144
+ scorer_definition_sha256: str
145
+ residual_request_sha256: str
146
+ proposal_sha256s: tuple[str, ...]
147
+ scores: tuple[MaterializedActionScore, ...]
148
+ candidate_outcomes_observed: bool
149
+ evidence_sha256: str
150
+ batch_sha256: str = field(init=False)
151
+
152
+ def __post_init__(self) -> None:
153
+ _require_token(self.scorer_id, name="scorer_id")
154
+ if type(self.scorer_version) is not int or self.scorer_version <= 0:
155
+ raise ValueError("scorer_version must be positive")
156
+ require_sha256(
157
+ self.scorer_definition_sha256,
158
+ "scorer_definition_sha256",
159
+ )
160
+ require_sha256(
161
+ self.residual_request_sha256,
162
+ "residual_request_sha256",
163
+ )
164
+ if (
165
+ type(self.proposal_sha256s) is not tuple
166
+ or not self.proposal_sha256s
167
+ or self.proposal_sha256s
168
+ != tuple(sorted(set(self.proposal_sha256s)))
169
+ ):
170
+ raise ValueError("proposal_sha256s must be non-empty and canonical")
171
+ for value in self.proposal_sha256s:
172
+ require_sha256(value, "proposal_sha256")
173
+ if type(self.scores) is not tuple or not self.scores:
174
+ raise ValueError("scores must be a non-empty exact tuple")
175
+ for value in self.scores:
176
+ if type(value) is not MaterializedActionScore:
177
+ raise TypeError("scores must contain exact score values")
178
+ value.__post_init__()
179
+ score_actions = tuple(value.action_sha256 for value in self.scores)
180
+ if score_actions != tuple(sorted(set(score_actions))):
181
+ raise ValueError("scores must cover unique actions canonically")
182
+ if type(self.candidate_outcomes_observed) is not bool:
183
+ raise TypeError("candidate_outcomes_observed must be an exact bool")
184
+ if self.candidate_outcomes_observed:
185
+ raise ValueError("prequential scores cannot observe current outcomes")
186
+ require_sha256(self.evidence_sha256, "evidence_sha256")
187
+ object.__setattr__(
188
+ self,
189
+ "batch_sha256",
190
+ _hash(_SCORE_BATCH_DOMAIN, self._unsigned_record()),
191
+ )
192
+
193
+ def _unsigned_record(self) -> dict[str, object]:
194
+ return {
195
+ "schema_version": 1,
196
+ "scorer": {
197
+ "scorer_id": self.scorer_id,
198
+ "scorer_version": self.scorer_version,
199
+ "definition_sha256": self.scorer_definition_sha256,
200
+ },
201
+ "residual_request_sha256": self.residual_request_sha256,
202
+ "proposal_sha256s": list(self.proposal_sha256s),
203
+ "scores": [value.to_record() for value in self.scores],
204
+ "candidate_outcomes_observed": self.candidate_outcomes_observed,
205
+ "evidence_sha256": self.evidence_sha256,
206
+ }
207
+
208
+ def to_record(self) -> dict[str, object]:
209
+ self.__post_init__()
210
+ return {**self._unsigned_record(), "batch_sha256": self.batch_sha256}
211
+
212
+
213
+ @runtime_checkable
214
+ class MaterializedActionScorePort(Protocol):
215
+ """Score a complete sealed population using strictly prior evidence."""
216
+
217
+ scorer_id: str
218
+ scorer_version: int
219
+ definition_sha256: str
220
+
221
+ async def score(
222
+ self,
223
+ request: ResidualPortfolioDecisionRequest,
224
+ proposals: tuple[MaterializedActionProposalBatch, ...],
225
+ ) -> MaterializedActionScoreBatch: ...
226
+
227
+
228
+ @dataclass(frozen=True, slots=True)
229
+ class MaterializedActionScoreReliabilityEvidence:
230
+ """Pre-evaluation authority calibration for one scorer and request."""
231
+
232
+ scorer_id: str
233
+ scorer_version: int
234
+ scorer_definition_sha256: str
235
+ residual_request_sha256: str
236
+ component_authorities: tuple[tuple[str, float], ...]
237
+ overall_reliability: float
238
+ candidate_outcomes_observed: bool
239
+ source_evidence_sha256: str
240
+ evidence_sha256: str = field(init=False)
241
+
242
+ def __post_init__(self) -> None:
243
+ _require_token(self.scorer_id, name="scorer_id")
244
+ if type(self.scorer_version) is not int or self.scorer_version <= 0:
245
+ raise ValueError("scorer_version must be positive")
246
+ require_sha256(
247
+ self.scorer_definition_sha256,
248
+ "scorer_definition_sha256",
249
+ )
250
+ require_sha256(
251
+ self.residual_request_sha256,
252
+ "residual_request_sha256",
253
+ )
254
+ if (
255
+ type(self.component_authorities) is not tuple
256
+ or not self.component_authorities
257
+ or tuple(value[0] for value in self.component_authorities)
258
+ != tuple(
259
+ sorted(
260
+ {value[0] for value in self.component_authorities}
261
+ )
262
+ )
263
+ ):
264
+ raise ValueError(
265
+ "component_authorities must be non-empty and canonical"
266
+ )
267
+ for component_id, authority in self.component_authorities:
268
+ _require_token(component_id, name="reliability component")
269
+ if (
270
+ type(authority) is not float
271
+ or not math.isfinite(authority)
272
+ or not 0.0 <= authority <= 1.0
273
+ ):
274
+ raise ValueError("component authority must lie in [0, 1]")
275
+ if (
276
+ type(self.overall_reliability) is not float
277
+ or not math.isfinite(self.overall_reliability)
278
+ or not 0.0 <= self.overall_reliability <= 1.0
279
+ ):
280
+ raise ValueError("overall_reliability must lie in [0, 1]")
281
+ if self.overall_reliability != min(
282
+ value for _, value in self.component_authorities
283
+ ):
284
+ raise ValueError(
285
+ "overall reliability must be the minimum component authority"
286
+ )
287
+ if type(self.candidate_outcomes_observed) is not bool:
288
+ raise TypeError(
289
+ "candidate_outcomes_observed must be an exact bool"
290
+ )
291
+ if self.candidate_outcomes_observed:
292
+ raise ValueError(
293
+ "score reliability cannot observe current outcomes"
294
+ )
295
+ require_sha256(
296
+ self.source_evidence_sha256,
297
+ "source_evidence_sha256",
298
+ )
299
+ object.__setattr__(
300
+ self,
301
+ "evidence_sha256",
302
+ _hash(_RELIABILITY_EVIDENCE_DOMAIN, self._unsigned_record()),
303
+ )
304
+
305
+ def _unsigned_record(self) -> dict[str, object]:
306
+ return {
307
+ "schema_version": 1,
308
+ "scorer": {
309
+ "scorer_id": self.scorer_id,
310
+ "scorer_version": self.scorer_version,
311
+ "definition_sha256": self.scorer_definition_sha256,
312
+ },
313
+ "residual_request_sha256": self.residual_request_sha256,
314
+ "component_authorities": {
315
+ component_id: authority.hex()
316
+ for component_id, authority in self.component_authorities
317
+ },
318
+ "overall_reliability_hex": self.overall_reliability.hex(),
319
+ "candidate_outcomes_observed": (
320
+ self.candidate_outcomes_observed
321
+ ),
322
+ "source_evidence_sha256": self.source_evidence_sha256,
323
+ }
324
+
325
+ def to_record(self) -> dict[str, object]:
326
+ self.__post_init__()
327
+ return {
328
+ **self._unsigned_record(),
329
+ "evidence_sha256": self.evidence_sha256,
330
+ }
331
+
332
+
333
+ @runtime_checkable
334
+ class MaterializedActionScoreReliabilityPort(Protocol):
335
+ """Expose authenticated prior-only reliability after scoring a batch."""
336
+
337
+ scorer_id: str
338
+ scorer_version: int
339
+ definition_sha256: str
340
+
341
+ def reliability(
342
+ self,
343
+ residual_request_sha256: str,
344
+ component_ids: tuple[str, ...],
345
+ ) -> MaterializedActionScoreReliabilityEvidence: ...
346
+
347
+
348
+ @dataclass(frozen=True, slots=True)
349
+ class PrequentialQuotaScorePortfolioPolicy:
350
+ """Nominate a phenotype-unique quota from each independent score lane."""
351
+
352
+ scorers: tuple[MaterializedActionScorePort, ...]
353
+ scorer_quotas: tuple[tuple[str, int], ...]
354
+
355
+ policy_id: ClassVar[str] = PREQUENTIAL_SCORE_PORTFOLIO_POLICY_ID
356
+ policy_version: ClassVar[int] = PREQUENTIAL_SCORE_PORTFOLIO_POLICY_VERSION
357
+ definition_sha256: ClassVar[str] = (
358
+ PREQUENTIAL_SCORE_PORTFOLIO_POLICY_DEFINITION_SHA256
359
+ )
360
+
361
+ def __post_init__(self) -> None:
362
+ if type(self.scorers) is not tuple or not self.scorers:
363
+ raise ValueError("scorers must be a non-empty exact tuple")
364
+ identities = tuple(_scorer_identity(value) for value in self.scorers)
365
+ scorer_ids = tuple(value[0] for value in identities)
366
+ if scorer_ids != tuple(sorted(set(scorer_ids))):
367
+ raise ValueError("scorers must use canonical unique IDs")
368
+ if (
369
+ type(self.scorer_quotas) is not tuple
370
+ or not self.scorer_quotas
371
+ ):
372
+ raise ValueError("scorer_quotas must be a non-empty exact tuple")
373
+ quota_ids: list[str] = []
374
+ for scorer_id, quota in self.scorer_quotas:
375
+ _require_token(scorer_id, name="quota scorer_id")
376
+ if type(quota) is not int or quota <= 0:
377
+ raise ValueError("every scorer quota must be positive")
378
+ quota_ids.append(scorer_id)
379
+ if tuple(quota_ids) != tuple(sorted(set(quota_ids))):
380
+ raise ValueError("scorer_quotas must use canonical unique IDs")
381
+ if tuple(quota_ids) != scorer_ids:
382
+ raise ValueError("scorer_quotas must exactly cover scorers")
383
+ _require_token(self.policy_id, name="policy_id")
384
+ if type(self.policy_version) is not int or self.policy_version <= 0:
385
+ raise ValueError("policy_version must be positive")
386
+ require_sha256(self.definition_sha256, "definition_sha256")
387
+
388
+ async def require(
389
+ self,
390
+ request: ResidualPortfolioDecisionRequest,
391
+ proposals: tuple[MaterializedActionProposalBatch, ...],
392
+ ) -> MaterializedActionAllocationRequirement:
393
+ self.__post_init__()
394
+ if type(request) is not ResidualPortfolioDecisionRequest:
395
+ raise TypeError("request must be exact")
396
+ request.__post_init__()
397
+ if type(proposals) is not tuple or not proposals:
398
+ raise ValueError("proposals must be a non-empty exact tuple")
399
+ for proposal in proposals:
400
+ if type(proposal) is not MaterializedActionProposalBatch:
401
+ raise TypeError("proposals must contain exact batches")
402
+ proposal.__post_init__()
403
+ proposal.require_request(request)
404
+
405
+ quota_total = sum(value for _, value in self.scorer_quotas)
406
+ if quota_total > request.evaluation_slots:
407
+ raise ValueError("score portfolio quotas exceed evaluation capacity")
408
+
409
+ proposal_sha256s = tuple(
410
+ sorted(value.proposal_sha256 for value in proposals)
411
+ )
412
+ actions = tuple(
413
+ action for proposal in proposals for action in proposal.actions
414
+ )
415
+ action_by_sha256 = {value.action_sha256: value for value in actions}
416
+ if len(action_by_sha256) != len(actions):
417
+ raise ValueError("proposal union repeats an action identity")
418
+ action_sha256s = tuple(sorted(action_by_sha256))
419
+
420
+ batches = tuple(
421
+ await asyncio.gather(
422
+ *(scorer.score(request, proposals) for scorer in self.scorers)
423
+ )
424
+ )
425
+ batch_by_scorer: dict[str, MaterializedActionScoreBatch] = {}
426
+ scorer_by_id = {
427
+ _scorer_identity(value)[0]: value for value in self.scorers
428
+ }
429
+ for batch in batches:
430
+ if type(batch) is not MaterializedActionScoreBatch:
431
+ raise TypeError("scorer returned a foreign score batch")
432
+ batch.__post_init__()
433
+ scorer = scorer_by_id.get(batch.scorer_id)
434
+ if scorer is None:
435
+ raise ValueError("score batch names a foreign scorer")
436
+ if (
437
+ batch.scorer_id,
438
+ batch.scorer_version,
439
+ batch.scorer_definition_sha256,
440
+ ) != _scorer_identity(scorer):
441
+ raise ValueError("score batch differs from its scorer identity")
442
+ if batch.residual_request_sha256 != request.request_sha256:
443
+ raise ValueError("score batch targets another residual request")
444
+ if batch.proposal_sha256s != proposal_sha256s:
445
+ raise ValueError("score batch targets another proposal universe")
446
+ if tuple(value.action_sha256 for value in batch.scores) != (
447
+ action_sha256s
448
+ ):
449
+ raise ValueError("score batch must exactly cover sealed actions")
450
+ batch_by_scorer[batch.scorer_id] = batch
451
+
452
+ ranked_by_scorer = {
453
+ scorer_id: tuple(
454
+ sorted(
455
+ batch_by_scorer[scorer_id].scores,
456
+ key=lambda value: (-value.value, value.action_sha256),
457
+ )
458
+ )
459
+ for scorer_id, _ in self.scorer_quotas
460
+ }
461
+ selected: list[str] = []
462
+ selected_phenotypes: set[str] = set()
463
+ cursors = {scorer_id: 0 for scorer_id, _ in self.scorer_quotas}
464
+ selected_by_scorer = {
465
+ scorer_id: [] for scorer_id, _ in self.scorer_quotas
466
+ }
467
+ maximum_quota = max(value for _, value in self.scorer_quotas)
468
+ for ordinal in range(maximum_quota):
469
+ for scorer_id, quota in self.scorer_quotas:
470
+ if ordinal >= quota:
471
+ continue
472
+ ranking = ranked_by_scorer[scorer_id]
473
+ while cursors[scorer_id] < len(ranking):
474
+ score = ranking[cursors[scorer_id]]
475
+ cursors[scorer_id] += 1
476
+ action = action_by_sha256[score.action_sha256]
477
+ if (
478
+ action.phenotype_identity_sha256
479
+ in selected_phenotypes
480
+ ):
481
+ continue
482
+ selected.append(action.action_sha256)
483
+ selected_phenotypes.add(
484
+ action.phenotype_identity_sha256
485
+ )
486
+ selected_by_scorer[scorer_id].append(
487
+ {
488
+ "action_sha256": action.action_sha256,
489
+ "score_hex": score.value.hex(),
490
+ "rank_position": cursors[scorer_id],
491
+ }
492
+ )
493
+ break
494
+ else:
495
+ raise ValueError(
496
+ "score portfolio cannot satisfy phenotype-unique quotas"
497
+ )
498
+
499
+ if len(selected) != quota_total:
500
+ raise AssertionError("score portfolio did not close its quota")
501
+ return MaterializedActionAllocationRequirement(
502
+ policy_id=self.policy_id,
503
+ policy_version=self.policy_version,
504
+ policy_definition_sha256=self.definition_sha256,
505
+ residual_request_sha256=request.request_sha256,
506
+ proposal_sha256s=proposal_sha256s,
507
+ required_action_sha256s=tuple(sorted(selected)),
508
+ candidate_outcomes_observed=False,
509
+ evidence=freeze_json(
510
+ {
511
+ "score_batch_sha256s": {
512
+ scorer_id: batch_by_scorer[scorer_id].batch_sha256
513
+ for scorer_id, _ in self.scorer_quotas
514
+ },
515
+ "scorer_quotas": {
516
+ scorer_id: quota
517
+ for scorer_id, quota in self.scorer_quotas
518
+ },
519
+ "selected_by_scorer": selected_by_scorer,
520
+ "nomination_slots": quota_total,
521
+ "evaluation_slots": request.evaluation_slots,
522
+ "downstream_unreserved_slots": (
523
+ request.evaluation_slots - quota_total
524
+ ),
525
+ "candidate_outcomes_observed": False,
526
+ }
527
+ ),
528
+ )
529
+
530
+
531
+ @dataclass(frozen=True, slots=True)
532
+ class ReliabilityAdaptiveScorePortfolioPolicy:
533
+ """Scale primary authority and refill exact-infeasibility rejections.
534
+
535
+ The optional hard-feasibility port is deliberately proof-only. An
536
+ ``UNKNOWN`` verdict remains eligible; only an authenticated
537
+ ``INFEASIBLE`` decision removes an action. Each score authority then
538
+ continues down its own frozen ranking, preserving quota provenance while
539
+ avoiding a workload-specific branch in this policy.
540
+ """
541
+
542
+ scorers: tuple[MaterializedActionScorePort, ...]
543
+ primary_scorer_id: str
544
+ primary_reliability: MaterializedActionScoreReliabilityPort = field(
545
+ repr=False,
546
+ compare=False,
547
+ )
548
+ reliability_component_ids: tuple[str, ...]
549
+ minimum_primary_fraction: float = 0.5
550
+ hard_feasibility: HardFeasibilityPort | None = field(
551
+ default=None,
552
+ repr=False,
553
+ compare=False,
554
+ )
555
+
556
+ policy_id: ClassVar[str] = (
557
+ RELIABILITY_ADAPTIVE_SCORE_PORTFOLIO_POLICY_ID
558
+ )
559
+ policy_version: ClassVar[int] = (
560
+ RELIABILITY_ADAPTIVE_SCORE_PORTFOLIO_POLICY_VERSION
561
+ )
562
+ definition_sha256: str = field(init=False)
563
+
564
+ def __post_init__(self) -> None:
565
+ if type(self.scorers) is not tuple or len(self.scorers) < 2:
566
+ raise ValueError(
567
+ "adaptive portfolio requires a primary and fallback scorer"
568
+ )
569
+ identities = tuple(_scorer_identity(value) for value in self.scorers)
570
+ scorer_ids = tuple(value[0] for value in identities)
571
+ if scorer_ids != tuple(sorted(set(scorer_ids))):
572
+ raise ValueError("scorers must use canonical unique IDs")
573
+ _require_token(self.primary_scorer_id, name="primary_scorer_id")
574
+ if self.primary_scorer_id not in scorer_ids:
575
+ raise ValueError("primary scorer is absent")
576
+ if not isinstance(
577
+ self.primary_reliability,
578
+ MaterializedActionScoreReliabilityPort,
579
+ ):
580
+ raise TypeError(
581
+ "primary_reliability must implement its runtime port"
582
+ )
583
+ primary_identity = next(
584
+ value
585
+ for value in identities
586
+ if value[0] == self.primary_scorer_id
587
+ )
588
+ if (
589
+ self.primary_reliability.scorer_id,
590
+ self.primary_reliability.scorer_version,
591
+ self.primary_reliability.definition_sha256,
592
+ ) != primary_identity:
593
+ raise ValueError(
594
+ "primary reliability identity differs from its scorer"
595
+ )
596
+ if (
597
+ type(self.reliability_component_ids) is not tuple
598
+ or not self.reliability_component_ids
599
+ or self.reliability_component_ids
600
+ != tuple(sorted(set(self.reliability_component_ids)))
601
+ ):
602
+ raise ValueError(
603
+ "reliability components must be non-empty and canonical"
604
+ )
605
+ for value in self.reliability_component_ids:
606
+ _require_token(value, name="reliability component")
607
+ if (
608
+ type(self.minimum_primary_fraction) is not float
609
+ or not math.isfinite(self.minimum_primary_fraction)
610
+ or not 0.0 < self.minimum_primary_fraction <= 1.0
611
+ ):
612
+ raise ValueError(
613
+ "minimum_primary_fraction must lie in (0, 1]"
614
+ )
615
+ hard_feasibility_identity = None
616
+ if self.hard_feasibility is not None:
617
+ hard_feasibility_identity = validate_hard_feasibility_port(
618
+ self.hard_feasibility
619
+ )
620
+ _require_token(self.policy_id, name="policy_id")
621
+ object.__setattr__(
622
+ self,
623
+ "definition_sha256",
624
+ _hash(
625
+ _ADAPTIVE_POLICY_DOMAIN,
626
+ {
627
+ "schema_version": 1,
628
+ "policy_id": self.policy_id,
629
+ "policy_version": self.policy_version,
630
+ "scorers": [
631
+ {
632
+ "scorer_id": scorer_id,
633
+ "scorer_version": scorer_version,
634
+ "definition_sha256": definition_sha256,
635
+ }
636
+ for scorer_id, scorer_version, definition_sha256
637
+ in identities
638
+ ],
639
+ "primary_scorer_id": self.primary_scorer_id,
640
+ "reliability_component_ids": list(
641
+ self.reliability_component_ids
642
+ ),
643
+ "minimum_primary_fraction_hex": (
644
+ self.minimum_primary_fraction.hex()
645
+ ),
646
+ "primary_quota_rule": (
647
+ "ceil_fraction_floor_plus_nearest_integer_of_"
648
+ "reliability_times_remaining_capacity"
649
+ ),
650
+ "fallback_rule": (
651
+ "canonical_equal_integer_split_with_early_remainder"
652
+ ),
653
+ "hard_feasibility": (
654
+ None
655
+ if hard_feasibility_identity is None
656
+ else {
657
+ "policy_id": hard_feasibility_identity[0],
658
+ "policy_version": hard_feasibility_identity[1],
659
+ "definition_sha256": hard_feasibility_identity[2],
660
+ }
661
+ ),
662
+ "hard_feasibility_rejection_rule": (
663
+ "reject_only_authenticated_infeasible;"
664
+ "retain_feasible_and_unknown"
665
+ ),
666
+ "hard_feasibility_refill_rule": (
667
+ "continue_same_authority_frozen_ranking"
668
+ ),
669
+ "composition": (
670
+ "canonical_round_robin_phenotype_unique"
671
+ ),
672
+ "candidate_outcomes_observed": False,
673
+ "workload_model_provider_branches": False,
674
+ },
675
+ ),
676
+ )
677
+
678
+ async def require(
679
+ self,
680
+ request: ResidualPortfolioDecisionRequest,
681
+ proposals: tuple[MaterializedActionProposalBatch, ...],
682
+ ) -> MaterializedActionAllocationRequirement:
683
+ self.__post_init__()
684
+ if type(request) is not ResidualPortfolioDecisionRequest:
685
+ raise TypeError("request must be exact")
686
+ request.__post_init__()
687
+ if type(proposals) is not tuple or not proposals:
688
+ raise ValueError("proposals must be a non-empty exact tuple")
689
+ for proposal in proposals:
690
+ if type(proposal) is not MaterializedActionProposalBatch:
691
+ raise TypeError("proposals must contain exact batches")
692
+ proposal.__post_init__()
693
+ proposal.require_request(request)
694
+
695
+ proposal_sha256s = tuple(
696
+ sorted(value.proposal_sha256 for value in proposals)
697
+ )
698
+ actions = tuple(
699
+ action for proposal in proposals for action in proposal.actions
700
+ )
701
+ action_by_sha256 = {
702
+ value.action_sha256: value for value in actions
703
+ }
704
+ if len(action_by_sha256) != len(actions):
705
+ raise ValueError("proposal union repeats an action identity")
706
+ action_sha256s = tuple(sorted(action_by_sha256))
707
+ scorer_by_id = {
708
+ _scorer_identity(value)[0]: value for value in self.scorers
709
+ }
710
+ batches = tuple(
711
+ await asyncio.gather(
712
+ *(scorer.score(request, proposals) for scorer in self.scorers)
713
+ )
714
+ )
715
+ batch_by_scorer: dict[str, MaterializedActionScoreBatch] = {}
716
+ for batch in batches:
717
+ if type(batch) is not MaterializedActionScoreBatch:
718
+ raise TypeError("scorer returned a foreign score batch")
719
+ batch.__post_init__()
720
+ scorer = scorer_by_id.get(batch.scorer_id)
721
+ if scorer is None:
722
+ raise ValueError("score batch names a foreign scorer")
723
+ if (
724
+ batch.scorer_id,
725
+ batch.scorer_version,
726
+ batch.scorer_definition_sha256,
727
+ ) != _scorer_identity(scorer):
728
+ raise ValueError("score batch differs from scorer identity")
729
+ if (
730
+ batch.residual_request_sha256 != request.request_sha256
731
+ or batch.proposal_sha256s != proposal_sha256s
732
+ or tuple(value.action_sha256 for value in batch.scores)
733
+ != action_sha256s
734
+ ):
735
+ raise ValueError("score batch differs from sealed universe")
736
+ batch_by_scorer[batch.scorer_id] = batch
737
+
738
+ reliability = self.primary_reliability.reliability(
739
+ request.request_sha256,
740
+ self.reliability_component_ids,
741
+ )
742
+ if type(reliability) is not MaterializedActionScoreReliabilityEvidence:
743
+ raise TypeError("reliability port returned foreign evidence")
744
+ reliability.__post_init__()
745
+ primary_batch = batch_by_scorer[self.primary_scorer_id]
746
+ if (
747
+ reliability.scorer_id,
748
+ reliability.scorer_version,
749
+ reliability.scorer_definition_sha256,
750
+ ) != (
751
+ primary_batch.scorer_id,
752
+ primary_batch.scorer_version,
753
+ primary_batch.scorer_definition_sha256,
754
+ ):
755
+ raise ValueError("reliability evidence names another scorer")
756
+ if reliability.residual_request_sha256 != request.request_sha256:
757
+ raise ValueError("reliability evidence names another request")
758
+
759
+ capacity = request.evaluation_slots
760
+ minimum_primary = math.ceil(
761
+ capacity * self.minimum_primary_fraction
762
+ )
763
+ adaptive_capacity = capacity - minimum_primary
764
+ primary_quota = minimum_primary + math.floor(
765
+ reliability.overall_reliability * adaptive_capacity + 0.5
766
+ )
767
+ primary_quota = min(
768
+ capacity,
769
+ max(minimum_primary, primary_quota),
770
+ )
771
+ fallback_ids = tuple(
772
+ value
773
+ for value in sorted(scorer_by_id)
774
+ if value != self.primary_scorer_id
775
+ )
776
+ residual = capacity - primary_quota
777
+ quotient, remainder = divmod(residual, len(fallback_ids))
778
+ quotas = {
779
+ self.primary_scorer_id: primary_quota,
780
+ **{
781
+ scorer_id: quotient + (1 if index < remainder else 0)
782
+ for index, scorer_id in enumerate(fallback_ids)
783
+ },
784
+ }
785
+ if sum(quotas.values()) != capacity:
786
+ raise AssertionError("adaptive quotas do not close")
787
+
788
+ ranked_by_scorer = {
789
+ scorer_id: tuple(
790
+ sorted(
791
+ batch_by_scorer[scorer_id].scores,
792
+ key=lambda value: (-value.value, value.action_sha256),
793
+ )
794
+ )
795
+ for scorer_id in sorted(scorer_by_id)
796
+ }
797
+ feasibility_decisions: tuple[
798
+ tuple[str, HardFeasibilityDecision], ...
799
+ ] = ()
800
+ infeasible_action_sha256s: set[str] = set()
801
+ if self.hard_feasibility is not None:
802
+ audited: list[tuple[str, HardFeasibilityDecision]] = []
803
+ for action_sha256 in action_sha256s:
804
+ action = action_by_sha256[action_sha256]
805
+ decision = assess_hard_feasibility(
806
+ self.hard_feasibility,
807
+ HardFeasibilityRequest(
808
+ campaign_scope_sha256=request.campaign_scope_sha256,
809
+ cutoff_index=request.decision_index,
810
+ configuration=action.configuration,
811
+ ),
812
+ )
813
+ audited.append((action_sha256, decision))
814
+ if decision.verdict is HardFeasibilityVerdict.INFEASIBLE:
815
+ infeasible_action_sha256s.add(action_sha256)
816
+ feasibility_decisions = tuple(audited)
817
+ if len(actions) - len(infeasible_action_sha256s) < capacity:
818
+ raise ValueError(
819
+ "hard-feasibility-screened proposal union cannot fill "
820
+ "evaluation capacity"
821
+ )
822
+ selected: list[str] = []
823
+ selected_phenotypes: set[str] = set()
824
+ cursors = {scorer_id: 0 for scorer_id in scorer_by_id}
825
+ selected_by_scorer = {
826
+ scorer_id: [] for scorer_id in sorted(scorer_by_id)
827
+ }
828
+ for ordinal in range(max(quotas.values())):
829
+ for scorer_id in sorted(scorer_by_id):
830
+ if ordinal >= quotas[scorer_id]:
831
+ continue
832
+ ranking = ranked_by_scorer[scorer_id]
833
+ while cursors[scorer_id] < len(ranking):
834
+ score = ranking[cursors[scorer_id]]
835
+ cursors[scorer_id] += 1
836
+ action = action_by_sha256[score.action_sha256]
837
+ if action.action_sha256 in infeasible_action_sha256s:
838
+ continue
839
+ if (
840
+ action.phenotype_identity_sha256
841
+ in selected_phenotypes
842
+ ):
843
+ continue
844
+ selected.append(action.action_sha256)
845
+ selected_phenotypes.add(
846
+ action.phenotype_identity_sha256
847
+ )
848
+ selected_by_scorer[scorer_id].append(
849
+ {
850
+ "action_sha256": action.action_sha256,
851
+ "score_hex": score.value.hex(),
852
+ "rank_position": cursors[scorer_id],
853
+ }
854
+ )
855
+ break
856
+ else:
857
+ raise ValueError(
858
+ "adaptive portfolio cannot close a unique quota"
859
+ )
860
+ if len(selected) != capacity:
861
+ raise AssertionError("adaptive portfolio did not fill capacity")
862
+ feasibility_verdict_counts = {
863
+ verdict.value: sum(
864
+ decision.verdict is verdict
865
+ for _action_sha256, decision in feasibility_decisions
866
+ )
867
+ for verdict in HardFeasibilityVerdict
868
+ }
869
+ feasibility_record = {
870
+ "enabled": self.hard_feasibility is not None,
871
+ "policy": (
872
+ None
873
+ if self.hard_feasibility is None
874
+ else {
875
+ "policy_id": self.hard_feasibility.policy_id,
876
+ "policy_version": self.hard_feasibility.policy_version,
877
+ "definition_sha256": (
878
+ self.hard_feasibility.definition_sha256
879
+ ),
880
+ }
881
+ ),
882
+ "verdict_counts": feasibility_verdict_counts,
883
+ "decision_batch_sha256": (
884
+ None
885
+ if not feasibility_decisions
886
+ else hard_feasibility_decision_batch_sha256(
887
+ tuple(
888
+ decision.decision_sha256
889
+ for _action_sha256, decision
890
+ in feasibility_decisions
891
+ )
892
+ )
893
+ ),
894
+ "rejected_actions": [
895
+ {
896
+ "action_sha256": action_sha256,
897
+ "decision": decision.to_record(),
898
+ }
899
+ for action_sha256, decision in feasibility_decisions
900
+ if decision.verdict
901
+ is HardFeasibilityVerdict.INFEASIBLE
902
+ ],
903
+ "rejection_authority": (
904
+ "authenticated_exact_infeasibility_only"
905
+ ),
906
+ "unknown_actions_remain_eligible": True,
907
+ "refill": "same_authority_frozen_ranking",
908
+ "candidate_outcomes_observed": False,
909
+ }
910
+ return MaterializedActionAllocationRequirement(
911
+ policy_id=self.policy_id,
912
+ policy_version=self.policy_version,
913
+ policy_definition_sha256=self.definition_sha256,
914
+ residual_request_sha256=request.request_sha256,
915
+ proposal_sha256s=proposal_sha256s,
916
+ required_action_sha256s=tuple(sorted(selected)),
917
+ candidate_outcomes_observed=False,
918
+ evidence=freeze_json(
919
+ {
920
+ "score_batch_sha256s": {
921
+ scorer_id: batch_by_scorer[
922
+ scorer_id
923
+ ].batch_sha256
924
+ for scorer_id in sorted(batch_by_scorer)
925
+ },
926
+ "primary_reliability": reliability.to_record(),
927
+ "minimum_primary_quota": minimum_primary,
928
+ "effective_quotas": {
929
+ scorer_id: quotas[scorer_id]
930
+ for scorer_id in sorted(quotas)
931
+ },
932
+ "selected_by_scorer": selected_by_scorer,
933
+ "hard_feasibility": feasibility_record,
934
+ "candidate_outcomes_observed": False,
935
+ "workload_model_provider_branches": False,
936
+ }
937
+ ),
938
+ )
939
+
940
+
941
+ __all__ = [
942
+ "MaterializedActionScore",
943
+ "MaterializedActionScoreBatch",
944
+ "MaterializedActionScorePort",
945
+ "MaterializedActionScoreReliabilityEvidence",
946
+ "MaterializedActionScoreReliabilityPort",
947
+ "PREQUENTIAL_SCORE_PORTFOLIO_POLICY_DEFINITION_SHA256",
948
+ "PREQUENTIAL_SCORE_PORTFOLIO_POLICY_ID",
949
+ "PREQUENTIAL_SCORE_PORTFOLIO_POLICY_VERSION",
950
+ "PrequentialQuotaScorePortfolioPolicy",
951
+ "RELIABILITY_ADAPTIVE_SCORE_PORTFOLIO_POLICY_ID",
952
+ "RELIABILITY_ADAPTIVE_SCORE_PORTFOLIO_POLICY_VERSION",
953
+ "ReliabilityAdaptiveScorePortfolioPolicy",
954
+ ]