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,674 @@
1
+ """Pydantic-AI adapter for compact hierarchical residual proposals.
2
+
3
+ The model selects a parent and one or two opaque atomic option IDs. The
4
+ application-layer reachability schema owns eligibility and trusted engine code
5
+ materializes the resulting configuration after this adapter returns. Queueing,
6
+ retry, backoff, and model routing remain injected through ``LowLevelRunner``.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass
12
+ import hashlib
13
+ import json
14
+ import math
15
+ import re
16
+ from typing import Annotated, Any, ClassVar, Literal, cast
17
+
18
+ from pydantic import (
19
+ BaseModel,
20
+ ConfigDict,
21
+ Field,
22
+ StringConstraints,
23
+ create_model,
24
+ model_validator,
25
+ )
26
+ from pydantic_core import PydanticCustomError
27
+
28
+ from agent_evolve.application.residual_reachability import (
29
+ CrossParentFiniteActionSchema,
30
+ HierarchicalResidualPlan,
31
+ ResidualProposalRole,
32
+ )
33
+ from agent_evolve.domain.ids import LLMCallId
34
+ from agent_evolve.domain.llm_task_queue import ValidationIssueReasonCode
35
+ from agent_evolve.domain.patch import require_sha256
36
+ from agent_evolve.domain.typed_json import FrozenJsonObject, freeze_json, thaw_json
37
+ from agent_evolve.integrations.pydantic_ai.agentic_generator import (
38
+ AttemptedStructuredGenerationResponse,
39
+ LowLevelRunner,
40
+ )
41
+ from agent_evolve.ports.agentic_generator import AgenticCallTelemetry
42
+ from agent_evolve.ports.portfolio_selection import (
43
+ pairwise_disjoint_parent_patch_pairs,
44
+ )
45
+ from agent_evolve.ports.structured_generator import (
46
+ MAX_OUTPUT_TOKENS,
47
+ StructuredGenerationRequest,
48
+ StructuredGenerationResponse,
49
+ )
50
+
51
+
52
+ HIERARCHICAL_RESIDUAL_PROPOSAL_TOOL_NAME = "propose_residual_plans"
53
+ HIERARCHICAL_RESIDUAL_PROPOSAL_POLICY_ID = (
54
+ "pydantic_ai_hierarchical_residual_proposal"
55
+ )
56
+ HIERARCHICAL_RESIDUAL_PROPOSAL_POLICY_VERSION = 2
57
+ HIERARCHICAL_RESIDUAL_PROPOSAL_POLICY_DEFINITION_SHA256 = hashlib.sha256(
58
+ b"agent-evolve:pydantic-ai-hierarchical-residual-proposal:v2;"
59
+ b"model-output=parent-id-plus-radius-one-or-two-atomic-id-tuple;"
60
+ b"consequence=p10-p50-p90-parent-relative-metric-deltas-plus-confidence-"
61
+ b"and-probability-valid;"
62
+ b"engine-materialization-only=true;cross-parent-schema=true;"
63
+ b"workload-model-provider-branches=false"
64
+ ).hexdigest()
65
+
66
+ _STRICT = ConfigDict(
67
+ extra="forbid",
68
+ strict=True,
69
+ populate_by_name=True,
70
+ validate_default=True,
71
+ )
72
+ _OPERATION = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
73
+ _Rationale = Annotated[
74
+ str,
75
+ StringConstraints(
76
+ strict=True,
77
+ strip_whitespace=True,
78
+ min_length=1,
79
+ max_length=16_384,
80
+ ),
81
+ ]
82
+ _DECISION_DOMAIN = b"agent-evolve:hierarchical-residual-proposal-decision:v2\x00"
83
+
84
+
85
+ def _canonical_bytes(value: object) -> bytes:
86
+ return json.dumps(
87
+ value,
88
+ allow_nan=False,
89
+ ensure_ascii=True,
90
+ separators=(",", ":"),
91
+ sort_keys=True,
92
+ ).encode("ascii", errors="strict")
93
+
94
+
95
+ def _hash(value: object) -> str:
96
+ return hashlib.sha256(_DECISION_DOMAIN + _canonical_bytes(value)).hexdigest()
97
+
98
+
99
+ @dataclass(frozen=True, slots=True)
100
+ class HierarchicalResidualProposalRequest:
101
+ """Provider-neutral request for one proposal expert."""
102
+
103
+ call_id: LLMCallId
104
+ operation: str
105
+ instruction: str
106
+ context: FrozenJsonObject
107
+ action_schema: CrossParentFiniteActionSchema
108
+ proposal_count: int
109
+ allowed_radii: tuple[int, ...]
110
+ allowed_roles: tuple[ResidualProposalRole, ...]
111
+ required_metric_ids: tuple[str, ...]
112
+ minimum_distinct_parents: int
113
+ expert_id: str
114
+ expert_definition_sha256: str
115
+ max_output_tokens: int
116
+ temperature: float
117
+
118
+ def __post_init__(self) -> None:
119
+ if type(self.call_id) is not LLMCallId:
120
+ raise TypeError("call_id must be an exact LLMCallId")
121
+ LLMCallId.__post_init__(self.call_id)
122
+ if type(self.operation) is not str or _OPERATION.fullmatch(self.operation) is None:
123
+ raise ValueError("operation must use the closed token grammar")
124
+ if type(self.instruction) is not str or not self.instruction.strip():
125
+ raise ValueError("instruction must be non-empty")
126
+ if len(self.instruction.encode("utf-8")) > 32_768:
127
+ raise ValueError("instruction exceeds its byte limit")
128
+ if type(self.context) is not FrozenJsonObject:
129
+ raise TypeError("context must be an exact FrozenJsonObject")
130
+ if freeze_json(self.context) is not self.context:
131
+ raise TypeError("context must already be frozen typed JSON")
132
+ if type(self.action_schema) is not CrossParentFiniteActionSchema:
133
+ raise TypeError("action_schema must be exact")
134
+ self.action_schema.__post_init__()
135
+ if type(self.proposal_count) is not int or not 1 <= self.proposal_count <= 32:
136
+ raise ValueError("proposal_count must lie in [1, 32]")
137
+ if (
138
+ type(self.allowed_radii) is not tuple
139
+ or not self.allowed_radii
140
+ or self.allowed_radii != tuple(sorted(set(self.allowed_radii)))
141
+ or not set(self.allowed_radii).issubset({1, 2})
142
+ ):
143
+ raise ValueError("allowed_radii must be a canonical subset of {1, 2}")
144
+ if (
145
+ type(self.allowed_roles) is not tuple
146
+ or not self.allowed_roles
147
+ or any(type(value) is not ResidualProposalRole for value in self.allowed_roles)
148
+ ):
149
+ raise TypeError("allowed_roles must contain exact role values")
150
+ if self.allowed_roles != tuple(
151
+ sorted(set(self.allowed_roles), key=lambda value: value.value)
152
+ ):
153
+ raise ValueError("allowed_roles must be unique and canonical")
154
+ if (
155
+ type(self.required_metric_ids) is not tuple
156
+ or not self.required_metric_ids
157
+ or self.required_metric_ids != tuple(sorted(set(self.required_metric_ids)))
158
+ ):
159
+ raise ValueError("required_metric_ids must be non-empty and canonical")
160
+ if (
161
+ type(self.minimum_distinct_parents) is not int
162
+ or not 1 <= self.minimum_distinct_parents <= self.proposal_count
163
+ or self.minimum_distinct_parents > len(self.action_schema.bindings)
164
+ ):
165
+ raise ValueError("minimum_distinct_parents is infeasible")
166
+ if type(self.expert_id) is not str or _OPERATION.fullmatch(self.expert_id) is None:
167
+ raise ValueError("expert_id must use the closed token grammar")
168
+ require_sha256(self.expert_definition_sha256, "expert_definition_sha256")
169
+ if (
170
+ type(self.max_output_tokens) is not int
171
+ or not 1 <= self.max_output_tokens <= MAX_OUTPUT_TOKENS
172
+ ):
173
+ raise ValueError("max_output_tokens is outside the generic bound")
174
+ if type(self.temperature) is not float or not math.isfinite(self.temperature):
175
+ raise TypeError("temperature must be a finite exact float")
176
+
177
+ @property
178
+ def request_sha256(self) -> str:
179
+ self.__post_init__()
180
+ return _hash(
181
+ {
182
+ "schema_version": 1,
183
+ "call_id": self.call_id.value,
184
+ "operation": self.operation,
185
+ "instruction": self.instruction,
186
+ "context": thaw_json(self.context),
187
+ "action_schema_sha256": self.action_schema.schema_sha256,
188
+ "proposal_count": self.proposal_count,
189
+ "allowed_radii": list(self.allowed_radii),
190
+ "allowed_roles": [value.value for value in self.allowed_roles],
191
+ "required_metric_ids": list(self.required_metric_ids),
192
+ "minimum_distinct_parents": self.minimum_distinct_parents,
193
+ "expert_id": self.expert_id,
194
+ "expert_definition_sha256": self.expert_definition_sha256,
195
+ "max_output_tokens": self.max_output_tokens,
196
+ "temperature_hex": self.temperature.hex(),
197
+ }
198
+ )
199
+
200
+
201
+ class _ResidualMemberBase(BaseModel):
202
+ model_config = _STRICT
203
+
204
+ available_option_ids_by_parent: ClassVar[dict[str, frozenset[str]]] = {}
205
+ compatible_radius_two_by_parent: ClassVar[
206
+ dict[str, frozenset[tuple[str, str]]]
207
+ ] = {}
208
+ allowed_radii: ClassVar[frozenset[int]] = frozenset()
209
+ required_metric_ids: ClassVar[frozenset[str]] = frozenset()
210
+
211
+ @model_validator(mode="after")
212
+ def _validate_member(self) -> "_ResidualMemberBase":
213
+ parent_id = cast(Any, self).parent_candidate_id
214
+ option_ids = tuple(cast(Any, self).component_option_ids)
215
+ if len(option_ids) not in type(self).allowed_radii:
216
+ raise PydanticCustomError(
217
+ ValidationIssueReasonCode.RESIDUAL_RADIUS_CONTRACT_VIOLATION.value,
218
+ "component tuple has a forbidden radius",
219
+ )
220
+ if len(set(option_ids)) != len(option_ids):
221
+ raise PydanticCustomError(
222
+ ValidationIssueReasonCode.RESIDUAL_OPTION_CONTRACT_VIOLATION.value,
223
+ "component option IDs cannot repeat",
224
+ )
225
+ if not set(option_ids).issubset(
226
+ type(self).available_option_ids_by_parent[parent_id]
227
+ ):
228
+ raise PydanticCustomError(
229
+ ValidationIssueReasonCode.RESIDUAL_OPTION_CONTRACT_VIOLATION.value,
230
+ "a component is unavailable for the selected parent",
231
+ )
232
+ if len(option_ids) == 2 and tuple(sorted(option_ids)) not in type(
233
+ self
234
+ ).compatible_radius_two_by_parent[parent_id]:
235
+ raise PydanticCustomError(
236
+ ValidationIssueReasonCode.RESIDUAL_OPTION_CONTRACT_VIOLATION.value,
237
+ "radius-two components are not a safe disjoint "
238
+ "parent-relative pair",
239
+ )
240
+ metrics = tuple(item.metric_id for item in cast(Any, self).effect_predictions)
241
+ if len(set(metrics)) != len(metrics) or set(metrics) != type(self).required_metric_ids:
242
+ raise PydanticCustomError(
243
+ ValidationIssueReasonCode.RESIDUAL_METRIC_CONTRACT_VIOLATION.value,
244
+ "effect predictions must cover each requested metric once",
245
+ )
246
+ return self
247
+
248
+
249
+ class _ResidualMetricPredictionBase(BaseModel):
250
+ model_config = _STRICT
251
+
252
+ @model_validator(mode="after")
253
+ def _validate_quantiles(self) -> "_ResidualMetricPredictionBase":
254
+ p10 = cast(float, cast(Any, self).p10_delta)
255
+ p50 = cast(float, cast(Any, self).p50_delta)
256
+ p90 = cast(float, cast(Any, self).p90_delta)
257
+ if not all(math.isfinite(value) for value in (p10, p50, p90)):
258
+ raise PydanticCustomError(
259
+ ValidationIssueReasonCode.RESIDUAL_QUANTILE_ORDER_VIOLATION.value,
260
+ "effect quantiles must be finite",
261
+ )
262
+ if not p10 <= p50 <= p90:
263
+ raise PydanticCustomError(
264
+ ValidationIssueReasonCode.RESIDUAL_QUANTILE_ORDER_VIOLATION.value,
265
+ "effect quantiles must satisfy p10 <= p50 <= p90",
266
+ )
267
+ return self
268
+
269
+
270
+ class _ResidualOutputBase(BaseModel):
271
+ model_config = _STRICT
272
+
273
+ proposal_count: ClassVar[int] = 1
274
+ minimum_distinct_parents: ClassVar[int] = 1
275
+
276
+ @model_validator(mode="after")
277
+ def _validate_output(self) -> "_ResidualOutputBase":
278
+ members = tuple(cast(Any, self).members)
279
+ if len(members) != type(self).proposal_count:
280
+ raise ValueError("members must have the exact requested size")
281
+ identities = tuple(
282
+ (value.parent_candidate_id, tuple(sorted(value.component_option_ids)))
283
+ for value in members
284
+ )
285
+ if len(set(identities)) != len(identities):
286
+ raise PydanticCustomError(
287
+ ValidationIssueReasonCode.RESIDUAL_PLAN_DIVERSITY_VIOLATION.value,
288
+ "members cannot repeat a parent-relative plan",
289
+ )
290
+ if len({value.parent_candidate_id for value in members}) < type(self).minimum_distinct_parents:
291
+ raise PydanticCustomError(
292
+ ValidationIssueReasonCode.RESIDUAL_PLAN_DIVERSITY_VIOLATION.value,
293
+ "members do not cover enough distinct parents",
294
+ )
295
+ return self
296
+
297
+
298
+ def hierarchical_residual_output_type(
299
+ request: HierarchicalResidualProposalRequest,
300
+ ) -> type[BaseModel]:
301
+ request.__post_init__()
302
+ parent_ids = tuple(
303
+ value.parent_candidate_id.value for value in request.action_schema.bindings
304
+ )
305
+ option_ids = request.action_schema.option_ids
306
+ role_ids = tuple(value.value for value in request.allowed_roles)
307
+ metric_ids = request.required_metric_ids
308
+ parent_literal = Literal.__getitem__(parent_ids)
309
+ option_literal = Literal.__getitem__(option_ids)
310
+ role_literal = Literal.__getitem__(role_ids)
311
+ metric_literal = Literal.__getitem__(metric_ids)
312
+ prediction_type = create_model(
313
+ "ResidualMetricPrediction",
314
+ __base__=_ResidualMetricPredictionBase,
315
+ __module__=__name__,
316
+ metric_id=(metric_literal, ...),
317
+ p10_delta=(float, ...),
318
+ p50_delta=(float, ...),
319
+ p90_delta=(float, ...),
320
+ confidence=(float, Field(ge=0.0, le=1.0, strict=True)),
321
+ )
322
+ member_type = create_model(
323
+ "HierarchicalResidualMember",
324
+ __base__=_ResidualMemberBase,
325
+ __module__=__name__,
326
+ parent_candidate_id=(parent_literal, ...),
327
+ component_option_ids=(
328
+ list[option_literal],
329
+ Field(min_length=min(request.allowed_radii), max_length=max(request.allowed_radii)),
330
+ ),
331
+ role=(role_literal, ...),
332
+ probability_valid=(float, Field(ge=0.0, le=1.0, strict=True)),
333
+ effect_predictions=(
334
+ list[prediction_type],
335
+ Field(min_length=len(metric_ids), max_length=len(metric_ids)),
336
+ ),
337
+ interaction_rationale=(_Rationale, ...),
338
+ )
339
+ member_type.available_option_ids_by_parent = {
340
+ value.parent_candidate_id.value: frozenset(
341
+ option.option_id for option in value.contract.options
342
+ )
343
+ for value in request.action_schema.bindings
344
+ }
345
+ member_type.compatible_radius_two_by_parent = {
346
+ value.parent_candidate_id.value: (
347
+ frozenset(
348
+ pairwise_disjoint_parent_patch_pairs(
349
+ value.contract,
350
+ tuple(option.option_id for option in value.contract.options),
351
+ )
352
+ )
353
+ if 2 in request.allowed_radii
354
+ else frozenset()
355
+ )
356
+ for value in request.action_schema.bindings
357
+ }
358
+ member_type.allowed_radii = frozenset(request.allowed_radii)
359
+ member_type.required_metric_ids = frozenset(metric_ids)
360
+ output_type = create_model(
361
+ "HierarchicalResidualProposalSlate",
362
+ __base__=_ResidualOutputBase,
363
+ __module__=__name__,
364
+ members=(
365
+ list[member_type],
366
+ Field(min_length=request.proposal_count, max_length=request.proposal_count),
367
+ ),
368
+ slate_rationale=(_Rationale, ...),
369
+ )
370
+ output_type.proposal_count = request.proposal_count
371
+ output_type.minimum_distinct_parents = request.minimum_distinct_parents
372
+ return output_type
373
+
374
+
375
+ def render_hierarchical_residual_prompt(
376
+ request: HierarchicalResidualProposalRequest,
377
+ ) -> str:
378
+ request.__post_init__()
379
+ contract = {
380
+ "schema_version": 1,
381
+ "request_sha256": request.request_sha256,
382
+ "expert_id": request.expert_id,
383
+ "context": thaw_json(request.context),
384
+ "cross_parent_action_schema": request.action_schema.prompt_record(),
385
+ "constraints": {
386
+ "proposal_count": request.proposal_count,
387
+ "allowed_radii": list(request.allowed_radii),
388
+ "allowed_roles": [value.value for value in request.allowed_roles],
389
+ "required_metric_ids": list(request.required_metric_ids),
390
+ "minimum_distinct_parents": request.minimum_distinct_parents,
391
+ "distinct_parent_relative_plans": True,
392
+ "select_only_available_option_ids_for_parent": True,
393
+ "do_not_return_configurations": True,
394
+ "effect_forecast_contract": {
395
+ "deltas_are_parent_relative_in_raw_metric_units": True,
396
+ "quantiles": ["p10_delta", "p50_delta", "p90_delta"],
397
+ "ordered_quantiles_required": True,
398
+ "confidence_and_probability_valid_range": [0.0, 1.0],
399
+ "future_evaluator_outcomes_are_unknown": True,
400
+ },
401
+ },
402
+ }
403
+ return "\n".join(
404
+ (
405
+ request.instruction,
406
+ "",
407
+ "HIERARCHICAL RESIDUAL PROPOSAL CONTRACT",
408
+ json.dumps(
409
+ contract,
410
+ allow_nan=False,
411
+ ensure_ascii=True,
412
+ separators=(",", ":"),
413
+ sort_keys=True,
414
+ ),
415
+ "Return exactly the requested best-first proposal slate. Select only "
416
+ "a supplied parent ID and atomic option IDs available for that parent. "
417
+ "The trusted engine will materialize and validate each tuple. Forecast "
418
+ "parent-relative p10/p50/p90 metric deltas in the raw metric units; "
419
+ "do not collapse magnitude into direction labels.",
420
+ )
421
+ )
422
+
423
+
424
+ @dataclass(frozen=True, slots=True)
425
+ class HierarchicalResidualMetricForecast:
426
+ """Provider-neutral magnitude forecast for one objective metric."""
427
+
428
+ metric_id: str
429
+ p10_delta: float
430
+ p50_delta: float
431
+ p90_delta: float
432
+ confidence: float
433
+
434
+ def __post_init__(self) -> None:
435
+ if type(self.metric_id) is not str or not self.metric_id:
436
+ raise ValueError("metric_id must be non-empty")
437
+ for name in ("p10_delta", "p50_delta", "p90_delta", "confidence"):
438
+ value = getattr(self, name)
439
+ if type(value) is not float or not math.isfinite(value):
440
+ raise TypeError(f"{name} must be a finite exact float")
441
+ if not self.p10_delta <= self.p50_delta <= self.p90_delta:
442
+ raise ValueError("forecast quantiles must be ordered")
443
+ if not 0.0 <= self.confidence <= 1.0:
444
+ raise ValueError("confidence must lie in [0,1]")
445
+
446
+ @property
447
+ def direction(self) -> str:
448
+ self.__post_init__()
449
+ if self.p10_delta == self.p50_delta == self.p90_delta == 0.0:
450
+ return "unchanged"
451
+ if self.p90_delta < 0.0:
452
+ return "decrease"
453
+ if self.p10_delta > 0.0:
454
+ return "increase"
455
+ return "unknown"
456
+
457
+ def to_record(self) -> dict[str, object]:
458
+ self.__post_init__()
459
+ return {
460
+ "metric_id": self.metric_id,
461
+ "p10_delta_hex": self.p10_delta.hex(),
462
+ "p50_delta_hex": self.p50_delta.hex(),
463
+ "p90_delta_hex": self.p90_delta.hex(),
464
+ "confidence_hex": self.confidence.hex(),
465
+ "direction": self.direction,
466
+ }
467
+
468
+
469
+ @dataclass(frozen=True, slots=True)
470
+ class HierarchicalResidualProposalSelection:
471
+ request_sha256: str
472
+ decision_sha256: str
473
+ plans: tuple[HierarchicalResidualPlan, ...]
474
+ rationales: tuple[str, ...]
475
+ probability_valid: tuple[float, ...]
476
+ effect_predictions: tuple[
477
+ tuple[HierarchicalResidualMetricForecast, ...],
478
+ ...,
479
+ ]
480
+ slate_rationale: str
481
+ telemetry: AgenticCallTelemetry
482
+
483
+ def __post_init__(self) -> None:
484
+ require_sha256(self.request_sha256, "request_sha256")
485
+ require_sha256(self.decision_sha256, "decision_sha256")
486
+ if type(self.plans) is not tuple or not self.plans:
487
+ raise ValueError("plans must be a non-empty exact tuple")
488
+ if any(type(value) is not HierarchicalResidualPlan for value in self.plans):
489
+ raise TypeError("plans contain a foreign value")
490
+ for value in self.plans:
491
+ HierarchicalResidualPlan.__post_init__(value)
492
+ if type(self.rationales) is not tuple or len(self.rationales) != len(self.plans):
493
+ raise ValueError("rationales must align with plans")
494
+ if (
495
+ type(self.probability_valid) is not tuple
496
+ or len(self.probability_valid) != len(self.plans)
497
+ ):
498
+ raise ValueError("probability_valid must align with plans")
499
+ for value in self.probability_valid:
500
+ if type(value) is not float or not 0.0 <= value <= 1.0:
501
+ raise ValueError("probability_valid must contain probabilities")
502
+ if type(self.effect_predictions) is not tuple or len(self.effect_predictions) != len(self.plans):
503
+ raise ValueError("effect_predictions must align with plans")
504
+ for values in self.effect_predictions:
505
+ if type(values) is not tuple or not values:
506
+ raise ValueError("each plan must forecast at least one metric")
507
+ for value in values:
508
+ if type(value) is not HierarchicalResidualMetricForecast:
509
+ raise TypeError("effect_predictions contain a foreign value")
510
+ value.__post_init__()
511
+ metric_ids = tuple(value.metric_id for value in values)
512
+ if metric_ids != tuple(sorted(set(metric_ids))):
513
+ raise ValueError("effect prediction metrics must be canonical")
514
+ if type(self.slate_rationale) is not str or not self.slate_rationale:
515
+ raise ValueError("slate_rationale must be non-empty")
516
+ if type(self.telemetry) is not AgenticCallTelemetry:
517
+ raise TypeError("telemetry must be exact")
518
+ AgenticCallTelemetry.__post_init__(self.telemetry)
519
+
520
+ def to_record(self) -> dict[str, object]:
521
+ self.__post_init__()
522
+ return {
523
+ "schema_version": 1,
524
+ "request_sha256": self.request_sha256,
525
+ "decision_sha256": self.decision_sha256,
526
+ "plans": [value.to_record() for value in self.plans],
527
+ "rationales": list(self.rationales),
528
+ "probability_valid_hex": [
529
+ value.hex() for value in self.probability_valid
530
+ ],
531
+ "effect_predictions": [
532
+ [value.to_record() for value in values]
533
+ for values in self.effect_predictions
534
+ ],
535
+ "slate_rationale": self.slate_rationale,
536
+ }
537
+
538
+
539
+ def _telemetry(
540
+ response: StructuredGenerationResponse[Any], attempt_count: int
541
+ ) -> AgenticCallTelemetry:
542
+ return AgenticCallTelemetry(
543
+ requested_model=response.requested_model,
544
+ resolved_model=response.resolved_model,
545
+ resolved_provider=response.resolved_provider,
546
+ provider_response_id=response.provider_response_id,
547
+ finish_reason=response.finish_reason,
548
+ input_tokens=response.input_tokens,
549
+ output_tokens=response.output_tokens,
550
+ reasoning_tokens=response.reasoning_tokens,
551
+ cache_read_tokens=response.cache_read_tokens,
552
+ cache_write_tokens=response.cache_write_tokens,
553
+ cost_usd=response.cost_usd,
554
+ latency_ns=response.latency_ns,
555
+ attempt_count=attempt_count,
556
+ )
557
+
558
+
559
+ @dataclass(slots=True)
560
+ class PydanticAIHierarchicalResidualProposalPolicy:
561
+ generate_once: LowLevelRunner
562
+
563
+ def __post_init__(self) -> None:
564
+ if not callable(self.generate_once):
565
+ raise TypeError("generate_once must be callable")
566
+
567
+ async def select(
568
+ self,
569
+ request: HierarchicalResidualProposalRequest,
570
+ ) -> HierarchicalResidualProposalSelection:
571
+ request.__post_init__()
572
+ output_type = hierarchical_residual_output_type(request)
573
+ prompt = render_hierarchical_residual_prompt(request)
574
+ raw = await self.generate_once(
575
+ StructuredGenerationRequest(
576
+ call_id=request.call_id,
577
+ operation=request.operation,
578
+ prompt=prompt,
579
+ output_type=output_type,
580
+ output_tool_name=HIERARCHICAL_RESIDUAL_PROPOSAL_TOOL_NAME,
581
+ max_output_tokens=request.max_output_tokens,
582
+ temperature=request.temperature,
583
+ )
584
+ )
585
+ if type(raw) is AttemptedStructuredGenerationResponse:
586
+ response = raw.response
587
+ attempt_count = raw.attempt_count
588
+ elif type(raw) is StructuredGenerationResponse:
589
+ response = raw
590
+ attempt_count = 1
591
+ else:
592
+ raise TypeError("low-level runner returned a foreign response")
593
+ StructuredGenerationResponse.__post_init__(response)
594
+ if type(response.value) is not output_type:
595
+ raise TypeError("response value differs from the requested output type")
596
+ value = cast(Any, response.value)
597
+ draft_record = {
598
+ "schema_version": 1,
599
+ "request_sha256": request.request_sha256,
600
+ "members": [member.model_dump(mode="json") for member in value.members],
601
+ "slate_rationale": value.slate_rationale,
602
+ }
603
+ decision_sha256 = _hash(draft_record)
604
+ plans = tuple(
605
+ HierarchicalResidualPlan(
606
+ parent_candidate_id=next(
607
+ binding.parent_candidate_id
608
+ for binding in request.action_schema.bindings
609
+ if binding.parent_candidate_id.value == member.parent_candidate_id
610
+ ),
611
+ parent_contract_sha256=request.action_schema.contract_for(
612
+ next(
613
+ binding.parent_candidate_id
614
+ for binding in request.action_schema.bindings
615
+ if binding.parent_candidate_id.value
616
+ == member.parent_candidate_id
617
+ )
618
+ ).identity_sha256,
619
+ action_schema_sha256=request.action_schema.schema_sha256,
620
+ component_option_ids=tuple(sorted(member.component_option_ids)),
621
+ role=ResidualProposalRole(member.role),
622
+ expert_id=request.expert_id,
623
+ expert_definition_sha256=request.expert_definition_sha256,
624
+ native_rank=rank,
625
+ decision_receipt_sha256=decision_sha256,
626
+ )
627
+ for rank, member in enumerate(value.members, start=1)
628
+ )
629
+ result = HierarchicalResidualProposalSelection(
630
+ request_sha256=request.request_sha256,
631
+ decision_sha256=decision_sha256,
632
+ plans=plans,
633
+ rationales=tuple(member.interaction_rationale for member in value.members),
634
+ probability_valid=tuple(
635
+ float(member.probability_valid)
636
+ for member in value.members
637
+ ),
638
+ effect_predictions=tuple(
639
+ tuple(
640
+ sorted(
641
+ (
642
+ HierarchicalResidualMetricForecast(
643
+ metric_id=prediction.metric_id,
644
+ p10_delta=float(prediction.p10_delta),
645
+ p50_delta=float(prediction.p50_delta),
646
+ p90_delta=float(prediction.p90_delta),
647
+ confidence=float(prediction.confidence),
648
+ )
649
+ for prediction in member.effect_predictions
650
+ ),
651
+ key=lambda item: item.metric_id,
652
+ )
653
+ )
654
+ for member in value.members
655
+ ),
656
+ slate_rationale=value.slate_rationale,
657
+ telemetry=_telemetry(response, attempt_count),
658
+ )
659
+ result.__post_init__()
660
+ return result
661
+
662
+
663
+ __all__ = [
664
+ "HIERARCHICAL_RESIDUAL_PROPOSAL_POLICY_DEFINITION_SHA256",
665
+ "HIERARCHICAL_RESIDUAL_PROPOSAL_POLICY_ID",
666
+ "HIERARCHICAL_RESIDUAL_PROPOSAL_POLICY_VERSION",
667
+ "HIERARCHICAL_RESIDUAL_PROPOSAL_TOOL_NAME",
668
+ "HierarchicalResidualProposalRequest",
669
+ "HierarchicalResidualProposalSelection",
670
+ "HierarchicalResidualMetricForecast",
671
+ "PydanticAIHierarchicalResidualProposalPolicy",
672
+ "hierarchical_residual_output_type",
673
+ "render_hierarchical_residual_prompt",
674
+ ]