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,659 @@
1
+ """Frozen, outcome-blind consequence scorers for materialized actions.
2
+
3
+ Feature construction is an injected port. This module owns only the
4
+ authenticated feature-vector boundary and deterministic application of frozen
5
+ standardized linear models. It deliberately has no workload, objective,
6
+ model-provider, prompt, or configuration-schema branches.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass, field
12
+ from enum import Enum
13
+ import hashlib
14
+ import json
15
+ import math
16
+ import re
17
+ from typing import Protocol, runtime_checkable
18
+
19
+ from agent_evolve.application.prequential_score_portfolio import (
20
+ MaterializedActionScore,
21
+ MaterializedActionScoreBatch,
22
+ )
23
+ from agent_evolve.application.residual_portfolio_evolution import (
24
+ MaterializedActionProposalBatch,
25
+ ResidualPortfolioDecisionRequest,
26
+ )
27
+ from agent_evolve.domain.patch import require_sha256
28
+ from agent_evolve.domain.typed_json import (
29
+ FrozenJsonObject,
30
+ freeze_json,
31
+ typed_json_sha256,
32
+ )
33
+
34
+
35
+ FROZEN_HURDLE_SCORE_VERSION = 1
36
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
37
+ _FEATURE_BATCH_DOMAIN = (
38
+ b"agent-evolve:materialized-action-feature-batch:v1\x00"
39
+ )
40
+ _LINEAR_MODEL_DOMAIN = b"agent-evolve:frozen-standardized-linear-model:v1\x00"
41
+ _SCORER_DOMAIN = b"agent-evolve:frozen-hurdle-action-scorer:v1\x00"
42
+ _SCORER_EVIDENCE_DOMAIN = (
43
+ b"agent-evolve:frozen-hurdle-action-score-evidence:v1\x00"
44
+ )
45
+ _WINSORIZED_SCORER_DOMAIN = (
46
+ b"agent-evolve:winsorized-frozen-hurdle-action-scorer:v1\x00"
47
+ )
48
+ _WINSORIZED_SCORER_EVIDENCE_DOMAIN = (
49
+ b"agent-evolve:winsorized-frozen-hurdle-score-evidence:v1\x00"
50
+ )
51
+
52
+
53
+ def _canonical_json(value: object) -> bytes:
54
+ return json.dumps(
55
+ value,
56
+ allow_nan=False,
57
+ ensure_ascii=True,
58
+ separators=(",", ":"),
59
+ sort_keys=True,
60
+ ).encode("ascii", errors="strict")
61
+
62
+
63
+ def _hash(domain: bytes, value: object) -> str:
64
+ return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
65
+
66
+
67
+ def _token(value: str, *, name: str) -> None:
68
+ if type(value) is not str or _TOKEN.fullmatch(value) is None:
69
+ raise ValueError(f"{name} must use the closed token grammar")
70
+
71
+
72
+ def _finite_tuple(
73
+ values: tuple[float, ...],
74
+ *,
75
+ name: str,
76
+ nonzero: bool = False,
77
+ ) -> None:
78
+ if type(values) is not tuple or not values:
79
+ raise ValueError(f"{name} must be a non-empty exact tuple")
80
+ for value in values:
81
+ if type(value) is not float or not math.isfinite(value):
82
+ raise TypeError(f"{name} must contain finite exact floats")
83
+ if nonzero and value <= 0.0:
84
+ raise ValueError(f"{name} must contain positive values")
85
+
86
+
87
+ @dataclass(frozen=True, slots=True)
88
+ class MaterializedActionFeatureVector:
89
+ """One canonical feature vector for one sealed materialized action."""
90
+
91
+ action_sha256: str
92
+ values: tuple[float, ...]
93
+
94
+ def __post_init__(self) -> None:
95
+ require_sha256(self.action_sha256, "action_sha256")
96
+ _finite_tuple(self.values, name="feature values")
97
+
98
+ def to_record(self) -> dict[str, object]:
99
+ self.__post_init__()
100
+ return {
101
+ "action_sha256": self.action_sha256,
102
+ "values_hex": [value.hex() for value in self.values],
103
+ }
104
+
105
+
106
+ @dataclass(frozen=True, slots=True)
107
+ class MaterializedActionFeatureBatch:
108
+ """Authenticated complete features for one sealed proposal universe."""
109
+
110
+ projection_id: str
111
+ projection_version: int
112
+ projection_definition_sha256: str
113
+ residual_request_sha256: str
114
+ proposal_sha256s: tuple[str, ...]
115
+ feature_names: tuple[str, ...]
116
+ vectors: tuple[MaterializedActionFeatureVector, ...]
117
+ candidate_outcomes_observed: bool
118
+ evidence: FrozenJsonObject
119
+ batch_sha256: str = field(init=False)
120
+
121
+ def __post_init__(self) -> None:
122
+ _token(self.projection_id, name="projection_id")
123
+ if type(self.projection_version) is not int or self.projection_version <= 0:
124
+ raise ValueError("projection_version must be positive")
125
+ require_sha256(
126
+ self.projection_definition_sha256,
127
+ "projection_definition_sha256",
128
+ )
129
+ require_sha256(
130
+ self.residual_request_sha256,
131
+ "residual_request_sha256",
132
+ )
133
+ if (
134
+ type(self.proposal_sha256s) is not tuple
135
+ or not self.proposal_sha256s
136
+ or self.proposal_sha256s
137
+ != tuple(sorted(set(self.proposal_sha256s)))
138
+ ):
139
+ raise ValueError(
140
+ "proposal_sha256s must be non-empty, unique, and canonical"
141
+ )
142
+ for value in self.proposal_sha256s:
143
+ require_sha256(value, "proposal_sha256")
144
+ if (
145
+ type(self.feature_names) is not tuple
146
+ or not self.feature_names
147
+ or self.feature_names != tuple(dict.fromkeys(self.feature_names))
148
+ ):
149
+ raise ValueError("feature_names must be non-empty and unique")
150
+ for value in self.feature_names:
151
+ _token(value, name="feature name")
152
+ if type(self.vectors) is not tuple or not self.vectors:
153
+ raise ValueError("vectors must be a non-empty exact tuple")
154
+ for vector in self.vectors:
155
+ if type(vector) is not MaterializedActionFeatureVector:
156
+ raise TypeError("vectors must contain exact feature vectors")
157
+ vector.__post_init__()
158
+ if len(vector.values) != len(self.feature_names):
159
+ raise ValueError("feature vector width differs from feature_names")
160
+ action_ids = tuple(value.action_sha256 for value in self.vectors)
161
+ if action_ids != tuple(sorted(set(action_ids))):
162
+ raise ValueError("feature vectors must be unique and canonical")
163
+ if type(self.candidate_outcomes_observed) is not bool:
164
+ raise TypeError(
165
+ "candidate_outcomes_observed must be an exact bool"
166
+ )
167
+ if self.candidate_outcomes_observed:
168
+ raise ValueError("prequential features cannot observe current outcomes")
169
+ if (
170
+ type(self.evidence) is not FrozenJsonObject
171
+ or freeze_json(self.evidence) is not self.evidence
172
+ ):
173
+ raise TypeError("feature evidence must be an exact frozen object")
174
+ object.__setattr__(
175
+ self,
176
+ "batch_sha256",
177
+ _hash(_FEATURE_BATCH_DOMAIN, self._unsigned_record()),
178
+ )
179
+
180
+ def _unsigned_record(self) -> dict[str, object]:
181
+ return {
182
+ "schema_version": 1,
183
+ "projection": {
184
+ "projection_id": self.projection_id,
185
+ "projection_version": self.projection_version,
186
+ "definition_sha256": self.projection_definition_sha256,
187
+ },
188
+ "residual_request_sha256": self.residual_request_sha256,
189
+ "proposal_sha256s": list(self.proposal_sha256s),
190
+ "feature_names": list(self.feature_names),
191
+ "vectors": [value.to_record() for value in self.vectors],
192
+ "candidate_outcomes_observed": self.candidate_outcomes_observed,
193
+ "evidence_sha256": typed_json_sha256(self.evidence),
194
+ }
195
+
196
+ def to_record(self) -> dict[str, object]:
197
+ self.__post_init__()
198
+ return {**self._unsigned_record(), "batch_sha256": self.batch_sha256}
199
+
200
+
201
+ @runtime_checkable
202
+ class MaterializedActionFeatureProjectionPort(Protocol):
203
+ """Project complete sealed proposals using strictly prior evidence."""
204
+
205
+ projection_id: str
206
+ projection_version: int
207
+ definition_sha256: str
208
+ feature_names: tuple[str, ...]
209
+
210
+ async def project(
211
+ self,
212
+ request: ResidualPortfolioDecisionRequest,
213
+ proposals: tuple[MaterializedActionProposalBatch, ...],
214
+ ) -> MaterializedActionFeatureBatch: ...
215
+
216
+
217
+ @dataclass(frozen=True, slots=True)
218
+ class FrozenStandardizedLinearModel:
219
+ """Immutable standardized linear predictor with authenticated identity."""
220
+
221
+ model_id: str
222
+ family: str
223
+ feature_names: tuple[str, ...]
224
+ means: tuple[float, ...]
225
+ scales: tuple[float, ...]
226
+ coefficients: tuple[float, ...]
227
+ definition_sha256: str = field(init=False)
228
+
229
+ def __post_init__(self) -> None:
230
+ _token(self.model_id, name="model_id")
231
+ _token(self.family, name="family")
232
+ if (
233
+ type(self.feature_names) is not tuple
234
+ or not self.feature_names
235
+ or self.feature_names != tuple(dict.fromkeys(self.feature_names))
236
+ ):
237
+ raise ValueError("feature_names must be non-empty and unique")
238
+ for value in self.feature_names:
239
+ _token(value, name="feature name")
240
+ _finite_tuple(self.means, name="means")
241
+ _finite_tuple(self.scales, name="scales", nonzero=True)
242
+ _finite_tuple(self.coefficients, name="coefficients")
243
+ width = len(self.feature_names)
244
+ if len(self.means) != width or len(self.scales) != width:
245
+ raise ValueError("standardizer width differs from feature ABI")
246
+ if len(self.coefficients) != width + 1:
247
+ raise ValueError(
248
+ "coefficients must contain one intercept plus feature weights"
249
+ )
250
+ object.__setattr__(
251
+ self,
252
+ "definition_sha256",
253
+ _hash(_LINEAR_MODEL_DOMAIN, self._unsigned_record()),
254
+ )
255
+
256
+ def _unsigned_record(self) -> dict[str, object]:
257
+ return {
258
+ "schema_version": 1,
259
+ "model_id": self.model_id,
260
+ "family": self.family,
261
+ "feature_names": list(self.feature_names),
262
+ "mean_hex": [value.hex() for value in self.means],
263
+ "scale_hex": [value.hex() for value in self.scales],
264
+ "coefficients_hex": [value.hex() for value in self.coefficients],
265
+ }
266
+
267
+ def predict(self, values: tuple[float, ...]) -> float:
268
+ self.__post_init__()
269
+ _finite_tuple(values, name="prediction features")
270
+ if len(values) != len(self.feature_names):
271
+ raise ValueError("prediction vector differs from feature ABI")
272
+ result = self.coefficients[0] + math.fsum(
273
+ coefficient * ((value - mean) / scale)
274
+ for value, mean, scale, coefficient in zip(
275
+ values,
276
+ self.means,
277
+ self.scales,
278
+ self.coefficients[1:],
279
+ strict=True,
280
+ )
281
+ )
282
+ if not math.isfinite(result):
283
+ raise RuntimeError("frozen linear prediction became non-finite")
284
+ return float(result)
285
+
286
+ def to_record(self) -> dict[str, object]:
287
+ self.__post_init__()
288
+ return {
289
+ **self._unsigned_record(),
290
+ "definition_sha256": self.definition_sha256,
291
+ }
292
+
293
+
294
+ class FrozenHurdleScoreKind(str, Enum):
295
+ POSITIVE_PROBABILITY = "positive_probability"
296
+ EXPECTED_POSITIVE_MAGNITUDE = "expected_positive_magnitude"
297
+
298
+
299
+ @dataclass(frozen=True, slots=True)
300
+ class FrozenHurdleMaterializedActionScorer:
301
+ """Apply a frozen positive/magnitude hurdle model before evaluation."""
302
+
303
+ scorer_id: str
304
+ projection: MaterializedActionFeatureProjectionPort = field(
305
+ repr=False,
306
+ compare=False,
307
+ )
308
+ positive_model: FrozenStandardizedLinearModel
309
+ magnitude_model: FrozenStandardizedLinearModel
310
+ score_kind: FrozenHurdleScoreKind
311
+ source_fit_sha256: str
312
+ scorer_version: int = FROZEN_HURDLE_SCORE_VERSION
313
+ definition_sha256: str = field(init=False)
314
+
315
+ def __post_init__(self) -> None:
316
+ _token(self.scorer_id, name="scorer_id")
317
+ if type(self.scorer_version) is not int or self.scorer_version <= 0:
318
+ raise ValueError("scorer_version must be positive")
319
+ require_sha256(self.source_fit_sha256, "source_fit_sha256")
320
+ if not isinstance(
321
+ self.projection,
322
+ MaterializedActionFeatureProjectionPort,
323
+ ):
324
+ raise TypeError("projection must implement its runtime port")
325
+ _token(self.projection.projection_id, name="projection_id")
326
+ if (
327
+ type(self.projection.projection_version) is not int
328
+ or self.projection.projection_version <= 0
329
+ ):
330
+ raise ValueError("projection_version must be positive")
331
+ require_sha256(
332
+ self.projection.definition_sha256,
333
+ "projection definition_sha256",
334
+ )
335
+ if type(self.positive_model) is not FrozenStandardizedLinearModel:
336
+ raise TypeError("positive_model must be exact")
337
+ if type(self.magnitude_model) is not FrozenStandardizedLinearModel:
338
+ raise TypeError("magnitude_model must be exact")
339
+ self.positive_model.__post_init__()
340
+ self.magnitude_model.__post_init__()
341
+ if type(self.score_kind) is not FrozenHurdleScoreKind:
342
+ raise TypeError("score_kind must be exact")
343
+ feature_names = self.projection.feature_names
344
+ if (
345
+ feature_names != self.positive_model.feature_names
346
+ or feature_names != self.magnitude_model.feature_names
347
+ ):
348
+ raise ValueError("projection and frozen models use different feature ABIs")
349
+ object.__setattr__(
350
+ self,
351
+ "definition_sha256",
352
+ _hash(
353
+ _SCORER_DOMAIN,
354
+ {
355
+ "schema_version": 1,
356
+ "scorer_id": self.scorer_id,
357
+ "scorer_version": self.scorer_version,
358
+ "score_kind": self.score_kind.value,
359
+ "source_fit_sha256": self.source_fit_sha256,
360
+ "projection": {
361
+ "projection_id": self.projection.projection_id,
362
+ "projection_version": (
363
+ self.projection.projection_version
364
+ ),
365
+ "definition_sha256": (
366
+ self.projection.definition_sha256
367
+ ),
368
+ },
369
+ "positive_model_sha256": (
370
+ self.positive_model.definition_sha256
371
+ ),
372
+ "magnitude_model_sha256": (
373
+ self.magnitude_model.definition_sha256
374
+ ),
375
+ "logit_clip": [-30, 30],
376
+ "log_magnitude_clip": [-30, 30],
377
+ "candidate_outcomes_observed": False,
378
+ "workload_model_provider_branches": False,
379
+ },
380
+ ),
381
+ )
382
+
383
+ @staticmethod
384
+ def _sigmoid(value: float) -> float:
385
+ clipped = min(30.0, max(-30.0, value))
386
+ return 1.0 / (1.0 + math.exp(-clipped))
387
+
388
+ async def score(
389
+ self,
390
+ request: ResidualPortfolioDecisionRequest,
391
+ proposals: tuple[MaterializedActionProposalBatch, ...],
392
+ ) -> MaterializedActionScoreBatch:
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
+ proposal_sha256s = tuple(
400
+ sorted(value.proposal_sha256 for value in proposals)
401
+ )
402
+ action_sha256s = tuple(
403
+ sorted(
404
+ action.action_sha256
405
+ for proposal in proposals
406
+ for action in proposal.actions
407
+ )
408
+ )
409
+ features = await self.projection.project(request, proposals)
410
+ if type(features) is not MaterializedActionFeatureBatch:
411
+ raise TypeError("feature projection returned a foreign batch")
412
+ features.__post_init__()
413
+ if (
414
+ features.projection_id,
415
+ features.projection_version,
416
+ features.projection_definition_sha256,
417
+ ) != (
418
+ self.projection.projection_id,
419
+ self.projection.projection_version,
420
+ self.projection.definition_sha256,
421
+ ):
422
+ raise ValueError("feature batch differs from its projection")
423
+ if features.residual_request_sha256 != request.request_sha256:
424
+ raise ValueError("feature batch targets another residual request")
425
+ if features.proposal_sha256s != proposal_sha256s:
426
+ raise ValueError("feature batch targets another proposal universe")
427
+ if features.feature_names != self.positive_model.feature_names:
428
+ raise ValueError("feature batch differs from the frozen model ABI")
429
+ if tuple(value.action_sha256 for value in features.vectors) != (
430
+ action_sha256s
431
+ ):
432
+ raise ValueError("feature batch must exactly cover sealed actions")
433
+
434
+ scores: list[MaterializedActionScore] = []
435
+ for vector in features.vectors:
436
+ probability = self._sigmoid(
437
+ self.positive_model.predict(vector.values)
438
+ )
439
+ if self.score_kind is FrozenHurdleScoreKind.POSITIVE_PROBABILITY:
440
+ value = probability
441
+ else:
442
+ log_magnitude = self.magnitude_model.predict(vector.values)
443
+ magnitude = max(
444
+ 0.0,
445
+ math.expm1(min(30.0, max(-30.0, log_magnitude))),
446
+ )
447
+ value = probability * magnitude
448
+ scores.append(
449
+ MaterializedActionScore(
450
+ action_sha256=vector.action_sha256,
451
+ value=float(value),
452
+ )
453
+ )
454
+ evidence_sha256 = _hash(
455
+ _SCORER_EVIDENCE_DOMAIN,
456
+ {
457
+ "scorer_definition_sha256": self.definition_sha256,
458
+ "source_fit_sha256": self.source_fit_sha256,
459
+ "feature_batch_sha256": features.batch_sha256,
460
+ "candidate_outcomes_observed": False,
461
+ },
462
+ )
463
+ return MaterializedActionScoreBatch(
464
+ scorer_id=self.scorer_id,
465
+ scorer_version=self.scorer_version,
466
+ scorer_definition_sha256=self.definition_sha256,
467
+ residual_request_sha256=request.request_sha256,
468
+ proposal_sha256s=proposal_sha256s,
469
+ scores=tuple(scores),
470
+ candidate_outcomes_observed=False,
471
+ evidence_sha256=evidence_sha256,
472
+ )
473
+
474
+
475
+ @dataclass(frozen=True, slots=True)
476
+ class WinsorizedFrozenHurdleMaterializedActionScorer(
477
+ FrozenHurdleMaterializedActionScorer
478
+ ):
479
+ """Apply independently standardized models with bounded source z-scores."""
480
+
481
+ winsorization_limit: float = 3.0
482
+
483
+ def __post_init__(self) -> None:
484
+ FrozenHurdleMaterializedActionScorer.__post_init__(self)
485
+ if (
486
+ type(self.winsorization_limit) is not float
487
+ or not math.isfinite(self.winsorization_limit)
488
+ or self.winsorization_limit <= 0.0
489
+ ):
490
+ raise ValueError(
491
+ "winsorization_limit must be a positive finite float"
492
+ )
493
+ object.__setattr__(
494
+ self,
495
+ "definition_sha256",
496
+ _hash(
497
+ _WINSORIZED_SCORER_DOMAIN,
498
+ {
499
+ "schema_version": 1,
500
+ "scorer_id": self.scorer_id,
501
+ "scorer_version": self.scorer_version,
502
+ "score_kind": self.score_kind.value,
503
+ "source_fit_sha256": self.source_fit_sha256,
504
+ "projection": {
505
+ "projection_id": self.projection.projection_id,
506
+ "projection_version": (
507
+ self.projection.projection_version
508
+ ),
509
+ "definition_sha256": (
510
+ self.projection.definition_sha256
511
+ ),
512
+ },
513
+ "positive_model_sha256": (
514
+ self.positive_model.definition_sha256
515
+ ),
516
+ "magnitude_model_sha256": (
517
+ self.magnitude_model.definition_sha256
518
+ ),
519
+ "winsorization_limit_hex": (
520
+ self.winsorization_limit.hex()
521
+ ),
522
+ "standardization": (
523
+ "independent_frozen_standardizer_per_hurdle_model"
524
+ ),
525
+ "candidate_outcomes_observed": False,
526
+ "workload_model_provider_branches": False,
527
+ },
528
+ ),
529
+ )
530
+
531
+ def _winsorized_linear(
532
+ self,
533
+ model: FrozenStandardizedLinearModel,
534
+ values: tuple[float, ...],
535
+ ) -> float:
536
+ result = model.coefficients[0] + math.fsum(
537
+ coefficient
538
+ * min(
539
+ self.winsorization_limit,
540
+ max(
541
+ -self.winsorization_limit,
542
+ (value - mean) / scale,
543
+ ),
544
+ )
545
+ for value, mean, scale, coefficient in zip(
546
+ values,
547
+ model.means,
548
+ model.scales,
549
+ model.coefficients[1:],
550
+ strict=True,
551
+ )
552
+ )
553
+ if not math.isfinite(result):
554
+ raise RuntimeError("winsorized hurdle prediction became non-finite")
555
+ return float(result)
556
+
557
+ async def score(
558
+ self,
559
+ request: ResidualPortfolioDecisionRequest,
560
+ proposals: tuple[MaterializedActionProposalBatch, ...],
561
+ ) -> MaterializedActionScoreBatch:
562
+ self.__post_init__()
563
+ if type(request) is not ResidualPortfolioDecisionRequest:
564
+ raise TypeError("request must be exact")
565
+ request.__post_init__()
566
+ if type(proposals) is not tuple or not proposals:
567
+ raise ValueError("proposals must be a non-empty exact tuple")
568
+ proposal_sha256s = tuple(
569
+ sorted(value.proposal_sha256 for value in proposals)
570
+ )
571
+ action_sha256s = tuple(
572
+ sorted(
573
+ action.action_sha256
574
+ for proposal in proposals
575
+ for action in proposal.actions
576
+ )
577
+ )
578
+ features = await self.projection.project(request, proposals)
579
+ if type(features) is not MaterializedActionFeatureBatch:
580
+ raise TypeError("feature projection returned a foreign batch")
581
+ features.__post_init__()
582
+ if (
583
+ features.projection_id,
584
+ features.projection_version,
585
+ features.projection_definition_sha256,
586
+ ) != (
587
+ self.projection.projection_id,
588
+ self.projection.projection_version,
589
+ self.projection.definition_sha256,
590
+ ):
591
+ raise ValueError("feature batch differs from its projection")
592
+ if (
593
+ features.residual_request_sha256 != request.request_sha256
594
+ or features.proposal_sha256s != proposal_sha256s
595
+ or features.feature_names != self.positive_model.feature_names
596
+ or tuple(value.action_sha256 for value in features.vectors)
597
+ != action_sha256s
598
+ ):
599
+ raise ValueError("feature batch differs from sealed universe")
600
+
601
+ scores: list[MaterializedActionScore] = []
602
+ for vector in features.vectors:
603
+ probability = self._sigmoid(
604
+ self._winsorized_linear(
605
+ self.positive_model,
606
+ vector.values,
607
+ )
608
+ )
609
+ if self.score_kind is FrozenHurdleScoreKind.POSITIVE_PROBABILITY:
610
+ value = probability
611
+ else:
612
+ log_magnitude = self._winsorized_linear(
613
+ self.magnitude_model,
614
+ vector.values,
615
+ )
616
+ magnitude = max(
617
+ 0.0,
618
+ math.expm1(
619
+ min(30.0, max(-30.0, log_magnitude))
620
+ ),
621
+ )
622
+ value = probability * magnitude
623
+ scores.append(
624
+ MaterializedActionScore(
625
+ action_sha256=vector.action_sha256,
626
+ value=float(value),
627
+ )
628
+ )
629
+ evidence_sha256 = _hash(
630
+ _WINSORIZED_SCORER_EVIDENCE_DOMAIN,
631
+ {
632
+ "scorer_definition_sha256": self.definition_sha256,
633
+ "source_fit_sha256": self.source_fit_sha256,
634
+ "feature_batch_sha256": features.batch_sha256,
635
+ "candidate_outcomes_observed": False,
636
+ },
637
+ )
638
+ return MaterializedActionScoreBatch(
639
+ scorer_id=self.scorer_id,
640
+ scorer_version=self.scorer_version,
641
+ scorer_definition_sha256=self.definition_sha256,
642
+ residual_request_sha256=request.request_sha256,
643
+ proposal_sha256s=proposal_sha256s,
644
+ scores=tuple(scores),
645
+ candidate_outcomes_observed=False,
646
+ evidence_sha256=evidence_sha256,
647
+ )
648
+
649
+
650
+ __all__ = [
651
+ "FROZEN_HURDLE_SCORE_VERSION",
652
+ "FrozenHurdleMaterializedActionScorer",
653
+ "FrozenHurdleScoreKind",
654
+ "FrozenStandardizedLinearModel",
655
+ "MaterializedActionFeatureBatch",
656
+ "MaterializedActionFeatureProjectionPort",
657
+ "MaterializedActionFeatureVector",
658
+ "WinsorizedFrozenHurdleMaterializedActionScorer",
659
+ ]