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,91 @@
1
+ """Quality-first allocation that evaluates an entire calibrated slate.
2
+
3
+ The model-facing proposal contract and the evaluator-facing portfolio width
4
+ are deliberately separate concerns. This policy closes that gap by selecting
5
+ every authenticated proposal in model order. It is useful while a campaign is
6
+ still collecting enough outcome evidence to justify a narrower learned
7
+ allocator, and it avoids silently converting proposal quality into an
8
+ allocation failure.
9
+
10
+ The policy is workload neutral: it sees only :class:`SlateAllocationRequest`
11
+ and never inspects option names, workload identifiers, configurations, or
12
+ outcomes.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import hashlib
18
+ from dataclasses import dataclass
19
+
20
+ from agent_evolve.policies.selection.calibrated_slate import (
21
+ SlateAllocationDecision,
22
+ SlateAllocationMode,
23
+ SlateAllocationRequest,
24
+ TraceCalibratedSlatePolicy,
25
+ )
26
+
27
+
28
+ POLICY_ID = "full_support_calibrated_slate"
29
+ POLICY_VERSION = 1
30
+ POLICY_DEFINITION_SHA256 = hashlib.sha256(
31
+ b"agent-evolve:full-support-calibrated-slate:v1;"
32
+ b"select-entire-authenticated-slate=true;model-order-preserved=true;"
33
+ b"outcome-blind=true;workload-identifiers-unused=true;"
34
+ b"quality-first-evidence-acquisition=true"
35
+ ).hexdigest()
36
+ CONFIGURATION_SHA256 = hashlib.sha256(
37
+ b"agent-evolve:full-support-calibrated-slate-configuration:v1;"
38
+ b"selection-scope=entire-authenticated-slate;"
39
+ b"outcome-access=false;workload-identifier-access=false"
40
+ ).hexdigest()
41
+
42
+
43
+ @dataclass(frozen=True, slots=True)
44
+ class FullSupportSlatePolicy:
45
+ """Select every member of a finite calibrated slate in model order."""
46
+
47
+ policy_id = POLICY_ID
48
+ policy_version = POLICY_VERSION
49
+ definition_sha256 = POLICY_DEFINITION_SHA256
50
+ configuration_sha256 = CONFIGURATION_SHA256
51
+
52
+ def __post_init__(self) -> None:
53
+ if type(self) is not FullSupportSlatePolicy:
54
+ raise TypeError("full-support policy must be exact")
55
+
56
+ def revalidate(self) -> None:
57
+ self.__post_init__()
58
+
59
+ def select(self, request: SlateAllocationRequest) -> SlateAllocationDecision:
60
+ self.__post_init__()
61
+ if type(request) is not SlateAllocationRequest:
62
+ raise TypeError("request must be exact SlateAllocationRequest")
63
+ request.revalidate()
64
+ if request.portfolio_size != len(request.slate.members):
65
+ raise ValueError(
66
+ "full-support allocation requires portfolio_size equal to slate size"
67
+ )
68
+ return TraceCalibratedSlatePolicy(
69
+ SlateAllocationMode.DIRECT_MODEL_TOP_K
70
+ ).select(request)
71
+
72
+ def to_record(self) -> dict[str, object]:
73
+ self.__post_init__()
74
+ return {
75
+ "policy_id": self.policy_id,
76
+ "policy_version": self.policy_version,
77
+ "definition_sha256": self.definition_sha256,
78
+ "configuration_sha256": self.configuration_sha256,
79
+ "selection_scope": "entire_authenticated_slate",
80
+ "outcome_access": False,
81
+ "workload_identifier_access": False,
82
+ }
83
+
84
+
85
+ __all__ = [
86
+ "CONFIGURATION_SHA256",
87
+ "POLICY_DEFINITION_SHA256",
88
+ "POLICY_ID",
89
+ "POLICY_VERSION",
90
+ "FullSupportSlatePolicy",
91
+ ]
@@ -0,0 +1,240 @@
1
+ """Workload-neutral adjudication of meaningful metric directions.
2
+
3
+ Benchmarks publish one explicit absolute resolution per metric. The policy
4
+ turns an exact parent/child contrast into the categorical vocabulary used by
5
+ forecast calibration. This is an identified scientific policy, not a
6
+ universal floating-point epsilon.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import json
13
+ import math
14
+ import re
15
+ from dataclasses import dataclass, field
16
+
17
+ from agent_evolve.core.optimization_semantics import OptimizationSemantics
18
+ from agent_evolve.domain.patch import require_sha256
19
+ from agent_evolve.policies.selection.forecast_calibration import (
20
+ MeaningfulDirectionAdjudicationReceipt,
21
+ MeaningfulDirectionRequest,
22
+ )
23
+ from agent_evolve.ports.agentic_generator import MetricEffectDirection
24
+ from agent_evolve.ports.decision_metric_projection import DecisionMetricProjection
25
+
26
+
27
+ _METRIC = re.compile(r"^[a-z][a-z0-9_.:-]{0,191}$")
28
+ _DEFINITION_DOMAIN = b"agent-evolve:absolute-metric-direction:def:v1\x00"
29
+ POLICY_ID = "absolute_tolerance_metric_direction"
30
+ POLICY_VERSION = 1
31
+
32
+
33
+ def _canonical_json(value: object) -> bytes:
34
+ return json.dumps(
35
+ value,
36
+ allow_nan=False,
37
+ ensure_ascii=True,
38
+ separators=(",", ":"),
39
+ sort_keys=True,
40
+ ).encode("ascii", errors="strict")
41
+
42
+
43
+ @dataclass(frozen=True, slots=True)
44
+ class MetricDirectionResolution:
45
+ """One metric's prospectively declared indistinguishable change band."""
46
+
47
+ metric_id: str
48
+ absolute_tolerance: float
49
+
50
+ def __post_init__(self) -> None:
51
+ if type(self.metric_id) is not str or _METRIC.fullmatch(self.metric_id) is None:
52
+ raise ValueError("metric_id must use the closed metric grammar")
53
+ if (
54
+ type(self.absolute_tolerance) is not float
55
+ or not math.isfinite(self.absolute_tolerance)
56
+ or self.absolute_tolerance < 0.0
57
+ ):
58
+ raise ValueError("absolute_tolerance must be a finite non-negative float")
59
+
60
+ def to_record(self) -> dict[str, str]:
61
+ self.__post_init__()
62
+ return {
63
+ "metric_id": self.metric_id,
64
+ "absolute_tolerance_hex": self.absolute_tolerance.hex(),
65
+ }
66
+
67
+
68
+ @dataclass(frozen=True, slots=True)
69
+ class AbsoluteToleranceDirectionAdjudicator:
70
+ """Classify exact parent/child deltas under declared metric resolutions."""
71
+
72
+ benchmark_sha256: str
73
+ session_sha256: str
74
+ resolutions: tuple[MetricDirectionResolution, ...]
75
+ policy_id: str = field(init=False, default=POLICY_ID)
76
+ policy_version: int = field(init=False, default=POLICY_VERSION)
77
+ definition_sha256: str = field(init=False, default="")
78
+
79
+ def __post_init__(self) -> None:
80
+ require_sha256(self.benchmark_sha256, "benchmark_sha256")
81
+ require_sha256(self.session_sha256, "session_sha256")
82
+ if (
83
+ type(self.resolutions) is not tuple
84
+ or not self.resolutions
85
+ or any(
86
+ type(value) is not MetricDirectionResolution
87
+ for value in self.resolutions
88
+ )
89
+ ):
90
+ raise ValueError("resolutions must contain exact metric resolutions")
91
+ for value in self.resolutions:
92
+ value.__post_init__()
93
+ if self.resolutions != tuple(
94
+ sorted(self.resolutions, key=lambda value: value.metric_id)
95
+ ):
96
+ raise ValueError("resolutions must use canonical metric order")
97
+ if len({value.metric_id for value in self.resolutions}) != len(
98
+ self.resolutions
99
+ ):
100
+ raise ValueError("resolutions cannot repeat a metric")
101
+ definition = {
102
+ "schema_version": 1,
103
+ "policy_id": self.policy_id,
104
+ "policy_version": self.policy_version,
105
+ "comparison": "absolute_child_minus_parent",
106
+ "unchanged_rule": "absolute_delta_lte_declared_tolerance",
107
+ "resolutions": [value.to_record() for value in self.resolutions],
108
+ }
109
+ computed = hashlib.sha256(
110
+ _DEFINITION_DOMAIN + _canonical_json(definition)
111
+ ).hexdigest()
112
+ if self.definition_sha256 not in ("", computed):
113
+ raise ValueError("definition_sha256 differs from the resolution policy")
114
+ object.__setattr__(self, "definition_sha256", computed)
115
+
116
+ @classmethod
117
+ def from_optimization_semantics(
118
+ cls,
119
+ *,
120
+ benchmark_sha256: str,
121
+ session_sha256: str,
122
+ semantics: OptimizationSemantics,
123
+ ) -> "AbsoluteToleranceDirectionAdjudicator":
124
+ """Bind every projected decision metric with an explicit tolerance.
125
+
126
+ Objective-only semantics retain the historical unprefixed objective
127
+ names. Mixed objective/violation/constraint semantics use their exact
128
+ role-prefixed IDs through :class:`DecisionMetricProjection`.
129
+ """
130
+
131
+ if type(semantics) is not OptimizationSemantics:
132
+ raise TypeError("semantics must be exact OptimizationSemantics")
133
+ semantics.__post_init__()
134
+ return cls.from_decision_metric_projection(
135
+ benchmark_sha256=benchmark_sha256,
136
+ session_sha256=session_sha256,
137
+ projection=DecisionMetricProjection.from_optimization_semantics(semantics),
138
+ )
139
+
140
+ @classmethod
141
+ def from_decision_metric_projection(
142
+ cls,
143
+ *,
144
+ benchmark_sha256: str,
145
+ session_sha256: str,
146
+ projection: DecisionMetricProjection,
147
+ ) -> "AbsoluteToleranceDirectionAdjudicator":
148
+ """Construct the adjudicator from the same projection used at feedback."""
149
+
150
+ if type(projection) is not DecisionMetricProjection:
151
+ raise TypeError("projection must be exact DecisionMetricProjection")
152
+ projection.__post_init__()
153
+ missing = tuple(
154
+ metric.metric_id
155
+ for metric in projection.metrics
156
+ if metric.absolute_tolerance is None
157
+ )
158
+ if missing:
159
+ raise ValueError(
160
+ "decision metrics require explicit direction tolerances: "
161
+ + ", ".join(sorted(missing))
162
+ )
163
+ return cls(
164
+ benchmark_sha256=benchmark_sha256,
165
+ session_sha256=session_sha256,
166
+ resolutions=tuple(
167
+ sorted(
168
+ (
169
+ MetricDirectionResolution(
170
+ metric_id=metric.metric_id,
171
+ absolute_tolerance=float(metric.absolute_tolerance),
172
+ )
173
+ for metric in projection.metrics
174
+ ),
175
+ key=lambda value: value.metric_id,
176
+ )
177
+ ),
178
+ )
179
+
180
+ def to_record(self) -> dict[str, object]:
181
+ self.__post_init__()
182
+ return {
183
+ "policy_id": self.policy_id,
184
+ "policy_version": self.policy_version,
185
+ "definition_sha256": self.definition_sha256,
186
+ "benchmark_sha256": self.benchmark_sha256,
187
+ "session_sha256": self.session_sha256,
188
+ "resolutions": [value.to_record() for value in self.resolutions],
189
+ }
190
+
191
+ def adjudicate(
192
+ self,
193
+ request: MeaningfulDirectionRequest,
194
+ ) -> MeaningfulDirectionAdjudicationReceipt:
195
+ self.__post_init__()
196
+ if type(request) is not MeaningfulDirectionRequest:
197
+ raise TypeError("request must be exact MeaningfulDirectionRequest")
198
+ request.revalidate()
199
+ if (
200
+ request.benchmark_sha256 != self.benchmark_sha256
201
+ or request.session_sha256 != self.session_sha256
202
+ ):
203
+ raise ValueError("direction request belongs to a foreign benchmark session")
204
+ tolerance_by_metric = {
205
+ value.metric_id: value.absolute_tolerance for value in self.resolutions
206
+ }
207
+ if request.metric_id not in tolerance_by_metric:
208
+ raise ValueError("direction request names an undeclared metric")
209
+ delta = request.child_metric_value - request.parent_metric_value
210
+ tolerance = tolerance_by_metric[request.metric_id]
211
+ if abs(delta) <= tolerance:
212
+ direction = MetricEffectDirection.UNCHANGED
213
+ elif delta < 0.0:
214
+ direction = MetricEffectDirection.DECREASE
215
+ else:
216
+ direction = MetricEffectDirection.INCREASE
217
+ return MeaningfulDirectionAdjudicationReceipt(
218
+ request_sha256=request.request_sha256,
219
+ benchmark_sha256=request.benchmark_sha256,
220
+ session_sha256=request.session_sha256,
221
+ wave_index=request.wave_index,
222
+ parent_candidate_identity_sha256=(request.parent_candidate_identity_sha256),
223
+ option_id=request.option_id,
224
+ option_identity_sha256=request.option_identity_sha256,
225
+ metric_id=request.metric_id,
226
+ parent_outcome_sha256=request.parent_outcome_sha256,
227
+ child_outcome_sha256=request.child_outcome_sha256,
228
+ actual_direction=direction,
229
+ adjudicator_policy_id=self.policy_id,
230
+ adjudicator_policy_version=self.policy_version,
231
+ adjudicator_definition_sha256=self.definition_sha256,
232
+ )
233
+
234
+
235
+ __all__ = [
236
+ "AbsoluteToleranceDirectionAdjudicator",
237
+ "MetricDirectionResolution",
238
+ "POLICY_ID",
239
+ "POLICY_VERSION",
240
+ ]
@@ -0,0 +1,259 @@
1
+ """Workload-neutral exact feasibility for bounded memory-dose attribution.
2
+
3
+ The portfolio reconciler must know whether a structural evaluation subset can
4
+ also carry the prospectively declared card dose. This module answers only
5
+ that finite constraint question. It never sees objective values, workload
6
+ identifiers, model/provider metadata, or natural-language card content.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import hashlib
12
+ import json
13
+ from dataclasses import dataclass, field
14
+ from itertools import combinations
15
+
16
+ from agent_evolve.domain.patch import require_sha256
17
+ from agent_evolve.ports.portfolio_memory_dose import (
18
+ BoundedPortfolioMemoryDoseContract,
19
+ PortfolioMemoryDoseStage,
20
+ )
21
+
22
+
23
+ POLICY_ID = "exact_bounded_memory_dose_attribution_feasibility"
24
+ POLICY_VERSION = 1
25
+ POLICY_DEFINITION_SHA256 = hashlib.sha256(
26
+ b"agent-evolve:exact-bounded-memory-dose-attribution-feasibility:v1;"
27
+ b"input=finite-option-identities,bounded-card-support-contract,stage;"
28
+ b"constraints=compatibility,member-bounds,unattributed-floor,max-cards,card-cover;"
29
+ b"objective=first-canonical-minimum-dose-witness;"
30
+ b"objective-values=false;workload-model-provider-identifiers=false"
31
+ ).hexdigest()
32
+ _DOMAIN = b"agent-evolve:memory-dose-attribution-feasibility-witness:v1\x00"
33
+
34
+
35
+ def _canonical_json(value: object) -> bytes:
36
+ return json.dumps(
37
+ value,
38
+ allow_nan=False,
39
+ ensure_ascii=True,
40
+ separators=(",", ":"),
41
+ sort_keys=True,
42
+ ).encode("ascii", errors="strict")
43
+
44
+
45
+ @dataclass(frozen=True, slots=True)
46
+ class MemoryDoseAttributionFeasibilityWitness:
47
+ """One exact card assignment for a fixed finite member subset."""
48
+
49
+ contract_sha256: str
50
+ stage: PortfolioMemoryDoseStage
51
+ member_option_identities: tuple[tuple[str, str], ...]
52
+ attributions: tuple[tuple[str, tuple[str, ...]], ...]
53
+ witness_sha256: str = field(init=False)
54
+
55
+ def __post_init__(self) -> None:
56
+ require_sha256(self.contract_sha256, "contract_sha256")
57
+ if type(self.stage) is not PortfolioMemoryDoseStage:
58
+ raise TypeError("stage must be exact PortfolioMemoryDoseStage")
59
+ if type(self.member_option_identities) is not tuple or any(
60
+ type(value) is not tuple
61
+ or len(value) != 2
62
+ or type(value[0]) is not str
63
+ or not value[0]
64
+ or type(value[1]) is not str
65
+ for value in self.member_option_identities
66
+ ):
67
+ raise TypeError("member_option_identities must contain exact pairs")
68
+ for _, identity_sha256 in self.member_option_identities:
69
+ require_sha256(identity_sha256, "option_identity_sha256")
70
+ if self.member_option_identities != tuple(
71
+ sorted(set(self.member_option_identities))
72
+ ):
73
+ raise ValueError(
74
+ "member_option_identities must be unique and canonical"
75
+ )
76
+ option_ids = tuple(value[0] for value in self.member_option_identities)
77
+ identity_sha256s = tuple(
78
+ value[1] for value in self.member_option_identities
79
+ )
80
+ if len(set(option_ids)) != len(option_ids):
81
+ raise ValueError("member option IDs must be unique")
82
+ if len(set(identity_sha256s)) != len(identity_sha256s):
83
+ raise ValueError("member option identities must be unique")
84
+ if type(self.attributions) is not tuple or any(
85
+ type(value) is not tuple
86
+ or len(value) != 2
87
+ or type(value[0]) is not str
88
+ or not value[0]
89
+ or type(value[1]) is not tuple
90
+ or any(type(card) is not str or not card for card in value[1])
91
+ or value[1] != tuple(sorted(set(value[1])))
92
+ for value in self.attributions
93
+ ):
94
+ raise TypeError("attributions must contain canonical exact values")
95
+ if tuple(value[0] for value in self.attributions) != tuple(
96
+ value[0] for value in self.member_option_identities
97
+ ):
98
+ raise ValueError("attributions differ from the witnessed members")
99
+ object.__setattr__(
100
+ self,
101
+ "witness_sha256",
102
+ hashlib.sha256(_DOMAIN + _canonical_json(self._unsigned_record())).hexdigest(),
103
+ )
104
+
105
+ @property
106
+ def supported_member_count(self) -> int:
107
+ return sum(bool(cards) for _, cards in self.attributions)
108
+
109
+ @property
110
+ def unattributed_member_count(self) -> int:
111
+ return len(self.attributions) - self.supported_member_count
112
+
113
+ @property
114
+ def covered_card_keys(self) -> tuple[str, ...]:
115
+ return tuple(
116
+ sorted({card for _, cards in self.attributions for card in cards})
117
+ )
118
+
119
+ def _unsigned_record(self) -> dict[str, object]:
120
+ return {
121
+ "schema_version": 1,
122
+ "policy": {
123
+ "policy_id": POLICY_ID,
124
+ "policy_version": POLICY_VERSION,
125
+ "definition_sha256": POLICY_DEFINITION_SHA256,
126
+ },
127
+ "contract_sha256": self.contract_sha256,
128
+ "stage": self.stage.value,
129
+ "members": [
130
+ {
131
+ "option_id": option_id,
132
+ "option_identity_sha256": identity_sha256,
133
+ "supporting_card_keys": list(cards),
134
+ }
135
+ for (option_id, identity_sha256), (_, cards) in zip(
136
+ self.member_option_identities,
137
+ self.attributions,
138
+ strict=True,
139
+ )
140
+ ],
141
+ "supported_member_count": self.supported_member_count,
142
+ "unattributed_member_count": self.unattributed_member_count,
143
+ "covered_card_keys": list(self.covered_card_keys),
144
+ "objective_values_consulted": False,
145
+ "workload_model_provider_identifiers_consulted": False,
146
+ }
147
+
148
+ def to_record(self) -> dict[str, object]:
149
+ self.__post_init__()
150
+ return {**self._unsigned_record(), "witness_sha256": self.witness_sha256}
151
+
152
+
153
+ def find_memory_dose_attribution_feasibility_witness(
154
+ contract: BoundedPortfolioMemoryDoseContract,
155
+ *,
156
+ stage: PortfolioMemoryDoseStage,
157
+ member_option_identities: tuple[tuple[str, str], ...],
158
+ ) -> MemoryDoseAttributionFeasibilityWitness | None:
159
+ """Return the first canonical exact attribution, or ``None`` if impossible."""
160
+
161
+ if type(contract) is not BoundedPortfolioMemoryDoseContract:
162
+ raise TypeError("contract must be exact BoundedPortfolioMemoryDoseContract")
163
+ contract.__post_init__()
164
+ if type(stage) is not PortfolioMemoryDoseStage:
165
+ raise TypeError("stage must be exact PortfolioMemoryDoseStage")
166
+ if type(member_option_identities) is not tuple or any(
167
+ type(value) is not tuple or len(value) != 2 for value in member_option_identities
168
+ ):
169
+ raise TypeError("member_option_identities must contain exact pairs")
170
+ members = tuple(sorted(member_option_identities))
171
+ # Construction performs the complete boundary validation once.
172
+ provisional = MemoryDoseAttributionFeasibilityWitness(
173
+ contract_sha256=contract.contract_sha256,
174
+ stage=stage,
175
+ member_option_identities=members,
176
+ attributions=tuple((option_id, ()) for option_id, _ in members),
177
+ )
178
+ del provisional
179
+
180
+ lower, upper = contract.bounds_for(stage)
181
+ maximum_supported = min(
182
+ upper,
183
+ len(members) - contract.minimum_unattributed_for(stage),
184
+ )
185
+ if lower > maximum_supported:
186
+ return None
187
+ assigned_cards = contract.assigned_card_keys
188
+ support_by_card = {value.card_key: value for value in contract.card_supports}
189
+ choices: list[tuple[tuple[str, ...], ...]] = []
190
+ for option_id, identity_sha256 in members:
191
+ compatible = tuple(
192
+ card_key
193
+ for card_key in assigned_cards
194
+ if support_by_card[card_key].supports(option_id, identity_sha256)
195
+ )
196
+ option_choices: list[tuple[str, ...]] = [()]
197
+ for count in range(
198
+ 1,
199
+ min(len(compatible), contract.maximum_cards_per_member) + 1,
200
+ ):
201
+ option_choices.extend(combinations(compatible, count))
202
+ choices.append(tuple(option_choices))
203
+
204
+ selected: list[tuple[str, ...]] = []
205
+ result: MemoryDoseAttributionFeasibilityWitness | None = None
206
+
207
+ def search(index: int, supported_count: int, covered: frozenset[str]) -> bool:
208
+ nonlocal result
209
+ remaining = len(members) - index
210
+ if supported_count > maximum_supported:
211
+ return False
212
+ if supported_count + remaining < lower:
213
+ return False
214
+ if contract.require_every_assigned_card:
215
+ future_cover = set(covered)
216
+ for future_choices in choices[index:]:
217
+ for candidate in future_choices:
218
+ future_cover.update(candidate)
219
+ if not set(assigned_cards).issubset(future_cover):
220
+ return False
221
+ if index == len(members):
222
+ if not lower <= supported_count <= maximum_supported:
223
+ return False
224
+ if contract.require_every_assigned_card and set(covered) != set(
225
+ assigned_cards
226
+ ):
227
+ return False
228
+ result = MemoryDoseAttributionFeasibilityWitness(
229
+ contract_sha256=contract.contract_sha256,
230
+ stage=stage,
231
+ member_option_identities=members,
232
+ attributions=tuple(
233
+ (option_id, cards)
234
+ for (option_id, _), cards in zip(members, selected, strict=True)
235
+ ),
236
+ )
237
+ return True
238
+ for candidate in choices[index]:
239
+ selected.append(candidate)
240
+ if search(
241
+ index + 1,
242
+ supported_count + bool(candidate),
243
+ covered.union(candidate),
244
+ ):
245
+ return True
246
+ selected.pop()
247
+ return False
248
+
249
+ search(0, 0, frozenset())
250
+ return result
251
+
252
+
253
+ __all__ = [
254
+ "MemoryDoseAttributionFeasibilityWitness",
255
+ "POLICY_DEFINITION_SHA256",
256
+ "POLICY_ID",
257
+ "POLICY_VERSION",
258
+ "find_memory_dose_attribution_feasibility_witness",
259
+ ]