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,651 @@
1
+ """Workload-neutral delayed frontier, lineage, and terminal credit projection.
2
+
3
+ The service joins framework candidate lineage to previously sealed contextual
4
+ observations. It never reads candidate configuration fields, objective names,
5
+ model prose, or provider metadata. Recombination credit is selection-
6
+ conditioned evidence: a source receives a positive descendant verdict only
7
+ when at least one evaluated direct recombinant using it survives on the sealed
8
+ post-stage front. Unselected sources remain unobserved for that channel rather
9
+ than being mislabeled as failures. Every source candidate independently
10
+ receives post-stage frontier-survival credit. Terminal persistence is
11
+ adjudicated separately after successful campaign completion.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import hashlib
17
+ import json
18
+ from dataclasses import dataclass, field
19
+
20
+ from agent_evolve.application.contextual_search_controller import (
21
+ ContextualSearchDelayedCredit,
22
+ ContextualSearchObservation,
23
+ )
24
+ from agent_evolve.application.portfolio_evolution import PortfolioMemberDisposition
25
+ from agent_evolve.application.portfolio_recombination import (
26
+ PortfolioRecombinationWaveResult,
27
+ )
28
+ from agent_evolve.domain.ids import CandidateId
29
+ from agent_evolve.domain.patch import require_sha256
30
+
31
+
32
+ _POST_RECOMBINATION_BATCH_DOMAIN = (
33
+ b"agent-evolve:contextual-post-recombination-credit-batch:v1\x00"
34
+ )
35
+ _POST_STAGE_SURVIVAL_BATCH_DOMAIN = (
36
+ b"agent-evolve:contextual-post-stage-survival-credit-batch:v1\x00"
37
+ )
38
+ _PERSISTENCE_BATCH_DOMAIN = (
39
+ b"agent-evolve:contextual-terminal-persistence-credit-batch:v1\x00"
40
+ )
41
+ CONTEXTUAL_DELAYED_CREDIT_POLICY_ID = "sealed_multi_horizon_contextual_credit"
42
+ CONTEXTUAL_DELAYED_CREDIT_POLICY_VERSION = 2
43
+ CONTEXTUAL_DELAYED_CREDIT_DEFINITION_SHA256 = hashlib.sha256(
44
+ b"agent-evolve:sealed-multi-horizon-contextual-credit:v2;"
45
+ b"lineage=framework-candidate-ids;stage-survival=all-source-candidates-on-"
46
+ b"sealed-post-stage-front;descendant=selected-direct-recombinant-survives-"
47
+ b"sealed-post-stage-front;unselected-descendant=unobserved;"
48
+ b"persistence=successful-campaign-terminal-front-membership;"
49
+ b"availability=strictly-after-source-wave;"
50
+ b"workload-objective-model-provider-fields=false"
51
+ ).hexdigest()
52
+ CONTEXTUAL_POST_STAGE_SURVIVAL_POLICY_ID = "sealed_contextual_stage_survival"
53
+ CONTEXTUAL_POST_STAGE_SURVIVAL_POLICY_VERSION = 1
54
+ CONTEXTUAL_POST_STAGE_SURVIVAL_DEFINITION_SHA256 = hashlib.sha256(
55
+ b"agent-evolve:sealed-contextual-stage-survival:v1;"
56
+ b"source=prior-contextual-observations;"
57
+ b"stage-survival=sealed-post-stage-front-membership;"
58
+ b"descendant=unobserved-when-no-source-descendant-attempt;"
59
+ b"availability=strictly-after-source-wave;"
60
+ b"workload-objective-model-provider-fields=false"
61
+ ).hexdigest()
62
+
63
+
64
+ def _canonical_json(value: object) -> bytes:
65
+ return json.dumps(
66
+ value,
67
+ allow_nan=False,
68
+ ensure_ascii=True,
69
+ separators=(",", ":"),
70
+ sort_keys=True,
71
+ ).encode("ascii", errors="strict")
72
+
73
+
74
+ def _canonical_candidate_ids(
75
+ values: tuple[CandidateId, ...],
76
+ *,
77
+ name: str,
78
+ allow_empty: bool = False,
79
+ ) -> tuple[CandidateId, ...]:
80
+ if type(values) is not tuple or any(
81
+ type(value) is not CandidateId for value in values
82
+ ):
83
+ raise TypeError(f"{name} must contain exact CandidateId values")
84
+ for value in values:
85
+ CandidateId.__post_init__(value)
86
+ if not allow_empty and not values:
87
+ raise ValueError(f"{name} must be non-empty")
88
+ if values != tuple(sorted(set(values))):
89
+ raise ValueError(f"{name} must be unique and canonical")
90
+ return values
91
+
92
+
93
+ @dataclass(frozen=True, slots=True)
94
+ class ContextualPostRecombinationCreditBatch:
95
+ campaign_scope_sha256: str
96
+ source_wave_index: int
97
+ available_at_wave_index: int
98
+ recombination_receipt_sha256s: tuple[str, ...]
99
+ selected_source_candidate_ids: tuple[CandidateId, ...]
100
+ stage_surviving_source_candidate_ids: tuple[CandidateId, ...]
101
+ useful_descendant_candidate_ids: tuple[CandidateId, ...]
102
+ post_stage_front_candidate_ids: tuple[CandidateId, ...]
103
+ credits: tuple[ContextualSearchDelayedCredit, ...]
104
+ batch_sha256: str = field(init=False)
105
+
106
+ def __post_init__(self) -> None:
107
+ require_sha256(self.campaign_scope_sha256, "campaign_scope_sha256")
108
+ if type(self.source_wave_index) is not int or self.source_wave_index <= 0:
109
+ raise ValueError("source_wave_index must be positive")
110
+ if (
111
+ type(self.available_at_wave_index) is not int
112
+ or self.available_at_wave_index <= self.source_wave_index
113
+ ):
114
+ raise ValueError("descendant credit must become available later")
115
+ if (
116
+ type(self.recombination_receipt_sha256s) is not tuple
117
+ or not self.recombination_receipt_sha256s
118
+ or self.recombination_receipt_sha256s
119
+ != tuple(sorted(set(self.recombination_receipt_sha256s)))
120
+ ):
121
+ raise ValueError("recombination receipts must be non-empty and canonical")
122
+ for value in self.recombination_receipt_sha256s:
123
+ require_sha256(value, "recombination_receipt_sha256")
124
+ _canonical_candidate_ids(
125
+ self.selected_source_candidate_ids,
126
+ name="selected_source_candidate_ids",
127
+ allow_empty=True,
128
+ )
129
+ _canonical_candidate_ids(
130
+ self.stage_surviving_source_candidate_ids,
131
+ name="stage_surviving_source_candidate_ids",
132
+ allow_empty=True,
133
+ )
134
+ _canonical_candidate_ids(
135
+ self.useful_descendant_candidate_ids,
136
+ name="useful_descendant_candidate_ids",
137
+ allow_empty=True,
138
+ )
139
+ _canonical_candidate_ids(
140
+ self.post_stage_front_candidate_ids,
141
+ name="post_stage_front_candidate_ids",
142
+ )
143
+ front = set(self.post_stage_front_candidate_ids)
144
+ if not set(self.stage_surviving_source_candidate_ids).issubset(front):
145
+ raise ValueError("stage survivors escape the post-stage front")
146
+ if not set(self.useful_descendant_candidate_ids).issubset(front):
147
+ raise ValueError("useful descendants escape the post-stage front")
148
+ if (
149
+ type(self.credits) is not tuple
150
+ or not self.credits
151
+ or any(
152
+ type(value) is not ContextualSearchDelayedCredit
153
+ for value in self.credits
154
+ )
155
+ ):
156
+ raise ValueError("credits must contain exact delayed-credit values")
157
+ for value in self.credits:
158
+ value.__post_init__()
159
+ if (
160
+ value.campaign_scope_sha256 != self.campaign_scope_sha256
161
+ or value.available_at_wave_index != self.available_at_wave_index
162
+ or value.final_front_persisted is not None
163
+ or value.stage_front_persisted is None
164
+ ):
165
+ raise ValueError("post-recombination credit differs from its batch")
166
+ if tuple(value.credit_sha256 for value in self.credits) != tuple(
167
+ sorted({value.credit_sha256 for value in self.credits})
168
+ ):
169
+ raise ValueError("post-recombination credits must be unique and canonical")
170
+ object.__setattr__(
171
+ self,
172
+ "batch_sha256",
173
+ hashlib.sha256(
174
+ _POST_RECOMBINATION_BATCH_DOMAIN
175
+ + _canonical_json(self._unsigned_record())
176
+ ).hexdigest(),
177
+ )
178
+
179
+ def _unsigned_record(self) -> dict[str, object]:
180
+ return {
181
+ "schema_version": 1,
182
+ "campaign_scope_sha256": self.campaign_scope_sha256,
183
+ "source_wave_index": self.source_wave_index,
184
+ "available_at_wave_index": self.available_at_wave_index,
185
+ "recombination_receipt_sha256s": list(self.recombination_receipt_sha256s),
186
+ "selected_source_candidate_ids": [
187
+ value.value for value in self.selected_source_candidate_ids
188
+ ],
189
+ "stage_surviving_source_candidate_ids": [
190
+ value.value for value in self.stage_surviving_source_candidate_ids
191
+ ],
192
+ "useful_descendant_candidate_ids": [
193
+ value.value for value in self.useful_descendant_candidate_ids
194
+ ],
195
+ "post_stage_front_candidate_ids": [
196
+ value.value for value in self.post_stage_front_candidate_ids
197
+ ],
198
+ "credit_sha256s": [value.credit_sha256 for value in self.credits],
199
+ "policy": {
200
+ "policy_id": CONTEXTUAL_DELAYED_CREDIT_POLICY_ID,
201
+ "policy_version": CONTEXTUAL_DELAYED_CREDIT_POLICY_VERSION,
202
+ "definition_sha256": CONTEXTUAL_DELAYED_CREDIT_DEFINITION_SHA256,
203
+ },
204
+ }
205
+
206
+ def to_record(self) -> dict[str, object]:
207
+ self.__post_init__()
208
+ return {
209
+ **self._unsigned_record(),
210
+ "credits": [value.to_record() for value in self.credits],
211
+ "batch_sha256": self.batch_sha256,
212
+ }
213
+
214
+
215
+ @dataclass(frozen=True, slots=True)
216
+ class ContextualPostStageSurvivalCreditBatch:
217
+ """Persistence evidence when a later stage evaluates no source descendant.
218
+
219
+ A capacity broker can legitimately allocate a transition to another
220
+ proposal expert. The prior source candidates still acquire observable
221
+ post-stage frontier-survival outcomes, while descendant usefulness remains
222
+ unobserved rather than being mislabeled false.
223
+ """
224
+
225
+ campaign_scope_sha256: str
226
+ source_wave_index: int
227
+ available_at_wave_index: int
228
+ stage_request_sha256: str
229
+ source_observation_sha256s: tuple[str, ...]
230
+ stage_surviving_source_candidate_ids: tuple[CandidateId, ...]
231
+ post_stage_front_candidate_ids: tuple[CandidateId, ...]
232
+ credits: tuple[ContextualSearchDelayedCredit, ...]
233
+ batch_sha256: str = field(init=False)
234
+
235
+ def __post_init__(self) -> None:
236
+ require_sha256(self.campaign_scope_sha256, "campaign_scope_sha256")
237
+ require_sha256(self.stage_request_sha256, "stage_request_sha256")
238
+ if type(self.source_wave_index) is not int or self.source_wave_index <= 0:
239
+ raise ValueError("source_wave_index must be positive")
240
+ if (
241
+ type(self.available_at_wave_index) is not int
242
+ or self.available_at_wave_index <= self.source_wave_index
243
+ ):
244
+ raise ValueError("stage-survival credit must become available later")
245
+ if (
246
+ type(self.source_observation_sha256s) is not tuple
247
+ or not self.source_observation_sha256s
248
+ or self.source_observation_sha256s
249
+ != tuple(sorted(set(self.source_observation_sha256s)))
250
+ ):
251
+ raise ValueError("source observations must be non-empty and canonical")
252
+ for value in self.source_observation_sha256s:
253
+ require_sha256(value, "source_observation_sha256")
254
+ _canonical_candidate_ids(
255
+ self.stage_surviving_source_candidate_ids,
256
+ name="stage_surviving_source_candidate_ids",
257
+ allow_empty=True,
258
+ )
259
+ front = _canonical_candidate_ids(
260
+ self.post_stage_front_candidate_ids,
261
+ name="post_stage_front_candidate_ids",
262
+ )
263
+ if not set(self.stage_surviving_source_candidate_ids).issubset(front):
264
+ raise ValueError("stage survivors escape the post-stage front")
265
+ if (
266
+ type(self.credits) is not tuple
267
+ or not self.credits
268
+ or any(
269
+ type(value) is not ContextualSearchDelayedCredit
270
+ for value in self.credits
271
+ )
272
+ ):
273
+ raise ValueError("credits must contain exact delayed-credit values")
274
+ for value in self.credits:
275
+ value.__post_init__()
276
+ if (
277
+ value.campaign_scope_sha256 != self.campaign_scope_sha256
278
+ or value.available_at_wave_index != self.available_at_wave_index
279
+ or value.stage_front_persisted is None
280
+ or value.final_front_persisted is not None
281
+ or value.useful_descendant_observed is not None
282
+ ):
283
+ raise ValueError("post-stage survival credit differs from its batch")
284
+ credit_sources = tuple(
285
+ sorted(value.source_observation_sha256 for value in self.credits)
286
+ )
287
+ if credit_sources != self.source_observation_sha256s:
288
+ raise ValueError("post-stage credits differ from source observations")
289
+ if tuple(value.credit_sha256 for value in self.credits) != tuple(
290
+ sorted({value.credit_sha256 for value in self.credits})
291
+ ):
292
+ raise ValueError("post-stage credits must be unique and canonical")
293
+ object.__setattr__(
294
+ self,
295
+ "batch_sha256",
296
+ hashlib.sha256(
297
+ _POST_STAGE_SURVIVAL_BATCH_DOMAIN
298
+ + _canonical_json(self._unsigned_record())
299
+ ).hexdigest(),
300
+ )
301
+
302
+ def _unsigned_record(self) -> dict[str, object]:
303
+ return {
304
+ "schema_version": 1,
305
+ "campaign_scope_sha256": self.campaign_scope_sha256,
306
+ "source_wave_index": self.source_wave_index,
307
+ "available_at_wave_index": self.available_at_wave_index,
308
+ "stage_request_sha256": self.stage_request_sha256,
309
+ "source_observation_sha256s": list(self.source_observation_sha256s),
310
+ "stage_surviving_source_candidate_ids": [
311
+ value.value for value in self.stage_surviving_source_candidate_ids
312
+ ],
313
+ "post_stage_front_candidate_ids": [
314
+ value.value for value in self.post_stage_front_candidate_ids
315
+ ],
316
+ "credit_sha256s": [value.credit_sha256 for value in self.credits],
317
+ "descendant_outcome": "unobserved_no_source_descendant_attempt",
318
+ "policy": {
319
+ "policy_id": CONTEXTUAL_POST_STAGE_SURVIVAL_POLICY_ID,
320
+ "policy_version": CONTEXTUAL_POST_STAGE_SURVIVAL_POLICY_VERSION,
321
+ "definition_sha256": (
322
+ CONTEXTUAL_POST_STAGE_SURVIVAL_DEFINITION_SHA256
323
+ ),
324
+ },
325
+ }
326
+
327
+ def to_record(self) -> dict[str, object]:
328
+ self.__post_init__()
329
+ return {
330
+ **self._unsigned_record(),
331
+ "credits": [value.to_record() for value in self.credits],
332
+ "batch_sha256": self.batch_sha256,
333
+ }
334
+
335
+
336
+ @dataclass(frozen=True, slots=True)
337
+ class ContextualTerminalPersistenceCreditBatch:
338
+ campaign_scope_sha256: str
339
+ available_at_wave_index: int
340
+ finalization_request_sha256: str
341
+ terminal_front_candidate_ids: tuple[CandidateId, ...]
342
+ credits: tuple[ContextualSearchDelayedCredit, ...]
343
+ batch_sha256: str = field(init=False)
344
+
345
+ def __post_init__(self) -> None:
346
+ require_sha256(self.campaign_scope_sha256, "campaign_scope_sha256")
347
+ require_sha256(
348
+ self.finalization_request_sha256,
349
+ "finalization_request_sha256",
350
+ )
351
+ if (
352
+ type(self.available_at_wave_index) is not int
353
+ or self.available_at_wave_index <= 1
354
+ ):
355
+ raise ValueError("terminal credit availability must follow search")
356
+ _canonical_candidate_ids(
357
+ self.terminal_front_candidate_ids,
358
+ name="terminal_front_candidate_ids",
359
+ )
360
+ if (
361
+ type(self.credits) is not tuple
362
+ or not self.credits
363
+ or any(
364
+ type(value) is not ContextualSearchDelayedCredit
365
+ for value in self.credits
366
+ )
367
+ ):
368
+ raise ValueError("credits must contain exact delayed-credit values")
369
+ for value in self.credits:
370
+ value.__post_init__()
371
+ if (
372
+ value.campaign_scope_sha256 != self.campaign_scope_sha256
373
+ or value.available_at_wave_index != self.available_at_wave_index
374
+ or value.stage_front_persisted is not None
375
+ or value.final_front_persisted is None
376
+ or value.useful_descendant_observed is not None
377
+ ):
378
+ raise ValueError("terminal persistence credit differs from its batch")
379
+ if tuple(value.credit_sha256 for value in self.credits) != tuple(
380
+ sorted({value.credit_sha256 for value in self.credits})
381
+ ):
382
+ raise ValueError("terminal credits must be unique and canonical")
383
+ object.__setattr__(
384
+ self,
385
+ "batch_sha256",
386
+ hashlib.sha256(
387
+ _PERSISTENCE_BATCH_DOMAIN + _canonical_json(self._unsigned_record())
388
+ ).hexdigest(),
389
+ )
390
+
391
+ def _unsigned_record(self) -> dict[str, object]:
392
+ return {
393
+ "schema_version": 1,
394
+ "campaign_scope_sha256": self.campaign_scope_sha256,
395
+ "available_at_wave_index": self.available_at_wave_index,
396
+ "finalization_request_sha256": self.finalization_request_sha256,
397
+ "terminal_front_candidate_ids": [
398
+ value.value for value in self.terminal_front_candidate_ids
399
+ ],
400
+ "credit_sha256s": [value.credit_sha256 for value in self.credits],
401
+ "policy": {
402
+ "policy_id": CONTEXTUAL_DELAYED_CREDIT_POLICY_ID,
403
+ "policy_version": CONTEXTUAL_DELAYED_CREDIT_POLICY_VERSION,
404
+ "definition_sha256": CONTEXTUAL_DELAYED_CREDIT_DEFINITION_SHA256,
405
+ },
406
+ }
407
+
408
+ def to_record(self) -> dict[str, object]:
409
+ self.__post_init__()
410
+ return {
411
+ **self._unsigned_record(),
412
+ "credits": [value.to_record() for value in self.credits],
413
+ "batch_sha256": self.batch_sha256,
414
+ }
415
+
416
+
417
+ def observe_contextual_post_recombination_credit(
418
+ *,
419
+ campaign_scope_sha256: str,
420
+ source_wave_index: int,
421
+ observations: tuple[ContextualSearchObservation, ...],
422
+ results: tuple[PortfolioRecombinationWaveResult, ...],
423
+ post_stage_front_candidate_ids: tuple[CandidateId, ...],
424
+ ) -> ContextualPostRecombinationCreditBatch:
425
+ """Adjudicate source survival and selected-source descendant yield."""
426
+
427
+ require_sha256(campaign_scope_sha256, "campaign_scope_sha256")
428
+ if type(source_wave_index) is not int or source_wave_index <= 0:
429
+ raise ValueError("source_wave_index must be positive")
430
+ if (
431
+ type(observations) is not tuple
432
+ or not observations
433
+ or any(type(value) is not ContextualSearchObservation for value in observations)
434
+ ):
435
+ raise ValueError("observations must contain exact contextual values")
436
+ observation_by_candidate: dict[CandidateId, ContextualSearchObservation] = {}
437
+ for value in observations:
438
+ value.__post_init__()
439
+ if (
440
+ value.campaign_scope_sha256 != campaign_scope_sha256
441
+ or value.wave_index != source_wave_index
442
+ ):
443
+ raise ValueError("observation differs from the source wave")
444
+ if value.candidate_id is None:
445
+ raise ValueError("delayed credit requires candidate-bound observations")
446
+ if value.candidate_id in observation_by_candidate:
447
+ raise ValueError("contextual source wave repeats a candidate")
448
+ observation_by_candidate[value.candidate_id] = value
449
+ if (
450
+ type(results) is not tuple
451
+ or not results
452
+ or any(type(value) is not PortfolioRecombinationWaveResult for value in results)
453
+ ):
454
+ raise ValueError("results must contain exact recombination values")
455
+ front = _canonical_candidate_ids(
456
+ post_stage_front_candidate_ids,
457
+ name="post_stage_front_candidate_ids",
458
+ )
459
+ front_set = set(front)
460
+ stage_survivors = set(observation_by_candidate) & front_set
461
+ selected_sources: set[CandidateId] = set()
462
+ useful_descendants: set[CandidateId] = set()
463
+ useful_by_source: dict[CandidateId, bool] = {}
464
+ receipts: list[str] = []
465
+ for result in results:
466
+ result.__post_init__()
467
+ receipts.append(result.receipt.receipt_sha256)
468
+ for member in result.receipt.members:
469
+ selected_sources.update(member.pair_ids)
470
+ useful = (
471
+ member.disposition is PortfolioMemberDisposition.SCORED
472
+ and member.target_candidate_id in front_set
473
+ )
474
+ if useful:
475
+ useful_descendants.add(member.target_candidate_id)
476
+ for source_id in member.pair_ids:
477
+ useful_by_source[source_id] = (
478
+ useful_by_source.get(source_id, False) or useful
479
+ )
480
+ missing = selected_sources - set(observation_by_candidate)
481
+ if missing:
482
+ raise ValueError("recombination cites a source without contextual observation")
483
+ credits = tuple(
484
+ sorted(
485
+ (
486
+ ContextualSearchDelayedCredit(
487
+ campaign_scope_sha256=campaign_scope_sha256,
488
+ source_observation_sha256=(
489
+ observation_by_candidate[candidate_id].observation_sha256
490
+ ),
491
+ available_at_wave_index=source_wave_index + 1,
492
+ stage_front_persisted=candidate_id in stage_survivors,
493
+ useful_descendant_observed=(
494
+ useful_by_source[candidate_id]
495
+ if candidate_id in selected_sources
496
+ else None
497
+ ),
498
+ )
499
+ for candidate_id in sorted(observation_by_candidate)
500
+ ),
501
+ key=lambda value: value.credit_sha256,
502
+ )
503
+ )
504
+ return ContextualPostRecombinationCreditBatch(
505
+ campaign_scope_sha256=campaign_scope_sha256,
506
+ source_wave_index=source_wave_index,
507
+ available_at_wave_index=source_wave_index + 1,
508
+ recombination_receipt_sha256s=tuple(sorted(receipts)),
509
+ selected_source_candidate_ids=tuple(sorted(selected_sources)),
510
+ stage_surviving_source_candidate_ids=tuple(sorted(stage_survivors)),
511
+ useful_descendant_candidate_ids=tuple(sorted(useful_descendants)),
512
+ post_stage_front_candidate_ids=front,
513
+ credits=credits,
514
+ )
515
+
516
+
517
+ def observe_contextual_post_stage_survival(
518
+ *,
519
+ campaign_scope_sha256: str,
520
+ source_wave_index: int,
521
+ stage_request_sha256: str,
522
+ observations: tuple[ContextualSearchObservation, ...],
523
+ post_stage_front_candidate_ids: tuple[CandidateId, ...],
524
+ ) -> ContextualPostStageSurvivalCreditBatch:
525
+ """Adjudicate source persistence when no source descendant was attempted."""
526
+
527
+ require_sha256(campaign_scope_sha256, "campaign_scope_sha256")
528
+ require_sha256(stage_request_sha256, "stage_request_sha256")
529
+ if type(source_wave_index) is not int or source_wave_index <= 0:
530
+ raise ValueError("source_wave_index must be positive")
531
+ if (
532
+ type(observations) is not tuple
533
+ or not observations
534
+ or any(type(value) is not ContextualSearchObservation for value in observations)
535
+ ):
536
+ raise ValueError("observations must contain exact contextual values")
537
+ observation_by_candidate: dict[CandidateId, ContextualSearchObservation] = {}
538
+ for value in observations:
539
+ value.__post_init__()
540
+ if (
541
+ value.campaign_scope_sha256 != campaign_scope_sha256
542
+ or value.wave_index != source_wave_index
543
+ ):
544
+ raise ValueError("observation differs from the source wave")
545
+ if value.candidate_id is None:
546
+ raise ValueError("stage-survival credit requires candidate-bound values")
547
+ if value.candidate_id in observation_by_candidate:
548
+ raise ValueError("contextual source wave repeats a candidate")
549
+ observation_by_candidate[value.candidate_id] = value
550
+ front = _canonical_candidate_ids(
551
+ post_stage_front_candidate_ids,
552
+ name="post_stage_front_candidate_ids",
553
+ )
554
+ front_set = set(front)
555
+ survivors = tuple(sorted(set(observation_by_candidate) & front_set))
556
+ credits = tuple(
557
+ sorted(
558
+ (
559
+ ContextualSearchDelayedCredit(
560
+ campaign_scope_sha256=campaign_scope_sha256,
561
+ source_observation_sha256=value.observation_sha256,
562
+ available_at_wave_index=source_wave_index + 1,
563
+ stage_front_persisted=candidate_id in front_set,
564
+ )
565
+ for candidate_id, value in observation_by_candidate.items()
566
+ ),
567
+ key=lambda value: value.credit_sha256,
568
+ )
569
+ )
570
+ return ContextualPostStageSurvivalCreditBatch(
571
+ campaign_scope_sha256=campaign_scope_sha256,
572
+ source_wave_index=source_wave_index,
573
+ available_at_wave_index=source_wave_index + 1,
574
+ stage_request_sha256=stage_request_sha256,
575
+ source_observation_sha256s=tuple(
576
+ sorted(value.observation_sha256 for value in observations)
577
+ ),
578
+ stage_surviving_source_candidate_ids=survivors,
579
+ post_stage_front_candidate_ids=front,
580
+ credits=credits,
581
+ )
582
+
583
+
584
+ def observe_contextual_terminal_persistence(
585
+ *,
586
+ campaign_scope_sha256: str,
587
+ available_at_wave_index: int,
588
+ finalization_request_sha256: str,
589
+ observations: tuple[ContextualSearchObservation, ...],
590
+ terminal_front_candidate_ids: tuple[CandidateId, ...],
591
+ ) -> ContextualTerminalPersistenceCreditBatch:
592
+ """Adjudicate candidate persistence only after successful completion."""
593
+
594
+ require_sha256(campaign_scope_sha256, "campaign_scope_sha256")
595
+ require_sha256(finalization_request_sha256, "finalization_request_sha256")
596
+ if (
597
+ type(observations) is not tuple
598
+ or not observations
599
+ or any(type(value) is not ContextualSearchObservation for value in observations)
600
+ ):
601
+ raise ValueError("observations must contain exact contextual values")
602
+ terminal = _canonical_candidate_ids(
603
+ terminal_front_candidate_ids,
604
+ name="terminal_front_candidate_ids",
605
+ )
606
+ terminal_set = set(terminal)
607
+ for value in observations:
608
+ value.__post_init__()
609
+ if value.campaign_scope_sha256 != campaign_scope_sha256:
610
+ raise ValueError("terminal credit crosses campaign scopes")
611
+ if value.candidate_id is None:
612
+ raise ValueError("terminal credit requires candidate-bound observations")
613
+ if available_at_wave_index <= value.wave_index:
614
+ raise ValueError("terminal credit predates a source observation")
615
+ credits = tuple(
616
+ sorted(
617
+ (
618
+ ContextualSearchDelayedCredit(
619
+ campaign_scope_sha256=campaign_scope_sha256,
620
+ source_observation_sha256=value.observation_sha256,
621
+ available_at_wave_index=available_at_wave_index,
622
+ final_front_persisted=value.candidate_id in terminal_set,
623
+ )
624
+ for value in observations
625
+ ),
626
+ key=lambda value: value.credit_sha256,
627
+ )
628
+ )
629
+ return ContextualTerminalPersistenceCreditBatch(
630
+ campaign_scope_sha256=campaign_scope_sha256,
631
+ available_at_wave_index=available_at_wave_index,
632
+ finalization_request_sha256=finalization_request_sha256,
633
+ terminal_front_candidate_ids=terminal,
634
+ credits=credits,
635
+ )
636
+
637
+
638
+ __all__ = [
639
+ "CONTEXTUAL_DELAYED_CREDIT_DEFINITION_SHA256",
640
+ "CONTEXTUAL_DELAYED_CREDIT_POLICY_ID",
641
+ "CONTEXTUAL_DELAYED_CREDIT_POLICY_VERSION",
642
+ "CONTEXTUAL_POST_STAGE_SURVIVAL_DEFINITION_SHA256",
643
+ "CONTEXTUAL_POST_STAGE_SURVIVAL_POLICY_ID",
644
+ "CONTEXTUAL_POST_STAGE_SURVIVAL_POLICY_VERSION",
645
+ "ContextualPostRecombinationCreditBatch",
646
+ "ContextualPostStageSurvivalCreditBatch",
647
+ "ContextualTerminalPersistenceCreditBatch",
648
+ "observe_contextual_post_recombination_credit",
649
+ "observe_contextual_post_stage_survival",
650
+ "observe_contextual_terminal_persistence",
651
+ ]