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,1580 @@
1
+ """Outcome-blind paired audits for one frozen adaptive-action prefix.
2
+
3
+ This module is an experimental interception primitive, not a production
4
+ allocation policy. It converts the final factor-stratified audit decision
5
+ into two distinct arms:
6
+
7
+ * the frozen legacy audit anchor; and
8
+ * one factor-stratified alternative selected without either arm's outcome.
9
+
10
+ Callers must durably commit the returned plan before evaluating either arm.
11
+ Both arms are then valued independently against the same pre-audit evaluation
12
+ prefix. Their union is never a budget-matched optimizer result and must not be
13
+ published to the authoritative archive.
14
+
15
+ The design consumes only portable action descriptors and authenticated racing
16
+ evidence. It has no workload, objective, configuration, prompt, model, or
17
+ provider branch.
18
+ """
19
+
20
+ from __future__ import annotations
21
+
22
+ import hashlib
23
+ import json
24
+ import math
25
+ import re
26
+ from dataclasses import dataclass, field
27
+ from enum import Enum
28
+ from typing import Protocol, runtime_checkable
29
+
30
+ from agent_evolve.application.outcome_adaptive_action_racing import (
31
+ AdaptiveActionDescriptor,
32
+ AdaptiveActionOutcome,
33
+ AdaptiveActionRacingDecision,
34
+ AdaptiveActionSetOutcome,
35
+ AdaptiveActionWave,
36
+ OUTCOME_ADAPTIVE_ACTION_RACING_POLICY_ID,
37
+ OUTCOME_ADAPTIVE_ACTION_RACING_STRATIFIED_AUDIT_POLICY_VERSION,
38
+ )
39
+ from agent_evolve.domain.patch import require_sha256
40
+ from agent_evolve.domain.typed_json import (
41
+ FrozenJsonObject,
42
+ freeze_json,
43
+ thaw_json,
44
+ typed_json_sha256,
45
+ )
46
+
47
+
48
+ SAME_PREFIX_PAIRED_AUDIT_DESIGNER_ID = (
49
+ "factor_stratified_same_prefix_paired_audit"
50
+ )
51
+ SAME_PREFIX_PAIRED_AUDIT_DESIGNER_VERSION = 1
52
+ FORECAST_OPPORTUNITY_SAME_PREFIX_SHADOW_DESIGNER_ID = (
53
+ "forecast_opportunity_same_prefix_shadow"
54
+ )
55
+ FORECAST_OPPORTUNITY_SAME_PREFIX_SHADOW_DESIGNER_VERSION = 1
56
+ FORECAST_STRATIFIED_SAME_PREFIX_AUDIT_DESIGNER_ID = (
57
+ "forecast_stratified_same_prefix_audit"
58
+ )
59
+ FORECAST_STRATIFIED_SAME_PREFIX_AUDIT_DESIGNER_VERSION = 1
60
+ FORECAST_OPPORTUNITY_SAME_PREFIX_AUDIT_DESIGNER_IDS = frozenset(
61
+ {
62
+ FORECAST_OPPORTUNITY_SAME_PREFIX_SHADOW_DESIGNER_ID,
63
+ FORECAST_STRATIFIED_SAME_PREFIX_AUDIT_DESIGNER_ID,
64
+ }
65
+ )
66
+ SAME_PREFIX_PAIRED_AUDIT_ADJUDICATOR_ID = (
67
+ "same_prefix_paired_audit_adjudicator"
68
+ )
69
+ SAME_PREFIX_PAIRED_AUDIT_ADJUDICATOR_VERSION = 1
70
+
71
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
72
+ _DESIGNER_DEFINITION_DOMAIN = (
73
+ b"agent-evolve:same-prefix-paired-audit-designer-definition:v1\x00"
74
+ )
75
+ _FORECAST_SHADOW_DESIGNER_DEFINITION_DOMAIN = (
76
+ b"agent-evolve:forecast-opportunity-same-prefix-shadow-designer:"
77
+ b"definition:v1\x00"
78
+ )
79
+ _FORECAST_STRATIFIED_DESIGNER_DEFINITION_DOMAIN = (
80
+ b"agent-evolve:forecast-stratified-same-prefix-audit-designer:"
81
+ b"definition:v1\x00"
82
+ )
83
+ _PLAN_DOMAIN = b"agent-evolve:same-prefix-paired-audit-plan:v1\x00"
84
+ _ADJUDICATOR_DEFINITION_DOMAIN = (
85
+ b"agent-evolve:same-prefix-paired-audit-adjudicator-definition:v1\x00"
86
+ )
87
+ _OBSERVATION_DOMAIN = (
88
+ b"agent-evolve:same-prefix-paired-audit-observation:v1\x00"
89
+ )
90
+
91
+
92
+ def _canonical_json(value: object) -> bytes:
93
+ return json.dumps(
94
+ value,
95
+ allow_nan=False,
96
+ ensure_ascii=True,
97
+ separators=(",", ":"),
98
+ sort_keys=True,
99
+ ).encode("ascii", errors="strict")
100
+
101
+
102
+ def _hash(domain: bytes, value: object) -> str:
103
+ return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
104
+
105
+
106
+ def _require_token(value: str, *, name: str) -> None:
107
+ if type(value) is not str or _TOKEN.fullmatch(value) is None:
108
+ raise ValueError(f"{name} must use the closed token grammar")
109
+
110
+
111
+ def _require_probability(value: float, *, name: str) -> None:
112
+ if (
113
+ type(value) is not float
114
+ or not math.isfinite(value)
115
+ or not 0.0 < value <= 1.0
116
+ ):
117
+ raise ValueError(f"{name} must be a finite positive probability")
118
+
119
+
120
+ def _read_nonnegative_hex(record: dict[str, object], key: str) -> float:
121
+ raw = record.get(key)
122
+ if type(raw) is not str:
123
+ raise TypeError(f"{key} must be an exact hexadecimal float")
124
+ try:
125
+ value = float.fromhex(raw)
126
+ except ValueError as error:
127
+ raise ValueError(f"{key} is not a hexadecimal float") from error
128
+ if not math.isfinite(value) or value < 0.0:
129
+ raise ValueError(f"{key} must be finite and non-negative")
130
+ return float(value)
131
+
132
+
133
+ def _stable_unit_interval(*parts: object) -> float:
134
+ payload = _canonical_json(list(parts))
135
+ numerator = int.from_bytes(hashlib.sha256(payload).digest()[:8], "big")
136
+ return numerator / float(2**64)
137
+
138
+
139
+ def _canonical_hash_tuple(
140
+ values: tuple[str, ...],
141
+ *,
142
+ name: str,
143
+ allow_empty: bool,
144
+ ) -> tuple[str, ...]:
145
+ if (
146
+ type(values) is not tuple
147
+ or (not allow_empty and not values)
148
+ or values != tuple(sorted(set(values)))
149
+ ):
150
+ raise ValueError(f"{name} must be a canonical exact tuple")
151
+ for value in values:
152
+ require_sha256(value, name)
153
+ return values
154
+
155
+
156
+ class SamePrefixPairedAuditArm(str, Enum):
157
+ """The arm retained by the original budget-matched decision."""
158
+
159
+ LEGACY = "legacy"
160
+ EXPLORATION = "exploration"
161
+
162
+
163
+ class SamePrefixPairedAuditWinner(str, Enum):
164
+ """Winner under conditional utility at the common prefix."""
165
+
166
+ LEGACY = "legacy"
167
+ EXPLORATION = "exploration"
168
+ TIE = "tie"
169
+
170
+
171
+ @dataclass(frozen=True, slots=True)
172
+ class SamePrefixPairedAuditPlan:
173
+ """Hash-bound plan that must be committed before arm evaluation."""
174
+
175
+ designer_id: str
176
+ designer_version: int
177
+ designer_definition_sha256: str
178
+ residual_request_sha256: str
179
+ racing_decision_sha256: str
180
+ common_prefix_action_sha256s: tuple[str, ...]
181
+ authoritative_arm: SamePrefixPairedAuditArm
182
+ authoritative_action_sha256: str
183
+ legacy_action_sha256: str
184
+ exploration_action_sha256: str
185
+ exploration_stratum_key: tuple[str, ...]
186
+ distinct_exploration_support_action_sha256s: tuple[str, ...]
187
+ exploration_selection_propensity: float
188
+ evidence: FrozenJsonObject
189
+ plan_sha256: str = field(init=False)
190
+
191
+ def __post_init__(self) -> None:
192
+ _require_token(self.designer_id, name="designer_id")
193
+ if type(self.designer_version) is not int or self.designer_version <= 0:
194
+ raise ValueError("designer_version must be positive")
195
+ for value, name in (
196
+ (
197
+ self.designer_definition_sha256,
198
+ "designer_definition_sha256",
199
+ ),
200
+ (self.residual_request_sha256, "residual_request_sha256"),
201
+ (self.racing_decision_sha256, "racing_decision_sha256"),
202
+ (self.authoritative_action_sha256, "authoritative_action_sha256"),
203
+ (self.legacy_action_sha256, "legacy_action_sha256"),
204
+ (self.exploration_action_sha256, "exploration_action_sha256"),
205
+ ):
206
+ require_sha256(value, name)
207
+ prefix = _canonical_hash_tuple(
208
+ self.common_prefix_action_sha256s,
209
+ name="common_prefix_action_sha256s",
210
+ allow_empty=False,
211
+ )
212
+ support = _canonical_hash_tuple(
213
+ self.distinct_exploration_support_action_sha256s,
214
+ name="distinct_exploration_support_action_sha256s",
215
+ allow_empty=False,
216
+ )
217
+ if type(self.authoritative_arm) is not SamePrefixPairedAuditArm:
218
+ raise TypeError("authoritative_arm must be exact")
219
+ if self.legacy_action_sha256 == self.exploration_action_sha256:
220
+ raise ValueError("paired audit arms must be distinct")
221
+ if {
222
+ self.legacy_action_sha256,
223
+ self.exploration_action_sha256,
224
+ } & set(prefix):
225
+ raise ValueError("paired audit arm is already in the common prefix")
226
+ if self.exploration_action_sha256 not in support:
227
+ raise ValueError("exploration arm is outside its distinct support")
228
+ expected_authoritative = (
229
+ self.legacy_action_sha256
230
+ if self.authoritative_arm is SamePrefixPairedAuditArm.LEGACY
231
+ else self.exploration_action_sha256
232
+ )
233
+ if self.authoritative_action_sha256 != expected_authoritative:
234
+ raise ValueError("authoritative action does not match its arm")
235
+ if (
236
+ type(self.exploration_stratum_key) is not tuple
237
+ or not self.exploration_stratum_key
238
+ ):
239
+ raise ValueError("exploration_stratum_key must be non-empty")
240
+ for value in self.exploration_stratum_key:
241
+ _require_token(value, name="exploration stratum level")
242
+ _require_probability(
243
+ self.exploration_selection_propensity,
244
+ name="exploration_selection_propensity",
245
+ )
246
+ if (
247
+ type(self.evidence) is not FrozenJsonObject
248
+ or freeze_json(self.evidence) is not self.evidence
249
+ ):
250
+ raise TypeError("evidence must be an exact frozen object")
251
+ object.__setattr__(
252
+ self,
253
+ "plan_sha256",
254
+ _hash(_PLAN_DOMAIN, self._unsigned_record()),
255
+ )
256
+
257
+ def _unsigned_record(self) -> dict[str, object]:
258
+ return {
259
+ "schema_version": 1,
260
+ "designer": {
261
+ "designer_id": self.designer_id,
262
+ "designer_version": self.designer_version,
263
+ "definition_sha256": self.designer_definition_sha256,
264
+ },
265
+ "residual_request_sha256": self.residual_request_sha256,
266
+ "racing_decision_sha256": self.racing_decision_sha256,
267
+ "common_prefix_action_sha256s": list(
268
+ self.common_prefix_action_sha256s
269
+ ),
270
+ "authoritative_arm": self.authoritative_arm.value,
271
+ "authoritative_action_sha256": (
272
+ self.authoritative_action_sha256
273
+ ),
274
+ "legacy_action_sha256": self.legacy_action_sha256,
275
+ "exploration_action_sha256": self.exploration_action_sha256,
276
+ "exploration_stratum_key": list(
277
+ self.exploration_stratum_key
278
+ ),
279
+ "distinct_exploration_support_action_sha256s": list(
280
+ self.distinct_exploration_support_action_sha256s
281
+ ),
282
+ "exploration_selection_propensity_hex": (
283
+ self.exploration_selection_propensity.hex()
284
+ ),
285
+ "evidence_sha256": typed_json_sha256(self.evidence),
286
+ "current_arm_outcomes_observed": False,
287
+ "assay_union_may_enter_authoritative_archive": False,
288
+ "workload_objective_model_provider_prompt_config_branches": False,
289
+ }
290
+
291
+ def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
292
+ self.__post_init__()
293
+ result = {
294
+ **self._unsigned_record(),
295
+ "plan_sha256": self.plan_sha256,
296
+ }
297
+ if include_evidence:
298
+ result["evidence"] = thaw_json(self.evidence)
299
+ return result
300
+
301
+
302
+ @runtime_checkable
303
+ class SamePrefixPairedAuditDesignerPort(Protocol):
304
+ """Inverted port for an outcome-blind paired-audit design."""
305
+
306
+ designer_id: str
307
+ designer_version: int
308
+ definition_sha256: str
309
+
310
+ def design(
311
+ self,
312
+ *,
313
+ decision: AdaptiveActionRacingDecision,
314
+ actions: tuple[AdaptiveActionDescriptor, ...],
315
+ ) -> SamePrefixPairedAuditPlan: ...
316
+
317
+
318
+ @runtime_checkable
319
+ class ForecastOpportunitySamePrefixShadowDesignerPort(Protocol):
320
+ """Inverted port for a pre-outcome challenger-versus-fallback shadow."""
321
+
322
+ designer_id: str
323
+ designer_version: int
324
+ definition_sha256: str
325
+
326
+ def design(
327
+ self,
328
+ *,
329
+ adaptive_step: int,
330
+ remaining_authoritative_slots_after_decision: int,
331
+ decision: AdaptiveActionRacingDecision,
332
+ fallback: AdaptiveActionRacingDecision,
333
+ actions: tuple[AdaptiveActionDescriptor, ...],
334
+ ) -> SamePrefixPairedAuditPlan | None: ...
335
+
336
+
337
+ ForecastOpportunitySamePrefixAuditDesignerPort = (
338
+ ForecastOpportunitySamePrefixShadowDesignerPort
339
+ )
340
+
341
+
342
+ @dataclass(frozen=True, slots=True)
343
+ class ForecastOpportunitySamePrefixShadowDesigner:
344
+ """Freeze a final-step forecast challenger against its exact fallback.
345
+
346
+ Final-step interception prevents a shadow outcome from becoming a later
347
+ authoritative action in the same stage. Only the challenger remains in
348
+ the budget-matched optimizer archive.
349
+ """
350
+
351
+ final_continuation_only: bool = True
352
+ designer_id: str = (
353
+ FORECAST_OPPORTUNITY_SAME_PREFIX_SHADOW_DESIGNER_ID
354
+ )
355
+ designer_version: int = (
356
+ FORECAST_OPPORTUNITY_SAME_PREFIX_SHADOW_DESIGNER_VERSION
357
+ )
358
+ definition_sha256: str = field(init=False)
359
+
360
+ def __post_init__(self) -> None:
361
+ if type(self.final_continuation_only) is not bool:
362
+ raise TypeError("final_continuation_only must be exact")
363
+ if (
364
+ self.designer_id
365
+ != FORECAST_OPPORTUNITY_SAME_PREFIX_SHADOW_DESIGNER_ID
366
+ or self.designer_version
367
+ != FORECAST_OPPORTUNITY_SAME_PREFIX_SHADOW_DESIGNER_VERSION
368
+ ):
369
+ raise ValueError("forecast shadow designer identity is immutable")
370
+ object.__setattr__(
371
+ self,
372
+ "definition_sha256",
373
+ _hash(
374
+ _FORECAST_SHADOW_DESIGNER_DEFINITION_DOMAIN,
375
+ {
376
+ "schema_version": 1,
377
+ "designer_id": self.designer_id,
378
+ "designer_version": self.designer_version,
379
+ "final_continuation_only": self.final_continuation_only,
380
+ "authoritative_arm": "forecast_opportunity_challenger",
381
+ "counterfactual_arm": "authenticated_fallback",
382
+ "common_prefix": "exact-real-selected-prefix",
383
+ "plan_frozen_before_either_arm_outcome": True,
384
+ "assay_union_may_enter_authoritative_archive": False,
385
+ "workload_objective_model_provider_prompt_config_"
386
+ "branches": False,
387
+ },
388
+ ),
389
+ )
390
+
391
+ @staticmethod
392
+ def _validate_action_market(
393
+ actions: tuple[AdaptiveActionDescriptor, ...],
394
+ ) -> dict[str, AdaptiveActionDescriptor]:
395
+ if type(actions) is not tuple or not actions:
396
+ raise ValueError("actions must be a non-empty exact tuple")
397
+ action_by_sha256: dict[str, AdaptiveActionDescriptor] = {}
398
+ for value in actions:
399
+ if type(value) is not AdaptiveActionDescriptor:
400
+ raise TypeError("actions must contain exact descriptors")
401
+ value.__post_init__()
402
+ if value.action_sha256 in action_by_sha256:
403
+ raise ValueError("actions repeat an identity")
404
+ action_by_sha256[value.action_sha256] = value
405
+ return action_by_sha256
406
+
407
+ def design(
408
+ self,
409
+ *,
410
+ adaptive_step: int,
411
+ remaining_authoritative_slots_after_decision: int,
412
+ decision: AdaptiveActionRacingDecision,
413
+ fallback: AdaptiveActionRacingDecision,
414
+ actions: tuple[AdaptiveActionDescriptor, ...],
415
+ ) -> SamePrefixPairedAuditPlan | None:
416
+ """Return no assay for abstention, unchanged action, or an early step."""
417
+
418
+ self.__post_init__()
419
+ if type(adaptive_step) is not int or adaptive_step <= 0:
420
+ raise ValueError("adaptive_step must be positive")
421
+ if (
422
+ type(remaining_authoritative_slots_after_decision) is not int
423
+ or remaining_authoritative_slots_after_decision < 0
424
+ ):
425
+ raise ValueError(
426
+ "remaining_authoritative_slots_after_decision must be "
427
+ "non-negative"
428
+ )
429
+ if (
430
+ self.final_continuation_only
431
+ and remaining_authoritative_slots_after_decision != 0
432
+ ):
433
+ return None
434
+ if type(decision) is not AdaptiveActionRacingDecision:
435
+ raise TypeError("decision must be exact")
436
+ if type(fallback) is not AdaptiveActionRacingDecision:
437
+ raise TypeError("fallback must be exact")
438
+ decision.__post_init__()
439
+ fallback.__post_init__()
440
+ if (
441
+ decision.wave is AdaptiveActionWave.DIAGNOSTIC
442
+ or fallback.wave is AdaptiveActionWave.DIAGNOSTIC
443
+ or decision.wave is not fallback.wave
444
+ ):
445
+ raise ValueError("forecast shadow requires one continuation wave")
446
+ if (
447
+ len(decision.selected_action_sha256s) != 1
448
+ or len(fallback.selected_action_sha256s) != 1
449
+ ):
450
+ raise ValueError("forecast shadow arms must each select one action")
451
+ if (
452
+ decision.residual_request_sha256
453
+ != fallback.residual_request_sha256
454
+ or decision.prior_selected_action_sha256s
455
+ != fallback.prior_selected_action_sha256s
456
+ or decision.observed_outcome_sha256s
457
+ != fallback.observed_outcome_sha256s
458
+ or decision.observed_set_outcome_sha256s
459
+ != fallback.observed_set_outcome_sha256s
460
+ ):
461
+ raise ValueError("forecast challenger and fallback cutoffs differ")
462
+ challenger_action_sha256 = decision.selected_action_sha256s[0]
463
+ fallback_action_sha256 = fallback.selected_action_sha256s[0]
464
+ if challenger_action_sha256 == fallback_action_sha256:
465
+ return None
466
+ action_by_sha256 = self._validate_action_market(actions)
467
+ prefix = set(decision.prior_selected_action_sha256s)
468
+ if (
469
+ not prefix
470
+ or not prefix.issubset(action_by_sha256)
471
+ or challenger_action_sha256 not in action_by_sha256
472
+ or fallback_action_sha256 not in action_by_sha256
473
+ or {
474
+ challenger_action_sha256,
475
+ fallback_action_sha256,
476
+ }
477
+ & prefix
478
+ ):
479
+ raise ValueError("forecast shadow arms are outside the open market")
480
+ evidence = thaw_json(decision.evidence)
481
+ if (
482
+ evidence.get("selection_source")
483
+ != "current_prefix_forecast_opportunity"
484
+ or evidence.get("fallback_preserved_on_abstention") is not True
485
+ or evidence.get("eligible_candidate_outcomes_observed") is not False
486
+ ):
487
+ raise ValueError(
488
+ "decision lacks the protected forecast-opportunity contract"
489
+ )
490
+ embedded_fallback = evidence.get("fallback_decision")
491
+ expected_fallback = fallback.to_record(include_evidence=True)
492
+ if embedded_fallback != expected_fallback:
493
+ raise ValueError(
494
+ "decision does not authenticate the supplied fallback"
495
+ )
496
+ return SamePrefixPairedAuditPlan(
497
+ designer_id=self.designer_id,
498
+ designer_version=self.designer_version,
499
+ designer_definition_sha256=self.definition_sha256,
500
+ residual_request_sha256=decision.residual_request_sha256,
501
+ racing_decision_sha256=decision.decision_sha256,
502
+ common_prefix_action_sha256s=(
503
+ decision.prior_selected_action_sha256s
504
+ ),
505
+ authoritative_arm=SamePrefixPairedAuditArm.EXPLORATION,
506
+ authoritative_action_sha256=challenger_action_sha256,
507
+ legacy_action_sha256=fallback_action_sha256,
508
+ exploration_action_sha256=challenger_action_sha256,
509
+ exploration_stratum_key=(
510
+ "selection_source",
511
+ "forecast_opportunity",
512
+ ),
513
+ distinct_exploration_support_action_sha256s=(
514
+ challenger_action_sha256,
515
+ ),
516
+ exploration_selection_propensity=1.0,
517
+ evidence=freeze_json(
518
+ {
519
+ "adaptive_step": adaptive_step,
520
+ "remaining_authoritative_slots_after_decision": (
521
+ remaining_authoritative_slots_after_decision
522
+ ),
523
+ "challenger_decision_sha256": decision.decision_sha256,
524
+ "fallback_decision_sha256": fallback.decision_sha256,
525
+ "challenger_action_sha256": challenger_action_sha256,
526
+ "fallback_action_sha256": fallback_action_sha256,
527
+ "legacy_arm_semantic_role": "authenticated_fallback",
528
+ "exploration_arm_semantic_role": (
529
+ "forecast_opportunity_challenger"
530
+ ),
531
+ "final_continuation_only": (
532
+ self.final_continuation_only
533
+ ),
534
+ "current_arm_outcomes_observed": False,
535
+ "plan_must_be_committed_before_arm_evaluation": True,
536
+ "assay_union_may_enter_authoritative_archive": False,
537
+ }
538
+ ),
539
+ )
540
+
541
+
542
+ @dataclass(frozen=True, slots=True)
543
+ class ForecastStratifiedSamePrefixAuditDesigner:
544
+ """Acquire one same-prefix forecast audit even when CPO abstains.
545
+
546
+ One continuation position is selected uniformly and deterministically from
547
+ the opaque residual-request identity. At that position, an unchanged
548
+ protected fallback remains authoritative while a forecast-covered action
549
+ is sampled by a uniform-nonempty-stratum, uniform-within-stratum design.
550
+ If the protected challenger already changed fallback, its selected action
551
+ is reused as the exploration arm. Neither arm outcome is available while
552
+ the plan is constructed.
553
+ """
554
+
555
+ random_seed: int = 0
556
+ designer_id: str = (
557
+ FORECAST_STRATIFIED_SAME_PREFIX_AUDIT_DESIGNER_ID
558
+ )
559
+ designer_version: int = (
560
+ FORECAST_STRATIFIED_SAME_PREFIX_AUDIT_DESIGNER_VERSION
561
+ )
562
+ definition_sha256: str = field(init=False)
563
+
564
+ def __post_init__(self) -> None:
565
+ if type(self.random_seed) is not int or self.random_seed < 0:
566
+ raise ValueError("random_seed must be non-negative")
567
+ if (
568
+ self.designer_id
569
+ != FORECAST_STRATIFIED_SAME_PREFIX_AUDIT_DESIGNER_ID
570
+ or self.designer_version
571
+ != FORECAST_STRATIFIED_SAME_PREFIX_AUDIT_DESIGNER_VERSION
572
+ ):
573
+ raise ValueError(
574
+ "forecast-stratified audit designer identity is immutable"
575
+ )
576
+ object.__setattr__(
577
+ self,
578
+ "definition_sha256",
579
+ _hash(
580
+ _FORECAST_STRATIFIED_DESIGNER_DEFINITION_DOMAIN,
581
+ {
582
+ "schema_version": 1,
583
+ "designer_id": self.designer_id,
584
+ "designer_version": self.designer_version,
585
+ "random_seed": self.random_seed,
586
+ "schedule": (
587
+ "one-hash-uniform-continuation-position-per-request"
588
+ ),
589
+ "strata": [
590
+ "recommended",
591
+ "adverse_positive",
592
+ "central_positive_adverse_zero",
593
+ "favorable_positive_central_zero",
594
+ "forecast_zero",
595
+ ],
596
+ "sampling": (
597
+ "uniform-nonempty-stratum-then-uniform-action"
598
+ ),
599
+ "abstention_authoritative_arm": "protected_fallback",
600
+ "intervention_authoritative_arm": (
601
+ "forecast_opportunity_challenger"
602
+ ),
603
+ "counterfactual_action_quarantined_after_assay": True,
604
+ "plan_frozen_before_either_arm_outcome": True,
605
+ "assay_union_may_enter_authoritative_archive": False,
606
+ "workload_objective_model_provider_prompt_config_"
607
+ "branches": False,
608
+ },
609
+ ),
610
+ )
611
+
612
+ @staticmethod
613
+ def _validate_action_market(
614
+ actions: tuple[AdaptiveActionDescriptor, ...],
615
+ ) -> dict[str, AdaptiveActionDescriptor]:
616
+ if type(actions) is not tuple or not actions:
617
+ raise ValueError("actions must be a non-empty exact tuple")
618
+ action_by_sha256: dict[str, AdaptiveActionDescriptor] = {}
619
+ for value in actions:
620
+ if type(value) is not AdaptiveActionDescriptor:
621
+ raise TypeError("actions must contain exact descriptors")
622
+ value.__post_init__()
623
+ if value.action_sha256 in action_by_sha256:
624
+ raise ValueError("actions repeat an identity")
625
+ action_by_sha256[value.action_sha256] = value
626
+ return action_by_sha256
627
+
628
+ @staticmethod
629
+ def _score_stratum(
630
+ *,
631
+ score: dict[str, object],
632
+ recommended_action_sha256s: set[str],
633
+ ) -> str:
634
+ action_sha256 = score.get("action_sha256")
635
+ if type(action_sha256) is not str:
636
+ raise TypeError("opportunity score lacks an action identity")
637
+ if action_sha256 in recommended_action_sha256s:
638
+ return "recommended"
639
+ adverse = _read_nonnegative_hex(score, "adverse_gain_hex")
640
+ central = _read_nonnegative_hex(score, "central_gain_hex")
641
+ favorable = _read_nonnegative_hex(score, "favorable_gain_hex")
642
+ if adverse > 0.0:
643
+ return "adverse_positive"
644
+ if central > 0.0:
645
+ return "central_positive_adverse_zero"
646
+ if favorable > 0.0:
647
+ return "favorable_positive_central_zero"
648
+ return "forecast_zero"
649
+
650
+ @classmethod
651
+ def _read_forecast_strata(
652
+ cls,
653
+ *,
654
+ evidence: dict[str, object],
655
+ action_by_sha256: dict[str, AdaptiveActionDescriptor],
656
+ prefix: set[str],
657
+ legacy_action_sha256: str,
658
+ ) -> tuple[
659
+ tuple[str, tuple[str, ...]],
660
+ ...,
661
+ ]:
662
+ ranking = evidence.get("opportunity_ranking")
663
+ if type(ranking) is not dict:
664
+ raise TypeError("decision lacks an opportunity ranking")
665
+ if (
666
+ ranking.get("eligible_candidate_outcomes_observed") is not False
667
+ ):
668
+ raise ValueError(
669
+ "forecast audit ranking observed eligible outcomes"
670
+ )
671
+ raw_recommended = ranking.get("recommended_action_sha256s")
672
+ raw_eligible = ranking.get("eligible_action_sha256s")
673
+ raw_scores = ranking.get("scores")
674
+ if (
675
+ type(raw_recommended) is not list
676
+ or type(raw_eligible) is not list
677
+ or type(raw_scores) is not list
678
+ ):
679
+ raise TypeError("opportunity ranking is incomplete")
680
+ recommended = set(raw_recommended)
681
+ eligible = tuple(raw_eligible)
682
+ if (
683
+ len(recommended) != len(raw_recommended)
684
+ or eligible != tuple(sorted(set(eligible)))
685
+ or not recommended <= set(eligible)
686
+ ):
687
+ raise ValueError("opportunity ranking support is not canonical")
688
+ grouped: dict[str, list[str]] = {}
689
+ seen_scores: set[str] = set()
690
+ for raw_score in raw_scores:
691
+ if type(raw_score) is not dict:
692
+ raise TypeError("opportunity score must be an exact object")
693
+ action_sha256 = raw_score.get("action_sha256")
694
+ if type(action_sha256) is not str:
695
+ raise TypeError("opportunity score lacks an action identity")
696
+ require_sha256(action_sha256, "opportunity action_sha256")
697
+ if (
698
+ action_sha256 in seen_scores
699
+ or action_sha256 not in set(eligible)
700
+ ):
701
+ raise ValueError(
702
+ "opportunity scores differ from eligible support"
703
+ )
704
+ seen_scores.add(action_sha256)
705
+ if (
706
+ action_sha256 == legacy_action_sha256
707
+ or action_sha256 in prefix
708
+ or action_sha256 not in action_by_sha256
709
+ ):
710
+ continue
711
+ stratum = cls._score_stratum(
712
+ score=raw_score,
713
+ recommended_action_sha256s=recommended,
714
+ )
715
+ grouped.setdefault(stratum, []).append(action_sha256)
716
+ if seen_scores != set(eligible):
717
+ raise ValueError(
718
+ "opportunity scores do not cover eligible support"
719
+ )
720
+ return tuple(
721
+ sorted(
722
+ (
723
+ stratum,
724
+ tuple(sorted(action_sha256s)),
725
+ )
726
+ for stratum, action_sha256s in grouped.items()
727
+ if action_sha256s
728
+ )
729
+ )
730
+
731
+ def design(
732
+ self,
733
+ *,
734
+ adaptive_step: int,
735
+ remaining_authoritative_slots_after_decision: int,
736
+ decision: AdaptiveActionRacingDecision,
737
+ fallback: AdaptiveActionRacingDecision,
738
+ actions: tuple[AdaptiveActionDescriptor, ...],
739
+ ) -> SamePrefixPairedAuditPlan | None:
740
+ """Freeze a propensity-logged audit at one rotated position."""
741
+
742
+ self.__post_init__()
743
+ if type(adaptive_step) is not int or adaptive_step <= 0:
744
+ raise ValueError("adaptive_step must be positive")
745
+ if (
746
+ type(remaining_authoritative_slots_after_decision) is not int
747
+ or remaining_authoritative_slots_after_decision < 0
748
+ ):
749
+ raise ValueError(
750
+ "remaining_authoritative_slots_after_decision must be "
751
+ "non-negative"
752
+ )
753
+ if type(decision) is not AdaptiveActionRacingDecision:
754
+ raise TypeError("decision must be exact")
755
+ if type(fallback) is not AdaptiveActionRacingDecision:
756
+ raise TypeError("fallback must be exact")
757
+ decision.__post_init__()
758
+ fallback.__post_init__()
759
+ if (
760
+ decision.wave is AdaptiveActionWave.DIAGNOSTIC
761
+ or fallback.wave is AdaptiveActionWave.DIAGNOSTIC
762
+ or decision.wave is not fallback.wave
763
+ or len(decision.selected_action_sha256s) != 1
764
+ or len(fallback.selected_action_sha256s) != 1
765
+ ):
766
+ raise ValueError(
767
+ "forecast-stratified audit requires one continuation action"
768
+ )
769
+ if (
770
+ decision.residual_request_sha256
771
+ != fallback.residual_request_sha256
772
+ or decision.prior_selected_action_sha256s
773
+ != fallback.prior_selected_action_sha256s
774
+ or decision.observed_outcome_sha256s
775
+ != fallback.observed_outcome_sha256s
776
+ or decision.observed_set_outcome_sha256s
777
+ != fallback.observed_set_outcome_sha256s
778
+ ):
779
+ raise ValueError("forecast challenger and fallback cutoffs differ")
780
+ total_continuation_count = (
781
+ adaptive_step
782
+ + remaining_authoritative_slots_after_decision
783
+ )
784
+ position_draw = _stable_unit_interval(
785
+ self.random_seed,
786
+ decision.residual_request_sha256,
787
+ "forecast_stratified_audit_position",
788
+ total_continuation_count,
789
+ )
790
+ target_adaptive_step = 1 + min(
791
+ int(position_draw * total_continuation_count),
792
+ total_continuation_count - 1,
793
+ )
794
+ if adaptive_step != target_adaptive_step:
795
+ return None
796
+
797
+ action_by_sha256 = self._validate_action_market(actions)
798
+ prefix = set(decision.prior_selected_action_sha256s)
799
+ authoritative_action_sha256 = (
800
+ decision.selected_action_sha256s[0]
801
+ )
802
+ legacy_action_sha256 = fallback.selected_action_sha256s[0]
803
+ if (
804
+ not prefix
805
+ or not prefix.issubset(action_by_sha256)
806
+ or authoritative_action_sha256 not in action_by_sha256
807
+ or legacy_action_sha256 not in action_by_sha256
808
+ or authoritative_action_sha256 in prefix
809
+ or legacy_action_sha256 in prefix
810
+ ):
811
+ raise ValueError(
812
+ "forecast audit arms are outside the open market"
813
+ )
814
+ # One authoritative action and one quarantined shadow must leave
815
+ # enough distinct actions for every remaining authoritative slot.
816
+ if (
817
+ len(action_by_sha256) - len(prefix)
818
+ < remaining_authoritative_slots_after_decision + 2
819
+ ):
820
+ return None
821
+ evidence = thaw_json(decision.evidence)
822
+ if (
823
+ evidence.get("fallback_preserved_on_abstention") is not True
824
+ or evidence.get("eligible_candidate_outcomes_observed") is not False
825
+ or evidence.get("fallback_decision")
826
+ != fallback.to_record(include_evidence=True)
827
+ ):
828
+ raise ValueError(
829
+ "decision lacks the protected forecast-opportunity contract"
830
+ )
831
+ selection_source = evidence.get("selection_source")
832
+ if selection_source not in {
833
+ "current_prefix_forecast_opportunity",
834
+ "protected_fallback",
835
+ }:
836
+ raise ValueError("decision has an unknown selection source")
837
+ if (
838
+ selection_source == "protected_fallback"
839
+ and authoritative_action_sha256 != legacy_action_sha256
840
+ ):
841
+ raise ValueError(
842
+ "protected fallback source changed the fallback action"
843
+ )
844
+ strata = self._read_forecast_strata(
845
+ evidence=evidence,
846
+ action_by_sha256=action_by_sha256,
847
+ prefix=prefix,
848
+ legacy_action_sha256=legacy_action_sha256,
849
+ )
850
+ if not strata:
851
+ return None
852
+ stratum_by_action = {
853
+ action_sha256: stratum
854
+ for stratum, action_sha256s in strata
855
+ for action_sha256 in action_sha256s
856
+ }
857
+ reused_challenger = (
858
+ authoritative_action_sha256 != legacy_action_sha256
859
+ )
860
+ stratum_draw: float | None = None
861
+ action_draw: float | None = None
862
+ selected_stratum_index: int
863
+ selected_action_index: int
864
+ if reused_challenger:
865
+ stratum = stratum_by_action.get(
866
+ authoritative_action_sha256
867
+ )
868
+ if stratum is None:
869
+ raise ValueError(
870
+ "forecast challenger is outside forecast audit support"
871
+ )
872
+ selected_stratum_index = tuple(
873
+ value[0] for value in strata
874
+ ).index(stratum)
875
+ selected_actions = strata[selected_stratum_index][1]
876
+ selected_action_index = selected_actions.index(
877
+ authoritative_action_sha256
878
+ )
879
+ exploration_action_sha256 = authoritative_action_sha256
880
+ exploration_propensity = 1.0
881
+ else:
882
+ stratum_draw = _stable_unit_interval(
883
+ self.random_seed,
884
+ decision.residual_request_sha256,
885
+ decision.decision_sha256,
886
+ "forecast_stratified_audit_stratum",
887
+ [
888
+ [stratum, list(action_sha256s)]
889
+ for stratum, action_sha256s in strata
890
+ ],
891
+ )
892
+ selected_stratum_index = min(
893
+ int(stratum_draw * len(strata)),
894
+ len(strata) - 1,
895
+ )
896
+ selected_actions = strata[selected_stratum_index][1]
897
+ action_draw = _stable_unit_interval(
898
+ self.random_seed,
899
+ decision.residual_request_sha256,
900
+ decision.decision_sha256,
901
+ "forecast_stratified_audit_action",
902
+ strata[selected_stratum_index][0],
903
+ list(selected_actions),
904
+ )
905
+ selected_action_index = min(
906
+ int(action_draw * len(selected_actions)),
907
+ len(selected_actions) - 1,
908
+ )
909
+ exploration_action_sha256 = selected_actions[
910
+ selected_action_index
911
+ ]
912
+ exploration_propensity = (
913
+ 1.0 / len(strata) / len(selected_actions)
914
+ )
915
+ exploration_stratum = strata[selected_stratum_index][0]
916
+ if exploration_action_sha256 == legacy_action_sha256:
917
+ raise RuntimeError("forecast audit arms unexpectedly coincide")
918
+ authoritative_arm = (
919
+ SamePrefixPairedAuditArm.EXPLORATION
920
+ if reused_challenger
921
+ else SamePrefixPairedAuditArm.LEGACY
922
+ )
923
+ distinct_support = tuple(
924
+ sorted(
925
+ action_sha256
926
+ for _, action_sha256s in strata
927
+ for action_sha256 in action_sha256s
928
+ )
929
+ )
930
+ ranking = evidence["opportunity_ranking"]
931
+ if type(ranking) is not dict:
932
+ raise TypeError("decision lacks an opportunity ranking")
933
+ ranking_sha256 = ranking.get("ranking_sha256")
934
+ if type(ranking_sha256) is not str:
935
+ raise TypeError("opportunity ranking lacks its identity")
936
+ require_sha256(ranking_sha256, "opportunity ranking_sha256")
937
+ return SamePrefixPairedAuditPlan(
938
+ designer_id=self.designer_id,
939
+ designer_version=self.designer_version,
940
+ designer_definition_sha256=self.definition_sha256,
941
+ residual_request_sha256=decision.residual_request_sha256,
942
+ racing_decision_sha256=decision.decision_sha256,
943
+ common_prefix_action_sha256s=(
944
+ decision.prior_selected_action_sha256s
945
+ ),
946
+ authoritative_arm=authoritative_arm,
947
+ authoritative_action_sha256=authoritative_action_sha256,
948
+ legacy_action_sha256=legacy_action_sha256,
949
+ exploration_action_sha256=exploration_action_sha256,
950
+ exploration_stratum_key=(
951
+ "forecast_geometry",
952
+ exploration_stratum,
953
+ ),
954
+ distinct_exploration_support_action_sha256s=(
955
+ distinct_support
956
+ ),
957
+ exploration_selection_propensity=float(
958
+ exploration_propensity
959
+ ),
960
+ evidence=freeze_json(
961
+ {
962
+ "adaptive_step": adaptive_step,
963
+ "total_continuation_count": (
964
+ total_continuation_count
965
+ ),
966
+ "target_adaptive_step": target_adaptive_step,
967
+ "remaining_authoritative_slots_after_decision": (
968
+ remaining_authoritative_slots_after_decision
969
+ ),
970
+ "position_draw_hex": position_draw.hex(),
971
+ "selection_source": selection_source,
972
+ "fallback_decision_sha256": (
973
+ fallback.decision_sha256
974
+ ),
975
+ "opportunity_ranking_sha256": ranking_sha256,
976
+ "strata": [
977
+ {
978
+ "stratum": stratum,
979
+ "action_sha256s": list(action_sha256s),
980
+ "conditional_stratum_propensity_hex": (
981
+ (1.0 / len(strata)).hex()
982
+ ),
983
+ "conditional_action_propensity_hex": (
984
+ (1.0 / len(action_sha256s)).hex()
985
+ ),
986
+ }
987
+ for stratum, action_sha256s in strata
988
+ ],
989
+ "stratum_draw_hex": (
990
+ None
991
+ if stratum_draw is None
992
+ else stratum_draw.hex()
993
+ ),
994
+ "action_draw_hex": (
995
+ None
996
+ if action_draw is None
997
+ else action_draw.hex()
998
+ ),
999
+ "selected_stratum_index": (
1000
+ selected_stratum_index
1001
+ ),
1002
+ "selected_action_index": selected_action_index,
1003
+ "challenger_reused": reused_challenger,
1004
+ "authoritative_semantic_role": (
1005
+ "forecast_opportunity_challenger"
1006
+ if reused_challenger
1007
+ else "protected_fallback"
1008
+ ),
1009
+ "counterfactual_semantic_role": (
1010
+ "protected_fallback"
1011
+ if reused_challenger
1012
+ else "forecast_stratum_action"
1013
+ ),
1014
+ "current_arm_outcomes_observed": False,
1015
+ "plan_must_be_committed_before_arm_evaluation": True,
1016
+ "counterfactual_action_must_be_quarantined": True,
1017
+ "assay_union_may_enter_authoritative_archive": False,
1018
+ }
1019
+ ),
1020
+ )
1021
+
1022
+
1023
+ @dataclass(frozen=True, slots=True)
1024
+ class FactorStratifiedSamePrefixPairedAuditDesigner:
1025
+ """Choose one distinct exploration arm from a v6 frozen audit support."""
1026
+
1027
+ random_seed: int = 0
1028
+ designer_id: str = SAME_PREFIX_PAIRED_AUDIT_DESIGNER_ID
1029
+ designer_version: int = SAME_PREFIX_PAIRED_AUDIT_DESIGNER_VERSION
1030
+ definition_sha256: str = field(init=False)
1031
+
1032
+ def __post_init__(self) -> None:
1033
+ if type(self.random_seed) is not int or self.random_seed < 0:
1034
+ raise ValueError("random_seed must be non-negative")
1035
+ if self.designer_id != SAME_PREFIX_PAIRED_AUDIT_DESIGNER_ID:
1036
+ raise ValueError("designer_id is immutable")
1037
+ if (
1038
+ self.designer_version
1039
+ != SAME_PREFIX_PAIRED_AUDIT_DESIGNER_VERSION
1040
+ ):
1041
+ raise ValueError("designer_version is immutable")
1042
+ object.__setattr__(
1043
+ self,
1044
+ "definition_sha256",
1045
+ _hash(
1046
+ _DESIGNER_DEFINITION_DOMAIN,
1047
+ {
1048
+ "schema_version": 1,
1049
+ "designer_id": self.designer_id,
1050
+ "designer_version": self.designer_version,
1051
+ "random_seed": self.random_seed,
1052
+ "input": (
1053
+ "authenticated-v6-decision-and-portable-action-market"
1054
+ ),
1055
+ "legacy_arm": "frozen-v6-legacy-audit-anchor",
1056
+ "exploration_arm": (
1057
+ "uniform-nonempty-stratum-then-uniform-action-"
1058
+ "conditioned-distinct-from-legacy"
1059
+ ),
1060
+ "current_arm_outcomes_observed": False,
1061
+ "assay_union_may_enter_authoritative_archive": False,
1062
+ "workload_objective_model_provider_prompt_config_branches": (
1063
+ False
1064
+ ),
1065
+ },
1066
+ ),
1067
+ )
1068
+
1069
+ @staticmethod
1070
+ def _read_strata(
1071
+ *,
1072
+ evidence: dict[str, object],
1073
+ action_by_sha256: dict[str, AdaptiveActionDescriptor],
1074
+ prefix: set[str],
1075
+ legacy_action_sha256: str,
1076
+ ) -> tuple[tuple[tuple[str, ...], tuple[str, ...]], ...]:
1077
+ raw_strata = evidence.get("audit_strata")
1078
+ if type(raw_strata) is not list or not raw_strata:
1079
+ raise ValueError("v6 decision does not expose audit strata")
1080
+ strata: list[tuple[tuple[str, ...], tuple[str, ...]]] = []
1081
+ seen_actions: set[str] = set()
1082
+ for raw_stratum in raw_strata:
1083
+ if type(raw_stratum) is not dict:
1084
+ raise TypeError("audit stratum must be an exact object")
1085
+ raw_key = raw_stratum.get("stratum_key")
1086
+ raw_actions = raw_stratum.get("action_sha256s")
1087
+ if (
1088
+ type(raw_key) is not list
1089
+ or not raw_key
1090
+ or type(raw_actions) is not list
1091
+ or not raw_actions
1092
+ ):
1093
+ raise ValueError("audit stratum is incomplete")
1094
+ key = tuple(raw_key)
1095
+ for value in key:
1096
+ _require_token(value, name="audit stratum level")
1097
+ action_sha256s = tuple(sorted(set(raw_actions)))
1098
+ if len(action_sha256s) != len(raw_actions):
1099
+ raise ValueError("audit stratum repeats an action")
1100
+ for value in action_sha256s:
1101
+ require_sha256(value, "audit stratum action_sha256")
1102
+ if value not in action_by_sha256:
1103
+ raise ValueError(
1104
+ "audit stratum action is outside the frozen market"
1105
+ )
1106
+ if value in prefix:
1107
+ raise ValueError(
1108
+ "audit stratum action is already in the prefix"
1109
+ )
1110
+ if value in seen_actions:
1111
+ raise ValueError(
1112
+ "audit action appears in multiple strata"
1113
+ )
1114
+ seen_actions.add(value)
1115
+ distinct_actions = tuple(
1116
+ value
1117
+ for value in action_sha256s
1118
+ if value != legacy_action_sha256
1119
+ )
1120
+ if distinct_actions:
1121
+ strata.append((key, distinct_actions))
1122
+ if not strata:
1123
+ raise ValueError(
1124
+ "paired audit has no exploration action distinct from legacy"
1125
+ )
1126
+ return tuple(sorted(strata))
1127
+
1128
+ def design(
1129
+ self,
1130
+ *,
1131
+ decision: AdaptiveActionRacingDecision,
1132
+ actions: tuple[AdaptiveActionDescriptor, ...],
1133
+ ) -> SamePrefixPairedAuditPlan:
1134
+ """Freeze two distinct arms without accepting either arm's outcome."""
1135
+
1136
+ self.__post_init__()
1137
+ if type(decision) is not AdaptiveActionRacingDecision:
1138
+ raise TypeError("decision must be exact")
1139
+ decision.__post_init__()
1140
+ if (
1141
+ decision.policy_id != OUTCOME_ADAPTIVE_ACTION_RACING_POLICY_ID
1142
+ or decision.policy_version
1143
+ != OUTCOME_ADAPTIVE_ACTION_RACING_STRATIFIED_AUDIT_POLICY_VERSION
1144
+ or decision.wave is not AdaptiveActionWave.RANDOMIZED_AUDIT
1145
+ or len(decision.selected_action_sha256s) != 1
1146
+ ):
1147
+ raise ValueError(
1148
+ "paired audit requires one final factor-stratified v6 decision"
1149
+ )
1150
+ if type(actions) is not tuple or not actions:
1151
+ raise ValueError("actions must be a non-empty exact tuple")
1152
+ action_by_sha256: dict[str, AdaptiveActionDescriptor] = {}
1153
+ for value in actions:
1154
+ if type(value) is not AdaptiveActionDescriptor:
1155
+ raise TypeError("actions must contain exact descriptors")
1156
+ value.__post_init__()
1157
+ if value.action_sha256 in action_by_sha256:
1158
+ raise ValueError("actions repeat an identity")
1159
+ action_by_sha256[value.action_sha256] = value
1160
+ prefix = set(decision.prior_selected_action_sha256s)
1161
+ if not prefix.issubset(action_by_sha256):
1162
+ raise ValueError("decision prefix is outside the frozen market")
1163
+ evidence = thaw_json(decision.evidence)
1164
+ if (
1165
+ evidence.get("risk_controlled_stratified_audit") is not True
1166
+ or evidence.get("candidate_factor_cells_outcome_blind") is not True
1167
+ ):
1168
+ raise ValueError("decision lacks the v6 outcome-blind audit contract")
1169
+ legacy_action_sha256 = evidence.get(
1170
+ "legacy_audit_anchor_action_sha256"
1171
+ )
1172
+ if type(legacy_action_sha256) is not str:
1173
+ raise TypeError("decision lacks a legacy audit anchor")
1174
+ require_sha256(
1175
+ legacy_action_sha256,
1176
+ "legacy_audit_anchor_action_sha256",
1177
+ )
1178
+ if (
1179
+ legacy_action_sha256 not in action_by_sha256
1180
+ or legacy_action_sha256 in prefix
1181
+ ):
1182
+ raise ValueError("legacy audit anchor is outside the remaining market")
1183
+ authoritative_action_sha256 = decision.selected_action_sha256s[0]
1184
+ if (
1185
+ authoritative_action_sha256 not in action_by_sha256
1186
+ or authoritative_action_sha256 in prefix
1187
+ ):
1188
+ raise ValueError(
1189
+ "authoritative audit action is outside the remaining market"
1190
+ )
1191
+ strata = self._read_strata(
1192
+ evidence=evidence,
1193
+ action_by_sha256=action_by_sha256,
1194
+ prefix=prefix,
1195
+ legacy_action_sha256=legacy_action_sha256,
1196
+ )
1197
+ authoritative_is_distinct_exploration = (
1198
+ evidence.get("audit_exploration_branch") is True
1199
+ and authoritative_action_sha256 != legacy_action_sha256
1200
+ )
1201
+ selected_stratum_index: int | None = None
1202
+ selected_action_index: int | None = None
1203
+ stratum_draw: float | None = None
1204
+ action_draw: float | None = None
1205
+ if authoritative_is_distinct_exploration:
1206
+ for stratum_index, (_, stratum_actions) in enumerate(strata):
1207
+ if authoritative_action_sha256 in stratum_actions:
1208
+ selected_stratum_index = stratum_index
1209
+ selected_action_index = stratum_actions.index(
1210
+ authoritative_action_sha256
1211
+ )
1212
+ break
1213
+ if selected_stratum_index is None:
1214
+ raise ValueError(
1215
+ "selected exploration action is outside distinct support"
1216
+ )
1217
+ else:
1218
+ stratum_draw = _stable_unit_interval(
1219
+ self.random_seed,
1220
+ decision.residual_request_sha256,
1221
+ decision.decision_sha256,
1222
+ "paired_audit_distinct_stratum",
1223
+ [
1224
+ [list(key), list(stratum_actions)]
1225
+ for key, stratum_actions in strata
1226
+ ],
1227
+ )
1228
+ selected_stratum_index = min(
1229
+ int(stratum_draw * len(strata)),
1230
+ len(strata) - 1,
1231
+ )
1232
+ selected_key, selected_actions = strata[selected_stratum_index]
1233
+ action_draw = _stable_unit_interval(
1234
+ self.random_seed,
1235
+ decision.residual_request_sha256,
1236
+ decision.decision_sha256,
1237
+ "paired_audit_distinct_action",
1238
+ list(selected_key),
1239
+ list(selected_actions),
1240
+ )
1241
+ selected_action_index = min(
1242
+ int(action_draw * len(selected_actions)),
1243
+ len(selected_actions) - 1,
1244
+ )
1245
+ if selected_stratum_index is None or selected_action_index is None:
1246
+ raise RuntimeError("paired audit did not resolve one exploration arm")
1247
+ exploration_stratum_key, stratum_actions = strata[
1248
+ selected_stratum_index
1249
+ ]
1250
+ exploration_action_sha256 = stratum_actions[selected_action_index]
1251
+ exploration_propensity = 1.0 / len(strata) / len(stratum_actions)
1252
+ authoritative_arm = (
1253
+ SamePrefixPairedAuditArm.LEGACY
1254
+ if authoritative_action_sha256 == legacy_action_sha256
1255
+ else SamePrefixPairedAuditArm.EXPLORATION
1256
+ )
1257
+ distinct_support = tuple(
1258
+ sorted(
1259
+ value
1260
+ for _, stratum_actions in strata
1261
+ for value in stratum_actions
1262
+ )
1263
+ )
1264
+ return SamePrefixPairedAuditPlan(
1265
+ designer_id=self.designer_id,
1266
+ designer_version=self.designer_version,
1267
+ designer_definition_sha256=self.definition_sha256,
1268
+ residual_request_sha256=decision.residual_request_sha256,
1269
+ racing_decision_sha256=decision.decision_sha256,
1270
+ common_prefix_action_sha256s=(
1271
+ decision.prior_selected_action_sha256s
1272
+ ),
1273
+ authoritative_arm=authoritative_arm,
1274
+ authoritative_action_sha256=authoritative_action_sha256,
1275
+ legacy_action_sha256=legacy_action_sha256,
1276
+ exploration_action_sha256=exploration_action_sha256,
1277
+ exploration_stratum_key=exploration_stratum_key,
1278
+ distinct_exploration_support_action_sha256s=distinct_support,
1279
+ exploration_selection_propensity=float(
1280
+ exploration_propensity
1281
+ ),
1282
+ evidence=freeze_json(
1283
+ {
1284
+ "source_racing_decision": decision.to_record(
1285
+ include_evidence=False
1286
+ ),
1287
+ "source_audit_exploration_branch": evidence.get(
1288
+ "audit_exploration_branch"
1289
+ ),
1290
+ "source_audit_branch_draw_hex": evidence.get(
1291
+ "audit_branch_draw_hex"
1292
+ ),
1293
+ "conditioned_distinct_from_legacy": True,
1294
+ "distinct_strata": [
1295
+ {
1296
+ "stratum_key": list(key),
1297
+ "action_sha256s": list(stratum_actions),
1298
+ "conditional_action_propensity_hex": (
1299
+ (1.0 / len(stratum_actions)).hex()
1300
+ ),
1301
+ }
1302
+ for key, stratum_actions in strata
1303
+ ],
1304
+ "stratum_draw_hex": (
1305
+ None
1306
+ if stratum_draw is None
1307
+ else stratum_draw.hex()
1308
+ ),
1309
+ "action_draw_hex": (
1310
+ None
1311
+ if action_draw is None
1312
+ else action_draw.hex()
1313
+ ),
1314
+ "selected_stratum_index": selected_stratum_index,
1315
+ "selected_action_index": selected_action_index,
1316
+ "exploration_selection_propensity_hex": (
1317
+ exploration_propensity.hex()
1318
+ ),
1319
+ "authoritative_action_reused_when_exploration": (
1320
+ authoritative_is_distinct_exploration
1321
+ ),
1322
+ "current_arm_outcomes_observed": False,
1323
+ "plan_must_be_committed_before_arm_evaluation": True,
1324
+ "assay_union_may_enter_authoritative_archive": False,
1325
+ }
1326
+ ),
1327
+ )
1328
+
1329
+
1330
+ @dataclass(frozen=True, slots=True)
1331
+ class SamePrefixPairedAuditObservation:
1332
+ """Two independently valued arms joined to one frozen common prefix."""
1333
+
1334
+ plan: SamePrefixPairedAuditPlan
1335
+ legacy_outcome: AdaptiveActionOutcome
1336
+ exploration_outcome: AdaptiveActionOutcome
1337
+ legacy_set_outcome: AdaptiveActionSetOutcome
1338
+ exploration_set_outcome: AdaptiveActionSetOutcome
1339
+ adjudicator_id: str
1340
+ adjudicator_version: int
1341
+ adjudicator_definition_sha256: str
1342
+ observation_sha256: str = field(init=False)
1343
+
1344
+ def __post_init__(self) -> None:
1345
+ if type(self.plan) is not SamePrefixPairedAuditPlan:
1346
+ raise TypeError("plan must be exact")
1347
+ self.plan.__post_init__()
1348
+ for value, name in (
1349
+ (self.legacy_outcome, "legacy_outcome"),
1350
+ (self.exploration_outcome, "exploration_outcome"),
1351
+ ):
1352
+ if type(value) is not AdaptiveActionOutcome:
1353
+ raise TypeError(f"{name} must be exact")
1354
+ value.__post_init__()
1355
+ for value, name in (
1356
+ (self.legacy_set_outcome, "legacy_set_outcome"),
1357
+ (self.exploration_set_outcome, "exploration_set_outcome"),
1358
+ ):
1359
+ if type(value) is not AdaptiveActionSetOutcome:
1360
+ raise TypeError(f"{name} must be exact")
1361
+ value.__post_init__()
1362
+ if (
1363
+ self.legacy_outcome.action_sha256
1364
+ != self.plan.legacy_action_sha256
1365
+ or self.exploration_outcome.action_sha256
1366
+ != self.plan.exploration_action_sha256
1367
+ ):
1368
+ raise ValueError("arm outcome does not match the frozen plan")
1369
+ expected_prefix = set(self.plan.common_prefix_action_sha256s)
1370
+ prior_bindings = self.legacy_set_outcome.prior_action_evaluation_bindings
1371
+ if (
1372
+ prior_bindings
1373
+ != self.exploration_set_outcome.prior_action_evaluation_bindings
1374
+ or {value[0] for value in prior_bindings} != expected_prefix
1375
+ ):
1376
+ raise ValueError("paired arms do not share the exact common prefix")
1377
+ if not math.isclose(
1378
+ self.legacy_set_outcome.prior_selected_set_gain,
1379
+ self.exploration_set_outcome.prior_selected_set_gain,
1380
+ rel_tol=1e-12,
1381
+ abs_tol=1e-15,
1382
+ ):
1383
+ raise ValueError("paired arms disagree on common-prefix utility")
1384
+ expected_current = (
1385
+ (
1386
+ self.plan.legacy_action_sha256,
1387
+ self.legacy_outcome.evaluation_sha256,
1388
+ ),
1389
+ )
1390
+ if self.legacy_set_outcome.current_action_evaluation_bindings != (
1391
+ expected_current
1392
+ ):
1393
+ raise ValueError("legacy set outcome does not join its evaluation")
1394
+ expected_current = (
1395
+ (
1396
+ self.plan.exploration_action_sha256,
1397
+ self.exploration_outcome.evaluation_sha256,
1398
+ ),
1399
+ )
1400
+ if (
1401
+ self.exploration_set_outcome.current_action_evaluation_bindings
1402
+ != expected_current
1403
+ ):
1404
+ raise ValueError(
1405
+ "exploration set outcome does not join its evaluation"
1406
+ )
1407
+ _require_token(self.adjudicator_id, name="adjudicator_id")
1408
+ if (
1409
+ type(self.adjudicator_version) is not int
1410
+ or self.adjudicator_version <= 0
1411
+ ):
1412
+ raise ValueError("adjudicator_version must be positive")
1413
+ require_sha256(
1414
+ self.adjudicator_definition_sha256,
1415
+ "adjudicator_definition_sha256",
1416
+ )
1417
+ object.__setattr__(
1418
+ self,
1419
+ "observation_sha256",
1420
+ _hash(_OBSERVATION_DOMAIN, self._unsigned_record()),
1421
+ )
1422
+
1423
+ @property
1424
+ def conditional_gain_delta(self) -> float:
1425
+ return (
1426
+ self.exploration_set_outcome.conditional_set_gain
1427
+ - self.legacy_set_outcome.conditional_set_gain
1428
+ )
1429
+
1430
+ @property
1431
+ def winner(self) -> SamePrefixPairedAuditWinner:
1432
+ delta = self.conditional_gain_delta
1433
+ if math.isclose(delta, 0.0, rel_tol=1e-12, abs_tol=1e-15):
1434
+ return SamePrefixPairedAuditWinner.TIE
1435
+ if delta > 0.0:
1436
+ return SamePrefixPairedAuditWinner.EXPLORATION
1437
+ return SamePrefixPairedAuditWinner.LEGACY
1438
+
1439
+ @property
1440
+ def authoritative_set_outcome(self) -> AdaptiveActionSetOutcome:
1441
+ if self.plan.authoritative_arm is SamePrefixPairedAuditArm.LEGACY:
1442
+ return self.legacy_set_outcome
1443
+ return self.exploration_set_outcome
1444
+
1445
+ def _unsigned_record(self) -> dict[str, object]:
1446
+ return {
1447
+ "schema_version": 1,
1448
+ "adjudicator": {
1449
+ "adjudicator_id": self.adjudicator_id,
1450
+ "adjudicator_version": self.adjudicator_version,
1451
+ "definition_sha256": self.adjudicator_definition_sha256,
1452
+ },
1453
+ "plan_sha256": self.plan.plan_sha256,
1454
+ "legacy_outcome_sha256": self.legacy_outcome.outcome_sha256,
1455
+ "exploration_outcome_sha256": (
1456
+ self.exploration_outcome.outcome_sha256
1457
+ ),
1458
+ "legacy_set_outcome_sha256": (
1459
+ self.legacy_set_outcome.set_outcome_sha256
1460
+ ),
1461
+ "exploration_set_outcome_sha256": (
1462
+ self.exploration_set_outcome.set_outcome_sha256
1463
+ ),
1464
+ "common_prefix_selected_set_gain_hex": (
1465
+ self.legacy_set_outcome.prior_selected_set_gain.hex()
1466
+ ),
1467
+ "legacy_conditional_gain_hex": (
1468
+ self.legacy_set_outcome.conditional_set_gain.hex()
1469
+ ),
1470
+ "exploration_conditional_gain_hex": (
1471
+ self.exploration_set_outcome.conditional_set_gain.hex()
1472
+ ),
1473
+ "conditional_gain_delta_hex": (
1474
+ self.conditional_gain_delta.hex()
1475
+ ),
1476
+ "winner": self.winner.value,
1477
+ "authoritative_arm": self.plan.authoritative_arm.value,
1478
+ "authoritative_set_outcome_sha256": (
1479
+ self.authoritative_set_outcome.set_outcome_sha256
1480
+ ),
1481
+ "assay_union_admitted_to_authoritative_archive": False,
1482
+ "counterfactual_endpoints_share_one_prefix": True,
1483
+ "workload_objective_model_provider_prompt_config_branches": False,
1484
+ }
1485
+
1486
+ def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
1487
+ self.__post_init__()
1488
+ return {
1489
+ **self._unsigned_record(),
1490
+ "plan": self.plan.to_record(include_evidence=include_evidence),
1491
+ "legacy_outcome": self.legacy_outcome.to_record(),
1492
+ "exploration_outcome": self.exploration_outcome.to_record(),
1493
+ "legacy_set_outcome": self.legacy_set_outcome.to_record(),
1494
+ "exploration_set_outcome": (
1495
+ self.exploration_set_outcome.to_record()
1496
+ ),
1497
+ "observation_sha256": self.observation_sha256,
1498
+ }
1499
+
1500
+
1501
+ @dataclass(frozen=True, slots=True)
1502
+ class SamePrefixPairedAuditAdjudicator:
1503
+ """Build one workload-opaque observation from real arm outcomes."""
1504
+
1505
+ adjudicator_id: str = SAME_PREFIX_PAIRED_AUDIT_ADJUDICATOR_ID
1506
+ adjudicator_version: int = SAME_PREFIX_PAIRED_AUDIT_ADJUDICATOR_VERSION
1507
+ definition_sha256: str = field(init=False)
1508
+
1509
+ def __post_init__(self) -> None:
1510
+ if self.adjudicator_id != SAME_PREFIX_PAIRED_AUDIT_ADJUDICATOR_ID:
1511
+ raise ValueError("adjudicator_id is immutable")
1512
+ if (
1513
+ self.adjudicator_version
1514
+ != SAME_PREFIX_PAIRED_AUDIT_ADJUDICATOR_VERSION
1515
+ ):
1516
+ raise ValueError("adjudicator_version is immutable")
1517
+ object.__setattr__(
1518
+ self,
1519
+ "definition_sha256",
1520
+ _hash(
1521
+ _ADJUDICATOR_DEFINITION_DOMAIN,
1522
+ {
1523
+ "schema_version": 1,
1524
+ "adjudicator_id": self.adjudicator_id,
1525
+ "adjudicator_version": self.adjudicator_version,
1526
+ "comparison": (
1527
+ "conditional-set-gain-at-identical-prior-bindings"
1528
+ ),
1529
+ "assay_union_admitted_to_authoritative_archive": False,
1530
+ "workload_objective_model_provider_prompt_config_branches": (
1531
+ False
1532
+ ),
1533
+ },
1534
+ ),
1535
+ )
1536
+
1537
+ def adjudicate(
1538
+ self,
1539
+ *,
1540
+ plan: SamePrefixPairedAuditPlan,
1541
+ legacy_outcome: AdaptiveActionOutcome,
1542
+ exploration_outcome: AdaptiveActionOutcome,
1543
+ legacy_set_outcome: AdaptiveActionSetOutcome,
1544
+ exploration_set_outcome: AdaptiveActionSetOutcome,
1545
+ ) -> SamePrefixPairedAuditObservation:
1546
+ self.__post_init__()
1547
+ return SamePrefixPairedAuditObservation(
1548
+ plan=plan,
1549
+ legacy_outcome=legacy_outcome,
1550
+ exploration_outcome=exploration_outcome,
1551
+ legacy_set_outcome=legacy_set_outcome,
1552
+ exploration_set_outcome=exploration_set_outcome,
1553
+ adjudicator_id=self.adjudicator_id,
1554
+ adjudicator_version=self.adjudicator_version,
1555
+ adjudicator_definition_sha256=self.definition_sha256,
1556
+ )
1557
+
1558
+
1559
+ __all__ = [
1560
+ "FactorStratifiedSamePrefixPairedAuditDesigner",
1561
+ "FORECAST_OPPORTUNITY_SAME_PREFIX_AUDIT_DESIGNER_IDS",
1562
+ "FORECAST_OPPORTUNITY_SAME_PREFIX_SHADOW_DESIGNER_ID",
1563
+ "FORECAST_OPPORTUNITY_SAME_PREFIX_SHADOW_DESIGNER_VERSION",
1564
+ "FORECAST_STRATIFIED_SAME_PREFIX_AUDIT_DESIGNER_ID",
1565
+ "FORECAST_STRATIFIED_SAME_PREFIX_AUDIT_DESIGNER_VERSION",
1566
+ "ForecastOpportunitySamePrefixAuditDesignerPort",
1567
+ "ForecastOpportunitySamePrefixShadowDesigner",
1568
+ "ForecastOpportunitySamePrefixShadowDesignerPort",
1569
+ "ForecastStratifiedSamePrefixAuditDesigner",
1570
+ "SAME_PREFIX_PAIRED_AUDIT_ADJUDICATOR_ID",
1571
+ "SAME_PREFIX_PAIRED_AUDIT_ADJUDICATOR_VERSION",
1572
+ "SAME_PREFIX_PAIRED_AUDIT_DESIGNER_ID",
1573
+ "SAME_PREFIX_PAIRED_AUDIT_DESIGNER_VERSION",
1574
+ "SamePrefixPairedAuditAdjudicator",
1575
+ "SamePrefixPairedAuditArm",
1576
+ "SamePrefixPairedAuditDesignerPort",
1577
+ "SamePrefixPairedAuditObservation",
1578
+ "SamePrefixPairedAuditPlan",
1579
+ "SamePrefixPairedAuditWinner",
1580
+ ]