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,1011 @@
1
+ """Workload-neutral conserved-backbone and earned-lineage control contracts.
2
+
3
+ This module deliberately contains no candidate schema, objective name,
4
+ workload identity, model identity, or provider field. Adapters authenticate
5
+ where a materialized candidate came from and an archive-utility policy supplies
6
+ conserved per-stage credit. The controller turns positive challenger credit
7
+ into expiring, one-use parent-exposure tickets.
8
+
9
+ Tickets reserve *proposal opportunities*, not evaluations. Descendants still
10
+ pass through the global feasibility, deduplication, and allocation broker.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import hashlib
16
+ import json
17
+ import math
18
+ import re
19
+ from collections.abc import Iterable
20
+ from dataclasses import dataclass, field
21
+ from enum import Enum
22
+ from fractions import Fraction
23
+
24
+ from agent_evolve.domain.ids import CandidateId
25
+ from agent_evolve.domain.patch import require_sha256
26
+
27
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
28
+ _PROVENANCE_DOMAIN = b"agent-evolve:candidate-proposal-provenance:v1\x00"
29
+ _STAGE_CREDIT_DOMAIN = b"agent-evolve:conserved-stage-credit:v1\x00"
30
+ _POLICY_DOMAIN = b"agent-evolve:earned-lineage-policy:v1\x00"
31
+ _TICKET_DOMAIN = b"agent-evolve:earned-reproduction-ticket:v1\x00"
32
+ _ISSUANCE_DOMAIN = b"agent-evolve:earned-reproduction-issuance:v1\x00"
33
+ _RESERVATION_DOMAIN = b"agent-evolve:earned-reproduction-reservation:v1\x00"
34
+ _COMMIT_DOMAIN = b"agent-evolve:earned-reproduction-commit:v1\x00"
35
+ _PARENT_ALLOCATION_DOMAIN = b"agent-evolve:earned-parent-allocation:v1\x00"
36
+ _CEILING_DOMAIN = b"agent-evolve:conserved-backbone-ceiling:v1\x00"
37
+
38
+
39
+ def _canonical_bytes(value: object) -> bytes:
40
+ return json.dumps(
41
+ value,
42
+ allow_nan=False,
43
+ ensure_ascii=True,
44
+ separators=(",", ":"),
45
+ sort_keys=True,
46
+ ).encode("ascii", errors="strict")
47
+
48
+
49
+ def _hash(domain: bytes, value: object) -> str:
50
+ return hashlib.sha256(domain + _canonical_bytes(value)).hexdigest()
51
+
52
+
53
+ def _token(value: str, name: str) -> None:
54
+ if type(value) is not str or _TOKEN.fullmatch(value) is None:
55
+ raise ValueError(f"{name} must use the closed token grammar")
56
+
57
+
58
+ def _canonical_float(value: float, name: str, *, nonnegative: bool = True) -> None:
59
+ if type(value) is not float or not math.isfinite(value):
60
+ raise TypeError(f"{name} must be a finite exact float")
61
+ if nonnegative and value < 0.0:
62
+ raise ValueError(f"{name} must be non-negative")
63
+
64
+
65
+ def _candidate_ids(
66
+ values: tuple[CandidateId, ...],
67
+ name: str,
68
+ *,
69
+ allow_empty: bool,
70
+ ) -> None:
71
+ if type(values) is not tuple or (not allow_empty and not values):
72
+ raise ValueError(f"{name} must be an exact non-empty tuple")
73
+ if any(type(value) is not CandidateId for value in values):
74
+ raise TypeError(f"{name} must contain exact CandidateId values")
75
+ for value in values:
76
+ CandidateId.__post_init__(value)
77
+ if len(set(values)) != len(values):
78
+ raise ValueError(f"{name} cannot contain duplicates")
79
+
80
+
81
+ class ProposalLineageRole(str, Enum):
82
+ """Scientific role of a proposal, independent of its implementation."""
83
+
84
+ BACKBONE = "backbone"
85
+ CHALLENGER = "challenger"
86
+
87
+
88
+ @dataclass(frozen=True, slots=True)
89
+ class CandidateProposalProvenance:
90
+ """Immutable source identity for one fully materialized candidate."""
91
+
92
+ candidate_id: CandidateId
93
+ configuration_sha256: str
94
+ generation: int
95
+ source_role: ProposalLineageRole
96
+ proposal_expert_id: str
97
+ proposal_expert_version: int
98
+ proposal_expert_definition_sha256: str
99
+ operator_id: str
100
+ parent_candidate_ids: tuple[CandidateId, ...]
101
+ decision_cutoff_sha256: str
102
+ source_receipt_sha256: str
103
+
104
+ def __post_init__(self) -> None:
105
+ if type(self.candidate_id) is not CandidateId:
106
+ raise TypeError("candidate_id must be an exact CandidateId")
107
+ CandidateId.__post_init__(self.candidate_id)
108
+ require_sha256(self.configuration_sha256, "configuration_sha256")
109
+ if type(self.generation) is not int or self.generation < 0:
110
+ raise ValueError("generation must be a non-negative exact integer")
111
+ if type(self.source_role) is not ProposalLineageRole:
112
+ raise TypeError("source_role must be an exact ProposalLineageRole")
113
+ _token(self.proposal_expert_id, "proposal_expert_id")
114
+ if (
115
+ type(self.proposal_expert_version) is not int
116
+ or self.proposal_expert_version <= 0
117
+ ):
118
+ raise ValueError("proposal_expert_version must be positive")
119
+ require_sha256(
120
+ self.proposal_expert_definition_sha256,
121
+ "proposal_expert_definition_sha256",
122
+ )
123
+ _token(self.operator_id, "operator_id")
124
+ _candidate_ids(
125
+ self.parent_candidate_ids,
126
+ "parent_candidate_ids",
127
+ allow_empty=True,
128
+ )
129
+ if self.candidate_id in self.parent_candidate_ids:
130
+ raise ValueError("a proposal cannot be its own parent")
131
+ require_sha256(self.decision_cutoff_sha256, "decision_cutoff_sha256")
132
+ require_sha256(self.source_receipt_sha256, "source_receipt_sha256")
133
+
134
+ def _unsigned_record(self) -> dict[str, object]:
135
+ self.__post_init__()
136
+ return {
137
+ "schema_version": 1,
138
+ "candidate_id": self.candidate_id.value,
139
+ "configuration_sha256": self.configuration_sha256,
140
+ "generation": self.generation,
141
+ "source_role": self.source_role.value,
142
+ "proposal_expert": {
143
+ "expert_id": self.proposal_expert_id,
144
+ "expert_version": self.proposal_expert_version,
145
+ "definition_sha256": self.proposal_expert_definition_sha256,
146
+ },
147
+ "operator_id": self.operator_id,
148
+ "parent_candidate_ids": [
149
+ value.value for value in self.parent_candidate_ids
150
+ ],
151
+ "decision_cutoff_sha256": self.decision_cutoff_sha256,
152
+ "source_receipt_sha256": self.source_receipt_sha256,
153
+ "workload_model_provider_fields_present": False,
154
+ }
155
+
156
+ @property
157
+ def provenance_sha256(self) -> str:
158
+ return _hash(_PROVENANCE_DOMAIN, self._unsigned_record())
159
+
160
+ def to_record(self) -> dict[str, object]:
161
+ return {
162
+ **self._unsigned_record(),
163
+ "provenance_sha256": self.provenance_sha256,
164
+ }
165
+
166
+
167
+ @dataclass(frozen=True, slots=True)
168
+ class CandidateConservedCredit:
169
+ """One candidate's non-negative share of a stage archive gain."""
170
+
171
+ candidate_id: CandidateId
172
+ contribution: float
173
+ admitted_to_archive: bool
174
+ outcome_receipt_sha256: str
175
+
176
+ def __post_init__(self) -> None:
177
+ if type(self.candidate_id) is not CandidateId:
178
+ raise TypeError("candidate_id must be an exact CandidateId")
179
+ CandidateId.__post_init__(self.candidate_id)
180
+ _canonical_float(self.contribution, "contribution")
181
+ if type(self.admitted_to_archive) is not bool:
182
+ raise TypeError("admitted_to_archive must be an exact bool")
183
+ if self.contribution > 0.0 and not self.admitted_to_archive:
184
+ raise ValueError("positive archive credit requires archive admission")
185
+ require_sha256(self.outcome_receipt_sha256, "outcome_receipt_sha256")
186
+
187
+ def to_record(self) -> dict[str, object]:
188
+ self.__post_init__()
189
+ return {
190
+ "candidate_id": self.candidate_id.value,
191
+ "contribution_hex": self.contribution.hex(),
192
+ "admitted_to_archive": self.admitted_to_archive,
193
+ "outcome_receipt_sha256": self.outcome_receipt_sha256,
194
+ }
195
+
196
+
197
+ @dataclass(frozen=True, slots=True)
198
+ class ConservedStageCreditReceipt:
199
+ """Candidate credits that close to one authenticated archive transition."""
200
+
201
+ generation: int
202
+ utility_id: str
203
+ utility_version: int
204
+ utility_definition_sha256: str
205
+ pre_archive_sha256: str
206
+ post_archive_sha256: str
207
+ pre_utility: float
208
+ post_utility: float
209
+ contribution_policy_id: str
210
+ contribution_policy_version: int
211
+ contribution_policy_definition_sha256: str
212
+ candidate_credits: tuple[CandidateConservedCredit, ...]
213
+
214
+ def __post_init__(self) -> None:
215
+ if type(self.generation) is not int or self.generation <= 0:
216
+ raise ValueError("generation must be a positive exact integer")
217
+ _token(self.utility_id, "utility_id")
218
+ if type(self.utility_version) is not int or self.utility_version <= 0:
219
+ raise ValueError("utility_version must be positive")
220
+ require_sha256(self.utility_definition_sha256, "utility_definition_sha256")
221
+ require_sha256(self.pre_archive_sha256, "pre_archive_sha256")
222
+ require_sha256(self.post_archive_sha256, "post_archive_sha256")
223
+ _canonical_float(self.pre_utility, "pre_utility")
224
+ _canonical_float(self.post_utility, "post_utility")
225
+ if self.post_utility < self.pre_utility:
226
+ raise ValueError("archive utility cannot decrease")
227
+ _token(self.contribution_policy_id, "contribution_policy_id")
228
+ if (
229
+ type(self.contribution_policy_version) is not int
230
+ or self.contribution_policy_version <= 0
231
+ ):
232
+ raise ValueError("contribution_policy_version must be positive")
233
+ require_sha256(
234
+ self.contribution_policy_definition_sha256,
235
+ "contribution_policy_definition_sha256",
236
+ )
237
+ if type(self.candidate_credits) is not tuple or not self.candidate_credits:
238
+ raise ValueError("candidate_credits must be a non-empty exact tuple")
239
+ if any(
240
+ type(value) is not CandidateConservedCredit
241
+ for value in self.candidate_credits
242
+ ):
243
+ raise TypeError("candidate_credits must contain exact values")
244
+ for value in self.candidate_credits:
245
+ CandidateConservedCredit.__post_init__(value)
246
+ ids = tuple(value.candidate_id.value for value in self.candidate_credits)
247
+ if ids != tuple(sorted(set(ids))):
248
+ raise ValueError("candidate credits must use canonical unique ID order")
249
+ gain = self.post_utility - self.pre_utility
250
+ total = math.fsum(value.contribution for value in self.candidate_credits)
251
+ tolerance = 8.0 * math.ulp(max(1.0, self.post_utility, self.pre_utility))
252
+ if abs(total - gain) > tolerance:
253
+ raise ValueError("candidate contributions do not conserve stage gain")
254
+
255
+ @property
256
+ def stage_gain(self) -> float:
257
+ return self.post_utility - self.pre_utility
258
+
259
+ def _unsigned_record(self) -> dict[str, object]:
260
+ self.__post_init__()
261
+ return {
262
+ "schema_version": 1,
263
+ "generation": self.generation,
264
+ "utility": {
265
+ "utility_id": self.utility_id,
266
+ "utility_version": self.utility_version,
267
+ "definition_sha256": self.utility_definition_sha256,
268
+ "pre_archive_sha256": self.pre_archive_sha256,
269
+ "post_archive_sha256": self.post_archive_sha256,
270
+ "pre_utility_hex": self.pre_utility.hex(),
271
+ "post_utility_hex": self.post_utility.hex(),
272
+ "stage_gain_hex": self.stage_gain.hex(),
273
+ },
274
+ "contribution_policy": {
275
+ "policy_id": self.contribution_policy_id,
276
+ "policy_version": self.contribution_policy_version,
277
+ "definition_sha256": self.contribution_policy_definition_sha256,
278
+ },
279
+ "candidate_credits": [
280
+ value.to_record() for value in self.candidate_credits
281
+ ],
282
+ "credit_conservation_verified": True,
283
+ }
284
+
285
+ @property
286
+ def receipt_sha256(self) -> str:
287
+ return _hash(_STAGE_CREDIT_DOMAIN, self._unsigned_record())
288
+
289
+ def to_record(self) -> dict[str, object]:
290
+ return {**self._unsigned_record(), "receipt_sha256": self.receipt_sha256}
291
+
292
+
293
+ @dataclass(frozen=True, slots=True)
294
+ class EarnedLineagePolicy:
295
+ """Frozen rule mapping positive real challenger credit to tickets."""
296
+
297
+ positive_credit_floor: float = 0.0
298
+ max_tickets_per_stage: int = 2
299
+ max_open_tickets_per_candidate: int = 1
300
+ ticket_ttl_generations: int = 2
301
+ descendant_discount: Fraction = Fraction(1, 2)
302
+
303
+ def __post_init__(self) -> None:
304
+ _canonical_float(self.positive_credit_floor, "positive_credit_floor")
305
+ for name in (
306
+ "max_tickets_per_stage",
307
+ "max_open_tickets_per_candidate",
308
+ "ticket_ttl_generations",
309
+ ):
310
+ value = getattr(self, name)
311
+ if type(value) is not int or value <= 0:
312
+ raise ValueError(f"{name} must be a positive exact integer")
313
+ if type(self.descendant_discount) is not Fraction:
314
+ raise TypeError("descendant_discount must be an exact Fraction")
315
+ if not Fraction(0, 1) < self.descendant_discount <= Fraction(1, 1):
316
+ raise ValueError("descendant_discount must lie in (0, 1]")
317
+
318
+ def _unsigned_record(self) -> dict[str, object]:
319
+ self.__post_init__()
320
+ return {
321
+ "schema_version": 1,
322
+ "positive_credit_floor_hex": self.positive_credit_floor.hex(),
323
+ "max_tickets_per_stage": self.max_tickets_per_stage,
324
+ "max_open_tickets_per_candidate": (
325
+ self.max_open_tickets_per_candidate
326
+ ),
327
+ "ticket_ttl_generations": self.ticket_ttl_generations,
328
+ "descendant_discount": {
329
+ "numerator": self.descendant_discount.numerator,
330
+ "denominator": self.descendant_discount.denominator,
331
+ },
332
+ "quality_signal": "conserved_real_archive_contribution_only",
333
+ "ticket_scope": "one_parent_exposure_not_evaluation_guarantee",
334
+ "workload_model_provider_fields_consulted": False,
335
+ }
336
+
337
+ @property
338
+ def definition_sha256(self) -> str:
339
+ return _hash(_POLICY_DOMAIN, self._unsigned_record())
340
+
341
+ def to_record(self) -> dict[str, object]:
342
+ return {**self._unsigned_record(), "definition_sha256": self.definition_sha256}
343
+
344
+
345
+ @dataclass(frozen=True, slots=True)
346
+ class ReproductionTicket:
347
+ candidate_id: CandidateId
348
+ issued_after_generation: int
349
+ eligible_generation: int
350
+ expires_after_generation: int
351
+ conserved_credit: float
352
+ stage_credit_receipt_sha256: str
353
+ policy_definition_sha256: str
354
+
355
+ def __post_init__(self) -> None:
356
+ if type(self.candidate_id) is not CandidateId:
357
+ raise TypeError("candidate_id must be an exact CandidateId")
358
+ CandidateId.__post_init__(self.candidate_id)
359
+ for name in (
360
+ "issued_after_generation",
361
+ "eligible_generation",
362
+ "expires_after_generation",
363
+ ):
364
+ value = getattr(self, name)
365
+ if type(value) is not int or value <= 0:
366
+ raise ValueError(f"{name} must be a positive exact integer")
367
+ if self.eligible_generation != self.issued_after_generation + 1:
368
+ raise ValueError("a ticket must first become eligible next generation")
369
+ if self.expires_after_generation < self.eligible_generation:
370
+ raise ValueError("ticket expiry precedes eligibility")
371
+ _canonical_float(self.conserved_credit, "conserved_credit")
372
+ if self.conserved_credit <= 0.0:
373
+ raise ValueError("a reproduction ticket requires positive credit")
374
+ require_sha256(
375
+ self.stage_credit_receipt_sha256,
376
+ "stage_credit_receipt_sha256",
377
+ )
378
+ require_sha256(self.policy_definition_sha256, "policy_definition_sha256")
379
+
380
+ def _unsigned_record(self) -> dict[str, object]:
381
+ self.__post_init__()
382
+ return {
383
+ "schema_version": 1,
384
+ "candidate_id": self.candidate_id.value,
385
+ "issued_after_generation": self.issued_after_generation,
386
+ "eligible_generation": self.eligible_generation,
387
+ "expires_after_generation": self.expires_after_generation,
388
+ "conserved_credit_hex": self.conserved_credit.hex(),
389
+ "stage_credit_receipt_sha256": self.stage_credit_receipt_sha256,
390
+ "policy_definition_sha256": self.policy_definition_sha256,
391
+ "entitlement": "one_parent_exposure_not_evaluation_guarantee",
392
+ }
393
+
394
+ @property
395
+ def ticket_sha256(self) -> str:
396
+ return _hash(_TICKET_DOMAIN, self._unsigned_record())
397
+
398
+ def to_record(self) -> dict[str, object]:
399
+ return {**self._unsigned_record(), "ticket_sha256": self.ticket_sha256}
400
+
401
+
402
+ @dataclass(frozen=True, slots=True)
403
+ class ReproductionTicketIssuance:
404
+ generation: int
405
+ stage_credit_receipt_sha256: str
406
+ policy_definition_sha256: str
407
+ tickets: tuple[ReproductionTicket, ...]
408
+
409
+ def __post_init__(self) -> None:
410
+ if type(self.generation) is not int or self.generation <= 0:
411
+ raise ValueError("generation must be positive")
412
+ require_sha256(
413
+ self.stage_credit_receipt_sha256,
414
+ "stage_credit_receipt_sha256",
415
+ )
416
+ require_sha256(self.policy_definition_sha256, "policy_definition_sha256")
417
+ if type(self.tickets) is not tuple or any(
418
+ type(value) is not ReproductionTicket for value in self.tickets
419
+ ):
420
+ raise TypeError("tickets must contain exact ReproductionTicket values")
421
+ for value in self.tickets:
422
+ ReproductionTicket.__post_init__(value)
423
+ if (
424
+ value.issued_after_generation != self.generation
425
+ or value.stage_credit_receipt_sha256
426
+ != self.stage_credit_receipt_sha256
427
+ or value.policy_definition_sha256 != self.policy_definition_sha256
428
+ ):
429
+ raise ValueError("issued ticket differs from issuance identity")
430
+ ids = tuple(value.ticket_sha256 for value in self.tickets)
431
+ if len(set(ids)) != len(ids):
432
+ raise ValueError("issuance cannot repeat a ticket")
433
+
434
+ def _unsigned_record(self) -> dict[str, object]:
435
+ self.__post_init__()
436
+ return {
437
+ "schema_version": 1,
438
+ "generation": self.generation,
439
+ "stage_credit_receipt_sha256": self.stage_credit_receipt_sha256,
440
+ "policy_definition_sha256": self.policy_definition_sha256,
441
+ "tickets": [value.to_record() for value in self.tickets],
442
+ }
443
+
444
+ @property
445
+ def issuance_sha256(self) -> str:
446
+ return _hash(_ISSUANCE_DOMAIN, self._unsigned_record())
447
+
448
+ def to_record(self) -> dict[str, object]:
449
+ return {**self._unsigned_record(), "issuance_sha256": self.issuance_sha256}
450
+
451
+
452
+ @dataclass(frozen=True, slots=True)
453
+ class PreparedReproductionReservation:
454
+ generation: int
455
+ ledger_version: int
456
+ available_candidate_ids_sha256: str
457
+ tickets: tuple[ReproductionTicket, ...]
458
+ policy_definition_sha256: str
459
+
460
+ def __post_init__(self) -> None:
461
+ if type(self.generation) is not int or self.generation <= 0:
462
+ raise ValueError("generation must be positive")
463
+ if type(self.ledger_version) is not int or self.ledger_version < 0:
464
+ raise ValueError("ledger_version must be non-negative")
465
+ require_sha256(
466
+ self.available_candidate_ids_sha256,
467
+ "available_candidate_ids_sha256",
468
+ )
469
+ if type(self.tickets) is not tuple or any(
470
+ type(value) is not ReproductionTicket for value in self.tickets
471
+ ):
472
+ raise TypeError("tickets must contain exact values")
473
+ for value in self.tickets:
474
+ ReproductionTicket.__post_init__(value)
475
+ if not value.eligible_generation <= self.generation <= (
476
+ value.expires_after_generation
477
+ ):
478
+ raise ValueError("reservation contains an ineligible ticket")
479
+ if len({value.candidate_id for value in self.tickets}) != len(self.tickets):
480
+ raise ValueError("reservation repeats a candidate")
481
+ require_sha256(self.policy_definition_sha256, "policy_definition_sha256")
482
+
483
+ @property
484
+ def candidate_ids(self) -> tuple[CandidateId, ...]:
485
+ return tuple(value.candidate_id for value in self.tickets)
486
+
487
+ def _unsigned_record(self) -> dict[str, object]:
488
+ self.__post_init__()
489
+ return {
490
+ "schema_version": 1,
491
+ "generation": self.generation,
492
+ "ledger_version": self.ledger_version,
493
+ "available_candidate_ids_sha256": self.available_candidate_ids_sha256,
494
+ "ticket_sha256s": [value.ticket_sha256 for value in self.tickets],
495
+ "candidate_ids": [value.value for value in self.candidate_ids],
496
+ "policy_definition_sha256": self.policy_definition_sha256,
497
+ }
498
+
499
+ @property
500
+ def reservation_sha256(self) -> str:
501
+ return _hash(_RESERVATION_DOMAIN, self._unsigned_record())
502
+
503
+ def to_record(self) -> dict[str, object]:
504
+ return {
505
+ **self._unsigned_record(),
506
+ "reservation_sha256": self.reservation_sha256,
507
+ }
508
+
509
+
510
+ @dataclass(frozen=True, slots=True)
511
+ class ReproductionReservationCommit:
512
+ reservation_sha256: str
513
+ generation: int
514
+ consumed_ticket_sha256s: tuple[str, ...]
515
+ parent_exposure_receipt_sha256: str
516
+
517
+ def __post_init__(self) -> None:
518
+ require_sha256(self.reservation_sha256, "reservation_sha256")
519
+ if type(self.generation) is not int or self.generation <= 0:
520
+ raise ValueError("generation must be positive")
521
+ if (
522
+ type(self.consumed_ticket_sha256s) is not tuple
523
+ or not self.consumed_ticket_sha256s
524
+ ):
525
+ raise ValueError("consumed_ticket_sha256s must be non-empty")
526
+ for value in self.consumed_ticket_sha256s:
527
+ require_sha256(value, "consumed_ticket_sha256")
528
+ if len(set(self.consumed_ticket_sha256s)) != len(
529
+ self.consumed_ticket_sha256s
530
+ ):
531
+ raise ValueError("commit repeats a consumed ticket")
532
+ require_sha256(
533
+ self.parent_exposure_receipt_sha256,
534
+ "parent_exposure_receipt_sha256",
535
+ )
536
+
537
+ def _unsigned_record(self) -> dict[str, object]:
538
+ self.__post_init__()
539
+ return {
540
+ "schema_version": 1,
541
+ "reservation_sha256": self.reservation_sha256,
542
+ "generation": self.generation,
543
+ "consumed_ticket_sha256s": list(self.consumed_ticket_sha256s),
544
+ "parent_exposure_receipt_sha256": (
545
+ self.parent_exposure_receipt_sha256
546
+ ),
547
+ }
548
+
549
+ @property
550
+ def commit_sha256(self) -> str:
551
+ return _hash(_COMMIT_DOMAIN, self._unsigned_record())
552
+
553
+ def to_record(self) -> dict[str, object]:
554
+ return {**self._unsigned_record(), "commit_sha256": self.commit_sha256}
555
+
556
+
557
+ @dataclass(frozen=True, slots=True)
558
+ class EarnedParentAllocation:
559
+ """A fixed-width parent set containing every reserved earned parent."""
560
+
561
+ generation: int
562
+ base_parent_ids: tuple[CandidateId, ...]
563
+ earned_parent_ids: tuple[CandidateId, ...]
564
+ selected_parent_ids: tuple[CandidateId, ...]
565
+ reservation_sha256: str
566
+
567
+ def __post_init__(self) -> None:
568
+ if type(self.generation) is not int or self.generation <= 0:
569
+ raise ValueError("generation must be positive")
570
+ for name in (
571
+ "base_parent_ids",
572
+ "earned_parent_ids",
573
+ "selected_parent_ids",
574
+ ):
575
+ _candidate_ids(
576
+ getattr(self, name),
577
+ name,
578
+ allow_empty=name == "earned_parent_ids",
579
+ )
580
+ if len(self.selected_parent_ids) != len(self.base_parent_ids):
581
+ raise ValueError("earned parent allocation must preserve width")
582
+ if not set(self.earned_parent_ids).issubset(self.selected_parent_ids):
583
+ raise ValueError("selected parents omit an earned parent")
584
+ require_sha256(self.reservation_sha256, "reservation_sha256")
585
+
586
+ def _unsigned_record(self) -> dict[str, object]:
587
+ self.__post_init__()
588
+ return {
589
+ "schema_version": 1,
590
+ "generation": self.generation,
591
+ "base_parent_ids": [value.value for value in self.base_parent_ids],
592
+ "earned_parent_ids": [value.value for value in self.earned_parent_ids],
593
+ "selected_parent_ids": [
594
+ value.value for value in self.selected_parent_ids
595
+ ],
596
+ "reservation_sha256": self.reservation_sha256,
597
+ "workload_model_provider_fields_consulted": False,
598
+ }
599
+
600
+ @property
601
+ def allocation_sha256(self) -> str:
602
+ return _hash(_PARENT_ALLOCATION_DOMAIN, self._unsigned_record())
603
+
604
+ def to_record(self) -> dict[str, object]:
605
+ return {**self._unsigned_record(), "allocation_sha256": self.allocation_sha256}
606
+
607
+
608
+ def allocate_earned_parents(
609
+ *,
610
+ generation: int,
611
+ base_parent_ids: tuple[CandidateId, ...],
612
+ reservation: PreparedReproductionReservation,
613
+ ) -> EarnedParentAllocation:
614
+ """Inject all earned parents while preserving the base selector's width."""
615
+
616
+ reservation.__post_init__()
617
+ if reservation.generation != generation:
618
+ raise ValueError("reservation belongs to another generation")
619
+ _candidate_ids(base_parent_ids, "base_parent_ids", allow_empty=False)
620
+ earned = reservation.candidate_ids
621
+ if len(earned) > len(base_parent_ids):
622
+ raise ValueError("earned tickets exceed parent-selection width")
623
+ retained = [value for value in base_parent_ids if value not in set(earned)]
624
+ retained = retained[: len(base_parent_ids) - len(earned)]
625
+ selected = tuple(retained) + earned
626
+ if len(selected) != len(base_parent_ids):
627
+ raise ValueError("base and earned parents cannot fill the required width")
628
+ return EarnedParentAllocation(
629
+ generation=generation,
630
+ base_parent_ids=base_parent_ids,
631
+ earned_parent_ids=earned,
632
+ selected_parent_ids=selected,
633
+ reservation_sha256=reservation.reservation_sha256,
634
+ )
635
+
636
+
637
+ @dataclass(frozen=True, slots=True)
638
+ class ConservedBackboneCeilingReceipt:
639
+ """One dual-ledger checkpoint proving a protected additive ceiling."""
640
+
641
+ generation: int
642
+ backbone_state_before_sha256: str
643
+ backbone_ask_receipt_sha256: str
644
+ backbone_outcome_receipt_sha256: str
645
+ backbone_state_after_sha256: str
646
+ backbone_candidate_ids: tuple[CandidateId, ...]
647
+ challenger_candidate_ids: tuple[CandidateId, ...]
648
+ utility_definition_sha256: str
649
+ backbone_utility: float
650
+ union_utility: float
651
+
652
+ def __post_init__(self) -> None:
653
+ if type(self.generation) is not int or self.generation <= 0:
654
+ raise ValueError("generation must be positive")
655
+ for name in (
656
+ "backbone_state_before_sha256",
657
+ "backbone_ask_receipt_sha256",
658
+ "backbone_outcome_receipt_sha256",
659
+ "backbone_state_after_sha256",
660
+ "utility_definition_sha256",
661
+ ):
662
+ require_sha256(getattr(self, name), name)
663
+ _candidate_ids(
664
+ self.backbone_candidate_ids,
665
+ "backbone_candidate_ids",
666
+ allow_empty=False,
667
+ )
668
+ _candidate_ids(
669
+ self.challenger_candidate_ids,
670
+ "challenger_candidate_ids",
671
+ allow_empty=True,
672
+ )
673
+ if set(self.backbone_candidate_ids).intersection(
674
+ self.challenger_candidate_ids
675
+ ):
676
+ raise ValueError("backbone and challenger candidate sets must be disjoint")
677
+ _canonical_float(self.backbone_utility, "backbone_utility")
678
+ _canonical_float(self.union_utility, "union_utility")
679
+ if self.union_utility < self.backbone_utility:
680
+ raise ValueError("additive union utility cannot trail its backbone")
681
+
682
+ @property
683
+ def complement(self) -> float:
684
+ return self.union_utility - self.backbone_utility
685
+
686
+ def _unsigned_record(self) -> dict[str, object]:
687
+ self.__post_init__()
688
+ return {
689
+ "schema_version": 1,
690
+ "generation": self.generation,
691
+ "backbone_state_before_sha256": self.backbone_state_before_sha256,
692
+ "backbone_ask_receipt_sha256": self.backbone_ask_receipt_sha256,
693
+ "backbone_outcome_receipt_sha256": (
694
+ self.backbone_outcome_receipt_sha256
695
+ ),
696
+ "backbone_state_after_sha256": self.backbone_state_after_sha256,
697
+ "backbone_candidate_ids": [
698
+ value.value for value in self.backbone_candidate_ids
699
+ ],
700
+ "challenger_candidate_ids": [
701
+ value.value for value in self.challenger_candidate_ids
702
+ ],
703
+ "utility_definition_sha256": self.utility_definition_sha256,
704
+ "backbone_utility_hex": self.backbone_utility.hex(),
705
+ "union_utility_hex": self.union_utility.hex(),
706
+ "complement_hex": self.complement.hex(),
707
+ "backbone_state_excludes_challenger_outcomes": True,
708
+ }
709
+
710
+ @property
711
+ def receipt_sha256(self) -> str:
712
+ return _hash(_CEILING_DOMAIN, self._unsigned_record())
713
+
714
+ def to_record(self) -> dict[str, object]:
715
+ return {**self._unsigned_record(), "receipt_sha256": self.receipt_sha256}
716
+
717
+
718
+ @dataclass(slots=True)
719
+ class EarnedLineageLedger:
720
+ """Transactional ticket ledger driven only by authenticated prior credit."""
721
+
722
+ policy: EarnedLineagePolicy = field(default_factory=EarnedLineagePolicy)
723
+ _provenance: dict[CandidateId, CandidateProposalProvenance] = field(
724
+ init=False,
725
+ default_factory=dict,
726
+ )
727
+ _credits: list[ConservedStageCreditReceipt] = field(
728
+ init=False,
729
+ default_factory=list,
730
+ )
731
+ _tickets: dict[str, ReproductionTicket] = field(
732
+ init=False,
733
+ default_factory=dict,
734
+ )
735
+ _consumed: set[str] = field(init=False, default_factory=set)
736
+ _reservations: dict[str, PreparedReproductionReservation] = field(
737
+ init=False,
738
+ default_factory=dict,
739
+ )
740
+ _reserved_ticket_ids: set[str] = field(init=False, default_factory=set)
741
+ _commits: list[ReproductionReservationCommit] = field(
742
+ init=False,
743
+ default_factory=list,
744
+ )
745
+ _version: int = field(init=False, default=0)
746
+
747
+ def __post_init__(self) -> None:
748
+ if type(self.policy) is not EarnedLineagePolicy:
749
+ raise TypeError("policy must be an exact EarnedLineagePolicy")
750
+ EarnedLineagePolicy.__post_init__(self.policy)
751
+
752
+ @property
753
+ def version(self) -> int:
754
+ return self._version
755
+
756
+ def register(self, values: Iterable[CandidateProposalProvenance]) -> None:
757
+ batch = tuple(values)
758
+ if not batch:
759
+ raise ValueError("provenance registration batch cannot be empty")
760
+ for value in batch:
761
+ if type(value) is not CandidateProposalProvenance:
762
+ raise TypeError("provenance batch contains an invalid value")
763
+ CandidateProposalProvenance.__post_init__(value)
764
+ if len({value.candidate_id for value in batch}) != len(batch):
765
+ raise ValueError("provenance registration batch repeats a candidate")
766
+ known = set(self._provenance)
767
+ batch_ids = {value.candidate_id for value in batch}
768
+ batch_by_id = {value.candidate_id: value for value in batch}
769
+ for value in batch:
770
+ missing = set(value.parent_candidate_ids) - known - batch_ids
771
+ if missing:
772
+ raise ValueError("proposal provenance names unknown parents")
773
+ for parent_id in value.parent_candidate_ids:
774
+ # Do not use ``dict.get(parent_id, batch_by_id[parent_id])``:
775
+ # Python evaluates the default expression eagerly, so that
776
+ # form raises for a parent that is already registered but is
777
+ # intentionally absent from the current batch.
778
+ if parent_id in self._provenance:
779
+ parent = self._provenance[parent_id]
780
+ else:
781
+ parent = batch_by_id[parent_id]
782
+ if parent.generation >= value.generation:
783
+ raise ValueError(
784
+ "proposal parents must come from an earlier generation"
785
+ )
786
+ previous = self._provenance.get(value.candidate_id)
787
+ if previous is not None and previous != value:
788
+ raise ValueError("candidate provenance is immutable")
789
+ changed = False
790
+ for value in batch:
791
+ if value.candidate_id not in self._provenance:
792
+ self._provenance[value.candidate_id] = value
793
+ changed = True
794
+ if changed:
795
+ self._version += 1
796
+
797
+ def observe(
798
+ self,
799
+ receipt: ConservedStageCreditReceipt,
800
+ ) -> ReproductionTicketIssuance:
801
+ if type(receipt) is not ConservedStageCreditReceipt:
802
+ raise TypeError("receipt must be an exact ConservedStageCreditReceipt")
803
+ ConservedStageCreditReceipt.__post_init__(receipt)
804
+ if self._credits and receipt.generation <= self._credits[-1].generation:
805
+ raise ValueError("stage credit generations must increase strictly")
806
+ unknown = {
807
+ value.candidate_id
808
+ for value in receipt.candidate_credits
809
+ if value.candidate_id not in self._provenance
810
+ }
811
+ if unknown:
812
+ raise ValueError("stage credit names candidates without provenance")
813
+ eligible = [
814
+ value
815
+ for value in receipt.candidate_credits
816
+ if value.contribution > self.policy.positive_credit_floor
817
+ and self._provenance[value.candidate_id].source_role
818
+ is ProposalLineageRole.CHALLENGER
819
+ ]
820
+ eligible.sort(
821
+ key=lambda value: (-value.contribution, value.candidate_id.value)
822
+ )
823
+ tickets: list[ReproductionTicket] = []
824
+ for credit in eligible:
825
+ open_count = sum(
826
+ value.candidate_id == credit.candidate_id
827
+ and ticket_id not in self._consumed
828
+ and value.expires_after_generation >= receipt.generation + 1
829
+ for ticket_id, value in self._tickets.items()
830
+ )
831
+ if open_count >= self.policy.max_open_tickets_per_candidate:
832
+ continue
833
+ ticket = ReproductionTicket(
834
+ candidate_id=credit.candidate_id,
835
+ issued_after_generation=receipt.generation,
836
+ eligible_generation=receipt.generation + 1,
837
+ expires_after_generation=(
838
+ receipt.generation + self.policy.ticket_ttl_generations
839
+ ),
840
+ conserved_credit=credit.contribution,
841
+ stage_credit_receipt_sha256=receipt.receipt_sha256,
842
+ policy_definition_sha256=self.policy.definition_sha256,
843
+ )
844
+ if ticket.ticket_sha256 in self._tickets:
845
+ raise RuntimeError("ticket identity collision")
846
+ tickets.append(ticket)
847
+ if len(tickets) == self.policy.max_tickets_per_stage:
848
+ break
849
+ issuance = ReproductionTicketIssuance(
850
+ generation=receipt.generation,
851
+ stage_credit_receipt_sha256=receipt.receipt_sha256,
852
+ policy_definition_sha256=self.policy.definition_sha256,
853
+ tickets=tuple(tickets),
854
+ )
855
+ self._credits.append(receipt)
856
+ self._tickets.update({value.ticket_sha256: value for value in tickets})
857
+ self._version += 1
858
+ return issuance
859
+
860
+ def prepare(
861
+ self,
862
+ *,
863
+ generation: int,
864
+ available_candidate_ids: tuple[CandidateId, ...],
865
+ maximum_tickets: int,
866
+ ) -> PreparedReproductionReservation:
867
+ if type(generation) is not int or generation <= 0:
868
+ raise ValueError("generation must be positive")
869
+ _candidate_ids(
870
+ available_candidate_ids,
871
+ "available_candidate_ids",
872
+ allow_empty=False,
873
+ )
874
+ if type(maximum_tickets) is not int or maximum_tickets <= 0:
875
+ raise ValueError("maximum_tickets must be positive")
876
+ available = set(available_candidate_ids)
877
+ tickets = [
878
+ value
879
+ for ticket_id, value in self._tickets.items()
880
+ if ticket_id not in self._consumed
881
+ and ticket_id not in self._reserved_ticket_ids
882
+ and value.candidate_id in available
883
+ and value.eligible_generation <= generation
884
+ <= value.expires_after_generation
885
+ ]
886
+ tickets.sort(
887
+ key=lambda value: (
888
+ -value.conserved_credit,
889
+ value.issued_after_generation,
890
+ value.candidate_id.value,
891
+ value.ticket_sha256,
892
+ )
893
+ )
894
+ selected = tuple(tickets[:maximum_tickets])
895
+ available_sha256 = hashlib.sha256(
896
+ _canonical_bytes(sorted(value.value for value in available_candidate_ids))
897
+ ).hexdigest()
898
+ reservation = PreparedReproductionReservation(
899
+ generation=generation,
900
+ ledger_version=self._version,
901
+ available_candidate_ids_sha256=available_sha256,
902
+ tickets=selected,
903
+ policy_definition_sha256=self.policy.definition_sha256,
904
+ )
905
+ if reservation.tickets:
906
+ if reservation.reservation_sha256 in self._reservations:
907
+ raise RuntimeError("reservation identity collision")
908
+ self._reservations[reservation.reservation_sha256] = reservation
909
+ self._reserved_ticket_ids.update(
910
+ value.ticket_sha256 for value in reservation.tickets
911
+ )
912
+ return reservation
913
+
914
+ def abort(self, reservation: PreparedReproductionReservation) -> None:
915
+ reservation.__post_init__()
916
+ if not reservation.tickets:
917
+ return
918
+ known = self._reservations.pop(reservation.reservation_sha256, None)
919
+ if known != reservation:
920
+ raise ValueError("reservation is absent, stale, or already closed")
921
+ self._reserved_ticket_ids.difference_update(
922
+ value.ticket_sha256 for value in reservation.tickets
923
+ )
924
+
925
+ def commit(
926
+ self,
927
+ reservation: PreparedReproductionReservation,
928
+ *,
929
+ parent_exposure_receipt_sha256: str,
930
+ ) -> ReproductionReservationCommit:
931
+ reservation.__post_init__()
932
+ require_sha256(
933
+ parent_exposure_receipt_sha256,
934
+ "parent_exposure_receipt_sha256",
935
+ )
936
+ if not reservation.tickets:
937
+ raise ValueError("an empty reservation has nothing to commit")
938
+ known = self._reservations.pop(reservation.reservation_sha256, None)
939
+ if known != reservation:
940
+ raise ValueError("reservation is absent, stale, or already closed")
941
+ ticket_ids = tuple(value.ticket_sha256 for value in reservation.tickets)
942
+ if any(value in self._consumed for value in ticket_ids):
943
+ raise RuntimeError("a reserved ticket was consumed concurrently")
944
+ commit = ReproductionReservationCommit(
945
+ reservation_sha256=reservation.reservation_sha256,
946
+ generation=reservation.generation,
947
+ consumed_ticket_sha256s=ticket_ids,
948
+ parent_exposure_receipt_sha256=parent_exposure_receipt_sha256,
949
+ )
950
+ self._reserved_ticket_ids.difference_update(ticket_ids)
951
+ self._consumed.update(ticket_ids)
952
+ self._commits.append(commit)
953
+ self._version += 1
954
+ return commit
955
+
956
+ def to_record(self, *, current_generation: int) -> dict[str, object]:
957
+ if type(current_generation) is not int or current_generation < 0:
958
+ raise ValueError("current_generation must be non-negative")
959
+ expired = {
960
+ ticket_id
961
+ for ticket_id, value in self._tickets.items()
962
+ if value.expires_after_generation < current_generation
963
+ and ticket_id not in self._consumed
964
+ }
965
+ return {
966
+ "schema_version": 1,
967
+ "policy": self.policy.to_record(),
968
+ "ledger_version": self._version,
969
+ "provenance": [
970
+ value.to_record()
971
+ for value in sorted(
972
+ self._provenance.values(),
973
+ key=lambda item: item.candidate_id.value,
974
+ )
975
+ ],
976
+ "stage_credits": [value.to_record() for value in self._credits],
977
+ "tickets": [
978
+ value.to_record()
979
+ for value in sorted(
980
+ self._tickets.values(),
981
+ key=lambda item: item.ticket_sha256,
982
+ )
983
+ ],
984
+ "consumed_ticket_sha256s": sorted(self._consumed),
985
+ "expired_unconsumed_ticket_sha256s": sorted(expired),
986
+ "open_reservations": [
987
+ value.to_record()
988
+ for value in sorted(
989
+ self._reservations.values(),
990
+ key=lambda item: item.reservation_sha256,
991
+ )
992
+ ],
993
+ "commits": [value.to_record() for value in self._commits],
994
+ }
995
+
996
+
997
+ __all__ = [
998
+ "CandidateConservedCredit",
999
+ "CandidateProposalProvenance",
1000
+ "ConservedBackboneCeilingReceipt",
1001
+ "ConservedStageCreditReceipt",
1002
+ "EarnedLineageLedger",
1003
+ "EarnedLineagePolicy",
1004
+ "EarnedParentAllocation",
1005
+ "PreparedReproductionReservation",
1006
+ "ProposalLineageRole",
1007
+ "ReproductionReservationCommit",
1008
+ "ReproductionTicket",
1009
+ "ReproductionTicketIssuance",
1010
+ "allocate_earned_parents",
1011
+ ]