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,559 @@
1
+ """Sealed *model-authored* candidates: replay by content, not by menu index.
2
+
3
+ The finite variation catalogue (:mod:`agent_evolve.domain.finite_variation`)
4
+ seals a decision as an **opaque option identifier** and lets trusted benchmark
5
+ code own every child configuration. That makes replay trivial -- resolve the id
6
+ against the sealed contract -- at the cost of deleting the operator: the model
7
+ never authors a genotype, it filters a list.
8
+
9
+ This module is the other half of that trade. A generative proposal seals the
10
+ **emitted configuration itself**, together with the exact prompt that produced
11
+ it and the schema that bounded it, so a replay reconstructs the decision from
12
+ the emission rather than from a catalogue index. Nothing here needs a
13
+ provider, a network, or a pre-enumerated option set.
14
+
15
+ Three properties are preserved from the catalogue scheme, and one is
16
+ deliberately given up.
17
+
18
+ Preserved:
19
+
20
+ ``provider-free replay`` the configuration is stored verbatim as canonical
21
+ typed JSON, so replay is a parse, not a call.
22
+ ``content addressing`` every record self-authenticates under a separated
23
+ hash domain, and calls are chained, so a call that
24
+ did not happen cannot be inserted after the fact.
25
+ ``support pinning`` ``candidate_schema_sha256`` records the exact schema
26
+ the emission was drawn from, which is what makes a
27
+ matched null checkable: the null must sample *that*
28
+ schema, not some other one.
29
+
30
+ Given up, on purpose:
31
+
32
+ ``bounded model authority`` the model now authors configurations. That is the
33
+ mechanism the catalogue was suppressing, so the
34
+ replacement guarantee is feasibility rather than
35
+ enumeration -- every emission carries the verdict
36
+ the problem's own ``validate`` returned for it, and
37
+ replay re-runs ``validate`` and requires agreement.
38
+ """
39
+
40
+ from __future__ import annotations
41
+
42
+ import hashlib
43
+ import re
44
+ from dataclasses import dataclass
45
+
46
+ from agent_evolve.domain.patch import require_sha256
47
+ from agent_evolve.domain.typed_json import (
48
+ FrozenJsonObject,
49
+ canonical_typed_json_bytes,
50
+ freeze_json,
51
+ typed_json_sha256,
52
+ )
53
+
54
+ __all__ = [
55
+ "GENESIS_CALL_SHA256",
56
+ "GenerativeEmission",
57
+ "GenerativeProposalCall",
58
+ "MAX_EMISSIONS_PER_CALL",
59
+ "SealedGuidanceCall",
60
+ "SealedRunHeader",
61
+ "chain_sealed_calls",
62
+ "generative_prompt_sha256",
63
+ "validate_generative_emission",
64
+ "validate_generative_proposal_call",
65
+ "validate_sealed_guidance_call",
66
+ "validate_sealed_run_header",
67
+ ]
68
+
69
+
70
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
71
+ _MODEL_ID = re.compile(r"^[A-Za-z0-9][A-Za-z0-9_.:/-]{0,255}$")
72
+ _MAX_REASON_BYTES = 4_096
73
+
74
+ #: An emitted batch is a proposal, not a corpus. The loop asks for at most a
75
+ #: generation's worth; anything larger is a runaway model, not a decision.
76
+ MAX_EMISSIONS_PER_CALL = 256
77
+
78
+ #: The predecessor digest of the first call in a campaign. A chain that starts
79
+ #: anywhere else is a chain with a missing head.
80
+ GENESIS_CALL_SHA256 = "0" * 64
81
+
82
+ #: Guidance text that survives into the next prompt. A model that writes a
83
+ #: paragraph of insight and then reads it back next generation is running a
84
+ #: feedback loop, and replaying the proposals without it would reconstruct a
85
+ #: different question. Bounded so a runaway generation cannot be sealed.
86
+ MAX_GUIDANCE_BYTES = 262_144
87
+
88
+ _PROMPT_HASH_DOMAIN = b"agent-evolve:generative-proposal-prompt:v1\x00"
89
+ _EMISSION_HASH_DOMAIN = b"agent-evolve:generative-proposal-emission:v1\x00"
90
+ _CALL_HASH_DOMAIN = b"agent-evolve:generative-proposal-call:v1\x00"
91
+ _GUIDANCE_CALL_HASH_DOMAIN = b"agent-evolve:generative-guidance-call:v1\x00"
92
+ _RUN_HEADER_HASH_DOMAIN = b"agent-evolve:generative-run-header:v1\x00"
93
+
94
+
95
+ def _frame(payload: bytes) -> bytes:
96
+ if type(payload) is not bytes:
97
+ raise TypeError("framed payloads must be exact bytes")
98
+ return len(payload).to_bytes(8, "big", signed=False) + payload
99
+
100
+
101
+ def _bounded_reason(value: str) -> bytes:
102
+ if type(value) is not str:
103
+ raise TypeError("rejection_reason must be an exact string")
104
+ encoded = value.encode("utf-8", errors="strict")
105
+ if len(encoded) > _MAX_REASON_BYTES:
106
+ raise ValueError("rejection_reason exceeds its byte limit")
107
+ return encoded
108
+
109
+
110
+ def generative_prompt_sha256(instruction: str) -> str:
111
+ """Digest the exact instruction text a generative call was issued with.
112
+
113
+ The prompt is hashed rather than stored: it is reconstructible from the
114
+ sealed campaign inputs, and a hash is what a replay needs in order to prove
115
+ it is answering the same question. Domain separation keeps this digest from
116
+ colliding with any other use of the same bytes.
117
+ """
118
+
119
+ if type(instruction) is not str:
120
+ raise TypeError("instruction must be an exact string")
121
+ if not instruction:
122
+ raise ValueError("instruction must be non-empty")
123
+ return hashlib.sha256(
124
+ _PROMPT_HASH_DOMAIN + _frame(instruction.encode("utf-8", errors="strict"))
125
+ ).hexdigest()
126
+
127
+
128
+ @dataclass(frozen=True, slots=True, eq=False)
129
+ class GenerativeEmission:
130
+ """One configuration the model authored, with the verdict it earned.
131
+
132
+ ``configuration`` is the complete candidate, frozen typed JSON, exactly as
133
+ it will be handed to ``materialize``. ``accepted`` is what the problem's
134
+ ``validate`` said about it at emission time; a replay that re-validates and
135
+ disagrees is a broken replay, not a repaired one.
136
+ """
137
+
138
+ configuration: FrozenJsonObject
139
+ accepted: bool
140
+ rejection_reason: str = ""
141
+
142
+ def __post_init__(self) -> None:
143
+ if type(self.configuration) is not FrozenJsonObject:
144
+ raise TypeError("configuration must be an exact FrozenJsonObject")
145
+ if freeze_json(self.configuration) is not self.configuration:
146
+ raise TypeError("configuration must already be frozen typed JSON")
147
+ if type(self.accepted) is not bool:
148
+ raise TypeError("accepted must be an exact bool")
149
+ _bounded_reason(self.rejection_reason)
150
+ if self.accepted and self.rejection_reason:
151
+ raise ValueError("an accepted emission carries no rejection reason")
152
+ if not self.accepted and not self.rejection_reason:
153
+ raise ValueError(
154
+ "a rejected emission must carry the reason validate() gave, "
155
+ "because that reason is what the proposer was shown"
156
+ )
157
+
158
+ @property
159
+ def configuration_sha256(self) -> str:
160
+ validate_generative_emission(self)
161
+ return typed_json_sha256(self.configuration)
162
+
163
+ @property
164
+ def identity_sha256(self) -> str:
165
+ """Bind the full configuration and its feasibility verdict."""
166
+
167
+ validate_generative_emission(self)
168
+ digest = hashlib.sha256()
169
+ digest.update(_EMISSION_HASH_DOMAIN)
170
+ digest.update(_frame(canonical_typed_json_bytes(self.configuration)))
171
+ digest.update(b"\x01" if self.accepted else b"\x00")
172
+ digest.update(_frame(_bounded_reason(self.rejection_reason)))
173
+ return digest.hexdigest()
174
+
175
+ def to_record(self) -> dict[str, object]:
176
+ """Return the durable projection. The configuration is *not* elided.
177
+
178
+ A catalogue seal can publish an option id and stay content-free because
179
+ the contract holds the child. Here the emission is the only copy, so
180
+ replay needs it in full.
181
+ """
182
+
183
+ validate_generative_emission(self)
184
+ return {
185
+ "configuration": _thawed(self.configuration),
186
+ "configuration_sha256": self.configuration_sha256,
187
+ "accepted": self.accepted,
188
+ "rejection_reason": self.rejection_reason,
189
+ "emission_identity_sha256": self.identity_sha256,
190
+ }
191
+
192
+ def _validated_values(self) -> tuple[object, ...]:
193
+ validate_generative_emission(self)
194
+ return (
195
+ canonical_typed_json_bytes(self.configuration),
196
+ self.accepted,
197
+ self.rejection_reason,
198
+ )
199
+
200
+ def __eq__(self, other: object) -> bool:
201
+ if type(self) is not GenerativeEmission or type(other) is not GenerativeEmission:
202
+ return False
203
+ return self._validated_values() == other._validated_values()
204
+
205
+ def __hash__(self) -> int:
206
+ return hash((GenerativeEmission, self._validated_values()))
207
+
208
+
209
+ def _thawed(value: FrozenJsonObject) -> dict[str, object]:
210
+ from agent_evolve.domain.typed_json import thaw_json
211
+
212
+ thawed = thaw_json(value)
213
+ if type(thawed) is not dict:
214
+ raise TypeError("a frozen JSON object must thaw to an exact dict")
215
+ return thawed
216
+
217
+
218
+ def validate_generative_emission(emission: GenerativeEmission) -> None:
219
+ """Revalidate an exact emission at a public trust boundary."""
220
+
221
+ if type(emission) is not GenerativeEmission:
222
+ raise TypeError("emission must be an exact GenerativeEmission")
223
+ GenerativeEmission.__post_init__(emission)
224
+
225
+
226
+ @dataclass(frozen=True, slots=True, eq=False)
227
+ class GenerativeProposalCall:
228
+ """One sealed model call: what was asked, what came back, and after what.
229
+
230
+ ``previous_call_sha256`` chains the calls of a campaign in issue order. The
231
+ chain is the part that makes fabrication detectable: a record invented for a
232
+ call that never happened cannot be spliced in without recomputing every
233
+ digest after it, and the campaign's terminal digest is published.
234
+ """
235
+
236
+ call_ordinal: int
237
+ op: str
238
+ requested_model: str
239
+ prompt_sha256: str
240
+ candidate_schema_sha256: str
241
+ emissions: tuple[GenerativeEmission, ...]
242
+ previous_call_sha256: str = GENESIS_CALL_SHA256
243
+
244
+ def __post_init__(self) -> None:
245
+ if type(self.call_ordinal) is not int or self.call_ordinal < 0:
246
+ raise ValueError("call_ordinal must be a non-negative exact integer")
247
+ if type(self.op) is not str or _TOKEN.fullmatch(self.op) is None:
248
+ raise ValueError("op must use the closed lowercase token grammar")
249
+ if (
250
+ type(self.requested_model) is not str
251
+ or _MODEL_ID.fullmatch(self.requested_model) is None
252
+ ):
253
+ raise ValueError("requested_model must be a closed model identifier")
254
+ require_sha256(self.prompt_sha256, "prompt_sha256")
255
+ require_sha256(self.candidate_schema_sha256, "candidate_schema_sha256")
256
+ require_sha256(self.previous_call_sha256, "previous_call_sha256")
257
+ if type(self.emissions) is not tuple:
258
+ raise TypeError("emissions must be an exact tuple")
259
+ if not self.emissions:
260
+ raise ValueError(
261
+ "a sealed call must carry at least one emission; a call that "
262
+ "returned nothing is a failure to record as a failure, not an "
263
+ "empty success"
264
+ )
265
+ if len(self.emissions) > MAX_EMISSIONS_PER_CALL:
266
+ raise ValueError("emission batch exceeds its limit")
267
+ for emission in self.emissions:
268
+ validate_generative_emission(emission)
269
+
270
+ @property
271
+ def identity_sha256(self) -> str:
272
+ """Bind the request identity, every emission, and the predecessor."""
273
+
274
+ validate_generative_proposal_call(self)
275
+ digest = hashlib.sha256()
276
+ digest.update(_CALL_HASH_DOMAIN)
277
+ digest.update(bytes.fromhex(self.previous_call_sha256))
278
+ digest.update(self.call_ordinal.to_bytes(8, "big", signed=False))
279
+ digest.update(_frame(self.op.encode("ascii")))
280
+ digest.update(_frame(self.requested_model.encode("ascii")))
281
+ digest.update(bytes.fromhex(self.prompt_sha256))
282
+ digest.update(bytes.fromhex(self.candidate_schema_sha256))
283
+ digest.update(len(self.emissions).to_bytes(8, "big", signed=False))
284
+ for emission in self.emissions:
285
+ digest.update(bytes.fromhex(emission.identity_sha256))
286
+ return digest.hexdigest()
287
+
288
+ @property
289
+ def accepted_configurations(self) -> tuple[FrozenJsonObject, ...]:
290
+ validate_generative_proposal_call(self)
291
+ return tuple(e.configuration for e in self.emissions if e.accepted)
292
+
293
+ def to_record(self) -> dict[str, object]:
294
+ validate_generative_proposal_call(self)
295
+ return {
296
+ "schema_version": 1,
297
+ "record_kind": "proposal",
298
+ "call_ordinal": self.call_ordinal,
299
+ "op": self.op,
300
+ "requested_model": self.requested_model,
301
+ "prompt_sha256": self.prompt_sha256,
302
+ "candidate_schema_sha256": self.candidate_schema_sha256,
303
+ "previous_call_sha256": self.previous_call_sha256,
304
+ "emissions": [e.to_record() for e in self.emissions],
305
+ "call_identity_sha256": self.identity_sha256,
306
+ }
307
+
308
+ def _validated_values(self) -> tuple[object, ...]:
309
+ validate_generative_proposal_call(self)
310
+ return (
311
+ self.call_ordinal,
312
+ self.op,
313
+ self.requested_model,
314
+ self.prompt_sha256,
315
+ self.candidate_schema_sha256,
316
+ self.previous_call_sha256,
317
+ tuple(e._validated_values() for e in self.emissions),
318
+ )
319
+
320
+ def __eq__(self, other: object) -> bool:
321
+ if (
322
+ type(self) is not GenerativeProposalCall
323
+ or type(other) is not GenerativeProposalCall
324
+ ):
325
+ return False
326
+ return self._validated_values() == other._validated_values()
327
+
328
+ def __hash__(self) -> int:
329
+ return hash((GenerativeProposalCall, self._validated_values()))
330
+
331
+
332
+ def validate_generative_proposal_call(call: GenerativeProposalCall) -> None:
333
+ """Revalidate an exact call at a public trust boundary."""
334
+
335
+ if type(call) is not GenerativeProposalCall:
336
+ raise TypeError("call must be an exact GenerativeProposalCall")
337
+ GenerativeProposalCall.__post_init__(call)
338
+
339
+
340
+ @dataclass(frozen=True, slots=True, eq=False)
341
+ class SealedGuidanceCall:
342
+ """One sealed model call that returned text rather than configurations.
343
+
344
+ Insight and constraint-guide calls author no candidate, so they are not the
345
+ operator under test -- but their output is *pasted into the next prompt*.
346
+ Leaving them out of the chain would make the next proposal call unreplayable
347
+ for a reason that looks like drift and is really an omission, so they are
348
+ sealed at the same altitude and in the same sequence.
349
+ """
350
+
351
+ call_ordinal: int
352
+ op: str
353
+ requested_model: str
354
+ prompt_sha256: str
355
+ outputs: tuple[str, ...]
356
+ previous_call_sha256: str = GENESIS_CALL_SHA256
357
+
358
+ def __post_init__(self) -> None:
359
+ if type(self.call_ordinal) is not int or self.call_ordinal < 0:
360
+ raise ValueError("call_ordinal must be a non-negative exact integer")
361
+ if type(self.op) is not str or _TOKEN.fullmatch(self.op) is None:
362
+ raise ValueError("op must use the closed lowercase token grammar")
363
+ if (
364
+ type(self.requested_model) is not str
365
+ or _MODEL_ID.fullmatch(self.requested_model) is None
366
+ ):
367
+ raise ValueError("requested_model must be a closed model identifier")
368
+ require_sha256(self.prompt_sha256, "prompt_sha256")
369
+ require_sha256(self.previous_call_sha256, "previous_call_sha256")
370
+ if type(self.outputs) is not tuple:
371
+ raise TypeError("outputs must be an exact tuple")
372
+ total = 0
373
+ for value in self.outputs:
374
+ if type(value) is not str:
375
+ raise TypeError("every guidance output must be an exact string")
376
+ total += len(value.encode("utf-8", errors="strict"))
377
+ if total > MAX_GUIDANCE_BYTES:
378
+ raise ValueError("guidance output exceeds its byte limit")
379
+
380
+ @property
381
+ def identity_sha256(self) -> str:
382
+ validate_sealed_guidance_call(self)
383
+ digest = hashlib.sha256()
384
+ digest.update(_GUIDANCE_CALL_HASH_DOMAIN)
385
+ digest.update(bytes.fromhex(self.previous_call_sha256))
386
+ digest.update(self.call_ordinal.to_bytes(8, "big", signed=False))
387
+ digest.update(_frame(self.op.encode("ascii")))
388
+ digest.update(_frame(self.requested_model.encode("ascii")))
389
+ digest.update(bytes.fromhex(self.prompt_sha256))
390
+ digest.update(len(self.outputs).to_bytes(8, "big", signed=False))
391
+ for value in self.outputs:
392
+ digest.update(_frame(value.encode("utf-8", errors="strict")))
393
+ return digest.hexdigest()
394
+
395
+ def to_record(self) -> dict[str, object]:
396
+ validate_sealed_guidance_call(self)
397
+ return {
398
+ "schema_version": 1,
399
+ "record_kind": "guidance",
400
+ "call_ordinal": self.call_ordinal,
401
+ "op": self.op,
402
+ "requested_model": self.requested_model,
403
+ "prompt_sha256": self.prompt_sha256,
404
+ "previous_call_sha256": self.previous_call_sha256,
405
+ "outputs": list(self.outputs),
406
+ "call_identity_sha256": self.identity_sha256,
407
+ }
408
+
409
+ def _validated_values(self) -> tuple[object, ...]:
410
+ validate_sealed_guidance_call(self)
411
+ return (
412
+ self.call_ordinal,
413
+ self.op,
414
+ self.requested_model,
415
+ self.prompt_sha256,
416
+ self.previous_call_sha256,
417
+ self.outputs,
418
+ )
419
+
420
+ def __eq__(self, other: object) -> bool:
421
+ if type(self) is not SealedGuidanceCall or type(other) is not SealedGuidanceCall:
422
+ return False
423
+ return self._validated_values() == other._validated_values()
424
+
425
+ def __hash__(self) -> int:
426
+ return hash((SealedGuidanceCall, self._validated_values()))
427
+
428
+
429
+ def validate_sealed_guidance_call(call: SealedGuidanceCall) -> None:
430
+ """Revalidate an exact guidance call at a public trust boundary."""
431
+
432
+ if type(call) is not SealedGuidanceCall:
433
+ raise TypeError("call must be an exact SealedGuidanceCall")
434
+ SealedGuidanceCall.__post_init__(call)
435
+
436
+
437
+ @dataclass(frozen=True, slots=True, eq=False)
438
+ class SealedRunHeader:
439
+ """The run-level declarations a replay cannot re-derive from the calls.
440
+
441
+ ``provides_insights`` is the reason this record exists. The loop skips
442
+ guidance operations entirely for a proposer that declares it makes none --
443
+ an uninformed baseline is exactly that case -- and a replay has no delegate
444
+ to ask. Guessing produced a call the recording never made, and then a drift
445
+ error about a divergence the replay had itself invented. A declaration that
446
+ changes which calls happen has to be sealed, not inferred.
447
+ """
448
+
449
+ proposer_id: str
450
+ requested_model: str
451
+ candidate_schema_sha256: str
452
+ provides_insights: bool
453
+ call_ordinal: int = 0
454
+ previous_call_sha256: str = GENESIS_CALL_SHA256
455
+
456
+ def __post_init__(self) -> None:
457
+ if type(self.proposer_id) is not str or _TOKEN.fullmatch(
458
+ self.proposer_id
459
+ ) is None:
460
+ raise ValueError("proposer_id must use the closed lowercase token grammar")
461
+ if (
462
+ type(self.requested_model) is not str
463
+ or _MODEL_ID.fullmatch(self.requested_model) is None
464
+ ):
465
+ raise ValueError("requested_model must be a closed model identifier")
466
+ require_sha256(self.candidate_schema_sha256, "candidate_schema_sha256")
467
+ if type(self.provides_insights) is not bool:
468
+ raise TypeError("provides_insights must be an exact bool")
469
+ if self.call_ordinal != 0:
470
+ raise ValueError("the run header is always the head of the chain")
471
+ if self.previous_call_sha256 != GENESIS_CALL_SHA256:
472
+ raise ValueError("the run header follows nothing")
473
+
474
+ @property
475
+ def identity_sha256(self) -> str:
476
+ validate_sealed_run_header(self)
477
+ digest = hashlib.sha256()
478
+ digest.update(_RUN_HEADER_HASH_DOMAIN)
479
+ digest.update(_frame(self.proposer_id.encode("ascii")))
480
+ digest.update(_frame(self.requested_model.encode("ascii")))
481
+ digest.update(bytes.fromhex(self.candidate_schema_sha256))
482
+ digest.update(b"\x01" if self.provides_insights else b"\x00")
483
+ return digest.hexdigest()
484
+
485
+ def to_record(self) -> dict[str, object]:
486
+ validate_sealed_run_header(self)
487
+ return {
488
+ "schema_version": 1,
489
+ "record_kind": "run_header",
490
+ "call_ordinal": 0,
491
+ "proposer_id": self.proposer_id,
492
+ "requested_model": self.requested_model,
493
+ "candidate_schema_sha256": self.candidate_schema_sha256,
494
+ "provides_insights": self.provides_insights,
495
+ "previous_call_sha256": self.previous_call_sha256,
496
+ "call_identity_sha256": self.identity_sha256,
497
+ }
498
+
499
+ def __eq__(self, other: object) -> bool:
500
+ if type(self) is not SealedRunHeader or type(other) is not SealedRunHeader:
501
+ return False
502
+ return self.to_record() == other.to_record()
503
+
504
+ def __hash__(self) -> int:
505
+ return hash((SealedRunHeader, self.identity_sha256))
506
+
507
+
508
+ def validate_sealed_run_header(header: SealedRunHeader) -> None:
509
+ """Revalidate an exact run header at a public trust boundary."""
510
+
511
+ if type(header) is not SealedRunHeader:
512
+ raise TypeError("header must be an exact SealedRunHeader")
513
+ SealedRunHeader.__post_init__(header)
514
+
515
+
516
+ def chain_sealed_calls(
517
+ calls: tuple[object, ...],
518
+ ) -> str:
519
+ """Verify a campaign's call chain and return its terminal digest.
520
+
521
+ Raises on the three ways a chain can lie: a missing head, a gap or a
522
+ reordering in the ordinals, and a predecessor digest that does not match the
523
+ call it claims to follow. Proposal and guidance calls share one sequence
524
+ because they share one conversation, and their hash domains differ so one
525
+ can never be replayed as the other.
526
+ """
527
+
528
+ if type(calls) is not tuple:
529
+ raise TypeError("calls must be an exact tuple")
530
+ if not calls:
531
+ raise ValueError("a campaign chain requires at least one call")
532
+ if type(calls[0]) is not SealedRunHeader:
533
+ raise ValueError(
534
+ "a sealed chain begins with its run header; without it a replay "
535
+ "cannot know which operations the recorded proposer declined"
536
+ )
537
+ previous = GENESIS_CALL_SHA256
538
+ for index, call in enumerate(calls):
539
+ if type(call) is SealedRunHeader:
540
+ validate_sealed_run_header(call)
541
+ if index != 0:
542
+ raise ValueError("a run header can only be the head of the chain")
543
+ elif type(call) is GenerativeProposalCall:
544
+ validate_generative_proposal_call(call)
545
+ elif type(call) is SealedGuidanceCall:
546
+ validate_sealed_guidance_call(call)
547
+ else:
548
+ raise TypeError("a sealed chain holds only exact sealed call records")
549
+ if call.call_ordinal != index:
550
+ raise ValueError(
551
+ f"call chain is not contiguous at position {index}: "
552
+ f"ordinal {call.call_ordinal}"
553
+ )
554
+ if call.previous_call_sha256 != previous:
555
+ raise ValueError(
556
+ f"call {index} does not follow the call it claims to follow"
557
+ )
558
+ previous = call.identity_sha256
559
+ return previous