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,611 @@
1
+ """Deterministic model-free union of strictly disjoint typed patches.
2
+
3
+ The three-way patch algebra deliberately classifies rather than merges. This
4
+ module provides the narrower policy that is safe to automate: two branches may
5
+ be united only when replay classifies every branch effect as either identical
6
+ or disjoint. Conflicts, prefix invalidation, and semantic-component coupling
7
+ remain explicit failures for a higher-authority operator to resolve.
8
+
9
+ The policy depends only on immutable domain values and the typed-patch policy.
10
+ It has no generator, evaluator, archive, or application dependency.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import hashlib
16
+ from dataclasses import dataclass
17
+ from enum import Enum
18
+ from typing import ClassVar
19
+
20
+ from agent_evolve.domain.ids import CandidateId
21
+ from agent_evolve.domain.patch import (
22
+ DEFAULT_PATCH_LIMITS,
23
+ DeleteSequenceItem,
24
+ InsertSequenceItem,
25
+ JsonPath,
26
+ PatchLimits,
27
+ PatchOperation,
28
+ PermuteSequence,
29
+ ReplaceScalar,
30
+ ReplaceSubtree,
31
+ TypedPatch,
32
+ canonical_path_bytes,
33
+ operation_effect_bytes,
34
+ operation_effect_sha256,
35
+ operation_occurrence_bytes,
36
+ operation_sort_key,
37
+ require_sha256,
38
+ validate_json_path,
39
+ validate_patch_limits,
40
+ validate_patch_operation,
41
+ validate_typed_patch,
42
+ )
43
+ from agent_evolve.domain.typed_json import (
44
+ FrozenJsonValue,
45
+ freeze_json,
46
+ typed_json_equal,
47
+ typed_json_sha256,
48
+ )
49
+ from agent_evolve.policies.variation.typed_patch import (
50
+ ComponentTagAssignment,
51
+ ThreeWayPatchClassification,
52
+ ThreeWayRelationKind,
53
+ apply_patch,
54
+ classify_three_way_patches,
55
+ derive_patch,
56
+ replace_existing_path,
57
+ value_at_path,
58
+ )
59
+
60
+
61
+ POLICY_ID = "disjoint_patch_union"
62
+ POLICY_VERSION = 1
63
+ _RECEIPT_DOMAIN = b"agent-evolve:disjoint-patch-union-receipt:v1\x00"
64
+
65
+
66
+ class DisjointPatchRecombinationError(ValueError):
67
+ """The requested branches do not admit the policy's exact safe union."""
68
+
69
+
70
+ class RecombinationBranch(str, Enum):
71
+ """A branch whose replay-verified effect appears in the union."""
72
+
73
+ LEFT = "left"
74
+ RIGHT = "right"
75
+
76
+
77
+ _CANONICAL_BOTH_BRANCHES = (
78
+ RecombinationBranch.LEFT,
79
+ RecombinationBranch.RIGHT,
80
+ )
81
+
82
+
83
+ def _frame(value: bytes) -> bytes:
84
+ if type(value) is not bytes:
85
+ raise TypeError("receipt components must be exact bytes")
86
+ return len(value).to_bytes(8, "big", signed=False) + value
87
+
88
+
89
+ def _validate_candidate_id(value: CandidateId, *, name: str) -> None:
90
+ if type(value) is not CandidateId:
91
+ raise TypeError(f"{name} must be an exact CandidateId")
92
+ CandidateId.__post_init__(value)
93
+
94
+
95
+ def _validate_sources(values: tuple[RecombinationBranch, ...]) -> None:
96
+ if type(values) is not tuple or any(
97
+ type(value) is not RecombinationBranch for value in values
98
+ ):
99
+ raise TypeError("sources must be an exact tuple of RecombinationBranch values")
100
+ if values not in {
101
+ (RecombinationBranch.LEFT,),
102
+ (RecombinationBranch.RIGHT,),
103
+ _CANONICAL_BOTH_BRANCHES,
104
+ }:
105
+ raise ValueError("sources must be a non-empty canonical branch set")
106
+
107
+
108
+ @dataclass(frozen=True, slots=True, eq=False)
109
+ class SystemPatchAttribution:
110
+ """System-derived provenance for one exact union-patch effect.
111
+
112
+ ``sources`` contains both branches only for a replay-classified identical
113
+ relation. The relation and effect digests make this evidence independently
114
+ bindable without relying on model-authored path strings or explanations.
115
+ """
116
+
117
+ path: JsonPath
118
+ sources: tuple[RecombinationBranch, ...]
119
+ relation_id: str
120
+ effect_sha256: str
121
+
122
+ def __post_init__(self) -> None:
123
+ validate_json_path(self.path)
124
+ _validate_sources(self.sources)
125
+ require_sha256(self.relation_id, "relation_id")
126
+ require_sha256(self.effect_sha256, "effect_sha256")
127
+
128
+ def revalidate(self) -> None:
129
+ if type(self) is not SystemPatchAttribution:
130
+ raise TypeError("attribution must be an exact SystemPatchAttribution")
131
+ SystemPatchAttribution.__post_init__(self)
132
+
133
+ def __eq__(self, other: object) -> bool:
134
+ if (
135
+ type(self) is not SystemPatchAttribution
136
+ or type(other) is not SystemPatchAttribution
137
+ ):
138
+ return False
139
+ self.revalidate()
140
+ other.revalidate()
141
+ return _attribution_fingerprint(self) == _attribution_fingerprint(other)
142
+
143
+ __hash__ = None
144
+
145
+
146
+ def _attribution_fingerprint(
147
+ value: SystemPatchAttribution,
148
+ ) -> tuple[bytes, tuple[str, ...], str, str]:
149
+ value.revalidate()
150
+ return (
151
+ canonical_path_bytes(value.path),
152
+ tuple(source.value for source in value.sources),
153
+ value.relation_id,
154
+ value.effect_sha256,
155
+ )
156
+
157
+
158
+ def _attribution_sort_key(
159
+ value: SystemPatchAttribution,
160
+ ) -> tuple[bytes, str, tuple[str, ...], str]:
161
+ value.revalidate()
162
+ return (
163
+ canonical_path_bytes(value.path),
164
+ value.effect_sha256,
165
+ tuple(source.value for source in value.sources),
166
+ value.relation_id,
167
+ )
168
+
169
+
170
+ def _operation_before_after(
171
+ operation: PatchOperation,
172
+ ) -> tuple[FrozenJsonValue, FrozenJsonValue]:
173
+ validate_patch_operation(operation)
174
+ if type(operation) in (ReplaceScalar, ReplaceSubtree):
175
+ return operation.old_value, operation.new_value
176
+ if type(operation) in (
177
+ InsertSequenceItem,
178
+ DeleteSequenceItem,
179
+ PermuteSequence,
180
+ ):
181
+ return operation.before_sequence, operation.after_sequence
182
+ raise TypeError("unsupported patch operation type")
183
+
184
+
185
+ def _safe_relations(
186
+ classification: ThreeWayPatchClassification,
187
+ ) -> tuple[PatchOperation, ...]:
188
+ """Return the canonical union operations or reject the classification."""
189
+
190
+ if type(classification) is not ThreeWayPatchClassification:
191
+ raise TypeError("classification must be an exact ThreeWayPatchClassification")
192
+ classification.revalidate()
193
+ rejected = tuple(
194
+ relation.kind
195
+ for relation in classification.relations
196
+ if relation.kind
197
+ not in {ThreeWayRelationKind.IDENTICAL, ThreeWayRelationKind.DISJOINT}
198
+ )
199
+ if rejected:
200
+ kinds = ", ".join(sorted({kind.value for kind in rejected}))
201
+ raise DisjointPatchRecombinationError(
202
+ f"branch classification contains unsafe relation kinds: {kinds}"
203
+ )
204
+
205
+ left_unique = False
206
+ right_unique = False
207
+ operations: list[PatchOperation] = []
208
+ for relation in classification.relations:
209
+ if relation.kind is ThreeWayRelationKind.IDENTICAL:
210
+ # Relation validation proves these are the exact same effect. The
211
+ # operation occurrence also has the same common-ancestor source, so
212
+ # choosing the left representation is deterministic and lossless.
213
+ operations.append(relation.left_operations[0])
214
+ elif relation.kind is ThreeWayRelationKind.DISJOINT:
215
+ if relation.left_operations:
216
+ left_unique = True
217
+ operations.append(relation.left_operations[0])
218
+ else:
219
+ right_unique = True
220
+ operations.append(relation.right_operations[0])
221
+ else: # pragma: no cover - rejected above and enum closes the cases.
222
+ raise AssertionError("unsafe relation passed the fail-closed gate")
223
+ if not left_unique or not right_unique:
224
+ missing = "left" if not left_unique else "right"
225
+ if not left_unique and not right_unique:
226
+ missing = "left and right"
227
+ raise DisjointPatchRecombinationError(
228
+ f"{missing} branch lacks a non-identical disjoint effect"
229
+ )
230
+ return tuple(sorted(operations, key=operation_sort_key))
231
+
232
+
233
+ def _expected_attribution(
234
+ classification: ThreeWayPatchClassification,
235
+ ) -> tuple[SystemPatchAttribution, ...]:
236
+ classification.revalidate()
237
+ values: list[SystemPatchAttribution] = []
238
+ for relation in classification.relations:
239
+ if relation.kind is ThreeWayRelationKind.IDENTICAL:
240
+ operation = relation.left_operations[0]
241
+ sources = _CANONICAL_BOTH_BRANCHES
242
+ elif relation.kind is ThreeWayRelationKind.DISJOINT:
243
+ if relation.left_operations:
244
+ operation = relation.left_operations[0]
245
+ sources = (RecombinationBranch.LEFT,)
246
+ else:
247
+ operation = relation.right_operations[0]
248
+ sources = (RecombinationBranch.RIGHT,)
249
+ else:
250
+ raise DisjointPatchRecombinationError(
251
+ "system attribution cannot represent an unsafe relation"
252
+ )
253
+ values.append(
254
+ SystemPatchAttribution(
255
+ path=operation.path,
256
+ sources=sources,
257
+ relation_id=relation.relation_id,
258
+ effect_sha256=operation_effect_sha256(
259
+ operation,
260
+ limits=classification.left_patch.limits.json_limits,
261
+ ),
262
+ )
263
+ )
264
+ return tuple(sorted(values, key=_attribution_sort_key))
265
+
266
+
267
+ def _construct_target(
268
+ ancestor: FrozenJsonValue,
269
+ operations: tuple[PatchOperation, ...],
270
+ *,
271
+ limits: PatchLimits,
272
+ ) -> FrozenJsonValue:
273
+ """Construct an endpoint using only exact old/new operation states."""
274
+
275
+ validate_patch_limits(limits)
276
+ frozen_ancestor = freeze_json(ancestor, limits=limits.json_limits)
277
+ if frozen_ancestor is not ancestor:
278
+ raise TypeError("ancestor must already be frozen typed JSON")
279
+ current = frozen_ancestor
280
+ for operation in operations:
281
+ validate_patch_operation(operation)
282
+ before, after = _operation_before_after(operation)
283
+ observed = value_at_path(current, operation.path)
284
+ if not typed_json_equal(observed, before, limits=limits.json_limits):
285
+ raise DisjointPatchRecombinationError(
286
+ "canonical union encountered a stale operation precondition"
287
+ )
288
+ current = replace_existing_path(current, operation.path, after)
289
+ if not typed_json_equal(
290
+ value_at_path(current, operation.path),
291
+ after,
292
+ limits=limits.json_limits,
293
+ ):
294
+ raise DisjointPatchRecombinationError(
295
+ "canonical union did not install an exact operation effect"
296
+ )
297
+ return current
298
+
299
+
300
+ def _effect_fingerprint(
301
+ patch: TypedPatch,
302
+ ) -> tuple[bytes, ...]:
303
+ validate_typed_patch(patch)
304
+ return tuple(
305
+ operation_effect_bytes(operation, limits=patch.limits.json_limits)
306
+ for operation in patch.operations
307
+ )
308
+
309
+
310
+ def _validate_materialization(
311
+ value: "DisjointPatchMaterialization",
312
+ ) -> None:
313
+ if type(value.union_patch) is not TypedPatch:
314
+ raise TypeError("union_patch must be an exact TypedPatch")
315
+ if type(value.classification) is not ThreeWayPatchClassification:
316
+ raise TypeError("classification must be an exact ThreeWayPatchClassification")
317
+ validate_typed_patch(value.union_patch)
318
+ value.classification.revalidate()
319
+ configuration = freeze_json(
320
+ value.configuration,
321
+ limits=value.union_patch.limits.json_limits,
322
+ )
323
+ if configuration is not value.configuration:
324
+ raise TypeError("configuration must already be frozen typed JSON")
325
+ classification = value.classification
326
+ union_patch = value.union_patch
327
+ if union_patch.limits != classification.left_patch.limits:
328
+ raise ValueError("union patch and branch patches must share exact limits")
329
+ if (
330
+ union_patch.base_candidate_id != classification.ancestor_candidate_id
331
+ or union_patch.base_hash != classification.ancestor_hash
332
+ ):
333
+ raise ValueError("union patch does not bind the classified ancestor")
334
+ if union_patch.target_candidate_id in {
335
+ classification.ancestor_candidate_id,
336
+ classification.left_patch.target_candidate_id,
337
+ classification.right_patch.target_candidate_id,
338
+ }:
339
+ raise ValueError("union target must be a distinct candidate occurrence")
340
+ expected_operations = _safe_relations(classification)
341
+ if tuple(
342
+ operation_occurrence_bytes(
343
+ operation,
344
+ limits=union_patch.limits.json_limits,
345
+ )
346
+ for operation in union_patch.operations
347
+ ) != tuple(
348
+ operation_occurrence_bytes(
349
+ operation,
350
+ limits=union_patch.limits.json_limits,
351
+ )
352
+ for operation in expected_operations
353
+ ):
354
+ raise ValueError(
355
+ "union patch does not contain the canonical classified effects"
356
+ )
357
+ replayed = apply_patch(classification.ancestor, union_patch)
358
+ if not typed_json_equal(
359
+ replayed,
360
+ configuration,
361
+ limits=union_patch.limits.json_limits,
362
+ ):
363
+ raise ValueError("configuration does not equal the replayed union patch")
364
+
365
+ rediff = derive_patch(
366
+ classification.ancestor,
367
+ configuration,
368
+ base_candidate_id=classification.ancestor_candidate_id,
369
+ target_candidate_id=union_patch.target_candidate_id,
370
+ limits=union_patch.limits,
371
+ )
372
+ if _effect_fingerprint(rediff) != _effect_fingerprint(union_patch):
373
+ raise ValueError(
374
+ "union endpoint does not re-diff to the exact classified effects"
375
+ )
376
+ if rediff.patch_hash != union_patch.patch_hash:
377
+ raise ValueError("union endpoint does not re-diff to the canonical union patch")
378
+
379
+ if type(value.system_attribution) is not tuple or any(
380
+ type(item) is not SystemPatchAttribution for item in value.system_attribution
381
+ ):
382
+ raise TypeError(
383
+ "system_attribution must be an exact tuple of SystemPatchAttribution values"
384
+ )
385
+ for item in value.system_attribution:
386
+ item.revalidate()
387
+ if value.system_attribution != tuple(
388
+ sorted(value.system_attribution, key=_attribution_sort_key)
389
+ ):
390
+ raise ValueError("system_attribution must use canonical order")
391
+ expected_attribution = _expected_attribution(classification)
392
+ if tuple(map(_attribution_fingerprint, value.system_attribution)) != tuple(
393
+ map(_attribution_fingerprint, expected_attribution)
394
+ ):
395
+ raise ValueError(
396
+ "system_attribution does not exactly bind every classified union effect"
397
+ )
398
+
399
+
400
+ @dataclass(frozen=True, slots=True, eq=False)
401
+ class DisjointPatchMaterialization:
402
+ """Immutable, replay-complete output of deterministic recombination."""
403
+
404
+ configuration: FrozenJsonValue
405
+ union_patch: TypedPatch
406
+ classification: ThreeWayPatchClassification
407
+ system_attribution: tuple[SystemPatchAttribution, ...]
408
+
409
+ policy_id: ClassVar[str] = POLICY_ID
410
+ policy_version: ClassVar[int] = POLICY_VERSION
411
+
412
+ def __post_init__(self) -> None:
413
+ if type(self.union_patch) is not TypedPatch:
414
+ raise TypeError("union_patch must be an exact TypedPatch")
415
+ frozen = freeze_json(
416
+ self.configuration,
417
+ limits=self.union_patch.limits.json_limits,
418
+ )
419
+ object.__setattr__(self, "configuration", frozen)
420
+ _validate_materialization(self)
421
+
422
+ def revalidate(self) -> None:
423
+ if type(self) is not DisjointPatchMaterialization:
424
+ raise TypeError(
425
+ "materialization must be an exact DisjointPatchMaterialization"
426
+ )
427
+ _validate_materialization(self)
428
+
429
+ @property
430
+ def receipt_sha256(self) -> str:
431
+ """Digest binding the policy, endpoints, effects, and provenance."""
432
+
433
+ self.revalidate()
434
+ digest = hashlib.sha256()
435
+ digest.update(_RECEIPT_DOMAIN)
436
+ digest.update(_frame(self.policy_id.encode("ascii", errors="strict")))
437
+ digest.update(self.policy_version.to_bytes(8, "big", signed=False))
438
+ for candidate_id in (
439
+ self.classification.ancestor_candidate_id,
440
+ self.classification.left_patch.target_candidate_id,
441
+ self.classification.right_patch.target_candidate_id,
442
+ self.union_patch.target_candidate_id,
443
+ ):
444
+ digest.update(_frame(candidate_id.value.encode("ascii", errors="strict")))
445
+ digest.update(bytes.fromhex(self.classification.left_patch_hash))
446
+ digest.update(bytes.fromhex(self.classification.right_patch_hash))
447
+ digest.update(bytes.fromhex(self.union_patch.patch_hash))
448
+ digest.update(
449
+ bytes.fromhex(
450
+ typed_json_sha256(
451
+ self.configuration,
452
+ limits=self.union_patch.limits.json_limits,
453
+ )
454
+ )
455
+ )
456
+ digest.update(len(self.classification.relations).to_bytes(8, "big"))
457
+ for relation in self.classification.relations:
458
+ digest.update(bytes.fromhex(relation.relation_id))
459
+ digest.update(len(self.system_attribution).to_bytes(8, "big"))
460
+ for attribution in self.system_attribution:
461
+ digest.update(_frame(canonical_path_bytes(attribution.path)))
462
+ digest.update(len(attribution.sources).to_bytes(8, "big"))
463
+ for source in attribution.sources:
464
+ digest.update(_frame(source.value.encode("ascii", errors="strict")))
465
+ digest.update(bytes.fromhex(attribution.relation_id))
466
+ digest.update(bytes.fromhex(attribution.effect_sha256))
467
+ return digest.hexdigest()
468
+
469
+ def __eq__(self, other: object) -> bool:
470
+ if (
471
+ type(self) is not DisjointPatchMaterialization
472
+ or type(other) is not DisjointPatchMaterialization
473
+ ):
474
+ return False
475
+ return self.receipt_sha256 == other.receipt_sha256
476
+
477
+ __hash__ = None
478
+
479
+
480
+ @dataclass(frozen=True, slots=True)
481
+ class DisjointPatchRecombiner:
482
+ """Materialize the exact union of two safe ancestor-relative branches."""
483
+
484
+ limits: PatchLimits = DEFAULT_PATCH_LIMITS
485
+
486
+ policy_id: ClassVar[str] = POLICY_ID
487
+ policy_version: ClassVar[int] = POLICY_VERSION
488
+
489
+ def __post_init__(self) -> None:
490
+ validate_patch_limits(self.limits)
491
+
492
+ def materialize(
493
+ self,
494
+ *,
495
+ ancestor: object,
496
+ ancestor_candidate_id: CandidateId,
497
+ left: object,
498
+ left_candidate_id: CandidateId,
499
+ right: object,
500
+ right_candidate_id: CandidateId,
501
+ target_candidate_id: CandidateId,
502
+ left_component_tags: tuple[ComponentTagAssignment, ...] = (),
503
+ right_component_tags: tuple[ComponentTagAssignment, ...] = (),
504
+ ) -> DisjointPatchMaterialization:
505
+ """Derive, classify, construct, replay, and independently re-diff.
506
+
507
+ All four occurrence IDs must be distinct. Component tags are optional
508
+ benchmark semantics; when they induce a same-component relation, this
509
+ mechanical policy intentionally refuses to decide whether combination
510
+ is safe.
511
+ """
512
+
513
+ validate_patch_limits(self.limits)
514
+ identifiers = (
515
+ (ancestor_candidate_id, "ancestor_candidate_id"),
516
+ (left_candidate_id, "left_candidate_id"),
517
+ (right_candidate_id, "right_candidate_id"),
518
+ (target_candidate_id, "target_candidate_id"),
519
+ )
520
+ for candidate_id, name in identifiers:
521
+ _validate_candidate_id(candidate_id, name=name)
522
+ if len({candidate_id for candidate_id, _ in identifiers}) != len(identifiers):
523
+ raise ValueError("recombination occurrence IDs must be pairwise distinct")
524
+
525
+ frozen_ancestor = freeze_json(ancestor, limits=self.limits.json_limits)
526
+ frozen_left = freeze_json(left, limits=self.limits.json_limits)
527
+ frozen_right = freeze_json(right, limits=self.limits.json_limits)
528
+ left_patch = derive_patch(
529
+ frozen_ancestor,
530
+ frozen_left,
531
+ base_candidate_id=ancestor_candidate_id,
532
+ target_candidate_id=left_candidate_id,
533
+ component_tags=left_component_tags,
534
+ limits=self.limits,
535
+ )
536
+ right_patch = derive_patch(
537
+ frozen_ancestor,
538
+ frozen_right,
539
+ base_candidate_id=ancestor_candidate_id,
540
+ target_candidate_id=right_candidate_id,
541
+ component_tags=right_component_tags,
542
+ limits=self.limits,
543
+ )
544
+ classification = classify_three_way_patches(
545
+ frozen_ancestor,
546
+ left_patch,
547
+ right_patch,
548
+ )
549
+ union_operations = _safe_relations(classification)
550
+ provisional_target = _construct_target(
551
+ frozen_ancestor,
552
+ union_operations,
553
+ limits=self.limits,
554
+ )
555
+ union_patch = TypedPatch(
556
+ base_candidate_id=ancestor_candidate_id,
557
+ target_candidate_id=target_candidate_id,
558
+ base_hash=classification.ancestor_hash,
559
+ target_hash=typed_json_sha256(
560
+ provisional_target,
561
+ limits=self.limits.json_limits,
562
+ ),
563
+ operations=union_operations,
564
+ limits=self.limits,
565
+ )
566
+
567
+ # Replay is an independent whole-patch check after the local, safe
568
+ # construction above. Re-diff then proves the endpoint did not merely
569
+ # happen to match while hiding a different canonical effect script.
570
+ replayed = apply_patch(frozen_ancestor, union_patch)
571
+ if not typed_json_equal(
572
+ replayed,
573
+ provisional_target,
574
+ limits=self.limits.json_limits,
575
+ ):
576
+ raise DisjointPatchRecombinationError(
577
+ "union patch replay disagrees with safe construction"
578
+ )
579
+ rediff = derive_patch(
580
+ frozen_ancestor,
581
+ replayed,
582
+ base_candidate_id=ancestor_candidate_id,
583
+ target_candidate_id=target_candidate_id,
584
+ limits=self.limits,
585
+ )
586
+ if _effect_fingerprint(rediff) != _effect_fingerprint(union_patch):
587
+ raise DisjointPatchRecombinationError(
588
+ "replayed union does not re-diff to the exact classified effects"
589
+ )
590
+ if rediff.patch_hash != union_patch.patch_hash:
591
+ raise DisjointPatchRecombinationError(
592
+ "replayed union does not re-diff to the canonical union patch"
593
+ )
594
+
595
+ return DisjointPatchMaterialization(
596
+ configuration=replayed,
597
+ union_patch=union_patch,
598
+ classification=classification,
599
+ system_attribution=_expected_attribution(classification),
600
+ )
601
+
602
+
603
+ __all__ = [
604
+ "DisjointPatchMaterialization",
605
+ "DisjointPatchRecombinationError",
606
+ "DisjointPatchRecombiner",
607
+ "POLICY_ID",
608
+ "POLICY_VERSION",
609
+ "RecombinationBranch",
610
+ "SystemPatchAttribution",
611
+ ]