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,1561 @@
1
+ """High-level agentic generation port used by the evolutionary workflow."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import hashlib
6
+ import math
7
+ import re
8
+ from dataclasses import dataclass, field
9
+ from decimal import Decimal
10
+ from enum import Enum
11
+ from typing import Any, Protocol, Tuple, runtime_checkable
12
+
13
+ from agent_evolve.domain.finite_variation import (
14
+ FiniteVariationContract,
15
+ FiniteVariationOption,
16
+ validate_finite_variation_contract,
17
+ )
18
+ from agent_evolve.domain.ids import LLMCallId
19
+ from agent_evolve.domain.patch import (
20
+ ArrayIndex,
21
+ JsonPath,
22
+ ObjectKey,
23
+ require_sha256,
24
+ validate_json_path,
25
+ )
26
+ from agent_evolve.domain.typed_json import (
27
+ FrozenJsonArray,
28
+ FrozenJsonObject,
29
+ FrozenJsonValue,
30
+ canonical_typed_json_bytes,
31
+ freeze_json,
32
+ is_json_scalar,
33
+ typed_json_equal,
34
+ )
35
+
36
+
37
+ _LOWER_SHA256 = re.compile(r"^[0-9a-f]{64}$")
38
+ _FINITE_OPTION_ID = re.compile(r"^[a-z][a-z0-9_.-]{0,255}$")
39
+ _CROSSOVER_LOCUS_ID = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
40
+ _REFLECTION_METRIC_ID = re.compile(r"^[a-z][a-z0-9_.:-]{0,191}$")
41
+ _FINITE_OPTION_FAMILY = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
42
+ _REFLECTION_SEMANTIC_TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,191}$")
43
+ _REFLECTION_DECISION_PATH = re.compile(r"^\$([.\[].*)?$")
44
+ _REFLECTION_INSIGHT_CONTRACT_DOMAIN = b"agent-evolve:reflection-insight-contract:v2\x00"
45
+ _REFLECTION_INSIGHT_CONTRACT_V3_DOMAIN = (
46
+ b"agent-evolve:reflection-insight-contract:v3\x00"
47
+ )
48
+ _REFLECTION_EVIDENCE_CATALOG_DOMAIN = b"agent-evolve:reflection-evidence-catalog:v1\x00"
49
+ _INSIGHT_DRAFT_CONTENT_DOMAIN = b"agent-evolve:insight-draft-content:v1\x00"
50
+ _INSIGHT_DRAFT_HYPOTHESIS_DOMAIN = (
51
+ b"agent-evolve:insight-draft-unverified-hypothesis:v1\x00"
52
+ )
53
+
54
+ # Shared by the prompt policy and the provider-visible structured-output schema.
55
+ # Keeping this at the port boundary prevents adapters from inventing different
56
+ # meanings for the same candidate-relative evidence paths.
57
+ CANDIDATE_COMPONENT_PATH_CONTRACT = (
58
+ "For every intended_changes entry and source_attribution.path, '$' denotes "
59
+ "the returned configuration value itself, not the enclosing proposal and "
60
+ "not a parent-evidence record. For example, when configuration is "
61
+ '{"gene":1,"settings":{"rate":2}}, use "$.gene" and '
62
+ '"$.settings.rate". For that example, "$.configuration.gene", '
63
+ '"$.parents[0].configuration.gene", and "$" are invalid component paths. '
64
+ "Never copy an enclosing configuration or parents wrapper into a path; "
65
+ '"$.configuration..." is valid only when "configuration" is genuinely a '
66
+ "top-level component inside the candidate configuration."
67
+ )
68
+
69
+ # Shared by the generic two-parent prompt and its provider-visible output
70
+ # schema. Left/right claims are executable provenance: the engine verifies the
71
+ # witness and copies the exact immutable subtree from the named parent.
72
+ TWO_PARENT_CROSSOVER_EVIDENCE_CONTRACT = (
73
+ "For a two-parent crossover, source='left' or source='right' is valid at a "
74
+ "path only when the intended child matches that named parent and differs "
75
+ "from the other parent at the same path. The engine treats each left/right "
76
+ "claim as an executable inheritance instruction and copies the exact "
77
+ "immutable parent subtree; the returned configuration is a consistency "
78
+ "witness, not authority for inherited values. Its structure and nonnumeric "
79
+ "values must match exactly; each finite float leaf may differ by at most "
80
+ "one binary64 ULP to accommodate decimal serialization drift. A path where "
81
+ "both parents have "
82
+ "identical values proves neither side and must not be attributed to left "
83
+ "or right. If the child preserves that shared value, omit the path from "
84
+ "both source_attribution and intended_changes; if the child changes it, "
85
+ "attribute the genuinely new value as synthesized. Synthesized values "
86
+ "remain model-authored and must differ from both parents at their explicit "
87
+ "paths. A structural deletion must be attributed as synthesized at the "
88
+ "smallest retained containing object or array whose complete child value "
89
+ "reflects the deletion; an omitted path cannot itself be claimed. Claims "
90
+ "must be unique, non-overlapping, and collectively account for every "
91
+ "parent/child difference. Any unclaimed value shared by both parents must "
92
+ "remain present and exactly equal in the child. Include at least one "
93
+ "discriminating left contribution and at least one discriminating right "
94
+ "contribution."
95
+ )
96
+
97
+ MAX_REFLECTION_EVIDENCE_CATALOG_ENTRIES = 256
98
+ MAX_REFLECTION_SEMANTIC_VOCABULARY_ENTRIES = 256
99
+ MAX_REFLECTION_DECISION_PATH_CHARS = 4_096
100
+ _REFLECTION_EVIDENCE_CITATION_KEY = re.compile(r"^e[0-9]{4}$")
101
+
102
+
103
+ def _validate_contrast_ids(values: tuple[str, ...], *, name: str) -> None:
104
+ if type(values) is not tuple or any(
105
+ type(value) is not str or _LOWER_SHA256.fullmatch(value) is None
106
+ for value in values
107
+ ):
108
+ raise TypeError(f"{name} must be an exact tuple of lowercase SHA-256 IDs")
109
+ if values != tuple(sorted(set(values))):
110
+ raise ValueError(f"{name} must be unique and canonically sorted")
111
+
112
+
113
+ def _validate_canonical_tokens(
114
+ values: tuple[str, ...],
115
+ *,
116
+ name: str,
117
+ pattern: re.Pattern[str],
118
+ ) -> None:
119
+ if type(values) is not tuple or any(
120
+ type(value) is not str or pattern.fullmatch(value) is None for value in values
121
+ ):
122
+ raise TypeError(f"{name} must be an exact tuple of canonical identifiers")
123
+ if not values:
124
+ raise ValueError(f"{name} must be non-empty")
125
+ if values != tuple(sorted(set(values))):
126
+ raise ValueError(f"{name} must be unique and canonically sorted")
127
+
128
+
129
+ def _validate_canonical_enum_values(
130
+ values: tuple[Enum, ...],
131
+ *,
132
+ name: str,
133
+ enum_type: type[Enum],
134
+ allow_empty: bool = False,
135
+ ) -> None:
136
+ if type(values) is not tuple or any(
137
+ type(value) is not enum_type for value in values
138
+ ):
139
+ raise TypeError(f"{name} must be an exact tuple of {enum_type.__name__} values")
140
+ if not values and not allow_empty:
141
+ raise ValueError(f"{name} must be non-empty")
142
+ canonical = tuple(sorted(set(values), key=lambda value: str(value.value)))
143
+ if values != canonical:
144
+ raise ValueError(f"{name} must be unique and canonically sorted")
145
+
146
+
147
+ def _validate_decision_paths(values: tuple[str, ...], *, name: str) -> None:
148
+ if type(values) is not tuple or any(type(value) is not str for value in values):
149
+ raise TypeError(f"{name} must be an exact tuple of strings")
150
+ if not values:
151
+ raise ValueError(f"{name} must be non-empty")
152
+ if any(
153
+ len(value) > MAX_REFLECTION_DECISION_PATH_CHARS
154
+ or _REFLECTION_DECISION_PATH.fullmatch(value) is None
155
+ for value in values
156
+ ):
157
+ raise ValueError(f"{name} must contain bounded rooted decision paths")
158
+ if len(values) > MAX_REFLECTION_SEMANTIC_VOCABULARY_ENTRIES:
159
+ raise ValueError(f"{name} exceeds MAX_REFLECTION_SEMANTIC_VOCABULARY_ENTRIES")
160
+ if values != tuple(sorted(set(values))):
161
+ raise ValueError(f"{name} must be unique and canonically sorted")
162
+
163
+
164
+ @dataclass(frozen=True, slots=True)
165
+ class ReflectionEvidenceCatalogEntry:
166
+ """One request-local short citation bound to a canonical contrast ID."""
167
+
168
+ citation_key: str
169
+ contrast_id: str
170
+
171
+ def __post_init__(self) -> None:
172
+ if (
173
+ type(self.citation_key) is not str
174
+ or _REFLECTION_EVIDENCE_CITATION_KEY.fullmatch(self.citation_key) is None
175
+ ):
176
+ raise ValueError("citation_key must use the eNNNN grammar")
177
+ if (
178
+ type(self.contrast_id) is not str
179
+ or _LOWER_SHA256.fullmatch(self.contrast_id) is None
180
+ ):
181
+ raise ValueError("contrast_id must be a lowercase SHA-256 ID")
182
+
183
+ def to_record(self) -> dict[str, str]:
184
+ ReflectionEvidenceCatalogEntry.__post_init__(self)
185
+ return {
186
+ "citation_key": self.citation_key,
187
+ "contrast_id": self.contrast_id,
188
+ }
189
+
190
+
191
+ @dataclass(frozen=True, slots=True)
192
+ class ReflectionEvidenceCatalog:
193
+ """Authenticated deterministic short keys for one reflection request.
194
+
195
+ The catalog does not alter the evidence universe. It is derived from the
196
+ request's already-canonical contrast IDs and merely replaces error-prone
197
+ model reproduction of 64-character hashes with closed ``eNNNN`` literals.
198
+ Resolution is exact: prefixes, fuzzy matches, and foreign keys are never
199
+ accepted.
200
+ """
201
+
202
+ entries: Tuple[ReflectionEvidenceCatalogEntry, ...]
203
+ catalog_identity_sha256: str = field(init=False)
204
+
205
+ def __post_init__(self) -> None:
206
+ if type(self.entries) is not tuple or not self.entries:
207
+ raise ValueError("entries must be a non-empty exact tuple")
208
+ if len(self.entries) > MAX_REFLECTION_EVIDENCE_CATALOG_ENTRIES:
209
+ raise ValueError("entries exceed MAX_REFLECTION_EVIDENCE_CATALOG_ENTRIES")
210
+ if any(
211
+ type(entry) is not ReflectionEvidenceCatalogEntry for entry in self.entries
212
+ ):
213
+ raise TypeError(
214
+ "entries must contain exact ReflectionEvidenceCatalogEntry values"
215
+ )
216
+ for entry in self.entries:
217
+ ReflectionEvidenceCatalogEntry.__post_init__(entry)
218
+ contrast_ids = tuple(entry.contrast_id for entry in self.entries)
219
+ _validate_contrast_ids(contrast_ids, name="catalog contrast_ids")
220
+ expected_keys = tuple(
221
+ f"e{index:04d}" for index in range(1, len(self.entries) + 1)
222
+ )
223
+ if self.citation_keys != expected_keys:
224
+ raise ValueError(
225
+ "citation keys must be contiguous e0001..eNNNN in contrast-ID order"
226
+ )
227
+ object.__setattr__(
228
+ self,
229
+ "catalog_identity_sha256",
230
+ hashlib.sha256(
231
+ _REFLECTION_EVIDENCE_CATALOG_DOMAIN
232
+ + canonical_typed_json_bytes(freeze_json(self._unsigned_record()))
233
+ ).hexdigest(),
234
+ )
235
+
236
+ @classmethod
237
+ def from_contrast_ids(
238
+ cls,
239
+ contrast_ids: Tuple[str, ...],
240
+ ) -> "ReflectionEvidenceCatalog":
241
+ """Derive the only canonical key assignment for an evidence universe."""
242
+
243
+ _validate_contrast_ids(contrast_ids, name="contrast_ids")
244
+ if not contrast_ids:
245
+ raise ValueError("a reflection evidence catalog cannot be empty")
246
+ if len(contrast_ids) > MAX_REFLECTION_EVIDENCE_CATALOG_ENTRIES:
247
+ raise ValueError(
248
+ "contrast_ids exceed MAX_REFLECTION_EVIDENCE_CATALOG_ENTRIES"
249
+ )
250
+ return cls(
251
+ tuple(
252
+ ReflectionEvidenceCatalogEntry(
253
+ citation_key=f"e{index:04d}",
254
+ contrast_id=contrast_id,
255
+ )
256
+ for index, contrast_id in enumerate(contrast_ids, start=1)
257
+ )
258
+ )
259
+
260
+ @property
261
+ def citation_keys(self) -> Tuple[str, ...]:
262
+ return tuple(entry.citation_key for entry in self.entries)
263
+
264
+ @property
265
+ def contrast_ids(self) -> Tuple[str, ...]:
266
+ return tuple(entry.contrast_id for entry in self.entries)
267
+
268
+ def citation_key_for_contrast_id(self, contrast_id: str) -> str:
269
+ """Return the exact request-local citation key for one full ID.
270
+
271
+ Keeping this lookup on the authenticated catalog prevents composition
272
+ roots from duplicating its field names or rebuilding a parallel map.
273
+ Unknown, malformed, and non-string IDs fail closed.
274
+ """
275
+
276
+ ReflectionEvidenceCatalog.__post_init__(self)
277
+ if type(contrast_id) is not str or _LOWER_SHA256.fullmatch(contrast_id) is None:
278
+ raise ValueError("contrast_id must be a lowercase SHA-256 ID")
279
+ for entry in self.entries:
280
+ if entry.contrast_id == contrast_id:
281
+ return entry.citation_key
282
+ raise ValueError("contrast_id is not present in this evidence catalog")
283
+
284
+ def resolve_citation_keys(
285
+ self,
286
+ citation_keys: Tuple[str, ...],
287
+ ) -> Tuple[str, ...]:
288
+ """Resolve exact keys to canonical full IDs without corrective matching."""
289
+
290
+ ReflectionEvidenceCatalog.__post_init__(self)
291
+ if type(citation_keys) is not tuple or any(
292
+ type(value) is not str for value in citation_keys
293
+ ):
294
+ raise TypeError("citation_keys must be an exact tuple of strings")
295
+ if not citation_keys:
296
+ raise ValueError("citation_keys cannot be empty")
297
+ if len(set(citation_keys)) != len(citation_keys):
298
+ raise ValueError("citation_keys cannot contain duplicates")
299
+ lookup = {entry.citation_key: entry.contrast_id for entry in self.entries}
300
+ if not set(citation_keys).issubset(lookup):
301
+ raise ValueError("citation_keys contain an unknown or foreign key")
302
+ return tuple(sorted(lookup[key] for key in citation_keys))
303
+
304
+ def _unsigned_record(self) -> dict[str, object]:
305
+ return {
306
+ "schema_version": 1,
307
+ "entries": [entry.to_record() for entry in self.entries],
308
+ }
309
+
310
+ def to_record(self) -> dict[str, object]:
311
+ ReflectionEvidenceCatalog.__post_init__(self)
312
+ return {
313
+ **self._unsigned_record(),
314
+ "catalog_identity_sha256": self.catalog_identity_sha256,
315
+ }
316
+
317
+
318
+ class MetricEffectDirection(str, Enum):
319
+ """Closed, testable prediction for one explicitly named numeric metric."""
320
+
321
+ DECREASE = "decrease"
322
+ INCREASE = "increase"
323
+ UNCHANGED = "unchanged"
324
+ UNKNOWN = "unknown"
325
+
326
+
327
+ class ReflectionInsightKind(str, Enum):
328
+ """Closed epistemic category for a model-authored reflection insight.
329
+
330
+ Kind deliberately does not encode where an insight may be consumed. That
331
+ separate scope prevents a mechanistic conjecture, for example, from
332
+ silently becoming authorization for every evolutionary operator.
333
+ """
334
+
335
+ EMPIRICAL_PREDICTIVE_RULE = "empirical_predictive_rule"
336
+ MECHANISTIC_CONJECTURE = "mechanistic_conjecture"
337
+ SEARCH_HEURISTIC = "search_heuristic"
338
+ CONTRACT_INVARIANT = "contract_invariant"
339
+
340
+
341
+ class ReflectionConsumerScope(str, Enum):
342
+ """Closed evolutionary decisions that may consume an insight."""
343
+
344
+ MUTATION_SELECTION = "mutation_selection"
345
+ RECOMBINATION_SELECTION = "recombination_selection"
346
+ PARENT_SELECTION = "parent_selection"
347
+
348
+
349
+ class MetricComparisonAnchorKind(str, Enum):
350
+ """Closed reference point for interpreting one metric direction."""
351
+
352
+ CURRENT_PARENT = "current_parent"
353
+ NAMED_SOURCE_ROLE = "named_source_role"
354
+ COMMON_ANCESTOR = "common_ancestor"
355
+ FROZEN_ARCHIVE_INCUMBENT = "frozen_archive_incumbent"
356
+
357
+
358
+ @dataclass(frozen=True, slots=True)
359
+ class MetricComparisonAnchor:
360
+ """Typed comparison reference, optionally bound to an adapter-owned role."""
361
+
362
+ kind: MetricComparisonAnchorKind
363
+ source_role_id: str | None = None
364
+
365
+ def __post_init__(self) -> None:
366
+ if type(self.kind) is not MetricComparisonAnchorKind:
367
+ raise TypeError("kind must be an exact MetricComparisonAnchorKind")
368
+ if self.kind is MetricComparisonAnchorKind.NAMED_SOURCE_ROLE:
369
+ if (
370
+ type(self.source_role_id) is not str
371
+ or _REFLECTION_SEMANTIC_TOKEN.fullmatch(self.source_role_id) is None
372
+ ):
373
+ raise ValueError(
374
+ "named_source_role anchors require a canonical source_role_id"
375
+ )
376
+ elif self.source_role_id is not None:
377
+ raise ValueError(
378
+ "source_role_id is valid only for named_source_role anchors"
379
+ )
380
+
381
+ def to_record(self) -> dict[str, str | None]:
382
+ MetricComparisonAnchor.__post_init__(self)
383
+ return {
384
+ "kind": self.kind.value,
385
+ "source_role_id": self.source_role_id,
386
+ }
387
+
388
+
389
+ @dataclass(frozen=True, slots=True)
390
+ class MetricEffectPrediction:
391
+ """One direction prediction, independent of any domain's goal semantics."""
392
+
393
+ metric_id: str
394
+ direction: MetricEffectDirection
395
+ comparison_anchor: MetricComparisonAnchor | None = None
396
+
397
+ def __post_init__(self) -> None:
398
+ if (
399
+ type(self.metric_id) is not str
400
+ or _REFLECTION_METRIC_ID.fullmatch(self.metric_id) is None
401
+ ):
402
+ raise ValueError(
403
+ "metric_id must use the closed reflection identifier grammar"
404
+ )
405
+ if type(self.direction) is not MetricEffectDirection:
406
+ raise TypeError("direction must be an exact MetricEffectDirection")
407
+ if self.comparison_anchor is not None:
408
+ if type(self.comparison_anchor) is not MetricComparisonAnchor:
409
+ raise TypeError(
410
+ "comparison_anchor must be an exact MetricComparisonAnchor or None"
411
+ )
412
+ MetricComparisonAnchor.__post_init__(self.comparison_anchor)
413
+
414
+ def to_record(self) -> dict[str, object]:
415
+ MetricEffectPrediction.__post_init__(self)
416
+ record: dict[str, object] = {
417
+ "metric_id": self.metric_id,
418
+ "direction": self.direction.value,
419
+ }
420
+ if self.comparison_anchor is not None:
421
+ record["comparison_anchor"] = self.comparison_anchor.to_record()
422
+ return record
423
+
424
+
425
+ @dataclass(frozen=True, slots=True)
426
+ class SourceAttribution:
427
+ path: str
428
+ source: str
429
+
430
+ def __post_init__(self) -> None:
431
+ if type(self.path) is not str or not self.path.strip():
432
+ raise ValueError("attribution path must be non-empty")
433
+ if self.source not in {"ancestor", "left", "right", "synthesized", "mutation"}:
434
+ raise ValueError("unsupported attribution source")
435
+
436
+
437
+ @dataclass(frozen=True, slots=True)
438
+ class ConflictResolutionDraft:
439
+ relation_id: str
440
+ choice: str
441
+ explanation: str
442
+
443
+ def __post_init__(self) -> None:
444
+ if type(self.relation_id) is not str or not self.relation_id.strip():
445
+ raise ValueError("relation_id must be non-empty")
446
+ if self.choice not in {
447
+ "choose_left",
448
+ "choose_right",
449
+ "synthesize",
450
+ "drop_both",
451
+ }:
452
+ raise ValueError("unsupported conflict resolution choice")
453
+ if type(self.explanation) is not str or not self.explanation.strip():
454
+ raise ValueError("resolution explanation must be non-empty")
455
+
456
+
457
+ @dataclass(frozen=True, slots=True)
458
+ class CandidateDraft:
459
+ configuration: dict[str, Any]
460
+ design_rationale: str
461
+ intended_changes: Tuple[str, ...] = ()
462
+ source_attribution: Tuple[SourceAttribution, ...] = ()
463
+ claimed_insight_ids: Tuple[str, ...] = ()
464
+ claimed_preservation_obligation_ids: Tuple[str, ...] = ()
465
+ conflict_resolutions: Tuple[ConflictResolutionDraft, ...] = ()
466
+
467
+ def __post_init__(self) -> None:
468
+ if type(self.configuration) is not dict:
469
+ raise TypeError("configuration must be an exact dict")
470
+ if type(self.design_rationale) is not str or not self.design_rationale.strip():
471
+ raise ValueError("design_rationale must be non-empty")
472
+ for name in (
473
+ "intended_changes",
474
+ "claimed_insight_ids",
475
+ "claimed_preservation_obligation_ids",
476
+ ):
477
+ values = getattr(self, name)
478
+ if type(values) is not tuple or any(
479
+ type(value) is not str or not value.strip() for value in values
480
+ ):
481
+ raise TypeError(f"{name} must be an exact tuple of non-empty strings")
482
+ if type(self.source_attribution) is not tuple or any(
483
+ type(value) is not SourceAttribution for value in self.source_attribution
484
+ ):
485
+ raise TypeError("source_attribution must contain exact values")
486
+ if type(self.conflict_resolutions) is not tuple or any(
487
+ type(value) is not ConflictResolutionDraft
488
+ for value in self.conflict_resolutions
489
+ ):
490
+ raise TypeError("conflict_resolutions must contain exact values")
491
+
492
+
493
+ def _frozen_value_at_path(
494
+ value: FrozenJsonValue,
495
+ path: JsonPath,
496
+ ) -> FrozenJsonValue:
497
+ """Resolve an already-frozen value without introducing a policy dependency."""
498
+
499
+ current = value
500
+ for segment in path.segments:
501
+ if type(segment) is ObjectKey:
502
+ if type(current) is not FrozenJsonObject:
503
+ raise ValueError("atomic mutation path reaches a non-object")
504
+ matches = tuple(item for key, item in current.items if key == segment.value)
505
+ if len(matches) != 1:
506
+ raise ValueError("atomic mutation path does not exist")
507
+ current = matches[0]
508
+ elif type(segment) is ArrayIndex:
509
+ if type(current) is not FrozenJsonArray:
510
+ raise ValueError("atomic mutation path reaches a non-array")
511
+ if segment.value >= len(current.items):
512
+ raise ValueError("atomic mutation path is out of bounds")
513
+ current = current.items[segment.value]
514
+ else: # pragma: no cover - JsonPath closes the segment union.
515
+ raise AssertionError("unsupported path segment")
516
+ return current
517
+
518
+
519
+ @dataclass(frozen=True, slots=True)
520
+ class AtomicMutationOutputContract:
521
+ """Immutable parent and exact scalar leaf exposed to one patch-native call."""
522
+
523
+ parent_configuration: FrozenJsonObject
524
+ editable_path: JsonPath
525
+ replacement_options: Tuple[FrozenJsonValue, ...] = ()
526
+
527
+ def __post_init__(self) -> None:
528
+ if type(self.parent_configuration) is not FrozenJsonObject:
529
+ raise TypeError("parent_configuration must be an exact FrozenJsonObject")
530
+ if freeze_json(self.parent_configuration) is not self.parent_configuration:
531
+ raise TypeError("parent_configuration must already be frozen typed JSON")
532
+ if type(self.editable_path) is not JsonPath:
533
+ raise TypeError("editable_path must be an exact JsonPath")
534
+ validate_json_path(self.editable_path)
535
+ if not self.editable_path.segments:
536
+ raise ValueError("atomic mutation cannot replace the candidate root")
537
+ current = _frozen_value_at_path(
538
+ self.parent_configuration,
539
+ self.editable_path,
540
+ )
541
+ if not is_json_scalar(current):
542
+ raise ValueError("atomic mutation editable_path must resolve to a scalar")
543
+ if type(self.replacement_options) is not tuple:
544
+ raise TypeError("replacement_options must be an exact tuple")
545
+ canonical_options: list[bytes] = []
546
+ for option in self.replacement_options:
547
+ if freeze_json(option) is not option or not is_json_scalar(option):
548
+ raise TypeError(
549
+ "replacement_options must contain frozen typed-JSON scalars"
550
+ )
551
+ if typed_json_equal(current, option):
552
+ raise ValueError("replacement_options must exclude the parent value")
553
+ canonical_options.append(canonical_typed_json_bytes(option))
554
+ if len(set(canonical_options)) != len(canonical_options):
555
+ raise ValueError("replacement_options cannot contain duplicates")
556
+
557
+
558
+ @dataclass(frozen=True, slots=True)
559
+ class AtomicMutationDraft:
560
+ """One model-authored scalar replacement; the engine owns materialization."""
561
+
562
+ path: JsonPath
563
+ replacement: FrozenJsonValue
564
+ design_rationale: str
565
+ claimed_insight_ids: Tuple[str, ...] = ()
566
+
567
+ def __post_init__(self) -> None:
568
+ if type(self.path) is not JsonPath:
569
+ raise TypeError("path must be an exact JsonPath")
570
+ validate_json_path(self.path)
571
+ if not self.path.segments:
572
+ raise ValueError("an atomic mutation path cannot be the root")
573
+ frozen_replacement = freeze_json(self.replacement)
574
+ if frozen_replacement is not self.replacement:
575
+ raise TypeError("replacement must already be frozen typed JSON")
576
+ if not is_json_scalar(self.replacement):
577
+ raise TypeError("replacement must be an exact typed-JSON scalar")
578
+ if type(self.design_rationale) is not str or not self.design_rationale.strip():
579
+ raise ValueError("design_rationale must be non-empty")
580
+ if type(self.claimed_insight_ids) is not tuple or any(
581
+ type(value) is not str or not value.strip()
582
+ for value in self.claimed_insight_ids
583
+ ):
584
+ raise TypeError(
585
+ "claimed_insight_ids must be an exact tuple of non-empty strings"
586
+ )
587
+
588
+
589
+ @dataclass(frozen=True, slots=True)
590
+ class ExactParentCrossoverOutputContract:
591
+ """Request-scoped finite vocabulary for an executable parent-import plan.
592
+
593
+ The engine owns parent configurations, locus paths, and materialization.
594
+ The provider sees only these opaque locus identifiers and selects a proper,
595
+ nonempty donor subset. Keeping parent payloads out of this port contract
596
+ prevents an integration adapter from becoming a second crossover engine.
597
+ """
598
+
599
+ contract_identity_sha256: str
600
+ locus_ids: Tuple[str, ...]
601
+ claimable_insight_ids: Tuple[str, ...] = ()
602
+ forbidden_import_locus_sets: Tuple[Tuple[str, ...], ...] = ()
603
+
604
+ def __post_init__(self) -> None:
605
+ require_sha256(
606
+ self.contract_identity_sha256,
607
+ "contract_identity_sha256",
608
+ )
609
+ if type(self.locus_ids) is not tuple or any(
610
+ type(value) is not str or _CROSSOVER_LOCUS_ID.fullmatch(value) is None
611
+ for value in self.locus_ids
612
+ ):
613
+ raise TypeError("locus_ids must be an exact tuple of canonical identifiers")
614
+ if len(self.locus_ids) < 2:
615
+ raise ValueError("exact parent crossover requires at least two loci")
616
+ if self.locus_ids != tuple(sorted(set(self.locus_ids))):
617
+ raise ValueError("locus_ids must be unique and canonically sorted")
618
+ if type(self.claimable_insight_ids) is not tuple or any(
619
+ type(value) is not str or not value.strip()
620
+ for value in self.claimable_insight_ids
621
+ ):
622
+ raise TypeError(
623
+ "claimable_insight_ids must be an exact tuple of non-empty strings"
624
+ )
625
+ if self.claimable_insight_ids != tuple(sorted(set(self.claimable_insight_ids))):
626
+ raise ValueError(
627
+ "claimable_insight_ids must be unique and canonically sorted"
628
+ )
629
+ if type(self.forbidden_import_locus_sets) is not tuple or any(
630
+ type(value) is not tuple for value in self.forbidden_import_locus_sets
631
+ ):
632
+ raise TypeError(
633
+ "forbidden_import_locus_sets must be an exact tuple of tuples"
634
+ )
635
+ allowed = set(self.locus_ids)
636
+ for forbidden in self.forbidden_import_locus_sets:
637
+ if not forbidden or len(forbidden) >= len(self.locus_ids):
638
+ raise ValueError(
639
+ "each forbidden import locus set must be a proper nonempty subset"
640
+ )
641
+ if forbidden != tuple(sorted(set(forbidden))):
642
+ raise ValueError(
643
+ "forbidden import locus sets must use canonical unique IDs"
644
+ )
645
+ if not set(forbidden).issubset(allowed):
646
+ raise ValueError(
647
+ "forbidden import locus sets cannot escape the locus catalog"
648
+ )
649
+ if self.forbidden_import_locus_sets != tuple(
650
+ sorted(set(self.forbidden_import_locus_sets))
651
+ ):
652
+ raise ValueError(
653
+ "forbidden import locus sets must be unique and canonically sorted"
654
+ )
655
+ if len(self.forbidden_import_locus_sets) == (1 << len(self.locus_ids)) - 2:
656
+ raise ValueError(
657
+ "forbidden import locus sets exhaust the exact crossover action space"
658
+ )
659
+
660
+
661
+ @dataclass(frozen=True, slots=True)
662
+ class ExactParentCrossoverDraft:
663
+ """One bounded model choice; the engine owns the exact child and evidence."""
664
+
665
+ contract_identity_sha256: str
666
+ import_locus_ids: Tuple[str, ...]
667
+ claimed_insight_ids: Tuple[str, ...] = ()
668
+
669
+ def __post_init__(self) -> None:
670
+ require_sha256(
671
+ self.contract_identity_sha256,
672
+ "contract_identity_sha256",
673
+ )
674
+ if type(self.import_locus_ids) is not tuple or any(
675
+ type(value) is not str or _CROSSOVER_LOCUS_ID.fullmatch(value) is None
676
+ for value in self.import_locus_ids
677
+ ):
678
+ raise TypeError(
679
+ "import_locus_ids must be an exact tuple of canonical identifiers"
680
+ )
681
+ if not self.import_locus_ids:
682
+ raise ValueError("a crossover plan must import at least one donor locus")
683
+ if self.import_locus_ids != tuple(sorted(set(self.import_locus_ids))):
684
+ raise ValueError("import_locus_ids must be unique and canonically sorted")
685
+ if type(self.claimed_insight_ids) is not tuple or any(
686
+ type(value) is not str or not value.strip()
687
+ for value in self.claimed_insight_ids
688
+ ):
689
+ raise TypeError(
690
+ "claimed_insight_ids must be an exact tuple of non-empty strings"
691
+ )
692
+
693
+
694
+ @dataclass(frozen=True, slots=True)
695
+ class FiniteVariationSelectionDraft:
696
+ """A model-selected ID bound to the exact presealed option and palette."""
697
+
698
+ option_id: str
699
+ option_identity_sha256: str
700
+ contract_identity_sha256: str
701
+ design_rationale: str
702
+ claimed_insight_ids: Tuple[str, ...] = ()
703
+
704
+ def __post_init__(self) -> None:
705
+ if (
706
+ type(self.option_id) is not str
707
+ or _FINITE_OPTION_ID.fullmatch(self.option_id) is None
708
+ ):
709
+ raise ValueError(
710
+ "option_id must use the closed lowercase identifier grammar"
711
+ )
712
+ require_sha256(self.option_identity_sha256, "option_identity_sha256")
713
+ require_sha256(self.contract_identity_sha256, "contract_identity_sha256")
714
+ if type(self.design_rationale) is not str or not self.design_rationale.strip():
715
+ raise ValueError("design_rationale must be non-empty")
716
+ if type(self.claimed_insight_ids) is not tuple or any(
717
+ type(value) is not str or not value.strip()
718
+ for value in self.claimed_insight_ids
719
+ ):
720
+ raise TypeError(
721
+ "claimed_insight_ids must be an exact tuple of non-empty strings"
722
+ )
723
+
724
+
725
+ def resolve_finite_variation_selection(
726
+ contract: FiniteVariationContract,
727
+ draft: FiniteVariationSelectionDraft,
728
+ ) -> FiniteVariationOption:
729
+ """Verify selection receipts and return the one sealed full child."""
730
+
731
+ validate_finite_variation_contract(contract)
732
+ if type(draft) is not FiniteVariationSelectionDraft:
733
+ raise TypeError("draft must be an exact FiniteVariationSelectionDraft")
734
+ FiniteVariationSelectionDraft.__post_init__(draft)
735
+ if draft.contract_identity_sha256 != contract.identity_sha256:
736
+ raise ValueError("selection draft is bound to a different finite contract")
737
+ option = contract.resolve(draft.option_id)
738
+ if draft.option_identity_sha256 != option.identity_sha256:
739
+ raise ValueError("selection draft is bound to a different finite option")
740
+ return option
741
+
742
+
743
+ @dataclass(frozen=True, slots=True)
744
+ class InsightDraft:
745
+ claim: str
746
+ trigger: str
747
+ mechanism: str
748
+ affected_paths: Tuple[str, ...]
749
+ evidence_summary: str
750
+ confidence: float
751
+ evidence_contrast_ids: Tuple[str, ...] = ()
752
+ effect_predictions: Tuple[MetricEffectPrediction, ...] = ()
753
+ recommended_option_families: Tuple[str, ...] = ()
754
+ recommended_option_ids: Tuple[str, ...] = ()
755
+ action_template: str | None = None
756
+ falsification_condition: str | None = None
757
+ insight_kind: ReflectionInsightKind | None = None
758
+ consumer_scopes: Tuple[ReflectionConsumerScope, ...] = ()
759
+ factor_capabilities: Tuple[str, ...] = ()
760
+
761
+ def __post_init__(self) -> None:
762
+ for name in ("claim", "trigger", "mechanism", "evidence_summary"):
763
+ value = getattr(self, name)
764
+ if type(value) is not str or not value.strip():
765
+ raise ValueError(f"{name} must be non-empty")
766
+ if type(self.affected_paths) is not tuple or any(
767
+ type(value) is not str or not value.strip() for value in self.affected_paths
768
+ ):
769
+ raise TypeError("affected_paths must be a tuple of non-empty strings")
770
+ if (
771
+ isinstance(self.confidence, bool)
772
+ or not isinstance(self.confidence, (int, float))
773
+ or not math.isfinite(float(self.confidence))
774
+ or not 0 <= float(self.confidence) <= 1
775
+ ):
776
+ raise ValueError("confidence must be finite in [0,1]")
777
+ _validate_contrast_ids(
778
+ self.evidence_contrast_ids,
779
+ name="evidence_contrast_ids",
780
+ )
781
+ semantic_fields_present = (
782
+ self.insight_kind is not None
783
+ or bool(self.consumer_scopes)
784
+ or bool(self.factor_capabilities)
785
+ or any(
786
+ prediction.comparison_anchor is not None
787
+ for prediction in self.effect_predictions
788
+ if type(prediction) is MetricEffectPrediction
789
+ )
790
+ )
791
+ if semantic_fields_present:
792
+ if type(self.insight_kind) is not ReflectionInsightKind:
793
+ raise TypeError(
794
+ "semantic insights require an exact ReflectionInsightKind"
795
+ )
796
+ _validate_canonical_enum_values(
797
+ self.consumer_scopes,
798
+ name="consumer_scopes",
799
+ enum_type=ReflectionConsumerScope,
800
+ )
801
+ if self.factor_capabilities:
802
+ _validate_canonical_tokens(
803
+ self.factor_capabilities,
804
+ name="factor_capabilities",
805
+ pattern=_REFLECTION_SEMANTIC_TOKEN,
806
+ )
807
+ if (
808
+ self.insight_kind is ReflectionInsightKind.SEARCH_HEURISTIC
809
+ and self.effect_predictions
810
+ ):
811
+ raise ValueError(
812
+ "search_heuristic insights cannot carry causal metric predictions"
813
+ )
814
+ elif type(self.consumer_scopes) is not tuple:
815
+ raise TypeError("consumer_scopes must be an exact tuple")
816
+ if type(self.factor_capabilities) is not tuple:
817
+ raise TypeError("factor_capabilities must be an exact tuple")
818
+ advanced_fields_present = (
819
+ bool(self.effect_predictions)
820
+ or bool(self.recommended_option_families)
821
+ or bool(self.recommended_option_ids)
822
+ or self.action_template is not None
823
+ or self.falsification_condition is not None
824
+ )
825
+ if not advanced_fields_present:
826
+ return
827
+ if type(self.effect_predictions) is not tuple or any(
828
+ type(value) is not MetricEffectPrediction
829
+ for value in self.effect_predictions
830
+ ):
831
+ raise TypeError(
832
+ "effect_predictions must contain exact MetricEffectPrediction values"
833
+ )
834
+ if not self.effect_predictions:
835
+ raise ValueError("advanced insights require effect_predictions")
836
+ for prediction in self.effect_predictions:
837
+ MetricEffectPrediction.__post_init__(prediction)
838
+ if semantic_fields_present and any(
839
+ prediction.comparison_anchor is None
840
+ for prediction in self.effect_predictions
841
+ ):
842
+ raise ValueError(
843
+ "semantic insight effect predictions require comparison anchors"
844
+ )
845
+ metric_ids = tuple(
846
+ prediction.metric_id for prediction in self.effect_predictions
847
+ )
848
+ if metric_ids != tuple(sorted(set(metric_ids))):
849
+ raise ValueError(
850
+ "effect_predictions must be unique and ordered by metric_id"
851
+ )
852
+ _validate_canonical_tokens(
853
+ self.recommended_option_families,
854
+ name="recommended_option_families",
855
+ pattern=_FINITE_OPTION_FAMILY,
856
+ )
857
+ if self.recommended_option_ids:
858
+ _validate_canonical_tokens(
859
+ self.recommended_option_ids,
860
+ name="recommended_option_ids",
861
+ pattern=_FINITE_OPTION_ID,
862
+ )
863
+ for name in ("action_template", "falsification_condition"):
864
+ value = getattr(self, name)
865
+ if type(value) is not str or not value.strip() or value != value.strip():
866
+ raise ValueError(
867
+ f"advanced insights require canonical non-empty {name}"
868
+ )
869
+
870
+ @property
871
+ def has_intervention_contract(self) -> bool:
872
+ """Whether the opt-in actionable/falsifiable fields are populated."""
873
+
874
+ return bool(self.effect_predictions)
875
+
876
+ @property
877
+ def has_semantic_contract(self) -> bool:
878
+ """Whether the v3 epistemic/scope vocabulary is populated."""
879
+
880
+ return self.insight_kind is not None
881
+
882
+ def intervention_record(self) -> dict[str, object] | None:
883
+ """Return a detached JSON-ready projection only for advanced insights."""
884
+
885
+ InsightDraft.__post_init__(self)
886
+ if not self.has_intervention_contract:
887
+ return None
888
+ assert self.action_template is not None
889
+ assert self.falsification_condition is not None
890
+ record: dict[str, object] = {
891
+ "effect_predictions": [
892
+ prediction.to_record() for prediction in self.effect_predictions
893
+ ],
894
+ "recommended_option_families": list(self.recommended_option_families),
895
+ "recommended_option_ids": list(self.recommended_option_ids),
896
+ "action_template": self.action_template,
897
+ "falsification_condition": self.falsification_condition,
898
+ }
899
+ semantic = self.semantic_record()
900
+ if semantic is not None:
901
+ record.update(semantic)
902
+ return record
903
+
904
+ def semantic_record(self) -> dict[str, object] | None:
905
+ """Return v3 semantics independently of intervention actionability.
906
+
907
+ Search heuristics and other outcome schemas may deliberately carry a
908
+ semantic scope without an intervention contract. Keeping this
909
+ projection separate prevents prompt adapters from silently dropping
910
+ the card kind, authorized consumers, or required factor capabilities.
911
+ """
912
+
913
+ InsightDraft.__post_init__(self)
914
+ if not self.has_semantic_contract:
915
+ return None
916
+ assert self.insight_kind is not None
917
+ return {
918
+ "insight_kind": self.insight_kind.value,
919
+ "consumer_scopes": [scope.value for scope in self.consumer_scopes],
920
+ "factor_capabilities": list(self.factor_capabilities),
921
+ }
922
+
923
+ def content_record(self) -> dict[str, object]:
924
+ """Return the complete immutable card content used by treatment binding."""
925
+
926
+ InsightDraft.__post_init__(self)
927
+ record: dict[str, object] = {
928
+ "schema_version": 2 if self.has_semantic_contract else 1,
929
+ "claim": self.claim,
930
+ "trigger": self.trigger,
931
+ "mechanism": self.mechanism,
932
+ "affected_paths": list(self.affected_paths),
933
+ "evidence_summary": self.evidence_summary,
934
+ "confidence": float(self.confidence),
935
+ "evidence_contrast_ids": list(self.evidence_contrast_ids),
936
+ "effect_predictions": [
937
+ prediction.to_record() for prediction in self.effect_predictions
938
+ ],
939
+ "recommended_option_families": list(self.recommended_option_families),
940
+ "recommended_option_ids": list(self.recommended_option_ids),
941
+ "action_template": self.action_template,
942
+ "falsification_condition": self.falsification_condition,
943
+ }
944
+ if self.has_semantic_contract:
945
+ assert self.insight_kind is not None
946
+ record.update(
947
+ {
948
+ "insight_kind": self.insight_kind.value,
949
+ "consumer_scopes": [scope.value for scope in self.consumer_scopes],
950
+ "factor_capabilities": list(self.factor_capabilities),
951
+ }
952
+ )
953
+ return record
954
+
955
+ def hypothesis_record(self) -> dict[str, object]:
956
+ """Project model-authored content with its epistemic status explicit.
957
+
958
+ This projection deliberately does not relabel ``evidence_summary`` as an
959
+ observation. It is the model's interpretation of evidence; trusted
960
+ empirical facts belong in an engine-issued evidence snapshot.
961
+ """
962
+
963
+ InsightDraft.__post_init__(self)
964
+ record: dict[str, object] = {
965
+ "schema_version": 2 if self.has_semantic_contract else 1,
966
+ "epistemic_status": "unverified_hypothesis",
967
+ "claim": self.claim,
968
+ "trigger": self.trigger,
969
+ "mechanism_hypothesis": self.mechanism,
970
+ "affected_paths": list(self.affected_paths),
971
+ "evidence_interpretation": self.evidence_summary,
972
+ "confidence": float(self.confidence),
973
+ "evidence_contrast_ids": list(self.evidence_contrast_ids),
974
+ "effect_predictions": [
975
+ prediction.to_record() for prediction in self.effect_predictions
976
+ ],
977
+ "recommended_option_families": list(self.recommended_option_families),
978
+ "recommended_option_ids": list(self.recommended_option_ids),
979
+ "action_template": self.action_template,
980
+ "falsification_condition": self.falsification_condition,
981
+ }
982
+ if self.has_semantic_contract:
983
+ assert self.insight_kind is not None
984
+ record.update(
985
+ {
986
+ "insight_kind": self.insight_kind.value,
987
+ "consumer_scopes": [scope.value for scope in self.consumer_scopes],
988
+ "factor_capabilities": list(self.factor_capabilities),
989
+ }
990
+ )
991
+ return record
992
+
993
+ @property
994
+ def hypothesis_sha256(self) -> str:
995
+ """Bind the explicitly unverified hypothesis projection."""
996
+
997
+ return hashlib.sha256(
998
+ _INSIGHT_DRAFT_HYPOTHESIS_DOMAIN
999
+ + canonical_typed_json_bytes(freeze_json(self.hypothesis_record()))
1000
+ ).hexdigest()
1001
+
1002
+ @property
1003
+ def content_sha256(self) -> str:
1004
+ """Bind prose, evidence, predictions, and exact finite actions."""
1005
+
1006
+ return hashlib.sha256(
1007
+ _INSIGHT_DRAFT_CONTENT_DOMAIN
1008
+ + canonical_typed_json_bytes(freeze_json(self.content_record()))
1009
+ ).hexdigest()
1010
+
1011
+
1012
+ @dataclass(frozen=True, slots=True)
1013
+ class ReflectionInsightContract:
1014
+ """Request-scoped vocabulary for actionable, falsifiable reflection.
1015
+
1016
+ Metric identifiers are benchmark-owned and name quantities whose numeric
1017
+ direction can be adjudicated later. Option families are drawn from the
1018
+ finite variation vocabulary and remain stable when parent-specific option
1019
+ IDs change. Keeping this contract request-scoped avoids imposing any one
1020
+ benchmark's metrics or action taxonomy on the core workflow.
1021
+ """
1022
+
1023
+ required_metric_ids: Tuple[str, ...]
1024
+ allowed_option_families: Tuple[str, ...]
1025
+ allowed_option_ids: Tuple[str, ...] = ()
1026
+ allowed_decision_paths: Tuple[str, ...] = ()
1027
+ allowed_insight_kinds: Tuple[ReflectionInsightKind, ...] = ()
1028
+ allowed_consumer_scopes: Tuple[ReflectionConsumerScope, ...] = ()
1029
+ allowed_comparison_anchor_kinds: Tuple[MetricComparisonAnchorKind, ...] = ()
1030
+ allowed_factor_capabilities: Tuple[str, ...] = ()
1031
+ allowed_source_role_ids: Tuple[str, ...] = ()
1032
+
1033
+ def __post_init__(self) -> None:
1034
+ _validate_canonical_tokens(
1035
+ self.required_metric_ids,
1036
+ name="required_metric_ids",
1037
+ pattern=_REFLECTION_METRIC_ID,
1038
+ )
1039
+ _validate_canonical_tokens(
1040
+ self.allowed_option_families,
1041
+ name="allowed_option_families",
1042
+ pattern=_FINITE_OPTION_FAMILY,
1043
+ )
1044
+ if self.allowed_option_ids:
1045
+ _validate_canonical_tokens(
1046
+ self.allowed_option_ids,
1047
+ name="allowed_option_ids",
1048
+ pattern=_FINITE_OPTION_ID,
1049
+ )
1050
+ for name in (
1051
+ "allowed_decision_paths",
1052
+ "allowed_insight_kinds",
1053
+ "allowed_consumer_scopes",
1054
+ "allowed_comparison_anchor_kinds",
1055
+ "allowed_factor_capabilities",
1056
+ "allowed_source_role_ids",
1057
+ ):
1058
+ if type(getattr(self, name)) is not tuple:
1059
+ raise TypeError(f"{name} must be an exact tuple")
1060
+ semantic_fields_present = any(
1061
+ (
1062
+ self.allowed_decision_paths,
1063
+ self.allowed_insight_kinds,
1064
+ self.allowed_consumer_scopes,
1065
+ self.allowed_comparison_anchor_kinds,
1066
+ self.allowed_factor_capabilities,
1067
+ self.allowed_source_role_ids,
1068
+ )
1069
+ )
1070
+ if not semantic_fields_present:
1071
+ return
1072
+ _validate_decision_paths(
1073
+ self.allowed_decision_paths,
1074
+ name="allowed_decision_paths",
1075
+ )
1076
+ _validate_canonical_enum_values(
1077
+ self.allowed_insight_kinds,
1078
+ name="allowed_insight_kinds",
1079
+ enum_type=ReflectionInsightKind,
1080
+ )
1081
+ _validate_canonical_enum_values(
1082
+ self.allowed_consumer_scopes,
1083
+ name="allowed_consumer_scopes",
1084
+ enum_type=ReflectionConsumerScope,
1085
+ )
1086
+ _validate_canonical_enum_values(
1087
+ self.allowed_comparison_anchor_kinds,
1088
+ name="allowed_comparison_anchor_kinds",
1089
+ enum_type=MetricComparisonAnchorKind,
1090
+ )
1091
+ if ReflectionInsightKind.SEARCH_HEURISTIC in self.allowed_insight_kinds:
1092
+ raise ValueError(
1093
+ "actionable reflection contracts cannot admit search_heuristic "
1094
+ "without a separate outcome schema"
1095
+ )
1096
+ if ReflectionInsightKind.CONTRACT_INVARIANT in self.allowed_insight_kinds:
1097
+ raise ValueError(
1098
+ "model-authored actionable reflection contracts cannot admit "
1099
+ "contract_invariant"
1100
+ )
1101
+ if self.allowed_factor_capabilities:
1102
+ _validate_canonical_tokens(
1103
+ self.allowed_factor_capabilities,
1104
+ name="allowed_factor_capabilities",
1105
+ pattern=_REFLECTION_SEMANTIC_TOKEN,
1106
+ )
1107
+ if (
1108
+ len(self.allowed_factor_capabilities)
1109
+ > MAX_REFLECTION_SEMANTIC_VOCABULARY_ENTRIES
1110
+ ):
1111
+ raise ValueError(
1112
+ "allowed_factor_capabilities exceeds the semantic vocabulary cap"
1113
+ )
1114
+ elif type(self.allowed_factor_capabilities) is not tuple:
1115
+ raise TypeError("allowed_factor_capabilities must be an exact tuple")
1116
+ if self.allowed_source_role_ids:
1117
+ _validate_canonical_tokens(
1118
+ self.allowed_source_role_ids,
1119
+ name="allowed_source_role_ids",
1120
+ pattern=_REFLECTION_SEMANTIC_TOKEN,
1121
+ )
1122
+ if (
1123
+ len(self.allowed_source_role_ids)
1124
+ > MAX_REFLECTION_SEMANTIC_VOCABULARY_ENTRIES
1125
+ ):
1126
+ raise ValueError(
1127
+ "allowed_source_role_ids exceeds the semantic vocabulary cap"
1128
+ )
1129
+ elif type(self.allowed_source_role_ids) is not tuple:
1130
+ raise TypeError("allowed_source_role_ids must be an exact tuple")
1131
+ named_role_allowed = (
1132
+ MetricComparisonAnchorKind.NAMED_SOURCE_ROLE
1133
+ in self.allowed_comparison_anchor_kinds
1134
+ )
1135
+ if named_role_allowed and not self.allowed_source_role_ids:
1136
+ raise ValueError(
1137
+ "named_source_role anchors require adapter-owned source role IDs"
1138
+ )
1139
+ if self.allowed_source_role_ids and not named_role_allowed:
1140
+ raise ValueError(
1141
+ "source role IDs require named_source_role in the anchor vocabulary"
1142
+ )
1143
+
1144
+ @property
1145
+ def is_semantic_v3(self) -> bool:
1146
+ """Whether this request opts into the fail-closed semantic contract."""
1147
+
1148
+ return bool(self.allowed_decision_paths)
1149
+
1150
+ def to_record(self) -> dict[str, object]:
1151
+ ReflectionInsightContract.__post_init__(self)
1152
+ record: dict[str, object] = {
1153
+ "schema_version": 3 if self.is_semantic_v3 else 2,
1154
+ "contract_identity_sha256": self.identity_sha256,
1155
+ "required_metric_ids": list(self.required_metric_ids),
1156
+ "allowed_option_families": list(self.allowed_option_families),
1157
+ "allowed_option_ids": list(self.allowed_option_ids),
1158
+ "direction_vocabulary": [
1159
+ direction.value for direction in MetricEffectDirection
1160
+ ],
1161
+ }
1162
+ if self.is_semantic_v3:
1163
+ record.update(
1164
+ {
1165
+ "allowed_decision_paths": list(self.allowed_decision_paths),
1166
+ "allowed_insight_kinds": [
1167
+ kind.value for kind in self.allowed_insight_kinds
1168
+ ],
1169
+ "allowed_consumer_scopes": [
1170
+ scope.value for scope in self.allowed_consumer_scopes
1171
+ ],
1172
+ "allowed_comparison_anchor_kinds": [
1173
+ kind.value for kind in self.allowed_comparison_anchor_kinds
1174
+ ],
1175
+ "allowed_factor_capabilities": list(
1176
+ self.allowed_factor_capabilities
1177
+ ),
1178
+ "allowed_source_role_ids": list(self.allowed_source_role_ids),
1179
+ }
1180
+ )
1181
+ return record
1182
+
1183
+ @property
1184
+ def identity_sha256(self) -> str:
1185
+ """Bind exact ordered metric/action vocabularies for replay."""
1186
+
1187
+ ReflectionInsightContract.__post_init__(self)
1188
+ record: dict[str, object] = {
1189
+ "schema_version": 3 if self.is_semantic_v3 else 2,
1190
+ "required_metric_ids": list(self.required_metric_ids),
1191
+ "allowed_option_families": list(self.allowed_option_families),
1192
+ "allowed_option_ids": list(self.allowed_option_ids),
1193
+ "direction_vocabulary": [
1194
+ direction.value for direction in MetricEffectDirection
1195
+ ],
1196
+ }
1197
+ if self.is_semantic_v3:
1198
+ record.update(
1199
+ {
1200
+ "allowed_decision_paths": list(self.allowed_decision_paths),
1201
+ "allowed_insight_kinds": [
1202
+ kind.value for kind in self.allowed_insight_kinds
1203
+ ],
1204
+ "allowed_consumer_scopes": [
1205
+ scope.value for scope in self.allowed_consumer_scopes
1206
+ ],
1207
+ "allowed_comparison_anchor_kinds": [
1208
+ kind.value for kind in self.allowed_comparison_anchor_kinds
1209
+ ],
1210
+ "allowed_factor_capabilities": list(
1211
+ self.allowed_factor_capabilities
1212
+ ),
1213
+ "allowed_source_role_ids": list(self.allowed_source_role_ids),
1214
+ }
1215
+ )
1216
+ payload = freeze_json(record)
1217
+ return hashlib.sha256(
1218
+ (
1219
+ _REFLECTION_INSIGHT_CONTRACT_V3_DOMAIN
1220
+ if self.is_semantic_v3
1221
+ else _REFLECTION_INSIGHT_CONTRACT_DOMAIN
1222
+ )
1223
+ + canonical_typed_json_bytes(payload)
1224
+ ).hexdigest()
1225
+
1226
+
1227
+ def validate_reflection_insight_draft(
1228
+ draft: InsightDraft,
1229
+ contract: ReflectionInsightContract,
1230
+ *,
1231
+ allow_all_unknown: bool = False,
1232
+ allow_missing_evidence: bool = False,
1233
+ ) -> None:
1234
+ """Verify exact metric coverage and finite-vocabulary actionability."""
1235
+
1236
+ if type(allow_all_unknown) is not bool:
1237
+ raise TypeError("allow_all_unknown must be an exact boolean")
1238
+ if type(allow_missing_evidence) is not bool:
1239
+ raise TypeError("allow_missing_evidence must be an exact boolean")
1240
+ if type(draft) is not InsightDraft:
1241
+ raise TypeError("draft must be an exact InsightDraft")
1242
+ InsightDraft.__post_init__(draft)
1243
+ if type(contract) is not ReflectionInsightContract:
1244
+ raise TypeError("contract must be an exact ReflectionInsightContract")
1245
+ ReflectionInsightContract.__post_init__(contract)
1246
+ if not draft.has_intervention_contract:
1247
+ raise ValueError("insight is missing the advanced intervention contract")
1248
+ if contract.is_semantic_v3:
1249
+ if not draft.has_semantic_contract:
1250
+ raise ValueError("v3 insight is missing its semantic contract")
1251
+ assert draft.insight_kind is not None
1252
+ if draft.insight_kind is ReflectionInsightKind.CONTRACT_INVARIANT:
1253
+ raise ValueError(
1254
+ "model-authored v3 reflections cannot assert contract_invariant"
1255
+ )
1256
+ if not draft.affected_paths or len(set(draft.affected_paths)) != len(
1257
+ draft.affected_paths
1258
+ ):
1259
+ raise ValueError("v3 affected paths must be nonempty and unique")
1260
+ if draft.insight_kind not in contract.allowed_insight_kinds:
1261
+ raise ValueError("insight kind escapes the request vocabulary")
1262
+ if not set(draft.consumer_scopes).issubset(contract.allowed_consumer_scopes):
1263
+ raise ValueError("consumer scopes escape the request vocabulary")
1264
+ if not set(draft.affected_paths).issubset(contract.allowed_decision_paths):
1265
+ raise ValueError(
1266
+ "affected paths escape the adapter-owned decision-path vocabulary"
1267
+ )
1268
+ if not set(draft.factor_capabilities).issubset(
1269
+ contract.allowed_factor_capabilities
1270
+ ):
1271
+ raise ValueError(
1272
+ "factor capabilities escape the adapter-owned capability vocabulary"
1273
+ )
1274
+ for prediction in draft.effect_predictions:
1275
+ if prediction.direction is MetricEffectDirection.UNKNOWN:
1276
+ raise ValueError(
1277
+ "v3 lifecycle hypotheses require adjudicable metric directions"
1278
+ )
1279
+ anchor = prediction.comparison_anchor
1280
+ if anchor is None:
1281
+ raise ValueError(
1282
+ "v3 effect predictions require an explicit comparison anchor"
1283
+ )
1284
+ if anchor.kind not in contract.allowed_comparison_anchor_kinds:
1285
+ raise ValueError(
1286
+ "comparison anchor kind escapes the request vocabulary"
1287
+ )
1288
+ if (
1289
+ anchor.source_role_id is not None
1290
+ and anchor.source_role_id not in contract.allowed_source_role_ids
1291
+ ):
1292
+ raise ValueError(
1293
+ "comparison source role escapes the request vocabulary"
1294
+ )
1295
+ elif draft.has_semantic_contract:
1296
+ raise ValueError("a v3 semantic insight requires a v3 reflection contract")
1297
+ if not allow_missing_evidence and not draft.evidence_contrast_ids:
1298
+ raise ValueError(
1299
+ "an outcome-grounded intervention must cite at least one evidence contrast"
1300
+ )
1301
+ predicted_metric_ids = tuple(
1302
+ prediction.metric_id for prediction in draft.effect_predictions
1303
+ )
1304
+ if predicted_metric_ids != contract.required_metric_ids:
1305
+ raise ValueError(
1306
+ "effect predictions must cover the exact required metric identifiers"
1307
+ )
1308
+ if not set(draft.recommended_option_families).issubset(
1309
+ contract.allowed_option_families
1310
+ ):
1311
+ raise ValueError(
1312
+ "recommended option families escape the finite action vocabulary"
1313
+ )
1314
+ if contract.allowed_option_ids:
1315
+ if not draft.recommended_option_ids:
1316
+ raise ValueError(
1317
+ "an exact-action insight must recommend at least one option ID"
1318
+ )
1319
+ if not set(draft.recommended_option_ids).issubset(contract.allowed_option_ids):
1320
+ raise ValueError(
1321
+ "recommended option IDs escape the finite action vocabulary"
1322
+ )
1323
+ elif draft.recommended_option_ids:
1324
+ raise ValueError(
1325
+ "recommended option IDs require a request-scoped exact-action vocabulary"
1326
+ )
1327
+ if not allow_all_unknown and all(
1328
+ prediction.direction is MetricEffectDirection.UNKNOWN
1329
+ for prediction in draft.effect_predictions
1330
+ ):
1331
+ raise ValueError(
1332
+ "an outcome-grounded intervention must make a directional prediction"
1333
+ )
1334
+
1335
+
1336
+ @dataclass(frozen=True, slots=True)
1337
+ class AgenticCallTelemetry:
1338
+ requested_model: str
1339
+ resolved_model: str
1340
+ resolved_provider: str
1341
+ provider_response_id: str | None
1342
+ finish_reason: str | None
1343
+ input_tokens: int
1344
+ output_tokens: int
1345
+ reasoning_tokens: int
1346
+ cache_read_tokens: int
1347
+ cache_write_tokens: int
1348
+ cost_usd: Decimal | None
1349
+ latency_ns: int
1350
+ attempt_count: int = 1
1351
+
1352
+ def __post_init__(self) -> None:
1353
+ for name in ("requested_model", "resolved_model", "resolved_provider"):
1354
+ if type(getattr(self, name)) is not str or not getattr(self, name).strip():
1355
+ raise ValueError(f"{name} must be non-empty")
1356
+ for name in (
1357
+ "input_tokens",
1358
+ "output_tokens",
1359
+ "reasoning_tokens",
1360
+ "cache_read_tokens",
1361
+ "cache_write_tokens",
1362
+ "latency_ns",
1363
+ ):
1364
+ if type(getattr(self, name)) is not int or getattr(self, name) < 0:
1365
+ raise ValueError(f"{name} must be a non-negative integer")
1366
+ if type(self.attempt_count) is not int or self.attempt_count <= 0:
1367
+ raise ValueError("attempt_count must be positive")
1368
+
1369
+
1370
+ @dataclass(frozen=True, slots=True)
1371
+ class VariationGenerationRequest:
1372
+ call_id: LLMCallId
1373
+ operation: str
1374
+ prompt: str
1375
+ candidate_model: type
1376
+ max_output_tokens: int = 2_048
1377
+ temperature: float | None = None
1378
+ atomic_mutation_contract: AtomicMutationOutputContract | None = None
1379
+ finite_variation_contract: FiniteVariationContract | None = None
1380
+ exact_parent_crossover_contract: ExactParentCrossoverOutputContract | None = None
1381
+
1382
+ def __post_init__(self) -> None:
1383
+ contracts = tuple(
1384
+ value
1385
+ for value in (
1386
+ self.atomic_mutation_contract,
1387
+ self.finite_variation_contract,
1388
+ self.exact_parent_crossover_contract,
1389
+ )
1390
+ if value is not None
1391
+ )
1392
+ if len(contracts) > 1:
1393
+ raise ValueError("variation output contracts are mutually exclusive")
1394
+ if self.atomic_mutation_contract is not None:
1395
+ if type(self.atomic_mutation_contract) is not AtomicMutationOutputContract:
1396
+ raise TypeError(
1397
+ "atomic_mutation_contract must be an exact "
1398
+ "AtomicMutationOutputContract"
1399
+ )
1400
+ AtomicMutationOutputContract.__post_init__(self.atomic_mutation_contract)
1401
+ if self.finite_variation_contract is not None:
1402
+ validate_finite_variation_contract(self.finite_variation_contract)
1403
+ if self.exact_parent_crossover_contract is not None:
1404
+ if (
1405
+ type(self.exact_parent_crossover_contract)
1406
+ is not ExactParentCrossoverOutputContract
1407
+ ):
1408
+ raise TypeError("exact_parent_crossover_contract must be exact")
1409
+ ExactParentCrossoverOutputContract.__post_init__(
1410
+ self.exact_parent_crossover_contract
1411
+ )
1412
+ if self.operation != "two_parent_crossover":
1413
+ raise ValueError(
1414
+ "exact parent crossover output is restricted to "
1415
+ "two_parent_crossover"
1416
+ )
1417
+
1418
+
1419
+ @dataclass(frozen=True, slots=True)
1420
+ class ReflectionGenerationRequest:
1421
+ call_id: LLMCallId
1422
+ operation: str
1423
+ prompt: str
1424
+ max_insights: int = 4
1425
+ min_insights: int = 0
1426
+ max_output_tokens: int = 2_048
1427
+ temperature: float | None = None
1428
+ available_contrast_ids: Tuple[str, ...] = ()
1429
+ insight_contract: ReflectionInsightContract | None = None
1430
+ evidence_catalog: ReflectionEvidenceCatalog | None = None
1431
+
1432
+ def __post_init__(self) -> None:
1433
+ if type(self.max_insights) is not int or not 1 <= self.max_insights <= 16:
1434
+ raise ValueError("max_insights must lie in [1,16]")
1435
+ if (
1436
+ type(self.min_insights) is not int
1437
+ or not 0 <= self.min_insights <= self.max_insights
1438
+ ):
1439
+ raise ValueError("min_insights must lie in [0,max_insights]")
1440
+ _validate_contrast_ids(
1441
+ self.available_contrast_ids,
1442
+ name="available_contrast_ids",
1443
+ )
1444
+ if self.evidence_catalog is not None:
1445
+ if type(self.evidence_catalog) is not ReflectionEvidenceCatalog:
1446
+ raise TypeError(
1447
+ "evidence_catalog must be an exact ReflectionEvidenceCatalog or None"
1448
+ )
1449
+ ReflectionEvidenceCatalog.__post_init__(self.evidence_catalog)
1450
+ if self.evidence_catalog.contrast_ids != self.available_contrast_ids:
1451
+ raise ValueError(
1452
+ "evidence_catalog must bind the exact available_contrast_ids"
1453
+ )
1454
+ if self.insight_contract is not None:
1455
+ if type(self.insight_contract) is not ReflectionInsightContract:
1456
+ raise TypeError(
1457
+ "insight_contract must be an exact ReflectionInsightContract"
1458
+ )
1459
+ ReflectionInsightContract.__post_init__(self.insight_contract)
1460
+
1461
+
1462
+ @dataclass(frozen=True, slots=True)
1463
+ class VariationGenerationResult:
1464
+ draft: (
1465
+ CandidateDraft
1466
+ | AtomicMutationDraft
1467
+ | FiniteVariationSelectionDraft
1468
+ | ExactParentCrossoverDraft
1469
+ )
1470
+ telemetry: AgenticCallTelemetry
1471
+
1472
+
1473
+ @dataclass(frozen=True, slots=True)
1474
+ class ReflectionGenerationResult:
1475
+ insights: Tuple[InsightDraft, ...]
1476
+ telemetry: AgenticCallTelemetry
1477
+ evidence_catalog_identity_sha256: str | None = None
1478
+
1479
+ def __post_init__(self) -> None:
1480
+ if self.evidence_catalog_identity_sha256 is not None:
1481
+ require_sha256(
1482
+ self.evidence_catalog_identity_sha256,
1483
+ "evidence_catalog_identity_sha256",
1484
+ )
1485
+
1486
+
1487
+ def validate_reflection_evidence_catalog_result(
1488
+ request: ReflectionGenerationRequest,
1489
+ result: ReflectionGenerationResult,
1490
+ ) -> None:
1491
+ """Bind resolved full-ID citations and catalog identity to one request."""
1492
+
1493
+ if type(request) is not ReflectionGenerationRequest:
1494
+ raise TypeError("request must be an exact ReflectionGenerationRequest")
1495
+ ReflectionGenerationRequest.__post_init__(request)
1496
+ if type(result) is not ReflectionGenerationResult:
1497
+ raise TypeError("result must be an exact ReflectionGenerationResult")
1498
+ ReflectionGenerationResult.__post_init__(result)
1499
+ if type(result.insights) is not tuple or any(
1500
+ type(insight) is not InsightDraft for insight in result.insights
1501
+ ):
1502
+ raise TypeError("result insights must contain exact InsightDraft values")
1503
+ available = set(request.available_contrast_ids)
1504
+ for insight in result.insights:
1505
+ InsightDraft.__post_init__(insight)
1506
+ if not set(insight.evidence_contrast_ids).issubset(available):
1507
+ raise ValueError("resolved reflection citations escaped the request")
1508
+ expected_identity = (
1509
+ None
1510
+ if request.evidence_catalog is None
1511
+ else request.evidence_catalog.catalog_identity_sha256
1512
+ )
1513
+ if result.evidence_catalog_identity_sha256 != expected_identity:
1514
+ raise ValueError("reflection result has a foreign evidence catalog identity")
1515
+
1516
+
1517
+ @runtime_checkable
1518
+ class AgenticGenerator(Protocol):
1519
+ async def propose(
1520
+ self, request: VariationGenerationRequest
1521
+ ) -> VariationGenerationResult: ...
1522
+
1523
+ async def reflect(
1524
+ self, request: ReflectionGenerationRequest
1525
+ ) -> ReflectionGenerationResult: ...
1526
+
1527
+
1528
+ __all__ = [
1529
+ "AgenticCallTelemetry",
1530
+ "AgenticGenerator",
1531
+ "AtomicMutationDraft",
1532
+ "AtomicMutationOutputContract",
1533
+ "CANDIDATE_COMPONENT_PATH_CONTRACT",
1534
+ "TWO_PARENT_CROSSOVER_EVIDENCE_CONTRACT",
1535
+ "CandidateDraft",
1536
+ "ConflictResolutionDraft",
1537
+ "ExactParentCrossoverDraft",
1538
+ "ExactParentCrossoverOutputContract",
1539
+ "FiniteVariationSelectionDraft",
1540
+ "InsightDraft",
1541
+ "MetricComparisonAnchor",
1542
+ "MetricComparisonAnchorKind",
1543
+ "MetricEffectDirection",
1544
+ "MetricEffectPrediction",
1545
+ "MAX_REFLECTION_EVIDENCE_CATALOG_ENTRIES",
1546
+ "MAX_REFLECTION_SEMANTIC_VOCABULARY_ENTRIES",
1547
+ "MAX_REFLECTION_DECISION_PATH_CHARS",
1548
+ "ReflectionEvidenceCatalog",
1549
+ "ReflectionEvidenceCatalogEntry",
1550
+ "ReflectionGenerationRequest",
1551
+ "ReflectionGenerationResult",
1552
+ "ReflectionConsumerScope",
1553
+ "ReflectionInsightContract",
1554
+ "ReflectionInsightKind",
1555
+ "resolve_finite_variation_selection",
1556
+ "SourceAttribution",
1557
+ "VariationGenerationRequest",
1558
+ "VariationGenerationResult",
1559
+ "validate_reflection_insight_draft",
1560
+ "validate_reflection_evidence_catalog_result",
1561
+ ]