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,205 @@
1
+ """Fail-closed telemetry policy before a successful agentic call can be used.
2
+
3
+ The provider queue durably publishes terminal metadata first. This decorator
4
+ then verifies the scientific route and per-call resource envelope before an
5
+ ``AgenticEvolutionEngine`` may materialize or physically evaluate the proposal.
6
+ Per-call aggregate ceilings avoid completion-order-dependent selective
7
+ acceptance: with a separate hard logical-call cap, their product is a
8
+ deterministic run ceiling. Reasoning usage is part of aggregate output usage;
9
+ an independent reasoning ceiling is enforced only when the selected route
10
+ actually guarantees one.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import hashlib
16
+ import json
17
+ from dataclasses import dataclass
18
+ from decimal import Decimal
19
+
20
+ from agent_evolve.ports.agentic_generator import (
21
+ AgenticCallTelemetry,
22
+ AgenticGenerator,
23
+ ReflectionGenerationRequest,
24
+ ReflectionGenerationResult,
25
+ VariationGenerationRequest,
26
+ VariationGenerationResult,
27
+ )
28
+
29
+
30
+ class AgenticTelemetryRejected(RuntimeError):
31
+ """A sanitized rejection that never includes prompts or model output."""
32
+
33
+ def __init__(self, reason: str) -> None:
34
+ if type(reason) is not str or not reason:
35
+ raise ValueError("rejection reason must be non-empty")
36
+ super().__init__(f"agentic response telemetry rejected: {reason}")
37
+ self.reason = reason
38
+
39
+
40
+ def _canonical_json(value: object) -> bytes:
41
+ return json.dumps(
42
+ value,
43
+ ensure_ascii=True,
44
+ allow_nan=False,
45
+ separators=(",", ":"),
46
+ sort_keys=True,
47
+ ).encode("ascii")
48
+
49
+
50
+ @dataclass(frozen=True, slots=True)
51
+ class AgenticTelemetryPolicy:
52
+ """Exact provider/model identity and one-call token/cost bounds."""
53
+
54
+ requested_model: str
55
+ allowed_resolved_models: tuple[str, ...]
56
+ allowed_resolved_providers: tuple[str, ...]
57
+ max_cost_usd: Decimal
58
+ max_input_tokens: int
59
+ max_output_tokens: int
60
+ max_reasoning_tokens: int | None
61
+ max_attempt_count: int
62
+
63
+ policy_id = "exact_agentic_telemetry_gate"
64
+ policy_version = 3
65
+ reasoning_token_accounting = "included_in_output_tokens"
66
+
67
+ def __post_init__(self) -> None:
68
+ for name in ("requested_model",):
69
+ value = getattr(self, name)
70
+ if type(value) is not str or not value or value != value.strip():
71
+ raise ValueError(f"{name} must be canonical non-empty text")
72
+ for name in ("allowed_resolved_models", "allowed_resolved_providers"):
73
+ values = getattr(self, name)
74
+ if (
75
+ type(values) is not tuple
76
+ or not values
77
+ or any(
78
+ type(value) is not str or not value or value != value.strip()
79
+ for value in values
80
+ )
81
+ ):
82
+ raise ValueError(f"{name} must be non-empty canonical text")
83
+ if len(set(values)) != len(values):
84
+ raise ValueError(f"{name} cannot contain duplicates")
85
+ if any("/" not in value for value in self.allowed_resolved_models):
86
+ raise ValueError("allowed_resolved_models must contain model slugs")
87
+ if type(self.max_cost_usd) is not Decimal:
88
+ raise TypeError("max_cost_usd must be an exact Decimal")
89
+ if not self.max_cost_usd.is_finite() or self.max_cost_usd < 0:
90
+ raise ValueError("max_cost_usd must be finite and non-negative")
91
+ for name in (
92
+ "max_input_tokens",
93
+ "max_output_tokens",
94
+ "max_attempt_count",
95
+ ):
96
+ value = getattr(self, name)
97
+ if type(value) is not int or value < 0:
98
+ raise ValueError(f"{name} must be a non-negative integer")
99
+ if self.max_reasoning_tokens is not None and (
100
+ type(self.max_reasoning_tokens) is not int
101
+ or self.max_reasoning_tokens < 0
102
+ ):
103
+ raise ValueError(
104
+ "max_reasoning_tokens must be a non-negative integer or None"
105
+ )
106
+ if self.max_attempt_count == 0:
107
+ raise ValueError("max_attempt_count must be positive")
108
+
109
+ def to_trace_record(self) -> dict[str, object]:
110
+ return {
111
+ "policy_id": self.policy_id,
112
+ "policy_version": self.policy_version,
113
+ "requested_model": self.requested_model,
114
+ "allowed_resolved_models": list(self.allowed_resolved_models),
115
+ "allowed_resolved_providers": list(self.allowed_resolved_providers),
116
+ "max_cost_usd": str(self.max_cost_usd),
117
+ "max_input_tokens": self.max_input_tokens,
118
+ "max_output_tokens": self.max_output_tokens,
119
+ "max_reasoning_tokens": self.max_reasoning_tokens,
120
+ "reasoning_token_accounting": self.reasoning_token_accounting,
121
+ "max_attempt_count": self.max_attempt_count,
122
+ }
123
+
124
+ @property
125
+ def policy_sha256(self) -> str:
126
+ return hashlib.sha256(
127
+ b"agent-evolve:agentic-telemetry-policy:v3\x00"
128
+ + _canonical_json(self.to_trace_record())
129
+ ).hexdigest()
130
+
131
+ def validate(self, telemetry: AgenticCallTelemetry) -> None:
132
+ if type(telemetry) is not AgenticCallTelemetry:
133
+ raise TypeError("telemetry must be an exact AgenticCallTelemetry")
134
+ AgenticCallTelemetry.__post_init__(telemetry)
135
+ if telemetry.reasoning_tokens > telemetry.output_tokens:
136
+ raise AgenticTelemetryRejected("reasoning_output_accounting")
137
+ checks = (
138
+ (telemetry.requested_model == self.requested_model, "requested_model"),
139
+ (
140
+ telemetry.resolved_model in self.allowed_resolved_models,
141
+ "resolved_model",
142
+ ),
143
+ (
144
+ telemetry.resolved_provider in self.allowed_resolved_providers,
145
+ "resolved_provider",
146
+ ),
147
+ (telemetry.input_tokens <= self.max_input_tokens, "input_tokens"),
148
+ (telemetry.output_tokens <= self.max_output_tokens, "output_tokens"),
149
+ (telemetry.attempt_count <= self.max_attempt_count, "attempt_count"),
150
+ )
151
+ for accepted, reason in checks:
152
+ if not accepted:
153
+ raise AgenticTelemetryRejected(reason)
154
+ if (
155
+ self.max_reasoning_tokens is not None
156
+ and telemetry.reasoning_tokens > self.max_reasoning_tokens
157
+ ):
158
+ raise AgenticTelemetryRejected("reasoning_tokens")
159
+ cost = telemetry.cost_usd
160
+ if cost is None:
161
+ raise AgenticTelemetryRejected("missing_cost")
162
+ if type(cost) is not Decimal:
163
+ raise AgenticTelemetryRejected("non_decimal_cost")
164
+ if not cost.is_finite() or cost < 0:
165
+ raise AgenticTelemetryRejected("invalid_cost")
166
+ if cost > self.max_cost_usd:
167
+ raise AgenticTelemetryRejected("cost_ceiling")
168
+
169
+
170
+ class TelemetryGatedAgenticGenerator:
171
+ """Transparent generator decorator with a pre-evaluation telemetry gate."""
172
+
173
+ def __init__(self, generator: AgenticGenerator, policy: AgenticTelemetryPolicy):
174
+ if not isinstance(generator, AgenticGenerator):
175
+ raise TypeError("generator must implement AgenticGenerator")
176
+ if type(policy) is not AgenticTelemetryPolicy:
177
+ raise TypeError("policy must be an exact AgenticTelemetryPolicy")
178
+ AgenticTelemetryPolicy.__post_init__(policy)
179
+ self.generator = generator
180
+ self.policy = policy
181
+
182
+ async def propose(
183
+ self, request: VariationGenerationRequest
184
+ ) -> VariationGenerationResult:
185
+ result = await self.generator.propose(request)
186
+ if type(result) is not VariationGenerationResult:
187
+ raise TypeError("generator returned a non-variation result")
188
+ self.policy.validate(result.telemetry)
189
+ return result
190
+
191
+ async def reflect(
192
+ self, request: ReflectionGenerationRequest
193
+ ) -> ReflectionGenerationResult:
194
+ result = await self.generator.reflect(request)
195
+ if type(result) is not ReflectionGenerationResult:
196
+ raise TypeError("generator returned a non-reflection result")
197
+ self.policy.validate(result.telemetry)
198
+ return result
199
+
200
+
201
+ __all__ = [
202
+ "AgenticTelemetryPolicy",
203
+ "AgenticTelemetryRejected",
204
+ "TelemetryGatedAgenticGenerator",
205
+ ]
@@ -0,0 +1,293 @@
1
+ """Budgeted inter-generation feedback contracts.
2
+
3
+ The optimizer owns admission and accounting, while an injected interceptor owns
4
+ the feedback behavior (for example, trace reflection or memory curation). A
5
+ reservation is frozen before a generation starts. The interceptor is invoked
6
+ only after that generation's receipt has been sealed, so the next planner call
7
+ can observe its effects without allowing feedback to alter in-flight evidence.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import hashlib
13
+ import json
14
+ import re
15
+ from dataclasses import dataclass
16
+ from typing import TYPE_CHECKING, Protocol, runtime_checkable
17
+
18
+ if TYPE_CHECKING:
19
+ from agent_evolve.application.budgeted_optimizer import (
20
+ GenerationPlan,
21
+ GenerationReceipt,
22
+ OptimizerState,
23
+ )
24
+
25
+
26
+ _POLICY_ID = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
27
+ _HASH_DOMAIN = b"agent-evolve:generation-feedback:v1\x00"
28
+
29
+
30
+ def _canonical_json(value: object) -> bytes:
31
+ return json.dumps(
32
+ value,
33
+ ensure_ascii=True,
34
+ allow_nan=False,
35
+ separators=(",", ":"),
36
+ sort_keys=True,
37
+ ).encode("ascii")
38
+
39
+
40
+ def _record_hash(kind: str, value: object) -> str:
41
+ return hashlib.sha256(
42
+ _HASH_DOMAIN + kind.encode("ascii") + b"\x00" + _canonical_json(value)
43
+ ).hexdigest()
44
+
45
+
46
+ def _validate_metadata(value: tuple[tuple[str, str], ...], *, name: str) -> None:
47
+ if type(value) is not tuple:
48
+ raise TypeError(f"{name} must be an exact tuple")
49
+ for item in value:
50
+ if (
51
+ type(item) is not tuple
52
+ or len(item) != 2
53
+ or any(type(part) is not str or not part for part in item)
54
+ ):
55
+ raise TypeError(f"{name} must contain non-empty exact string pairs")
56
+ if value != tuple(sorted(set(value))):
57
+ raise ValueError(f"{name} must be unique and canonically sorted")
58
+
59
+
60
+ @dataclass(frozen=True, slots=True)
61
+ class GenerationFeedbackReservation:
62
+ """Pre-generation upper bound for one interceptor invocation."""
63
+
64
+ policy_id: str
65
+ policy_version: int
66
+ logical_llm_calls: int
67
+ metadata: tuple[tuple[str, str], ...] = ()
68
+
69
+ def __post_init__(self) -> None:
70
+ if (
71
+ type(self.policy_id) is not str
72
+ or _POLICY_ID.fullmatch(self.policy_id) is None
73
+ ):
74
+ raise ValueError("policy_id must use the closed lowercase token grammar")
75
+ if type(self.policy_version) is not int or self.policy_version <= 0:
76
+ raise ValueError("policy_version must be a positive exact integer")
77
+ if type(self.logical_llm_calls) is not int or self.logical_llm_calls < 0:
78
+ raise ValueError("logical_llm_calls must be a non-negative exact integer")
79
+ _validate_metadata(self.metadata, name="metadata")
80
+
81
+ def to_record(self) -> dict[str, object]:
82
+ return {
83
+ "policy_id": self.policy_id,
84
+ "policy_version": self.policy_version,
85
+ "logical_llm_calls": self.logical_llm_calls,
86
+ "metadata": [list(item) for item in self.metadata],
87
+ }
88
+
89
+ @property
90
+ def reservation_hash(self) -> str:
91
+ return _record_hash("reservation", self.to_record())
92
+
93
+
94
+ @dataclass(frozen=True, slots=True)
95
+ class GenerationFeedbackContext:
96
+ """Immutable post-generation evidence exposed to an interceptor."""
97
+
98
+ state: OptimizerState
99
+ plan: GenerationPlan
100
+ generation_receipt: GenerationReceipt
101
+ reservation: GenerationFeedbackReservation
102
+
103
+ def __post_init__(self) -> None:
104
+ if type(self.reservation) is not GenerationFeedbackReservation:
105
+ raise TypeError(
106
+ "reservation must be an exact GenerationFeedbackReservation"
107
+ )
108
+ if self.state.generation != self.plan.generation:
109
+ raise ValueError("feedback state and plan generations differ")
110
+ if self.generation_receipt.generation != self.plan.generation:
111
+ raise ValueError("feedback receipt and plan generations differ")
112
+ if not self.state.generation_receipts:
113
+ raise ValueError("feedback state has no sealed generation receipt")
114
+ if self.state.generation_receipts[-1] != self.generation_receipt:
115
+ raise ValueError(
116
+ "feedback must observe the latest sealed generation receipt"
117
+ )
118
+
119
+
120
+ @dataclass(frozen=True, slots=True)
121
+ class GenerationFeedbackResult:
122
+ """Interceptor-declared consumption and content-free result metadata."""
123
+
124
+ logical_llm_calls_used: int
125
+ metadata: tuple[tuple[str, str], ...] = ()
126
+
127
+ def __post_init__(self) -> None:
128
+ if (
129
+ type(self.logical_llm_calls_used) is not int
130
+ or self.logical_llm_calls_used < 0
131
+ ):
132
+ raise ValueError(
133
+ "logical_llm_calls_used must be a non-negative exact integer"
134
+ )
135
+ _validate_metadata(self.metadata, name="metadata")
136
+
137
+
138
+ @dataclass(frozen=True, slots=True)
139
+ class GenerationFeedbackReceipt:
140
+ """Authenticated accounting record for one completed interceptor call."""
141
+
142
+ generation: int
143
+ policy_id: str
144
+ policy_version: int
145
+ reservation_hash: str
146
+ generation_receipt_hash: str
147
+ logical_llm_calls_before: int
148
+ logical_llm_calls_after: int
149
+ reserved_logical_llm_calls: int
150
+ used_logical_llm_calls: int
151
+ result_metadata: tuple[tuple[str, str], ...]
152
+ receipt_hash: str
153
+
154
+ def __post_init__(self) -> None:
155
+ if type(self.generation) is not int or self.generation <= 0:
156
+ raise ValueError("generation must be a positive exact integer")
157
+ if (
158
+ type(self.policy_id) is not str
159
+ or _POLICY_ID.fullmatch(self.policy_id) is None
160
+ ):
161
+ raise ValueError("policy_id must use the closed lowercase token grammar")
162
+ if type(self.policy_version) is not int or self.policy_version <= 0:
163
+ raise ValueError("policy_version must be a positive exact integer")
164
+ for name in ("reservation_hash", "generation_receipt_hash", "receipt_hash"):
165
+ value = getattr(self, name)
166
+ if type(value) is not str or re.fullmatch(r"[0-9a-f]{64}", value) is None:
167
+ raise ValueError(f"{name} must be a lowercase SHA-256 digest")
168
+ for name in (
169
+ "logical_llm_calls_before",
170
+ "logical_llm_calls_after",
171
+ "reserved_logical_llm_calls",
172
+ "used_logical_llm_calls",
173
+ ):
174
+ value = getattr(self, name)
175
+ if type(value) is not int or value < 0:
176
+ raise ValueError(f"{name} must be a non-negative exact integer")
177
+ if self.used_logical_llm_calls > self.reserved_logical_llm_calls:
178
+ raise ValueError("used feedback calls cannot exceed the reservation")
179
+ if self.logical_llm_calls_after - self.logical_llm_calls_before != (
180
+ self.used_logical_llm_calls
181
+ ):
182
+ raise ValueError("feedback counters differ from declared consumption")
183
+ _validate_metadata(self.result_metadata, name="result_metadata")
184
+
185
+
186
+ def _receipt_record(receipt: GenerationFeedbackReceipt) -> dict[str, object]:
187
+ return {
188
+ "generation": receipt.generation,
189
+ "policy_id": receipt.policy_id,
190
+ "policy_version": receipt.policy_version,
191
+ "reservation_hash": receipt.reservation_hash,
192
+ "generation_receipt_hash": receipt.generation_receipt_hash,
193
+ "logical_llm_calls_before": receipt.logical_llm_calls_before,
194
+ "logical_llm_calls_after": receipt.logical_llm_calls_after,
195
+ "reserved_logical_llm_calls": receipt.reserved_logical_llm_calls,
196
+ "used_logical_llm_calls": receipt.used_logical_llm_calls,
197
+ "result_metadata": [list(item) for item in receipt.result_metadata],
198
+ }
199
+
200
+
201
+ def generation_feedback_receipt_hash(receipt: GenerationFeedbackReceipt) -> str:
202
+ """Recompute the canonical feedback receipt identity."""
203
+
204
+ if type(receipt) is not GenerationFeedbackReceipt:
205
+ raise TypeError("receipt must be an exact GenerationFeedbackReceipt")
206
+ return _record_hash("receipt", _receipt_record(receipt))
207
+
208
+
209
+ def validate_generation_feedback_receipt(
210
+ receipt: GenerationFeedbackReceipt,
211
+ ) -> None:
212
+ """Fail closed unless a feedback receipt authenticates its contents."""
213
+
214
+ if type(receipt) is not GenerationFeedbackReceipt:
215
+ raise TypeError("receipt must be an exact GenerationFeedbackReceipt")
216
+ GenerationFeedbackReceipt.__post_init__(receipt)
217
+ if generation_feedback_receipt_hash(receipt) != receipt.receipt_hash:
218
+ raise ValueError("feedback receipt hash does not authenticate its contents")
219
+
220
+
221
+ def seal_generation_feedback(
222
+ *,
223
+ context: GenerationFeedbackContext,
224
+ result: GenerationFeedbackResult,
225
+ ) -> GenerationFeedbackReceipt:
226
+ """Validate exact consumption and seal the feedback accounting record."""
227
+
228
+ if type(context) is not GenerationFeedbackContext:
229
+ raise TypeError("context must be an exact GenerationFeedbackContext")
230
+ GenerationFeedbackContext.__post_init__(context)
231
+ if type(result) is not GenerationFeedbackResult:
232
+ raise TypeError("result must be an exact GenerationFeedbackResult")
233
+ GenerationFeedbackResult.__post_init__(result)
234
+ reservation = context.reservation
235
+ if result.logical_llm_calls_used > reservation.logical_llm_calls:
236
+ raise ValueError("feedback consumption exceeds its pre-generation reservation")
237
+ before = context.state.logical_llm_calls
238
+ after = before + result.logical_llm_calls_used
239
+ provisional = GenerationFeedbackReceipt(
240
+ generation=context.plan.generation,
241
+ policy_id=reservation.policy_id,
242
+ policy_version=reservation.policy_version,
243
+ reservation_hash=reservation.reservation_hash,
244
+ generation_receipt_hash=context.generation_receipt.receipt_hash,
245
+ logical_llm_calls_before=before,
246
+ logical_llm_calls_after=after,
247
+ reserved_logical_llm_calls=reservation.logical_llm_calls,
248
+ used_logical_llm_calls=result.logical_llm_calls_used,
249
+ result_metadata=result.metadata,
250
+ receipt_hash="0" * 64,
251
+ )
252
+ return GenerationFeedbackReceipt(
253
+ generation=provisional.generation,
254
+ policy_id=provisional.policy_id,
255
+ policy_version=provisional.policy_version,
256
+ reservation_hash=provisional.reservation_hash,
257
+ generation_receipt_hash=provisional.generation_receipt_hash,
258
+ logical_llm_calls_before=provisional.logical_llm_calls_before,
259
+ logical_llm_calls_after=provisional.logical_llm_calls_after,
260
+ reserved_logical_llm_calls=provisional.reserved_logical_llm_calls,
261
+ used_logical_llm_calls=provisional.used_logical_llm_calls,
262
+ result_metadata=provisional.result_metadata,
263
+ receipt_hash=_record_hash("receipt", _receipt_record(provisional)),
264
+ )
265
+
266
+
267
+ @runtime_checkable
268
+ class GenerationFeedbackInterceptor(Protocol):
269
+ """Optional feedback behavior injected between sealed generations."""
270
+
271
+ def reserve(
272
+ self,
273
+ *,
274
+ state: OptimizerState,
275
+ plan: GenerationPlan,
276
+ ) -> GenerationFeedbackReservation: ...
277
+
278
+ async def after_generation(
279
+ self,
280
+ context: GenerationFeedbackContext,
281
+ ) -> GenerationFeedbackResult: ...
282
+
283
+
284
+ __all__ = [
285
+ "GenerationFeedbackContext",
286
+ "GenerationFeedbackInterceptor",
287
+ "GenerationFeedbackReceipt",
288
+ "GenerationFeedbackReservation",
289
+ "GenerationFeedbackResult",
290
+ "generation_feedback_receipt_hash",
291
+ "seal_generation_feedback",
292
+ "validate_generation_feedback_receipt",
293
+ ]
@@ -0,0 +1,185 @@
1
+ """The durable side of a generative seal: one chained JSONL per campaign.
2
+
3
+ One line per model call, in issue order, each carrying the digest of the line
4
+ before it. Reading it back reconstructs the exact call sequence and re-derives
5
+ every digest, so a journal that has been edited, reordered, truncated at the
6
+ front, or had a call inserted into it fails to close.
7
+
8
+ The last property is the one that matters most here. An agent on this project
9
+ filled unevaluated compositions with predicted values and reported a 1.7x win
10
+ that had to be retracted. A chained journal makes the analogous move on the
11
+ proposal side impossible to do quietly: a call that did not happen has no
12
+ predecessor digest to inherit, and the terminal digest of the campaign is
13
+ published with the result.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import hashlib
19
+ import json
20
+ from pathlib import Path
21
+ from typing import Any, Iterable, Sequence
22
+
23
+ from agent_evolve.domain.generative_emission import (
24
+ GenerativeEmission,
25
+ GenerativeProposalCall,
26
+ SealedGuidanceCall,
27
+ SealedRunHeader,
28
+ chain_sealed_calls,
29
+ )
30
+ from agent_evolve.domain.typed_json import freeze_json
31
+
32
+ __all__ = [
33
+ "candidate_schema_sha256",
34
+ "journal_line",
35
+ "read_generative_journal",
36
+ "verify_generative_journal",
37
+ "write_generative_journal",
38
+ ]
39
+
40
+ _SCHEMA_HASH_DOMAIN = b"agent-evolve:candidate-schema-identity:v1\x00"
41
+
42
+
43
+ def candidate_schema_sha256(candidate_model: Any) -> str:
44
+ """Digest the exact JSON schema a proposal must satisfy.
45
+
46
+ This is the support of the generative operator, and therefore the support a
47
+ matched null has to sample. Recording it turns "the null draws from the same
48
+ space" from a claim in a write-up into a field two runs can be compared on.
49
+ """
50
+
51
+ if candidate_model is None:
52
+ raise ValueError(
53
+ "a generative campaign needs a candidate schema. Without one the "
54
+ "proposer has no declared support and no null can be matched to it."
55
+ )
56
+ schema = candidate_model.model_json_schema()
57
+ payload = json.dumps(
58
+ schema, sort_keys=True, separators=(",", ":"), ensure_ascii=True
59
+ ).encode("ascii")
60
+ return hashlib.sha256(_SCHEMA_HASH_DOMAIN + payload).hexdigest()
61
+
62
+
63
+ def journal_line(record: dict) -> str:
64
+ """Serialise one sealed call as canonical JSON on a single line."""
65
+
66
+ return json.dumps(
67
+ record, sort_keys=True, separators=(",", ":"), ensure_ascii=True, allow_nan=False
68
+ )
69
+
70
+
71
+ def write_generative_journal(path: Path, calls: Sequence[Any]) -> str:
72
+ """Write the chain and return its terminal digest."""
73
+
74
+ terminal = chain_sealed_calls(tuple(calls))
75
+ path.parent.mkdir(parents=True, exist_ok=True)
76
+ with path.open("w", encoding="ascii") as handle:
77
+ for call in calls:
78
+ handle.write(journal_line(call.to_record()) + "\n")
79
+ return terminal
80
+
81
+
82
+ def _call_from_record(record: dict) -> Any:
83
+ if record.get("schema_version") != 1:
84
+ raise ValueError("unsupported sealed call schema_version")
85
+ kind = record.get("record_kind")
86
+ if kind == "run_header":
87
+ call = SealedRunHeader(
88
+ proposer_id=str(record["proposer_id"]),
89
+ requested_model=str(record["requested_model"]),
90
+ candidate_schema_sha256=str(record["candidate_schema_sha256"]),
91
+ provides_insights=bool(record["provides_insights"]),
92
+ )
93
+ elif "emissions" in record:
94
+ emissions = tuple(
95
+ GenerativeEmission(
96
+ configuration=freeze_json(dict(item["configuration"])),
97
+ accepted=bool(item["accepted"]),
98
+ rejection_reason=str(item.get("rejection_reason", "")),
99
+ )
100
+ for item in record["emissions"]
101
+ )
102
+ call = GenerativeProposalCall(
103
+ call_ordinal=int(record["call_ordinal"]),
104
+ op=str(record["op"]),
105
+ requested_model=str(record["requested_model"]),
106
+ prompt_sha256=str(record["prompt_sha256"]),
107
+ candidate_schema_sha256=str(record["candidate_schema_sha256"]),
108
+ emissions=emissions,
109
+ previous_call_sha256=str(record["previous_call_sha256"]),
110
+ )
111
+ elif "outputs" in record:
112
+ call = SealedGuidanceCall(
113
+ call_ordinal=int(record["call_ordinal"]),
114
+ op=str(record["op"]),
115
+ requested_model=str(record["requested_model"]),
116
+ prompt_sha256=str(record["prompt_sha256"]),
117
+ outputs=tuple(str(x) for x in record["outputs"]),
118
+ previous_call_sha256=str(record["previous_call_sha256"]),
119
+ )
120
+ else:
121
+ raise ValueError("a sealed call carries either emissions or outputs")
122
+ if call.identity_sha256 != record["call_identity_sha256"]:
123
+ raise ValueError(
124
+ f"call {record['call_ordinal']} does not authenticate: its recorded "
125
+ "identity is not the identity of its contents"
126
+ )
127
+ return call
128
+
129
+
130
+ def read_generative_journal(path: Path) -> tuple:
131
+ """Read a journal back into sealed call objects, authenticating each line."""
132
+
133
+ calls = []
134
+ with path.open("r", encoding="ascii") as handle:
135
+ for line in handle:
136
+ if not line.strip():
137
+ continue
138
+ calls.append(_call_from_record(json.loads(line)))
139
+ return tuple(calls)
140
+
141
+
142
+ def verify_generative_journal(path: Path) -> dict:
143
+ """Authenticate a journal end to end and summarise what it says happened.
144
+
145
+ Every count here is derived from the sealed content. Nothing is declared.
146
+ """
147
+
148
+ calls = read_generative_journal(path)
149
+ terminal = chain_sealed_calls(calls)
150
+ header = calls[0]
151
+ proposals = tuple(c for c in calls if type(c) is GenerativeProposalCall)
152
+ emitted = sum(len(c.emissions) for c in proposals)
153
+ accepted = sum(1 for c in proposals for e in c.emissions if e.accepted)
154
+ distinct = {
155
+ e.configuration_sha256 for c in proposals for e in c.emissions if e.accepted
156
+ }
157
+ schemas = {c.candidate_schema_sha256 for c in proposals}
158
+ models = {c.requested_model for c in calls}
159
+ return {
160
+ "path": str(path),
161
+ "terminal_sha256": terminal,
162
+ "proposer_id": header.proposer_id,
163
+ "provides_insights": header.provides_insights,
164
+ "calls": len(calls) - 1,
165
+ "proposal_calls": len(proposals),
166
+ "guidance_calls": len(calls) - 1 - len(proposals),
167
+ "emitted_configurations": emitted,
168
+ "accepted_configurations": accepted,
169
+ "distinct_accepted_configurations": len(distinct),
170
+ "candidate_schema_sha256s": sorted(schemas),
171
+ "requested_models": sorted(models),
172
+ }
173
+
174
+
175
+ def iter_accepted_configurations(calls: Iterable[Any]) -> tuple:
176
+ """Every configuration the model authored that ``validate`` let through."""
177
+
178
+ out = []
179
+ for call in calls:
180
+ if type(call) is not GenerativeProposalCall:
181
+ continue
182
+ for emission in call.emissions:
183
+ if emission.accepted:
184
+ out.append(emission.configuration)
185
+ return tuple(out)