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,2827 @@
1
+ """Outcome-adaptive allocation inside one sealed materialized-action market.
2
+
3
+ The policy in this module is deliberately narrower than proposal generation.
4
+ It receives a workload-opaque market whose candidates were all materialized
5
+ before current outcomes existed. It first chooses a diagnostic pilot using
6
+ only portable action descriptors. After real pilot outcomes are durably
7
+ available, it chooses one continuation action at a time.
8
+
9
+ This is a normal sequential-optimization information boundary:
10
+
11
+ * unobserved candidate outcomes are never accepted by the policy;
12
+ * the proposal market and real-evaluation budget remain fixed;
13
+ * every decision binds the exact observed outcome hashes that precede it; and
14
+ * one continuation seat is randomized over an authenticated exploration pool.
15
+
16
+ The policy knows no workload, objective, configuration field, model, provider,
17
+ or prompt. Callers project those concerns into opaque lane/operator/semantic
18
+ cells and a normalized, outcome-blind prior score.
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import hashlib
24
+ import json
25
+ import math
26
+ import random
27
+ import re
28
+ from dataclasses import dataclass, field
29
+ from enum import Enum
30
+
31
+ from agent_evolve.domain.patch import require_sha256
32
+ from agent_evolve.domain.typed_json import (
33
+ FrozenJsonObject,
34
+ freeze_json,
35
+ thaw_json,
36
+ typed_json_sha256,
37
+ )
38
+
39
+
40
+ OUTCOME_ADAPTIVE_ACTION_RACING_POLICY_ID = (
41
+ "outcome_adaptive_action_racing"
42
+ )
43
+ OUTCOME_ADAPTIVE_ACTION_RACING_POLICY_VERSION = 2
44
+ OUTCOME_ADAPTIVE_ACTION_RACING_SET_AWARE_POLICY_VERSION = 3
45
+ OUTCOME_ADAPTIVE_ACTION_RACING_CAUSAL_SET_POLICY_VERSION = 4
46
+ OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION = 5
47
+ OUTCOME_ADAPTIVE_ACTION_RACING_STRATIFIED_AUDIT_POLICY_VERSION = 6
48
+ OUTCOME_ADAPTIVE_ACTION_RACING_HORIZON_HIERARCHICAL_POLICY_VERSION = 7
49
+
50
+ _CAUSAL_SET_POLICY_VERSIONS = frozenset(
51
+ {
52
+ OUTCOME_ADAPTIVE_ACTION_RACING_CAUSAL_SET_POLICY_VERSION,
53
+ OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION,
54
+ }
55
+ )
56
+
57
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
58
+ _POLICY_DEFINITION_DOMAIN = (
59
+ b"agent-evolve:outcome-adaptive-action-racing-definition:v1\x00"
60
+ )
61
+ _OUTCOME_DOMAIN = b"agent-evolve:adaptive-action-outcome:v1\x00"
62
+ _SET_OUTCOME_DOMAIN = b"agent-evolve:adaptive-action-set-outcome:v1\x00"
63
+ _DECISION_DOMAIN = b"agent-evolve:adaptive-action-racing-decision:v1\x00"
64
+ _DIRECTIVE_DOMAIN = (
65
+ b"agent-evolve:adaptive-action-allocation-directive:v1\x00"
66
+ )
67
+
68
+
69
+ def _canonical_json(value: object) -> bytes:
70
+ return json.dumps(
71
+ value,
72
+ allow_nan=False,
73
+ ensure_ascii=True,
74
+ separators=(",", ":"),
75
+ sort_keys=True,
76
+ ).encode("ascii", errors="strict")
77
+
78
+
79
+ def _hash(domain: bytes, value: object) -> str:
80
+ return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
81
+
82
+
83
+ def _require_token(value: str, *, name: str) -> None:
84
+ if type(value) is not str or _TOKEN.fullmatch(value) is None:
85
+ raise ValueError(f"{name} must use the closed token grammar")
86
+
87
+
88
+ def _require_probability(value: float, *, name: str) -> None:
89
+ if (
90
+ type(value) is not float
91
+ or not math.isfinite(value)
92
+ or not 0.0 <= value <= 1.0
93
+ ):
94
+ raise ValueError(f"{name} must be a finite probability")
95
+
96
+
97
+ def _stable_unit_interval(*parts: object) -> float:
98
+ payload = _canonical_json(list(parts))
99
+ numerator = int.from_bytes(hashlib.sha256(payload).digest()[:8], "big")
100
+ return numerator / float(2**64)
101
+
102
+
103
+ @dataclass(frozen=True, slots=True, order=True)
104
+ class AdaptiveActionFactorCell:
105
+ """One opaque, pre-evaluation factor level used for audit strata."""
106
+
107
+ family_id: str
108
+ level_id: str
109
+
110
+ def __post_init__(self) -> None:
111
+ _require_token(self.family_id, name="factor family_id")
112
+ _require_token(self.level_id, name="factor level_id")
113
+
114
+ def to_record(self) -> dict[str, str]:
115
+ self.__post_init__()
116
+ return {
117
+ "family_id": self.family_id,
118
+ "level_id": self.level_id,
119
+ }
120
+
121
+
122
+ @dataclass(frozen=True, slots=True)
123
+ class AdaptiveActionDescriptor:
124
+ """Portable, outcome-blind view of one materialized action."""
125
+
126
+ action_sha256: str
127
+ phenotype_sha256: str
128
+ lane_id: str
129
+ operator_id: str
130
+ native_rank: int
131
+ lane_size: int
132
+ prior_score: float
133
+ parent_generated_in_current_run: bool
134
+ semantic_cell_ids: tuple[str, ...] = ()
135
+ factor_cells: tuple[AdaptiveActionFactorCell, ...] = ()
136
+
137
+ def __post_init__(self) -> None:
138
+ require_sha256(self.action_sha256, "action_sha256")
139
+ require_sha256(self.phenotype_sha256, "phenotype_sha256")
140
+ _require_token(self.lane_id, name="lane_id")
141
+ _require_token(self.operator_id, name="operator_id")
142
+ if (
143
+ type(self.native_rank) is not int
144
+ or self.native_rank <= 0
145
+ or type(self.lane_size) is not int
146
+ or self.lane_size <= 0
147
+ or self.native_rank > self.lane_size
148
+ ):
149
+ raise ValueError("native rank must fit the positive lane size")
150
+ _require_probability(self.prior_score, name="prior_score")
151
+ if type(self.parent_generated_in_current_run) is not bool:
152
+ raise TypeError(
153
+ "parent_generated_in_current_run must be exact"
154
+ )
155
+ if (
156
+ type(self.semantic_cell_ids) is not tuple
157
+ or self.semantic_cell_ids
158
+ != tuple(sorted(set(self.semantic_cell_ids)))
159
+ ):
160
+ raise ValueError(
161
+ "semantic_cell_ids must be an exact canonical tuple"
162
+ )
163
+ for value in self.semantic_cell_ids:
164
+ _require_token(value, name="semantic_cell_id")
165
+ if (
166
+ type(self.factor_cells) is not tuple
167
+ or self.factor_cells != tuple(sorted(self.factor_cells))
168
+ or any(
169
+ type(value) is not AdaptiveActionFactorCell
170
+ for value in self.factor_cells
171
+ )
172
+ ):
173
+ raise ValueError(
174
+ "factor_cells must be an exact canonical cell tuple"
175
+ )
176
+ for value in self.factor_cells:
177
+ value.__post_init__()
178
+ if len({value.family_id for value in self.factor_cells}) != len(
179
+ self.factor_cells
180
+ ):
181
+ raise ValueError(
182
+ "factor_cells must contain at most one level per family"
183
+ )
184
+
185
+ @property
186
+ def rank_quality(self) -> float:
187
+ """Return one for the lane head and zero for the lane tail."""
188
+
189
+ if self.lane_size == 1:
190
+ return 1.0
191
+ return 1.0 - (
192
+ (self.native_rank - 1) / float(self.lane_size - 1)
193
+ )
194
+
195
+ def to_record(self) -> dict[str, object]:
196
+ self.__post_init__()
197
+ record: dict[str, object] = {
198
+ "action_sha256": self.action_sha256,
199
+ "phenotype_sha256": self.phenotype_sha256,
200
+ "lane_id": self.lane_id,
201
+ "operator_id": self.operator_id,
202
+ "native_rank": self.native_rank,
203
+ "lane_size": self.lane_size,
204
+ "rank_quality_hex": self.rank_quality.hex(),
205
+ "prior_score_hex": self.prior_score.hex(),
206
+ "parent_generated_in_current_run": (
207
+ self.parent_generated_in_current_run
208
+ ),
209
+ "semantic_cell_ids": list(self.semantic_cell_ids),
210
+ }
211
+ # Preserve byte-identical records for policy versions 2--5.
212
+ if self.factor_cells:
213
+ record["factor_cells"] = [
214
+ value.to_record() for value in self.factor_cells
215
+ ]
216
+ return record
217
+
218
+
219
+ @dataclass(frozen=True, slots=True)
220
+ class AdaptiveActionOutcome:
221
+ """One real outcome available before a continuation decision."""
222
+
223
+ action_sha256: str
224
+ evaluation_sha256: str
225
+ feasible: bool
226
+ marginal_archive_gain: float
227
+ outcome_sha256: str = field(init=False)
228
+
229
+ def __post_init__(self) -> None:
230
+ require_sha256(self.action_sha256, "action_sha256")
231
+ require_sha256(self.evaluation_sha256, "evaluation_sha256")
232
+ if type(self.feasible) is not bool:
233
+ raise TypeError("feasible must be exact")
234
+ if (
235
+ type(self.marginal_archive_gain) is not float
236
+ or not math.isfinite(self.marginal_archive_gain)
237
+ or self.marginal_archive_gain < 0.0
238
+ ):
239
+ raise ValueError(
240
+ "marginal_archive_gain must be finite and non-negative"
241
+ )
242
+ if not self.feasible and self.marginal_archive_gain != 0.0:
243
+ raise ValueError("an infeasible action cannot contribute gain")
244
+ object.__setattr__(
245
+ self,
246
+ "outcome_sha256",
247
+ _hash(_OUTCOME_DOMAIN, self._unsigned_record()),
248
+ )
249
+
250
+ @property
251
+ def positive(self) -> bool:
252
+ return self.marginal_archive_gain > 0.0
253
+
254
+ def _unsigned_record(self) -> dict[str, object]:
255
+ return {
256
+ "schema_version": 1,
257
+ "action_sha256": self.action_sha256,
258
+ "evaluation_sha256": self.evaluation_sha256,
259
+ "feasible": self.feasible,
260
+ "marginal_archive_gain_hex": (
261
+ self.marginal_archive_gain.hex()
262
+ ),
263
+ }
264
+
265
+ def to_record(self) -> dict[str, object]:
266
+ self.__post_init__()
267
+ return {
268
+ **self._unsigned_record(),
269
+ "positive": self.positive,
270
+ "outcome_sha256": self.outcome_sha256,
271
+ }
272
+
273
+
274
+ def _validated_action_evaluation_bindings(
275
+ values: tuple[tuple[str, str], ...],
276
+ *,
277
+ name: str,
278
+ allow_empty: bool,
279
+ ) -> tuple[tuple[str, str], ...]:
280
+ if type(values) is not tuple or (not allow_empty and not values):
281
+ raise ValueError(f"{name} must be a canonical exact tuple")
282
+ bindings: list[tuple[str, str]] = []
283
+ for value in values:
284
+ if type(value) is not tuple or len(value) != 2:
285
+ raise TypeError(f"{name} must contain exact hash pairs")
286
+ action_sha256, evaluation_sha256 = value
287
+ require_sha256(action_sha256, f"{name} action_sha256")
288
+ require_sha256(evaluation_sha256, f"{name} evaluation_sha256")
289
+ bindings.append((action_sha256, evaluation_sha256))
290
+ if bindings != sorted(set(bindings)):
291
+ raise ValueError(f"{name} must be unique and canonical")
292
+ if len({value[0] for value in bindings}) != len(bindings):
293
+ raise ValueError(f"{name} repeats an action identity")
294
+ if len({value[1] for value in bindings}) != len(bindings):
295
+ raise ValueError(f"{name} repeats an evaluation identity")
296
+ return tuple(bindings)
297
+
298
+
299
+ def _require_nonnegative_metric(value: float, *, name: str) -> None:
300
+ if (
301
+ type(value) is not float
302
+ or not math.isfinite(value)
303
+ or value < 0.0
304
+ ):
305
+ raise ValueError(f"{name} must be finite and non-negative")
306
+
307
+
308
+ def _metric_close(left: float, right: float) -> bool:
309
+ return math.isclose(left, right, rel_tol=1e-12, abs_tol=1e-15)
310
+
311
+
312
+ @dataclass(frozen=True, slots=True)
313
+ class AdaptiveActionSetOutcome:
314
+ """Workload-opaque causal utility observation for one evaluated wave.
315
+
316
+ ``current_wave_fixed_set_gain`` values the current wave against the
317
+ pre-stage archive. ``conditional_set_gain`` values the same wave after
318
+ every earlier selected evaluation. Their difference therefore separates
319
+ local saturation (redundancy) from positive set interaction (synergy)
320
+ without exposing objective names, senses, configuration fields, or
321
+ workload semantics to the generic controller.
322
+ """
323
+
324
+ prior_action_evaluation_bindings: tuple[tuple[str, str], ...]
325
+ current_action_evaluation_bindings: tuple[tuple[str, str], ...]
326
+ prior_selected_set_gain: float
327
+ current_wave_fixed_set_gain: float
328
+ augmented_selected_set_gain: float
329
+ conditional_set_gain: float
330
+ set_outcome_sha256: str = field(init=False)
331
+
332
+ def __post_init__(self) -> None:
333
+ prior = _validated_action_evaluation_bindings(
334
+ self.prior_action_evaluation_bindings,
335
+ name="prior_action_evaluation_bindings",
336
+ allow_empty=True,
337
+ )
338
+ current = _validated_action_evaluation_bindings(
339
+ self.current_action_evaluation_bindings,
340
+ name="current_action_evaluation_bindings",
341
+ allow_empty=False,
342
+ )
343
+ prior_actions = {value[0] for value in prior}
344
+ current_actions = {value[0] for value in current}
345
+ prior_evaluations = {value[1] for value in prior}
346
+ current_evaluations = {value[1] for value in current}
347
+ if prior_actions & current_actions:
348
+ raise ValueError("prior and current bindings repeat an action")
349
+ if prior_evaluations & current_evaluations:
350
+ raise ValueError(
351
+ "prior and current bindings repeat an evaluation"
352
+ )
353
+ for name in (
354
+ "prior_selected_set_gain",
355
+ "current_wave_fixed_set_gain",
356
+ "augmented_selected_set_gain",
357
+ "conditional_set_gain",
358
+ ):
359
+ _require_nonnegative_metric(getattr(self, name), name=name)
360
+ if not _metric_close(
361
+ self.augmented_selected_set_gain,
362
+ self.prior_selected_set_gain + self.conditional_set_gain,
363
+ ):
364
+ raise ValueError(
365
+ "conditional_set_gain does not close the augmented set"
366
+ )
367
+ object.__setattr__(
368
+ self,
369
+ "set_outcome_sha256",
370
+ _hash(_SET_OUTCOME_DOMAIN, self._unsigned_record()),
371
+ )
372
+
373
+ @property
374
+ def prior_conditioned_redundancy(self) -> float:
375
+ if _metric_close(
376
+ self.current_wave_fixed_set_gain,
377
+ self.conditional_set_gain,
378
+ ):
379
+ return 0.0
380
+ return max(
381
+ self.current_wave_fixed_set_gain
382
+ - self.conditional_set_gain,
383
+ 0.0,
384
+ )
385
+
386
+ @property
387
+ def prior_conditioned_synergy(self) -> float:
388
+ if _metric_close(
389
+ self.current_wave_fixed_set_gain,
390
+ self.conditional_set_gain,
391
+ ):
392
+ return 0.0
393
+ return max(
394
+ self.conditional_set_gain
395
+ - self.current_wave_fixed_set_gain,
396
+ 0.0,
397
+ )
398
+
399
+ @property
400
+ def saturation_fraction(self) -> float:
401
+ if self.current_wave_fixed_set_gain == 0.0:
402
+ return 0.0
403
+ return min(
404
+ self.prior_conditioned_redundancy
405
+ / self.current_wave_fixed_set_gain,
406
+ 1.0,
407
+ )
408
+
409
+ def _unsigned_record(self) -> dict[str, object]:
410
+ return {
411
+ "schema_version": 1,
412
+ "prior_action_evaluation_bindings": [
413
+ {
414
+ "action_sha256": action_sha256,
415
+ "evaluation_sha256": evaluation_sha256,
416
+ }
417
+ for action_sha256, evaluation_sha256 in (
418
+ self.prior_action_evaluation_bindings
419
+ )
420
+ ],
421
+ "current_action_evaluation_bindings": [
422
+ {
423
+ "action_sha256": action_sha256,
424
+ "evaluation_sha256": evaluation_sha256,
425
+ }
426
+ for action_sha256, evaluation_sha256 in (
427
+ self.current_action_evaluation_bindings
428
+ )
429
+ ],
430
+ "prior_selected_set_gain_hex": (
431
+ self.prior_selected_set_gain.hex()
432
+ ),
433
+ "current_wave_fixed_set_gain_hex": (
434
+ self.current_wave_fixed_set_gain.hex()
435
+ ),
436
+ "augmented_selected_set_gain_hex": (
437
+ self.augmented_selected_set_gain.hex()
438
+ ),
439
+ "conditional_set_gain_hex": self.conditional_set_gain.hex(),
440
+ }
441
+
442
+ def to_record(self) -> dict[str, object]:
443
+ self.__post_init__()
444
+ return {
445
+ **self._unsigned_record(),
446
+ "prior_conditioned_redundancy_hex": (
447
+ self.prior_conditioned_redundancy.hex()
448
+ ),
449
+ "prior_conditioned_synergy_hex": (
450
+ self.prior_conditioned_synergy.hex()
451
+ ),
452
+ "saturation_fraction_hex": self.saturation_fraction.hex(),
453
+ "set_outcome_sha256": self.set_outcome_sha256,
454
+ }
455
+
456
+
457
+ class AdaptiveActionWave(str, Enum):
458
+ DIAGNOSTIC = "diagnostic"
459
+ ADAPTIVE = "adaptive"
460
+ RANDOMIZED_AUDIT = "randomized_audit"
461
+
462
+
463
+ @dataclass(frozen=True, slots=True)
464
+ class AdaptiveActionRacingDecision:
465
+ """Hash-bound action subset chosen at one information cutoff."""
466
+
467
+ policy_id: str
468
+ policy_version: int
469
+ policy_definition_sha256: str
470
+ residual_request_sha256: str
471
+ wave: AdaptiveActionWave
472
+ selected_action_sha256s: tuple[str, ...]
473
+ prior_selected_action_sha256s: tuple[str, ...]
474
+ observed_outcome_sha256s: tuple[str, ...]
475
+ observed_set_outcome_sha256s: tuple[str, ...]
476
+ selection_propensity: float
477
+ evidence: FrozenJsonObject
478
+ decision_sha256: str = field(init=False)
479
+
480
+ def __post_init__(self) -> None:
481
+ _require_token(self.policy_id, name="policy_id")
482
+ if type(self.policy_version) is not int or self.policy_version <= 0:
483
+ raise ValueError("policy_version must be positive")
484
+ require_sha256(
485
+ self.policy_definition_sha256,
486
+ "policy_definition_sha256",
487
+ )
488
+ require_sha256(
489
+ self.residual_request_sha256,
490
+ "residual_request_sha256",
491
+ )
492
+ if type(self.wave) is not AdaptiveActionWave:
493
+ raise TypeError("wave must be an exact AdaptiveActionWave")
494
+ for values, name in (
495
+ (self.selected_action_sha256s, "selected_action_sha256s"),
496
+ (
497
+ self.prior_selected_action_sha256s,
498
+ "prior_selected_action_sha256s",
499
+ ),
500
+ (
501
+ self.observed_outcome_sha256s,
502
+ "observed_outcome_sha256s",
503
+ ),
504
+ (
505
+ self.observed_set_outcome_sha256s,
506
+ "observed_set_outcome_sha256s",
507
+ ),
508
+ ):
509
+ if type(values) is not tuple or values != tuple(
510
+ sorted(set(values))
511
+ ):
512
+ raise ValueError(f"{name} must be an exact canonical tuple")
513
+ for value in values:
514
+ require_sha256(value, name)
515
+ if not self.selected_action_sha256s:
516
+ raise ValueError("a racing decision must select an action")
517
+ if set(self.selected_action_sha256s) & set(
518
+ self.prior_selected_action_sha256s
519
+ ):
520
+ raise ValueError("a racing decision cannot repeat an action")
521
+ _require_probability(
522
+ self.selection_propensity,
523
+ name="selection_propensity",
524
+ )
525
+ if self.selection_propensity <= 0.0:
526
+ raise ValueError("selection propensity must be positive")
527
+ if (
528
+ self.wave is AdaptiveActionWave.DIAGNOSTIC
529
+ and (
530
+ self.observed_outcome_sha256s
531
+ or self.observed_set_outcome_sha256s
532
+ )
533
+ ):
534
+ raise ValueError(
535
+ "diagnostic design cannot observe current outcomes"
536
+ )
537
+ if (
538
+ type(self.evidence) is not FrozenJsonObject
539
+ or freeze_json(self.evidence) is not self.evidence
540
+ ):
541
+ raise TypeError("evidence must be an exact frozen object")
542
+ object.__setattr__(
543
+ self,
544
+ "decision_sha256",
545
+ _hash(_DECISION_DOMAIN, self._unsigned_record()),
546
+ )
547
+
548
+ @property
549
+ def candidate_outcomes_observed(self) -> bool:
550
+ return bool(self.observed_outcome_sha256s)
551
+
552
+ def _unsigned_record(self) -> dict[str, object]:
553
+ return {
554
+ "schema_version": 2,
555
+ "policy": {
556
+ "policy_id": self.policy_id,
557
+ "policy_version": self.policy_version,
558
+ "definition_sha256": self.policy_definition_sha256,
559
+ },
560
+ "residual_request_sha256": self.residual_request_sha256,
561
+ "wave": self.wave.value,
562
+ "selected_action_sha256s": list(
563
+ self.selected_action_sha256s
564
+ ),
565
+ "prior_selected_action_sha256s": list(
566
+ self.prior_selected_action_sha256s
567
+ ),
568
+ "observed_outcome_sha256s": list(
569
+ self.observed_outcome_sha256s
570
+ ),
571
+ "observed_set_outcome_sha256s": list(
572
+ self.observed_set_outcome_sha256s
573
+ ),
574
+ "candidate_outcomes_observed": (
575
+ self.candidate_outcomes_observed
576
+ ),
577
+ "selection_propensity_hex": self.selection_propensity.hex(),
578
+ "evidence_sha256": typed_json_sha256(self.evidence),
579
+ }
580
+
581
+ def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
582
+ self.__post_init__()
583
+ record = {
584
+ **self._unsigned_record(),
585
+ "decision_sha256": self.decision_sha256,
586
+ }
587
+ if include_evidence:
588
+ record["evidence"] = thaw_json(self.evidence)
589
+ return record
590
+
591
+
592
+ @dataclass(frozen=True, slots=True)
593
+ class AdaptiveActionAllocationDirective:
594
+ """Final outcome-adaptive slate constraint consumed by the broker.
595
+
596
+ Unlike ``MaterializedActionAllocationRequirement``, this directive is
597
+ intentionally outcome-conditioned. It binds the complete chain of
598
+ diagnostic and continuation decisions so downstream code cannot mistake it
599
+ for an outcome-blind requirement.
600
+ """
601
+
602
+ policy_id: str
603
+ policy_version: int
604
+ policy_definition_sha256: str
605
+ residual_request_sha256: str
606
+ proposal_sha256s: tuple[str, ...]
607
+ required_action_sha256s: tuple[str, ...]
608
+ diagnostic_decision_sha256: str
609
+ continuation_decision_sha256s: tuple[str, ...]
610
+ observed_outcome_sha256s: tuple[str, ...]
611
+ observed_set_outcome_sha256s: tuple[str, ...]
612
+ evidence: FrozenJsonObject
613
+ directive_sha256: str = field(init=False)
614
+
615
+ def __post_init__(self) -> None:
616
+ _require_token(self.policy_id, name="policy_id")
617
+ if type(self.policy_version) is not int or self.policy_version <= 0:
618
+ raise ValueError("policy_version must be positive")
619
+ require_sha256(
620
+ self.policy_definition_sha256,
621
+ "policy_definition_sha256",
622
+ )
623
+ require_sha256(
624
+ self.residual_request_sha256,
625
+ "residual_request_sha256",
626
+ )
627
+ for values, name, allow_empty in (
628
+ (self.proposal_sha256s, "proposal_sha256s", False),
629
+ (
630
+ self.required_action_sha256s,
631
+ "required_action_sha256s",
632
+ False,
633
+ ),
634
+ (
635
+ self.continuation_decision_sha256s,
636
+ "continuation_decision_sha256s",
637
+ False,
638
+ ),
639
+ (
640
+ self.observed_outcome_sha256s,
641
+ "observed_outcome_sha256s",
642
+ False,
643
+ ),
644
+ (
645
+ self.observed_set_outcome_sha256s,
646
+ "observed_set_outcome_sha256s",
647
+ False,
648
+ ),
649
+ ):
650
+ if (
651
+ type(values) is not tuple
652
+ or (not allow_empty and not values)
653
+ or values != tuple(sorted(set(values)))
654
+ ):
655
+ raise ValueError(f"{name} must be a canonical exact tuple")
656
+ for value in values:
657
+ require_sha256(value, name)
658
+ require_sha256(
659
+ self.diagnostic_decision_sha256,
660
+ "diagnostic_decision_sha256",
661
+ )
662
+ if (
663
+ type(self.evidence) is not FrozenJsonObject
664
+ or freeze_json(self.evidence) is not self.evidence
665
+ ):
666
+ raise TypeError("evidence must be an exact frozen object")
667
+ object.__setattr__(
668
+ self,
669
+ "directive_sha256",
670
+ _hash(_DIRECTIVE_DOMAIN, self._unsigned_record()),
671
+ )
672
+
673
+ @property
674
+ def candidate_outcomes_observed(self) -> bool:
675
+ return True
676
+
677
+ @property
678
+ def requirement_sha256(self) -> str:
679
+ """Compatibility identity for the broker's existing constraint slot."""
680
+
681
+ return self.directive_sha256
682
+
683
+ def _unsigned_record(self) -> dict[str, object]:
684
+ return {
685
+ "schema_version": 2,
686
+ "allocation_kind": "outcome_adaptive_directive",
687
+ "policy": {
688
+ "policy_id": self.policy_id,
689
+ "policy_version": self.policy_version,
690
+ "definition_sha256": self.policy_definition_sha256,
691
+ },
692
+ "residual_request_sha256": self.residual_request_sha256,
693
+ "proposal_sha256s": list(self.proposal_sha256s),
694
+ "required_action_sha256s": list(
695
+ self.required_action_sha256s
696
+ ),
697
+ "diagnostic_decision_sha256": (
698
+ self.diagnostic_decision_sha256
699
+ ),
700
+ "continuation_decision_sha256s": list(
701
+ self.continuation_decision_sha256s
702
+ ),
703
+ "observed_outcome_sha256s": list(
704
+ self.observed_outcome_sha256s
705
+ ),
706
+ "observed_set_outcome_sha256s": list(
707
+ self.observed_set_outcome_sha256s
708
+ ),
709
+ "candidate_outcomes_observed": True,
710
+ "evidence_sha256": typed_json_sha256(self.evidence),
711
+ }
712
+
713
+ def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
714
+ self.__post_init__()
715
+ record = {
716
+ **self._unsigned_record(),
717
+ "directive_sha256": self.directive_sha256,
718
+ "requirement_sha256": self.requirement_sha256,
719
+ }
720
+ if include_evidence:
721
+ record["evidence"] = thaw_json(self.evidence)
722
+ return record
723
+
724
+
725
+ def _semantic_distance(
726
+ left: tuple[str, ...],
727
+ right: tuple[str, ...],
728
+ ) -> float:
729
+ union = set(left) | set(right)
730
+ if not union:
731
+ return 0.0
732
+ return 1.0 - (len(set(left) & set(right)) / len(union))
733
+
734
+
735
+ def _action_distance(
736
+ left: AdaptiveActionDescriptor,
737
+ right: AdaptiveActionDescriptor,
738
+ ) -> float:
739
+ """Portable mixed-type distance used only for coverage/uncertainty."""
740
+
741
+ left.__post_init__()
742
+ right.__post_init__()
743
+ return (
744
+ (1.0 if left.lane_id != right.lane_id else 0.0)
745
+ + abs(left.rank_quality - right.rank_quality)
746
+ + (
747
+ 0.5
748
+ if left.parent_generated_in_current_run
749
+ != right.parent_generated_in_current_run
750
+ else 0.0
751
+ )
752
+ + (0.25 if left.operator_id != right.operator_id else 0.0)
753
+ + 0.25
754
+ * _semantic_distance(
755
+ left.semantic_cell_ids,
756
+ right.semantic_cell_ids,
757
+ )
758
+ ) / 3.0
759
+
760
+
761
+ @dataclass(frozen=True, slots=True)
762
+ class OutcomeAdaptiveActionRacingPolicy:
763
+ """Lane-head diagnostic design followed by conservative contextual UCB."""
764
+
765
+ diagnostic_slots: int = 4
766
+ randomized_audit_slots: int = 1
767
+ reference_gain_scale: float = 1.0e-4
768
+ reference_gain_evidence_sha256: str = "0" * 64
769
+ prior_strength: float = 2.0
770
+ ucb_strength: float = 1.0
771
+ counterfactual_strength: float = 0.5
772
+ diversity_strength: float = 0.25
773
+ positive_redundancy_strength: float = 0.0
774
+ conditional_saturation_strength: float = 0.0
775
+ conditional_synergy_strength: float = 0.0
776
+ causal_prior_strength: float = 0.0
777
+ randomized_audit_after_directed_steps: int = 0
778
+ audit_exploration_probability: float = 0.0
779
+ exploration_pool_size: int = 4
780
+ trace_alternative_count: int = 0
781
+ stratified_audit_coverage_family_ids: tuple[str, ...] = ()
782
+ stratified_audit_stratum_family_ids: tuple[str, ...] = ()
783
+ minimum_post_audit_optimization_slots: int = 0
784
+ terminal_hierarchical_slots: int = 0
785
+ native_rank_strength: float = 0.0
786
+ random_seed: int = 0
787
+ policy_id: str = OUTCOME_ADAPTIVE_ACTION_RACING_POLICY_ID
788
+ policy_version: int = OUTCOME_ADAPTIVE_ACTION_RACING_POLICY_VERSION
789
+ definition_sha256: str = field(init=False)
790
+
791
+ def __post_init__(self) -> None:
792
+ if type(self.diagnostic_slots) is not int or self.diagnostic_slots <= 0:
793
+ raise ValueError("diagnostic_slots must be positive")
794
+ if (
795
+ type(self.randomized_audit_slots) is not int
796
+ or self.randomized_audit_slots <= 0
797
+ or self.randomized_audit_slots >= self.diagnostic_slots * 2
798
+ ):
799
+ raise ValueError("randomized_audit_slots must be bounded")
800
+ if (
801
+ type(self.reference_gain_scale) is not float
802
+ or not math.isfinite(self.reference_gain_scale)
803
+ or self.reference_gain_scale <= 0.0
804
+ ):
805
+ raise ValueError("reference_gain_scale must be positive")
806
+ require_sha256(
807
+ self.reference_gain_evidence_sha256,
808
+ "reference_gain_evidence_sha256",
809
+ )
810
+ for value, name in (
811
+ (self.prior_strength, "prior_strength"),
812
+ (self.ucb_strength, "ucb_strength"),
813
+ (
814
+ self.counterfactual_strength,
815
+ "counterfactual_strength",
816
+ ),
817
+ (self.diversity_strength, "diversity_strength"),
818
+ (
819
+ self.positive_redundancy_strength,
820
+ "positive_redundancy_strength",
821
+ ),
822
+ (
823
+ self.conditional_saturation_strength,
824
+ "conditional_saturation_strength",
825
+ ),
826
+ (
827
+ self.conditional_synergy_strength,
828
+ "conditional_synergy_strength",
829
+ ),
830
+ (
831
+ self.causal_prior_strength,
832
+ "causal_prior_strength",
833
+ ),
834
+ ):
835
+ if (
836
+ type(value) is not float
837
+ or not math.isfinite(value)
838
+ or value < 0.0
839
+ ):
840
+ raise ValueError(f"{name} must be finite and non-negative")
841
+ if (
842
+ type(self.exploration_pool_size) is not int
843
+ or self.exploration_pool_size <= 0
844
+ ):
845
+ raise ValueError("exploration_pool_size must be positive")
846
+ if (
847
+ type(self.randomized_audit_after_directed_steps) is not int
848
+ or self.randomized_audit_after_directed_steps < 0
849
+ ):
850
+ raise ValueError(
851
+ "randomized_audit_after_directed_steps must be "
852
+ "non-negative"
853
+ )
854
+ if (
855
+ type(self.minimum_post_audit_optimization_slots) is not int
856
+ or self.minimum_post_audit_optimization_slots < 0
857
+ ):
858
+ raise ValueError(
859
+ "minimum_post_audit_optimization_slots must be non-negative"
860
+ )
861
+ if (
862
+ type(self.terminal_hierarchical_slots) is not int
863
+ or self.terminal_hierarchical_slots < 0
864
+ ):
865
+ raise ValueError(
866
+ "terminal_hierarchical_slots must be non-negative"
867
+ )
868
+ if (
869
+ type(self.native_rank_strength) is not float
870
+ or not math.isfinite(self.native_rank_strength)
871
+ or self.native_rank_strength < 0.0
872
+ ):
873
+ raise ValueError(
874
+ "native_rank_strength must be finite and non-negative"
875
+ )
876
+ _require_probability(
877
+ self.audit_exploration_probability,
878
+ name="audit_exploration_probability",
879
+ )
880
+ if (
881
+ type(self.trace_alternative_count) is not int
882
+ or self.trace_alternative_count < 0
883
+ ):
884
+ raise ValueError(
885
+ "trace_alternative_count must be non-negative"
886
+ )
887
+ for values, name in (
888
+ (
889
+ self.stratified_audit_coverage_family_ids,
890
+ "stratified_audit_coverage_family_ids",
891
+ ),
892
+ (
893
+ self.stratified_audit_stratum_family_ids,
894
+ "stratified_audit_stratum_family_ids",
895
+ ),
896
+ ):
897
+ if (
898
+ type(values) is not tuple
899
+ or values != tuple(sorted(set(values)))
900
+ ):
901
+ raise ValueError(f"{name} must be an exact canonical tuple")
902
+ for value in values:
903
+ _require_token(value, name=name)
904
+ if type(self.random_seed) is not int or self.random_seed < 0:
905
+ raise ValueError("random_seed must be non-negative")
906
+ _require_token(self.policy_id, name="policy_id")
907
+ if self.policy_version not in {
908
+ OUTCOME_ADAPTIVE_ACTION_RACING_POLICY_VERSION,
909
+ OUTCOME_ADAPTIVE_ACTION_RACING_SET_AWARE_POLICY_VERSION,
910
+ OUTCOME_ADAPTIVE_ACTION_RACING_CAUSAL_SET_POLICY_VERSION,
911
+ OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION,
912
+ OUTCOME_ADAPTIVE_ACTION_RACING_STRATIFIED_AUDIT_POLICY_VERSION,
913
+ OUTCOME_ADAPTIVE_ACTION_RACING_HORIZON_HIERARCHICAL_POLICY_VERSION,
914
+ }:
915
+ raise ValueError("policy_version is unsupported")
916
+ if (
917
+ self.policy_version
918
+ == OUTCOME_ADAPTIVE_ACTION_RACING_POLICY_VERSION
919
+ and (
920
+ self.positive_redundancy_strength != 0.0
921
+ or self.trace_alternative_count != 0
922
+ or self.conditional_saturation_strength != 0.0
923
+ or self.conditional_synergy_strength != 0.0
924
+ or self.causal_prior_strength != 0.0
925
+ or self.randomized_audit_after_directed_steps != 0
926
+ or self.audit_exploration_probability != 0.0
927
+ or self.stratified_audit_coverage_family_ids
928
+ or self.stratified_audit_stratum_family_ids
929
+ or self.minimum_post_audit_optimization_slots != 0
930
+ or self.terminal_hierarchical_slots != 0
931
+ or self.native_rank_strength != 0.0
932
+ )
933
+ ):
934
+ raise ValueError(
935
+ "set-aware controls require policy version 3"
936
+ )
937
+ if (
938
+ self.policy_version
939
+ == OUTCOME_ADAPTIVE_ACTION_RACING_SET_AWARE_POLICY_VERSION
940
+ and (
941
+ self.trace_alternative_count <= 0
942
+ or self.conditional_saturation_strength != 0.0
943
+ or self.conditional_synergy_strength != 0.0
944
+ or self.causal_prior_strength != 0.0
945
+ or self.randomized_audit_after_directed_steps != 0
946
+ or self.audit_exploration_probability != 0.0
947
+ or self.stratified_audit_coverage_family_ids
948
+ or self.stratified_audit_stratum_family_ids
949
+ or self.minimum_post_audit_optimization_slots != 0
950
+ or self.terminal_hierarchical_slots != 0
951
+ or self.native_rank_strength != 0.0
952
+ )
953
+ ):
954
+ raise ValueError(
955
+ "policy version 3 requires auditable alternatives and "
956
+ "permits only its proxy controls"
957
+ )
958
+ if (
959
+ self.policy_version
960
+ == OUTCOME_ADAPTIVE_ACTION_RACING_CAUSAL_SET_POLICY_VERSION
961
+ and (
962
+ self.trace_alternative_count <= 0
963
+ or self.positive_redundancy_strength != 0.0
964
+ or self.conditional_saturation_strength <= 0.0
965
+ or self.causal_prior_strength <= 0.0
966
+ or self.randomized_audit_slots != 1
967
+ or self.audit_exploration_probability != 0.0
968
+ or self.stratified_audit_coverage_family_ids
969
+ or self.stratified_audit_stratum_family_ids
970
+ or self.minimum_post_audit_optimization_slots != 0
971
+ or self.terminal_hierarchical_slots != 0
972
+ or self.native_rank_strength != 0.0
973
+ )
974
+ ):
975
+ raise ValueError(
976
+ "policy version 4 requires causal set controls, one "
977
+ "mid-wave audit, and auditable alternatives"
978
+ )
979
+ if (
980
+ self.policy_version
981
+ == OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION
982
+ and (
983
+ self.trace_alternative_count <= 0
984
+ or self.positive_redundancy_strength != 0.0
985
+ or self.conditional_saturation_strength <= 0.0
986
+ or self.causal_prior_strength <= 0.0
987
+ or self.randomized_audit_slots != 1
988
+ or self.audit_exploration_probability <= 0.0
989
+ or self.stratified_audit_coverage_family_ids
990
+ or self.stratified_audit_stratum_family_ids
991
+ or self.minimum_post_audit_optimization_slots != 0
992
+ or self.terminal_hierarchical_slots != 0
993
+ or self.native_rank_strength != 0.0
994
+ )
995
+ ):
996
+ raise ValueError(
997
+ "policy version 5 requires causal set controls, one "
998
+ "risk-controlled audit, positive epsilon, and auditable "
999
+ "alternatives"
1000
+ )
1001
+ if (
1002
+ self.policy_version
1003
+ == OUTCOME_ADAPTIVE_ACTION_RACING_STRATIFIED_AUDIT_POLICY_VERSION
1004
+ and (
1005
+ self.trace_alternative_count <= 0
1006
+ or self.positive_redundancy_strength != 0.0
1007
+ or self.conditional_saturation_strength != 0.0
1008
+ or self.conditional_synergy_strength != 0.0
1009
+ or self.causal_prior_strength != 0.0
1010
+ or self.randomized_audit_after_directed_steps != 0
1011
+ or self.randomized_audit_slots != 1
1012
+ or self.audit_exploration_probability <= 0.0
1013
+ or not self.stratified_audit_coverage_family_ids
1014
+ or not self.stratified_audit_stratum_family_ids
1015
+ or self.minimum_post_audit_optimization_slots != 0
1016
+ or self.terminal_hierarchical_slots != 0
1017
+ or self.native_rank_strength != 0.0
1018
+ )
1019
+ ):
1020
+ raise ValueError(
1021
+ "policy version 6 requires one final risk-controlled audit, "
1022
+ "positive epsilon, auditable alternatives, and explicit "
1023
+ "coverage/stratum factor families"
1024
+ )
1025
+ if (
1026
+ self.policy_version
1027
+ == OUTCOME_ADAPTIVE_ACTION_RACING_HORIZON_HIERARCHICAL_POLICY_VERSION
1028
+ and (
1029
+ self.trace_alternative_count <= 0
1030
+ or self.positive_redundancy_strength != 0.0
1031
+ or self.conditional_saturation_strength != 0.0
1032
+ or self.conditional_synergy_strength != 0.0
1033
+ or self.causal_prior_strength != 0.0
1034
+ or self.randomized_audit_slots != 1
1035
+ or self.audit_exploration_probability != 0.0
1036
+ or self.stratified_audit_coverage_family_ids
1037
+ or self.stratified_audit_stratum_family_ids
1038
+ or self.minimum_post_audit_optimization_slots <= 0
1039
+ or self.terminal_hierarchical_slots <= 0
1040
+ or self.native_rank_strength <= 0.0
1041
+ )
1042
+ ):
1043
+ raise ValueError(
1044
+ "policy version 7 requires robust hierarchical terminal "
1045
+ "allocation, at least one post-audit optimization slot, "
1046
+ "positive native-rank strength, one horizon-gated audit, "
1047
+ "and auditable alternatives"
1048
+ )
1049
+ definition = {
1050
+ "schema_version": 1,
1051
+ "policy_id": self.policy_id,
1052
+ "policy_version": self.policy_version,
1053
+ "diagnostic_slots": self.diagnostic_slots,
1054
+ "randomized_audit_slots": self.randomized_audit_slots,
1055
+ "reference_gain_scale_hex": (
1056
+ self.reference_gain_scale.hex()
1057
+ ),
1058
+ "reference_gain_evidence_sha256": (
1059
+ self.reference_gain_evidence_sha256
1060
+ ),
1061
+ "prior_strength_hex": self.prior_strength.hex(),
1062
+ "ucb_strength_hex": self.ucb_strength.hex(),
1063
+ "counterfactual_strength_hex": (
1064
+ self.counterfactual_strength.hex()
1065
+ ),
1066
+ "diversity_strength_hex": (
1067
+ self.diversity_strength.hex()
1068
+ ),
1069
+ "exploration_pool_size": self.exploration_pool_size,
1070
+ "random_seed": self.random_seed,
1071
+ "diagnostic_design": (
1072
+ "authenticated_fixed_constraints_then_one_consensus_"
1073
+ "lane_head_then_authority_disagreement_maximin"
1074
+ ),
1075
+ "continuation": (
1076
+ "sequential_coalition_efficiency_scaled_"
1077
+ "contextual_ucb_plus_randomized_audit"
1078
+ ),
1079
+ "unobserved_outcomes_accepted": False,
1080
+ "workload_objective_model_provider_prompt_branches": False,
1081
+ }
1082
+ if (
1083
+ self.policy_version
1084
+ == OUTCOME_ADAPTIVE_ACTION_RACING_SET_AWARE_POLICY_VERSION
1085
+ ):
1086
+ definition.update(
1087
+ {
1088
+ "positive_redundancy_strength_hex": (
1089
+ self.positive_redundancy_strength.hex()
1090
+ ),
1091
+ "trace_alternative_count": (
1092
+ self.trace_alternative_count
1093
+ ),
1094
+ "continuation": (
1095
+ "sequential_coalition_efficiency_scaled_contextual_"
1096
+ "ucb_minus_positive_consequence_redundancy_plus_"
1097
+ "randomized_audit"
1098
+ ),
1099
+ "set_value_proxy": (
1100
+ "outcome_weighted_portable_action_similarity"
1101
+ ),
1102
+ }
1103
+ )
1104
+ if (
1105
+ self.policy_version
1106
+ == OUTCOME_ADAPTIVE_ACTION_RACING_CAUSAL_SET_POLICY_VERSION
1107
+ ):
1108
+ definition.update(
1109
+ {
1110
+ "conditional_saturation_strength_hex": (
1111
+ self.conditional_saturation_strength.hex()
1112
+ ),
1113
+ "conditional_synergy_strength_hex": (
1114
+ self.conditional_synergy_strength.hex()
1115
+ ),
1116
+ "causal_prior_strength_hex": (
1117
+ self.causal_prior_strength.hex()
1118
+ ),
1119
+ "randomized_audit_after_directed_steps": (
1120
+ self.randomized_audit_after_directed_steps
1121
+ ),
1122
+ "trace_alternative_count": (
1123
+ self.trace_alternative_count
1124
+ ),
1125
+ "continuation": (
1126
+ "conditional_opportunity_saturation_ucb_with_"
1127
+ "midwave_randomized_audit"
1128
+ ),
1129
+ "set_value_evidence": (
1130
+ "real_fixed_and_prior_conditioned_archive_lift"
1131
+ ),
1132
+ "proxy_positive_similarity_penalty": False,
1133
+ }
1134
+ )
1135
+ if (
1136
+ self.policy_version
1137
+ == OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION
1138
+ ):
1139
+ definition.update(
1140
+ {
1141
+ "conditional_saturation_strength_hex": (
1142
+ self.conditional_saturation_strength.hex()
1143
+ ),
1144
+ "conditional_synergy_strength_hex": (
1145
+ self.conditional_synergy_strength.hex()
1146
+ ),
1147
+ "causal_prior_strength_hex": (
1148
+ self.causal_prior_strength.hex()
1149
+ ),
1150
+ "randomized_audit_after_directed_steps": (
1151
+ self.randomized_audit_after_directed_steps
1152
+ ),
1153
+ "audit_exploration_probability_hex": (
1154
+ self.audit_exploration_probability.hex()
1155
+ ),
1156
+ "trace_alternative_count": (
1157
+ self.trace_alternative_count
1158
+ ),
1159
+ "diagnostic_and_directed_tie_breaks": (
1160
+ "canonical_action_hash_seed_invariant"
1161
+ ),
1162
+ "continuation": (
1163
+ "conditional_opportunity_saturation_ucb_with_"
1164
+ "epsilon_greedy_risk_controlled_audit"
1165
+ ),
1166
+ "audit_anchor": (
1167
+ "highest_conditional_ucb_action"
1168
+ ),
1169
+ "audit_exploration_pool": (
1170
+ "anchor_plus_portable_diversity_ranked_actions"
1171
+ ),
1172
+ "audit_propensity": (
1173
+ "anchor=one_minus_epsilon_plus_epsilon_over_pool;"
1174
+ "other=epsilon_over_pool"
1175
+ ),
1176
+ "set_value_evidence": (
1177
+ "real_fixed_and_prior_conditioned_archive_lift"
1178
+ ),
1179
+ "proxy_positive_similarity_penalty": False,
1180
+ }
1181
+ )
1182
+ if (
1183
+ self.policy_version
1184
+ == OUTCOME_ADAPTIVE_ACTION_RACING_STRATIFIED_AUDIT_POLICY_VERSION
1185
+ ):
1186
+ definition.update(
1187
+ {
1188
+ "audit_exploration_probability_hex": (
1189
+ self.audit_exploration_probability.hex()
1190
+ ),
1191
+ "trace_alternative_count": (
1192
+ self.trace_alternative_count
1193
+ ),
1194
+ "stratified_audit_coverage_family_ids": list(
1195
+ self.stratified_audit_coverage_family_ids
1196
+ ),
1197
+ "stratified_audit_stratum_family_ids": list(
1198
+ self.stratified_audit_stratum_family_ids
1199
+ ),
1200
+ "continuation": (
1201
+ "set_aware_ucb_with_legacy_audit_anchor_and_"
1202
+ "risk_controlled_factor_stratified_exploration"
1203
+ ),
1204
+ "audit_anchor": (
1205
+ "frozen_version3_diversity_rank_counterfactual_"
1206
+ "seeded_choice"
1207
+ ),
1208
+ "audit_exploration_support": (
1209
+ "maximally_uncovered_configured_factor_cells"
1210
+ ),
1211
+ "audit_exploration_propensity": (
1212
+ "uniform-nonempty-factor-stratum-then-uniform-action"
1213
+ ),
1214
+ "audit_total_propensity": (
1215
+ "legacy-anchor=one-minus-epsilon-plus-exploration-"
1216
+ "mass-if-supported;other=exploration-mass"
1217
+ ),
1218
+ "candidate_factor_cells_outcome_blind": True,
1219
+ "unobserved_outcomes_accepted": False,
1220
+ }
1221
+ )
1222
+ if (
1223
+ self.policy_version
1224
+ == OUTCOME_ADAPTIVE_ACTION_RACING_HORIZON_HIERARCHICAL_POLICY_VERSION
1225
+ ):
1226
+ definition.update(
1227
+ {
1228
+ "trace_alternative_count": (
1229
+ self.trace_alternative_count
1230
+ ),
1231
+ "randomized_audit_after_directed_steps": (
1232
+ self.randomized_audit_after_directed_steps
1233
+ ),
1234
+ "minimum_post_audit_optimization_slots": (
1235
+ self.minimum_post_audit_optimization_slots
1236
+ ),
1237
+ "terminal_hierarchical_slots": (
1238
+ self.terminal_hierarchical_slots
1239
+ ),
1240
+ "native_rank_strength_hex": (
1241
+ self.native_rank_strength.hex()
1242
+ ),
1243
+ "engine_return": (
1244
+ "bayesian_mean_of_reference_scale_capped_"
1245
+ "marginal_archive_gain"
1246
+ ),
1247
+ "engine_then_action_allocation": True,
1248
+ "within_engine_terminal_index": (
1249
+ "contextual_posterior_gain_plus_calibratable_"
1250
+ "native_rank_prior"
1251
+ ),
1252
+ "continuation": (
1253
+ "contextual_ucb_before_terminal_horizon_then_"
1254
+ "robust_engine_exposure_and_within_engine_"
1255
+ "exploitation"
1256
+ ),
1257
+ "audit_schedule": (
1258
+ "configured_directed_step_only_when_at_least_"
1259
+ "minimum_post_audit_optimization_slots_remain"
1260
+ ),
1261
+ "terminal_information_only_authoritative_purchase": False,
1262
+ "workload_model_provider_prompt_branches": False,
1263
+ }
1264
+ )
1265
+ object.__setattr__(
1266
+ self,
1267
+ "definition_sha256",
1268
+ _hash(_POLICY_DEFINITION_DOMAIN, definition),
1269
+ )
1270
+
1271
+ @staticmethod
1272
+ def _validate_market(
1273
+ actions: tuple[AdaptiveActionDescriptor, ...],
1274
+ ) -> dict[str, AdaptiveActionDescriptor]:
1275
+ if type(actions) is not tuple or not actions:
1276
+ raise ValueError("actions must be a non-empty exact tuple")
1277
+ by_action: dict[str, AdaptiveActionDescriptor] = {}
1278
+ lane_counts: dict[str, int] = {}
1279
+ for value in actions:
1280
+ if type(value) is not AdaptiveActionDescriptor:
1281
+ raise TypeError("actions must contain exact descriptors")
1282
+ value.__post_init__()
1283
+ if value.action_sha256 in by_action:
1284
+ raise ValueError("action identities repeat")
1285
+ by_action[value.action_sha256] = value
1286
+ lane_counts[value.lane_id] = lane_counts.get(value.lane_id, 0) + 1
1287
+ if any(
1288
+ value.lane_size != lane_counts[value.lane_id]
1289
+ for value in actions
1290
+ ):
1291
+ raise ValueError("declared lane sizes differ from the market")
1292
+ if len({value.phenotype_sha256 for value in actions}) != len(actions):
1293
+ raise ValueError(
1294
+ "adaptive market must contain unique phenotype identities"
1295
+ )
1296
+ return by_action
1297
+
1298
+ @staticmethod
1299
+ def _minimum_distance(
1300
+ action: AdaptiveActionDescriptor,
1301
+ selected: tuple[AdaptiveActionDescriptor, ...],
1302
+ ) -> float:
1303
+ if not selected:
1304
+ return 1.0
1305
+ return min(_action_distance(action, value) for value in selected)
1306
+
1307
+ def design_diagnostic_pilot(
1308
+ self,
1309
+ *,
1310
+ residual_request_sha256: str,
1311
+ actions: tuple[AdaptiveActionDescriptor, ...],
1312
+ evaluation_slots: int,
1313
+ required_action_sha256s: tuple[str, ...] = (),
1314
+ ) -> AdaptiveActionRacingDecision:
1315
+ """Choose a constrained lane-head pilot, then fill it by maximin."""
1316
+
1317
+ self.__post_init__()
1318
+ require_sha256(
1319
+ residual_request_sha256,
1320
+ "residual_request_sha256",
1321
+ )
1322
+ by_action = self._validate_market(actions)
1323
+ if (
1324
+ type(evaluation_slots) is not int
1325
+ or not 2 <= evaluation_slots <= len(actions)
1326
+ ):
1327
+ raise ValueError("evaluation_slots must fit the action market")
1328
+ pilot_width = min(
1329
+ self.diagnostic_slots,
1330
+ evaluation_slots - self.randomized_audit_slots,
1331
+ )
1332
+ if pilot_width <= 0:
1333
+ raise ValueError("diagnostic design leaves no pilot")
1334
+ if (
1335
+ type(required_action_sha256s) is not tuple
1336
+ or required_action_sha256s
1337
+ != tuple(sorted(set(required_action_sha256s)))
1338
+ ):
1339
+ raise ValueError(
1340
+ "required_action_sha256s must be an exact canonical tuple"
1341
+ )
1342
+ if not set(required_action_sha256s).issubset(by_action):
1343
+ raise ValueError(
1344
+ "a required diagnostic action is outside the sealed market"
1345
+ )
1346
+ if len(required_action_sha256s) > pilot_width:
1347
+ raise ValueError(
1348
+ "fixed allocation constraints exceed diagnostic capacity"
1349
+ )
1350
+
1351
+ by_lane: dict[str, list[AdaptiveActionDescriptor]] = {}
1352
+ for action in actions:
1353
+ by_lane.setdefault(action.lane_id, []).append(action)
1354
+ lane_heads = tuple(
1355
+ sorted(
1356
+ (
1357
+ min(
1358
+ values,
1359
+ key=lambda value: (
1360
+ -value.prior_score,
1361
+ value.native_rank,
1362
+ value.action_sha256,
1363
+ ),
1364
+ )
1365
+ for values in by_lane.values()
1366
+ ),
1367
+ key=lambda value: (
1368
+ -value.prior_score,
1369
+ value.native_rank,
1370
+ value.lane_id,
1371
+ value.action_sha256,
1372
+ ),
1373
+ )
1374
+ )
1375
+ selected: list[AdaptiveActionDescriptor] = [
1376
+ by_action[value] for value in required_action_sha256s
1377
+ ]
1378
+ trace: list[dict[str, object]] = [
1379
+ {
1380
+ "ordinal": ordinal,
1381
+ "action_sha256": value.action_sha256,
1382
+ "reason": "fixed_allocation_constraint",
1383
+ "lane_id": value.lane_id,
1384
+ "native_rank": value.native_rank,
1385
+ }
1386
+ for ordinal, value in enumerate(selected, start=1)
1387
+ ]
1388
+ for value in lane_heads:
1389
+ if len(selected) >= pilot_width:
1390
+ break
1391
+ if value.action_sha256 in {
1392
+ item.action_sha256 for item in selected
1393
+ }:
1394
+ continue
1395
+ selected.append(value)
1396
+ trace.append(
1397
+ {
1398
+ "ordinal": len(selected),
1399
+ "action_sha256": value.action_sha256,
1400
+ "reason": "lane_head",
1401
+ "lane_id": value.lane_id,
1402
+ "native_rank": value.native_rank,
1403
+ }
1404
+ )
1405
+ while len(selected) < pilot_width:
1406
+ candidates = tuple(
1407
+ value
1408
+ for value in actions
1409
+ if value.action_sha256
1410
+ not in {item.action_sha256 for item in selected}
1411
+ )
1412
+ if not candidates:
1413
+ raise ValueError("action market cannot fill diagnostic pilot")
1414
+ scored = tuple(
1415
+ (
1416
+ abs(value.rank_quality - value.prior_score),
1417
+ self._minimum_distance(value, tuple(selected)),
1418
+ value.prior_score,
1419
+ (
1420
+ 0.0
1421
+ if self.policy_version
1422
+ == OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION
1423
+ else _stable_unit_interval(
1424
+ self.random_seed,
1425
+ residual_request_sha256,
1426
+ "diagnostic",
1427
+ len(selected),
1428
+ value.action_sha256,
1429
+ )
1430
+ ),
1431
+ value,
1432
+ )
1433
+ for value in candidates
1434
+ )
1435
+ chosen = max(
1436
+ scored,
1437
+ key=lambda row: (
1438
+ row[0],
1439
+ row[1],
1440
+ row[2],
1441
+ row[3],
1442
+ row[4].action_sha256,
1443
+ ),
1444
+ )[4]
1445
+ selected.append(chosen)
1446
+ trace.append(
1447
+ {
1448
+ "ordinal": len(selected),
1449
+ "action_sha256": chosen.action_sha256,
1450
+ "reason": "authority_disagreement_maximin",
1451
+ "lane_id": chosen.lane_id,
1452
+ "native_rank": chosen.native_rank,
1453
+ "authority_disagreement_hex": abs(
1454
+ chosen.rank_quality - chosen.prior_score
1455
+ ).hex(),
1456
+ "minimum_distance_hex": self._minimum_distance(
1457
+ chosen,
1458
+ tuple(selected[:-1]),
1459
+ ).hex(),
1460
+ }
1461
+ )
1462
+ return AdaptiveActionRacingDecision(
1463
+ policy_id=self.policy_id,
1464
+ policy_version=self.policy_version,
1465
+ policy_definition_sha256=self.definition_sha256,
1466
+ residual_request_sha256=residual_request_sha256,
1467
+ wave=AdaptiveActionWave.DIAGNOSTIC,
1468
+ selected_action_sha256s=tuple(
1469
+ sorted(value.action_sha256 for value in selected)
1470
+ ),
1471
+ prior_selected_action_sha256s=(),
1472
+ observed_outcome_sha256s=(),
1473
+ observed_set_outcome_sha256s=(),
1474
+ selection_propensity=1.0,
1475
+ evidence=freeze_json(
1476
+ {
1477
+ "selection_trace": trace,
1478
+ "pilot_width": pilot_width,
1479
+ "lane_count": len(by_lane),
1480
+ "lane_head_count": sum(
1481
+ value["reason"] == "lane_head"
1482
+ for value in trace
1483
+ ),
1484
+ "fixed_constraint_count": len(
1485
+ required_action_sha256s
1486
+ ),
1487
+ "required_action_sha256s": list(
1488
+ required_action_sha256s
1489
+ ),
1490
+ "candidate_outcomes_observed": False,
1491
+ "all_actions_materialized_before_decision": True,
1492
+ }
1493
+ ),
1494
+ )
1495
+
1496
+ @staticmethod
1497
+ def _outcome_map(
1498
+ *,
1499
+ by_action: dict[str, AdaptiveActionDescriptor],
1500
+ selected_action_sha256s: tuple[str, ...],
1501
+ outcomes: tuple[AdaptiveActionOutcome, ...],
1502
+ ) -> dict[str, AdaptiveActionOutcome]:
1503
+ if (
1504
+ type(selected_action_sha256s) is not tuple
1505
+ or selected_action_sha256s
1506
+ != tuple(sorted(set(selected_action_sha256s)))
1507
+ ):
1508
+ raise ValueError(
1509
+ "selected_action_sha256s must be an exact canonical tuple"
1510
+ )
1511
+ if not set(selected_action_sha256s).issubset(by_action):
1512
+ raise ValueError("selected action is outside the sealed market")
1513
+ if (
1514
+ type(outcomes) is not tuple
1515
+ or any(type(value) is not AdaptiveActionOutcome for value in outcomes)
1516
+ ):
1517
+ raise TypeError("outcomes must contain exact values")
1518
+ result: dict[str, AdaptiveActionOutcome] = {}
1519
+ for value in outcomes:
1520
+ value.__post_init__()
1521
+ if value.action_sha256 in result:
1522
+ raise ValueError("observed outcomes repeat an action")
1523
+ result[value.action_sha256] = value
1524
+ if set(result) != set(selected_action_sha256s):
1525
+ raise ValueError(
1526
+ "observations must exactly cover all previously selected actions"
1527
+ )
1528
+ return result
1529
+
1530
+ @staticmethod
1531
+ def _validate_set_outcomes(
1532
+ *,
1533
+ selected_action_sha256s: tuple[str, ...],
1534
+ diagnostic_action_sha256s: tuple[str, ...],
1535
+ outcome_by_action: dict[str, AdaptiveActionOutcome],
1536
+ set_outcomes: tuple[AdaptiveActionSetOutcome, ...],
1537
+ ) -> tuple[
1538
+ AdaptiveActionSetOutcome | None,
1539
+ dict[str, AdaptiveActionSetOutcome],
1540
+ ]:
1541
+ if type(set_outcomes) is not tuple:
1542
+ raise TypeError("set_outcomes must be an exact tuple")
1543
+ if not set_outcomes:
1544
+ return None, {}
1545
+ prior_bindings: list[tuple[str, str]] = []
1546
+ prior_augmented_gain = 0.0
1547
+ singleton_by_action: dict[str, AdaptiveActionSetOutcome] = {}
1548
+ for ordinal, observation in enumerate(set_outcomes):
1549
+ if type(observation) is not AdaptiveActionSetOutcome:
1550
+ raise TypeError("set_outcomes must contain exact values")
1551
+ observation.__post_init__()
1552
+ if observation.prior_action_evaluation_bindings != tuple(
1553
+ sorted(prior_bindings)
1554
+ ):
1555
+ raise ValueError(
1556
+ "set outcomes skip their causal evaluation prefix"
1557
+ )
1558
+ if not _metric_close(
1559
+ observation.prior_selected_set_gain,
1560
+ prior_augmented_gain,
1561
+ ):
1562
+ raise ValueError(
1563
+ "set outcomes skip their causal utility prefix"
1564
+ )
1565
+ current = observation.current_action_evaluation_bindings
1566
+ current_actions = {value[0] for value in current}
1567
+ if ordinal == 0:
1568
+ if current_actions != set(diagnostic_action_sha256s):
1569
+ raise ValueError(
1570
+ "first set outcome must cover the diagnostic wave"
1571
+ )
1572
+ elif len(current) != 1:
1573
+ raise ValueError(
1574
+ "continuation set outcomes must bind one action"
1575
+ )
1576
+ for action_sha256, evaluation_sha256 in current:
1577
+ outcome = outcome_by_action.get(action_sha256)
1578
+ if (
1579
+ outcome is None
1580
+ or outcome.evaluation_sha256 != evaluation_sha256
1581
+ ):
1582
+ raise ValueError(
1583
+ "set outcome does not join an observed outcome"
1584
+ )
1585
+ if len(current) == 1:
1586
+ singleton_by_action[current[0][0]] = observation
1587
+ prior_bindings.extend(current)
1588
+ prior_augmented_gain = (
1589
+ observation.augmented_selected_set_gain
1590
+ )
1591
+ if {value[0] for value in prior_bindings} != set(
1592
+ selected_action_sha256s
1593
+ ):
1594
+ raise ValueError(
1595
+ "set outcomes must exactly cover selected actions"
1596
+ )
1597
+ return set_outcomes[0], singleton_by_action
1598
+
1599
+ def _causal_set_components(
1600
+ self,
1601
+ *,
1602
+ candidate: AdaptiveActionDescriptor,
1603
+ selected_by_action: dict[str, AdaptiveActionDescriptor],
1604
+ diagnostic: AdaptiveActionSetOutcome,
1605
+ singleton_by_action: dict[str, AdaptiveActionSetOutcome],
1606
+ base: dict[str, float],
1607
+ ) -> dict[str, float]:
1608
+ if not _metric_close(
1609
+ diagnostic.current_wave_fixed_set_gain,
1610
+ base["diagnostic_joint_gain"],
1611
+ ):
1612
+ raise ValueError(
1613
+ "diagnostic set outcome differs from joint gain"
1614
+ )
1615
+ diagnostic_sum = base["diagnostic_individual_gain_sum"]
1616
+ diagnostic_saturation = (
1617
+ 0.0
1618
+ if diagnostic_sum <= 0.0
1619
+ else max(
1620
+ 0.0,
1621
+ 1.0 - base["diagnostic_coalition_efficiency"],
1622
+ )
1623
+ )
1624
+ saturation_weighted = (
1625
+ self.causal_prior_strength * diagnostic_saturation
1626
+ )
1627
+ saturation_weight = self.causal_prior_strength
1628
+ synergy_weighted = 0.0
1629
+ synergy_weight = self.causal_prior_strength
1630
+ causal_evidence_count = 0
1631
+ for action_sha256, observation in singleton_by_action.items():
1632
+ action = selected_by_action[action_sha256]
1633
+ similarity = max(
1634
+ 0.0,
1635
+ 1.0 - _action_distance(candidate, action),
1636
+ )
1637
+ weight = 0.10 + 0.90 * similarity
1638
+ fixed_gain = observation.current_wave_fixed_set_gain
1639
+ if fixed_gain > 0.0:
1640
+ saturation_weighted += (
1641
+ weight * observation.saturation_fraction
1642
+ )
1643
+ saturation_weight += weight
1644
+ causal_evidence_count += 1
1645
+ if (
1646
+ fixed_gain > 0.0
1647
+ or observation.prior_conditioned_synergy > 0.0
1648
+ ):
1649
+ synergy_ratio = min(
1650
+ observation.prior_conditioned_synergy
1651
+ / max(fixed_gain, self.reference_gain_scale),
1652
+ 2.0,
1653
+ )
1654
+ synergy_weighted += weight * synergy_ratio
1655
+ synergy_weight += weight
1656
+ posterior_saturation = (
1657
+ saturation_weighted / saturation_weight
1658
+ )
1659
+ posterior_synergy = synergy_weighted / synergy_weight
1660
+ causal_uncertainty = 1.0 / math.sqrt(saturation_weight)
1661
+ conditional_multiplier = max(
1662
+ 0.0,
1663
+ 1.0
1664
+ - self.conditional_saturation_strength
1665
+ * posterior_saturation
1666
+ + self.conditional_synergy_strength
1667
+ * posterior_synergy,
1668
+ )
1669
+ predicted_conditional_gain = (
1670
+ base["posterior_gain"] * conditional_multiplier
1671
+ )
1672
+ # Saturation is evidence about expected conditional value, not a
1673
+ # license to equate structural distance with archive complementarity.
1674
+ # The existing UCB already prices uncertainty and diversity once.
1675
+ # Keeping both bonuses at zero avoids the failed V52 proxy penalty's
1676
+ # double counting while retaining them as explicit trace fields.
1677
+ complement_bonus = 0.0
1678
+ causal_uncertainty_bonus = 0.0
1679
+ conditional_ucb_index = (
1680
+ base["ucb_index"]
1681
+ - base["posterior_gain"]
1682
+ + predicted_conditional_gain
1683
+ + complement_bonus
1684
+ + causal_uncertainty_bonus
1685
+ )
1686
+ return {
1687
+ **base,
1688
+ "diagnostic_saturation": diagnostic_saturation,
1689
+ "posterior_saturation": posterior_saturation,
1690
+ "posterior_synergy": posterior_synergy,
1691
+ "causal_evidence_count": float(causal_evidence_count),
1692
+ "causal_effective_weight": saturation_weight,
1693
+ "causal_uncertainty": causal_uncertainty,
1694
+ "conditional_multiplier": conditional_multiplier,
1695
+ "predicted_conditional_gain": predicted_conditional_gain,
1696
+ "complement_bonus": complement_bonus,
1697
+ "causal_uncertainty_bonus": causal_uncertainty_bonus,
1698
+ "conditional_ucb_index": conditional_ucb_index,
1699
+ "ucb_index": conditional_ucb_index,
1700
+ }
1701
+
1702
+ def _ucb_components(
1703
+ self,
1704
+ *,
1705
+ candidate: AdaptiveActionDescriptor,
1706
+ selected: tuple[AdaptiveActionDescriptor, ...],
1707
+ outcome_by_action: dict[str, AdaptiveActionOutcome],
1708
+ diagnostic_action_sha256s: tuple[str, ...],
1709
+ diagnostic_joint_gain: float,
1710
+ ) -> dict[str, float]:
1711
+ weighted_gain = 0.0
1712
+ weighted_positive = 0.0
1713
+ total_weight = 0.0
1714
+ same_lane_ranks: list[float] = []
1715
+ for action in selected:
1716
+ outcome = outcome_by_action[action.action_sha256]
1717
+ rank_distance = abs(
1718
+ candidate.rank_quality - action.rank_quality
1719
+ )
1720
+ weight = 0.10
1721
+ if candidate.lane_id == action.lane_id:
1722
+ weight += 0.55 * math.exp(-rank_distance / 0.35)
1723
+ same_lane_ranks.append(action.rank_quality)
1724
+ if candidate.operator_id == action.operator_id:
1725
+ weight += 0.15
1726
+ if (
1727
+ candidate.parent_generated_in_current_run
1728
+ == action.parent_generated_in_current_run
1729
+ ):
1730
+ weight += 0.10
1731
+ weight += 0.10 * (
1732
+ 1.0
1733
+ - _semantic_distance(
1734
+ candidate.semantic_cell_ids,
1735
+ action.semantic_cell_ids,
1736
+ )
1737
+ )
1738
+ weighted_gain += weight * outcome.marginal_archive_gain
1739
+ weighted_positive += weight * float(outcome.positive)
1740
+ total_weight += weight
1741
+
1742
+ prior_positive = 0.25 + 0.50 * candidate.prior_score
1743
+ prior_gain = self.reference_gain_scale * (
1744
+ 0.25 + 0.75 * candidate.prior_score
1745
+ )
1746
+ active_gain_scale = max(
1747
+ self.reference_gain_scale,
1748
+ max(
1749
+ (
1750
+ value.marginal_archive_gain
1751
+ for value in outcome_by_action.values()
1752
+ ),
1753
+ default=0.0,
1754
+ ),
1755
+ )
1756
+ positive_redundancy = 0.0
1757
+ if (
1758
+ self.policy_version
1759
+ == OUTCOME_ADAPTIVE_ACTION_RACING_SET_AWARE_POLICY_VERSION
1760
+ ):
1761
+ positive_redundancy = max(
1762
+ (
1763
+ max(0.0, 1.0 - _action_distance(candidate, action))
1764
+ * min(
1765
+ 1.0,
1766
+ outcome_by_action[
1767
+ action.action_sha256
1768
+ ].marginal_archive_gain
1769
+ / active_gain_scale,
1770
+ )
1771
+ for action in selected
1772
+ if outcome_by_action[
1773
+ action.action_sha256
1774
+ ].positive
1775
+ ),
1776
+ default=0.0,
1777
+ )
1778
+ redundancy_penalty = (
1779
+ self.positive_redundancy_strength
1780
+ * active_gain_scale
1781
+ * positive_redundancy
1782
+ )
1783
+ diagnostic_individual_gain_sum = math.fsum(
1784
+ outcome_by_action[value].marginal_archive_gain
1785
+ for value in diagnostic_action_sha256s
1786
+ )
1787
+ diagnostic_coalition_efficiency = (
1788
+ 0.0
1789
+ if diagnostic_individual_gain_sum <= 0.0
1790
+ else min(
1791
+ 1.0,
1792
+ diagnostic_joint_gain / diagnostic_individual_gain_sum,
1793
+ )
1794
+ )
1795
+ exploration_gain_scale = (
1796
+ self.reference_gain_scale
1797
+ + (active_gain_scale - self.reference_gain_scale)
1798
+ * (1.0 - diagnostic_coalition_efficiency)
1799
+ )
1800
+ denominator = self.prior_strength + total_weight
1801
+ posterior_positive = (
1802
+ self.prior_strength * prior_positive + weighted_positive
1803
+ ) / denominator
1804
+ posterior_gain = (
1805
+ self.prior_strength * prior_gain + weighted_gain
1806
+ ) / denominator
1807
+ uncertainty = exploration_gain_scale / math.sqrt(denominator)
1808
+ if same_lane_ranks:
1809
+ rank_counterfactual = min(
1810
+ abs(candidate.rank_quality - value)
1811
+ for value in same_lane_ranks
1812
+ )
1813
+ else:
1814
+ rank_counterfactual = 1.0
1815
+ diversity = self._minimum_distance(candidate, selected)
1816
+ ucb_index = (
1817
+ posterior_gain
1818
+ + self.ucb_strength * uncertainty
1819
+ + self.counterfactual_strength
1820
+ * exploration_gain_scale
1821
+ * rank_counterfactual
1822
+ + self.diversity_strength
1823
+ * exploration_gain_scale
1824
+ * diversity
1825
+ - redundancy_penalty
1826
+ )
1827
+ result = {
1828
+ "posterior_positive": posterior_positive,
1829
+ "posterior_gain": posterior_gain,
1830
+ "uncertainty": uncertainty,
1831
+ "rank_counterfactual": rank_counterfactual,
1832
+ "diversity": diversity,
1833
+ "ucb_index": ucb_index,
1834
+ "effective_observation_weight": total_weight,
1835
+ "active_gain_scale": active_gain_scale,
1836
+ "diagnostic_joint_gain": diagnostic_joint_gain,
1837
+ "diagnostic_individual_gain_sum": (
1838
+ diagnostic_individual_gain_sum
1839
+ ),
1840
+ "diagnostic_coalition_efficiency": (
1841
+ diagnostic_coalition_efficiency
1842
+ ),
1843
+ "exploration_gain_scale": exploration_gain_scale,
1844
+ }
1845
+ if (
1846
+ self.policy_version
1847
+ == OUTCOME_ADAPTIVE_ACTION_RACING_SET_AWARE_POLICY_VERSION
1848
+ ):
1849
+ result.update(
1850
+ {
1851
+ "positive_redundancy": positive_redundancy,
1852
+ "redundancy_penalty": redundancy_penalty,
1853
+ }
1854
+ )
1855
+ return result
1856
+
1857
+ def _terminal_hierarchical_ranking(
1858
+ self,
1859
+ *,
1860
+ actions: tuple[AdaptiveActionDescriptor, ...],
1861
+ remaining: tuple[AdaptiveActionDescriptor, ...],
1862
+ selected: tuple[AdaptiveActionDescriptor, ...],
1863
+ outcome_by_action: dict[str, AdaptiveActionOutcome],
1864
+ components: dict[str, dict[str, float]],
1865
+ seats_left: int,
1866
+ ) -> tuple[
1867
+ tuple[AdaptiveActionDescriptor, ...],
1868
+ dict[str, dict[str, float]],
1869
+ tuple[str, ...],
1870
+ ]:
1871
+ """Rank engines first, then actions, at a short residual horizon.
1872
+
1873
+ Engine return is capped at the authenticated reference-gain scale so
1874
+ one unusually large action cannot monopolize a sparse engine posterior.
1875
+ This is an allocation statistic only; authoritative archive utility
1876
+ remains uncapped. Within the chosen engine, native rank is retained as
1877
+ a separately weighted cold-start prior rather than mixed into another
1878
+ engine's native units.
1879
+ """
1880
+
1881
+ if (
1882
+ self.policy_version
1883
+ != OUTCOME_ADAPTIVE_ACTION_RACING_HORIZON_HIERARCHICAL_POLICY_VERSION
1884
+ ):
1885
+ raise ValueError(
1886
+ "terminal hierarchical ranking requires policy version 7"
1887
+ )
1888
+ if not remaining or seats_left <= 0:
1889
+ raise ValueError(
1890
+ "terminal hierarchical ranking requires remaining capacity"
1891
+ )
1892
+ market_by_lane: dict[str, list[AdaptiveActionDescriptor]] = {}
1893
+ remaining_by_lane: dict[str, list[AdaptiveActionDescriptor]] = {}
1894
+ selected_by_lane: dict[str, list[AdaptiveActionDescriptor]] = {}
1895
+ for action in actions:
1896
+ market_by_lane.setdefault(action.lane_id, []).append(action)
1897
+ for action in remaining:
1898
+ remaining_by_lane.setdefault(action.lane_id, []).append(action)
1899
+ for action in selected:
1900
+ selected_by_lane.setdefault(action.lane_id, []).append(action)
1901
+
1902
+ future_optimization_slots = max(0, seats_left - 1)
1903
+ horizon_exploration_fraction = min(
1904
+ 1.0,
1905
+ future_optimization_slots
1906
+ / float(max(1, self.terminal_hierarchical_slots)),
1907
+ )
1908
+ engine: dict[str, dict[str, float]] = {}
1909
+ for lane_id in sorted(remaining_by_lane):
1910
+ lane_market = market_by_lane[lane_id]
1911
+ lane_selected = selected_by_lane.get(lane_id, [])
1912
+ mean_prior_score = math.fsum(
1913
+ value.prior_score for value in lane_market
1914
+ ) / len(lane_market)
1915
+ prior_positive = 0.25 + 0.50 * mean_prior_score
1916
+ prior_capped_gain = self.reference_gain_scale * (
1917
+ 0.25 + 0.75 * mean_prior_score
1918
+ )
1919
+ observed = tuple(
1920
+ outcome_by_action[value.action_sha256]
1921
+ for value in lane_selected
1922
+ )
1923
+ denominator = self.prior_strength + len(observed)
1924
+ posterior_positive = (
1925
+ self.prior_strength * prior_positive
1926
+ + math.fsum(float(value.positive) for value in observed)
1927
+ ) / denominator
1928
+ posterior_capped_gain = (
1929
+ self.prior_strength * prior_capped_gain
1930
+ + math.fsum(
1931
+ min(
1932
+ self.reference_gain_scale,
1933
+ value.marginal_archive_gain,
1934
+ )
1935
+ for value in observed
1936
+ )
1937
+ ) / denominator
1938
+ uncertainty = self.reference_gain_scale / math.sqrt(denominator)
1939
+ selection_index = (
1940
+ posterior_capped_gain
1941
+ + horizon_exploration_fraction
1942
+ * self.ucb_strength
1943
+ * uncertainty
1944
+ )
1945
+ engine[lane_id] = {
1946
+ "engine_mean_prior_score": mean_prior_score,
1947
+ "engine_prior_positive": prior_positive,
1948
+ "engine_prior_capped_gain": prior_capped_gain,
1949
+ "engine_observed_count": float(len(observed)),
1950
+ "engine_positive_count": float(
1951
+ sum(value.positive for value in observed)
1952
+ ),
1953
+ "engine_posterior_positive": posterior_positive,
1954
+ "engine_posterior_capped_gain": posterior_capped_gain,
1955
+ "engine_uncertainty": uncertainty,
1956
+ "engine_selection_index": selection_index,
1957
+ "future_optimization_slots_after_decision": float(
1958
+ future_optimization_slots
1959
+ ),
1960
+ "horizon_exploration_fraction": (
1961
+ horizon_exploration_fraction
1962
+ ),
1963
+ }
1964
+
1965
+ engine_order = tuple(
1966
+ sorted(
1967
+ engine,
1968
+ key=lambda lane_id: (
1969
+ engine[lane_id]["engine_selection_index"],
1970
+ engine[lane_id]["engine_posterior_positive"],
1971
+ engine[lane_id]["engine_mean_prior_score"],
1972
+ lane_id,
1973
+ ),
1974
+ reverse=True,
1975
+ )
1976
+ )
1977
+ enriched = {
1978
+ action_sha256: dict(value)
1979
+ for action_sha256, value in components.items()
1980
+ }
1981
+ ranked: list[AdaptiveActionDescriptor] = []
1982
+ for lane_id in engine_order:
1983
+ lane_actions = remaining_by_lane[lane_id]
1984
+ for action in lane_actions:
1985
+ row = enriched[action.action_sha256]
1986
+ native_rank_bonus = (
1987
+ self.native_rank_strength
1988
+ * self.reference_gain_scale
1989
+ * action.rank_quality
1990
+ )
1991
+ row.update(engine[lane_id])
1992
+ row["native_rank_bonus"] = native_rank_bonus
1993
+ row["within_engine_terminal_index"] = (
1994
+ row["posterior_gain"] + native_rank_bonus
1995
+ )
1996
+ ranked.extend(
1997
+ sorted(
1998
+ lane_actions,
1999
+ key=lambda value: (
2000
+ enriched[value.action_sha256][
2001
+ "within_engine_terminal_index"
2002
+ ],
2003
+ enriched[value.action_sha256][
2004
+ "posterior_positive"
2005
+ ],
2006
+ value.prior_score,
2007
+ value.action_sha256,
2008
+ ),
2009
+ reverse=True,
2010
+ )
2011
+ )
2012
+ return tuple(ranked), enriched, engine_order
2013
+
2014
+ def select_next(
2015
+ self,
2016
+ *,
2017
+ residual_request_sha256: str,
2018
+ actions: tuple[AdaptiveActionDescriptor, ...],
2019
+ evaluation_slots: int,
2020
+ diagnostic_action_sha256s: tuple[str, ...],
2021
+ diagnostic_joint_gain: float,
2022
+ selected_action_sha256s: tuple[str, ...],
2023
+ outcomes: tuple[AdaptiveActionOutcome, ...],
2024
+ set_outcomes: tuple[AdaptiveActionSetOutcome, ...] = (),
2025
+ excluded_action_sha256s: tuple[str, ...] = (),
2026
+ ) -> AdaptiveActionRacingDecision:
2027
+ """Select one next action using only outcomes of already selected actions."""
2028
+
2029
+ self.__post_init__()
2030
+ require_sha256(
2031
+ residual_request_sha256,
2032
+ "residual_request_sha256",
2033
+ )
2034
+ by_action = self._validate_market(actions)
2035
+ if (
2036
+ type(excluded_action_sha256s) is not tuple
2037
+ or excluded_action_sha256s
2038
+ != tuple(sorted(set(excluded_action_sha256s)))
2039
+ ):
2040
+ raise ValueError(
2041
+ "excluded action hashes must be unique and canonical"
2042
+ )
2043
+ for value in excluded_action_sha256s:
2044
+ require_sha256(value, "excluded_action_sha256")
2045
+ if (
2046
+ not set(excluded_action_sha256s) <= set(by_action)
2047
+ or set(excluded_action_sha256s)
2048
+ & set(selected_action_sha256s)
2049
+ ):
2050
+ raise ValueError(
2051
+ "excluded actions must be unselected market members"
2052
+ )
2053
+ if (
2054
+ type(evaluation_slots) is not int
2055
+ or not 2 <= evaluation_slots <= len(actions)
2056
+ ):
2057
+ raise ValueError("evaluation_slots must fit the action market")
2058
+ if len(selected_action_sha256s) >= evaluation_slots:
2059
+ raise ValueError("the evaluation slate is already complete")
2060
+ outcome_by_action = self._outcome_map(
2061
+ by_action=by_action,
2062
+ selected_action_sha256s=selected_action_sha256s,
2063
+ outcomes=outcomes,
2064
+ )
2065
+ if (
2066
+ type(diagnostic_action_sha256s) is not tuple
2067
+ or not diagnostic_action_sha256s
2068
+ or diagnostic_action_sha256s
2069
+ != tuple(sorted(set(diagnostic_action_sha256s)))
2070
+ or not set(diagnostic_action_sha256s).issubset(
2071
+ selected_action_sha256s
2072
+ )
2073
+ ):
2074
+ raise ValueError(
2075
+ "diagnostic actions must be a canonical selected subset"
2076
+ )
2077
+ if (
2078
+ type(diagnostic_joint_gain) is not float
2079
+ or not math.isfinite(diagnostic_joint_gain)
2080
+ or diagnostic_joint_gain < 0.0
2081
+ ):
2082
+ raise ValueError(
2083
+ "diagnostic_joint_gain must be finite and non-negative"
2084
+ )
2085
+ (
2086
+ diagnostic_set_outcome,
2087
+ singleton_set_outcomes,
2088
+ ) = self._validate_set_outcomes(
2089
+ selected_action_sha256s=selected_action_sha256s,
2090
+ diagnostic_action_sha256s=diagnostic_action_sha256s,
2091
+ outcome_by_action=outcome_by_action,
2092
+ set_outcomes=set_outcomes,
2093
+ )
2094
+ if (
2095
+ self.policy_version in _CAUSAL_SET_POLICY_VERSIONS
2096
+ and diagnostic_set_outcome is None
2097
+ ):
2098
+ raise ValueError(
2099
+ "causal policy versions require causal set outcomes"
2100
+ )
2101
+ selected = tuple(
2102
+ by_action[value] for value in selected_action_sha256s
2103
+ )
2104
+ selected_phenotypes = {
2105
+ value.phenotype_sha256 for value in selected
2106
+ }
2107
+ remaining = tuple(
2108
+ value
2109
+ for value in actions
2110
+ if value.action_sha256 not in outcome_by_action
2111
+ and value.action_sha256 not in set(excluded_action_sha256s)
2112
+ and value.phenotype_sha256 not in selected_phenotypes
2113
+ )
2114
+ if not remaining:
2115
+ raise ValueError("no unevaluated action can fill the slate")
2116
+ seats_left = evaluation_slots - len(selected)
2117
+
2118
+ components: dict[str, dict[str, float]] = {
2119
+ value.action_sha256: self._ucb_components(
2120
+ candidate=value,
2121
+ selected=selected,
2122
+ outcome_by_action=outcome_by_action,
2123
+ diagnostic_action_sha256s=(
2124
+ diagnostic_action_sha256s
2125
+ ),
2126
+ diagnostic_joint_gain=diagnostic_joint_gain,
2127
+ )
2128
+ for value in remaining
2129
+ }
2130
+ if (
2131
+ self.policy_version in _CAUSAL_SET_POLICY_VERSIONS
2132
+ ):
2133
+ if diagnostic_set_outcome is None: # pragma: no cover
2134
+ raise AssertionError("validated causal observation vanished")
2135
+ selected_by_action = {
2136
+ value.action_sha256: value for value in selected
2137
+ }
2138
+ components = {
2139
+ value.action_sha256: self._causal_set_components(
2140
+ candidate=value,
2141
+ selected_by_action=selected_by_action,
2142
+ diagnostic=diagnostic_set_outcome,
2143
+ singleton_by_action=singleton_set_outcomes,
2144
+ base=components[value.action_sha256],
2145
+ )
2146
+ for value in remaining
2147
+ }
2148
+ directed_steps_completed = (
2149
+ len(selected) - len(diagnostic_action_sha256s)
2150
+ )
2151
+ terminal_hierarchical = (
2152
+ self.policy_version
2153
+ == OUTCOME_ADAPTIVE_ACTION_RACING_HORIZON_HIERARCHICAL_POLICY_VERSION
2154
+ and seats_left <= self.terminal_hierarchical_slots
2155
+ )
2156
+ horizon_audit_due: bool | None = None
2157
+ horizon_audit_blocked_reason: str | None = None
2158
+ if (
2159
+ self.policy_version
2160
+ == OUTCOME_ADAPTIVE_ACTION_RACING_HORIZON_HIERARCHICAL_POLICY_VERSION
2161
+ ):
2162
+ horizon_audit_due = (
2163
+ directed_steps_completed
2164
+ == self.randomized_audit_after_directed_steps
2165
+ )
2166
+ post_audit_optimization_slots = max(0, seats_left - 1)
2167
+ audit = bool(
2168
+ horizon_audit_due
2169
+ and not terminal_hierarchical
2170
+ and post_audit_optimization_slots
2171
+ >= self.minimum_post_audit_optimization_slots
2172
+ )
2173
+ if horizon_audit_due and not audit:
2174
+ horizon_audit_blocked_reason = (
2175
+ "terminal_hierarchical_exploitation"
2176
+ if terminal_hierarchical
2177
+ else "insufficient_post_audit_optimization_horizon"
2178
+ )
2179
+ elif self.policy_version in _CAUSAL_SET_POLICY_VERSIONS:
2180
+ audit = (
2181
+ directed_steps_completed
2182
+ == self.randomized_audit_after_directed_steps
2183
+ )
2184
+ else:
2185
+ audit = seats_left <= self.randomized_audit_slots
2186
+ directed_ranked = tuple(
2187
+ sorted(
2188
+ remaining,
2189
+ key=lambda value: (
2190
+ components[value.action_sha256]["ucb_index"],
2191
+ components[value.action_sha256][
2192
+ "posterior_positive"
2193
+ ],
2194
+ value.prior_score,
2195
+ (
2196
+ 0.0
2197
+ if self.policy_version
2198
+ == OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION
2199
+ else _stable_unit_interval(
2200
+ self.random_seed,
2201
+ residual_request_sha256,
2202
+ "adaptive_tie",
2203
+ len(selected),
2204
+ value.action_sha256,
2205
+ )
2206
+ ),
2207
+ value.action_sha256,
2208
+ ),
2209
+ reverse=True,
2210
+ )
2211
+ )
2212
+ hierarchical_engine_order: tuple[str, ...] = ()
2213
+ if terminal_hierarchical:
2214
+ (
2215
+ directed_ranked,
2216
+ components,
2217
+ hierarchical_engine_order,
2218
+ ) = self._terminal_hierarchical_ranking(
2219
+ actions=actions,
2220
+ remaining=remaining,
2221
+ selected=selected,
2222
+ outcome_by_action=outcome_by_action,
2223
+ components=components,
2224
+ seats_left=seats_left,
2225
+ )
2226
+ audit_anchor_sha256: str | None = None
2227
+ audit_exploration_branch: bool | None = None
2228
+ audit_branch_draw: float | None = None
2229
+ audit_choice_draw: float | None = None
2230
+ audit_stratum_draw: float | None = None
2231
+ audit_stratum_key: tuple[str, ...] | None = None
2232
+ audit_strata_record: list[dict[str, object]] | None = None
2233
+ audit_max_uncovered_factor_count: int | None = None
2234
+ legacy_audit_pool_ids: list[str] | None = None
2235
+ if audit:
2236
+ ranked = tuple(
2237
+ sorted(
2238
+ remaining,
2239
+ key=lambda value: (
2240
+ -components[value.action_sha256]["diversity"],
2241
+ -components[value.action_sha256][
2242
+ "rank_counterfactual"
2243
+ ],
2244
+ -value.prior_score,
2245
+ value.action_sha256,
2246
+ ),
2247
+ )
2248
+ )
2249
+ if (
2250
+ self.policy_version
2251
+ == OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION
2252
+ ):
2253
+ anchor = directed_ranked[0]
2254
+ pool_values = [anchor]
2255
+ pool_values.extend(
2256
+ value
2257
+ for value in ranked
2258
+ if value.action_sha256 != anchor.action_sha256
2259
+ )
2260
+ pool = tuple(
2261
+ pool_values[
2262
+ : min(
2263
+ self.exploration_pool_size,
2264
+ len(pool_values),
2265
+ )
2266
+ ]
2267
+ )
2268
+ pool_ids = [value.action_sha256 for value in pool]
2269
+ audit_anchor_sha256 = anchor.action_sha256
2270
+ audit_branch_draw = _stable_unit_interval(
2271
+ self.random_seed,
2272
+ residual_request_sha256,
2273
+ "risk_controlled_audit_branch",
2274
+ len(selected),
2275
+ pool_ids,
2276
+ )
2277
+ audit_exploration_branch = (
2278
+ audit_branch_draw
2279
+ < self.audit_exploration_probability
2280
+ )
2281
+ if audit_exploration_branch:
2282
+ audit_choice_draw = _stable_unit_interval(
2283
+ self.random_seed,
2284
+ residual_request_sha256,
2285
+ "risk_controlled_audit_choice",
2286
+ len(selected),
2287
+ pool_ids,
2288
+ )
2289
+ chosen = pool[
2290
+ min(
2291
+ int(audit_choice_draw * len(pool)),
2292
+ len(pool) - 1,
2293
+ )
2294
+ ]
2295
+ else:
2296
+ chosen = anchor
2297
+ if chosen.action_sha256 == anchor.action_sha256:
2298
+ propensity = (
2299
+ 1.0
2300
+ - self.audit_exploration_probability
2301
+ + self.audit_exploration_probability / len(pool)
2302
+ )
2303
+ else:
2304
+ propensity = (
2305
+ self.audit_exploration_probability / len(pool)
2306
+ )
2307
+ ranked_candidates = directed_ranked
2308
+ ranking_basis = (
2309
+ "conditional_ucb_anchor_plus_epsilon_greedy_"
2310
+ "portable_diversity_audit"
2311
+ )
2312
+ elif (
2313
+ self.policy_version
2314
+ == OUTCOME_ADAPTIVE_ACTION_RACING_STRATIFIED_AUDIT_POLICY_VERSION
2315
+ ):
2316
+ legacy_pool = ranked[
2317
+ : min(self.exploration_pool_size, len(ranked))
2318
+ ]
2319
+ legacy_audit_pool_ids = [
2320
+ value.action_sha256 for value in legacy_pool
2321
+ ]
2322
+ legacy_rng = random.Random(
2323
+ int(
2324
+ hashlib.sha256(
2325
+ _canonical_json(
2326
+ [
2327
+ self.random_seed,
2328
+ residual_request_sha256,
2329
+ "randomized_audit",
2330
+ len(selected),
2331
+ legacy_audit_pool_ids,
2332
+ ]
2333
+ )
2334
+ ).hexdigest(),
2335
+ 16,
2336
+ )
2337
+ )
2338
+ anchor = legacy_pool[
2339
+ legacy_rng.randrange(len(legacy_pool))
2340
+ ]
2341
+ audit_anchor_sha256 = anchor.action_sha256
2342
+ required_families = set(
2343
+ self.stratified_audit_coverage_family_ids
2344
+ ) | set(self.stratified_audit_stratum_family_ids)
2345
+ factor_by_action: dict[str, dict[str, str]] = {}
2346
+ for action in (*selected, *remaining):
2347
+ factors = {
2348
+ value.family_id: value.level_id
2349
+ for value in action.factor_cells
2350
+ }
2351
+ missing = required_families - set(factors)
2352
+ if missing:
2353
+ raise ValueError(
2354
+ "stratified audit action lacks factor families: "
2355
+ + ",".join(sorted(missing))
2356
+ )
2357
+ factor_by_action[action.action_sha256] = factors
2358
+ selected_levels = {
2359
+ family_id: {
2360
+ factor_by_action[action.action_sha256][family_id]
2361
+ for action in selected
2362
+ }
2363
+ for family_id in (
2364
+ self.stratified_audit_coverage_family_ids
2365
+ )
2366
+ }
2367
+ uncovered_count = {
2368
+ action.action_sha256: sum(
2369
+ factor_by_action[action.action_sha256][family_id]
2370
+ not in selected_levels[family_id]
2371
+ for family_id in (
2372
+ self.stratified_audit_coverage_family_ids
2373
+ )
2374
+ )
2375
+ for action in remaining
2376
+ }
2377
+ audit_max_uncovered_factor_count = max(
2378
+ uncovered_count.values()
2379
+ )
2380
+ exploration_support = tuple(
2381
+ action
2382
+ for action in remaining
2383
+ if uncovered_count[action.action_sha256]
2384
+ == audit_max_uncovered_factor_count
2385
+ )
2386
+ strata: dict[
2387
+ tuple[str, ...],
2388
+ list[AdaptiveActionDescriptor],
2389
+ ] = {}
2390
+ for action in exploration_support:
2391
+ key = tuple(
2392
+ factor_by_action[action.action_sha256][family_id]
2393
+ for family_id in (
2394
+ self.stratified_audit_stratum_family_ids
2395
+ )
2396
+ )
2397
+ strata.setdefault(key, []).append(action)
2398
+ canonical_strata = tuple(
2399
+ (
2400
+ key,
2401
+ tuple(
2402
+ sorted(
2403
+ values,
2404
+ key=lambda value: value.action_sha256,
2405
+ )
2406
+ ),
2407
+ )
2408
+ for key, values in sorted(strata.items())
2409
+ )
2410
+ audit_strata_record = [
2411
+ {
2412
+ "stratum_key": list(key),
2413
+ "action_sha256s": [
2414
+ value.action_sha256 for value in values
2415
+ ],
2416
+ "conditional_action_propensity_hex": (
2417
+ (1.0 / len(values)).hex()
2418
+ ),
2419
+ }
2420
+ for key, values in canonical_strata
2421
+ ]
2422
+ pool_ids = sorted(
2423
+ value.action_sha256
2424
+ for value in exploration_support
2425
+ )
2426
+ audit_branch_draw = _stable_unit_interval(
2427
+ self.random_seed,
2428
+ residual_request_sha256,
2429
+ "stratified_audit_branch",
2430
+ len(selected),
2431
+ legacy_audit_pool_ids,
2432
+ pool_ids,
2433
+ )
2434
+ audit_exploration_branch = (
2435
+ audit_branch_draw
2436
+ < self.audit_exploration_probability
2437
+ )
2438
+ if audit_exploration_branch:
2439
+ audit_stratum_draw = _stable_unit_interval(
2440
+ self.random_seed,
2441
+ residual_request_sha256,
2442
+ "stratified_audit_stratum",
2443
+ len(selected),
2444
+ [value[0] for value in canonical_strata],
2445
+ )
2446
+ stratum_index = min(
2447
+ int(audit_stratum_draw * len(canonical_strata)),
2448
+ len(canonical_strata) - 1,
2449
+ )
2450
+ (
2451
+ audit_stratum_key,
2452
+ stratum_actions,
2453
+ ) = canonical_strata[stratum_index]
2454
+ audit_choice_draw = _stable_unit_interval(
2455
+ self.random_seed,
2456
+ residual_request_sha256,
2457
+ "stratified_audit_action",
2458
+ len(selected),
2459
+ audit_stratum_key,
2460
+ [
2461
+ value.action_sha256
2462
+ for value in stratum_actions
2463
+ ],
2464
+ )
2465
+ action_index = min(
2466
+ int(audit_choice_draw * len(stratum_actions)),
2467
+ len(stratum_actions) - 1,
2468
+ )
2469
+ chosen = stratum_actions[action_index]
2470
+ else:
2471
+ chosen = anchor
2472
+ chosen_factors = factor_by_action[
2473
+ chosen.action_sha256
2474
+ ]
2475
+ audit_stratum_key = tuple(
2476
+ chosen_factors[family_id]
2477
+ for family_id in (
2478
+ self.stratified_audit_stratum_family_ids
2479
+ )
2480
+ )
2481
+ chosen_stratum = next(
2482
+ (
2483
+ values
2484
+ for key, values in canonical_strata
2485
+ if key == audit_stratum_key
2486
+ ),
2487
+ (),
2488
+ )
2489
+ exploration_propensity = (
2490
+ 0.0
2491
+ if not chosen_stratum
2492
+ or chosen.action_sha256
2493
+ not in {
2494
+ value.action_sha256
2495
+ for value in chosen_stratum
2496
+ }
2497
+ else 1.0
2498
+ / len(canonical_strata)
2499
+ / len(chosen_stratum)
2500
+ )
2501
+ propensity = (
2502
+ (
2503
+ 1.0 - self.audit_exploration_probability
2504
+ if chosen.action_sha256 == anchor.action_sha256
2505
+ else 0.0
2506
+ )
2507
+ + self.audit_exploration_probability
2508
+ * exploration_propensity
2509
+ )
2510
+ ranked_candidates = ranked
2511
+ ranking_basis = (
2512
+ "legacy_v3_audit_anchor_plus_risk_controlled_"
2513
+ "factor_stratified_exploration"
2514
+ )
2515
+ else:
2516
+ pool = ranked[
2517
+ : min(self.exploration_pool_size, len(ranked))
2518
+ ]
2519
+ rng = random.Random(
2520
+ int(
2521
+ hashlib.sha256(
2522
+ _canonical_json(
2523
+ [
2524
+ self.random_seed,
2525
+ residual_request_sha256,
2526
+ "randomized_audit",
2527
+ len(selected),
2528
+ [
2529
+ value.action_sha256
2530
+ for value in pool
2531
+ ],
2532
+ ]
2533
+ )
2534
+ ).hexdigest(),
2535
+ 16,
2536
+ )
2537
+ )
2538
+ chosen = pool[rng.randrange(len(pool))]
2539
+ propensity = 1.0 / len(pool)
2540
+ pool_ids = [value.action_sha256 for value in pool]
2541
+ ranked_candidates = ranked
2542
+ ranking_basis = (
2543
+ "diversity_then_rank_counterfactual_then_prior"
2544
+ )
2545
+ wave = AdaptiveActionWave.RANDOMIZED_AUDIT
2546
+ else:
2547
+ chosen = directed_ranked[0]
2548
+ propensity = 1.0
2549
+ wave = AdaptiveActionWave.ADAPTIVE
2550
+ pool_ids = []
2551
+ ranked_candidates = directed_ranked
2552
+ ranking_basis = (
2553
+ (
2554
+ "conditional_opportunity_saturation_ucb_then_"
2555
+ "positive_then_prior"
2556
+ if self.policy_version in _CAUSAL_SET_POLICY_VERSIONS
2557
+ else (
2558
+ "robust_engine_exposure_then_within_engine_"
2559
+ "posterior_plus_native_rank"
2560
+ if terminal_hierarchical
2561
+ else "set_aware_ucb_then_positive_then_prior"
2562
+ )
2563
+ )
2564
+ )
2565
+ chosen_components = components[chosen.action_sha256]
2566
+ evidence: dict[str, object] = {
2567
+ "selected_action": chosen.to_record(),
2568
+ "selected_components": {
2569
+ name: value.hex()
2570
+ for name, value in chosen_components.items()
2571
+ },
2572
+ "randomized_exploration_pool_action_sha256s": pool_ids,
2573
+ "candidate_score_count": len(components),
2574
+ "observed_action_count": len(outcomes),
2575
+ "diagnostic_action_sha256s": list(
2576
+ diagnostic_action_sha256s
2577
+ ),
2578
+ "diagnostic_joint_gain_hex": (
2579
+ diagnostic_joint_gain.hex()
2580
+ ),
2581
+ "observed_set_outcome_sha256s": [
2582
+ value.set_outcome_sha256 for value in set_outcomes
2583
+ ],
2584
+ "causal_set_outcomes_used_for_selection": (
2585
+ self.policy_version in _CAUSAL_SET_POLICY_VERSIONS
2586
+ ),
2587
+ "directed_steps_completed_before_decision": (
2588
+ directed_steps_completed
2589
+ ),
2590
+ "unobserved_candidate_outcomes_available": False,
2591
+ "all_actions_materialized_before_current_outcomes": True,
2592
+ }
2593
+ if excluded_action_sha256s:
2594
+ evidence.update(
2595
+ {
2596
+ "excluded_action_sha256s": list(
2597
+ excluded_action_sha256s
2598
+ ),
2599
+ "exclusion_role": (
2600
+ "same_prefix_counterfactual_quarantine"
2601
+ ),
2602
+ "excluded_action_outcomes_used_for_selection": False,
2603
+ }
2604
+ )
2605
+ if (
2606
+ self.policy_version
2607
+ == OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION
2608
+ ):
2609
+ evidence.update(
2610
+ {
2611
+ "risk_controlled_audit": audit,
2612
+ "audit_exploration_probability_hex": (
2613
+ self.audit_exploration_probability.hex()
2614
+ ),
2615
+ "audit_anchor_action_sha256": (
2616
+ audit_anchor_sha256
2617
+ ),
2618
+ "audit_exploration_branch": (
2619
+ audit_exploration_branch
2620
+ ),
2621
+ "audit_branch_draw_hex": (
2622
+ None
2623
+ if audit_branch_draw is None
2624
+ else audit_branch_draw.hex()
2625
+ ),
2626
+ "audit_choice_draw_hex": (
2627
+ None
2628
+ if audit_choice_draw is None
2629
+ else audit_choice_draw.hex()
2630
+ ),
2631
+ "audit_selected_propensity_hex": (
2632
+ float(propensity).hex()
2633
+ ),
2634
+ "seed_affects_only_audit_draw": True,
2635
+ }
2636
+ )
2637
+ if (
2638
+ self.policy_version
2639
+ == OUTCOME_ADAPTIVE_ACTION_RACING_STRATIFIED_AUDIT_POLICY_VERSION
2640
+ ):
2641
+ evidence.update(
2642
+ {
2643
+ "risk_controlled_stratified_audit": audit,
2644
+ "audit_exploration_probability_hex": (
2645
+ self.audit_exploration_probability.hex()
2646
+ ),
2647
+ "legacy_audit_anchor_action_sha256": (
2648
+ audit_anchor_sha256
2649
+ ),
2650
+ "legacy_audit_pool_action_sha256s": (
2651
+ legacy_audit_pool_ids
2652
+ ),
2653
+ "audit_exploration_branch": (
2654
+ audit_exploration_branch
2655
+ ),
2656
+ "audit_branch_draw_hex": (
2657
+ None
2658
+ if audit_branch_draw is None
2659
+ else audit_branch_draw.hex()
2660
+ ),
2661
+ "audit_stratum_draw_hex": (
2662
+ None
2663
+ if audit_stratum_draw is None
2664
+ else audit_stratum_draw.hex()
2665
+ ),
2666
+ "audit_choice_draw_hex": (
2667
+ None
2668
+ if audit_choice_draw is None
2669
+ else audit_choice_draw.hex()
2670
+ ),
2671
+ "audit_selected_stratum_key": (
2672
+ None
2673
+ if audit_stratum_key is None
2674
+ else list(audit_stratum_key)
2675
+ ),
2676
+ "audit_strata": audit_strata_record,
2677
+ "audit_max_uncovered_factor_count": (
2678
+ audit_max_uncovered_factor_count
2679
+ ),
2680
+ "audit_coverage_family_ids": list(
2681
+ self.stratified_audit_coverage_family_ids
2682
+ ),
2683
+ "audit_stratum_family_ids": list(
2684
+ self.stratified_audit_stratum_family_ids
2685
+ ),
2686
+ "audit_selected_propensity_hex": (
2687
+ float(propensity).hex()
2688
+ ),
2689
+ "legacy_anchor_probability_hex": (
2690
+ (1.0 - self.audit_exploration_probability).hex()
2691
+ ),
2692
+ "candidate_factor_cells_outcome_blind": True,
2693
+ "seed_affects_legacy_anchor_and_audit_draws": True,
2694
+ }
2695
+ )
2696
+ if (
2697
+ self.policy_version
2698
+ == OUTCOME_ADAPTIVE_ACTION_RACING_HORIZON_HIERARCHICAL_POLICY_VERSION
2699
+ ):
2700
+ evidence.update(
2701
+ {
2702
+ "horizon_aware_authoritative_measurement": True,
2703
+ "seats_left_before_decision": seats_left,
2704
+ "future_optimization_slots_after_decision": max(
2705
+ 0,
2706
+ seats_left - 1,
2707
+ ),
2708
+ "authoritative_audit_due": horizon_audit_due,
2709
+ "authoritative_audit_selected": audit,
2710
+ "authoritative_audit_blocked_reason": (
2711
+ horizon_audit_blocked_reason
2712
+ ),
2713
+ "minimum_post_audit_optimization_slots": (
2714
+ self.minimum_post_audit_optimization_slots
2715
+ ),
2716
+ "terminal_hierarchical_slots": (
2717
+ self.terminal_hierarchical_slots
2718
+ ),
2719
+ "terminal_hierarchical_allocation": (
2720
+ terminal_hierarchical
2721
+ ),
2722
+ "hierarchical_engine_order": list(
2723
+ hierarchical_engine_order
2724
+ ),
2725
+ "selected_engine_id": chosen.lane_id,
2726
+ "native_rank_strength_hex": (
2727
+ self.native_rank_strength.hex()
2728
+ ),
2729
+ "engine_returns_capped_only_for_allocation": True,
2730
+ "authoritative_archive_utility_capped": False,
2731
+ "workload_model_provider_prompt_branches": False,
2732
+ }
2733
+ )
2734
+ if (
2735
+ self.policy_version
2736
+ in {
2737
+ OUTCOME_ADAPTIVE_ACTION_RACING_SET_AWARE_POLICY_VERSION,
2738
+ OUTCOME_ADAPTIVE_ACTION_RACING_CAUSAL_SET_POLICY_VERSION,
2739
+ OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION,
2740
+ OUTCOME_ADAPTIVE_ACTION_RACING_STRATIFIED_AUDIT_POLICY_VERSION,
2741
+ OUTCOME_ADAPTIVE_ACTION_RACING_HORIZON_HIERARCHICAL_POLICY_VERSION,
2742
+ }
2743
+ ):
2744
+ evidence.update(
2745
+ {
2746
+ "candidate_score_cards": [
2747
+ {
2748
+ "rank": rank,
2749
+ "selected": (
2750
+ value.action_sha256
2751
+ == chosen.action_sha256
2752
+ ),
2753
+ "randomized_pool_member": (
2754
+ value.action_sha256 in set(pool_ids)
2755
+ ),
2756
+ "action": value.to_record(),
2757
+ "components": {
2758
+ name: component.hex()
2759
+ for name, component in components[
2760
+ value.action_sha256
2761
+ ].items()
2762
+ },
2763
+ }
2764
+ for rank, value in enumerate(
2765
+ ranked_candidates[
2766
+ : self.trace_alternative_count
2767
+ ],
2768
+ start=1,
2769
+ )
2770
+ ],
2771
+ "candidate_score_card_count": min(
2772
+ self.trace_alternative_count,
2773
+ len(ranked_candidates),
2774
+ ),
2775
+ "candidate_score_ranking_basis": ranking_basis,
2776
+ "chosen_action_present_in_score_cards": (
2777
+ chosen.action_sha256
2778
+ in {
2779
+ value.action_sha256
2780
+ for value in ranked_candidates[
2781
+ : self.trace_alternative_count
2782
+ ]
2783
+ }
2784
+ ),
2785
+ }
2786
+ )
2787
+ return AdaptiveActionRacingDecision(
2788
+ policy_id=self.policy_id,
2789
+ policy_version=self.policy_version,
2790
+ policy_definition_sha256=self.definition_sha256,
2791
+ residual_request_sha256=residual_request_sha256,
2792
+ wave=wave,
2793
+ selected_action_sha256s=(chosen.action_sha256,),
2794
+ prior_selected_action_sha256s=tuple(
2795
+ sorted(selected_action_sha256s)
2796
+ ),
2797
+ observed_outcome_sha256s=tuple(
2798
+ sorted(value.outcome_sha256 for value in outcomes)
2799
+ ),
2800
+ observed_set_outcome_sha256s=tuple(
2801
+ sorted(
2802
+ value.set_outcome_sha256
2803
+ for value in set_outcomes
2804
+ )
2805
+ ),
2806
+ selection_propensity=float(propensity),
2807
+ evidence=freeze_json(evidence),
2808
+ )
2809
+
2810
+
2811
+ __all__ = [
2812
+ "AdaptiveActionAllocationDirective",
2813
+ "AdaptiveActionDescriptor",
2814
+ "AdaptiveActionFactorCell",
2815
+ "AdaptiveActionOutcome",
2816
+ "AdaptiveActionSetOutcome",
2817
+ "AdaptiveActionRacingDecision",
2818
+ "AdaptiveActionWave",
2819
+ "OUTCOME_ADAPTIVE_ACTION_RACING_CAUSAL_SET_POLICY_VERSION",
2820
+ "OUTCOME_ADAPTIVE_ACTION_RACING_HORIZON_HIERARCHICAL_POLICY_VERSION",
2821
+ "OUTCOME_ADAPTIVE_ACTION_RACING_POLICY_ID",
2822
+ "OUTCOME_ADAPTIVE_ACTION_RACING_POLICY_VERSION",
2823
+ "OUTCOME_ADAPTIVE_ACTION_RACING_RISK_CONTROLLED_POLICY_VERSION",
2824
+ "OUTCOME_ADAPTIVE_ACTION_RACING_STRATIFIED_AUDIT_POLICY_VERSION",
2825
+ "OUTCOME_ADAPTIVE_ACTION_RACING_SET_AWARE_POLICY_VERSION",
2826
+ "OutcomeAdaptiveActionRacingPolicy",
2827
+ ]