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,1977 @@
1
+ """Transactional runtime adapter for closed-loop campaign insight learning.
2
+
3
+ This module is the workload-neutral bridge between campaign runtime hooks and
4
+ ``ClosedLoopCampaignLearning``. Workload adapters project opaque reflection
5
+ results into typed drafts/evidence/audit-plan templates. The concrete
6
+ transactional generation auditor then registers evaluated finite actions and
7
+ issues global audit bindings through the sealed falsification gate. The bridge
8
+ owns memory registration, bank-issued diagnostic admissions, pure lifecycle
9
+ preparation, and post-memory commit; it never interprets benchmark metrics.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import hashlib
15
+ import json
16
+ import math
17
+ import re
18
+ from dataclasses import dataclass, field
19
+ from typing import Protocol, runtime_checkable
20
+
21
+ from agent_evolve.application.campaign_execution import (
22
+ CampaignReflectionReceipt,
23
+ CampaignReflectionRequest,
24
+ CampaignReflectionStatus,
25
+ CampaignReflectionTestAdmissionRequest,
26
+ CampaignStageRequest,
27
+ )
28
+ from agent_evolve.application.campaign_generation_audit import (
29
+ CampaignGenerationAuditPreparation,
30
+ CampaignGenerationAuditProjection,
31
+ TransactionalPortfolioGenerationAuditor,
32
+ )
33
+ from agent_evolve.application.campaign_learning import (
34
+ CampaignDiagnosticAdmissionReceipt,
35
+ CampaignInsightRegistrationReceipt,
36
+ CampaignPreparedLearningBarrier,
37
+ CampaignSemanticAuditPlan,
38
+ ClosedLoopCampaignLearning,
39
+ )
40
+ from agent_evolve.application.insight_memory import (
41
+ EmpiricalEvidenceSnapshot,
42
+ InsightEvidenceLineage,
43
+ InsightLifecycleState,
44
+ InsightMemoryEntry,
45
+ QuarantineTestAdmissionReceipt,
46
+ ReflectedInsightBatchItem,
47
+ )
48
+ from agent_evolve.domain.finite_variation import FiniteActionEvidenceBinding
49
+ from agent_evolve.domain.ids import CandidateId, LLMCallId, OperatorInvocationId
50
+ from agent_evolve.application.portfolio_evolution import (
51
+ PortfolioMemoryCreditBatchPreparation,
52
+ PortfolioVariationWaveRequest,
53
+ PortfolioVariationWaveResult,
54
+ )
55
+ from agent_evolve.application.portfolio_campaign_runtime import (
56
+ CampaignPortfolioLearningPreparation,
57
+ )
58
+ from agent_evolve.domain.insight import InsightRef
59
+ from agent_evolve.domain.patch import require_sha256
60
+ from agent_evolve.domain.typed_json import (
61
+ FrozenJsonObject,
62
+ freeze_json,
63
+ thaw_json,
64
+ typed_json_sha256,
65
+ )
66
+ from agent_evolve.policies.memory.global_falsification import (
67
+ GLOBAL_FALSIFICATION_POLICY_DEFINITION_SHA256,
68
+ HypothesisAuditScope,
69
+ HypothesisClaimStrength,
70
+ HypothesisMetricPrediction,
71
+ TypedEvidencePredicate,
72
+ TypedInterventionSignature,
73
+ )
74
+ from agent_evolve.ports.agentic_generator import (
75
+ InsightDraft,
76
+ MetricComparisonAnchor,
77
+ MetricComparisonAnchorKind,
78
+ MetricEffectDirection,
79
+ MetricEffectPrediction,
80
+ ReflectionConsumerScope,
81
+ ReflectionEvidenceCatalog,
82
+ ReflectionEvidenceCatalogEntry,
83
+ ReflectionInsightContract,
84
+ ReflectionInsightKind,
85
+ validate_reflection_insight_draft,
86
+ )
87
+
88
+
89
+ _TOKEN = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
90
+ _OPERATOR = re.compile(r"^[a-z][a-z0-9_]*$")
91
+ _PATH = re.compile(r"^\$\.[^.\[\]\s]+(?:\.[^.\[\]\s]+|\[(?:0|[1-9][0-9]*)\])*$")
92
+ _TEMPLATE_DOMAIN = b"agent-evolve:campaign-semantic-audit-template:v1\x00"
93
+ _REFLECTION_PROJECTION_DOMAIN = (
94
+ b"agent-evolve:campaign-reflection-learning-projection:v1\x00"
95
+ )
96
+ _REFLECTION_REGISTRATION_DOMAIN = (
97
+ b"agent-evolve:campaign-runtime-reflection-registration:v1\x00"
98
+ )
99
+ _DIAGNOSTIC_EXPOSURE_DOMAIN = (
100
+ b"agent-evolve:campaign-runtime-diagnostic-exposure:v1\x00"
101
+ )
102
+ _REFLECTION_LEARNING_RECORD_DOMAIN = (
103
+ b"agent-evolve:campaign-reflection-learning-record:v1\x00"
104
+ )
105
+ _COMPILED_INSIGHT_SEMANTICS_DOMAIN = (
106
+ b"agent-evolve:campaign-compiled-insight-semantics:v1\x00"
107
+ )
108
+ CAMPAIGN_REFLECTION_LEARNING_RECORD_KEY = "campaign_reflection_learning"
109
+ STRUCTURED_REFLECTION_PROJECTION_POLICY_ID = "structured_reflection_learning"
110
+ STRUCTURED_REFLECTION_PROJECTION_POLICY_VERSION = 1
111
+ STRUCTURED_REFLECTION_PROJECTION_DEFINITION_SHA256 = hashlib.sha256(
112
+ b"agent-evolve:structured-reflection-learning-projection:v1"
113
+ ).hexdigest()
114
+
115
+
116
+ def _canonical_json(value: object) -> bytes:
117
+ return json.dumps(
118
+ value,
119
+ allow_nan=False,
120
+ ensure_ascii=True,
121
+ separators=(",", ":"),
122
+ sort_keys=True,
123
+ ).encode("ascii", errors="strict")
124
+
125
+
126
+ def _hash(domain: bytes, value: object) -> str:
127
+ return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
128
+
129
+
130
+ def _object(value: dict[str, object]) -> FrozenJsonObject:
131
+ frozen = freeze_json(value)
132
+ if type(frozen) is not FrozenJsonObject: # pragma: no cover - closed root.
133
+ raise AssertionError("runtime learning evidence did not freeze to an object")
134
+ return frozen
135
+
136
+
137
+ def _reference_record(reference: InsightRef) -> dict[str, object]:
138
+ return {
139
+ "insight_id": reference.insight_id.value,
140
+ "version": reference.version,
141
+ }
142
+
143
+
144
+ def _canonical_tokens(
145
+ values: tuple[str, ...],
146
+ *,
147
+ name: str,
148
+ pattern: re.Pattern[str],
149
+ allow_empty: bool = False,
150
+ ) -> None:
151
+ if type(values) is not tuple or any(
152
+ type(value) is not str or pattern.fullmatch(value) is None for value in values
153
+ ):
154
+ raise TypeError(f"{name} must contain canonical strings")
155
+ if not allow_empty and not values:
156
+ raise ValueError(f"{name} cannot be empty")
157
+ if values != tuple(sorted(set(values))):
158
+ raise ValueError(f"{name} must be unique and canonical")
159
+
160
+
161
+ def _paths_overlap(first: str, second: str) -> bool:
162
+ return (
163
+ first == second
164
+ or first.startswith(second + ".")
165
+ or first.startswith(second + "[")
166
+ or second.startswith(first + ".")
167
+ or second.startswith(first + "[")
168
+ )
169
+
170
+
171
+ def _plain_object(value: object, *, name: str) -> dict[str, object]:
172
+ if type(value) is not dict:
173
+ raise TypeError(f"{name} must be an exact JSON object")
174
+ return value
175
+
176
+
177
+ def _exact_keys(
178
+ value: dict[str, object],
179
+ expected: set[str],
180
+ *,
181
+ name: str,
182
+ ) -> None:
183
+ observed = set(value)
184
+ if observed != expected:
185
+ missing = tuple(sorted(expected - observed))
186
+ foreign = tuple(sorted(observed - expected))
187
+ raise ValueError(
188
+ f"{name} fields differ from the canonical schema; "
189
+ f"missing={missing!r}, foreign={foreign!r}"
190
+ )
191
+
192
+
193
+ def _string_tuple(value: object, *, name: str) -> tuple[str, ...]:
194
+ if type(value) is not list or any(type(item) is not str for item in value):
195
+ raise TypeError(f"{name} must be an exact JSON string array")
196
+ return tuple(value)
197
+
198
+
199
+ def _object_tuple(value: object, *, name: str) -> tuple[dict[str, object], ...]:
200
+ if type(value) is not list or any(type(item) is not dict for item in value):
201
+ raise TypeError(f"{name} must be an exact JSON object array")
202
+ return tuple(value)
203
+
204
+
205
+ def _decode_metric_prediction(
206
+ value: object,
207
+ *,
208
+ name: str,
209
+ ) -> MetricEffectPrediction:
210
+ record = _plain_object(value, name=name)
211
+ allowed = {"metric_id", "direction", "comparison_anchor"}
212
+ if set(record) not in (
213
+ {"metric_id", "direction"},
214
+ allowed,
215
+ ):
216
+ _exact_keys(record, allowed, name=name)
217
+ metric_id = record.get("metric_id")
218
+ direction = record.get("direction")
219
+ if type(metric_id) is not str or type(direction) is not str:
220
+ raise TypeError(f"{name} metric_id and direction must be exact strings")
221
+ anchor_record = record.get("comparison_anchor")
222
+ anchor: MetricComparisonAnchor | None
223
+ if anchor_record is None:
224
+ anchor = None
225
+ else:
226
+ raw_anchor = _plain_object(anchor_record, name=f"{name}.comparison_anchor")
227
+ _exact_keys(
228
+ raw_anchor,
229
+ {"kind", "source_role_id"},
230
+ name=f"{name}.comparison_anchor",
231
+ )
232
+ kind = raw_anchor["kind"]
233
+ source_role_id = raw_anchor["source_role_id"]
234
+ if type(kind) is not str or (
235
+ source_role_id is not None and type(source_role_id) is not str
236
+ ):
237
+ raise TypeError(f"{name}.comparison_anchor has non-string fields")
238
+ anchor = MetricComparisonAnchor(
239
+ kind=MetricComparisonAnchorKind(kind),
240
+ source_role_id=source_role_id,
241
+ )
242
+ prediction = MetricEffectPrediction(
243
+ metric_id=metric_id,
244
+ direction=MetricEffectDirection(direction),
245
+ comparison_anchor=anchor,
246
+ )
247
+ if prediction.to_record() != record:
248
+ raise ValueError(f"{name} is not the canonical prediction record")
249
+ return prediction
250
+
251
+
252
+ def _decode_insight_draft(value: object, *, name: str) -> InsightDraft:
253
+ record = _plain_object(value, name=name)
254
+ schema_version = record.get("schema_version")
255
+ base_fields = {
256
+ "schema_version",
257
+ "claim",
258
+ "trigger",
259
+ "mechanism",
260
+ "affected_paths",
261
+ "evidence_summary",
262
+ "confidence",
263
+ "evidence_contrast_ids",
264
+ "effect_predictions",
265
+ "recommended_option_families",
266
+ "recommended_option_ids",
267
+ "action_template",
268
+ "falsification_condition",
269
+ }
270
+ semantic_fields = {
271
+ "insight_kind",
272
+ "consumer_scopes",
273
+ "factor_capabilities",
274
+ }
275
+ if schema_version != 2:
276
+ raise ValueError(f"{name} must use semantic-v3 InsightDraft schema version 2")
277
+ _exact_keys(record, base_fields | semantic_fields, name=name)
278
+ text_fields = ("claim", "trigger", "mechanism", "evidence_summary")
279
+ if any(type(record[field]) is not str for field in text_fields):
280
+ raise TypeError(f"{name} prose fields must be exact strings")
281
+ confidence = record["confidence"]
282
+ if type(confidence) is not float:
283
+ raise TypeError(f"{name}.confidence must be an exact JSON float")
284
+ action_template = record["action_template"]
285
+ falsification_condition = record["falsification_condition"]
286
+ insight_kind = record["insight_kind"]
287
+ if (
288
+ type(action_template) is not str
289
+ or type(falsification_condition) is not str
290
+ or type(insight_kind) is not str
291
+ ):
292
+ raise TypeError(f"{name} actionable semantic fields must be exact strings")
293
+ predictions = tuple(
294
+ _decode_metric_prediction(item, name=f"{name}.effect_predictions[{index}]")
295
+ for index, item in enumerate(
296
+ _object_tuple(
297
+ record["effect_predictions"],
298
+ name=f"{name}.effect_predictions",
299
+ )
300
+ )
301
+ )
302
+ consumer_scopes = tuple(
303
+ ReflectionConsumerScope(item)
304
+ for item in _string_tuple(
305
+ record["consumer_scopes"],
306
+ name=f"{name}.consumer_scopes",
307
+ )
308
+ )
309
+ draft = InsightDraft(
310
+ claim=record["claim"],
311
+ trigger=record["trigger"],
312
+ mechanism=record["mechanism"],
313
+ affected_paths=_string_tuple(
314
+ record["affected_paths"],
315
+ name=f"{name}.affected_paths",
316
+ ),
317
+ evidence_summary=record["evidence_summary"],
318
+ confidence=confidence,
319
+ evidence_contrast_ids=_string_tuple(
320
+ record["evidence_contrast_ids"],
321
+ name=f"{name}.evidence_contrast_ids",
322
+ ),
323
+ effect_predictions=predictions,
324
+ recommended_option_families=_string_tuple(
325
+ record["recommended_option_families"],
326
+ name=f"{name}.recommended_option_families",
327
+ ),
328
+ recommended_option_ids=_string_tuple(
329
+ record["recommended_option_ids"],
330
+ name=f"{name}.recommended_option_ids",
331
+ ),
332
+ action_template=action_template,
333
+ falsification_condition=falsification_condition,
334
+ insight_kind=ReflectionInsightKind(insight_kind),
335
+ consumer_scopes=consumer_scopes,
336
+ factor_capabilities=_string_tuple(
337
+ record["factor_capabilities"],
338
+ name=f"{name}.factor_capabilities",
339
+ ),
340
+ )
341
+ if draft.content_record() != record:
342
+ raise ValueError(f"{name} is not the canonical InsightDraft content record")
343
+ return draft
344
+
345
+
346
+ def _decode_insight_contract(value: object) -> ReflectionInsightContract:
347
+ record = _plain_object(value, name="insight_contract")
348
+ fields = {
349
+ "schema_version",
350
+ "contract_identity_sha256",
351
+ "required_metric_ids",
352
+ "allowed_option_families",
353
+ "allowed_option_ids",
354
+ "direction_vocabulary",
355
+ "allowed_decision_paths",
356
+ "allowed_insight_kinds",
357
+ "allowed_consumer_scopes",
358
+ "allowed_comparison_anchor_kinds",
359
+ "allowed_factor_capabilities",
360
+ "allowed_source_role_ids",
361
+ }
362
+ _exact_keys(record, fields, name="insight_contract")
363
+ if record["schema_version"] != 3:
364
+ raise ValueError("insight_contract must use semantic-v3 schema version 3")
365
+ contract = ReflectionInsightContract(
366
+ required_metric_ids=_string_tuple(
367
+ record["required_metric_ids"],
368
+ name="insight_contract.required_metric_ids",
369
+ ),
370
+ allowed_option_families=_string_tuple(
371
+ record["allowed_option_families"],
372
+ name="insight_contract.allowed_option_families",
373
+ ),
374
+ allowed_option_ids=_string_tuple(
375
+ record["allowed_option_ids"],
376
+ name="insight_contract.allowed_option_ids",
377
+ ),
378
+ allowed_decision_paths=_string_tuple(
379
+ record["allowed_decision_paths"],
380
+ name="insight_contract.allowed_decision_paths",
381
+ ),
382
+ allowed_insight_kinds=tuple(
383
+ ReflectionInsightKind(item)
384
+ for item in _string_tuple(
385
+ record["allowed_insight_kinds"],
386
+ name="insight_contract.allowed_insight_kinds",
387
+ )
388
+ ),
389
+ allowed_consumer_scopes=tuple(
390
+ ReflectionConsumerScope(item)
391
+ for item in _string_tuple(
392
+ record["allowed_consumer_scopes"],
393
+ name="insight_contract.allowed_consumer_scopes",
394
+ )
395
+ ),
396
+ allowed_comparison_anchor_kinds=tuple(
397
+ MetricComparisonAnchorKind(item)
398
+ for item in _string_tuple(
399
+ record["allowed_comparison_anchor_kinds"],
400
+ name="insight_contract.allowed_comparison_anchor_kinds",
401
+ )
402
+ ),
403
+ allowed_factor_capabilities=_string_tuple(
404
+ record["allowed_factor_capabilities"],
405
+ name="insight_contract.allowed_factor_capabilities",
406
+ ),
407
+ allowed_source_role_ids=_string_tuple(
408
+ record["allowed_source_role_ids"],
409
+ name="insight_contract.allowed_source_role_ids",
410
+ ),
411
+ )
412
+ if not contract.is_semantic_v3 or contract.to_record() != record:
413
+ raise ValueError("insight_contract is not its canonical semantic-v3 record")
414
+ return contract
415
+
416
+
417
+ def _decode_evidence_catalog(value: object) -> ReflectionEvidenceCatalog:
418
+ record = _plain_object(value, name="evidence_catalog")
419
+ _exact_keys(
420
+ record,
421
+ {"schema_version", "entries", "catalog_identity_sha256"},
422
+ name="evidence_catalog",
423
+ )
424
+ if record["schema_version"] != 1:
425
+ raise ValueError("evidence_catalog must use schema version 1")
426
+ entries_list: list[ReflectionEvidenceCatalogEntry] = []
427
+ for item in _object_tuple(record["entries"], name="evidence_catalog.entries"):
428
+ _exact_keys(
429
+ item,
430
+ {"citation_key", "contrast_id"},
431
+ name="evidence_catalog entry",
432
+ )
433
+ citation_key = item["citation_key"]
434
+ contrast_id = item["contrast_id"]
435
+ if type(citation_key) is not str or type(contrast_id) is not str:
436
+ raise TypeError("catalog entry fields must be exact strings")
437
+ entries_list.append(ReflectionEvidenceCatalogEntry(citation_key, contrast_id))
438
+ entries = tuple(entries_list)
439
+ catalog = ReflectionEvidenceCatalog(entries)
440
+ if catalog.to_record() != record:
441
+ raise ValueError("evidence_catalog is not its canonical record")
442
+ return catalog
443
+
444
+
445
+ def _decode_finite_action_binding(
446
+ value: object,
447
+ *,
448
+ name: str,
449
+ ) -> FiniteActionEvidenceBinding:
450
+ record = _plain_object(value, name=name)
451
+ _exact_keys(
452
+ record,
453
+ {
454
+ "schema_version",
455
+ "contrast_id",
456
+ "option_id",
457
+ "family",
458
+ "option_identity_sha256",
459
+ "contract_identity_sha256",
460
+ "binding_identity_sha256",
461
+ },
462
+ name=name,
463
+ )
464
+ for field_name in (
465
+ "contrast_id",
466
+ "option_id",
467
+ "family",
468
+ "option_identity_sha256",
469
+ "contract_identity_sha256",
470
+ ):
471
+ if type(record[field_name]) is not str:
472
+ raise TypeError(f"{name}.{field_name} must be an exact string")
473
+ binding = FiniteActionEvidenceBinding(
474
+ contrast_id=record["contrast_id"],
475
+ option_id=record["option_id"],
476
+ family=record["family"],
477
+ option_identity_sha256=record["option_identity_sha256"],
478
+ contract_identity_sha256=record["contract_identity_sha256"],
479
+ )
480
+ if binding.to_record() != record:
481
+ raise ValueError(f"{name} is not its canonical record")
482
+ return binding
483
+
484
+
485
+ def _decode_empirical_snapshot(
486
+ value: object,
487
+ *,
488
+ name: str,
489
+ ) -> EmpiricalEvidenceSnapshot:
490
+ record = _plain_object(value, name=name)
491
+ _exact_keys(
492
+ record,
493
+ {
494
+ "schema_version",
495
+ "contrast_id",
496
+ "fact_schema_id",
497
+ "fact_schema_version",
498
+ "fact_schema_definition_sha256",
499
+ "facts",
500
+ "optimization_semantics_definition_sha256",
501
+ "action_semantics_definition_sha256",
502
+ "snapshot_sha256",
503
+ },
504
+ name=name,
505
+ )
506
+ string_fields = (
507
+ "contrast_id",
508
+ "fact_schema_id",
509
+ "fact_schema_definition_sha256",
510
+ )
511
+ if any(type(record[field_name]) is not str for field_name in string_fields):
512
+ raise TypeError(f"{name} identity fields must be exact strings")
513
+ if type(record["fact_schema_version"]) is not int:
514
+ raise TypeError(f"{name}.fact_schema_version must be an exact integer")
515
+ for field_name in (
516
+ "optimization_semantics_definition_sha256",
517
+ "action_semantics_definition_sha256",
518
+ ):
519
+ field_value = record[field_name]
520
+ if field_value is not None and type(field_value) is not str:
521
+ raise TypeError(f"{name}.{field_name} must be a string or null")
522
+ facts = freeze_json(_plain_object(record["facts"], name=f"{name}.facts"))
523
+ if type(facts) is not FrozenJsonObject:
524
+ raise AssertionError("empirical facts did not freeze to an object")
525
+ snapshot = EmpiricalEvidenceSnapshot(
526
+ contrast_id=record["contrast_id"],
527
+ fact_schema_id=record["fact_schema_id"],
528
+ fact_schema_version=record["fact_schema_version"],
529
+ fact_schema_definition_sha256=record["fact_schema_definition_sha256"],
530
+ facts=facts,
531
+ optimization_semantics_definition_sha256=record[
532
+ "optimization_semantics_definition_sha256"
533
+ ],
534
+ action_semantics_definition_sha256=record["action_semantics_definition_sha256"],
535
+ )
536
+ if snapshot.to_record() != record:
537
+ raise ValueError(f"{name} is not its canonical record")
538
+ return snapshot
539
+
540
+
541
+ @dataclass(frozen=True, slots=True)
542
+ class CampaignReflectionLearningRecord:
543
+ """Canonical provider-independent input to reflection learning.
544
+
545
+ The opaque campaign result may carry telemetry or runner-specific trace data
546
+ beside this record. Only this exact nested schema may create memory cards.
547
+ Engine-owned source IDs and empirical snapshots are therefore separated from
548
+ model-authored :class:`InsightDraft` content before projection.
549
+ """
550
+
551
+ reflection_generation_request_sha256: str
552
+ reflection_call_id: LLMCallId
553
+ source_generation: int
554
+ source_stage_receipt_sha256: str
555
+ origin_cutoff_event_index: int
556
+ source_operator_invocation_ids: tuple[OperatorInvocationId, ...]
557
+ source_candidate_ids: tuple[CandidateId, ...]
558
+ evidence_catalog: ReflectionEvidenceCatalog
559
+ insight_contract: ReflectionInsightContract
560
+ insights: tuple[InsightDraft, ...]
561
+ finite_action_bindings: tuple[FiniteActionEvidenceBinding, ...]
562
+ empirical_evidence: tuple[EmpiricalEvidenceSnapshot, ...]
563
+ record_sha256: str = field(init=False)
564
+
565
+ def __post_init__(self) -> None:
566
+ require_sha256(
567
+ self.reflection_generation_request_sha256,
568
+ "reflection_generation_request_sha256",
569
+ )
570
+ if type(self.reflection_call_id) is not LLMCallId:
571
+ raise TypeError("reflection_call_id must be an exact LLMCallId")
572
+ LLMCallId.__post_init__(self.reflection_call_id)
573
+ if type(self.source_generation) is not int or self.source_generation <= 0:
574
+ raise ValueError("source_generation must be a positive exact integer")
575
+ require_sha256(
576
+ self.source_stage_receipt_sha256,
577
+ "source_stage_receipt_sha256",
578
+ )
579
+ if (
580
+ type(self.origin_cutoff_event_index) is not int
581
+ or self.origin_cutoff_event_index < 0
582
+ ):
583
+ raise ValueError("origin_cutoff_event_index must be non-negative")
584
+ for values, expected_type, name in (
585
+ (
586
+ self.source_operator_invocation_ids,
587
+ OperatorInvocationId,
588
+ "source_operator_invocation_ids",
589
+ ),
590
+ (self.source_candidate_ids, CandidateId, "source_candidate_ids"),
591
+ ):
592
+ if (
593
+ type(values) is not tuple
594
+ or not values
595
+ or any(type(item) is not expected_type for item in values)
596
+ ):
597
+ raise TypeError(f"{name} must contain exact non-empty IDs")
598
+ for item in values:
599
+ expected_type.__post_init__(item)
600
+ if values != tuple(sorted(set(values))):
601
+ raise ValueError(f"{name} must be unique and canonical")
602
+ if type(self.evidence_catalog) is not ReflectionEvidenceCatalog:
603
+ raise TypeError("evidence_catalog must be exact")
604
+ ReflectionEvidenceCatalog.__post_init__(self.evidence_catalog)
605
+ if type(self.insight_contract) is not ReflectionInsightContract:
606
+ raise TypeError("insight_contract must be exact")
607
+ ReflectionInsightContract.__post_init__(self.insight_contract)
608
+ if not self.insight_contract.is_semantic_v3:
609
+ raise ValueError("campaign reflection learning requires semantic-v3")
610
+ if (
611
+ type(self.insights) is not tuple
612
+ or not self.insights
613
+ or any(type(item) is not InsightDraft for item in self.insights)
614
+ ):
615
+ raise ValueError("insights must contain exact InsightDraft values")
616
+ for draft in self.insights:
617
+ validate_reflection_insight_draft(draft, self.insight_contract)
618
+ if len({draft.content_sha256 for draft in self.insights}) != len(self.insights):
619
+ raise ValueError("reflection learning record repeats an insight draft")
620
+ if type(self.finite_action_bindings) is not tuple or any(
621
+ type(item) is not FiniteActionEvidenceBinding
622
+ for item in self.finite_action_bindings
623
+ ):
624
+ raise TypeError("finite_action_bindings must contain exact bindings")
625
+ for item in self.finite_action_bindings:
626
+ FiniteActionEvidenceBinding.__post_init__(item)
627
+ binding_ids = tuple(item.contrast_id for item in self.finite_action_bindings)
628
+ if binding_ids != tuple(sorted(set(binding_ids))):
629
+ raise ValueError("finite action bindings must use canonical contrast order")
630
+ if type(self.empirical_evidence) is not tuple or any(
631
+ type(item) is not EmpiricalEvidenceSnapshot
632
+ for item in self.empirical_evidence
633
+ ):
634
+ raise TypeError("empirical_evidence must contain exact snapshots")
635
+ for item in self.empirical_evidence:
636
+ EmpiricalEvidenceSnapshot.__post_init__(item)
637
+ empirical_ids = tuple(item.contrast_id for item in self.empirical_evidence)
638
+ if empirical_ids != self.evidence_catalog.contrast_ids:
639
+ raise ValueError(
640
+ "empirical evidence must exactly cover the request evidence catalog"
641
+ )
642
+ if not set(binding_ids).issubset(self.evidence_catalog.contrast_ids):
643
+ raise ValueError("finite action binding names a foreign contrast")
644
+ for draft in self.insights:
645
+ ReflectedInsightBatchItem(draft, self._lineage_for(draft))
646
+ object.__setattr__(
647
+ self,
648
+ "record_sha256",
649
+ _hash(_REFLECTION_LEARNING_RECORD_DOMAIN, self._unsigned_record()),
650
+ )
651
+
652
+ def _lineage_for(self, draft: InsightDraft) -> InsightEvidenceLineage:
653
+ cited = draft.evidence_contrast_ids
654
+ return InsightEvidenceLineage(
655
+ reflection_call_id=self.reflection_call_id,
656
+ source_operator_invocation_ids=self.source_operator_invocation_ids,
657
+ source_candidate_ids=self.source_candidate_ids,
658
+ available_contrast_ids=self.evidence_catalog.contrast_ids,
659
+ cited_contrast_ids=cited,
660
+ finite_action_bindings=tuple(
661
+ item
662
+ for item in self.finite_action_bindings
663
+ if item.contrast_id in cited
664
+ ),
665
+ empirical_evidence=tuple(
666
+ item for item in self.empirical_evidence if item.contrast_id in cited
667
+ ),
668
+ )
669
+
670
+ def lineage_for(self, draft: InsightDraft) -> InsightEvidenceLineage:
671
+ self.__post_init__()
672
+ if type(draft) is not InsightDraft or draft not in self.insights:
673
+ raise ValueError("draft is not part of this reflection learning record")
674
+ return self._lineage_for(draft)
675
+
676
+ def _unsigned_record(self) -> dict[str, object]:
677
+ return {
678
+ "schema_version": 1,
679
+ "reflection_generation_request_sha256": (
680
+ self.reflection_generation_request_sha256
681
+ ),
682
+ "reflection_call_id": self.reflection_call_id.value,
683
+ "source_generation": self.source_generation,
684
+ "source_stage_receipt_sha256": self.source_stage_receipt_sha256,
685
+ "origin_cutoff_event_index": self.origin_cutoff_event_index,
686
+ "source_operator_invocation_ids": [
687
+ item.value for item in self.source_operator_invocation_ids
688
+ ],
689
+ "source_candidate_ids": [item.value for item in self.source_candidate_ids],
690
+ "evidence_catalog": self.evidence_catalog.to_record(),
691
+ "insight_contract": self.insight_contract.to_record(),
692
+ "insights": [item.content_record() for item in self.insights],
693
+ "finite_action_bindings": [
694
+ item.to_record() for item in self.finite_action_bindings
695
+ ],
696
+ "empirical_evidence": [
697
+ item.to_record() for item in self.empirical_evidence
698
+ ],
699
+ }
700
+
701
+ def to_record(self) -> dict[str, object]:
702
+ self.__post_init__()
703
+ return {**self._unsigned_record(), "record_sha256": self.record_sha256}
704
+
705
+
706
+ @dataclass(frozen=True, slots=True)
707
+ class CampaignReflectionLearningRecordCodec:
708
+ """Strict codec for the one canonical nested campaign learning record."""
709
+
710
+ @staticmethod
711
+ def encode(record: CampaignReflectionLearningRecord) -> FrozenJsonObject:
712
+ if type(record) is not CampaignReflectionLearningRecord:
713
+ raise TypeError("record must be exact CampaignReflectionLearningRecord")
714
+ CampaignReflectionLearningRecord.__post_init__(record)
715
+ return _object({CAMPAIGN_REFLECTION_LEARNING_RECORD_KEY: record.to_record()})
716
+
717
+ @staticmethod
718
+ def decode(result: FrozenJsonObject) -> CampaignReflectionLearningRecord:
719
+ if type(result) is not FrozenJsonObject or freeze_json(result) is not result:
720
+ raise TypeError("result must be an exact frozen object")
721
+ outer = thaw_json(result)
722
+ if type(outer) is not dict: # pragma: no cover - exact root above.
723
+ raise AssertionError("frozen reflection result thawed to a non-object")
724
+ if CAMPAIGN_REFLECTION_LEARNING_RECORD_KEY not in outer:
725
+ raise ValueError("reflection result omits the canonical learning record")
726
+ raw = _plain_object(
727
+ outer[CAMPAIGN_REFLECTION_LEARNING_RECORD_KEY],
728
+ name=CAMPAIGN_REFLECTION_LEARNING_RECORD_KEY,
729
+ )
730
+ fields = {
731
+ "schema_version",
732
+ "reflection_generation_request_sha256",
733
+ "reflection_call_id",
734
+ "source_generation",
735
+ "source_stage_receipt_sha256",
736
+ "origin_cutoff_event_index",
737
+ "source_operator_invocation_ids",
738
+ "source_candidate_ids",
739
+ "evidence_catalog",
740
+ "insight_contract",
741
+ "insights",
742
+ "finite_action_bindings",
743
+ "empirical_evidence",
744
+ "record_sha256",
745
+ }
746
+ _exact_keys(raw, fields, name=CAMPAIGN_REFLECTION_LEARNING_RECORD_KEY)
747
+ if raw["schema_version"] != 1:
748
+ raise ValueError("unsupported campaign reflection learning schema")
749
+ for field_name in (
750
+ "reflection_generation_request_sha256",
751
+ "reflection_call_id",
752
+ "source_stage_receipt_sha256",
753
+ ):
754
+ if type(raw[field_name]) is not str:
755
+ raise TypeError(f"{field_name} must be an exact string")
756
+ if (
757
+ type(raw["source_generation"]) is not int
758
+ or type(raw["origin_cutoff_event_index"]) is not int
759
+ ):
760
+ raise TypeError("reflection generation and cutoff must be exact integers")
761
+ record = CampaignReflectionLearningRecord(
762
+ reflection_generation_request_sha256=raw[
763
+ "reflection_generation_request_sha256"
764
+ ],
765
+ reflection_call_id=LLMCallId(raw["reflection_call_id"]),
766
+ source_generation=raw["source_generation"],
767
+ source_stage_receipt_sha256=raw["source_stage_receipt_sha256"],
768
+ origin_cutoff_event_index=raw["origin_cutoff_event_index"],
769
+ source_operator_invocation_ids=tuple(
770
+ OperatorInvocationId(item)
771
+ for item in _string_tuple(
772
+ raw["source_operator_invocation_ids"],
773
+ name="source_operator_invocation_ids",
774
+ )
775
+ ),
776
+ source_candidate_ids=tuple(
777
+ CandidateId(item)
778
+ for item in _string_tuple(
779
+ raw["source_candidate_ids"],
780
+ name="source_candidate_ids",
781
+ )
782
+ ),
783
+ evidence_catalog=_decode_evidence_catalog(raw["evidence_catalog"]),
784
+ insight_contract=_decode_insight_contract(raw["insight_contract"]),
785
+ insights=tuple(
786
+ _decode_insight_draft(item, name=f"insights[{index}]")
787
+ for index, item in enumerate(
788
+ _object_tuple(raw["insights"], name="insights")
789
+ )
790
+ ),
791
+ finite_action_bindings=tuple(
792
+ _decode_finite_action_binding(
793
+ item,
794
+ name=f"finite_action_bindings[{index}]",
795
+ )
796
+ for index, item in enumerate(
797
+ _object_tuple(
798
+ raw["finite_action_bindings"],
799
+ name="finite_action_bindings",
800
+ )
801
+ )
802
+ ),
803
+ empirical_evidence=tuple(
804
+ _decode_empirical_snapshot(
805
+ item,
806
+ name=f"empirical_evidence[{index}]",
807
+ )
808
+ for index, item in enumerate(
809
+ _object_tuple(raw["empirical_evidence"], name="empirical_evidence")
810
+ )
811
+ ),
812
+ )
813
+ if record.to_record() != raw:
814
+ raise ValueError("campaign reflection learning record is not canonical")
815
+ return record
816
+
817
+
818
+ @dataclass(frozen=True, slots=True)
819
+ class CompiledCampaignInsightSemantics:
820
+ """Workload compilation output bound to one exact draft and evidence lineage."""
821
+
822
+ draft_content_sha256: str
823
+ insight_contract_identity_sha256: str
824
+ evidence_lineage_sha256: str
825
+ trigger: TypedEvidencePredicate
826
+ old_value_predicate: TypedEvidencePredicate
827
+ new_action: TypedEvidencePredicate
828
+ matcher_definition_sha256: str
829
+ compiler_policy_id: str
830
+ compiler_policy_version: int
831
+ compiler_definition_sha256: str
832
+ compilation_sha256: str = field(init=False)
833
+
834
+ def __post_init__(self) -> None:
835
+ for name in (
836
+ "draft_content_sha256",
837
+ "insight_contract_identity_sha256",
838
+ "evidence_lineage_sha256",
839
+ "matcher_definition_sha256",
840
+ "compiler_definition_sha256",
841
+ ):
842
+ require_sha256(getattr(self, name), name)
843
+ for name in ("trigger", "old_value_predicate", "new_action"):
844
+ value = getattr(self, name)
845
+ if type(value) is not TypedEvidencePredicate:
846
+ raise TypeError(f"{name} must be an exact TypedEvidencePredicate")
847
+ TypedEvidencePredicate.__post_init__(value)
848
+ if (
849
+ type(self.compiler_policy_id) is not str
850
+ or _TOKEN.fullmatch(self.compiler_policy_id) is None
851
+ ):
852
+ raise ValueError("compiler_policy_id must be canonical")
853
+ if (
854
+ type(self.compiler_policy_version) is not int
855
+ or self.compiler_policy_version <= 0
856
+ ):
857
+ raise ValueError("compiler_policy_version must be positive")
858
+ object.__setattr__(
859
+ self,
860
+ "compilation_sha256",
861
+ _hash(_COMPILED_INSIGHT_SEMANTICS_DOMAIN, self._unsigned_record()),
862
+ )
863
+
864
+ def _unsigned_record(self) -> dict[str, object]:
865
+ return {
866
+ "schema_version": 1,
867
+ "draft_content_sha256": self.draft_content_sha256,
868
+ "insight_contract_identity_sha256": (self.insight_contract_identity_sha256),
869
+ "evidence_lineage_sha256": self.evidence_lineage_sha256,
870
+ "trigger_predicate_sha256": self.trigger.predicate_sha256,
871
+ "old_value_predicate_sha256": self.old_value_predicate.predicate_sha256,
872
+ "new_action_predicate_sha256": self.new_action.predicate_sha256,
873
+ "matcher_definition_sha256": self.matcher_definition_sha256,
874
+ "compiler": {
875
+ "policy_id": self.compiler_policy_id,
876
+ "policy_version": self.compiler_policy_version,
877
+ "definition_sha256": self.compiler_definition_sha256,
878
+ },
879
+ }
880
+
881
+ def to_record(self) -> dict[str, object]:
882
+ self.__post_init__()
883
+ return {
884
+ **self._unsigned_record(),
885
+ "compilation_sha256": self.compilation_sha256,
886
+ }
887
+
888
+
889
+ @runtime_checkable
890
+ class CampaignInsightSemanticCompiler(Protocol):
891
+ """Irreducible workload seam for replayable trigger/action semantics."""
892
+
893
+ policy_id: str
894
+ policy_version: int
895
+ definition_sha256: str
896
+
897
+ def compile(
898
+ self,
899
+ *,
900
+ draft: InsightDraft,
901
+ insight_contract: ReflectionInsightContract,
902
+ evidence_lineage: InsightEvidenceLineage,
903
+ ) -> CompiledCampaignInsightSemantics: ...
904
+
905
+
906
+ @dataclass(frozen=True, slots=True)
907
+ class CampaignSemanticAuditPlanTemplate:
908
+ """Reference-free semantic plan projected before memory allocates an ID."""
909
+
910
+ trigger: TypedEvidencePredicate
911
+ intervention: TypedInterventionSignature
912
+ predictions: tuple[HypothesisMetricPrediction, ...]
913
+ claim_strength: HypothesisClaimStrength
914
+ scope: HypothesisAuditScope
915
+ matcher_definition_sha256: str
916
+ origin_cutoff_event_index: int
917
+ minimum_support_clusters: int
918
+ minimum_support_instances: int
919
+ audit_policy_definition_sha256: str = GLOBAL_FALSIFICATION_POLICY_DEFINITION_SHA256
920
+ template_sha256: str = field(init=False)
921
+
922
+ def __post_init__(self) -> None:
923
+ if type(self.trigger) is not TypedEvidencePredicate:
924
+ raise TypeError("trigger must be exact")
925
+ TypedEvidencePredicate.__post_init__(self.trigger)
926
+ if type(self.intervention) is not TypedInterventionSignature:
927
+ raise TypeError("intervention must be exact")
928
+ TypedInterventionSignature.__post_init__(self.intervention)
929
+ if (
930
+ type(self.predictions) is not tuple
931
+ or not self.predictions
932
+ or any(
933
+ type(value) is not HypothesisMetricPrediction
934
+ for value in self.predictions
935
+ )
936
+ ):
937
+ raise ValueError("predictions must contain exact typed predictions")
938
+ for value in self.predictions:
939
+ HypothesisMetricPrediction.__post_init__(value)
940
+ if type(self.claim_strength) is not HypothesisClaimStrength:
941
+ raise TypeError("claim_strength must be exact")
942
+ HypothesisClaimStrength.__post_init__(self.claim_strength)
943
+ if type(self.scope) is not HypothesisAuditScope:
944
+ raise TypeError("scope must be exact")
945
+ HypothesisAuditScope.__post_init__(self.scope)
946
+ require_sha256(self.matcher_definition_sha256, "matcher_definition_sha256")
947
+ if (
948
+ type(self.origin_cutoff_event_index) is not int
949
+ or self.origin_cutoff_event_index < 0
950
+ ):
951
+ raise ValueError("origin_cutoff_event_index must be non-negative")
952
+ for name in ("minimum_support_clusters", "minimum_support_instances"):
953
+ value = getattr(self, name)
954
+ if type(value) is not int or value <= 0:
955
+ raise ValueError(f"{name} must be a positive exact integer")
956
+ if (
957
+ self.audit_policy_definition_sha256
958
+ != GLOBAL_FALSIFICATION_POLICY_DEFINITION_SHA256
959
+ ):
960
+ raise ValueError("unsupported global falsification policy definition")
961
+ object.__setattr__(
962
+ self,
963
+ "template_sha256",
964
+ _hash(_TEMPLATE_DOMAIN, self._unsigned_record()),
965
+ )
966
+
967
+ def _unsigned_record(self) -> dict[str, object]:
968
+ return {
969
+ "schema_version": 1,
970
+ "trigger_predicate_sha256": self.trigger.predicate_sha256,
971
+ "intervention_signature_sha256": self.intervention.signature_sha256,
972
+ "predictions": [value.to_record() for value in self.predictions],
973
+ "claim_strength": self.claim_strength.to_record(),
974
+ "scope_sha256": self.scope.scope_sha256,
975
+ "matcher_definition_sha256": self.matcher_definition_sha256,
976
+ "origin_cutoff_event_index": self.origin_cutoff_event_index,
977
+ "minimum_support_clusters": self.minimum_support_clusters,
978
+ "minimum_support_instances": self.minimum_support_instances,
979
+ "audit_policy_definition_sha256": (self.audit_policy_definition_sha256),
980
+ }
981
+
982
+ def to_record(self) -> dict[str, object]:
983
+ self.__post_init__()
984
+ return {**self._unsigned_record(), "template_sha256": self.template_sha256}
985
+
986
+ def validate_source(
987
+ self,
988
+ draft: InsightDraft,
989
+ applicable_operator_kinds: tuple[str, ...],
990
+ ) -> None:
991
+ """Fail before memory publication if a template changes card semantics."""
992
+
993
+ if type(draft) is not InsightDraft:
994
+ raise TypeError("draft must be exact")
995
+ InsightDraft.__post_init__(draft)
996
+ _canonical_tokens(
997
+ applicable_operator_kinds,
998
+ name="applicable_operator_kinds",
999
+ pattern=_OPERATOR,
1000
+ )
1001
+ if not draft.has_semantic_contract or not draft.has_intervention_contract:
1002
+ raise ValueError("runtime reflection must be actionable semantic-v3")
1003
+ if draft.insight_kind not in {
1004
+ ReflectionInsightKind.EMPIRICAL_PREDICTIVE_RULE,
1005
+ ReflectionInsightKind.MECHANISTIC_CONJECTURE,
1006
+ }:
1007
+ raise ValueError("runtime reflection kind is not promotion-eligible")
1008
+ expected_strength = HypothesisClaimStrength(
1009
+ sufficiency=True,
1010
+ necessity=False,
1011
+ invariance=False,
1012
+ mechanistic_or_causal=(
1013
+ draft.insight_kind is ReflectionInsightKind.MECHANISTIC_CONJECTURE
1014
+ ),
1015
+ )
1016
+ expected_predictions = tuple(
1017
+ (value.metric_id, value.direction, None, None)
1018
+ for value in draft.effect_predictions
1019
+ )
1020
+ observed_predictions = tuple(
1021
+ (
1022
+ value.metric_id,
1023
+ value.direction,
1024
+ value.minimum_delta,
1025
+ value.maximum_delta,
1026
+ )
1027
+ for value in self.predictions
1028
+ )
1029
+ if any(
1030
+ value.direction is MetricEffectDirection.UNKNOWN
1031
+ for value in draft.effect_predictions
1032
+ ):
1033
+ raise ValueError("runtime reflection predictions must be known")
1034
+ if (
1035
+ draft.affected_paths != tuple(sorted(set(draft.affected_paths)))
1036
+ or self.intervention.affected_paths != draft.affected_paths
1037
+ or self.intervention.admissible_operator_families
1038
+ != applicable_operator_kinds
1039
+ or observed_predictions != expected_predictions
1040
+ or self.claim_strength != expected_strength
1041
+ ):
1042
+ raise ValueError("semantic audit template differs from reflection draft")
1043
+
1044
+ def bind(self, entry: InsightMemoryEntry) -> CampaignSemanticAuditPlan:
1045
+ if type(entry) is not InsightMemoryEntry:
1046
+ raise TypeError("entry must be exact")
1047
+ InsightMemoryEntry.__post_init__(entry)
1048
+ self.validate_source(entry.draft, entry.applicable_operator_kinds)
1049
+ return CampaignSemanticAuditPlan(
1050
+ reference=entry.reference,
1051
+ draft_content_sha256=entry.draft.content_sha256,
1052
+ draft_hypothesis_sha256=entry.draft.hypothesis_sha256,
1053
+ trigger=self.trigger,
1054
+ intervention=self.intervention,
1055
+ predictions=self.predictions,
1056
+ claim_strength=self.claim_strength,
1057
+ scope=self.scope,
1058
+ matcher_definition_sha256=self.matcher_definition_sha256,
1059
+ origin_cutoff_event_index=self.origin_cutoff_event_index,
1060
+ minimum_support_clusters=self.minimum_support_clusters,
1061
+ minimum_support_instances=self.minimum_support_instances,
1062
+ audit_policy_definition_sha256=(self.audit_policy_definition_sha256),
1063
+ )
1064
+
1065
+
1066
+ @dataclass(frozen=True, slots=True)
1067
+ class CampaignReflectedInsightProjection:
1068
+ draft: InsightDraft
1069
+ evidence_lineage: InsightEvidenceLineage
1070
+ semantic_audit_template: CampaignSemanticAuditPlanTemplate
1071
+
1072
+ def __post_init__(self) -> None:
1073
+ if type(self.draft) is not InsightDraft:
1074
+ raise TypeError("draft must be exact")
1075
+ InsightDraft.__post_init__(self.draft)
1076
+ if type(self.evidence_lineage) is not InsightEvidenceLineage:
1077
+ raise TypeError("evidence_lineage must be exact")
1078
+ InsightEvidenceLineage.__post_init__(self.evidence_lineage)
1079
+ if type(self.semantic_audit_template) is not (
1080
+ CampaignSemanticAuditPlanTemplate
1081
+ ):
1082
+ raise TypeError("semantic_audit_template must be exact")
1083
+ CampaignSemanticAuditPlanTemplate.__post_init__(self.semantic_audit_template)
1084
+ ReflectedInsightBatchItem(self.draft, self.evidence_lineage)
1085
+
1086
+
1087
+ @dataclass(frozen=True, slots=True)
1088
+ class CampaignReflectionLearningProjection:
1089
+ reflection_request_sha256: str
1090
+ reflection_receipt_sha256: str
1091
+ reflection_result_sha256: str
1092
+ insights: tuple[CampaignReflectedInsightProjection, ...]
1093
+ applicable_operator_kinds: tuple[str, ...]
1094
+ diagnostic_operator_kind: str
1095
+ diagnostic_editable_paths: tuple[str, ...]
1096
+ initial_score: float
1097
+ projection_policy_id: str
1098
+ projection_policy_version: int
1099
+ projection_policy_definition_sha256: str
1100
+ projection_sha256: str = field(init=False)
1101
+
1102
+ def __post_init__(self) -> None:
1103
+ for name in (
1104
+ "reflection_request_sha256",
1105
+ "reflection_receipt_sha256",
1106
+ "reflection_result_sha256",
1107
+ "projection_policy_definition_sha256",
1108
+ ):
1109
+ require_sha256(getattr(self, name), name)
1110
+ if (
1111
+ type(self.insights) is not tuple
1112
+ or not self.insights
1113
+ or any(
1114
+ type(value) is not CampaignReflectedInsightProjection
1115
+ for value in self.insights
1116
+ )
1117
+ ):
1118
+ raise ValueError("insights must contain exact projections")
1119
+ for value in self.insights:
1120
+ CampaignReflectedInsightProjection.__post_init__(value)
1121
+ _canonical_tokens(
1122
+ self.applicable_operator_kinds,
1123
+ name="applicable_operator_kinds",
1124
+ pattern=_OPERATOR,
1125
+ )
1126
+ if (
1127
+ type(self.diagnostic_operator_kind) is not str
1128
+ or _OPERATOR.fullmatch(self.diagnostic_operator_kind) is None
1129
+ or self.diagnostic_operator_kind not in self.applicable_operator_kinds
1130
+ ):
1131
+ raise ValueError("diagnostic_operator_kind must be explicitly applicable")
1132
+ _canonical_tokens(
1133
+ self.diagnostic_editable_paths,
1134
+ name="diagnostic_editable_paths",
1135
+ pattern=_PATH,
1136
+ )
1137
+ if any(
1138
+ not any(
1139
+ _paths_overlap(affected, editable)
1140
+ for editable in self.diagnostic_editable_paths
1141
+ )
1142
+ for item in self.insights
1143
+ for affected in item.draft.affected_paths
1144
+ ):
1145
+ raise ValueError("diagnostic paths do not cover every reflection path")
1146
+ if type(self.initial_score) is not float or not math.isfinite(
1147
+ self.initial_score
1148
+ ):
1149
+ raise TypeError("initial_score must be a finite canonical float")
1150
+ if (
1151
+ type(self.projection_policy_id) is not str
1152
+ or _TOKEN.fullmatch(self.projection_policy_id) is None
1153
+ ):
1154
+ raise ValueError("projection_policy_id must be canonical")
1155
+ if (
1156
+ type(self.projection_policy_version) is not int
1157
+ or self.projection_policy_version <= 0
1158
+ ):
1159
+ raise ValueError("projection_policy_version must be positive")
1160
+ for item in self.insights:
1161
+ item.semantic_audit_template.validate_source(
1162
+ item.draft,
1163
+ self.applicable_operator_kinds,
1164
+ )
1165
+ object.__setattr__(
1166
+ self,
1167
+ "projection_sha256",
1168
+ _hash(_REFLECTION_PROJECTION_DOMAIN, self._unsigned_record()),
1169
+ )
1170
+
1171
+ def _unsigned_record(self) -> dict[str, object]:
1172
+ return {
1173
+ "schema_version": 1,
1174
+ "reflection_request_sha256": self.reflection_request_sha256,
1175
+ "reflection_receipt_sha256": self.reflection_receipt_sha256,
1176
+ "reflection_result_sha256": self.reflection_result_sha256,
1177
+ "insights": [
1178
+ {
1179
+ "draft_content_sha256": value.draft.content_sha256,
1180
+ "draft_hypothesis_sha256": value.draft.hypothesis_sha256,
1181
+ "evidence_lineage_sha256": value.evidence_lineage.identity_sha256,
1182
+ "semantic_audit_template_sha256": (
1183
+ value.semantic_audit_template.template_sha256
1184
+ ),
1185
+ }
1186
+ for value in self.insights
1187
+ ],
1188
+ "applicable_operator_kinds": list(self.applicable_operator_kinds),
1189
+ "diagnostic_operator_kind": self.diagnostic_operator_kind,
1190
+ "diagnostic_editable_paths": list(self.diagnostic_editable_paths),
1191
+ "initial_score_hex": self.initial_score.hex(),
1192
+ "projection_policy": {
1193
+ "policy_id": self.projection_policy_id,
1194
+ "policy_version": self.projection_policy_version,
1195
+ "definition_sha256": self.projection_policy_definition_sha256,
1196
+ },
1197
+ }
1198
+
1199
+ def to_record(self) -> dict[str, object]:
1200
+ self.__post_init__()
1201
+ return {**self._unsigned_record(), "projection_sha256": self.projection_sha256}
1202
+
1203
+
1204
+ @runtime_checkable
1205
+ class CampaignReflectionLearningProjectionPort(Protocol):
1206
+ policy_id: str
1207
+ policy_version: int
1208
+ definition_sha256: str
1209
+
1210
+ def project(
1211
+ self,
1212
+ request: CampaignReflectionRequest,
1213
+ receipt: CampaignReflectionReceipt,
1214
+ result: FrozenJsonObject,
1215
+ ) -> CampaignReflectionLearningProjection: ...
1216
+
1217
+
1218
+ @dataclass(frozen=True, slots=True)
1219
+ class StructuredCampaignReflectionLearningProjector:
1220
+ """Generic strict-record projector with injected workload semantics.
1221
+
1222
+ All structural joins, lineage construction, prediction projection, claim
1223
+ strength, and audit-template binding are application-owned. Only typed
1224
+ trigger/old-value/new-action compilation remains workload-owned.
1225
+ """
1226
+
1227
+ semantic_compiler: CampaignInsightSemanticCompiler
1228
+ scope: HypothesisAuditScope
1229
+ applicable_operator_kinds: tuple[str, ...]
1230
+ diagnostic_operator_kind: str
1231
+ diagnostic_editable_paths: tuple[str, ...]
1232
+ initial_score: float = 0.0
1233
+ minimum_support_clusters: int = 2
1234
+ minimum_support_instances: int = 1
1235
+ policy_id: str = STRUCTURED_REFLECTION_PROJECTION_POLICY_ID
1236
+ policy_version: int = STRUCTURED_REFLECTION_PROJECTION_POLICY_VERSION
1237
+ definition_sha256: str = STRUCTURED_REFLECTION_PROJECTION_DEFINITION_SHA256
1238
+
1239
+ def __post_init__(self) -> None:
1240
+ if not isinstance(self.semantic_compiler, CampaignInsightSemanticCompiler):
1241
+ raise TypeError("semantic_compiler must implement its exact port")
1242
+ compiler = self.semantic_compiler
1243
+ if (
1244
+ type(compiler.policy_id) is not str
1245
+ or _TOKEN.fullmatch(compiler.policy_id) is None
1246
+ ):
1247
+ raise ValueError("semantic compiler policy_id must be canonical")
1248
+ if type(compiler.policy_version) is not int or compiler.policy_version <= 0:
1249
+ raise ValueError("semantic compiler policy_version must be positive")
1250
+ require_sha256(
1251
+ compiler.definition_sha256,
1252
+ "semantic_compiler.definition_sha256",
1253
+ )
1254
+ if type(self.scope) is not HypothesisAuditScope:
1255
+ raise TypeError("scope must be an exact HypothesisAuditScope")
1256
+ HypothesisAuditScope.__post_init__(self.scope)
1257
+ _canonical_tokens(
1258
+ self.applicable_operator_kinds,
1259
+ name="applicable_operator_kinds",
1260
+ pattern=_OPERATOR,
1261
+ )
1262
+ if (
1263
+ type(self.diagnostic_operator_kind) is not str
1264
+ or _OPERATOR.fullmatch(self.diagnostic_operator_kind) is None
1265
+ or self.diagnostic_operator_kind not in self.applicable_operator_kinds
1266
+ ):
1267
+ raise ValueError("diagnostic_operator_kind must be explicitly applicable")
1268
+ _canonical_tokens(
1269
+ self.diagnostic_editable_paths,
1270
+ name="diagnostic_editable_paths",
1271
+ pattern=_PATH,
1272
+ )
1273
+ if type(self.initial_score) is not float or not math.isfinite(
1274
+ self.initial_score
1275
+ ):
1276
+ raise TypeError("initial_score must be a finite canonical float")
1277
+ for name in ("minimum_support_clusters", "minimum_support_instances"):
1278
+ value = getattr(self, name)
1279
+ if type(value) is not int or value <= 0:
1280
+ raise ValueError(f"{name} must be a positive exact integer")
1281
+ if type(self.policy_id) is not str or _TOKEN.fullmatch(self.policy_id) is None:
1282
+ raise ValueError("policy_id must be canonical")
1283
+ if type(self.policy_version) is not int or self.policy_version != 1:
1284
+ raise ValueError("unsupported structured projection policy version")
1285
+ if self.definition_sha256 != (
1286
+ STRUCTURED_REFLECTION_PROJECTION_DEFINITION_SHA256
1287
+ ):
1288
+ raise ValueError("unsupported structured projection policy definition")
1289
+
1290
+ def _compile(
1291
+ self,
1292
+ *,
1293
+ draft: InsightDraft,
1294
+ contract: ReflectionInsightContract,
1295
+ lineage: InsightEvidenceLineage,
1296
+ ) -> CompiledCampaignInsightSemantics:
1297
+ compiled = self.semantic_compiler.compile(
1298
+ draft=draft,
1299
+ insight_contract=contract,
1300
+ evidence_lineage=lineage,
1301
+ )
1302
+ if type(compiled) is not CompiledCampaignInsightSemantics:
1303
+ raise TypeError("semantic compiler returned a foreign value")
1304
+ CompiledCampaignInsightSemantics.__post_init__(compiled)
1305
+ observed = (
1306
+ compiled.draft_content_sha256,
1307
+ compiled.insight_contract_identity_sha256,
1308
+ compiled.evidence_lineage_sha256,
1309
+ compiled.compiler_policy_id,
1310
+ compiled.compiler_policy_version,
1311
+ compiled.compiler_definition_sha256,
1312
+ )
1313
+ expected = (
1314
+ draft.content_sha256,
1315
+ contract.identity_sha256,
1316
+ lineage.identity_sha256,
1317
+ self.semantic_compiler.policy_id,
1318
+ self.semantic_compiler.policy_version,
1319
+ self.semantic_compiler.definition_sha256,
1320
+ )
1321
+ if observed != expected:
1322
+ raise ValueError("semantic compilation belongs to foreign inputs or policy")
1323
+ return compiled
1324
+
1325
+ def project(
1326
+ self,
1327
+ request: CampaignReflectionRequest,
1328
+ receipt: CampaignReflectionReceipt,
1329
+ result: FrozenJsonObject,
1330
+ ) -> CampaignReflectionLearningProjection:
1331
+ self.__post_init__()
1332
+ if type(request) is not CampaignReflectionRequest:
1333
+ raise TypeError("request must be an exact CampaignReflectionRequest")
1334
+ CampaignReflectionRequest.__post_init__(request)
1335
+ if type(receipt) is not CampaignReflectionReceipt:
1336
+ raise TypeError("receipt must be an exact CampaignReflectionReceipt")
1337
+ CampaignReflectionReceipt.__post_init__(receipt)
1338
+ if type(result) is not FrozenJsonObject or freeze_json(result) is not result:
1339
+ raise TypeError("result must be an exact frozen object")
1340
+ if (
1341
+ receipt.request_sha256 != request.request_sha256
1342
+ or receipt.quarantined_result != result
1343
+ ):
1344
+ raise ValueError("reflection receipt differs from request/result")
1345
+ if receipt.status is not CampaignReflectionStatus.COMPLETED:
1346
+ raise ValueError("failed reflection cannot enter campaign learning")
1347
+ if receipt.logical_agent_calls != 1:
1348
+ raise ValueError(
1349
+ "reflection learning record v1 requires exactly one agentic call"
1350
+ )
1351
+ record = CampaignReflectionLearningRecordCodec.decode(result)
1352
+ if (
1353
+ record.source_generation != request.wave.source_generation
1354
+ or record.source_generation != receipt.source_generation
1355
+ or record.source_stage_receipt_sha256 != request.source_stage.receipt_sha256
1356
+ or record.source_stage_receipt_sha256 != receipt.source_stage_receipt_sha256
1357
+ ):
1358
+ raise ValueError("reflection learning record names a foreign source stage")
1359
+ projected: list[CampaignReflectedInsightProjection] = []
1360
+ for draft in record.insights:
1361
+ lineage = record.lineage_for(draft)
1362
+ compiled = self._compile(
1363
+ draft=draft,
1364
+ contract=record.insight_contract,
1365
+ lineage=lineage,
1366
+ )
1367
+ predictions = tuple(
1368
+ HypothesisMetricPrediction(
1369
+ metric_id=value.metric_id,
1370
+ direction=value.direction,
1371
+ )
1372
+ for value in draft.effect_predictions
1373
+ )
1374
+ claim_strength = HypothesisClaimStrength(
1375
+ sufficiency=True,
1376
+ necessity=False,
1377
+ invariance=False,
1378
+ mechanistic_or_causal=(
1379
+ draft.insight_kind is ReflectionInsightKind.MECHANISTIC_CONJECTURE
1380
+ ),
1381
+ )
1382
+ template = CampaignSemanticAuditPlanTemplate(
1383
+ trigger=compiled.trigger,
1384
+ intervention=TypedInterventionSignature(
1385
+ affected_paths=draft.affected_paths,
1386
+ old_value_predicate=compiled.old_value_predicate,
1387
+ new_action=compiled.new_action,
1388
+ admissible_operator_families=self.applicable_operator_kinds,
1389
+ ),
1390
+ predictions=predictions,
1391
+ claim_strength=claim_strength,
1392
+ scope=self.scope,
1393
+ matcher_definition_sha256=compiled.matcher_definition_sha256,
1394
+ origin_cutoff_event_index=record.origin_cutoff_event_index,
1395
+ minimum_support_clusters=self.minimum_support_clusters,
1396
+ minimum_support_instances=self.minimum_support_instances,
1397
+ )
1398
+ projected.append(
1399
+ CampaignReflectedInsightProjection(
1400
+ draft=draft,
1401
+ evidence_lineage=lineage,
1402
+ semantic_audit_template=template,
1403
+ )
1404
+ )
1405
+ return CampaignReflectionLearningProjection(
1406
+ reflection_request_sha256=request.request_sha256,
1407
+ reflection_receipt_sha256=receipt.receipt_sha256,
1408
+ reflection_result_sha256=typed_json_sha256(result),
1409
+ insights=tuple(projected),
1410
+ applicable_operator_kinds=self.applicable_operator_kinds,
1411
+ diagnostic_operator_kind=self.diagnostic_operator_kind,
1412
+ diagnostic_editable_paths=self.diagnostic_editable_paths,
1413
+ initial_score=self.initial_score,
1414
+ projection_policy_id=self.policy_id,
1415
+ projection_policy_version=self.policy_version,
1416
+ projection_policy_definition_sha256=self.definition_sha256,
1417
+ )
1418
+
1419
+
1420
+ @dataclass(frozen=True, slots=True)
1421
+ class CampaignRuntimeReflectionRegistrationReceipt:
1422
+ reflection_receipt_sha256: str
1423
+ reflection_result_sha256: str
1424
+ projection: CampaignReflectionLearningProjection
1425
+ registration: CampaignInsightRegistrationReceipt
1426
+ references: tuple[InsightRef, ...]
1427
+ receipt_sha256: str = field(init=False)
1428
+
1429
+ def __post_init__(self) -> None:
1430
+ require_sha256(self.reflection_receipt_sha256, "reflection_receipt_sha256")
1431
+ require_sha256(self.reflection_result_sha256, "reflection_result_sha256")
1432
+ if type(self.projection) is not CampaignReflectionLearningProjection:
1433
+ raise TypeError("projection must be exact")
1434
+ CampaignReflectionLearningProjection.__post_init__(self.projection)
1435
+ if type(self.registration) is not CampaignInsightRegistrationReceipt:
1436
+ raise TypeError("registration must be exact")
1437
+ CampaignInsightRegistrationReceipt.__post_init__(self.registration)
1438
+ if (
1439
+ type(self.references) is not tuple
1440
+ or not self.references
1441
+ or any(type(value) is not InsightRef for value in self.references)
1442
+ ):
1443
+ raise ValueError("references must contain exact InsightRef values")
1444
+ if self.references != tuple(sorted(set(self.references))):
1445
+ raise ValueError("references must be unique and canonical")
1446
+ if (
1447
+ self.reflection_receipt_sha256 != self.projection.reflection_receipt_sha256
1448
+ or self.reflection_result_sha256 != self.projection.reflection_result_sha256
1449
+ or self.references != tuple(value[0] for value in self.registration.entries)
1450
+ ):
1451
+ raise ValueError("reflection registration evidence is not joined")
1452
+ object.__setattr__(
1453
+ self,
1454
+ "receipt_sha256",
1455
+ _hash(_REFLECTION_REGISTRATION_DOMAIN, self._unsigned_record()),
1456
+ )
1457
+
1458
+ def _unsigned_record(self) -> dict[str, object]:
1459
+ return {
1460
+ "schema_version": 1,
1461
+ "reflection_receipt_sha256": self.reflection_receipt_sha256,
1462
+ "reflection_result_sha256": self.reflection_result_sha256,
1463
+ "projection_sha256": self.projection.projection_sha256,
1464
+ "registration_receipt_sha256": self.registration.receipt_sha256,
1465
+ "references": [_reference_record(value) for value in self.references],
1466
+ "lifecycle_state": "quarantined",
1467
+ }
1468
+
1469
+ def to_record(self) -> dict[str, object]:
1470
+ return {**self._unsigned_record(), "receipt_sha256": self.receipt_sha256}
1471
+
1472
+
1473
+ @dataclass(frozen=True, slots=True)
1474
+ class CampaignDiagnosticExposureReceipt:
1475
+ campaign_admission_request_sha256: str
1476
+ barrier_generation: int
1477
+ reflection_receipt_sha256s: tuple[str, ...]
1478
+ registration_receipt_sha256s: tuple[str, ...]
1479
+ admission: CampaignDiagnosticAdmissionReceipt
1480
+ memory_admission: QuarantineTestAdmissionReceipt
1481
+ references: tuple[InsightRef, ...]
1482
+ receipt_sha256: str = field(init=False)
1483
+
1484
+ def __post_init__(self) -> None:
1485
+ require_sha256(
1486
+ self.campaign_admission_request_sha256,
1487
+ "campaign_admission_request_sha256",
1488
+ )
1489
+ for name in (
1490
+ "reflection_receipt_sha256s",
1491
+ "registration_receipt_sha256s",
1492
+ ):
1493
+ values = getattr(self, name)
1494
+ if type(values) is not tuple or not values:
1495
+ raise ValueError(f"{name} must be non-empty")
1496
+ for value in values:
1497
+ require_sha256(value, name)
1498
+ if values != tuple(sorted(set(values))):
1499
+ raise ValueError(f"{name} must be unique and canonical")
1500
+ if type(self.barrier_generation) is not int or self.barrier_generation <= 0:
1501
+ raise ValueError("barrier_generation must be positive")
1502
+ if type(self.admission) is not CampaignDiagnosticAdmissionReceipt:
1503
+ raise TypeError("admission must be exact")
1504
+ CampaignDiagnosticAdmissionReceipt.__post_init__(self.admission)
1505
+ if type(self.memory_admission) is not QuarantineTestAdmissionReceipt:
1506
+ raise TypeError("memory_admission must be exact")
1507
+ QuarantineTestAdmissionReceipt.__post_init__(self.memory_admission)
1508
+ if (
1509
+ type(self.references) is not tuple
1510
+ or not self.references
1511
+ or any(type(value) is not InsightRef for value in self.references)
1512
+ ):
1513
+ raise TypeError("references must contain exact InsightRef values")
1514
+ if self.references != tuple(sorted(set(self.references))):
1515
+ raise ValueError("references must be unique and canonical")
1516
+ if (
1517
+ self.admission.campaign_admission_request_sha256
1518
+ != self.campaign_admission_request_sha256
1519
+ or self.admission.admission_generation != self.barrier_generation
1520
+ or self.admission.references != self.references
1521
+ or self.memory_admission.references != self.references
1522
+ or self.admission.memory_admission_receipt_sha256
1523
+ != self.memory_admission.receipt_sha256
1524
+ or self.registration_receipt_sha256s
1525
+ != self.admission.registration_receipt_sha256s
1526
+ ):
1527
+ raise ValueError("diagnostic exposure evidence is not joined")
1528
+ object.__setattr__(
1529
+ self,
1530
+ "receipt_sha256",
1531
+ _hash(_DIAGNOSTIC_EXPOSURE_DOMAIN, self._unsigned_record()),
1532
+ )
1533
+
1534
+ def _unsigned_record(self) -> dict[str, object]:
1535
+ return {
1536
+ "schema_version": 1,
1537
+ "campaign_admission_request_sha256": (
1538
+ self.campaign_admission_request_sha256
1539
+ ),
1540
+ "barrier_generation": self.barrier_generation,
1541
+ "reflection_receipt_sha256s": list(self.reflection_receipt_sha256s),
1542
+ "registration_receipt_sha256s": list(self.registration_receipt_sha256s),
1543
+ "campaign_diagnostic_admission_receipt_sha256": (
1544
+ self.admission.receipt_sha256
1545
+ ),
1546
+ "memory_admission_receipt_sha256": self.memory_admission.receipt_sha256,
1547
+ "references": [_reference_record(value) for value in self.references],
1548
+ "scope": "controlled_future_testing_only",
1549
+ }
1550
+
1551
+ def to_record(self) -> dict[str, object]:
1552
+ return {**self._unsigned_record(), "receipt_sha256": self.receipt_sha256}
1553
+
1554
+
1555
+ @dataclass(frozen=True, slots=True)
1556
+ class _RuntimeGenerationLearningPreparation:
1557
+ audit: CampaignGenerationAuditPreparation
1558
+ learning: CampaignPreparedLearningBarrier | None
1559
+
1560
+ def __post_init__(self) -> None:
1561
+ if type(self.audit) is not CampaignGenerationAuditPreparation:
1562
+ raise TypeError("audit must be exact")
1563
+ CampaignGenerationAuditPreparation.__post_init__(self.audit)
1564
+ if self.learning is not None:
1565
+ if type(self.learning) is not CampaignPreparedLearningBarrier:
1566
+ raise TypeError("learning must be exact or None")
1567
+ CampaignPreparedLearningBarrier.__post_init__(self.learning)
1568
+ projection = self.audit.projection
1569
+ if projection is None:
1570
+ raise ValueError(
1571
+ "learning preparation requires a real audit projection"
1572
+ )
1573
+ if self.learning.audits != projection.audits:
1574
+ raise ValueError("learning preparation differs from real-gate audits")
1575
+
1576
+
1577
+ @dataclass(slots=True)
1578
+ class ClosedLoopCampaignLearningRuntime:
1579
+ """Real coordinator adapter behind campaign learning lifecycle hooks."""
1580
+
1581
+ learning: ClosedLoopCampaignLearning
1582
+ reflection_projection: CampaignReflectionLearningProjectionPort
1583
+ generation_auditor: TransactionalPortfolioGenerationAuditor
1584
+ _registrations: dict[str, CampaignRuntimeReflectionRegistrationReceipt] = field(
1585
+ init=False, default_factory=dict
1586
+ )
1587
+ _exposures: dict[str, CampaignDiagnosticExposureReceipt] = field(
1588
+ init=False,
1589
+ default_factory=dict,
1590
+ )
1591
+ _runtime_preparations: dict[str, _RuntimeGenerationLearningPreparation] = field(
1592
+ init=False, default_factory=dict
1593
+ )
1594
+
1595
+ def __post_init__(self) -> None:
1596
+ if type(self.learning) is not ClosedLoopCampaignLearning:
1597
+ raise TypeError("learning must be an exact ClosedLoopCampaignLearning")
1598
+ if not isinstance(
1599
+ self.reflection_projection,
1600
+ CampaignReflectionLearningProjectionPort,
1601
+ ):
1602
+ raise TypeError("reflection_projection must implement its port")
1603
+ if type(self.generation_auditor) is not TransactionalPortfolioGenerationAuditor:
1604
+ raise TypeError("generation_auditor must be exact")
1605
+ TransactionalPortfolioGenerationAuditor.__post_init__(self.generation_auditor)
1606
+ self._validate_port_identity(self.reflection_projection, "reflection")
1607
+
1608
+ @staticmethod
1609
+ def _validate_port_identity(port: object, name: str) -> None:
1610
+ policy_id = getattr(port, "policy_id", None)
1611
+ policy_version = getattr(port, "policy_version", None)
1612
+ definition_sha256 = getattr(port, "definition_sha256", None)
1613
+ if type(policy_id) is not str or _TOKEN.fullmatch(policy_id) is None:
1614
+ raise ValueError(f"{name} projection policy_id must be canonical")
1615
+ if type(policy_version) is not int or policy_version <= 0:
1616
+ raise ValueError(f"{name} projection policy_version must be positive")
1617
+ require_sha256(definition_sha256, f"{name} projection definition_sha256")
1618
+
1619
+ def reflection_completed(
1620
+ self,
1621
+ request: CampaignReflectionRequest,
1622
+ receipt: CampaignReflectionReceipt,
1623
+ result: FrozenJsonObject,
1624
+ ) -> FrozenJsonObject:
1625
+ self.__post_init__()
1626
+ if type(request) is not CampaignReflectionRequest:
1627
+ raise TypeError("request must be exact")
1628
+ CampaignReflectionRequest.__post_init__(request)
1629
+ if type(receipt) is not CampaignReflectionReceipt:
1630
+ raise TypeError("receipt must be exact")
1631
+ CampaignReflectionReceipt.__post_init__(receipt)
1632
+ if type(result) is not FrozenJsonObject or freeze_json(result) is not result:
1633
+ raise TypeError("result must be an exact frozen object")
1634
+ result_sha256 = typed_json_sha256(result)
1635
+ if (
1636
+ receipt.request_sha256 != request.request_sha256
1637
+ or receipt.quarantined_result != result
1638
+ ):
1639
+ raise ValueError("reflection receipt differs from request/result")
1640
+ if receipt.receipt_sha256 in self._registrations:
1641
+ raise ValueError("reflection receipt was already registered")
1642
+ projection = self.reflection_projection.project(request, receipt, result)
1643
+ if type(projection) is not CampaignReflectionLearningProjection:
1644
+ raise TypeError("reflection projector returned a foreign value")
1645
+ CampaignReflectionLearningProjection.__post_init__(projection)
1646
+ expected_identity = (
1647
+ self.reflection_projection.policy_id,
1648
+ self.reflection_projection.policy_version,
1649
+ self.reflection_projection.definition_sha256,
1650
+ )
1651
+ observed_identity = (
1652
+ projection.projection_policy_id,
1653
+ projection.projection_policy_version,
1654
+ projection.projection_policy_definition_sha256,
1655
+ )
1656
+ if (
1657
+ projection.reflection_request_sha256 != request.request_sha256
1658
+ or projection.reflection_receipt_sha256 != receipt.receipt_sha256
1659
+ or projection.reflection_result_sha256 != result_sha256
1660
+ or observed_identity != expected_identity
1661
+ ):
1662
+ raise ValueError("reflection learning projection is foreign")
1663
+ entries = self.learning.memory.add_reflection_batch(
1664
+ tuple(
1665
+ ReflectedInsightBatchItem(value.draft, value.evidence_lineage)
1666
+ for value in projection.insights
1667
+ ),
1668
+ initial_score=projection.initial_score,
1669
+ applicable_operator_kinds=projection.applicable_operator_kinds,
1670
+ )
1671
+ plans = tuple(
1672
+ item.semantic_audit_template.bind(entry)
1673
+ for item, entry in zip(projection.insights, entries, strict=True)
1674
+ )
1675
+ registration = self.learning.register_quarantined_reflections(
1676
+ origin_generation=request.wave.source_generation,
1677
+ references=tuple(entry.reference for entry in entries),
1678
+ semantic_audit_plans=plans,
1679
+ )
1680
+ registered = CampaignRuntimeReflectionRegistrationReceipt(
1681
+ reflection_receipt_sha256=receipt.receipt_sha256,
1682
+ reflection_result_sha256=result_sha256,
1683
+ projection=projection,
1684
+ registration=registration,
1685
+ references=tuple(sorted(entry.reference for entry in entries)),
1686
+ )
1687
+ self._registrations[receipt.receipt_sha256] = registered
1688
+ return _object(registered.to_record())
1689
+
1690
+ def reflections_admitted(
1691
+ self,
1692
+ request: CampaignReflectionTestAdmissionRequest,
1693
+ contents: tuple[
1694
+ tuple[CampaignReflectionReceipt, FrozenJsonObject],
1695
+ ...,
1696
+ ],
1697
+ ) -> FrozenJsonObject:
1698
+ self.__post_init__()
1699
+ if type(request) is not CampaignReflectionTestAdmissionRequest:
1700
+ raise TypeError("request must be exact")
1701
+ CampaignReflectionTestAdmissionRequest.__post_init__(request)
1702
+ if type(contents) is not tuple or not contents:
1703
+ raise ValueError("contents must be a non-empty exact tuple")
1704
+ content_hashes = tuple(value[0].receipt_sha256 for value in contents)
1705
+ if content_hashes != tuple(sorted(set(content_hashes))):
1706
+ raise ValueError("contents must use canonical reflection receipt order")
1707
+ registrations: list[CampaignRuntimeReflectionRegistrationReceipt] = []
1708
+ for reflection, result in contents:
1709
+ if type(reflection) is not CampaignReflectionReceipt:
1710
+ raise TypeError("content reflection receipt must be exact")
1711
+ CampaignReflectionReceipt.__post_init__(reflection)
1712
+ if (
1713
+ type(result) is not FrozenJsonObject
1714
+ or freeze_json(result) is not result
1715
+ ):
1716
+ raise TypeError("content result must be frozen")
1717
+ registered = self._registrations.get(reflection.receipt_sha256)
1718
+ if registered is None:
1719
+ raise ValueError("reflection content was not registered")
1720
+ if (
1721
+ registered.reflection_result_sha256 != typed_json_sha256(result)
1722
+ or reflection.quarantined_result != result
1723
+ ):
1724
+ raise ValueError("admission content differs from registration")
1725
+ if reflection.receipt_sha256 in self._exposures:
1726
+ raise ValueError("reflection was already admitted")
1727
+ registrations.append(registered)
1728
+ diagnostic_scopes = {
1729
+ (
1730
+ value.projection.diagnostic_operator_kind,
1731
+ value.projection.diagnostic_editable_paths,
1732
+ )
1733
+ for value in registrations
1734
+ }
1735
+ if len(diagnostic_scopes) != 1:
1736
+ raise ValueError(
1737
+ "one atomic reflection barrier requires one diagnostic scope"
1738
+ )
1739
+ operator_kind, editable_paths = next(iter(diagnostic_scopes))
1740
+ references = tuple(
1741
+ sorted(
1742
+ reference
1743
+ for registered in registrations
1744
+ for reference in registered.references
1745
+ )
1746
+ )
1747
+ if len(set(references)) != len(references):
1748
+ raise ValueError("reflection barrier repeats an insight reference")
1749
+ admission = self.learning.admit_for_diagnostic_testing(
1750
+ admission_generation=request.barrier.generation,
1751
+ references=references,
1752
+ campaign_admission_request_sha256=request.request_sha256,
1753
+ operator_kind=operator_kind,
1754
+ editable_paths=editable_paths,
1755
+ )
1756
+ memory_admission = self.learning.memory.quarantine_test_admission_receipt(
1757
+ admission.memory_admission_receipt_sha256
1758
+ )
1759
+ exposure = CampaignDiagnosticExposureReceipt(
1760
+ campaign_admission_request_sha256=request.request_sha256,
1761
+ barrier_generation=request.barrier.generation,
1762
+ reflection_receipt_sha256s=content_hashes,
1763
+ registration_receipt_sha256s=tuple(
1764
+ sorted(value.registration.receipt_sha256 for value in registrations)
1765
+ ),
1766
+ admission=admission,
1767
+ memory_admission=memory_admission,
1768
+ references=admission.references,
1769
+ )
1770
+ for reflection_sha256 in content_hashes:
1771
+ self._exposures[reflection_sha256] = exposure
1772
+ return _object(
1773
+ {
1774
+ "schema_version": 1,
1775
+ "campaign_admission_request_sha256": request.request_sha256,
1776
+ "diagnostic_exposures": [exposure.to_record()],
1777
+ "normal_retrieval_mutated": False,
1778
+ }
1779
+ )
1780
+
1781
+ def diagnostic_exposure(
1782
+ self,
1783
+ reflection_receipt_sha256: str,
1784
+ ) -> CampaignDiagnosticExposureReceipt:
1785
+ require_sha256(reflection_receipt_sha256, "reflection_receipt_sha256")
1786
+ try:
1787
+ return self._exposures[reflection_receipt_sha256]
1788
+ except KeyError as exc:
1789
+ raise ValueError("reflection has no issued diagnostic exposure") from exc
1790
+
1791
+ def diagnostic_exposures(
1792
+ self,
1793
+ reflection_receipt_sha256s: tuple[str, ...],
1794
+ ) -> tuple[CampaignDiagnosticExposureReceipt, ...]:
1795
+ if reflection_receipt_sha256s != tuple(sorted(set(reflection_receipt_sha256s))):
1796
+ raise ValueError("reflection receipt hashes must be unique and canonical")
1797
+ by_receipt = {
1798
+ exposure.receipt_sha256: exposure
1799
+ for exposure in (
1800
+ self.diagnostic_exposure(value) for value in reflection_receipt_sha256s
1801
+ )
1802
+ }
1803
+ return tuple(by_receipt[value] for value in sorted(by_receipt))
1804
+
1805
+ def normal_references(self, **eligibility: object) -> tuple[InsightRef, ...]:
1806
+ """Expose only the memory bank's normal lifecycle-gated retrieval view."""
1807
+
1808
+ return self.learning.memory.eligible_references(**eligibility)
1809
+
1810
+ def _active_diagnostic_exposures(
1811
+ self,
1812
+ ) -> tuple[CampaignDiagnosticExposureReceipt, ...]:
1813
+ active: list[CampaignDiagnosticExposureReceipt] = []
1814
+ for exposure in {
1815
+ value.receipt_sha256: value for value in self._exposures.values()
1816
+ }.values():
1817
+ entries = self.learning.memory.entries_for(exposure.references)
1818
+ if any(
1819
+ entry.lifecycle_state is InsightLifecycleState.QUARANTINED
1820
+ for entry in entries
1821
+ ):
1822
+ active.append(exposure)
1823
+ return tuple(sorted(active, key=lambda value: value.receipt_sha256))
1824
+
1825
+ async def prepare_portfolio_generation_close(
1826
+ self,
1827
+ request: CampaignStageRequest,
1828
+ waves: tuple[PortfolioVariationWaveRequest, ...],
1829
+ results: tuple[PortfolioVariationWaveResult, ...],
1830
+ memory_credit_preparation: PortfolioMemoryCreditBatchPreparation,
1831
+ ) -> CampaignPortfolioLearningPreparation:
1832
+ """Implement the runtime's pure prepare half without publishing state."""
1833
+
1834
+ self.__post_init__()
1835
+ if type(request) is not CampaignStageRequest:
1836
+ raise TypeError("request must be exact")
1837
+ CampaignStageRequest.__post_init__(request)
1838
+ if type(memory_credit_preparation) is not (
1839
+ PortfolioMemoryCreditBatchPreparation
1840
+ ):
1841
+ raise TypeError("memory_credit_preparation must be exact")
1842
+ PortfolioMemoryCreditBatchPreparation.__post_init__(memory_credit_preparation)
1843
+ if memory_credit_preparation.prepared_results != results:
1844
+ raise ValueError("learning results differ from memory preparation")
1845
+ wave_request_sha256s = tuple(
1846
+ value.selection_request.request_sha256 for value in waves
1847
+ )
1848
+ result_receipt_sha256s = tuple(
1849
+ value.receipt.receipt_sha256 for value in results
1850
+ )
1851
+ active = self._active_diagnostic_exposures()
1852
+ references = tuple(
1853
+ sorted(
1854
+ {
1855
+ entry.reference
1856
+ for exposure in active
1857
+ for entry in self.learning.memory.entries_for(exposure.references)
1858
+ if entry.lifecycle_state is InsightLifecycleState.QUARANTINED
1859
+ }
1860
+ )
1861
+ )
1862
+ entries = self.learning.memory.entries_for(references) if references else ()
1863
+ plans = self.learning.audit_plans_for(references) if references else ()
1864
+ audit_preparation = self.generation_auditor.prepare_generation_audit(
1865
+ request=request,
1866
+ waves=waves,
1867
+ results=results,
1868
+ memory_credit_preparation=memory_credit_preparation,
1869
+ entries=entries,
1870
+ plans=plans,
1871
+ )
1872
+ projection = audit_preparation.projection
1873
+ try:
1874
+ if projection is not None:
1875
+ batch = memory_credit_preparation.batch_receipt
1876
+ if batch is None: # Closed by the auditor; retained defensively.
1877
+ raise AssertionError("real audit projection lost its memory batch")
1878
+ prepared = self.learning.prepare_generation_close(
1879
+ memory_credit_batch=batch,
1880
+ audits=projection.audits,
1881
+ prospective_trials=memory_credit_preparation.expected_trials,
1882
+ )
1883
+ evidence = _object(
1884
+ {
1885
+ "schema_version": 2,
1886
+ "status": "prepared_closed_loop_learning_real_gate",
1887
+ "generation_audit_preparation": (audit_preparation.to_record()),
1888
+ "coordinator_preparation": prepared.to_record(),
1889
+ "lifecycle_publication_deferred": True,
1890
+ }
1891
+ )
1892
+ learning_preparation: CampaignPreparedLearningBarrier | None = prepared
1893
+ else:
1894
+ evidence = _object(
1895
+ {
1896
+ "schema_version": 2,
1897
+ "status": "evidence_append_prepared_no_diagnostic_assignment",
1898
+ "generation_audit_preparation": (audit_preparation.to_record()),
1899
+ "lifecycle_publication_deferred": False,
1900
+ }
1901
+ )
1902
+ learning_preparation = None
1903
+ internal = _RuntimeGenerationLearningPreparation(
1904
+ audit=audit_preparation,
1905
+ learning=learning_preparation,
1906
+ )
1907
+ runtime_preparation = CampaignPortfolioLearningPreparation(
1908
+ request_sha256=request.request_sha256,
1909
+ generation=request.step.generation,
1910
+ wave_request_sha256s=wave_request_sha256s,
1911
+ result_receipt_sha256s=result_receipt_sha256s,
1912
+ memory_credit_preparation_sha256=(
1913
+ memory_credit_preparation.preparation_sha256
1914
+ ),
1915
+ evidence=evidence,
1916
+ )
1917
+ if runtime_preparation.preparation_sha256 in self._runtime_preparations:
1918
+ raise ValueError("runtime learning preparation identity collided")
1919
+ except BaseException:
1920
+ self.generation_auditor.abort_generation_audit(audit_preparation)
1921
+ raise
1922
+ self._runtime_preparations[runtime_preparation.preparation_sha256] = internal
1923
+ return runtime_preparation
1924
+
1925
+ def commit_portfolio_generation_close(
1926
+ self,
1927
+ preparation: CampaignPortfolioLearningPreparation,
1928
+ ) -> None:
1929
+ """Publish only the already-sealed coordinator decision after memory."""
1930
+
1931
+ if type(preparation) is not CampaignPortfolioLearningPreparation:
1932
+ raise TypeError("preparation must be exact")
1933
+ CampaignPortfolioLearningPreparation.__post_init__(preparation)
1934
+ if preparation.preparation_sha256 not in self._runtime_preparations:
1935
+ raise ValueError("runtime learning preparation is absent")
1936
+ internal = self._runtime_preparations[preparation.preparation_sha256]
1937
+ if internal.learning is not None:
1938
+ self.learning.commit_generation_close(internal.learning)
1939
+ self.generation_auditor.commit_generation_audit(internal.audit)
1940
+ del self._runtime_preparations[preparation.preparation_sha256]
1941
+
1942
+ def abort_portfolio_generation_close(
1943
+ self,
1944
+ preparation: CampaignPortfolioLearningPreparation,
1945
+ ) -> None:
1946
+ """Discard transient preparation state without touching memory/lifecycle."""
1947
+
1948
+ if type(preparation) is not CampaignPortfolioLearningPreparation:
1949
+ raise TypeError("preparation must be exact")
1950
+ CampaignPortfolioLearningPreparation.__post_init__(preparation)
1951
+ internal = self._runtime_preparations.pop(
1952
+ preparation.preparation_sha256,
1953
+ None,
1954
+ )
1955
+ if internal is not None:
1956
+ self.generation_auditor.abort_generation_audit(internal.audit)
1957
+
1958
+
1959
+ __all__ = [
1960
+ "CAMPAIGN_REFLECTION_LEARNING_RECORD_KEY",
1961
+ "CampaignDiagnosticExposureReceipt",
1962
+ "CampaignGenerationAuditProjection",
1963
+ "CampaignInsightSemanticCompiler",
1964
+ "CampaignReflectedInsightProjection",
1965
+ "CampaignReflectionLearningRecord",
1966
+ "CampaignReflectionLearningRecordCodec",
1967
+ "CampaignReflectionLearningProjection",
1968
+ "CampaignReflectionLearningProjectionPort",
1969
+ "CampaignRuntimeReflectionRegistrationReceipt",
1970
+ "CampaignSemanticAuditPlanTemplate",
1971
+ "ClosedLoopCampaignLearningRuntime",
1972
+ "CompiledCampaignInsightSemantics",
1973
+ "STRUCTURED_REFLECTION_PROJECTION_DEFINITION_SHA256",
1974
+ "STRUCTURED_REFLECTION_PROJECTION_POLICY_ID",
1975
+ "STRUCTURED_REFLECTION_PROJECTION_POLICY_VERSION",
1976
+ "StructuredCampaignReflectionLearningProjector",
1977
+ ]