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,1084 @@
1
+ """Regret-bounded finite-slate selection with interceptable future value.
2
+
3
+ The strongest strictly-prior numerical slate remains the live anchor. A
4
+ challenger can be evaluated only when its frozen acquisition value lies inside
5
+ an explicit multiplicative retention envelope. Inside that envelope, an
6
+ injected policy may price authenticated information, descendant capacity, and
7
+ risk. An optional identification quota requires a bounded number of members
8
+ outside the all-anchor reference, preventing a zero-evidence source from being
9
+ starved forever; the policy fails closed when no such slate satisfies the
10
+ retention envelope. The language model never owns the final decision, and the
11
+ complete anchor remains a scored, authenticated counterfactual even when an
12
+ audit member displaces one of its evaluations.
13
+
14
+ This module deliberately does not know a workload, objective name, model, or
15
+ provider. It is the first executable RBIE broker seam; cumulative regret-bank
16
+ allocation and learned delayed value can be injected without changing the
17
+ workload adapter or finite acquisition scorer.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import hashlib
23
+ import json
24
+ import math
25
+ from dataclasses import dataclass, field
26
+ from enum import Enum
27
+ from typing import Protocol, runtime_checkable
28
+
29
+ from agent_evolve.domain.patch import require_sha256
30
+ from agent_evolve.policies.selection.acquisition_certified_slate import (
31
+ AcquisitionCertifiedSlateContext,
32
+ AcquisitionCertifiedSlateContextProvider,
33
+ feasible_slate_option_id_subsets,
34
+ finite_acquisition_policy_identity,
35
+ )
36
+ from agent_evolve.policies.selection.calibrated_slate import (
37
+ AllocatedSlateMember,
38
+ SlateAllocationRequest,
39
+ SlateAllocationRole,
40
+ assess_allocated_slate_memory_dose,
41
+ )
42
+ from agent_evolve.ports.finite_acquisition_batch import (
43
+ FiniteAcquisitionBatchScoreDecision,
44
+ FiniteAcquisitionBatchScorePolicy,
45
+ FiniteAcquisitionBatchScoreRequest,
46
+ FiniteAcquisitionSlate,
47
+ validate_finite_acquisition_batch_score_decision,
48
+ )
49
+ from agent_evolve.ports.portfolio_memory_dose import PortfolioMemoryDoseAssessment
50
+
51
+
52
+ POLICY_ID = "regret_bounded_information_slate"
53
+ POLICY_VERSION = 2
54
+ _POLICY_DOMAIN = b"agent-evolve:regret-bounded-information-slate-policy:v2\x00"
55
+ _ESTIMATE_DOMAIN = b"agent-evolve:slate-future-value-estimate:v1\x00"
56
+ _ASSESSMENT_DOMAIN = b"agent-evolve:regret-bounded-slate-assessment:v1\x00"
57
+ _DECISION_DOMAIN = b"agent-evolve:regret-bounded-slate-decision:v1\x00"
58
+
59
+
60
+ def _canonical_json(value: object) -> bytes:
61
+ return json.dumps(
62
+ value,
63
+ allow_nan=False,
64
+ ensure_ascii=True,
65
+ separators=(",", ":"),
66
+ sort_keys=True,
67
+ ).encode("ascii", errors="strict")
68
+
69
+
70
+ def _hash(domain: bytes, value: object) -> str:
71
+ return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
72
+
73
+
74
+ def _finite_nonnegative(value: float, name: str) -> None:
75
+ if type(value) is not float or not math.isfinite(value) or value < 0.0:
76
+ raise ValueError(f"{name} must be finite and non-negative")
77
+
78
+
79
+ class SlateFutureValueAuthority(str, Enum):
80
+ ZERO = "zero"
81
+ DEVELOPMENT_ASSAY = "development_assay"
82
+ CALIBRATED = "calibrated"
83
+
84
+
85
+ @dataclass(frozen=True, slots=True, eq=False)
86
+ class SlateFutureValueEstimate:
87
+ """Pre-outcome lower/upper bounds in log-acquisition-equivalent units."""
88
+
89
+ slate_option_ids: tuple[str, ...]
90
+ information_value_lcb: float
91
+ descendant_value_lcb: float
92
+ risk_cost_ucb: float
93
+ authority: SlateFutureValueAuthority
94
+ evidence_receipt_sha256: str
95
+ policy_definition_sha256: str
96
+ estimate_sha256: str = field(init=False, default="")
97
+
98
+ def __post_init__(self) -> None:
99
+ if self.slate_option_ids != tuple(sorted(set(self.slate_option_ids))) or not (
100
+ self.slate_option_ids
101
+ ):
102
+ raise ValueError("slate_option_ids must be non-empty and canonical")
103
+ for name in (
104
+ "information_value_lcb",
105
+ "descendant_value_lcb",
106
+ "risk_cost_ucb",
107
+ ):
108
+ _finite_nonnegative(getattr(self, name), name)
109
+ if type(self.authority) is not SlateFutureValueAuthority:
110
+ raise TypeError("authority must be exact")
111
+ if self.authority is SlateFutureValueAuthority.ZERO and (
112
+ self.information_value_lcb != 0.0
113
+ or self.descendant_value_lcb != 0.0
114
+ ):
115
+ raise ValueError("zero authority cannot claim positive future value")
116
+ require_sha256(self.evidence_receipt_sha256, "evidence_receipt_sha256")
117
+ require_sha256(self.policy_definition_sha256, "policy_definition_sha256")
118
+ computed = _hash(_ESTIMATE_DOMAIN, self._unsigned_record())
119
+ if self.estimate_sha256 not in ("", computed):
120
+ raise ValueError("estimate_sha256 does not authenticate the estimate")
121
+ object.__setattr__(self, "estimate_sha256", computed)
122
+
123
+ @property
124
+ def net_future_value(self) -> float:
125
+ return (
126
+ self.information_value_lcb
127
+ + self.descendant_value_lcb
128
+ - self.risk_cost_ucb
129
+ )
130
+
131
+ def _unsigned_record(self) -> dict[str, object]:
132
+ return {
133
+ "schema_version": 1,
134
+ "slate_option_ids": list(self.slate_option_ids),
135
+ "information_value_lcb_hex": self.information_value_lcb.hex(),
136
+ "descendant_value_lcb_hex": self.descendant_value_lcb.hex(),
137
+ "risk_cost_ucb_hex": self.risk_cost_ucb.hex(),
138
+ "net_future_value_hex": self.net_future_value.hex(),
139
+ "authority": self.authority.value,
140
+ "evidence_receipt_sha256": self.evidence_receipt_sha256,
141
+ "policy_definition_sha256": self.policy_definition_sha256,
142
+ }
143
+
144
+ def to_record(self) -> dict[str, object]:
145
+ self.__post_init__()
146
+ return {**self._unsigned_record(), "estimate_sha256": self.estimate_sha256}
147
+
148
+ def __eq__(self, other: object) -> bool:
149
+ return (
150
+ type(other) is SlateFutureValueEstimate
151
+ and self.estimate_sha256 == other.estimate_sha256
152
+ )
153
+
154
+ __hash__ = None
155
+
156
+
157
+ @runtime_checkable
158
+ class SlateFutureValuePolicy(Protocol):
159
+ policy_id: str
160
+ policy_version: int
161
+ definition_sha256: str
162
+
163
+ def estimate(
164
+ self,
165
+ *,
166
+ request: SlateAllocationRequest,
167
+ reference_option_ids: tuple[str, ...],
168
+ slate_option_ids: tuple[str, ...],
169
+ reference_log_acquisition_value: float,
170
+ slate_log_acquisition_value: float,
171
+ ) -> SlateFutureValueEstimate: ...
172
+
173
+
174
+ @dataclass(frozen=True, slots=True)
175
+ class ZeroSlateFutureValuePolicy:
176
+ """Safe default: RBIE collapses to acquisition-certified selection."""
177
+
178
+ policy_id: str = field(init=False, default="zero_slate_future_value")
179
+ policy_version: int = field(init=False, default=1)
180
+ definition_sha256: str = field(
181
+ init=False,
182
+ default=hashlib.sha256(
183
+ b"agent-evolve:zero-slate-future-value:v1;all-lcbs=0;risk=0"
184
+ ).hexdigest(),
185
+ )
186
+
187
+ def estimate(
188
+ self,
189
+ *,
190
+ request: SlateAllocationRequest,
191
+ reference_option_ids: tuple[str, ...],
192
+ slate_option_ids: tuple[str, ...],
193
+ reference_log_acquisition_value: float,
194
+ slate_log_acquisition_value: float,
195
+ ) -> SlateFutureValueEstimate:
196
+ del request, reference_option_ids
197
+ if not math.isfinite(reference_log_acquisition_value) or not math.isfinite(
198
+ slate_log_acquisition_value
199
+ ):
200
+ raise ValueError("acquisition values must be finite")
201
+ return SlateFutureValueEstimate(
202
+ slate_option_ids=slate_option_ids,
203
+ information_value_lcb=0.0,
204
+ descendant_value_lcb=0.0,
205
+ risk_cost_ucb=0.0,
206
+ authority=SlateFutureValueAuthority.ZERO,
207
+ evidence_receipt_sha256=self.definition_sha256,
208
+ policy_definition_sha256=self.definition_sha256,
209
+ )
210
+
211
+
212
+ @dataclass(frozen=True, slots=True)
213
+ class ResidualInformationAssayValuePolicy:
214
+ """Explicitly development-only treatment for the first regret assay.
215
+
216
+ This policy does not pretend that residual information value is calibrated.
217
+ It exists to run the matched 2/5/10% challenger experiment and is rejected
218
+ by the broker unless ``allow_development_assay`` is explicitly enabled.
219
+ """
220
+
221
+ value_per_residual: float
222
+ maximum_credited_residuals: int = 1
223
+ policy_id: str = field(init=False, default="residual_information_assay")
224
+ policy_version: int = field(init=False, default=1)
225
+ definition_sha256: str = field(init=False, default="")
226
+
227
+ def __post_init__(self) -> None:
228
+ _finite_nonnegative(self.value_per_residual, "value_per_residual")
229
+ if self.value_per_residual == 0.0:
230
+ raise ValueError("assay value must be positive")
231
+ if (
232
+ type(self.maximum_credited_residuals) is not int
233
+ or self.maximum_credited_residuals < 1
234
+ ):
235
+ raise ValueError("maximum_credited_residuals must be positive")
236
+ object.__setattr__(
237
+ self,
238
+ "definition_sha256",
239
+ hashlib.sha256(
240
+ b"agent-evolve:residual-information-assay:v1;"
241
+ + self.value_per_residual.hex().encode("ascii")
242
+ + b";max="
243
+ + str(self.maximum_credited_residuals).encode("ascii")
244
+ ).hexdigest(),
245
+ )
246
+
247
+ def estimate(
248
+ self,
249
+ *,
250
+ request: SlateAllocationRequest,
251
+ reference_option_ids: tuple[str, ...],
252
+ slate_option_ids: tuple[str, ...],
253
+ reference_log_acquisition_value: float,
254
+ slate_log_acquisition_value: float,
255
+ ) -> SlateFutureValueEstimate:
256
+ del request
257
+ if not math.isfinite(reference_log_acquisition_value) or not math.isfinite(
258
+ slate_log_acquisition_value
259
+ ):
260
+ raise ValueError("acquisition values must be finite")
261
+ residual_count = len(set(slate_option_ids).difference(reference_option_ids))
262
+ credited = min(residual_count, self.maximum_credited_residuals)
263
+ evidence = _hash(
264
+ b"agent-evolve:residual-information-assay-evidence:v1\x00",
265
+ {
266
+ "policy_definition_sha256": self.definition_sha256,
267
+ "reference_option_ids": list(reference_option_ids),
268
+ "slate_option_ids": list(slate_option_ids),
269
+ "credited_residuals": credited,
270
+ },
271
+ )
272
+ return SlateFutureValueEstimate(
273
+ slate_option_ids=slate_option_ids,
274
+ information_value_lcb=float(credited * self.value_per_residual),
275
+ descendant_value_lcb=0.0,
276
+ risk_cost_ucb=0.0,
277
+ authority=SlateFutureValueAuthority.DEVELOPMENT_ASSAY,
278
+ evidence_receipt_sha256=evidence,
279
+ policy_definition_sha256=self.definition_sha256,
280
+ )
281
+
282
+
283
+ @dataclass(frozen=True, slots=True, eq=False)
284
+ class RegretBoundedSlateAssessment:
285
+ slate_option_ids: tuple[str, ...]
286
+ log_acquisition_value: float
287
+ acquisition_log_gap_from_reference: float
288
+ acquisition_retention_ratio: float
289
+ inside_regret_envelope: bool
290
+ future_value: SlateFutureValueEstimate | None
291
+ broker_value: float | None
292
+ assessment_sha256: str = field(init=False, default="")
293
+
294
+ def __post_init__(self) -> None:
295
+ if self.slate_option_ids != tuple(sorted(set(self.slate_option_ids))) or not (
296
+ self.slate_option_ids
297
+ ):
298
+ raise ValueError("assessment slate must be non-empty and canonical")
299
+ for name in (
300
+ "log_acquisition_value",
301
+ "acquisition_log_gap_from_reference",
302
+ "acquisition_retention_ratio",
303
+ ):
304
+ value = getattr(self, name)
305
+ if type(value) is not float or not math.isfinite(value):
306
+ raise ValueError(f"{name} must be finite")
307
+ if not 0.0 < self.acquisition_retention_ratio <= 1.0:
308
+ raise ValueError("acquisition retention ratio must lie in (0, 1]")
309
+ if type(self.inside_regret_envelope) is not bool:
310
+ raise TypeError("inside_regret_envelope must be exact")
311
+ if self.inside_regret_envelope:
312
+ if type(self.future_value) is not SlateFutureValueEstimate:
313
+ raise TypeError("admissible slate requires an exact future estimate")
314
+ self.future_value.__post_init__()
315
+ if self.future_value.slate_option_ids != self.slate_option_ids:
316
+ raise ValueError("future value belongs to a foreign slate")
317
+ if type(self.broker_value) is not float or not math.isfinite(
318
+ self.broker_value
319
+ ):
320
+ raise ValueError("admissible slate requires finite broker value")
321
+ elif self.future_value is not None or self.broker_value is not None:
322
+ raise ValueError("inadmissible slate cannot receive future authority")
323
+ computed = _hash(_ASSESSMENT_DOMAIN, self._unsigned_record())
324
+ if self.assessment_sha256 not in ("", computed):
325
+ raise ValueError("assessment_sha256 does not authenticate the value")
326
+ object.__setattr__(self, "assessment_sha256", computed)
327
+
328
+ def _unsigned_record(self) -> dict[str, object]:
329
+ return {
330
+ "schema_version": 1,
331
+ "slate_option_ids": list(self.slate_option_ids),
332
+ "log_acquisition_value_hex": self.log_acquisition_value.hex(),
333
+ "acquisition_log_gap_from_reference_hex": (
334
+ self.acquisition_log_gap_from_reference.hex()
335
+ ),
336
+ "acquisition_retention_ratio_hex": (
337
+ self.acquisition_retention_ratio.hex()
338
+ ),
339
+ "inside_regret_envelope": self.inside_regret_envelope,
340
+ "future_value": (
341
+ None if self.future_value is None else self.future_value.to_record()
342
+ ),
343
+ "broker_value_hex": (
344
+ None if self.broker_value is None else self.broker_value.hex()
345
+ ),
346
+ }
347
+
348
+ def to_record(self) -> dict[str, object]:
349
+ self.__post_init__()
350
+ return {
351
+ **self._unsigned_record(),
352
+ "assessment_sha256": self.assessment_sha256,
353
+ }
354
+
355
+ def __eq__(self, other: object) -> bool:
356
+ return (
357
+ type(other) is RegretBoundedSlateAssessment
358
+ and self.assessment_sha256 == other.assessment_sha256
359
+ )
360
+
361
+ __hash__ = None
362
+
363
+
364
+ @dataclass(frozen=True, slots=True, eq=False)
365
+ class RegretBoundedSlateDecision:
366
+ request: SlateAllocationRequest
367
+ selected: tuple[AllocatedSlateMember, ...]
368
+ reference_option_ids: tuple[str, ...]
369
+ selected_option_ids: tuple[str, ...]
370
+ reference_log_acquisition_value: float
371
+ selected_log_acquisition_value: float
372
+ acquisition_regret: float
373
+ acquisition_retention_ratio: float
374
+ minimum_acquisition_retention_ratio: float
375
+ minimum_residual_audit_members: int
376
+ tie_tolerance: float
377
+ reference_member_count: int
378
+ feasible_slate_count: int
379
+ admissible_slate_count: int
380
+ assessments: tuple[RegretBoundedSlateAssessment, ...]
381
+ selected_future_value: SlateFutureValueEstimate
382
+ selected_broker_value: float
383
+ calibration_error_bound: float | None
384
+ conditional_return_gap_lower_bound: float | None
385
+ score_request: FiniteAcquisitionBatchScoreRequest
386
+ score_decision: FiniteAcquisitionBatchScoreDecision
387
+ memory_dose_assessment: PortfolioMemoryDoseAssessment | None
388
+ policy_definition_sha256: str
389
+ decision_sha256: str = field(init=False, default="")
390
+
391
+ policy_id = POLICY_ID
392
+ policy_version = POLICY_VERSION
393
+
394
+ def __post_init__(self) -> None:
395
+ if type(self.request) is not SlateAllocationRequest:
396
+ raise TypeError("request must be exact")
397
+ self.request.revalidate()
398
+ if type(self.selected) is not tuple or len(self.selected) != (
399
+ self.request.portfolio_size
400
+ ):
401
+ raise ValueError("selected must fill the evaluation portfolio")
402
+ if any(
403
+ type(value) is not AllocatedSlateMember
404
+ or value.role is not SlateAllocationRole.REGRET_BOUNDED_INFORMATION
405
+ for value in self.selected
406
+ ):
407
+ raise ValueError("selected members must carry the RBIE role")
408
+ for value in self.selected:
409
+ value.__post_init__()
410
+ if not math.isclose(
411
+ value.role_score,
412
+ self.selected_broker_value,
413
+ rel_tol=0.0,
414
+ abs_tol=1e-12,
415
+ ):
416
+ raise ValueError("selected role score differs from broker value")
417
+ for name in ("reference_option_ids", "selected_option_ids"):
418
+ values = getattr(self, name)
419
+ if values != tuple(sorted(set(values))) or len(values) != (
420
+ self.request.portfolio_size
421
+ ):
422
+ raise ValueError(f"{name} must be a canonical complete slate")
423
+ if tuple(sorted(value.option_id for value in self.selected)) != (
424
+ self.selected_option_ids
425
+ ):
426
+ raise ValueError("selected identities differ from selected slate")
427
+ for name in (
428
+ "reference_log_acquisition_value",
429
+ "selected_log_acquisition_value",
430
+ "acquisition_regret",
431
+ "acquisition_retention_ratio",
432
+ "minimum_acquisition_retention_ratio",
433
+ "tie_tolerance",
434
+ "selected_broker_value",
435
+ ):
436
+ value = getattr(self, name)
437
+ if type(value) is not float or not math.isfinite(value):
438
+ raise ValueError(f"{name} must be finite")
439
+ if (
440
+ type(self.minimum_residual_audit_members) is not int
441
+ or not 0
442
+ <= self.minimum_residual_audit_members
443
+ < self.request.portfolio_size
444
+ ):
445
+ raise ValueError(
446
+ "minimum_residual_audit_members must lie in [0, portfolio_size)"
447
+ )
448
+ if self.acquisition_regret < 0.0:
449
+ raise ValueError("acquisition regret must be non-negative")
450
+ if self.tie_tolerance < 0.0:
451
+ raise ValueError("tie_tolerance must be non-negative")
452
+ expected_regret = max(
453
+ 0.0,
454
+ self.reference_log_acquisition_value
455
+ - self.selected_log_acquisition_value,
456
+ )
457
+ if not math.isclose(
458
+ self.acquisition_regret, expected_regret, rel_tol=0.0, abs_tol=1e-12
459
+ ):
460
+ raise ValueError("acquisition regret does not close")
461
+ expected_ratio = math.exp(
462
+ min(
463
+ 0.0,
464
+ self.selected_log_acquisition_value
465
+ - self.reference_log_acquisition_value,
466
+ )
467
+ )
468
+ if not math.isclose(
469
+ self.acquisition_retention_ratio,
470
+ expected_ratio,
471
+ rel_tol=0.0,
472
+ abs_tol=1e-12,
473
+ ):
474
+ raise ValueError("selected acquisition ratio does not close")
475
+ if not (
476
+ 0.0
477
+ < self.minimum_acquisition_retention_ratio
478
+ <= self.acquisition_retention_ratio
479
+ <= 1.0
480
+ ):
481
+ raise ValueError("selected slate escapes its regret envelope")
482
+ if self.reference_member_count != len(
483
+ set(self.selected_option_ids).intersection(self.reference_option_ids)
484
+ ):
485
+ raise ValueError("reference member count does not close")
486
+ selected_residual_members = (
487
+ self.request.portfolio_size - self.reference_member_count
488
+ )
489
+ if selected_residual_members < self.minimum_residual_audit_members:
490
+ raise ValueError("selected slate violates the residual audit floor")
491
+ if (
492
+ type(self.feasible_slate_count) is not int
493
+ or type(self.admissible_slate_count) is not int
494
+ or not 1 <= self.admissible_slate_count <= self.feasible_slate_count
495
+ ):
496
+ raise ValueError("slate counts are invalid")
497
+ if (
498
+ type(self.assessments) is not tuple
499
+ or len(self.assessments) != self.feasible_slate_count
500
+ or any(
501
+ type(value) is not RegretBoundedSlateAssessment
502
+ for value in self.assessments
503
+ )
504
+ ):
505
+ raise ValueError("assessments must cover every feasible slate")
506
+ for value in self.assessments:
507
+ value.__post_init__()
508
+ if tuple(value.slate_option_ids for value in self.assessments) != tuple(
509
+ sorted(value.slate_option_ids for value in self.assessments)
510
+ ):
511
+ raise ValueError("assessments must use canonical slate order")
512
+ selected_assessment = next(
513
+ (
514
+ value
515
+ for value in self.assessments
516
+ if value.slate_option_ids == self.selected_option_ids
517
+ ),
518
+ None,
519
+ )
520
+ if (
521
+ selected_assessment is None
522
+ or selected_assessment.future_value != self.selected_future_value
523
+ or selected_assessment.broker_value != self.selected_broker_value
524
+ ):
525
+ raise ValueError("selected assessment does not close")
526
+ self.selected_future_value.__post_init__()
527
+ if self.calibration_error_bound is None:
528
+ if self.conditional_return_gap_lower_bound is not None:
529
+ raise ValueError("conditional bound requires calibration error")
530
+ else:
531
+ _finite_nonnegative(
532
+ self.calibration_error_bound, "calibration_error_bound"
533
+ )
534
+ expected_bound = -self.acquisition_regret - 2.0 * (
535
+ self.calibration_error_bound
536
+ )
537
+ if self.conditional_return_gap_lower_bound is None or not math.isclose(
538
+ self.conditional_return_gap_lower_bound,
539
+ expected_bound,
540
+ rel_tol=0.0,
541
+ abs_tol=1e-12,
542
+ ):
543
+ raise ValueError("conditional return bound does not close")
544
+ if type(self.score_request) is not FiniteAcquisitionBatchScoreRequest:
545
+ raise TypeError("score_request must be exact")
546
+ if type(self.score_decision) is not FiniteAcquisitionBatchScoreDecision:
547
+ raise TypeError("score_decision must be exact")
548
+ validate_finite_acquisition_batch_score_decision(
549
+ self.score_request, self.score_decision
550
+ )
551
+ scored = {
552
+ value.slate.candidate_ids: value.log_acquisition_value
553
+ for value in self.score_decision.scores
554
+ }
555
+ assessment_by_ids = {
556
+ value.slate_option_ids: value for value in self.assessments
557
+ }
558
+ if set(scored) != set(assessment_by_ids):
559
+ raise ValueError("assessments differ from the frozen score request")
560
+ for slate_ids, score in scored.items():
561
+ assessment = assessment_by_ids[slate_ids]
562
+ if not math.isclose(
563
+ assessment.log_acquisition_value,
564
+ score,
565
+ rel_tol=0.0,
566
+ abs_tol=1e-12,
567
+ ):
568
+ raise ValueError("assessment acquisition value does not replay")
569
+ expected_gap = score - self.reference_log_acquisition_value
570
+ if not math.isclose(
571
+ assessment.acquisition_log_gap_from_reference,
572
+ expected_gap,
573
+ rel_tol=0.0,
574
+ abs_tol=1e-12,
575
+ ):
576
+ raise ValueError("assessment acquisition gap does not close")
577
+ expected_retention = math.exp(min(0.0, expected_gap))
578
+ if not math.isclose(
579
+ assessment.acquisition_retention_ratio,
580
+ expected_retention,
581
+ rel_tol=0.0,
582
+ abs_tol=1e-12,
583
+ ):
584
+ raise ValueError("assessment acquisition retention does not close")
585
+ expected_inside = expected_gap >= (
586
+ math.log(self.minimum_acquisition_retention_ratio)
587
+ - self.tie_tolerance
588
+ )
589
+ if assessment.inside_regret_envelope is not expected_inside:
590
+ raise ValueError("assessment regret-envelope status does not replay")
591
+ if assessment.future_value is not None:
592
+ expected_broker = expected_gap + assessment.future_value.net_future_value
593
+ if assessment.broker_value is None or not math.isclose(
594
+ assessment.broker_value,
595
+ expected_broker,
596
+ rel_tol=0.0,
597
+ abs_tol=1e-12,
598
+ ):
599
+ raise ValueError("assessment broker value does not close")
600
+ if sum(
601
+ value.inside_regret_envelope
602
+ and (
603
+ self.request.portfolio_size
604
+ - len(
605
+ set(value.slate_option_ids).intersection(
606
+ self.reference_option_ids
607
+ )
608
+ )
609
+ >= self.minimum_residual_audit_members
610
+ )
611
+ for value in self.assessments
612
+ ) != self.admissible_slate_count:
613
+ raise ValueError("admissible slate count does not close")
614
+ if not math.isclose(
615
+ scored[self.reference_option_ids],
616
+ self.reference_log_acquisition_value,
617
+ rel_tol=0.0,
618
+ abs_tol=1e-12,
619
+ ) or not math.isclose(
620
+ scored[self.selected_option_ids],
621
+ self.selected_log_acquisition_value,
622
+ rel_tol=0.0,
623
+ abs_tol=1e-12,
624
+ ):
625
+ raise ValueError("reference or selected acquisition value does not replay")
626
+ if self.memory_dose_assessment is not None:
627
+ self.memory_dose_assessment.__post_init__()
628
+ if not self.memory_dose_assessment.passed:
629
+ raise ValueError("selected slate violates memory dose")
630
+ require_sha256(self.policy_definition_sha256, "policy_definition_sha256")
631
+ computed = _hash(_DECISION_DOMAIN, self._unsigned_record())
632
+ if self.decision_sha256 not in ("", computed):
633
+ raise ValueError("decision_sha256 does not authenticate the decision")
634
+ object.__setattr__(self, "decision_sha256", computed)
635
+
636
+ def revalidate(self) -> None:
637
+ self.__post_init__()
638
+
639
+ def _unsigned_record(self) -> dict[str, object]:
640
+ return {
641
+ "schema_version": 1,
642
+ "event_type": "regret_bounded_information_slate_allocated",
643
+ "policy_id": self.policy_id,
644
+ "policy_version": self.policy_version,
645
+ "policy_definition_sha256": self.policy_definition_sha256,
646
+ "request": self.request.to_record(),
647
+ "selected": [value.to_record() for value in self.selected],
648
+ "reference_option_ids": list(self.reference_option_ids),
649
+ "selected_option_ids": list(self.selected_option_ids),
650
+ "reference_log_acquisition_value_hex": (
651
+ self.reference_log_acquisition_value.hex()
652
+ ),
653
+ "selected_log_acquisition_value_hex": (
654
+ self.selected_log_acquisition_value.hex()
655
+ ),
656
+ "acquisition_regret_hex": self.acquisition_regret.hex(),
657
+ "acquisition_retention_ratio_hex": (
658
+ self.acquisition_retention_ratio.hex()
659
+ ),
660
+ "minimum_acquisition_retention_ratio_hex": (
661
+ self.minimum_acquisition_retention_ratio.hex()
662
+ ),
663
+ "minimum_residual_audit_members": (
664
+ self.minimum_residual_audit_members
665
+ ),
666
+ "selected_residual_member_count": (
667
+ self.request.portfolio_size - self.reference_member_count
668
+ ),
669
+ "tie_tolerance_hex": self.tie_tolerance.hex(),
670
+ "reference_member_count": self.reference_member_count,
671
+ "feasible_slate_count": self.feasible_slate_count,
672
+ "admissible_slate_count": self.admissible_slate_count,
673
+ "assessments": [value.to_record() for value in self.assessments],
674
+ "selected_future_value": self.selected_future_value.to_record(),
675
+ "selected_broker_value_hex": self.selected_broker_value.hex(),
676
+ "calibration_error_bound_hex": (
677
+ None
678
+ if self.calibration_error_bound is None
679
+ else self.calibration_error_bound.hex()
680
+ ),
681
+ "conditional_return_gap_lower_bound_hex": (
682
+ None
683
+ if self.conditional_return_gap_lower_bound is None
684
+ else self.conditional_return_gap_lower_bound.hex()
685
+ ),
686
+ "score_request": self.score_request.to_record(),
687
+ "score_decision": self.score_decision.to_record(),
688
+ "memory_dose_assessment": (
689
+ None
690
+ if self.memory_dose_assessment is None
691
+ else self.memory_dose_assessment.to_record()
692
+ ),
693
+ "certificate_scope": (
694
+ "conditional_on_frozen_acquisition_calibration_not_sota"
695
+ ),
696
+ }
697
+
698
+ def to_record(self) -> dict[str, object]:
699
+ self.revalidate()
700
+ return {**self._unsigned_record(), "decision_sha256": self.decision_sha256}
701
+
702
+ def __eq__(self, other: object) -> bool:
703
+ return (
704
+ type(other) is RegretBoundedSlateDecision
705
+ and self.decision_sha256 == other.decision_sha256
706
+ )
707
+
708
+ __hash__ = None
709
+
710
+ @property
711
+ def prior_only(self) -> bool:
712
+ return True
713
+
714
+ @property
715
+ def administered_card_keys(self) -> tuple[str, ...]:
716
+ selected_ids = {value.option_id for value in self.selected}
717
+ return tuple(
718
+ sorted(
719
+ {
720
+ card_key
721
+ for member in self.request.slate.members
722
+ if member.option_id in selected_ids
723
+ for card_key in member.supporting_card_keys
724
+ if card_key in self.request.assigned_card_keys
725
+ }
726
+ )
727
+ )
728
+
729
+
730
+ @dataclass(frozen=True, slots=True)
731
+ class RegretBoundedSlatePolicy:
732
+ context_provider: AcquisitionCertifiedSlateContextProvider
733
+ scorer: FiniteAcquisitionBatchScorePolicy
734
+ future_value_policy: SlateFutureValuePolicy = field(
735
+ default_factory=ZeroSlateFutureValuePolicy
736
+ )
737
+ minimum_acquisition_retention_ratio: float = 1.0
738
+ minimum_residual_audit_members: int = 0
739
+ calibration_error_bound: float | None = None
740
+ allow_development_assay: bool = False
741
+ exact_combination_limit: int = 250_000
742
+ tie_tolerance: float = 1e-12
743
+ policy_id: str = field(init=False, default=POLICY_ID)
744
+ policy_version: int = field(init=False, default=POLICY_VERSION)
745
+ definition_sha256: str = field(init=False, default="")
746
+
747
+ def __post_init__(self) -> None:
748
+ if not isinstance(
749
+ self.context_provider, AcquisitionCertifiedSlateContextProvider
750
+ ):
751
+ raise TypeError("context_provider must implement its exact port")
752
+ scorer_identity = finite_acquisition_policy_identity(self.scorer)
753
+ if not isinstance(self.future_value_policy, SlateFutureValuePolicy):
754
+ raise TypeError("future_value_policy must implement its port")
755
+ future_identity = (
756
+ self.future_value_policy.policy_id,
757
+ self.future_value_policy.policy_version,
758
+ self.future_value_policy.definition_sha256,
759
+ )
760
+ if (
761
+ type(future_identity[0]) is not str
762
+ or not future_identity[0]
763
+ or type(future_identity[1]) is not int
764
+ or future_identity[1] <= 0
765
+ ):
766
+ raise ValueError("future value policy identity is invalid")
767
+ require_sha256(future_identity[2], "future value definition_sha256")
768
+ if (
769
+ type(self.minimum_acquisition_retention_ratio) is not float
770
+ or not math.isfinite(self.minimum_acquisition_retention_ratio)
771
+ or not 0.0 < self.minimum_acquisition_retention_ratio <= 1.0
772
+ ):
773
+ raise ValueError("minimum acquisition retention must lie in (0, 1]")
774
+ if (
775
+ type(self.minimum_residual_audit_members) is not int
776
+ or self.minimum_residual_audit_members < 0
777
+ ):
778
+ raise ValueError("minimum residual audit members must be non-negative")
779
+ if self.calibration_error_bound is not None:
780
+ _finite_nonnegative(
781
+ self.calibration_error_bound, "calibration_error_bound"
782
+ )
783
+ if type(self.allow_development_assay) is not bool:
784
+ raise TypeError("allow_development_assay must be exact")
785
+ if type(self.exact_combination_limit) is not int or (
786
+ self.exact_combination_limit < 1
787
+ ):
788
+ raise ValueError("exact_combination_limit must be positive")
789
+ _finite_nonnegative(self.tie_tolerance, "tie_tolerance")
790
+ record = {
791
+ "schema_version": 1,
792
+ "policy_id": POLICY_ID,
793
+ "policy_version": POLICY_VERSION,
794
+ "context_provider": {
795
+ "provider_id": self.context_provider.provider_id,
796
+ "provider_version": self.context_provider.provider_version,
797
+ "definition_sha256": self.context_provider.definition_sha256,
798
+ },
799
+ "scorer": {
800
+ "policy_id": scorer_identity[0],
801
+ "policy_version": scorer_identity[1],
802
+ "definition_sha256": scorer_identity[2],
803
+ },
804
+ "future_value_policy": {
805
+ "policy_id": future_identity[0],
806
+ "policy_version": future_identity[1],
807
+ "definition_sha256": future_identity[2],
808
+ },
809
+ "minimum_acquisition_retention_ratio_hex": (
810
+ self.minimum_acquisition_retention_ratio.hex()
811
+ ),
812
+ "minimum_residual_audit_members": (
813
+ self.minimum_residual_audit_members
814
+ ),
815
+ "calibration_error_bound_hex": (
816
+ None
817
+ if self.calibration_error_bound is None
818
+ else self.calibration_error_bound.hex()
819
+ ),
820
+ "allow_development_assay": self.allow_development_assay,
821
+ "exact_combination_limit": self.exact_combination_limit,
822
+ "tie_tolerance_hex": self.tie_tolerance.hex(),
823
+ "reference": "maximum-anchor-count-feasible-slate",
824
+ "authority": "trusted-code-only",
825
+ "outcome_access": "strictly-prior-only",
826
+ }
827
+ object.__setattr__(self, "definition_sha256", _hash(_POLICY_DOMAIN, record))
828
+
829
+ def select(self, request: SlateAllocationRequest) -> RegretBoundedSlateDecision:
830
+ self.__post_init__()
831
+ if type(request) is not SlateAllocationRequest:
832
+ raise TypeError("request must be exact")
833
+ request.revalidate()
834
+ if self.minimum_residual_audit_members >= request.portfolio_size:
835
+ raise ValueError(
836
+ "minimum residual audit members must be below portfolio size"
837
+ )
838
+ context = self.context_provider.context_for(
839
+ request.slate.finite_contract_sha256
840
+ )
841
+ if type(context) is not AcquisitionCertifiedSlateContext:
842
+ raise TypeError("context provider returned a foreign context")
843
+ context.__post_init__()
844
+ if len(context.reference_option_ids) != request.portfolio_size:
845
+ raise ValueError("reference must exactly fill the evaluation portfolio")
846
+ feasible = feasible_slate_option_id_subsets(request)
847
+ if not feasible:
848
+ raise ValueError("proposal contains no hard-feasible evaluation slate")
849
+ if len(feasible) > self.exact_combination_limit:
850
+ raise ValueError("feasible slate count exceeds exact broker limit")
851
+ slate_ids = {value.option_id for value in request.slate.members}
852
+ candidate_by_id = {value.candidate_id: value for value in context.candidates}
853
+ if not slate_ids <= set(candidate_by_id):
854
+ raise ValueError("numerical context does not cover the proposal slate")
855
+ reference_set = set(context.reference_option_ids)
856
+ maximum_reference_count = max(
857
+ len(set(value).intersection(reference_set)) for value in feasible
858
+ )
859
+ if maximum_reference_count != request.portfolio_size:
860
+ raise ValueError("complete numerical reference is not hard-feasible")
861
+ reference = min(
862
+ value
863
+ for value in feasible
864
+ if len(set(value).intersection(reference_set)) == maximum_reference_count
865
+ )
866
+ score_request = FiniteAcquisitionBatchScoreRequest(
867
+ campaign_scope_sha256=context.campaign_scope_sha256,
868
+ cutoff_index=context.cutoff_index,
869
+ seed=context.seed,
870
+ objectives=context.objectives,
871
+ observations=context.observations,
872
+ candidates=tuple(candidate_by_id[value] for value in sorted(slate_ids)),
873
+ slates=tuple(FiniteAcquisitionSlate(value) for value in feasible),
874
+ )
875
+ score_decision = self.scorer.score(score_request)
876
+ validate_finite_acquisition_batch_score_decision(
877
+ score_request, score_decision
878
+ )
879
+ expected_scorer = finite_acquisition_policy_identity(self.scorer)
880
+ if (
881
+ score_decision.policy_id,
882
+ score_decision.policy_version,
883
+ score_decision.policy_definition_sha256,
884
+ ) != expected_scorer:
885
+ raise ValueError("batch scorer returned a foreign policy identity")
886
+ score_by_ids = {
887
+ value.slate.candidate_ids: value.log_acquisition_value
888
+ for value in score_decision.scores
889
+ }
890
+ reference_value = float(score_by_ids[reference])
891
+ log_floor = math.log(self.minimum_acquisition_retention_ratio)
892
+ assessments: list[RegretBoundedSlateAssessment] = []
893
+ for slate_option_ids in feasible:
894
+ score = float(score_by_ids[slate_option_ids])
895
+ gap = score - reference_value
896
+ ratio = math.exp(min(0.0, gap))
897
+ inside = gap >= log_floor - self.tie_tolerance
898
+ estimate = None
899
+ broker_value = None
900
+ if inside:
901
+ estimate = self.future_value_policy.estimate(
902
+ request=request,
903
+ reference_option_ids=reference,
904
+ slate_option_ids=slate_option_ids,
905
+ reference_log_acquisition_value=reference_value,
906
+ slate_log_acquisition_value=score,
907
+ )
908
+ if type(estimate) is not SlateFutureValueEstimate:
909
+ raise TypeError("future value policy returned a foreign estimate")
910
+ estimate.__post_init__()
911
+ if estimate.policy_definition_sha256 != (
912
+ self.future_value_policy.definition_sha256
913
+ ):
914
+ raise ValueError("future value estimate has foreign policy authority")
915
+ if (
916
+ estimate.authority
917
+ is SlateFutureValueAuthority.DEVELOPMENT_ASSAY
918
+ and not self.allow_development_assay
919
+ ):
920
+ raise ValueError(
921
+ "development-only future value lacks explicit authority"
922
+ )
923
+ broker_value = gap + estimate.net_future_value
924
+ assessments.append(
925
+ RegretBoundedSlateAssessment(
926
+ slate_option_ids=slate_option_ids,
927
+ log_acquisition_value=score,
928
+ acquisition_log_gap_from_reference=gap,
929
+ acquisition_retention_ratio=ratio,
930
+ inside_regret_envelope=inside,
931
+ future_value=estimate,
932
+ broker_value=broker_value,
933
+ )
934
+ )
935
+ admissible = tuple(
936
+ value
937
+ for value in assessments
938
+ if value.inside_regret_envelope
939
+ and (
940
+ request.portfolio_size
941
+ - len(set(value.slate_option_ids).intersection(reference_set))
942
+ >= self.minimum_residual_audit_members
943
+ )
944
+ )
945
+ if not admissible:
946
+ raise ValueError(
947
+ "no regret-admissible slate satisfies the residual audit floor"
948
+ )
949
+ best_value = max(value.broker_value for value in admissible)
950
+ assert best_value is not None
951
+ tied = tuple(
952
+ value
953
+ for value in admissible
954
+ if value.broker_value is not None
955
+ and value.broker_value >= best_value - self.tie_tolerance
956
+ )
957
+ reference_assessment = next(
958
+ value for value in assessments if value.slate_option_ids == reference
959
+ )
960
+ selected_assessment = (
961
+ reference_assessment
962
+ if reference_assessment in tied
963
+ else min(tied, key=lambda value: value.slate_option_ids)
964
+ )
965
+ selected_ids = selected_assessment.slate_option_ids
966
+ member_by_id = {value.option_id: value for value in request.slate.members}
967
+ selected_members = tuple(
968
+ sorted(
969
+ (member_by_id[value] for value in selected_ids),
970
+ key=lambda value: value.model_rank,
971
+ )
972
+ )
973
+ memory_dose_assessment = (
974
+ None
975
+ if request.memory_dose_contract is None
976
+ else assess_allocated_slate_memory_dose(request, selected_members)
977
+ )
978
+ if memory_dose_assessment is not None and not memory_dose_assessment.passed:
979
+ raise AssertionError("broker winner violated enumerated memory dose")
980
+ selected_value = float(score_by_ids[selected_ids])
981
+ acquisition_regret = max(0.0, reference_value - selected_value)
982
+ selected_future_value = selected_assessment.future_value
983
+ selected_broker_value = selected_assessment.broker_value
984
+ assert selected_future_value is not None
985
+ assert selected_broker_value is not None
986
+ conditional_bound = (
987
+ None
988
+ if self.calibration_error_bound is None
989
+ else -acquisition_regret - 2.0 * self.calibration_error_bound
990
+ )
991
+ return RegretBoundedSlateDecision(
992
+ request=request,
993
+ selected=tuple(
994
+ AllocatedSlateMember(
995
+ role=SlateAllocationRole.REGRET_BOUNDED_INFORMATION,
996
+ option_id=value.option_id,
997
+ option_identity_sha256=value.option_identity_sha256,
998
+ model_rank=value.model_rank,
999
+ role_score=float(selected_broker_value),
1000
+ )
1001
+ for value in selected_members
1002
+ ),
1003
+ reference_option_ids=reference,
1004
+ selected_option_ids=selected_ids,
1005
+ reference_log_acquisition_value=reference_value,
1006
+ selected_log_acquisition_value=selected_value,
1007
+ acquisition_regret=float(acquisition_regret),
1008
+ acquisition_retention_ratio=float(
1009
+ math.exp(min(0.0, selected_value - reference_value))
1010
+ ),
1011
+ minimum_acquisition_retention_ratio=(
1012
+ self.minimum_acquisition_retention_ratio
1013
+ ),
1014
+ minimum_residual_audit_members=(
1015
+ self.minimum_residual_audit_members
1016
+ ),
1017
+ tie_tolerance=self.tie_tolerance,
1018
+ reference_member_count=len(
1019
+ set(selected_ids).intersection(reference_set)
1020
+ ),
1021
+ feasible_slate_count=len(feasible),
1022
+ admissible_slate_count=len(admissible),
1023
+ assessments=tuple(assessments),
1024
+ selected_future_value=selected_future_value,
1025
+ selected_broker_value=float(selected_broker_value),
1026
+ calibration_error_bound=self.calibration_error_bound,
1027
+ conditional_return_gap_lower_bound=conditional_bound,
1028
+ score_request=score_request,
1029
+ score_decision=score_decision,
1030
+ memory_dose_assessment=memory_dose_assessment,
1031
+ policy_definition_sha256=self.definition_sha256,
1032
+ )
1033
+
1034
+ def to_record(self) -> dict[str, object]:
1035
+ self.__post_init__()
1036
+ scorer = finite_acquisition_policy_identity(self.scorer)
1037
+ return {
1038
+ "policy_id": self.policy_id,
1039
+ "policy_version": self.policy_version,
1040
+ "definition_sha256": self.definition_sha256,
1041
+ "context_provider": {
1042
+ "provider_id": self.context_provider.provider_id,
1043
+ "provider_version": self.context_provider.provider_version,
1044
+ "definition_sha256": self.context_provider.definition_sha256,
1045
+ },
1046
+ "scorer": {
1047
+ "policy_id": scorer[0],
1048
+ "policy_version": scorer[1],
1049
+ "definition_sha256": scorer[2],
1050
+ },
1051
+ "future_value_policy": {
1052
+ "policy_id": self.future_value_policy.policy_id,
1053
+ "policy_version": self.future_value_policy.policy_version,
1054
+ "definition_sha256": self.future_value_policy.definition_sha256,
1055
+ },
1056
+ "minimum_acquisition_retention_ratio_hex": (
1057
+ self.minimum_acquisition_retention_ratio.hex()
1058
+ ),
1059
+ "minimum_residual_audit_members": (
1060
+ self.minimum_residual_audit_members
1061
+ ),
1062
+ "calibration_error_bound_hex": (
1063
+ None
1064
+ if self.calibration_error_bound is None
1065
+ else self.calibration_error_bound.hex()
1066
+ ),
1067
+ "allow_development_assay": self.allow_development_assay,
1068
+ "exact_combination_limit": self.exact_combination_limit,
1069
+ "tie_tolerance_hex": self.tie_tolerance.hex(),
1070
+ }
1071
+
1072
+
1073
+ __all__ = [
1074
+ "POLICY_ID",
1075
+ "POLICY_VERSION",
1076
+ "RegretBoundedSlateAssessment",
1077
+ "RegretBoundedSlateDecision",
1078
+ "RegretBoundedSlatePolicy",
1079
+ "ResidualInformationAssayValuePolicy",
1080
+ "SlateFutureValueAuthority",
1081
+ "SlateFutureValueEstimate",
1082
+ "SlateFutureValuePolicy",
1083
+ "ZeroSlateFutureValuePolicy",
1084
+ ]