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,737 @@
1
+ """Framework-free occurrence, parentage, and variation-case contracts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import re
7
+ from dataclasses import dataclass
8
+ from enum import Enum
9
+
10
+ from agent_evolve.domain.ids import CandidateId, InsightId, OperatorInvocationId
11
+ from agent_evolve.domain.insight import InsightRef
12
+ from agent_evolve.domain.patch import (
13
+ ArrayIndex,
14
+ JsonPath,
15
+ ObjectKey,
16
+ TypedPatch,
17
+ canonical_path_bytes,
18
+ require_sha256,
19
+ validate_json_path,
20
+ validate_typed_patch,
21
+ )
22
+
23
+
24
+ _OPERATOR_TOKEN = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
25
+ MAX_REQUESTED_CHILDREN = 1024
26
+ MAX_SELECTED_INSIGHTS = 1024
27
+ MAX_PRESERVATION_OBLIGATIONS = 4096
28
+ _PRESERVATION_OBLIGATION_DOMAIN = b"agent-evolve:preservation-obligation:v1\x00"
29
+
30
+
31
+ class VariationKind(str, Enum):
32
+ REPRODUCTION = "reproduction"
33
+ TYPED_MUTATION = "typed_mutation"
34
+ TWO_PARENT_CROSSOVER = "two_parent_crossover"
35
+ THREE_WAY_RECOMBINATION = "three_way_recombination"
36
+ REPAIR = "repair"
37
+
38
+
39
+ class ParentRole(str, Enum):
40
+ REPRODUCTION_SOURCE = "reproduction_source"
41
+ MUTATION_PARENT = "mutation_parent"
42
+ CROSSOVER_LEFT = "crossover_left"
43
+ CROSSOVER_RIGHT = "crossover_right"
44
+ COMMON_ANCESTOR = "common_ancestor"
45
+ REPAIR_TARGET = "repair_target"
46
+
47
+
48
+ class PreservationSource(str, Enum):
49
+ """Exact branch provenance of one factory-derived preservation obligation."""
50
+
51
+ LEFT_BRANCH = "left_branch"
52
+ RIGHT_BRANCH = "right_branch"
53
+ IDENTICAL_NEUTRAL = "identical_neutral"
54
+
55
+
56
+ class PreservationExpectation(str, Enum):
57
+ PRESENT = "present"
58
+ ABSENT = "absent"
59
+
60
+
61
+ class AbsenceContextKind(str, Enum):
62
+ OBJECT = "object"
63
+ ARRAY = "array"
64
+
65
+
66
+ class AbsenceFailureKind(str, Enum):
67
+ MISSING_OBJECT_KEY = "missing_object_key"
68
+ ARRAY_INDEX_OUT_OF_BOUNDS = "array_index_out_of_bounds"
69
+
70
+
71
+ def _validate_candidate_id(value: CandidateId, name: str) -> None:
72
+ if type(value) is not CandidateId:
73
+ raise TypeError(f"{name} must be an exact CandidateId")
74
+ CandidateId.__post_init__(value)
75
+
76
+
77
+ def _validate_operator_invocation_id(
78
+ value: OperatorInvocationId,
79
+ name: str,
80
+ ) -> None:
81
+ if type(value) is not OperatorInvocationId:
82
+ raise TypeError(f"{name} must be an exact OperatorInvocationId")
83
+ OperatorInvocationId.__post_init__(value)
84
+
85
+
86
+ @dataclass(frozen=True, slots=True, eq=False)
87
+ class CandidateOccurrence:
88
+ """One proposal occurrence, distinct even when candidate content repeats."""
89
+
90
+ candidate_id: CandidateId
91
+ configuration_hash: str
92
+ configuration_artifact_hash: str
93
+ proposal_sequence: int
94
+ operator_invocation_id: OperatorInvocationId | None = None
95
+
96
+ def __post_init__(self) -> None:
97
+ _validate_candidate_id(self.candidate_id, "candidate_id")
98
+ require_sha256(self.configuration_hash, "configuration_hash")
99
+ require_sha256(
100
+ self.configuration_artifact_hash,
101
+ "configuration_artifact_hash",
102
+ )
103
+ if type(self.proposal_sequence) is not int or self.proposal_sequence < 0:
104
+ raise ValueError("proposal_sequence must be a non-negative exact integer")
105
+ if self.operator_invocation_id is not None and type(
106
+ self.operator_invocation_id
107
+ ) is not OperatorInvocationId:
108
+ raise TypeError(
109
+ "operator_invocation_id must be an exact OperatorInvocationId or None"
110
+ )
111
+ if self.operator_invocation_id is not None:
112
+ _validate_operator_invocation_id(
113
+ self.operator_invocation_id,
114
+ "operator_invocation_id",
115
+ )
116
+
117
+ def _validated_values(self) -> tuple[str, str, str, int, str | None]:
118
+ if type(self) is not CandidateOccurrence:
119
+ raise TypeError("occurrence must be an exact CandidateOccurrence")
120
+ CandidateOccurrence.__post_init__(self)
121
+ return (
122
+ self.candidate_id.value,
123
+ self.configuration_hash,
124
+ self.configuration_artifact_hash,
125
+ self.proposal_sequence,
126
+ None
127
+ if self.operator_invocation_id is None
128
+ else self.operator_invocation_id.value,
129
+ )
130
+
131
+ def __eq__(self, other: object) -> bool:
132
+ if type(self) is not CandidateOccurrence or type(other) is not CandidateOccurrence:
133
+ return False
134
+ return self._validated_values() == other._validated_values()
135
+
136
+ __hash__ = None
137
+
138
+
139
+ @dataclass(frozen=True, slots=True, eq=False)
140
+ class VariationParent:
141
+ role: ParentRole
142
+ occurrence: CandidateOccurrence
143
+
144
+ def __post_init__(self) -> None:
145
+ if type(self.role) is not ParentRole:
146
+ raise TypeError("role must be a ParentRole")
147
+ if type(self.occurrence) is not CandidateOccurrence:
148
+ raise TypeError("occurrence must be an exact CandidateOccurrence")
149
+ CandidateOccurrence.__post_init__(self.occurrence)
150
+ if self.role is ParentRole.COMMON_ANCESTOR:
151
+ raise ValueError("common ancestors use VariationCase.common_ancestor")
152
+
153
+ def _validated_values(self) -> tuple[str, tuple[str, str, str, int, str | None]]:
154
+ if type(self) is not VariationParent:
155
+ raise TypeError("parent must be an exact VariationParent")
156
+ VariationParent.__post_init__(self)
157
+ return self.role.value, self.occurrence._validated_values()
158
+
159
+ def __eq__(self, other: object) -> bool:
160
+ if type(self) is not VariationParent or type(other) is not VariationParent:
161
+ return False
162
+ return self._validated_values() == other._validated_values()
163
+
164
+ __hash__ = None
165
+
166
+
167
+ @dataclass(frozen=True, slots=True, eq=False)
168
+ class ParentEdge:
169
+ """A verified occurrence edge carrying its exact parent-to-child patch."""
170
+
171
+ role: ParentRole
172
+ parent: CandidateOccurrence
173
+ child: CandidateOccurrence
174
+ patch: TypedPatch
175
+
176
+ def __post_init__(self) -> None:
177
+ if type(self.role) is not ParentRole:
178
+ raise TypeError("role must be a ParentRole")
179
+ if self.role is ParentRole.COMMON_ANCESTOR:
180
+ raise ValueError("COMMON_ANCESTOR is not a direct parent edge role")
181
+ if type(self.parent) is not CandidateOccurrence or type(
182
+ self.child
183
+ ) is not CandidateOccurrence:
184
+ raise TypeError("parent and child must be exact CandidateOccurrence values")
185
+ CandidateOccurrence.__post_init__(self.parent)
186
+ CandidateOccurrence.__post_init__(self.child)
187
+ if self.parent.candidate_id == self.child.candidate_id:
188
+ raise ValueError("a lineage edge cannot be self-referential")
189
+ if self.parent.proposal_sequence >= self.child.proposal_sequence:
190
+ raise ValueError("a lineage edge must point to a later proposal sequence")
191
+ validate_typed_patch(self.patch)
192
+ if (
193
+ self.patch.base_candidate_id != self.parent.candidate_id
194
+ or self.patch.target_candidate_id != self.child.candidate_id
195
+ or self.patch.base_hash != self.parent.configuration_hash
196
+ or self.patch.target_hash != self.child.configuration_hash
197
+ ):
198
+ raise ValueError("parent edge endpoints do not match its exact patch")
199
+
200
+ def __eq__(self, other: object) -> bool:
201
+ if type(self) is not ParentEdge or type(other) is not ParentEdge:
202
+ return False
203
+ ParentEdge.__post_init__(self)
204
+ ParentEdge.__post_init__(other)
205
+ return (
206
+ self.role.value,
207
+ self.parent._validated_values(),
208
+ self.child._validated_values(),
209
+ self.patch.patch_hash,
210
+ ) == (
211
+ other.role.value,
212
+ other.parent._validated_values(),
213
+ other.child._validated_values(),
214
+ other.patch.patch_hash,
215
+ )
216
+
217
+ __hash__ = None
218
+
219
+
220
+ @dataclass(frozen=True, slots=True, eq=False)
221
+ class PreservationClaim:
222
+ """An output claim referencing one immutable predeclared obligation."""
223
+
224
+ obligation_id: str
225
+
226
+ def __post_init__(self) -> None:
227
+ require_sha256(self.obligation_id, "obligation_id")
228
+
229
+ def __eq__(self, other: object) -> bool:
230
+ if type(self) is not PreservationClaim or type(other) is not PreservationClaim:
231
+ return False
232
+ PreservationClaim.__post_init__(self)
233
+ PreservationClaim.__post_init__(other)
234
+ return self.obligation_id == other.obligation_id
235
+
236
+ __hash__ = None
237
+
238
+
239
+ @dataclass(frozen=True, slots=True, eq=False)
240
+ class PreservationObligation:
241
+ """A replay-derived exact branch effect that a child is asked to preserve.
242
+
243
+ The identity binds the source branch patch, operation effect, three-way
244
+ relation, path, and both ancestor and expected presence-aware states. A
245
+ branch-specific obligation therefore cannot describe unchanged ancestor
246
+ content. Identical branch effects are represented once as neutral evidence
247
+ and never count as use of either individual parent.
248
+ """
249
+
250
+ source: PreservationSource
251
+ source_parent_candidate_ids: tuple[CandidateId, ...]
252
+ branch_patch_hashes: tuple[str, ...]
253
+ operation_effect_hashes: tuple[str, ...]
254
+ relation_id: str
255
+ path: JsonPath
256
+ expected_state: PreservationExpectation
257
+ expected_value_hash: str | None
258
+ ancestor_state: PreservationExpectation
259
+ ancestor_value_hash: str | None
260
+ absence_context_path: JsonPath | None = None
261
+ absence_context_kind: AbsenceContextKind | None = None
262
+ absence_context_shape_hash: str | None = None
263
+ absence_failure_kind: AbsenceFailureKind | None = None
264
+
265
+ def __post_init__(self) -> None:
266
+ if type(self.source) is not PreservationSource:
267
+ raise TypeError("source must be a PreservationSource")
268
+ if type(self.source_parent_candidate_ids) is not tuple:
269
+ raise TypeError("source_parent_candidate_ids must be an exact CandidateId tuple")
270
+ required_sources = (
271
+ 2 if self.source is PreservationSource.IDENTICAL_NEUTRAL else 1
272
+ )
273
+ if len(self.source_parent_candidate_ids) != required_sources:
274
+ raise ValueError("preservation source has the wrong number of parent identities")
275
+ if any(
276
+ type(value) is not CandidateId
277
+ for value in self.source_parent_candidate_ids
278
+ ):
279
+ raise TypeError("source_parent_candidate_ids must be an exact CandidateId tuple")
280
+ for value in self.source_parent_candidate_ids:
281
+ _validate_candidate_id(value, "source_parent_candidate_id")
282
+ if len(set(self.source_parent_candidate_ids)) != len(
283
+ self.source_parent_candidate_ids
284
+ ):
285
+ raise ValueError("preservation source parent identities must be distinct")
286
+ for name, values in (
287
+ ("branch_patch_hashes", self.branch_patch_hashes),
288
+ ("operation_effect_hashes", self.operation_effect_hashes),
289
+ ):
290
+ if type(values) is not tuple or len(values) != required_sources:
291
+ raise TypeError(f"{name} must be an exact tuple of source-aligned hashes")
292
+ for value in values:
293
+ require_sha256(value, name)
294
+ require_sha256(self.relation_id, "relation_id")
295
+ validate_json_path(self.path)
296
+ self._validate_state(
297
+ self.expected_state,
298
+ self.expected_value_hash,
299
+ name="expected",
300
+ )
301
+ self._validate_state(
302
+ self.ancestor_state,
303
+ self.ancestor_value_hash,
304
+ name="ancestor",
305
+ )
306
+ if (
307
+ self.expected_state is self.ancestor_state
308
+ and self.expected_value_hash == self.ancestor_value_hash
309
+ ):
310
+ raise ValueError(
311
+ "a preservation obligation must bind an actual change from the ancestor"
312
+ )
313
+ absence_values = (
314
+ self.absence_context_path,
315
+ self.absence_context_kind,
316
+ self.absence_context_shape_hash,
317
+ self.absence_failure_kind,
318
+ )
319
+ if self.expected_state is PreservationExpectation.PRESENT:
320
+ if any(value is not None for value in absence_values):
321
+ raise ValueError(
322
+ "present preservation state cannot carry an absence-context receipt"
323
+ )
324
+ else:
325
+ if any(value is None for value in absence_values):
326
+ raise ValueError(
327
+ "absent preservation state requires a complete context receipt"
328
+ )
329
+ validate_json_path(self.absence_context_path) # type: ignore[arg-type]
330
+ if not self.absence_context_path.is_prefix_of(self.path) or len(
331
+ self.absence_context_path.segments
332
+ ) >= len(self.path.segments):
333
+ raise ValueError(
334
+ "absence context must be a strict prefix of the obligation path"
335
+ )
336
+ if type(self.absence_context_kind) is not AbsenceContextKind:
337
+ raise TypeError("absence_context_kind must be an AbsenceContextKind")
338
+ if type(self.absence_failure_kind) is not AbsenceFailureKind:
339
+ raise TypeError("absence_failure_kind must be an AbsenceFailureKind")
340
+ require_sha256(
341
+ self.absence_context_shape_hash, # type: ignore[arg-type]
342
+ "absence_context_shape_hash",
343
+ )
344
+ failed_segment = self.path.segments[
345
+ len(self.absence_context_path.segments)
346
+ ]
347
+ expected_pair = (
348
+ AbsenceContextKind.OBJECT,
349
+ AbsenceFailureKind.MISSING_OBJECT_KEY,
350
+ ObjectKey,
351
+ )
352
+ if self.absence_context_kind is AbsenceContextKind.ARRAY:
353
+ expected_pair = (
354
+ AbsenceContextKind.ARRAY,
355
+ AbsenceFailureKind.ARRAY_INDEX_OUT_OF_BOUNDS,
356
+ ArrayIndex,
357
+ )
358
+ if (
359
+ self.absence_context_kind is not expected_pair[0]
360
+ or self.absence_failure_kind is not expected_pair[1]
361
+ or type(failed_segment) is not expected_pair[2]
362
+ ):
363
+ raise ValueError(
364
+ "absence receipt kind does not match its failing path segment"
365
+ )
366
+
367
+ @staticmethod
368
+ def _validate_state(
369
+ state: PreservationExpectation,
370
+ value_hash: str | None,
371
+ *,
372
+ name: str,
373
+ ) -> None:
374
+ if type(state) is not PreservationExpectation:
375
+ raise TypeError(f"{name}_state must be a PreservationExpectation")
376
+ if state is PreservationExpectation.PRESENT:
377
+ if value_hash is None:
378
+ raise ValueError(f"{name} present state requires a value hash")
379
+ require_sha256(value_hash, f"{name}_value_hash")
380
+ elif value_hash is not None:
381
+ raise ValueError(f"{name} absent state cannot carry a value hash")
382
+
383
+ @property
384
+ def obligation_id(self) -> str:
385
+ if type(self) is not PreservationObligation:
386
+ raise TypeError("obligation must be an exact PreservationObligation")
387
+ PreservationObligation.__post_init__(self)
388
+ digest = hashlib.sha256()
389
+ digest.update(_PRESERVATION_OBLIGATION_DOMAIN)
390
+ digest.update(self.source.value.encode("ascii", errors="strict"))
391
+ digest.update(len(self.source_parent_candidate_ids).to_bytes(8, "big"))
392
+ for candidate_id in self.source_parent_candidate_ids:
393
+ encoded = candidate_id.value.encode("ascii", errors="strict")
394
+ digest.update(len(encoded).to_bytes(8, "big"))
395
+ digest.update(encoded)
396
+ for values in (self.branch_patch_hashes, self.operation_effect_hashes):
397
+ digest.update(len(values).to_bytes(8, "big"))
398
+ for value in values:
399
+ digest.update(bytes.fromhex(value))
400
+ digest.update(bytes.fromhex(self.relation_id))
401
+ path_bytes = canonical_path_bytes(self.path)
402
+ digest.update(len(path_bytes).to_bytes(8, "big"))
403
+ digest.update(path_bytes)
404
+ for state, value_hash in (
405
+ (self.expected_state, self.expected_value_hash),
406
+ (self.ancestor_state, self.ancestor_value_hash),
407
+ ):
408
+ digest.update(state.value.encode("ascii", errors="strict"))
409
+ digest.update(b"\x00" if value_hash is None else b"\x01")
410
+ if value_hash is not None:
411
+ digest.update(bytes.fromhex(value_hash))
412
+ if self.absence_context_path is None:
413
+ digest.update(b"\x00")
414
+ else:
415
+ digest.update(b"\x01")
416
+ context_path = canonical_path_bytes(self.absence_context_path)
417
+ digest.update(len(context_path).to_bytes(8, "big"))
418
+ digest.update(context_path)
419
+ digest.update(self.absence_context_kind.value.encode("ascii"))
420
+ digest.update(bytes.fromhex(self.absence_context_shape_hash))
421
+ digest.update(self.absence_failure_kind.value.encode("ascii"))
422
+ return digest.hexdigest()
423
+
424
+ def __eq__(self, other: object) -> bool:
425
+ if (
426
+ type(self) is not PreservationObligation
427
+ or type(other) is not PreservationObligation
428
+ ):
429
+ return False
430
+ PreservationObligation.__post_init__(self)
431
+ PreservationObligation.__post_init__(other)
432
+ return self.obligation_id == other.obligation_id
433
+
434
+ __hash__ = None
435
+
436
+
437
+ def _validate_obligation_path_overlaps(
438
+ obligations: tuple[PreservationObligation, ...],
439
+ ) -> None:
440
+ """Reject parent-local equal/prefix paths in linear total path length."""
441
+
442
+ terminal = object()
443
+ roots: dict[CandidateId, dict[object, object]] = {}
444
+ for obligation in obligations:
445
+ for parent_id in obligation.source_parent_candidate_ids:
446
+ node = roots.setdefault(parent_id, {})
447
+ for segment in obligation.path.segments:
448
+ if terminal in node:
449
+ raise ValueError(
450
+ "preservation obligation paths cannot overlap within one parent"
451
+ )
452
+ child = node.setdefault(segment, {})
453
+ if type(child) is not dict: # pragma: no cover - local trie invariant.
454
+ raise AssertionError("invalid preservation-path trie")
455
+ node = child
456
+ if terminal in node or node:
457
+ raise ValueError(
458
+ "preservation obligation paths cannot overlap within one parent"
459
+ )
460
+ node[terminal] = True
461
+
462
+
463
+ @dataclass(frozen=True, slots=True, eq=False)
464
+ class VariationCase:
465
+ """Frozen causal inputs for one isolated variation-policy invocation.
466
+
467
+ This first slice deliberately contains no prompt, provider, evaluator, or
468
+ event object. Those identities remain a later application-layer concern.
469
+ """
470
+
471
+ operator_invocation_id: OperatorInvocationId
472
+ variation_kind: VariationKind
473
+ operator_id: str
474
+ operator_version: int
475
+ parents: tuple[VariationParent, ...]
476
+ requested_child_count: int
477
+ context_stratum_hash: str
478
+ reward_definition_hash: str
479
+ common_ancestor: CandidateOccurrence | None = None
480
+ ancestor_to_parent_patches: tuple[TypedPatch, ...] = ()
481
+ selected_insights: tuple[InsightRef, ...] = ()
482
+ preservation_obligations: tuple[PreservationObligation, ...] = ()
483
+
484
+ def __post_init__(self) -> None:
485
+ _validate_operator_invocation_id(
486
+ self.operator_invocation_id,
487
+ "operator_invocation_id",
488
+ )
489
+ if type(self.variation_kind) is not VariationKind:
490
+ raise TypeError("variation_kind must be a VariationKind")
491
+ if type(self.operator_id) is not str or _OPERATOR_TOKEN.fullmatch(
492
+ self.operator_id
493
+ ) is None:
494
+ raise ValueError("operator_id must use the closed lowercase token grammar")
495
+ if type(self.operator_version) is not int or self.operator_version <= 0:
496
+ raise ValueError("operator_version must be a positive exact integer")
497
+ if type(self.parents) is not tuple:
498
+ raise TypeError("parents must be an exact tuple of VariationParent values")
499
+ # Every closed variation kind consumes either one or two parents. Bound
500
+ # the container before inspecting its elements so an oversized hostile
501
+ # tuple cannot force an unbounded validation scan.
502
+ if not 1 <= len(self.parents) <= 2:
503
+ raise ValueError("parents must contain one or two variation parents")
504
+ if any(type(parent) is not VariationParent for parent in self.parents):
505
+ raise TypeError("parents must be an exact tuple of VariationParent values")
506
+ for parent in self.parents:
507
+ VariationParent.__post_init__(parent)
508
+ if type(self.requested_child_count) is not int:
509
+ raise TypeError("requested_child_count must be an exact integer")
510
+ if not 1 <= self.requested_child_count <= MAX_REQUESTED_CHILDREN:
511
+ raise ValueError(
512
+ f"requested_child_count must lie in [1, {MAX_REQUESTED_CHILDREN}]"
513
+ )
514
+ require_sha256(self.context_stratum_hash, "context_stratum_hash")
515
+ require_sha256(self.reward_definition_hash, "reward_definition_hash")
516
+
517
+ parent_ids = tuple(parent.occurrence.candidate_id for parent in self.parents)
518
+ roles = tuple(parent.role for parent in self.parents)
519
+ if len(set(parent_ids)) != len(parent_ids):
520
+ raise ValueError("variation parents must be distinct occurrences")
521
+ if len(set(roles)) != len(roles):
522
+ raise ValueError("variation parent roles must be unique")
523
+ expected_roles = {
524
+ VariationKind.REPRODUCTION: (ParentRole.REPRODUCTION_SOURCE,),
525
+ VariationKind.TYPED_MUTATION: (ParentRole.MUTATION_PARENT,),
526
+ VariationKind.TWO_PARENT_CROSSOVER: (
527
+ ParentRole.CROSSOVER_LEFT,
528
+ ParentRole.CROSSOVER_RIGHT,
529
+ ),
530
+ VariationKind.THREE_WAY_RECOMBINATION: (
531
+ ParentRole.CROSSOVER_LEFT,
532
+ ParentRole.CROSSOVER_RIGHT,
533
+ ),
534
+ VariationKind.REPAIR: (ParentRole.REPAIR_TARGET,),
535
+ }[self.variation_kind]
536
+ if roles != expected_roles:
537
+ raise ValueError(
538
+ "parents must appear in the exact role order required by variation_kind"
539
+ )
540
+ if any(
541
+ parent.occurrence.operator_invocation_id == self.operator_invocation_id
542
+ for parent in self.parents
543
+ ):
544
+ raise ValueError(
545
+ "an operator invocation cannot consume an occurrence it produced itself"
546
+ )
547
+
548
+ if type(self.ancestor_to_parent_patches) is not tuple:
549
+ raise TypeError(
550
+ "ancestor_to_parent_patches must be an exact tuple of TypedPatch values"
551
+ )
552
+ if len(self.ancestor_to_parent_patches) > 2:
553
+ raise ValueError("ancestor_to_parent_patches cannot contain more than two patches")
554
+ if any(
555
+ type(patch) is not TypedPatch
556
+ for patch in self.ancestor_to_parent_patches
557
+ ):
558
+ raise TypeError(
559
+ "ancestor_to_parent_patches must be an exact tuple of TypedPatch values"
560
+ )
561
+ for patch in self.ancestor_to_parent_patches:
562
+ validate_typed_patch(patch)
563
+ if self.variation_kind is VariationKind.THREE_WAY_RECOMBINATION:
564
+ if type(self.common_ancestor) is not CandidateOccurrence:
565
+ raise ValueError("three-way recombination requires one common ancestor")
566
+ CandidateOccurrence.__post_init__(self.common_ancestor)
567
+ if self.common_ancestor.candidate_id in parent_ids:
568
+ raise ValueError("common ancestor must be a distinct occurrence")
569
+ if self.common_ancestor.operator_invocation_id == self.operator_invocation_id:
570
+ raise ValueError(
571
+ "an operator invocation cannot consume its own common ancestor"
572
+ )
573
+ if any(
574
+ self.common_ancestor.proposal_sequence
575
+ >= parent.occurrence.proposal_sequence
576
+ for parent in self.parents
577
+ ):
578
+ raise ValueError(
579
+ "common ancestor must precede both branch-parent occurrences"
580
+ )
581
+ if len(self.ancestor_to_parent_patches) != 2:
582
+ raise ValueError("three-way recombination requires exactly two branch patches")
583
+ if (
584
+ self.ancestor_to_parent_patches[0].limits
585
+ != self.ancestor_to_parent_patches[1].limits
586
+ ):
587
+ raise ValueError(
588
+ "three-way branch patches must share exact algebra limits"
589
+ )
590
+ expected_targets = parent_ids
591
+ actual_targets = tuple(
592
+ patch.target_candidate_id for patch in self.ancestor_to_parent_patches
593
+ )
594
+ if actual_targets != expected_targets:
595
+ raise ValueError("branch patches must follow left/right parent order")
596
+ for parent, patch in zip(
597
+ self.parents,
598
+ self.ancestor_to_parent_patches,
599
+ ):
600
+ if (
601
+ patch.base_candidate_id != self.common_ancestor.candidate_id
602
+ or patch.base_hash != self.common_ancestor.configuration_hash
603
+ or patch.target_candidate_id != parent.occurrence.candidate_id
604
+ or patch.target_hash != parent.occurrence.configuration_hash
605
+ ):
606
+ raise ValueError("ancestor branch patch endpoints do not match the case")
607
+ elif self.common_ancestor is not None or self.ancestor_to_parent_patches:
608
+ raise ValueError(
609
+ "common ancestor and branch patches are exclusive to three-way recombination"
610
+ )
611
+
612
+ if type(self.selected_insights) is not tuple:
613
+ raise TypeError("selected_insights must be an exact tuple of InsightRef values")
614
+ if len(self.selected_insights) > MAX_SELECTED_INSIGHTS:
615
+ raise ValueError("selected_insights exceeds MAX_SELECTED_INSIGHTS")
616
+ if any(type(reference) is not InsightRef for reference in self.selected_insights):
617
+ raise TypeError("selected_insights must be an exact tuple of InsightRef values")
618
+ for reference in self.selected_insights:
619
+ InsightRef.__post_init__(reference)
620
+ if type(reference.insight_id) is not InsightId:
621
+ raise TypeError("selected insight IDs must be exact InsightId values")
622
+ InsightId.__post_init__(reference.insight_id)
623
+ if len(set(self.selected_insights)) != len(self.selected_insights):
624
+ raise ValueError("selected_insights cannot contain duplicate exact versions")
625
+
626
+ if type(self.preservation_obligations) is not tuple:
627
+ raise TypeError(
628
+ "preservation_obligations must be an exact tuple of PreservationObligation values"
629
+ )
630
+ if len(self.preservation_obligations) > MAX_PRESERVATION_OBLIGATIONS:
631
+ raise ValueError(
632
+ "preservation_obligations exceeds MAX_PRESERVATION_OBLIGATIONS"
633
+ )
634
+ if any(
635
+ type(obligation) is not PreservationObligation
636
+ for obligation in self.preservation_obligations
637
+ ):
638
+ raise TypeError(
639
+ "preservation_obligations must be an exact tuple of PreservationObligation values"
640
+ )
641
+ for obligation in self.preservation_obligations:
642
+ PreservationObligation.__post_init__(obligation)
643
+ if (
644
+ self.preservation_obligations
645
+ and self.variation_kind is not VariationKind.THREE_WAY_RECOMBINATION
646
+ ):
647
+ raise ValueError(
648
+ "this slice admits preservation obligations only for verified three-way cases"
649
+ )
650
+ canonical_obligations = tuple(
651
+ sorted(
652
+ self.preservation_obligations,
653
+ key=lambda obligation: obligation.obligation_id,
654
+ )
655
+ )
656
+ if self.preservation_obligations != canonical_obligations:
657
+ raise ValueError(
658
+ "preservation_obligations must use canonical obligation-id order"
659
+ )
660
+ obligation_ids = tuple(
661
+ obligation.obligation_id for obligation in self.preservation_obligations
662
+ )
663
+ if len(set(obligation_ids)) != len(obligation_ids):
664
+ raise ValueError("preservation_obligations cannot duplicate an identity")
665
+ for obligation in self.preservation_obligations:
666
+ expected_source_ids = {
667
+ PreservationSource.LEFT_BRANCH: (parent_ids[0],),
668
+ PreservationSource.RIGHT_BRANCH: (parent_ids[1],),
669
+ PreservationSource.IDENTICAL_NEUTRAL: parent_ids,
670
+ }[obligation.source]
671
+ if obligation.source_parent_candidate_ids != expected_source_ids:
672
+ raise ValueError(
673
+ "preservation obligation branch provenance does not match case roles"
674
+ )
675
+ _validate_obligation_path_overlaps(self.preservation_obligations)
676
+
677
+ def __eq__(self, other: object) -> bool:
678
+ if type(self) is not VariationCase or type(other) is not VariationCase:
679
+ return False
680
+ VariationCase.__post_init__(self)
681
+ VariationCase.__post_init__(other)
682
+
683
+ def projection(value: VariationCase) -> tuple[object, ...]:
684
+ return (
685
+ value.operator_invocation_id.value,
686
+ value.variation_kind.value,
687
+ value.operator_id,
688
+ value.operator_version,
689
+ tuple(parent._validated_values() for parent in value.parents),
690
+ value.requested_child_count,
691
+ value.context_stratum_hash,
692
+ value.reward_definition_hash,
693
+ None
694
+ if value.common_ancestor is None
695
+ else value.common_ancestor._validated_values(),
696
+ tuple(patch.patch_hash for patch in value.ancestor_to_parent_patches),
697
+ tuple(
698
+ (reference.insight_id.value, reference.version)
699
+ for reference in value.selected_insights
700
+ ),
701
+ tuple(
702
+ obligation.obligation_id
703
+ for obligation in value.preservation_obligations
704
+ ),
705
+ )
706
+
707
+ return projection(self) == projection(other)
708
+
709
+ __hash__ = None
710
+
711
+
712
+ def validate_variation_case(value: VariationCase) -> None:
713
+ """Revalidate the complete immutable variation-case graph."""
714
+
715
+ if type(value) is not VariationCase:
716
+ raise TypeError("variation_case must be an exact VariationCase")
717
+ VariationCase.__post_init__(value)
718
+
719
+
720
+ __all__ = [
721
+ "AbsenceContextKind",
722
+ "AbsenceFailureKind",
723
+ "MAX_PRESERVATION_OBLIGATIONS",
724
+ "MAX_REQUESTED_CHILDREN",
725
+ "MAX_SELECTED_INSIGHTS",
726
+ "CandidateOccurrence",
727
+ "ParentEdge",
728
+ "ParentRole",
729
+ "PreservationClaim",
730
+ "PreservationExpectation",
731
+ "PreservationObligation",
732
+ "PreservationSource",
733
+ "VariationCase",
734
+ "VariationKind",
735
+ "VariationParent",
736
+ "validate_variation_case",
737
+ ]