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,526 @@
1
+ """Sealed finite, parent-relative variation choices.
2
+
3
+ The language model selects only an opaque option identifier. Trusted benchmark
4
+ code owns each complete child configuration, so one option may change any
5
+ number of coordinates without expanding the model's proposal authority.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import re
12
+ from dataclasses import dataclass
13
+
14
+ from agent_evolve.domain.patch import require_sha256
15
+ from agent_evolve.domain.typed_json import (
16
+ FrozenJsonObject,
17
+ _typed_json_sha256_canonical_bytes,
18
+ canonical_typed_json_bytes,
19
+ freeze_json,
20
+ typed_json_sha256,
21
+ )
22
+
23
+
24
+ _OPTION_ID = re.compile(r"^[a-z][a-z0-9_.-]{0,255}$")
25
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
26
+ _METADATA_KEY = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
27
+ _MAX_DESCRIPTION_BYTES = 2_048
28
+ _MAX_METADATA_ITEMS = 64
29
+ _MAX_METADATA_VALUE_BYTES = 4_096
30
+ MAX_FINITE_VARIATION_OPTIONS = 1_024
31
+ _OPTION_HASH_DOMAIN = b"agent-evolve:finite-variation-option:v1\x00"
32
+ _CONTRACT_HASH_DOMAIN = b"agent-evolve:finite-variation-contract:v1\x00"
33
+ _ACTION_EVIDENCE_BINDING_HASH_DOMAIN = (
34
+ b"agent-evolve:finite-action-evidence-binding:v1\x00"
35
+ )
36
+
37
+
38
+ def _frame(payload: bytes) -> bytes:
39
+ if type(payload) is not bytes:
40
+ raise TypeError("framed payloads must be exact bytes")
41
+ return len(payload).to_bytes(8, "big", signed=False) + payload
42
+
43
+
44
+ def _prompt_text(value: str, *, name: str, max_bytes: int) -> bytes:
45
+ """Admit bounded, canonical, single-line printable prompt data."""
46
+
47
+ if type(value) is not str:
48
+ raise TypeError(f"{name} must be an exact string")
49
+ if not value or value != value.strip():
50
+ raise ValueError(f"{name} must be canonical non-empty text")
51
+ try:
52
+ encoded = value.encode("ascii", errors="strict")
53
+ except UnicodeEncodeError as exc:
54
+ raise ValueError(f"{name} must contain printable ASCII only") from exc
55
+ if len(encoded) > max_bytes:
56
+ raise ValueError(f"{name} exceeds its byte limit")
57
+ if any(byte < 0x20 or byte > 0x7E for byte in encoded):
58
+ raise ValueError(f"{name} must be single-line printable ASCII")
59
+ return encoded
60
+
61
+
62
+ @dataclass(frozen=True, slots=True, eq=False)
63
+ class FiniteVariationOption:
64
+ """One immutable full-child choice bound to one exact parent phenotype.
65
+
66
+ ``description`` and ``metadata`` are the only option data intended for an
67
+ LLM prompt. The child configuration remains engine-owned and is never a
68
+ model-authored payload.
69
+ """
70
+
71
+ option_id: str
72
+ parent_configuration_sha256: str
73
+ child_configuration: FrozenJsonObject
74
+ family: str
75
+ description: str
76
+ metadata: tuple[tuple[str, str], ...] = ()
77
+
78
+ def __post_init__(self) -> None:
79
+ if type(self.option_id) is not str or _OPTION_ID.fullmatch(
80
+ self.option_id
81
+ ) is None:
82
+ raise ValueError(
83
+ "option_id must use the closed lowercase identifier grammar"
84
+ )
85
+ require_sha256(
86
+ self.parent_configuration_sha256,
87
+ "parent_configuration_sha256",
88
+ )
89
+ if type(self.child_configuration) is not FrozenJsonObject:
90
+ raise TypeError("child_configuration must be an exact FrozenJsonObject")
91
+ if freeze_json(self.child_configuration) is not self.child_configuration:
92
+ raise TypeError("child_configuration must already be frozen typed JSON")
93
+ if (
94
+ typed_json_sha256(self.child_configuration)
95
+ == self.parent_configuration_sha256
96
+ ):
97
+ raise ValueError("a finite variation option must change its parent")
98
+ if type(self.family) is not str or _TOKEN.fullmatch(self.family) is None:
99
+ raise ValueError("family must use the closed lowercase token grammar")
100
+ _prompt_text(
101
+ self.description,
102
+ name="description",
103
+ max_bytes=_MAX_DESCRIPTION_BYTES,
104
+ )
105
+ if type(self.metadata) is not tuple:
106
+ raise TypeError("metadata must be an exact tuple")
107
+ if len(self.metadata) > _MAX_METADATA_ITEMS:
108
+ raise ValueError("metadata exceeds the item limit")
109
+ keys: list[str] = []
110
+ for item in self.metadata:
111
+ if type(item) is not tuple or len(item) != 2:
112
+ raise TypeError("metadata entries must be exact key/value tuples")
113
+ key, value = item
114
+ if type(key) is not str or _METADATA_KEY.fullmatch(key) is None:
115
+ raise ValueError(
116
+ "metadata keys must use the closed lowercase token grammar"
117
+ )
118
+ _prompt_text(
119
+ value,
120
+ name=f"metadata value for {key!r}",
121
+ max_bytes=_MAX_METADATA_VALUE_BYTES,
122
+ )
123
+ keys.append(key)
124
+ if keys != sorted(keys) or len(set(keys)) != len(keys):
125
+ raise ValueError("metadata keys must be unique and canonically sorted")
126
+
127
+ @property
128
+ def child_configuration_sha256(self) -> str:
129
+ validate_finite_variation_option(self)
130
+ return typed_json_sha256(self.child_configuration)
131
+
132
+ @property
133
+ def identity_sha256(self) -> str:
134
+ """Bind parent, full child, family, and all prompt-visible semantics."""
135
+
136
+ validate_finite_variation_option(self)
137
+ digest = hashlib.sha256()
138
+ digest.update(_OPTION_HASH_DOMAIN)
139
+ digest.update(_frame(self.option_id.encode("ascii")))
140
+ digest.update(bytes.fromhex(self.parent_configuration_sha256))
141
+ digest.update(_frame(canonical_typed_json_bytes(self.child_configuration)))
142
+ digest.update(_frame(self.family.encode("ascii")))
143
+ digest.update(_frame(self.description.encode("ascii")))
144
+ digest.update(len(self.metadata).to_bytes(8, "big", signed=False))
145
+ for key, value in self.metadata:
146
+ digest.update(_frame(key.encode("ascii")))
147
+ digest.update(_frame(value.encode("ascii")))
148
+ return digest.hexdigest()
149
+
150
+ def prompt_record(self) -> dict[str, object]:
151
+ """Return bounded option facts without exposing the sealed child."""
152
+
153
+ validate_finite_variation_option(self)
154
+ return {
155
+ "option_id": self.option_id,
156
+ "family": self.family,
157
+ "description": self.description,
158
+ "metadata": {key: value for key, value in self.metadata},
159
+ }
160
+
161
+ def evidence_record(self) -> dict[str, object]:
162
+ """Return replay identity without copying the full child tree."""
163
+
164
+ return {
165
+ **self.prompt_record(),
166
+ "parent_configuration_sha256": self.parent_configuration_sha256,
167
+ "child_configuration_sha256": self.child_configuration_sha256,
168
+ "option_identity_sha256": self.identity_sha256,
169
+ }
170
+
171
+ def _validated_values(self) -> tuple[object, ...]:
172
+ validate_finite_variation_option(self)
173
+ return (
174
+ self.option_id,
175
+ self.parent_configuration_sha256,
176
+ canonical_typed_json_bytes(self.child_configuration),
177
+ self.family,
178
+ self.description,
179
+ self.metadata,
180
+ )
181
+
182
+ def __eq__(self, other: object) -> bool:
183
+ if type(self) is not FiniteVariationOption or type(
184
+ other
185
+ ) is not FiniteVariationOption:
186
+ return False
187
+ return self._validated_values() == other._validated_values()
188
+
189
+ def __hash__(self) -> int:
190
+ return hash((FiniteVariationOption, self._validated_values()))
191
+
192
+
193
+ @dataclass(frozen=True, slots=True)
194
+ class FiniteActionEvidenceBinding:
195
+ """Replay-safe link from one reflection contrast to its executed action.
196
+
197
+ The binding deliberately carries only opaque finite-option identity and
198
+ prompt-safe taxonomy. It neither copies a benchmark configuration nor
199
+ assumes that a later portfolio uses the same parent-bound contract.
200
+ ``option_identity_sha256`` and ``contract_identity_sha256`` retain the
201
+ exact originating action and palette for trusted replay.
202
+ """
203
+
204
+ contrast_id: str
205
+ option_id: str
206
+ family: str
207
+ option_identity_sha256: str
208
+ contract_identity_sha256: str
209
+
210
+ def __post_init__(self) -> None:
211
+ require_sha256(self.contrast_id, "contrast_id")
212
+ if type(self.option_id) is not str or _OPTION_ID.fullmatch(
213
+ self.option_id
214
+ ) is None:
215
+ raise ValueError(
216
+ "option_id must use the closed lowercase identifier grammar"
217
+ )
218
+ if type(self.family) is not str or _TOKEN.fullmatch(self.family) is None:
219
+ raise ValueError("family must use the closed lowercase token grammar")
220
+ require_sha256(self.option_identity_sha256, "option_identity_sha256")
221
+ require_sha256(self.contract_identity_sha256, "contract_identity_sha256")
222
+
223
+ def _identity_record(self) -> dict[str, object]:
224
+ self.__post_init__()
225
+ return {
226
+ "schema_version": 1,
227
+ "contrast_id": self.contrast_id,
228
+ "option_id": self.option_id,
229
+ "family": self.family,
230
+ "option_identity_sha256": self.option_identity_sha256,
231
+ "contract_identity_sha256": self.contract_identity_sha256,
232
+ }
233
+
234
+ @property
235
+ def identity_sha256(self) -> str:
236
+ """Bind the source contrast and exact originating finite action."""
237
+
238
+ return hashlib.sha256(
239
+ _ACTION_EVIDENCE_BINDING_HASH_DOMAIN
240
+ + canonical_typed_json_bytes(freeze_json(self._identity_record()))
241
+ ).hexdigest()
242
+
243
+ def to_record(self) -> dict[str, object]:
244
+ """Return a framework-neutral portfolio/evidence projection."""
245
+
246
+ return {
247
+ **self._identity_record(),
248
+ "binding_identity_sha256": self.identity_sha256,
249
+ }
250
+
251
+ def finite_option_record(self) -> dict[str, object]:
252
+ """Reproduce the prompt-safe attribution nested in a contrast row."""
253
+
254
+ self.__post_init__()
255
+ return {
256
+ "option_id": self.option_id,
257
+ "family": self.family,
258
+ "option_identity_sha256": self.option_identity_sha256,
259
+ "contract_identity_sha256": self.contract_identity_sha256,
260
+ }
261
+
262
+
263
+ def validate_finite_variation_option(option: FiniteVariationOption) -> None:
264
+ """Revalidate an exact option at a public trust boundary."""
265
+
266
+ if type(option) is not FiniteVariationOption:
267
+ raise TypeError("option must be an exact FiniteVariationOption")
268
+ FiniteVariationOption.__post_init__(option)
269
+
270
+
271
+ def _validated_option_identity_material(
272
+ option: FiniteVariationOption,
273
+ ) -> tuple[bytes, str, str]:
274
+ """Validate once and derive child bytes, child digest, and option digest."""
275
+
276
+ validate_finite_variation_option(option)
277
+ child_bytes = canonical_typed_json_bytes(option.child_configuration)
278
+ child_sha256 = _typed_json_sha256_canonical_bytes(child_bytes)
279
+ digest = hashlib.sha256()
280
+ digest.update(_OPTION_HASH_DOMAIN)
281
+ digest.update(_frame(option.option_id.encode("ascii")))
282
+ digest.update(bytes.fromhex(option.parent_configuration_sha256))
283
+ digest.update(_frame(child_bytes))
284
+ digest.update(_frame(option.family.encode("ascii")))
285
+ digest.update(_frame(option.description.encode("ascii")))
286
+ digest.update(len(option.metadata).to_bytes(8, "big", signed=False))
287
+ for key, value in option.metadata:
288
+ digest.update(_frame(key.encode("ascii")))
289
+ digest.update(_frame(value.encode("ascii")))
290
+ return child_bytes, child_sha256, digest.hexdigest()
291
+
292
+
293
+ @dataclass(frozen=True, slots=True)
294
+ class ValidatedFiniteVariationIdentityIndex:
295
+ """Immutable identities derived by one complete contract validation pass."""
296
+
297
+ parent_configuration_sha256: str
298
+ contract_identity_sha256: str
299
+ option_ids: tuple[str, ...]
300
+ option_identity_sha256s: tuple[str, ...]
301
+ child_configuration_sha256s: tuple[str, ...]
302
+
303
+ def __post_init__(self) -> None:
304
+ require_sha256(
305
+ self.parent_configuration_sha256,
306
+ "parent_configuration_sha256",
307
+ )
308
+ require_sha256(
309
+ self.contract_identity_sha256,
310
+ "contract_identity_sha256",
311
+ )
312
+ count = len(self.option_ids)
313
+ if count == 0 or any(
314
+ type(value) is not str or _OPTION_ID.fullmatch(value) is None
315
+ for value in self.option_ids
316
+ ):
317
+ raise ValueError("option_ids must be a non-empty exact identifier tuple")
318
+ for name in (
319
+ "option_identity_sha256s",
320
+ "child_configuration_sha256s",
321
+ ):
322
+ values = getattr(self, name)
323
+ if type(values) is not tuple or len(values) != count:
324
+ raise ValueError(f"{name} must cover every indexed option")
325
+ for index, value in enumerate(values):
326
+ require_sha256(value, f"{name}[{index}]")
327
+ if len(set(self.option_ids)) != count:
328
+ raise ValueError("indexed option IDs must be unique")
329
+ if len(set(self.option_identity_sha256s)) != count:
330
+ raise ValueError("indexed option identities must be unique")
331
+ if len(set(self.child_configuration_sha256s)) != count:
332
+ raise ValueError("indexed child configurations must be unique")
333
+
334
+
335
+ @dataclass(frozen=True, slots=True, eq=False)
336
+ class FiniteVariationContract:
337
+ """One catalog snapshot sealed against one immutable parent configuration."""
338
+
339
+ catalog_id: str
340
+ catalog_version: int
341
+ catalog_definition_sha256: str
342
+ parent_configuration: FrozenJsonObject
343
+ options: tuple[FiniteVariationOption, ...]
344
+
345
+ def __post_init__(self) -> None:
346
+ _validated_finite_variation_identity_index(self)
347
+
348
+ @property
349
+ def parent_configuration_sha256(self) -> str:
350
+ return _validated_finite_variation_identity_index(
351
+ self
352
+ ).parent_configuration_sha256
353
+
354
+ @property
355
+ def identity_sha256(self) -> str:
356
+ """Bind catalog semantics, parent identity, option order, and all children."""
357
+
358
+ return _validated_finite_variation_identity_index(
359
+ self
360
+ ).contract_identity_sha256
361
+
362
+ def resolve(self, option_id: str) -> FiniteVariationOption:
363
+ """Resolve exactly one selected ID without accepting aliases."""
364
+
365
+ validate_finite_variation_contract(self)
366
+ if type(option_id) is not str:
367
+ raise TypeError("option_id must be an exact string")
368
+ matches = tuple(
369
+ option for option in self.options if option.option_id == option_id
370
+ )
371
+ if len(matches) != 1:
372
+ raise ValueError("selected option_id is outside the sealed contract")
373
+ return matches[0]
374
+
375
+ def prompt_records(self) -> tuple[dict[str, object], ...]:
376
+ """Return the exact ordered, prompt-safe action palette."""
377
+
378
+ validate_finite_variation_contract(self)
379
+ return tuple(option.prompt_record() for option in self.options)
380
+
381
+ def evidence_record(self) -> dict[str, object]:
382
+ validate_finite_variation_contract(self)
383
+ return {
384
+ "catalog_id": self.catalog_id,
385
+ "catalog_version": self.catalog_version,
386
+ "catalog_definition_sha256": self.catalog_definition_sha256,
387
+ "parent_configuration_sha256": self.parent_configuration_sha256,
388
+ "contract_identity_sha256": self.identity_sha256,
389
+ "options": [option.evidence_record() for option in self.options],
390
+ }
391
+
392
+ def _validated_values(self) -> tuple[object, ...]:
393
+ validate_finite_variation_contract(self)
394
+ return (
395
+ self.catalog_id,
396
+ self.catalog_version,
397
+ self.catalog_definition_sha256,
398
+ canonical_typed_json_bytes(self.parent_configuration),
399
+ tuple(option._validated_values() for option in self.options),
400
+ )
401
+
402
+ def __eq__(self, other: object) -> bool:
403
+ if type(self) is not FiniteVariationContract or type(
404
+ other
405
+ ) is not FiniteVariationContract:
406
+ return False
407
+ return self._validated_values() == other._validated_values()
408
+
409
+ def __hash__(self) -> int:
410
+ return hash((FiniteVariationContract, self._validated_values()))
411
+
412
+
413
+ def _validated_finite_variation_identity_index(
414
+ contract: FiniteVariationContract,
415
+ ) -> ValidatedFiniteVariationIdentityIndex:
416
+ """Validate one contract graph and derive every repeated identity once."""
417
+
418
+ if type(contract) is not FiniteVariationContract:
419
+ raise TypeError("contract must be an exact FiniteVariationContract")
420
+ if type(contract.catalog_id) is not str or _TOKEN.fullmatch(
421
+ contract.catalog_id
422
+ ) is None:
423
+ raise ValueError("catalog_id must use the closed lowercase token grammar")
424
+ if type(contract.catalog_version) is not int or contract.catalog_version <= 0:
425
+ raise ValueError("catalog_version must be a positive exact integer")
426
+ require_sha256(
427
+ contract.catalog_definition_sha256,
428
+ "catalog_definition_sha256",
429
+ )
430
+ if type(contract.parent_configuration) is not FrozenJsonObject:
431
+ raise TypeError("parent_configuration must be an exact FrozenJsonObject")
432
+ parent_bytes = canonical_typed_json_bytes(contract.parent_configuration)
433
+ parent_sha256 = _typed_json_sha256_canonical_bytes(parent_bytes)
434
+ if type(contract.options) is not tuple:
435
+ raise TypeError("options must be an exact tuple")
436
+ if not contract.options:
437
+ raise ValueError("a finite variation contract requires at least one option")
438
+ if len(contract.options) > MAX_FINITE_VARIATION_OPTIONS:
439
+ raise ValueError("finite variation contract exceeds its option limit")
440
+
441
+ option_ids: list[str] = []
442
+ option_hashes: list[str] = []
443
+ child_hashes: list[str] = []
444
+ for option in contract.options:
445
+ _child_bytes, child_sha256, option_sha256 = (
446
+ _validated_option_identity_material(option)
447
+ )
448
+ if option.parent_configuration_sha256 != parent_sha256:
449
+ raise ValueError("option is bound to a different parent configuration")
450
+ # The option validator already rejects a child whose typed digest is
451
+ # its declared parent digest. Reusing that validated digest avoids a
452
+ # second full structural comparison of large frozen configurations.
453
+ option_ids.append(option.option_id)
454
+ option_hashes.append(option_sha256)
455
+ child_hashes.append(child_sha256)
456
+ if len(set(option_ids)) != len(option_ids):
457
+ raise ValueError("finite variation option IDs must be unique")
458
+ if len(set(option_hashes)) != len(option_hashes):
459
+ raise ValueError("finite variation option identities must be unique")
460
+ if len(set(child_hashes)) != len(child_hashes):
461
+ raise ValueError("finite variation options must materialize distinct children")
462
+
463
+ digest = hashlib.sha256()
464
+ digest.update(_CONTRACT_HASH_DOMAIN)
465
+ digest.update(_frame(contract.catalog_id.encode("ascii")))
466
+ digest.update(contract.catalog_version.to_bytes(8, "big", signed=False))
467
+ digest.update(bytes.fromhex(contract.catalog_definition_sha256))
468
+ digest.update(_frame(parent_bytes))
469
+ digest.update(len(contract.options).to_bytes(8, "big", signed=False))
470
+ for option_sha256 in option_hashes:
471
+ digest.update(bytes.fromhex(option_sha256))
472
+ return ValidatedFiniteVariationIdentityIndex(
473
+ parent_configuration_sha256=parent_sha256,
474
+ contract_identity_sha256=digest.hexdigest(),
475
+ option_ids=tuple(option_ids),
476
+ option_identity_sha256s=tuple(option_hashes),
477
+ child_configuration_sha256s=tuple(child_hashes),
478
+ )
479
+
480
+
481
+ def validated_finite_variation_identity_index(
482
+ contract: FiniteVariationContract,
483
+ ) -> ValidatedFiniteVariationIdentityIndex:
484
+ """Return an immutable index from one complete public validation pass."""
485
+
486
+ return _validated_finite_variation_identity_index(contract)
487
+
488
+
489
+ def validate_finite_variation_contract(contract: FiniteVariationContract) -> None:
490
+ """Revalidate an exact contract and its complete option graph."""
491
+
492
+ if type(contract) is not FiniteVariationContract:
493
+ raise TypeError("contract must be an exact FiniteVariationContract")
494
+ FiniteVariationContract.__post_init__(contract)
495
+
496
+
497
+ def bind_finite_action_evidence(
498
+ *,
499
+ contrast_id: str,
500
+ contract: FiniteVariationContract,
501
+ option_id: str,
502
+ ) -> FiniteActionEvidenceBinding:
503
+ """Issue one action-evidence binding only from a sealed contract option."""
504
+
505
+ validate_finite_variation_contract(contract)
506
+ option = contract.resolve(option_id)
507
+ return FiniteActionEvidenceBinding(
508
+ contrast_id=contrast_id,
509
+ option_id=option.option_id,
510
+ family=option.family,
511
+ option_identity_sha256=option.identity_sha256,
512
+ contract_identity_sha256=contract.identity_sha256,
513
+ )
514
+
515
+
516
+ __all__ = [
517
+ "FiniteActionEvidenceBinding",
518
+ "FiniteVariationContract",
519
+ "ValidatedFiniteVariationIdentityIndex",
520
+ "FiniteVariationOption",
521
+ "MAX_FINITE_VARIATION_OPTIONS",
522
+ "bind_finite_action_evidence",
523
+ "validate_finite_variation_contract",
524
+ "validate_finite_variation_option",
525
+ "validated_finite_variation_identity_index",
526
+ ]