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,1527 @@
1
+ """Generic target-conditioned, evaluator-updated portfolio acquisition.
2
+
3
+ The policy is deliberately split from workload adapters and provider code. A
4
+ caller supplies an authenticated affine frontier target, a portable numeric
5
+ feature row for every member of a sealed slate, a complete realizable-set
6
+ receipt, and an immutable linear-Gaussian state. The policy scores and exactly
7
+ selects one feasible portfolio. A separate generation-barrier update consumes
8
+ outcomes for selected members only.
9
+
10
+ No workload, model, provider, option-name, or evaluator implementation is part
11
+ of the scoring interface. Optional workload knowledge belongs in a separately
12
+ authenticated pre-outcome feature projector, not in this policy.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import hashlib
18
+ from dataclasses import dataclass
19
+ from enum import Enum
20
+ from itertools import combinations
21
+ import json
22
+ import math
23
+ import re
24
+ from statistics import fmean
25
+ from typing import ClassVar, Sequence
26
+
27
+ from agent_evolve.domain.patch import require_sha256
28
+ from agent_evolve.policies.selection.calibrated_slate import (
29
+ CalibratedSlateMember,
30
+ SlateAllocationRequest,
31
+ assess_allocated_slate_memory_dose,
32
+ )
33
+ from agent_evolve.ports.frontier_target import CampaignPortfolioFrontierTarget
34
+ from agent_evolve.ports.portfolio_memory_dose import PortfolioMemoryDoseAssessment
35
+
36
+
37
+ POLICY_ID = "target_conditioned_prequential_realizable_portfolio"
38
+ POLICY_VERSION = 1
39
+ POLICY_DEFINITION_SHA256 = hashlib.sha256(
40
+ b"agent-evolve:target-conditioned-prequential-realizable-portfolio:v1;"
41
+ b"input=sealed-slate,prior-only-affine-target,portable-features,"
42
+ b"immutable-linear-gaussian-state,complete-realizable-set;"
43
+ b"heads=normalized-marginal-archive-utility,target-achievement;"
44
+ b"scoring=within-slate-z-marginal-plus-bounded-direction-plus-"
45
+ b"finite-horizon-epistemic;selection=exact-set-sum-canonical-ties;"
46
+ b"updates=selected-outcomes-only-at-generation-barrier;"
47
+ b"workload-model-provider-option-name-fields=false"
48
+ ).hexdigest()
49
+
50
+ BASE_REALIZABILITY_PROJECTOR_ID = "sealed_slate_base_realizability"
51
+ BASE_REALIZABILITY_PROJECTOR_VERSION = 1
52
+ BASE_REALIZABILITY_DEFINITION_SHA256 = hashlib.sha256(
53
+ b"agent-evolve:sealed-slate-base-realizability:v1;"
54
+ b"constraints=cardinality,required-members,pairwise-compatibility,"
55
+ b"minimum-distinct-families,bounded-memory-dose;"
56
+ b"enumeration=complete;ties=canonical-option-id-set"
57
+ ).hexdigest()
58
+
59
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
60
+ _FEATURE = re.compile(r"^[a-z][a-z0-9_]{0,127}$")
61
+ _HEAD_DOMAIN = b"agent-evolve:prequential-linear-gaussian-head:v1\x00"
62
+ _META_PRIOR_DOMAIN = b"agent-evolve:trap-portable-meta-prior:v1\x00"
63
+ _STATE_DOMAIN = b"agent-evolve:target-conditioned-acquisition-state:v1\x00"
64
+ _PROFILE_DOMAIN = b"agent-evolve:target-conditioned-acquisition-profile:v1\x00"
65
+ _REALIZABLE_DOMAIN = b"agent-evolve:realizable-portfolio-set:v1\x00"
66
+ _FEATURE_ROW_DOMAIN = b"agent-evolve:target-conditioned-feature-row:v1\x00"
67
+ _REQUEST_DOMAIN = b"agent-evolve:target-conditioned-slate-request:v1\x00"
68
+ _DECISION_DOMAIN = b"agent-evolve:target-conditioned-slate-decision:v1\x00"
69
+ _OBSERVATION_DOMAIN = b"agent-evolve:target-conditioned-observation:v1\x00"
70
+ _UPDATE_DOMAIN = b"agent-evolve:target-conditioned-state-update:v1\x00"
71
+
72
+
73
+ def _canonical_json(value: object) -> bytes:
74
+ return json.dumps(
75
+ value,
76
+ allow_nan=False,
77
+ ensure_ascii=True,
78
+ separators=(",", ":"),
79
+ sort_keys=True,
80
+ ).encode("ascii", errors="strict")
81
+
82
+
83
+ def _hash(domain: bytes, value: object) -> str:
84
+ return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
85
+
86
+
87
+ def _finite(value: float, *, name: str) -> None:
88
+ if type(value) is not float or not math.isfinite(value):
89
+ raise TypeError(f"{name} must be an exact finite float")
90
+
91
+
92
+ def _hex_float(value: object, *, name: str) -> float:
93
+ if type(value) is not str:
94
+ raise TypeError(f"{name} must be a binary64 hexadecimal string")
95
+ try:
96
+ result = float.fromhex(value)
97
+ except ValueError as error:
98
+ raise ValueError(f"{name} is not valid binary64 hexadecimal text") from error
99
+ _finite(result, name=name)
100
+ return result
101
+
102
+
103
+ def _exact_record_keys(
104
+ value: object, *, expected: set[str], name: str
105
+ ) -> dict[str, object]:
106
+ if type(value) is not dict:
107
+ raise TypeError(f"{name} must be an exact JSON object")
108
+ keys = set(value)
109
+ if keys != expected:
110
+ raise ValueError(
111
+ f"{name} fields differ from the closed schema: "
112
+ f"missing={sorted(expected - keys)}, extra={sorted(keys - expected)}"
113
+ )
114
+ return value
115
+
116
+
117
+ def _feature_names(values: tuple[str, ...]) -> None:
118
+ if type(values) is not tuple or not values:
119
+ raise ValueError("feature_names must be a non-empty exact tuple")
120
+ if any(type(value) is not str or _FEATURE.fullmatch(value) is None for value in values):
121
+ raise ValueError("feature names must use the closed lowercase grammar")
122
+ if values != tuple(dict.fromkeys(values)):
123
+ raise ValueError("feature names must be unique and ordered")
124
+ if "bias" not in values:
125
+ raise ValueError("feature schema must include bias")
126
+
127
+
128
+ def _cholesky(matrix: tuple[tuple[float, ...], ...]) -> tuple[tuple[float, ...], ...]:
129
+ size = len(matrix)
130
+ lower = [[0.0 for _ in range(size)] for _ in range(size)]
131
+ for row in range(size):
132
+ for column in range(row + 1):
133
+ value = matrix[row][column] - sum(
134
+ lower[row][index] * lower[column][index]
135
+ for index in range(column)
136
+ )
137
+ if row == column:
138
+ if value <= 1e-14 or not math.isfinite(value):
139
+ raise ValueError("head precision must be positive definite")
140
+ lower[row][column] = math.sqrt(value)
141
+ else:
142
+ lower[row][column] = value / lower[column][column]
143
+ return tuple(tuple(value for value in row) for row in lower)
144
+
145
+
146
+ def _solve_cholesky(
147
+ lower: tuple[tuple[float, ...], ...], rhs: Sequence[float]
148
+ ) -> tuple[float, ...]:
149
+ size = len(lower)
150
+ forward = [0.0 for _ in range(size)]
151
+ for row in range(size):
152
+ forward[row] = (
153
+ float(rhs[row])
154
+ - sum(lower[row][index] * forward[index] for index in range(row))
155
+ ) / lower[row][row]
156
+ result = [0.0 for _ in range(size)]
157
+ for row in range(size - 1, -1, -1):
158
+ result[row] = (
159
+ forward[row]
160
+ - sum(
161
+ lower[index][row] * result[index]
162
+ for index in range(row + 1, size)
163
+ )
164
+ ) / lower[row][row]
165
+ return tuple(result)
166
+
167
+
168
+ @dataclass(frozen=True, slots=True)
169
+ class _HeadProjection:
170
+ head: PrequentialLinearGaussianHead
171
+ lower: tuple[tuple[float, ...], ...]
172
+ coefficients: tuple[float, ...]
173
+
174
+ def standardized(self, values: Sequence[float]) -> tuple[float, ...]:
175
+ if len(values) != len(self.head.feature_names):
176
+ raise ValueError("feature vector differs from the head schema")
177
+ return tuple(
178
+ (float(value) - mean) / scale
179
+ for value, mean, scale in zip(
180
+ values, self.head.means, self.head.scales, strict=True
181
+ )
182
+ )
183
+
184
+ def predict(self, values: Sequence[float]) -> float:
185
+ row = self.standardized(values)
186
+ return sum(
187
+ value * coefficient
188
+ for value, coefficient in zip(row, self.coefficients, strict=True)
189
+ )
190
+
191
+ def uncertainty(self, values: Sequence[float]) -> float:
192
+ row = self.standardized(values)
193
+ # x' P^-1 x == ||L^-1 x||^2 for P = L L'.
194
+ whitened: list[float] = []
195
+ for index in range(len(row)):
196
+ whitened.append(
197
+ (
198
+ row[index]
199
+ - sum(
200
+ self.lower[index][prior] * whitened[prior]
201
+ for prior in range(index)
202
+ )
203
+ )
204
+ / self.lower[index][index]
205
+ )
206
+ leverage = max(0.0, sum(value * value for value in whitened))
207
+ return math.sqrt(self.head.residual_variance * leverage)
208
+
209
+
210
+ @dataclass(frozen=True, slots=True, eq=False)
211
+ class PrequentialLinearGaussianHead:
212
+ """Serializable regularized head represented by sufficient statistics."""
213
+
214
+ feature_names: tuple[str, ...]
215
+ means: tuple[float, ...]
216
+ scales: tuple[float, ...]
217
+ precision: tuple[tuple[float, ...], ...]
218
+ rhs: tuple[float, ...]
219
+ residual_variance: float
220
+
221
+ def __post_init__(self) -> None:
222
+ _feature_names(self.feature_names)
223
+ size = len(self.feature_names)
224
+ for name, values in (
225
+ ("means", self.means),
226
+ ("scales", self.scales),
227
+ ("rhs", self.rhs),
228
+ ):
229
+ if type(values) is not tuple or len(values) != size:
230
+ raise ValueError(f"{name} must match the feature schema")
231
+ for value in values:
232
+ _finite(value, name=name)
233
+ if any(value <= 0.0 for value in self.scales):
234
+ raise ValueError("feature scales must be strictly positive")
235
+ if type(self.precision) is not tuple or len(self.precision) != size:
236
+ raise ValueError("precision must be a square exact tuple matrix")
237
+ for row in self.precision:
238
+ if type(row) is not tuple or len(row) != size:
239
+ raise ValueError("precision must be a square exact tuple matrix")
240
+ for value in row:
241
+ _finite(value, name="precision")
242
+ for row in range(size):
243
+ for column in range(row):
244
+ if not math.isclose(
245
+ self.precision[row][column],
246
+ self.precision[column][row],
247
+ rel_tol=0.0,
248
+ abs_tol=1e-10,
249
+ ):
250
+ raise ValueError("precision must be symmetric")
251
+ _finite(self.residual_variance, name="residual_variance")
252
+ if self.residual_variance <= 0.0:
253
+ raise ValueError("residual_variance must be strictly positive")
254
+ _cholesky(self.precision)
255
+
256
+ def project(self) -> _HeadProjection:
257
+ self.__post_init__()
258
+ lower = _cholesky(self.precision)
259
+ return _HeadProjection(
260
+ head=self,
261
+ lower=lower,
262
+ coefficients=_solve_cholesky(lower, self.rhs),
263
+ )
264
+
265
+ def update(
266
+ self,
267
+ rows: Sequence[Sequence[float]],
268
+ targets: Sequence[float],
269
+ ) -> PrequentialLinearGaussianHead:
270
+ self.__post_init__()
271
+ if not rows or len(rows) != len(targets):
272
+ raise ValueError("head update requires aligned non-empty observations")
273
+ projection = self.project()
274
+ design = [projection.standardized(row) for row in rows]
275
+ for target in targets:
276
+ _finite(float(target), name="target")
277
+ size = len(self.feature_names)
278
+ precision = [list(row) for row in self.precision]
279
+ rhs = list(self.rhs)
280
+ for row, target in zip(design, targets, strict=True):
281
+ for left in range(size):
282
+ rhs[left] += row[left] * float(target)
283
+ for right in range(size):
284
+ precision[left][right] += row[left] * row[right]
285
+ return PrequentialLinearGaussianHead(
286
+ feature_names=self.feature_names,
287
+ means=self.means,
288
+ scales=self.scales,
289
+ precision=tuple(tuple(value for value in row) for row in precision),
290
+ rhs=tuple(rhs),
291
+ residual_variance=self.residual_variance,
292
+ )
293
+
294
+ def _unsigned_record(self) -> dict[str, object]:
295
+ self.__post_init__()
296
+ return {
297
+ "schema_version": 1,
298
+ "feature_names": list(self.feature_names),
299
+ "means_hex": [value.hex() for value in self.means],
300
+ "scales_hex": [value.hex() for value in self.scales],
301
+ "precision_hex": [
302
+ [value.hex() for value in row] for row in self.precision
303
+ ],
304
+ "rhs_hex": [value.hex() for value in self.rhs],
305
+ "residual_variance_hex": self.residual_variance.hex(),
306
+ }
307
+
308
+ @property
309
+ def head_sha256(self) -> str:
310
+ return _hash(_HEAD_DOMAIN, self._unsigned_record())
311
+
312
+ def to_record(self) -> dict[str, object]:
313
+ return {**self._unsigned_record(), "head_sha256": self.head_sha256}
314
+
315
+ @classmethod
316
+ def from_record(
317
+ cls, record: object
318
+ ) -> PrequentialLinearGaussianHead:
319
+ value = _exact_record_keys(
320
+ record,
321
+ expected={
322
+ "schema_version",
323
+ "feature_names",
324
+ "means_hex",
325
+ "scales_hex",
326
+ "precision_hex",
327
+ "rhs_hex",
328
+ "residual_variance_hex",
329
+ "head_sha256",
330
+ },
331
+ name="linear-Gaussian head record",
332
+ )
333
+ if value["schema_version"] != 1:
334
+ raise ValueError("unsupported linear-Gaussian head schema")
335
+ raw_names = value["feature_names"]
336
+ raw_means = value["means_hex"]
337
+ raw_scales = value["scales_hex"]
338
+ raw_precision = value["precision_hex"]
339
+ raw_rhs = value["rhs_hex"]
340
+ if type(raw_names) is not list or any(type(item) is not str for item in raw_names):
341
+ raise TypeError("feature_names must be an exact JSON string array")
342
+ for name, raw in (
343
+ ("means_hex", raw_means),
344
+ ("scales_hex", raw_scales),
345
+ ("rhs_hex", raw_rhs),
346
+ ):
347
+ if type(raw) is not list:
348
+ raise TypeError(f"{name} must be an exact JSON array")
349
+ if type(raw_precision) is not list or any(
350
+ type(row) is not list for row in raw_precision
351
+ ):
352
+ raise TypeError("precision_hex must be an exact JSON matrix")
353
+ result = cls(
354
+ feature_names=tuple(raw_names),
355
+ means=tuple(
356
+ _hex_float(item, name=f"means_hex[{index}]")
357
+ for index, item in enumerate(raw_means)
358
+ ),
359
+ scales=tuple(
360
+ _hex_float(item, name=f"scales_hex[{index}]")
361
+ for index, item in enumerate(raw_scales)
362
+ ),
363
+ precision=tuple(
364
+ tuple(
365
+ _hex_float(
366
+ item,
367
+ name=f"precision_hex[{row_index}][{column_index}]",
368
+ )
369
+ for column_index, item in enumerate(row)
370
+ )
371
+ for row_index, row in enumerate(raw_precision)
372
+ ),
373
+ rhs=tuple(
374
+ _hex_float(item, name=f"rhs_hex[{index}]")
375
+ for index, item in enumerate(raw_rhs)
376
+ ),
377
+ residual_variance=_hex_float(
378
+ value["residual_variance_hex"],
379
+ name="residual_variance_hex",
380
+ ),
381
+ )
382
+ if value["head_sha256"] != result.head_sha256:
383
+ raise ValueError("linear-Gaussian head identity mismatch")
384
+ return result
385
+
386
+ def __eq__(self, other: object) -> bool:
387
+ return (
388
+ type(other) is PrequentialLinearGaussianHead
389
+ and self.head_sha256 == other.head_sha256
390
+ )
391
+
392
+ __hash__ = None
393
+
394
+
395
+ @dataclass(frozen=True, slots=True, eq=False)
396
+ class TargetConditionedMetaPrior:
397
+ """Frozen cross-campaign prior from an authenticated training panel."""
398
+
399
+ training_data_sha256: str
400
+ marginal_head: PrequentialLinearGaussianHead
401
+ direction_head: PrequentialLinearGaussianHead
402
+
403
+ def __post_init__(self) -> None:
404
+ require_sha256(self.training_data_sha256, "training_data_sha256")
405
+ if type(self.marginal_head) is not PrequentialLinearGaussianHead:
406
+ raise TypeError("marginal_head must be exact")
407
+ if type(self.direction_head) is not PrequentialLinearGaussianHead:
408
+ raise TypeError("direction_head must be exact")
409
+ self.marginal_head.__post_init__()
410
+ self.direction_head.__post_init__()
411
+ if self.marginal_head.feature_names != self.direction_head.feature_names:
412
+ raise ValueError("meta-prior heads must share one feature schema")
413
+ if (
414
+ self.marginal_head.means != self.direction_head.means
415
+ or self.marginal_head.scales != self.direction_head.scales
416
+ ):
417
+ raise ValueError("meta-prior heads must share one standardizer")
418
+
419
+ def _unsigned_record(self) -> dict[str, object]:
420
+ self.__post_init__()
421
+ return {
422
+ "schema_version": 1,
423
+ "training_data_sha256": self.training_data_sha256,
424
+ "marginal_head": self.marginal_head.to_record(),
425
+ "direction_head": self.direction_head.to_record(),
426
+ }
427
+
428
+ @property
429
+ def meta_prior_sha256(self) -> str:
430
+ return _hash(_META_PRIOR_DOMAIN, self._unsigned_record())
431
+
432
+ def to_record(self) -> dict[str, object]:
433
+ return {
434
+ **self._unsigned_record(),
435
+ "meta_prior_sha256": self.meta_prior_sha256,
436
+ }
437
+
438
+ @classmethod
439
+ def from_record(cls, record: object) -> TargetConditionedMetaPrior:
440
+ value = _exact_record_keys(
441
+ record,
442
+ expected={
443
+ "schema_version",
444
+ "training_data_sha256",
445
+ "marginal_head",
446
+ "direction_head",
447
+ "meta_prior_sha256",
448
+ },
449
+ name="target-conditioned meta-prior record",
450
+ )
451
+ if value["schema_version"] != 1:
452
+ raise ValueError("unsupported target-conditioned meta-prior schema")
453
+ result = cls(
454
+ training_data_sha256=value["training_data_sha256"],
455
+ marginal_head=PrequentialLinearGaussianHead.from_record(
456
+ value["marginal_head"]
457
+ ),
458
+ direction_head=PrequentialLinearGaussianHead.from_record(
459
+ value["direction_head"]
460
+ ),
461
+ )
462
+ if value["meta_prior_sha256"] != result.meta_prior_sha256:
463
+ raise ValueError("target-conditioned meta-prior identity mismatch")
464
+ return result
465
+
466
+ def initial_state(
467
+ self, *, campaign_scope_sha256: str
468
+ ) -> TargetConditionedAcquisitionState:
469
+ self.__post_init__()
470
+ return TargetConditionedAcquisitionState(
471
+ campaign_scope_sha256=campaign_scope_sha256,
472
+ training_data_sha256=self.training_data_sha256,
473
+ marginal_head=self.marginal_head,
474
+ direction_head=self.direction_head,
475
+ )
476
+
477
+ def __eq__(self, other: object) -> bool:
478
+ return (
479
+ type(other) is TargetConditionedMetaPrior
480
+ and self.meta_prior_sha256 == other.meta_prior_sha256
481
+ )
482
+
483
+ __hash__ = None
484
+
485
+
486
+ @dataclass(frozen=True, slots=True, eq=False)
487
+ class TargetConditionedAcquisitionState:
488
+ """Branch-local immutable posterior state at one generation cutoff."""
489
+
490
+ campaign_scope_sha256: str
491
+ training_data_sha256: str
492
+ marginal_head: PrequentialLinearGaussianHead
493
+ direction_head: PrequentialLinearGaussianHead
494
+ cutoff_generation: int = 0
495
+ selected_observation_count: int = 0
496
+
497
+ def __post_init__(self) -> None:
498
+ require_sha256(self.campaign_scope_sha256, "campaign_scope_sha256")
499
+ require_sha256(self.training_data_sha256, "training_data_sha256")
500
+ if type(self.marginal_head) is not PrequentialLinearGaussianHead:
501
+ raise TypeError("marginal_head must be exact")
502
+ if type(self.direction_head) is not PrequentialLinearGaussianHead:
503
+ raise TypeError("direction_head must be exact")
504
+ self.marginal_head.__post_init__()
505
+ self.direction_head.__post_init__()
506
+ if self.marginal_head.feature_names != self.direction_head.feature_names:
507
+ raise ValueError("acquisition heads must use one feature schema")
508
+ if (
509
+ self.marginal_head.means != self.direction_head.means
510
+ or self.marginal_head.scales != self.direction_head.scales
511
+ ):
512
+ raise ValueError("acquisition heads must share one standardizer")
513
+ if type(self.cutoff_generation) is not int or self.cutoff_generation < 0:
514
+ raise ValueError("cutoff_generation must be non-negative")
515
+ if (
516
+ type(self.selected_observation_count) is not int
517
+ or self.selected_observation_count < 0
518
+ ):
519
+ raise ValueError("selected_observation_count must be non-negative")
520
+
521
+ def _unsigned_record(self) -> dict[str, object]:
522
+ self.__post_init__()
523
+ return {
524
+ "schema_version": 1,
525
+ "campaign_scope_sha256": self.campaign_scope_sha256,
526
+ "training_data_sha256": self.training_data_sha256,
527
+ "marginal_head": self.marginal_head.to_record(),
528
+ "direction_head": self.direction_head.to_record(),
529
+ "cutoff_generation": self.cutoff_generation,
530
+ "selected_observation_count": self.selected_observation_count,
531
+ }
532
+
533
+ @property
534
+ def state_sha256(self) -> str:
535
+ return _hash(_STATE_DOMAIN, self._unsigned_record())
536
+
537
+ def to_record(self) -> dict[str, object]:
538
+ return {**self._unsigned_record(), "state_sha256": self.state_sha256}
539
+
540
+ def __eq__(self, other: object) -> bool:
541
+ return (
542
+ type(other) is TargetConditionedAcquisitionState
543
+ and self.state_sha256 == other.state_sha256
544
+ )
545
+
546
+ __hash__ = None
547
+
548
+
549
+ @dataclass(frozen=True, slots=True, eq=False)
550
+ class TargetConditionedAcquisitionProfile:
551
+ """Frozen portable coefficients; no route-specific test-time tuning."""
552
+
553
+ direction_weight: float
554
+ uncertainty_weight: float
555
+ maximum_remaining_horizon: int
556
+ profile_id: str = "trap_portable_v1"
557
+ profile_version: int = 1
558
+
559
+ def __post_init__(self) -> None:
560
+ if type(self.profile_id) is not str or _TOKEN.fullmatch(self.profile_id) is None:
561
+ raise ValueError("profile_id must use the closed token grammar")
562
+ if type(self.profile_version) is not int or self.profile_version <= 0:
563
+ raise ValueError("profile_version must be positive")
564
+ for name in ("direction_weight", "uncertainty_weight"):
565
+ value = getattr(self, name)
566
+ _finite(value, name=name)
567
+ if not 0.0 <= value <= 1.0:
568
+ raise ValueError(f"{name} must lie in [0, 1]")
569
+ if (
570
+ type(self.maximum_remaining_horizon) is not int
571
+ or self.maximum_remaining_horizon <= 0
572
+ ):
573
+ raise ValueError("maximum_remaining_horizon must be positive")
574
+
575
+ def _unsigned_record(self) -> dict[str, object]:
576
+ self.__post_init__()
577
+ return {
578
+ "schema_version": 1,
579
+ "profile_id": self.profile_id,
580
+ "profile_version": self.profile_version,
581
+ "direction_weight_hex": self.direction_weight.hex(),
582
+ "uncertainty_weight_hex": self.uncertainty_weight.hex(),
583
+ "maximum_remaining_horizon": self.maximum_remaining_horizon,
584
+ }
585
+
586
+ @property
587
+ def profile_sha256(self) -> str:
588
+ return _hash(_PROFILE_DOMAIN, self._unsigned_record())
589
+
590
+ def to_record(self) -> dict[str, object]:
591
+ return {**self._unsigned_record(), "profile_sha256": self.profile_sha256}
592
+
593
+ @classmethod
594
+ def from_record(
595
+ cls, record: object
596
+ ) -> TargetConditionedAcquisitionProfile:
597
+ value = _exact_record_keys(
598
+ record,
599
+ expected={
600
+ "schema_version",
601
+ "profile_id",
602
+ "profile_version",
603
+ "direction_weight_hex",
604
+ "uncertainty_weight_hex",
605
+ "maximum_remaining_horizon",
606
+ "profile_sha256",
607
+ },
608
+ name="target-conditioned acquisition profile record",
609
+ )
610
+ if value["schema_version"] != 1:
611
+ raise ValueError("unsupported target-conditioned profile schema")
612
+ result = cls(
613
+ profile_id=value["profile_id"],
614
+ profile_version=value["profile_version"],
615
+ direction_weight=_hex_float(
616
+ value["direction_weight_hex"], name="direction_weight_hex"
617
+ ),
618
+ uncertainty_weight=_hex_float(
619
+ value["uncertainty_weight_hex"], name="uncertainty_weight_hex"
620
+ ),
621
+ maximum_remaining_horizon=value["maximum_remaining_horizon"],
622
+ )
623
+ if value["profile_sha256"] != result.profile_sha256:
624
+ raise ValueError("target-conditioned profile identity mismatch")
625
+ return result
626
+
627
+ def __eq__(self, other: object) -> bool:
628
+ return (
629
+ type(other) is TargetConditionedAcquisitionProfile
630
+ and self.profile_sha256 == other.profile_sha256
631
+ )
632
+
633
+ __hash__ = None
634
+
635
+
636
+ @dataclass(frozen=True, slots=True, eq=False)
637
+ class TargetConditionedMemberFeatures:
638
+ """Authenticated numeric projection for one exact sealed option."""
639
+
640
+ option_id: str
641
+ option_identity_sha256: str
642
+ feature_names: tuple[str, ...]
643
+ values: tuple[float, ...]
644
+ projector_id: str
645
+ projector_version: int
646
+ projector_definition_sha256: str
647
+
648
+ def __post_init__(self) -> None:
649
+ if type(self.option_id) is not str or not self.option_id:
650
+ raise ValueError("option_id must be non-empty")
651
+ require_sha256(self.option_identity_sha256, "option_identity_sha256")
652
+ _feature_names(self.feature_names)
653
+ if type(self.values) is not tuple or len(self.values) != len(
654
+ self.feature_names
655
+ ):
656
+ raise ValueError("feature values must match the feature schema")
657
+ for value in self.values:
658
+ _finite(value, name="feature value")
659
+ if type(self.projector_id) is not str or _TOKEN.fullmatch(self.projector_id) is None:
660
+ raise ValueError("projector_id must use the closed token grammar")
661
+ if type(self.projector_version) is not int or self.projector_version <= 0:
662
+ raise ValueError("projector_version must be positive")
663
+ require_sha256(
664
+ self.projector_definition_sha256, "projector_definition_sha256"
665
+ )
666
+
667
+ def _unsigned_record(self) -> dict[str, object]:
668
+ self.__post_init__()
669
+ return {
670
+ "option_id": self.option_id,
671
+ "option_identity_sha256": self.option_identity_sha256,
672
+ "feature_names": list(self.feature_names),
673
+ "values_hex": [value.hex() for value in self.values],
674
+ "projector": {
675
+ "projector_id": self.projector_id,
676
+ "projector_version": self.projector_version,
677
+ "definition_sha256": self.projector_definition_sha256,
678
+ },
679
+ }
680
+
681
+ @property
682
+ def feature_row_sha256(self) -> str:
683
+ return _hash(_FEATURE_ROW_DOMAIN, self._unsigned_record())
684
+
685
+ def to_record(self) -> dict[str, object]:
686
+ return {
687
+ **self._unsigned_record(),
688
+ "feature_row_sha256": self.feature_row_sha256,
689
+ }
690
+
691
+ def __eq__(self, other: object) -> bool:
692
+ return (
693
+ type(other) is TargetConditionedMemberFeatures
694
+ and self.feature_row_sha256 == other.feature_row_sha256
695
+ )
696
+
697
+ __hash__ = None
698
+
699
+
700
+ @dataclass(frozen=True, slots=True, eq=False)
701
+ class RealizablePortfolioSet:
702
+ """Complete finite portfolio universe certified by a generic projector."""
703
+
704
+ source_request_sha256: str
705
+ projector_id: str
706
+ projector_version: int
707
+ projector_definition_sha256: str
708
+ option_id_sets: tuple[tuple[str, ...], ...]
709
+
710
+ def __post_init__(self) -> None:
711
+ require_sha256(self.source_request_sha256, "source_request_sha256")
712
+ if type(self.projector_id) is not str or _TOKEN.fullmatch(self.projector_id) is None:
713
+ raise ValueError("projector_id must use the closed token grammar")
714
+ if type(self.projector_version) is not int or self.projector_version <= 0:
715
+ raise ValueError("projector_version must be positive")
716
+ require_sha256(
717
+ self.projector_definition_sha256, "projector_definition_sha256"
718
+ )
719
+ if type(self.option_id_sets) is not tuple or not self.option_id_sets:
720
+ raise ValueError("option_id_sets must be a non-empty exact tuple")
721
+ for values in self.option_id_sets:
722
+ if type(values) is not tuple or not values:
723
+ raise ValueError("each realizable portfolio must be non-empty")
724
+ if values != tuple(sorted(set(values))):
725
+ raise ValueError("realizable option IDs must be unique and canonical")
726
+ if self.option_id_sets != tuple(sorted(set(self.option_id_sets))):
727
+ raise ValueError("realizable portfolios must be unique and canonical")
728
+
729
+ def _unsigned_record(self) -> dict[str, object]:
730
+ self.__post_init__()
731
+ return {
732
+ "schema_version": 1,
733
+ "source_request_sha256": self.source_request_sha256,
734
+ "projector": {
735
+ "projector_id": self.projector_id,
736
+ "projector_version": self.projector_version,
737
+ "definition_sha256": self.projector_definition_sha256,
738
+ },
739
+ "option_id_sets": [list(value) for value in self.option_id_sets],
740
+ "complete_for_projector_contract": True,
741
+ }
742
+
743
+ @property
744
+ def realizable_set_sha256(self) -> str:
745
+ return _hash(_REALIZABLE_DOMAIN, self._unsigned_record())
746
+
747
+ def to_record(self) -> dict[str, object]:
748
+ return {
749
+ **self._unsigned_record(),
750
+ "realizable_set_sha256": self.realizable_set_sha256,
751
+ }
752
+
753
+ def __eq__(self, other: object) -> bool:
754
+ return (
755
+ type(other) is RealizablePortfolioSet
756
+ and self.realizable_set_sha256 == other.realizable_set_sha256
757
+ )
758
+
759
+ __hash__ = None
760
+
761
+
762
+ def _members_for_ids(
763
+ request: SlateAllocationRequest, option_ids: Sequence[str]
764
+ ) -> tuple[CalibratedSlateMember, ...]:
765
+ selected = set(option_ids)
766
+ return tuple(
767
+ member for member in request.slate.members if member.option_id in selected
768
+ )
769
+
770
+
771
+ def _base_feasible(
772
+ request: SlateAllocationRequest, option_ids: tuple[str, ...]
773
+ ) -> tuple[bool, PortfolioMemoryDoseAssessment | None]:
774
+ if len(option_ids) != request.portfolio_size:
775
+ return False, None
776
+ if not set(request.required_option_ids).issubset(option_ids):
777
+ return False, None
778
+ members = _members_for_ids(request, option_ids)
779
+ if len(members) != request.portfolio_size:
780
+ return False, None
781
+ if request.pairwise_disjoint_option_id_pairs is not None:
782
+ allowed = {frozenset(value) for value in request.pairwise_disjoint_option_id_pairs}
783
+ if any(
784
+ frozenset(value) not in allowed for value in combinations(option_ids, 2)
785
+ ):
786
+ return False, None
787
+ if request.min_distinct_families is not None and len(
788
+ {value.family for value in members}
789
+ ) < request.min_distinct_families:
790
+ return False, None
791
+ assessment = (
792
+ None
793
+ if request.memory_dose_contract is None
794
+ else assess_allocated_slate_memory_dose(request, members)
795
+ )
796
+ if assessment is not None and not assessment.passed:
797
+ return False, assessment
798
+ return True, assessment
799
+
800
+
801
+ def enumerate_base_realizable_portfolios(
802
+ request: SlateAllocationRequest,
803
+ ) -> RealizablePortfolioSet:
804
+ """Exactly enumerate the constraints represented by ``SlateAllocationRequest``."""
805
+
806
+ if type(request) is not SlateAllocationRequest:
807
+ raise TypeError("request must be exact SlateAllocationRequest")
808
+ request.revalidate()
809
+ values = []
810
+ for members in combinations(request.slate.members, request.portfolio_size):
811
+ option_ids = tuple(sorted(value.option_id for value in members))
812
+ feasible, _ = _base_feasible(request, option_ids)
813
+ if feasible:
814
+ values.append(option_ids)
815
+ if not values:
816
+ raise ValueError("sealed slate has no base-realizable portfolio")
817
+ return RealizablePortfolioSet(
818
+ source_request_sha256=request.request_sha256,
819
+ projector_id=BASE_REALIZABILITY_PROJECTOR_ID,
820
+ projector_version=BASE_REALIZABILITY_PROJECTOR_VERSION,
821
+ projector_definition_sha256=BASE_REALIZABILITY_DEFINITION_SHA256,
822
+ option_id_sets=tuple(sorted(set(values))),
823
+ )
824
+
825
+
826
+ @dataclass(frozen=True, slots=True, eq=False)
827
+ class TargetConditionedSlateRequest:
828
+ """All authenticated inputs for one prior-only T-RAP decision."""
829
+
830
+ allocation_request: SlateAllocationRequest
831
+ frontier_target: CampaignPortfolioFrontierTarget
832
+ state: TargetConditionedAcquisitionState
833
+ member_features: tuple[TargetConditionedMemberFeatures, ...]
834
+ realizable_portfolios: RealizablePortfolioSet
835
+ campaign_generation: int
836
+ remaining_proposal_horizon: int
837
+
838
+ def __post_init__(self) -> None:
839
+ if type(self.allocation_request) is not SlateAllocationRequest:
840
+ raise TypeError("allocation_request must be exact")
841
+ self.allocation_request.revalidate()
842
+ if type(self.frontier_target) is not CampaignPortfolioFrontierTarget:
843
+ raise TypeError("frontier_target must be exact")
844
+ self.frontier_target.__post_init__()
845
+ if type(self.state) is not TargetConditionedAcquisitionState:
846
+ raise TypeError("state must be exact")
847
+ self.state.__post_init__()
848
+ if (
849
+ type(self.member_features) is not tuple
850
+ or any(
851
+ type(value) is not TargetConditionedMemberFeatures
852
+ for value in self.member_features
853
+ )
854
+ ):
855
+ raise TypeError("member_features must contain exact rows")
856
+ for value in self.member_features:
857
+ value.__post_init__()
858
+ if type(self.realizable_portfolios) is not RealizablePortfolioSet:
859
+ raise TypeError("realizable_portfolios must be exact")
860
+ self.realizable_portfolios.__post_init__()
861
+ if (
862
+ self.realizable_portfolios.source_request_sha256
863
+ != self.allocation_request.request_sha256
864
+ ):
865
+ raise ValueError("realizable set names a foreign allocation request")
866
+ base_projector_identity = (
867
+ BASE_REALIZABILITY_PROJECTOR_ID,
868
+ BASE_REALIZABILITY_PROJECTOR_VERSION,
869
+ BASE_REALIZABILITY_DEFINITION_SHA256,
870
+ )
871
+ supplied_projector_identity = (
872
+ self.realizable_portfolios.projector_id,
873
+ self.realizable_portfolios.projector_version,
874
+ self.realizable_portfolios.projector_definition_sha256,
875
+ )
876
+ if self.realizable_portfolios.projector_id == BASE_REALIZABILITY_PROJECTOR_ID:
877
+ if supplied_projector_identity != base_projector_identity:
878
+ raise ValueError("reserved base projector ID has a foreign identity")
879
+ expected = enumerate_base_realizable_portfolios(self.allocation_request)
880
+ if self.realizable_portfolios != expected:
881
+ raise ValueError("base realizability receipt is not complete")
882
+ if type(self.campaign_generation) is not int or self.campaign_generation <= 0:
883
+ raise ValueError("campaign_generation must be positive")
884
+ if (
885
+ type(self.remaining_proposal_horizon) is not int
886
+ or self.remaining_proposal_horizon < 0
887
+ ):
888
+ raise ValueError("remaining_proposal_horizon must be non-negative")
889
+ if self.state.cutoff_generation >= self.campaign_generation:
890
+ raise ValueError("posterior cutoff reaches current/future generation")
891
+ slate = self.allocation_request.slate
892
+ if (
893
+ self.frontier_target.parent_configuration_sha256
894
+ != slate.parent_candidate_identity_sha256
895
+ ):
896
+ raise ValueError("frontier target names a foreign parent")
897
+ feature_by_id = {value.option_id: value for value in self.member_features}
898
+ member_by_id = {value.option_id: value for value in slate.members}
899
+ if len(feature_by_id) != len(self.member_features) or set(feature_by_id) != set(
900
+ member_by_id
901
+ ):
902
+ raise ValueError("feature rows must cover every slate member exactly")
903
+ expected_order = tuple(sorted(feature_by_id))
904
+ if tuple(value.option_id for value in self.member_features) != expected_order:
905
+ raise ValueError("feature rows must use canonical option order")
906
+ for option_id, row in feature_by_id.items():
907
+ if row.option_identity_sha256 != member_by_id[option_id].option_identity_sha256:
908
+ raise ValueError("feature row names a foreign option identity")
909
+ if row.feature_names != self.state.marginal_head.feature_names:
910
+ raise ValueError("feature row differs from the posterior schema")
911
+ projectors = {
912
+ (
913
+ value.projector_id,
914
+ value.projector_version,
915
+ value.projector_definition_sha256,
916
+ )
917
+ for value in self.member_features
918
+ }
919
+ if len(projectors) != 1:
920
+ raise ValueError("feature rows must share one projector identity")
921
+ slate_ids = set(member_by_id)
922
+ for option_ids in self.realizable_portfolios.option_id_sets:
923
+ if not set(option_ids).issubset(slate_ids):
924
+ raise ValueError("realizable portfolio escapes the sealed slate")
925
+ feasible, _ = _base_feasible(self.allocation_request, option_ids)
926
+ if not feasible:
927
+ raise ValueError("realizable projector admitted a base-infeasible set")
928
+
929
+ def _unsigned_record(self) -> dict[str, object]:
930
+ self.__post_init__()
931
+ return {
932
+ "schema_version": 1,
933
+ "allocation_request_sha256": self.allocation_request.request_sha256,
934
+ "frontier_target": self.frontier_target.to_record(),
935
+ "state": self.state.to_record(),
936
+ "member_features": [value.to_record() for value in self.member_features],
937
+ "realizable_portfolios": self.realizable_portfolios.to_record(),
938
+ "campaign_generation": self.campaign_generation,
939
+ "remaining_proposal_horizon": self.remaining_proposal_horizon,
940
+ "current_or_future_outcomes_consulted": False,
941
+ }
942
+
943
+ @property
944
+ def request_sha256(self) -> str:
945
+ return _hash(_REQUEST_DOMAIN, self._unsigned_record())
946
+
947
+ def to_record(self) -> dict[str, object]:
948
+ return {**self._unsigned_record(), "request_sha256": self.request_sha256}
949
+
950
+ def __eq__(self, other: object) -> bool:
951
+ return (
952
+ type(other) is TargetConditionedSlateRequest
953
+ and self.request_sha256 == other.request_sha256
954
+ )
955
+
956
+ __hash__ = None
957
+
958
+
959
+ def _z_scores(values: dict[str, float]) -> dict[str, float]:
960
+ mean = fmean(values.values())
961
+ scale = math.sqrt(fmean((value - mean) ** 2 for value in values.values()))
962
+ if scale < 1e-12:
963
+ return {key: 0.0 for key in values}
964
+ return {key: (value - mean) / scale for key, value in values.items()}
965
+
966
+
967
+ @dataclass(frozen=True, slots=True)
968
+ class TargetConditionedMemberScore:
969
+ option_id: str
970
+ option_identity_sha256: str
971
+ model_rank: int
972
+ predicted_marginal: float
973
+ predicted_direction: float
974
+ epistemic_uncertainty: float
975
+ marginal_z: float
976
+ direction_z: float
977
+ uncertainty_z: float
978
+ final_score: float
979
+
980
+ def __post_init__(self) -> None:
981
+ if type(self.option_id) is not str or not self.option_id:
982
+ raise ValueError("option_id must be non-empty")
983
+ require_sha256(self.option_identity_sha256, "option_identity_sha256")
984
+ if type(self.model_rank) is not int or self.model_rank <= 0:
985
+ raise ValueError("model_rank must be positive")
986
+ for name in (
987
+ "predicted_marginal",
988
+ "predicted_direction",
989
+ "epistemic_uncertainty",
990
+ "marginal_z",
991
+ "direction_z",
992
+ "uncertainty_z",
993
+ "final_score",
994
+ ):
995
+ _finite(getattr(self, name), name=name)
996
+ if self.epistemic_uncertainty < 0.0:
997
+ raise ValueError("epistemic_uncertainty must be non-negative")
998
+
999
+ def to_record(self) -> dict[str, object]:
1000
+ self.__post_init__()
1001
+ return {
1002
+ "option_id": self.option_id,
1003
+ "option_identity_sha256": self.option_identity_sha256,
1004
+ "model_rank": self.model_rank,
1005
+ "predicted_marginal_hex": self.predicted_marginal.hex(),
1006
+ "predicted_direction_hex": self.predicted_direction.hex(),
1007
+ "epistemic_uncertainty_hex": self.epistemic_uncertainty.hex(),
1008
+ "marginal_z_hex": self.marginal_z.hex(),
1009
+ "direction_z_hex": self.direction_z.hex(),
1010
+ "uncertainty_z_hex": self.uncertainty_z.hex(),
1011
+ "final_score_hex": self.final_score.hex(),
1012
+ }
1013
+
1014
+
1015
+ class TargetConditionedSlateRole(str, Enum):
1016
+ """Engine-owned role for each evaluator exposure selected by T-RAP."""
1017
+
1018
+ ACQUISITION = "target_conditioned_acquisition"
1019
+
1020
+
1021
+ @dataclass(frozen=True, slots=True)
1022
+ class TargetConditionedAllocatedMember:
1023
+ option_id: str
1024
+ option_identity_sha256: str
1025
+ model_rank: int
1026
+ acquisition_score: float
1027
+ role: TargetConditionedSlateRole = TargetConditionedSlateRole.ACQUISITION
1028
+
1029
+ def __post_init__(self) -> None:
1030
+ if type(self.option_id) is not str or not self.option_id:
1031
+ raise ValueError("option_id must be non-empty")
1032
+ require_sha256(self.option_identity_sha256, "option_identity_sha256")
1033
+ if type(self.model_rank) is not int or self.model_rank <= 0:
1034
+ raise ValueError("model_rank must be positive")
1035
+ _finite(self.acquisition_score, name="acquisition_score")
1036
+ if type(self.role) is not TargetConditionedSlateRole:
1037
+ raise TypeError("role must be exact TargetConditionedSlateRole")
1038
+
1039
+ def to_record(self) -> dict[str, object]:
1040
+ self.__post_init__()
1041
+ return {
1042
+ "option_id": self.option_id,
1043
+ "option_identity_sha256": self.option_identity_sha256,
1044
+ "model_rank": self.model_rank,
1045
+ "acquisition_score_hex": self.acquisition_score.hex(),
1046
+ "role": self.role.value,
1047
+ }
1048
+
1049
+
1050
+ @dataclass(frozen=True, slots=True, eq=False)
1051
+ class TargetConditionedSlateDecision:
1052
+ request: TargetConditionedSlateRequest
1053
+ profile: TargetConditionedAcquisitionProfile
1054
+ score_rows: tuple[TargetConditionedMemberScore, ...]
1055
+ selected: tuple[TargetConditionedAllocatedMember, ...]
1056
+ joint_score: float
1057
+ feasible_subset_count: int
1058
+ administered_card_keys: tuple[str, ...]
1059
+ memory_dose_assessment: PortfolioMemoryDoseAssessment | None
1060
+
1061
+ policy_id: ClassVar[str] = POLICY_ID
1062
+ policy_version: ClassVar[int] = POLICY_VERSION
1063
+ policy_definition_sha256: ClassVar[str] = POLICY_DEFINITION_SHA256
1064
+
1065
+ def __post_init__(self) -> None:
1066
+ if type(self.request) is not TargetConditionedSlateRequest:
1067
+ raise TypeError("request must be exact")
1068
+ self.request.__post_init__()
1069
+ if type(self.profile) is not TargetConditionedAcquisitionProfile:
1070
+ raise TypeError("profile must be exact")
1071
+ self.profile.__post_init__()
1072
+ if type(self.score_rows) is not tuple or any(
1073
+ type(value) is not TargetConditionedMemberScore for value in self.score_rows
1074
+ ):
1075
+ raise TypeError("score_rows must contain exact values")
1076
+ if type(self.selected) is not tuple or len(self.selected) != (
1077
+ self.request.allocation_request.portfolio_size
1078
+ ):
1079
+ raise ValueError("selected must have the exact portfolio size")
1080
+ for value in (*self.score_rows, *self.selected):
1081
+ value.__post_init__()
1082
+ score_ids = tuple(value.option_id for value in self.score_rows)
1083
+ expected_score_ids = tuple(
1084
+ value.option_id for value in self.request.member_features
1085
+ )
1086
+ if score_ids != expected_score_ids:
1087
+ raise ValueError("score rows differ from the canonical feature rows")
1088
+ selected_ids = tuple(sorted(value.option_id for value in self.selected))
1089
+ if selected_ids not in self.request.realizable_portfolios.option_id_sets:
1090
+ raise ValueError("selected set is not realizable")
1091
+ _finite(self.joint_score, name="joint_score")
1092
+ if (
1093
+ type(self.feasible_subset_count) is not int
1094
+ or self.feasible_subset_count
1095
+ != len(self.request.realizable_portfolios.option_id_sets)
1096
+ ):
1097
+ raise ValueError("feasible_subset_count differs from the sealed universe")
1098
+ if self.administered_card_keys != tuple(sorted(set(self.administered_card_keys))):
1099
+ raise ValueError("administered_card_keys must be unique and canonical")
1100
+ if self.memory_dose_assessment is not None:
1101
+ if type(self.memory_dose_assessment) is not PortfolioMemoryDoseAssessment:
1102
+ raise TypeError("memory_dose_assessment must be exact or None")
1103
+ self.memory_dose_assessment.__post_init__()
1104
+ if not self.memory_dose_assessment.passed:
1105
+ raise ValueError("selected memory dose must pass")
1106
+
1107
+ def revalidate(self) -> None:
1108
+ if type(self) is not TargetConditionedSlateDecision:
1109
+ raise TypeError("decision must be exact")
1110
+ TargetConditionedSlateDecision.__post_init__(self)
1111
+
1112
+ @property
1113
+ def prior_only(self) -> bool:
1114
+ return self.request.state.cutoff_generation < self.request.campaign_generation
1115
+
1116
+ def _unsigned_record(self) -> dict[str, object]:
1117
+ self.revalidate()
1118
+ return {
1119
+ "schema_version": 1,
1120
+ "event_type": "target_conditioned_prequential_portfolio_allocated",
1121
+ "policy_id": self.policy_id,
1122
+ "policy_version": self.policy_version,
1123
+ "policy_definition_sha256": self.policy_definition_sha256,
1124
+ "request": self.request.to_record(),
1125
+ "profile": self.profile.to_record(),
1126
+ "score_rows": [value.to_record() for value in self.score_rows],
1127
+ "selected": [value.to_record() for value in self.selected],
1128
+ "joint_score_hex": self.joint_score.hex(),
1129
+ "feasible_subset_count": self.feasible_subset_count,
1130
+ "administered_card_keys": list(self.administered_card_keys),
1131
+ "memory_dose_assessment": (
1132
+ None
1133
+ if self.memory_dose_assessment is None
1134
+ else self.memory_dose_assessment.to_record()
1135
+ ),
1136
+ "prior_only": self.prior_only,
1137
+ "claim_scope": "allocation_receipt_not_efficacy_or_outcome_claim",
1138
+ }
1139
+
1140
+ @property
1141
+ def decision_sha256(self) -> str:
1142
+ return _hash(_DECISION_DOMAIN, self._unsigned_record())
1143
+
1144
+ def to_record(self) -> dict[str, object]:
1145
+ return {**self._unsigned_record(), "decision_sha256": self.decision_sha256}
1146
+
1147
+ def __eq__(self, other: object) -> bool:
1148
+ return (
1149
+ type(other) is TargetConditionedSlateDecision
1150
+ and self.decision_sha256 == other.decision_sha256
1151
+ )
1152
+
1153
+ __hash__ = None
1154
+
1155
+
1156
+ @dataclass(frozen=True, slots=True)
1157
+ class TargetConditionedPrequentialSlatePolicy:
1158
+ """Select the exact highest-scoring realizable set under a frozen profile."""
1159
+
1160
+ profile: TargetConditionedAcquisitionProfile
1161
+
1162
+ policy_id: ClassVar[str] = POLICY_ID
1163
+ policy_version: ClassVar[int] = POLICY_VERSION
1164
+ definition_sha256: ClassVar[str] = POLICY_DEFINITION_SHA256
1165
+
1166
+ def __post_init__(self) -> None:
1167
+ if type(self.profile) is not TargetConditionedAcquisitionProfile:
1168
+ raise TypeError("profile must be exact")
1169
+ self.profile.__post_init__()
1170
+
1171
+ def select(self, request: TargetConditionedSlateRequest) -> TargetConditionedSlateDecision:
1172
+ self.__post_init__()
1173
+ if type(request) is not TargetConditionedSlateRequest:
1174
+ raise TypeError("request must be exact")
1175
+ request.__post_init__()
1176
+ if request.remaining_proposal_horizon > self.profile.maximum_remaining_horizon:
1177
+ raise ValueError("remaining horizon exceeds the frozen profile")
1178
+ marginal_head = request.state.marginal_head.project()
1179
+ direction_head = request.state.direction_head.project()
1180
+ marginal = {
1181
+ row.option_id: marginal_head.predict(row.values)
1182
+ for row in request.member_features
1183
+ }
1184
+ direction = {
1185
+ row.option_id: direction_head.predict(row.values)
1186
+ for row in request.member_features
1187
+ }
1188
+ uncertainty = {
1189
+ row.option_id: marginal_head.uncertainty(row.values)
1190
+ for row in request.member_features
1191
+ }
1192
+ marginal_z = _z_scores(marginal)
1193
+ direction_z = _z_scores(direction)
1194
+ uncertainty_z = _z_scores(uncertainty)
1195
+ horizon_fraction = (
1196
+ request.remaining_proposal_horizon
1197
+ / self.profile.maximum_remaining_horizon
1198
+ )
1199
+ scores = {
1200
+ option_id: (
1201
+ marginal_z[option_id]
1202
+ + self.profile.direction_weight * direction_z[option_id]
1203
+ + self.profile.uncertainty_weight
1204
+ * horizon_fraction
1205
+ * uncertainty_z[option_id]
1206
+ )
1207
+ for option_id in marginal
1208
+ }
1209
+ selected_set = min(
1210
+ request.realizable_portfolios.option_id_sets,
1211
+ key=lambda option_ids: (
1212
+ -sum(scores[option_id] for option_id in option_ids),
1213
+ option_ids,
1214
+ ),
1215
+ )
1216
+ selected_members = _members_for_ids(
1217
+ request.allocation_request, selected_set
1218
+ )
1219
+ feasible, dose = _base_feasible(request.allocation_request, selected_set)
1220
+ if not feasible: # Defensive after request validation.
1221
+ raise RuntimeError("winning realizable set became base-infeasible")
1222
+ feature_by_id = {value.option_id: value for value in request.member_features}
1223
+ member_by_id = {
1224
+ value.option_id: value for value in request.allocation_request.slate.members
1225
+ }
1226
+ score_rows = tuple(
1227
+ TargetConditionedMemberScore(
1228
+ option_id=option_id,
1229
+ option_identity_sha256=feature_by_id[
1230
+ option_id
1231
+ ].option_identity_sha256,
1232
+ model_rank=member_by_id[option_id].model_rank,
1233
+ predicted_marginal=marginal[option_id],
1234
+ predicted_direction=direction[option_id],
1235
+ epistemic_uncertainty=uncertainty[option_id],
1236
+ marginal_z=marginal_z[option_id],
1237
+ direction_z=direction_z[option_id],
1238
+ uncertainty_z=uncertainty_z[option_id],
1239
+ final_score=scores[option_id],
1240
+ )
1241
+ for option_id in sorted(member_by_id)
1242
+ )
1243
+ selected = tuple(
1244
+ TargetConditionedAllocatedMember(
1245
+ option_id=member.option_id,
1246
+ option_identity_sha256=member.option_identity_sha256,
1247
+ model_rank=member.model_rank,
1248
+ acquisition_score=scores[member.option_id],
1249
+ )
1250
+ for member in selected_members
1251
+ )
1252
+ administered = tuple(
1253
+ sorted(
1254
+ {
1255
+ card
1256
+ for member in selected_members
1257
+ for card in member.supporting_card_keys
1258
+ if card in request.allocation_request.assigned_card_keys
1259
+ }
1260
+ )
1261
+ )
1262
+ return TargetConditionedSlateDecision(
1263
+ request=request,
1264
+ profile=self.profile,
1265
+ score_rows=score_rows,
1266
+ selected=selected,
1267
+ joint_score=sum(scores[value] for value in selected_set),
1268
+ feasible_subset_count=len(
1269
+ request.realizable_portfolios.option_id_sets
1270
+ ),
1271
+ administered_card_keys=administered,
1272
+ memory_dose_assessment=dose,
1273
+ )
1274
+
1275
+ def to_record(self) -> dict[str, object]:
1276
+ self.__post_init__()
1277
+ return {
1278
+ "policy_id": self.policy_id,
1279
+ "policy_version": self.policy_version,
1280
+ "definition_sha256": self.definition_sha256,
1281
+ "profile": self.profile.to_record(),
1282
+ }
1283
+
1284
+
1285
+ @dataclass(frozen=True, slots=True, eq=False)
1286
+ class TargetConditionedSelectedObservation:
1287
+ """Two evaluator-derived labels for one actually selected member."""
1288
+
1289
+ decision_sha256: str
1290
+ campaign_generation: int
1291
+ option_id: str
1292
+ option_identity_sha256: str
1293
+ feature_row_sha256: str
1294
+ feature_values: tuple[float, ...]
1295
+ normalized_marginal_utility: float
1296
+ normalized_target_improvement: float
1297
+ evaluator_receipt_sha256: str
1298
+
1299
+ def __post_init__(self) -> None:
1300
+ for name in (
1301
+ "decision_sha256",
1302
+ "option_identity_sha256",
1303
+ "feature_row_sha256",
1304
+ "evaluator_receipt_sha256",
1305
+ ):
1306
+ require_sha256(getattr(self, name), name)
1307
+ if type(self.campaign_generation) is not int or self.campaign_generation <= 0:
1308
+ raise ValueError("campaign_generation must be positive")
1309
+ if type(self.option_id) is not str or not self.option_id:
1310
+ raise ValueError("option_id must be non-empty")
1311
+ if type(self.feature_values) is not tuple or not self.feature_values:
1312
+ raise ValueError("feature_values must be non-empty")
1313
+ for value in self.feature_values:
1314
+ _finite(value, name="feature value")
1315
+ for name in (
1316
+ "normalized_marginal_utility",
1317
+ "normalized_target_improvement",
1318
+ ):
1319
+ _finite(getattr(self, name), name=name)
1320
+ if not -1.0 <= self.normalized_target_improvement <= 1.0:
1321
+ raise ValueError("normalized_target_improvement must lie in [-1, 1]")
1322
+
1323
+ def _unsigned_record(self) -> dict[str, object]:
1324
+ self.__post_init__()
1325
+ return {
1326
+ "decision_sha256": self.decision_sha256,
1327
+ "campaign_generation": self.campaign_generation,
1328
+ "option_id": self.option_id,
1329
+ "option_identity_sha256": self.option_identity_sha256,
1330
+ "feature_row_sha256": self.feature_row_sha256,
1331
+ "feature_values_hex": [value.hex() for value in self.feature_values],
1332
+ "normalized_marginal_utility_hex": (
1333
+ self.normalized_marginal_utility.hex()
1334
+ ),
1335
+ "normalized_target_improvement_hex": (
1336
+ self.normalized_target_improvement.hex()
1337
+ ),
1338
+ "evaluator_receipt_sha256": self.evaluator_receipt_sha256,
1339
+ }
1340
+
1341
+ @property
1342
+ def observation_sha256(self) -> str:
1343
+ return _hash(_OBSERVATION_DOMAIN, self._unsigned_record())
1344
+
1345
+ def to_record(self) -> dict[str, object]:
1346
+ return {
1347
+ **self._unsigned_record(),
1348
+ "observation_sha256": self.observation_sha256,
1349
+ }
1350
+
1351
+ def __eq__(self, other: object) -> bool:
1352
+ return (
1353
+ type(other) is TargetConditionedSelectedObservation
1354
+ and self.observation_sha256 == other.observation_sha256
1355
+ )
1356
+
1357
+ __hash__ = None
1358
+
1359
+
1360
+ @dataclass(frozen=True, slots=True, eq=False)
1361
+ class TargetConditionedStateUpdateReceipt:
1362
+ prior_state_sha256: str
1363
+ next_state: TargetConditionedAcquisitionState
1364
+ campaign_generation: int
1365
+ decision_sha256s: tuple[str, ...]
1366
+ observation_sha256s: tuple[str, ...]
1367
+
1368
+ def __post_init__(self) -> None:
1369
+ require_sha256(self.prior_state_sha256, "prior_state_sha256")
1370
+ if type(self.next_state) is not TargetConditionedAcquisitionState:
1371
+ raise TypeError("next_state must be exact")
1372
+ self.next_state.__post_init__()
1373
+ if type(self.campaign_generation) is not int or self.campaign_generation <= 0:
1374
+ raise ValueError("campaign_generation must be positive")
1375
+ for name in ("decision_sha256s", "observation_sha256s"):
1376
+ values = getattr(self, name)
1377
+ if type(values) is not tuple or not values:
1378
+ raise ValueError(f"{name} must be non-empty")
1379
+ for value in values:
1380
+ require_sha256(value, name)
1381
+ if values != tuple(sorted(set(values))):
1382
+ raise ValueError(f"{name} must be unique and canonical")
1383
+
1384
+ def _unsigned_record(self) -> dict[str, object]:
1385
+ self.__post_init__()
1386
+ return {
1387
+ "schema_version": 1,
1388
+ "prior_state_sha256": self.prior_state_sha256,
1389
+ "next_state": self.next_state.to_record(),
1390
+ "campaign_generation": self.campaign_generation,
1391
+ "decision_sha256s": list(self.decision_sha256s),
1392
+ "observation_sha256s": list(self.observation_sha256s),
1393
+ "update_boundary": "all_concurrent_lanes_complete",
1394
+ "rejected_outcomes_consulted": False,
1395
+ }
1396
+
1397
+ @property
1398
+ def update_sha256(self) -> str:
1399
+ return _hash(_UPDATE_DOMAIN, self._unsigned_record())
1400
+
1401
+ def to_record(self) -> dict[str, object]:
1402
+ return {**self._unsigned_record(), "update_sha256": self.update_sha256}
1403
+
1404
+ def __eq__(self, other: object) -> bool:
1405
+ return (
1406
+ type(other) is TargetConditionedStateUpdateReceipt
1407
+ and self.update_sha256 == other.update_sha256
1408
+ )
1409
+
1410
+ __hash__ = None
1411
+
1412
+
1413
+ def update_target_conditioned_state(
1414
+ state: TargetConditionedAcquisitionState,
1415
+ *,
1416
+ decisions: tuple[TargetConditionedSlateDecision, ...],
1417
+ observations: tuple[TargetConditionedSelectedObservation, ...],
1418
+ ) -> TargetConditionedStateUpdateReceipt:
1419
+ """Update once after every concurrent lane in one generation completes."""
1420
+
1421
+ if type(state) is not TargetConditionedAcquisitionState:
1422
+ raise TypeError("state must be exact")
1423
+ state.__post_init__()
1424
+ if type(decisions) is not tuple or not decisions or any(
1425
+ type(value) is not TargetConditionedSlateDecision for value in decisions
1426
+ ):
1427
+ raise TypeError("decisions must contain exact decisions")
1428
+ if type(observations) is not tuple or not observations or any(
1429
+ type(value) is not TargetConditionedSelectedObservation
1430
+ for value in observations
1431
+ ):
1432
+ raise TypeError("observations must contain exact selected observations")
1433
+ for value in decisions:
1434
+ value.revalidate()
1435
+ if value.request.state != state:
1436
+ raise ValueError("concurrent decisions must share the exact prior state")
1437
+ for value in observations:
1438
+ value.__post_init__()
1439
+ generations = {value.request.campaign_generation for value in decisions}
1440
+ generations.update(value.campaign_generation for value in observations)
1441
+ if len(generations) != 1:
1442
+ raise ValueError("one update cannot mix campaign generations")
1443
+ generation = next(iter(generations))
1444
+ if state.cutoff_generation >= generation:
1445
+ raise ValueError("state cutoff reaches the update generation")
1446
+ decisions_by_sha = {value.decision_sha256: value for value in decisions}
1447
+ if len(decisions_by_sha) != len(decisions):
1448
+ raise ValueError("decisions must be unique")
1449
+ expected: dict[tuple[str, str], tuple[str, str, tuple[float, ...]]] = {}
1450
+ for decision in decisions:
1451
+ features = {
1452
+ value.option_id: value for value in decision.request.member_features
1453
+ }
1454
+ for selected in decision.selected:
1455
+ row = features[selected.option_id]
1456
+ expected[(decision.decision_sha256, selected.option_id)] = (
1457
+ selected.option_identity_sha256,
1458
+ row.feature_row_sha256,
1459
+ row.values,
1460
+ )
1461
+ observed = {
1462
+ (value.decision_sha256, value.option_id): value for value in observations
1463
+ }
1464
+ if len(observed) != len(observations) or set(observed) != set(expected):
1465
+ raise ValueError("updates must cover exactly every selected member once")
1466
+ ordered = []
1467
+ for key in sorted(expected):
1468
+ observation = observed[key]
1469
+ option_identity, feature_sha, feature_values = expected[key]
1470
+ if (
1471
+ observation.option_identity_sha256 != option_identity
1472
+ or observation.feature_row_sha256 != feature_sha
1473
+ or observation.feature_values != feature_values
1474
+ ):
1475
+ raise ValueError("observation differs from its selected feature row")
1476
+ ordered.append(observation)
1477
+ next_state = TargetConditionedAcquisitionState(
1478
+ campaign_scope_sha256=state.campaign_scope_sha256,
1479
+ training_data_sha256=state.training_data_sha256,
1480
+ marginal_head=state.marginal_head.update(
1481
+ [value.feature_values for value in ordered],
1482
+ [value.normalized_marginal_utility for value in ordered],
1483
+ ),
1484
+ direction_head=state.direction_head.update(
1485
+ [value.feature_values for value in ordered],
1486
+ [value.normalized_target_improvement for value in ordered],
1487
+ ),
1488
+ cutoff_generation=generation,
1489
+ selected_observation_count=(
1490
+ state.selected_observation_count + len(ordered)
1491
+ ),
1492
+ )
1493
+ return TargetConditionedStateUpdateReceipt(
1494
+ prior_state_sha256=state.state_sha256,
1495
+ next_state=next_state,
1496
+ campaign_generation=generation,
1497
+ decision_sha256s=tuple(sorted(decisions_by_sha)),
1498
+ observation_sha256s=tuple(
1499
+ sorted(value.observation_sha256 for value in ordered)
1500
+ ),
1501
+ )
1502
+
1503
+
1504
+ __all__ = [
1505
+ "BASE_REALIZABILITY_DEFINITION_SHA256",
1506
+ "BASE_REALIZABILITY_PROJECTOR_ID",
1507
+ "BASE_REALIZABILITY_PROJECTOR_VERSION",
1508
+ "POLICY_DEFINITION_SHA256",
1509
+ "POLICY_ID",
1510
+ "POLICY_VERSION",
1511
+ "PrequentialLinearGaussianHead",
1512
+ "RealizablePortfolioSet",
1513
+ "TargetConditionedAcquisitionProfile",
1514
+ "TargetConditionedAcquisitionState",
1515
+ "TargetConditionedAllocatedMember",
1516
+ "TargetConditionedMemberFeatures",
1517
+ "TargetConditionedMemberScore",
1518
+ "TargetConditionedMetaPrior",
1519
+ "TargetConditionedPrequentialSlatePolicy",
1520
+ "TargetConditionedSelectedObservation",
1521
+ "TargetConditionedSlateDecision",
1522
+ "TargetConditionedSlateRequest",
1523
+ "TargetConditionedSlateRole",
1524
+ "TargetConditionedStateUpdateReceipt",
1525
+ "enumerate_base_realizable_portfolios",
1526
+ "update_target_conditioned_state",
1527
+ ]