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,112 @@
1
+ """Apply a benchmark decision-metric projection to sealed candidates."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from dataclasses import dataclass
7
+
8
+ from agent_evolve.application.agentic_evolution import EvolutionCandidate
9
+ from agent_evolve.core.optimization_semantics import MetricRole
10
+ from agent_evolve.domain.patch import require_sha256
11
+ from agent_evolve.ports.decision_metric_projection import DecisionMetricProjection
12
+
13
+
14
+ @dataclass(frozen=True, slots=True)
15
+ class ProjectedDecisionMetrics:
16
+ """Canonical finite values extracted under one immutable projection."""
17
+
18
+ projection_definition_sha256: str
19
+ values: tuple[tuple[str, float], ...]
20
+
21
+ def __post_init__(self) -> None:
22
+ require_sha256(
23
+ self.projection_definition_sha256,
24
+ "projection_definition_sha256",
25
+ )
26
+ if type(self.values) is not tuple or not self.values:
27
+ raise ValueError("values must be a non-empty exact tuple")
28
+ metric_ids: list[str] = []
29
+ for value in self.values:
30
+ if type(value) is not tuple or len(value) != 2:
31
+ raise TypeError("values must contain exact metric/value pairs")
32
+ metric_id, number = value
33
+ if type(metric_id) is not str or not metric_id:
34
+ raise TypeError("projected metric IDs must be non-empty strings")
35
+ if type(number) is not float or not math.isfinite(number):
36
+ raise TypeError("projected metric values must be finite floats")
37
+ metric_ids.append(metric_id)
38
+ if tuple(metric_ids) != tuple(sorted(set(metric_ids))):
39
+ raise ValueError("projected metric values must be unique and canonical")
40
+
41
+ @property
42
+ def metric_map(self) -> dict[str, float]:
43
+ self.__post_init__()
44
+ return dict(self.values)
45
+
46
+ def to_record(self) -> dict[str, object]:
47
+ self.__post_init__()
48
+ return {
49
+ "projection_definition_sha256": self.projection_definition_sha256,
50
+ "values": [
51
+ {"metric_id": metric_id, "value_hex": value.hex()}
52
+ for metric_id, value in self.values
53
+ ],
54
+ }
55
+
56
+
57
+ def project_candidate_decision_metrics(
58
+ candidate: EvolutionCandidate,
59
+ projection: DecisionMetricProjection,
60
+ ) -> ProjectedDecisionMetrics:
61
+ """Extract canonical objectives and sealed violation/constraint values."""
62
+
63
+ if type(candidate) is not EvolutionCandidate:
64
+ raise TypeError("candidate must be exact EvolutionCandidate")
65
+ EvolutionCandidate.__post_init__(candidate)
66
+ if type(projection) is not DecisionMetricProjection:
67
+ raise TypeError("projection must be exact DecisionMetricProjection")
68
+ projection.__post_init__()
69
+ if not candidate.valid:
70
+ raise ValueError("decision metrics require a valid evaluated candidate")
71
+
72
+ objectives = candidate.objective_map
73
+ detailed_values: dict[str, float] | None = None
74
+ values: list[tuple[str, float]] = []
75
+ for binding in projection.metrics:
76
+ if binding.role is MetricRole.OBJECTIVE:
77
+ if binding.value_name not in objectives:
78
+ raise ValueError(
79
+ "decision projection objective is absent from the candidate: "
80
+ f"{binding.value_name}"
81
+ )
82
+ value = objectives[binding.value_name]
83
+ else:
84
+ detailed = candidate.detailed_evaluation
85
+ if detailed is None or not detailed.success:
86
+ raise ValueError(
87
+ "violation/constraint projection requires successful detailed "
88
+ "evaluation evidence"
89
+ )
90
+ if detailed_values is None:
91
+ detailed_values = dict(detailed.violations)
92
+ if binding.value_name not in detailed_values:
93
+ raise ValueError(
94
+ "decision projection violation/constraint is absent from "
95
+ f"detailed evidence: {binding.value_name}"
96
+ )
97
+ value = detailed_values[binding.value_name]
98
+ if type(value) is not float or not math.isfinite(value):
99
+ raise TypeError(
100
+ "candidate decision metrics must be finite canonical floats"
101
+ )
102
+ values.append((binding.metric_id, value))
103
+ return ProjectedDecisionMetrics(
104
+ projection_definition_sha256=projection.definition_sha256,
105
+ values=tuple(values),
106
+ )
107
+
108
+
109
+ __all__ = [
110
+ "ProjectedDecisionMetrics",
111
+ "project_candidate_decision_metrics",
112
+ ]
@@ -0,0 +1,129 @@
1
+ """Structural action semantics derived from any sealed finite contract.
2
+
3
+ Benchmarks may expose a richer, human-authored action glossary through the
4
+ public inverted API. This module supplies the portable fallback: exact
5
+ parent-to-child patch paths and option-family membership are enough to state
6
+ what coordinates an action touches without inventing workload knowledge.
7
+ The option descriptions remain the authoritative prompt-visible semantics.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import hashlib
13
+ import re
14
+
15
+ from agent_evolve.core.action_semantics import (
16
+ ActionAxisSemantics,
17
+ ActionSpaceSemantics,
18
+ )
19
+ from agent_evolve.domain.finite_variation import (
20
+ FiniteVariationContract,
21
+ validate_finite_variation_contract,
22
+ )
23
+ from agent_evolve.domain.ids import CandidateId
24
+ from agent_evolve.domain.patch import ArrayIndex, JsonPath, ObjectKey
25
+ from agent_evolve.policies.variation.typed_patch import derive_patch
26
+
27
+
28
+ DERIVED_ACTION_SEMANTICS_ID = "derived_finite_contract_action_space"
29
+ DERIVED_ACTION_SEMANTICS_VERSION = 1
30
+ _SAFE_PATH_KEY = re.compile(r"^[^\.\[\]\s]+$")
31
+
32
+
33
+ def _render_path(path: JsonPath) -> str:
34
+ path.__post_init__()
35
+ if not path.segments:
36
+ raise ValueError(
37
+ "root-replacement finite actions require explicit benchmark action semantics"
38
+ )
39
+ rendered = "$"
40
+ for segment in path.segments:
41
+ if type(segment) is ObjectKey:
42
+ if _SAFE_PATH_KEY.fullmatch(segment.value) is None:
43
+ raise ValueError(
44
+ "finite-action path cannot use the canonical prompt path grammar; "
45
+ "provide explicit benchmark action semantics"
46
+ )
47
+ rendered += "." + segment.value
48
+ elif type(segment) is ArrayIndex:
49
+ rendered += f"[{segment.value}]"
50
+ else: # pragma: no cover - JsonPath validation closes the union.
51
+ raise AssertionError("unsupported typed path segment")
52
+ return rendered
53
+
54
+
55
+ def derive_action_space_semantics(
56
+ contract: FiniteVariationContract,
57
+ ) -> ActionSpaceSemantics:
58
+ """Derive a hash-bound structural glossary for one parent-bound palette.
59
+
60
+ The derivation reads sealed children only in trusted code. Provider-visible
61
+ output contains canonical coordinate paths and family membership, never a
62
+ child configuration or an inferred causal interpretation.
63
+ """
64
+
65
+ validate_finite_variation_contract(contract)
66
+ families_by_path: dict[str, set[str]] = {}
67
+ base_id = CandidateId("candidate_derived_action_semantics_parent")
68
+ child_id = CandidateId("candidate_derived_action_semantics_child")
69
+ for option in contract.options:
70
+ patch = derive_patch(
71
+ contract.parent_configuration,
72
+ option.child_configuration,
73
+ base_candidate_id=base_id,
74
+ target_candidate_id=child_id,
75
+ )
76
+ if not patch.operations: # pragma: no cover - contract already forbids this.
77
+ raise ValueError("finite action does not change its parent")
78
+ for operation in patch.operations:
79
+ families_by_path.setdefault(_render_path(operation.path), set()).add(
80
+ option.family
81
+ )
82
+ axes = tuple(
83
+ sorted(
84
+ (
85
+ ActionAxisSemantics(
86
+ axis_id=(
87
+ "coordinate_"
88
+ + hashlib.sha256(path.encode("utf-8")).hexdigest()[:20]
89
+ ),
90
+ configuration_paths=(path,),
91
+ option_families=tuple(sorted(families)),
92
+ definition=(
93
+ "A configuration coordinate changed by at least one sealed "
94
+ f"finite action: {path}. Exact option descriptions are "
95
+ "authoritative for its domain meaning."
96
+ ),
97
+ independence=(
98
+ "No coordinate independence is assumed; one sealed finite "
99
+ "action may jointly change multiple declared coordinates."
100
+ ),
101
+ excluded_interpretations=(
102
+ "Do not infer geometry, ordering, causality, or units from "
103
+ "the canonical path alone.",
104
+ ),
105
+ )
106
+ for path, families in families_by_path.items()
107
+ ),
108
+ key=lambda value: value.axis_id,
109
+ )
110
+ )
111
+ return ActionSpaceSemantics(
112
+ semantics_id=DERIVED_ACTION_SEMANTICS_ID,
113
+ semantics_version=DERIVED_ACTION_SEMANTICS_VERSION,
114
+ catalog_identities=(
115
+ (
116
+ contract.catalog_id,
117
+ contract.catalog_version,
118
+ contract.catalog_definition_sha256,
119
+ ),
120
+ ),
121
+ axes=axes,
122
+ )
123
+
124
+
125
+ __all__ = [
126
+ "DERIVED_ACTION_SEMANTICS_ID",
127
+ "DERIVED_ACTION_SEMANTICS_VERSION",
128
+ "derive_action_space_semantics",
129
+ ]
@@ -0,0 +1,449 @@
1
+ """Immutable evaluator evidence sealed by the agentic engine.
2
+
3
+ An adapter owns domain semantics and returns :class:`DetailedEvaluationPayload`.
4
+ It never sees the engine's injected phenotype policy. The engine measures the
5
+ around-port wall time, binds its phenotype identity, and caches that complete
6
+ physical-evaluation record. Candidate occurrence identity deliberately lives
7
+ outside this module because multiple configurations may share one phenotype.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import hashlib
13
+ import json
14
+ import math
15
+ import re
16
+ from dataclasses import dataclass, replace
17
+ from enum import Enum
18
+ from numbers import Real
19
+ from typing import Protocol, runtime_checkable
20
+
21
+ from agent_evolve.core.problem import ObjectiveSpec, normalize_objective_values
22
+ from agent_evolve.domain.artifact import ArtifactRef
23
+ from agent_evolve.domain.outcome import FailureRecord
24
+ from agent_evolve.domain.typed_json import (
25
+ FrozenJsonValue,
26
+ canonical_typed_json_bytes,
27
+ freeze_json,
28
+ thaw_json,
29
+ )
30
+ from agent_evolve.policies.selection.phenotype_recourse import PhenotypeIdentity
31
+
32
+
33
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
34
+ _SHA256 = re.compile(r"^[0-9a-f]{64}$")
35
+ _HASH_DOMAIN = b"agent-evolve:detailed-evaluation:v1\x00"
36
+ _MAX_OBSERVED_VALUE_BYTES = 8_192
37
+
38
+
39
+ def _finite_nonnegative(value: Real, *, name: str) -> float:
40
+ if isinstance(value, bool) or not isinstance(value, Real):
41
+ raise TypeError(f"{name} must be a real number")
42
+ number = float(value)
43
+ if not math.isfinite(number) or number < 0:
44
+ raise ValueError(f"{name} must be finite and non-negative")
45
+ return number
46
+
47
+
48
+ def _named_finite_values(
49
+ values: tuple[tuple[str, float], ...],
50
+ *,
51
+ name: str,
52
+ nonnegative: bool,
53
+ require_sorted: bool,
54
+ ) -> None:
55
+ if type(values) is not tuple:
56
+ raise TypeError(f"{name} must be an exact tuple")
57
+ names: list[str] = []
58
+ for item in values:
59
+ if type(item) is not tuple or len(item) != 2:
60
+ raise TypeError(f"{name} must contain exact name/value pairs")
61
+ key, value = item
62
+ if type(key) is not str or _TOKEN.fullmatch(key) is None:
63
+ raise ValueError(f"{name} names must use the closed token grammar")
64
+ if type(value) is not float:
65
+ raise TypeError(f"{name} values must be canonical floats")
66
+ if not math.isfinite(value) or (nonnegative and value < 0):
67
+ qualifier = "finite non-negative" if nonnegative else "finite"
68
+ raise ValueError(f"{name} values must be {qualifier}")
69
+ names.append(key)
70
+ if len(set(names)) != len(names):
71
+ raise ValueError(f"{name} names must be unique")
72
+ if require_sorted and names != sorted(names):
73
+ raise ValueError(f"{name} names must be canonically ordered")
74
+
75
+
76
+ class EvaluationCheckStatus(str, Enum):
77
+ PASS = "pass"
78
+ FAIL = "fail"
79
+ NOT_APPLICABLE = "not_applicable"
80
+
81
+
82
+ @dataclass(frozen=True, slots=True)
83
+ class EvaluationCheck:
84
+ """One compact, receipt-addressable evaluator fact."""
85
+
86
+ name: str
87
+ status: EvaluationCheckStatus
88
+ observed_value: FrozenJsonValue
89
+ receipt_locator: str
90
+
91
+ def __post_init__(self) -> None:
92
+ if type(self.name) is not str or _TOKEN.fullmatch(self.name) is None:
93
+ raise ValueError("check name must use the closed token grammar")
94
+ if type(self.status) is not EvaluationCheckStatus:
95
+ raise TypeError("check status must be an EvaluationCheckStatus")
96
+ frozen = freeze_json(self.observed_value)
97
+ if frozen is not self.observed_value:
98
+ raise TypeError("observed_value must already be frozen typed JSON")
99
+ if len(canonical_typed_json_bytes(frozen)) > _MAX_OBSERVED_VALUE_BYTES:
100
+ raise ValueError("observed_value exceeds the compact evidence limit")
101
+ if (
102
+ type(self.receipt_locator) is not str
103
+ or not self.receipt_locator.strip()
104
+ or self.receipt_locator != self.receipt_locator.strip()
105
+ or len(self.receipt_locator.encode("utf-8")) > 512
106
+ ):
107
+ raise ValueError("receipt_locator must be compact canonical text")
108
+
109
+ def to_record(self) -> dict[str, object]:
110
+ return {
111
+ "name": self.name,
112
+ "status": self.status.value,
113
+ "observed_value": thaw_json(self.observed_value),
114
+ "receipt_locator": self.receipt_locator,
115
+ }
116
+
117
+
118
+ @dataclass(frozen=True, slots=True)
119
+ class EvaluationTimings:
120
+ """Non-additive timing observations for one physical evaluation."""
121
+
122
+ total_wall_seconds: float
123
+ active_wall_seconds: float | None = None
124
+ resource_queue_wall_seconds: float | None = None
125
+
126
+ def __post_init__(self) -> None:
127
+ _finite_nonnegative(self.total_wall_seconds, name="total_wall_seconds")
128
+ if type(self.total_wall_seconds) is not float:
129
+ raise TypeError("total_wall_seconds must be a canonical float")
130
+ for name in ("active_wall_seconds", "resource_queue_wall_seconds"):
131
+ value = getattr(self, name)
132
+ if value is not None:
133
+ _finite_nonnegative(value, name=name)
134
+ if type(value) is not float:
135
+ raise TypeError(f"{name} must be a canonical float or None")
136
+
137
+ def to_record(self) -> dict[str, float | None]:
138
+ return {
139
+ "total_wall_seconds": self.total_wall_seconds,
140
+ "active_wall_seconds": self.active_wall_seconds,
141
+ "resource_queue_wall_seconds": self.resource_queue_wall_seconds,
142
+ }
143
+
144
+
145
+ @dataclass(frozen=True, slots=True)
146
+ class EvaluatorIdentity:
147
+ """Stable evaluator implementation/task context used in cache identity."""
148
+
149
+ evaluator_id: str
150
+ evaluator_version: int
151
+ evaluator_context_sha256: str
152
+
153
+ def __post_init__(self) -> None:
154
+ if type(self.evaluator_id) is not str or _TOKEN.fullmatch(
155
+ self.evaluator_id
156
+ ) is None:
157
+ raise ValueError("evaluator_id must use the closed token grammar")
158
+ if type(self.evaluator_version) is not int or self.evaluator_version <= 0:
159
+ raise ValueError("evaluator_version must be a positive exact integer")
160
+ if (
161
+ type(self.evaluator_context_sha256) is not str
162
+ or _SHA256.fullmatch(self.evaluator_context_sha256) is None
163
+ ):
164
+ raise ValueError(
165
+ "evaluator_context_sha256 must be a lowercase SHA-256 digest"
166
+ )
167
+
168
+ def to_record(self) -> dict[str, object]:
169
+ return {
170
+ "evaluator_id": self.evaluator_id,
171
+ "evaluator_version": self.evaluator_version,
172
+ "evaluator_context_sha256": self.evaluator_context_sha256,
173
+ }
174
+
175
+
176
+ def _artifact_record(value: ArtifactRef | None) -> dict[str, object] | None:
177
+ if value is None:
178
+ return None
179
+ return {
180
+ "artifact_id": value.artifact_id.value,
181
+ "sha256_hex": value.sha256_hex,
182
+ "size_bytes": value.size_bytes,
183
+ "media_type": value.media_type,
184
+ }
185
+
186
+
187
+ def _failure_record(value: FailureRecord | None) -> dict[str, object] | None:
188
+ if value is None:
189
+ return None
190
+ return {
191
+ "category": value.category.value,
192
+ "code": value.code.value,
193
+ "message": value.message,
194
+ "retryable": value.retryable,
195
+ "exception_type": value.exception_type,
196
+ "diagnostics_artifact_id": (
197
+ None
198
+ if value.diagnostics_artifact_id is None
199
+ else value.diagnostics_artifact_id.value
200
+ ),
201
+ }
202
+
203
+
204
+ @dataclass(frozen=True, slots=True)
205
+ class DetailedEvaluationPayload:
206
+ """Adapter-authored evidence before engine identity and timing binding."""
207
+
208
+ failure: FailureRecord | None
209
+ objectives: tuple[tuple[str, float], ...]
210
+ violations: tuple[tuple[str, float], ...]
211
+ checks: tuple[EvaluationCheck, ...]
212
+ receipt: ArtifactRef | None
213
+ evaluator: EvaluatorIdentity
214
+ active_wall_seconds: float | None = None
215
+ resource_queue_wall_seconds: float | None = None
216
+ observations: tuple[tuple[str, float], ...] = ()
217
+ """Sub-problem measurements the evaluator already computed, carried but
218
+ **never scored**.
219
+
220
+ An evaluation unit that aggregates sub-problems -- a panel of layers, a set
221
+ of instances, a multi-medoid network -- publishes the parts and then throws
222
+ them away, because the only typed channel out of an adapter was the
223
+ aggregate objective vector. On Timeloop that discarded exactly the
224
+ per-medoid split, measured to be worth 43.1 % of that domain's attainable
225
+ range.
226
+
227
+ `observations` is that channel. It is deliberately parallel to
228
+ `violations`: a named finite vector, adapter-authored, sealed with the
229
+ evaluation. It differs from `objectives` in the one way that matters --
230
+ **nothing reads it to compute reward**. The reward path consumes
231
+ `objectives` alone, so widening the observation does not move the target,
232
+ and every existing `objectives` equality invariant holds unchanged.
233
+
234
+ Not required to be sorted, because sub-problem order is meaningful (medoid
235
+ 0, 1, 2 is not an alphabetical fact), and not required nonnegative, because
236
+ a sub-problem measurement may legitimately be signed.
237
+ """
238
+
239
+ def __post_init__(self) -> None:
240
+ if self.failure is not None:
241
+ if type(self.failure) is not FailureRecord:
242
+ raise TypeError("failure must be an exact FailureRecord or None")
243
+ FailureRecord.__post_init__(self.failure)
244
+ _named_finite_values(
245
+ self.objectives,
246
+ name="objectives",
247
+ nonnegative=False,
248
+ require_sorted=False,
249
+ )
250
+ _named_finite_values(
251
+ self.violations,
252
+ name="violations",
253
+ nonnegative=True,
254
+ require_sorted=True,
255
+ )
256
+ _named_finite_values(
257
+ self.observations,
258
+ name="observations",
259
+ nonnegative=False,
260
+ require_sorted=False,
261
+ )
262
+ if self.failure is None and not self.objectives:
263
+ raise ValueError("successful detailed evaluations require objectives")
264
+ if self.failure is not None and (
265
+ self.objectives or self.violations or self.observations
266
+ ):
267
+ raise ValueError("failed detailed evaluations cannot carry projections")
268
+ observation_names = tuple(name for name, _ in self.observations)
269
+ if len(set(observation_names)) != len(observation_names):
270
+ raise ValueError("observation names must be unique")
271
+ objective_names = {name for name, _ in self.objectives}
272
+ collisions = objective_names & set(observation_names)
273
+ if collisions:
274
+ raise ValueError(
275
+ "observations must not shadow objective names: "
276
+ f"{sorted(collisions)}"
277
+ )
278
+ if type(self.checks) is not tuple or any(
279
+ type(check) is not EvaluationCheck for check in self.checks
280
+ ):
281
+ raise TypeError("checks must contain exact EvaluationCheck values")
282
+ for check in self.checks:
283
+ EvaluationCheck.__post_init__(check)
284
+ check_names = tuple(check.name for check in self.checks)
285
+ if check_names != tuple(sorted(set(check_names))):
286
+ raise ValueError("checks must be unique and canonically ordered")
287
+ if self.receipt is not None:
288
+ if type(self.receipt) is not ArtifactRef:
289
+ raise TypeError("receipt must be an exact ArtifactRef or None")
290
+ ArtifactRef.__post_init__(self.receipt)
291
+ if self.checks and self.receipt is None:
292
+ raise ValueError("receipt-addressable checks require a receipt ArtifactRef")
293
+ if type(self.evaluator) is not EvaluatorIdentity:
294
+ raise TypeError("evaluator must be an exact EvaluatorIdentity")
295
+ EvaluatorIdentity.__post_init__(self.evaluator)
296
+ for name in ("active_wall_seconds", "resource_queue_wall_seconds"):
297
+ value = getattr(self, name)
298
+ if value is not None:
299
+ _finite_nonnegative(value, name=name)
300
+ if type(value) is not float:
301
+ raise TypeError(f"{name} must be a canonical float or None")
302
+
303
+
304
+ @runtime_checkable
305
+ class DetailedEvaluationAdapter(Protocol):
306
+ """Domain port returning evidence without engine-owned phenotype identity."""
307
+
308
+ evaluator_identity: EvaluatorIdentity
309
+
310
+ def evaluate_evidence(
311
+ self,
312
+ configuration: dict[str, object],
313
+ ) -> DetailedEvaluationPayload: ...
314
+
315
+
316
+ def normalize_detailed_payload(
317
+ payload: DetailedEvaluationPayload,
318
+ objectives: tuple[ObjectiveSpec, ...],
319
+ ) -> DetailedEvaluationPayload:
320
+ """Validate the complete objective vector and freeze declaration order."""
321
+
322
+ if type(payload) is not DetailedEvaluationPayload:
323
+ raise TypeError("adapter must return an exact DetailedEvaluationPayload")
324
+ DetailedEvaluationPayload.__post_init__(payload)
325
+ if payload.failure is not None:
326
+ return payload
327
+ normalized = normalize_objective_values(dict(payload.objectives), objectives)
328
+ ordered = tuple((spec.name, normalized[spec.name]) for spec in objectives)
329
+ return replace(payload, objectives=ordered)
330
+
331
+
332
+ @dataclass(frozen=True, slots=True)
333
+ class DetailedEvaluation:
334
+ """One engine-sealed, phenotype-cached physical evaluation record."""
335
+
336
+ phenotype: PhenotypeIdentity
337
+ payload: DetailedEvaluationPayload
338
+ timings: EvaluationTimings
339
+
340
+ def __post_init__(self) -> None:
341
+ if type(self.phenotype) is not PhenotypeIdentity:
342
+ raise TypeError("phenotype must be an exact PhenotypeIdentity")
343
+ PhenotypeIdentity.__post_init__(self.phenotype)
344
+ if type(self.payload) is not DetailedEvaluationPayload:
345
+ raise TypeError("payload must be an exact DetailedEvaluationPayload")
346
+ DetailedEvaluationPayload.__post_init__(self.payload)
347
+ if type(self.timings) is not EvaluationTimings:
348
+ raise TypeError("timings must be an exact EvaluationTimings")
349
+ EvaluationTimings.__post_init__(self.timings)
350
+ if self.timings.active_wall_seconds != self.payload.active_wall_seconds:
351
+ raise ValueError("active timing must be copied unchanged from the adapter")
352
+ if (
353
+ self.timings.resource_queue_wall_seconds
354
+ != self.payload.resource_queue_wall_seconds
355
+ ):
356
+ raise ValueError("queue timing must be copied unchanged from the adapter")
357
+
358
+ @property
359
+ def failure(self) -> FailureRecord | None:
360
+ return self.payload.failure
361
+
362
+ @property
363
+ def objectives(self) -> tuple[tuple[str, float], ...]:
364
+ return self.payload.objectives
365
+
366
+ @property
367
+ def violations(self) -> tuple[tuple[str, float], ...]:
368
+ return self.payload.violations
369
+
370
+ @property
371
+ def checks(self) -> tuple[EvaluationCheck, ...]:
372
+ return self.payload.checks
373
+
374
+ @property
375
+ def receipt(self) -> ArtifactRef | None:
376
+ return self.payload.receipt
377
+
378
+ @property
379
+ def success(self) -> bool:
380
+ return self.failure is None
381
+
382
+ @property
383
+ def observations(self) -> tuple[tuple[str, float], ...]:
384
+ return self.payload.observations
385
+
386
+ def _identity_record(self) -> dict[str, object]:
387
+ record: dict[str, object] = {
388
+ "phenotype": {
389
+ **self.phenotype.to_trace_record(),
390
+ "identity_sha256": self.phenotype.identity_sha256,
391
+ },
392
+ "failure": _failure_record(self.failure),
393
+ "objectives": [[name, value.hex()] for name, value in self.objectives],
394
+ "violations": [[name, value.hex()] for name, value in self.violations],
395
+ "checks": [check.to_record() for check in self.checks],
396
+ "receipt": _artifact_record(self.payload.receipt),
397
+ "evaluator": self.payload.evaluator.to_record(),
398
+ "timings": {
399
+ name: None if value is None else value.hex()
400
+ for name, value in self.timings.to_record().items()
401
+ },
402
+ }
403
+ # `observations` enters the seal only when an adapter actually supplies
404
+ # one. `evidence_sha256` is a published identity: it is carried in
405
+ # sealed campaign journals and in the prompt-shape commitment as
406
+ # `parent_evidence_sha256s` and `common_ancestor_evidence_sha256`.
407
+ # Adding an always-present key would re-hash every evaluation ever
408
+ # recorded and invalidate that material. Omitting the key when the
409
+ # tuple is empty makes the serialization byte-identical for every
410
+ # existing payload, so old records verify unchanged while new
411
+ # observations are still sealed rather than merely reported.
412
+ if self.observations:
413
+ record["observations"] = [
414
+ [name, value.hex()] for name, value in self.observations
415
+ ]
416
+ return record
417
+
418
+ @property
419
+ def evidence_sha256(self) -> str:
420
+ canonical = json.dumps(
421
+ self._identity_record(),
422
+ ensure_ascii=True,
423
+ allow_nan=False,
424
+ separators=(",", ":"),
425
+ sort_keys=True,
426
+ ).encode("ascii")
427
+ return hashlib.sha256(_HASH_DOMAIN + canonical).hexdigest()
428
+
429
+ def to_record(self) -> dict[str, object]:
430
+ return {
431
+ **self._identity_record(),
432
+ "objectives": {name: value for name, value in self.objectives},
433
+ "violations": {name: value for name, value in self.violations},
434
+ "observations": {name: value for name, value in self.observations},
435
+ "timings": self.timings.to_record(),
436
+ "evidence_sha256": self.evidence_sha256,
437
+ }
438
+
439
+
440
+ __all__ = [
441
+ "DetailedEvaluation",
442
+ "DetailedEvaluationAdapter",
443
+ "DetailedEvaluationPayload",
444
+ "EvaluationCheck",
445
+ "EvaluationCheckStatus",
446
+ "EvaluationTimings",
447
+ "EvaluatorIdentity",
448
+ "normalize_detailed_payload",
449
+ ]