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.
- agent_evolve/__init__.py +722 -0
- agent_evolve/agentic.py +2800 -0
- agent_evolve/api.py +767 -0
- agent_evolve/application/__init__.py +1580 -0
- agent_evolve/application/action_allocation.py +744 -0
- agent_evolve/application/action_allocation_frame.py +347 -0
- agent_evolve/application/action_allocation_frame_commit.py +185 -0
- agent_evolve/application/action_allocation_frame_commit_v3.py +184 -0
- agent_evolve/application/action_allocation_frame_v3.py +338 -0
- agent_evolve/application/action_archive_value.py +497 -0
- agent_evolve/application/action_evidence_consistency.py +455 -0
- agent_evolve/application/action_forecast_partitioning.py +1471 -0
- agent_evolve/application/action_metric_projection.py +211 -0
- agent_evolve/application/action_role_value.py +680 -0
- agent_evolve/application/action_score_authorities.py +363 -0
- agent_evolve/application/action_structural_signature.py +116 -0
- agent_evolve/application/action_target_realization.py +402 -0
- agent_evolve/application/agentic_evolution.py +7734 -0
- agent_evolve/application/agentic_portfolio_residual_expert.py +835 -0
- agent_evolve/application/anchor_residual_identification.py +463 -0
- agent_evolve/application/archive_conditioned_action_target.py +208 -0
- agent_evolve/application/artifact_journal.py +246 -0
- agent_evolve/application/artifact_replay.py +347 -0
- agent_evolve/application/budgeted_optimizer.py +1828 -0
- agent_evolve/application/calibrated_campaign.py +485 -0
- agent_evolve/application/calibrated_current_prefix_forecast_opportunity.py +322 -0
- agent_evolve/application/calibrated_positive_gain_opportunity.py +1581 -0
- agent_evolve/application/campaign_capacity_recourse.py +254 -0
- agent_evolve/application/campaign_contextual_outcomes.py +119 -0
- agent_evolve/application/campaign_diagnostic_blocks.py +930 -0
- agent_evolve/application/campaign_evidence_registry.py +262 -0
- agent_evolve/application/campaign_execution.py +2537 -0
- agent_evolve/application/campaign_generation_audit.py +942 -0
- agent_evolve/application/campaign_learning.py +1812 -0
- agent_evolve/application/campaign_learning_runtime.py +1977 -0
- agent_evolve/application/campaign_search_phase.py +227 -0
- agent_evolve/application/campaign_selector_context_extension.py +220 -0
- agent_evolve/application/campaign_variation_envelope.py +649 -0
- agent_evolve/application/campaign_variation_trace.py +451 -0
- agent_evolve/application/candidate_archive_consequence.py +128 -0
- agent_evolve/application/causal_opportunity_portfolio_gate.py +385 -0
- agent_evolve/application/composite_outcome_updater.py +145 -0
- agent_evolve/application/composition_portfolio_selection.py +363 -0
- agent_evolve/application/concurrent_stage.py +144 -0
- agent_evolve/application/contextual_action_allocation.py +181 -0
- agent_evolve/application/contextual_campaign_outcomes.py +267 -0
- agent_evolve/application/contextual_campaign_planning.py +1366 -0
- agent_evolve/application/contextual_delayed_credit.py +651 -0
- agent_evolve/application/contextual_search_controller.py +2374 -0
- agent_evolve/application/current_prefix_forecast_opportunity.py +714 -0
- agent_evolve/application/decision_metric_projection.py +112 -0
- agent_evolve/application/derived_action_semantics.py +129 -0
- agent_evolve/application/detailed_evaluation.py +449 -0
- agent_evolve/application/earned_lineage.py +1011 -0
- agent_evolve/application/effective_choice_audit.py +484 -0
- agent_evolve/application/empirical_consequence_calibration.py +908 -0
- agent_evolve/application/evaluation_accounting.py +325 -0
- agent_evolve/application/evaluation_cache.py +199 -0
- agent_evolve/application/evaluation_escrow.py +547 -0
- agent_evolve/application/evaluation_recourse.py +253 -0
- agent_evolve/application/event_recorder.py +151 -0
- agent_evolve/application/evolution_campaign.py +1840 -0
- agent_evolve/application/executable_hypothesis.py +323 -0
- agent_evolve/application/factorial_branch_pilot.py +772 -0
- agent_evolve/application/finite_acquisition_capacity_recourse.py +672 -0
- agent_evolve/application/finite_acquisition_residual_expert.py +373 -0
- agent_evolve/application/finite_acquisition_variation_envelope.py +802 -0
- agent_evolve/application/finite_action_hypothesis_semantics.py +446 -0
- agent_evolve/application/finite_action_selection.py +188 -0
- agent_evolve/application/finite_action_set.py +306 -0
- agent_evolve/application/finite_action_transition.py +537 -0
- agent_evolve/application/finite_variation_eligibility.py +296 -0
- agent_evolve/application/forecast_geometry_portfolio.py +799 -0
- agent_evolve/application/forecast_opportunity_shadow_calibration.py +316 -0
- agent_evolve/application/front_proximity_admission.py +311 -0
- agent_evolve/application/front_proximity_parent_basis.py +458 -0
- agent_evolve/application/frozen_hurdle_score.py +659 -0
- agent_evolve/application/g3_causal_screen.py +2257 -0
- agent_evolve/application/g3_causal_validation.py +1046 -0
- agent_evolve/application/g3_postseal_curation.py +818 -0
- agent_evolve/application/gated_agentic_generator.py +205 -0
- agent_evolve/application/generation_feedback.py +293 -0
- agent_evolve/application/generative_proposal_journal.py +185 -0
- agent_evolve/application/geometry_conditional_elasticity.py +453 -0
- agent_evolve/application/global_wave_action_allocation.py +1151 -0
- agent_evolve/application/head_mass_conditional_seat.py +268 -0
- agent_evolve/application/identifiable_reflection_evidence.py +1147 -0
- agent_evolve/application/identifiable_reflection_learning.py +395 -0
- agent_evolve/application/identifiable_reflection_request.py +364 -0
- agent_evolve/application/in_memory_residual_archive.py +341 -0
- agent_evolve/application/insight_memory.py +1804 -0
- agent_evolve/application/live_runtime_manifest.py +758 -0
- agent_evolve/application/llm_task_queue.py +769 -0
- agent_evolve/application/matched_finite_action_block.py +409 -0
- agent_evolve/application/materialized_action_broker.py +2328 -0
- agent_evolve/application/materialized_action_constraints.py +83 -0
- agent_evolve/application/materialized_variation.py +211 -0
- agent_evolve/application/multi_option_evolution.py +1536 -0
- agent_evolve/application/outcome_adaptive_action_racing.py +2827 -0
- agent_evolve/application/outcome_adaptive_residual_campaign_runtime.py +580 -0
- agent_evolve/application/outcome_adaptive_residual_portfolio_evolution.py +3671 -0
- agent_evolve/application/outcome_conditioned_portfolio_selection.py +1374 -0
- agent_evolve/application/outcome_relation.py +193 -0
- agent_evolve/application/paired_allocation_comparison.py +241 -0
- agent_evolve/application/paired_block_schedule.py +127 -0
- agent_evolve/application/parent_measurement.py +226 -0
- agent_evolve/application/pareto_archive.py +811 -0
- agent_evolve/application/portfolio_campaign_runtime.py +4739 -0
- agent_evolve/application/portfolio_evolution.py +2950 -0
- agent_evolve/application/portfolio_hypothesis_observations.py +814 -0
- agent_evolve/application/portfolio_memory_attribution.py +581 -0
- agent_evolve/application/portfolio_memory_dose.py +788 -0
- agent_evolve/application/portfolio_memory_matched_control.py +938 -0
- agent_evolve/application/portfolio_memory_transfer.py +297 -0
- agent_evolve/application/portfolio_optimization_memory.py +363 -0
- agent_evolve/application/portfolio_outcome_feedback.py +1613 -0
- agent_evolve/application/portfolio_projection.py +335 -0
- agent_evolve/application/portfolio_recombination.py +2032 -0
- agent_evolve/application/post_evolution_reflection.py +834 -0
- agent_evolve/application/postcommit_rank_authority.py +245 -0
- agent_evolve/application/precommitted_portfolio_racing.py +2762 -0
- agent_evolve/application/prequential_archive_opportunity_calibration.py +1154 -0
- agent_evolve/application/prequential_residual_exploration.py +343 -0
- agent_evolve/application/prequential_score_portfolio.py +954 -0
- agent_evolve/application/projections.py +292 -0
- agent_evolve/application/protected_action_committee.py +1027 -0
- agent_evolve/application/protected_branch_pilot.py +376 -0
- agent_evolve/application/protected_current_prefix_forecast_opportunity.py +552 -0
- agent_evolve/application/provider_replay.py +910 -0
- agent_evolve/application/rank_balanced_causal_pilot.py +1372 -0
- agent_evolve/application/recombination_residual_expert.py +403 -0
- agent_evolve/application/reflection_workflow.py +571 -0
- agent_evolve/application/region_conditional_credit.py +911 -0
- agent_evolve/application/residual_campaign_runtime.py +531 -0
- agent_evolve/application/residual_headroom_campaign_runtime.py +459 -0
- agent_evolve/application/residual_headroom_ledger.py +1544 -0
- agent_evolve/application/residual_learning_transaction.py +396 -0
- agent_evolve/application/residual_portfolio_evolution.py +1228 -0
- agent_evolve/application/residual_reachability.py +749 -0
- agent_evolve/application/residual_stage_credit.py +499 -0
- agent_evolve/application/same_prefix_paired_audit.py +1580 -0
- agent_evolve/application/semantic_coverage_score_portfolio.py +838 -0
- agent_evolve/application/sequential_lineage_allocation.py +1017 -0
- agent_evolve/application/sequential_market_replay.py +1395 -0
- agent_evolve/application/sequential_residual_campaign_runtime.py +305 -0
- agent_evolve/application/sequential_residual_portfolio_evolution.py +940 -0
- agent_evolve/application/single_score_action_allocation.py +299 -0
- agent_evolve/application/source_exposure_allocation.py +906 -0
- agent_evolve/application/staged_memory.py +210 -0
- agent_evolve/application/stratified_cold_start_allocation.py +732 -0
- agent_evolve/application/support_guarded_hurdle_score.py +549 -0
- agent_evolve/application/target_conditioned_action_forecast.py +595 -0
- agent_evolve/application/target_conditioned_campaign.py +566 -0
- agent_evolve/application/treatment_assignment.py +201 -0
- agent_evolve/application/trusted_objective_evidence.py +217 -0
- agent_evolve/application/two_stage_action_evolution.py +1131 -0
- agent_evolve/application/v8lite_allocation_policy.py +1083 -0
- agent_evolve/application/v9_candidate_policy.py +1303 -0
- agent_evolve/bootstrap.py +108 -0
- agent_evolve/campaign_presets.py +517 -0
- agent_evolve/campaign_profiles.py +452 -0
- agent_evolve/campaign_variation_topology.py +288 -0
- agent_evolve/campaign_workload.py +950 -0
- agent_evolve/cli.py +797 -0
- agent_evolve/contract.py +241 -0
- agent_evolve/core/__init__.py +91 -0
- agent_evolve/core/action_semantics.py +411 -0
- agent_evolve/core/authored.py +105 -0
- agent_evolve/core/formatting.py +286 -0
- agent_evolve/core/optimization_semantics.py +324 -0
- agent_evolve/core/problem.py +167 -0
- agent_evolve/core/results.py +323 -0
- agent_evolve/core/stats.py +70 -0
- agent_evolve/core/telemetry.py +100 -0
- agent_evolve/domain/__init__.py +89 -0
- agent_evolve/domain/artifact.py +162 -0
- agent_evolve/domain/durable_text.py +68 -0
- agent_evolve/domain/event.py +1454 -0
- agent_evolve/domain/finite_action_set.py +426 -0
- agent_evolve/domain/finite_variation.py +526 -0
- agent_evolve/domain/generative_emission.py +559 -0
- agent_evolve/domain/ids.py +163 -0
- agent_evolve/domain/inline_text.py +106 -0
- agent_evolve/domain/insight.py +27 -0
- agent_evolve/domain/lineage.py +737 -0
- agent_evolve/domain/llm_task_queue.py +960 -0
- agent_evolve/domain/outcome.py +96 -0
- agent_evolve/domain/patch.py +854 -0
- agent_evolve/domain/typed_json.py +542 -0
- agent_evolve/domain/variation_space.py +158 -0
- agent_evolve/driver.py +1014 -0
- agent_evolve/harness/__init__.py +29 -0
- agent_evolve/harness/base.py +242 -0
- agent_evolve/harness/directives.py +163 -0
- agent_evolve/harness/generative_seal.py +479 -0
- agent_evolve/harness/registry.py +41 -0
- agent_evolve/infrastructure/__init__.py +39 -0
- agent_evolve/infrastructure/artifacts/__init__.py +6 -0
- agent_evolve/infrastructure/artifacts/_verification.py +67 -0
- agent_evolve/infrastructure/artifacts/filesystem.py +343 -0
- agent_evolve/infrastructure/artifacts/in_memory.py +73 -0
- agent_evolve/infrastructure/asyncio_runtime.py +109 -0
- agent_evolve/infrastructure/authored_runtime.py +188 -0
- agent_evolve/infrastructure/authored_worker.py +171 -0
- agent_evolve/infrastructure/clock.py +53 -0
- agent_evolve/infrastructure/events/__init__.py +6 -0
- agent_evolve/infrastructure/events/_validation.py +89 -0
- agent_evolve/infrastructure/events/in_memory.py +56 -0
- agent_evolve/infrastructure/events/jsonl.py +193 -0
- agent_evolve/infrastructure/exception_provenance.py +215 -0
- agent_evolve/infrastructure/ids.py +118 -0
- agent_evolve/infrastructure/lineage_codec.py +1836 -0
- agent_evolve/infrastructure/outcome_adaptive_phase_journal.py +170 -0
- agent_evolve/infrastructure/residual_headroom_journal.py +221 -0
- agent_evolve/infrastructure/resource_lease.py +370 -0
- agent_evolve/infrastructure/sanitization/__init__.py +8 -0
- agent_evolve/infrastructure/sanitization/strict_json.py +484 -0
- agent_evolve/infrastructure/sequential_phase_journal.py +170 -0
- agent_evolve/infrastructure/stream_liveness.py +383 -0
- agent_evolve/infrastructure/subprocess_boundary.py +136 -0
- agent_evolve/integrations/__init__.py +1 -0
- agent_evolve/integrations/botorch/__init__.py +28 -0
- agent_evolve/integrations/botorch/finite_qlognehvi.py +190 -0
- agent_evolve/integrations/botorch/finite_qlognehvi_batch.py +155 -0
- agent_evolve/integrations/botorch/finite_qlognehvi_batch_identity.py +20 -0
- agent_evolve/integrations/botorch/finite_qlognehvi_batch_worker.py +55 -0
- agent_evolve/integrations/botorch/finite_qlognehvi_identity.py +22 -0
- agent_evolve/integrations/botorch/finite_qlognehvi_worker.py +55 -0
- agent_evolve/integrations/botorch/subprocess_qlognehvi.py +261 -0
- agent_evolve/integrations/botorch/subprocess_qlognehvi_batch.py +273 -0
- agent_evolve/integrations/completion.py +242 -0
- agent_evolve/integrations/pydantic_ai/__init__.py +441 -0
- agent_evolve/integrations/pydantic_ai/action_forecast.py +1068 -0
- agent_evolve/integrations/pydantic_ai/agentic_generator.py +2308 -0
- agent_evolve/integrations/pydantic_ai/async_generator.py +1604 -0
- agent_evolve/integrations/pydantic_ai/boundary_codec.py +1526 -0
- agent_evolve/integrations/pydantic_ai/calibrated_portfolio_campaign.py +756 -0
- agent_evolve/integrations/pydantic_ai/calibrated_portfolio_selection.py +7537 -0
- agent_evolve/integrations/pydantic_ai/campaign_acquisition.py +609 -0
- agent_evolve/integrations/pydantic_ai/execution_binding.py +138 -0
- agent_evolve/integrations/pydantic_ai/forecast_geometry_action_committee.py +217 -0
- agent_evolve/integrations/pydantic_ai/harness.py +159 -0
- agent_evolve/integrations/pydantic_ai/heterogeneous_model_execution.py +306 -0
- agent_evolve/integrations/pydantic_ai/hierarchical_residual_adaptive_semantic_view.py +179 -0
- agent_evolve/integrations/pydantic_ai/json_schema_dialect.py +108 -0
- agent_evolve/integrations/pydantic_ai/materialized_hierarchical_residual_expert.py +952 -0
- agent_evolve/integrations/pydantic_ai/materialized_portfolio_judge.py +520 -0
- agent_evolve/integrations/pydantic_ai/model_execution_profile.py +659 -0
- agent_evolve/integrations/pydantic_ai/outbound_request_manifest.py +1170 -0
- agent_evolve/integrations/pydantic_ai/portable_residual_consequence_features.py +575 -0
- agent_evolve/integrations/pydantic_ai/portfolio_selection.py +422 -0
- agent_evolve/integrations/pydantic_ai/progress_aware_openrouter.py +416 -0
- agent_evolve/integrations/pydantic_ai/provider_attempt_join.py +1523 -0
- agent_evolve/integrations/pydantic_ai/provider_free_calibrated_runner.py +607 -0
- agent_evolve/integrations/pydantic_ai/queued_runner.py +2634 -0
- agent_evolve/integrations/pydantic_ai/reconciled_residual_reachability.py +1417 -0
- agent_evolve/integrations/pydantic_ai/residual_forecast_geometry.py +445 -0
- agent_evolve/integrations/pydantic_ai/residual_reachability.py +674 -0
- agent_evolve/integrations/pydantic_ai/residual_semantic_cells.py +239 -0
- agent_evolve/integrations/pydantic_ai/sealed_output_replay.py +1068 -0
- agent_evolve/integrations/pydantic_ai/semantic_coverage_residual_portfolio.py +770 -0
- agent_evolve/integrations/pydantic_ai/semantic_decision_replay.py +383 -0
- agent_evolve/integrations/pydantic_ai/support_adaptive_residual_portfolio.py +135 -0
- agent_evolve/integrations/pydantic_ai/trusted_residual_prompt_context.py +143 -0
- agent_evolve/integrations/pydantic_ai/validated_openrouter_model.py +107 -0
- agent_evolve/integrations/pymoo_adapter.py +242 -0
- agent_evolve/policies/__init__.py +17 -0
- agent_evolve/policies/check.py +469 -0
- agent_evolve/policies/emit_scaffold.py +451 -0
- agent_evolve/policies/feedback/__init__.py +37 -0
- agent_evolve/policies/feedback/held_out_asn.py +1325 -0
- agent_evolve/policies/genetic.py +607 -0
- agent_evolve/policies/llm_backoff.py +183 -0
- agent_evolve/policies/llm_chooser.py +226 -0
- agent_evolve/policies/llm_generator.py +1760 -0
- agent_evolve/policies/llm_init.py +267 -0
- agent_evolve/policies/llm_operator.py +109 -0
- agent_evolve/policies/llm_prior.py +194 -0
- agent_evolve/policies/llm_surrogate.py +334 -0
- agent_evolve/policies/measurement_evidence.py +704 -0
- agent_evolve/policies/memory/__init__.py +223 -0
- agent_evolve/policies/memory/balanced_subset_blocks.py +707 -0
- agent_evolve/policies/memory/compatibility_matching.py +593 -0
- agent_evolve/policies/memory/global_falsification.py +1841 -0
- agent_evolve/policies/memory/prompt_shape.py +503 -0
- agent_evolve/policies/memory/randomized_subset.py +714 -0
- agent_evolve/policies/memory/staged_causal.py +1270 -0
- agent_evolve/policies/memory/treatment_compliance.py +759 -0
- agent_evolve/policies/objective_resolution/__init__.py +17 -0
- agent_evolve/policies/objective_resolution/fixed_grid.py +364 -0
- agent_evolve/policies/operator_portfolio.py +407 -0
- agent_evolve/policies/reguidance.py +1133 -0
- agent_evolve/policies/reward/__init__.py +83 -0
- agent_evolve/policies/reward/affine_candidate_consequence.py +156 -0
- agent_evolve/policies/reward/affine_candidate_consequence_3d.py +159 -0
- agent_evolve/policies/reward/affine_hypervolume.py +490 -0
- agent_evolve/policies/reward/affine_hypervolume_3d.py +567 -0
- agent_evolve/policies/reward/contextual_marginal_utility.py +318 -0
- agent_evolve/policies/reward/frozen_archive.py +360 -0
- agent_evolve/policies/reward/frozen_wave_archive.py +368 -0
- agent_evolve/policies/search_state.py +208 -0
- agent_evolve/policies/selection/__init__.py +345 -0
- agent_evolve/policies/selection/acquisition_certified_slate.py +684 -0
- agent_evolve/policies/selection/affine_frontier_context.py +330 -0
- agent_evolve/policies/selection/affine_frontier_target.py +473 -0
- agent_evolve/policies/selection/archive_elite.py +1346 -0
- agent_evolve/policies/selection/calibrated_portfolio_binding.py +640 -0
- agent_evolve/policies/selection/calibrated_slate.py +1394 -0
- agent_evolve/policies/selection/calibrated_slate_codec.py +579 -0
- agent_evolve/policies/selection/common_candidate_pool.py +685 -0
- agent_evolve/policies/selection/diagnostic_sampling.py +319 -0
- agent_evolve/policies/selection/disjoint_pairs.py +479 -0
- agent_evolve/policies/selection/elite_explorer.py +719 -0
- agent_evolve/policies/selection/finite_action.py +187 -0
- agent_evolve/policies/selection/finite_option_prompt_projection.py +377 -0
- agent_evolve/policies/selection/finite_palette_evidence.py +247 -0
- agent_evolve/policies/selection/forecast_calibration.py +922 -0
- agent_evolve/policies/selection/frontier_probe_slate.py +814 -0
- agent_evolve/policies/selection/frozen_archive_pairs.py +762 -0
- agent_evolve/policies/selection/full_support_slate.py +91 -0
- agent_evolve/policies/selection/meaningful_direction.py +240 -0
- agent_evolve/policies/selection/memory_dose_feasibility.py +259 -0
- agent_evolve/policies/selection/model_anchored_slate.py +826 -0
- agent_evolve/policies/selection/phenotype_recourse.py +979 -0
- agent_evolve/policies/selection/proposal_support.py +368 -0
- agent_evolve/policies/selection/random_portfolio.py +254 -0
- agent_evolve/policies/selection/regret_bounded_slate.py +1084 -0
- agent_evolve/policies/selection/residual_frontier.py +463 -0
- agent_evolve/policies/selection/residual_frontier_target.py +605 -0
- agent_evolve/policies/selection/structural_posterior_slate.py +1571 -0
- agent_evolve/policies/selection/target_conditioned_allocator.py +648 -0
- agent_evolve/policies/selection/target_conditioned_features.py +812 -0
- agent_evolve/policies/selection/target_conditioned_prequential.py +1527 -0
- agent_evolve/policies/selection/task_keyed_palette.py +906 -0
- agent_evolve/policies/semantics.py +147 -0
- agent_evolve/policies/structure.py +362 -0
- agent_evolve/policies/structured_output_budget.py +62 -0
- agent_evolve/policies/surrogate.py +696 -0
- agent_evolve/policies/variation/__init__.py +1 -0
- agent_evolve/policies/variation/compositional_finite_catalog.py +426 -0
- agent_evolve/policies/variation/crossover_inheritance.py +575 -0
- agent_evolve/policies/variation/disjoint_recombination.py +611 -0
- agent_evolve/policies/variation/exact_composition_capacity.py +214 -0
- agent_evolve/policies/variation/exact_parent_crossover.py +950 -0
- agent_evolve/policies/variation/multiscale_restart_catalog.py +372 -0
- agent_evolve/policies/variation/source_union_finite_catalog.py +403 -0
- agent_evolve/policies/variation/typed_patch.py +1981 -0
- agent_evolve/policies/weighted_prior.py +394 -0
- agent_evolve/ports/__init__.py +383 -0
- agent_evolve/ports/action_allocation.py +733 -0
- agent_evolve/ports/action_allocation_frame.py +1153 -0
- agent_evolve/ports/action_allocation_frame_commit.py +294 -0
- agent_evolve/ports/action_allocation_frame_commit_v3.py +432 -0
- agent_evolve/ports/action_allocation_frame_v3.py +995 -0
- agent_evolve/ports/action_forecast.py +1568 -0
- agent_evolve/ports/action_metric_projection.py +165 -0
- agent_evolve/ports/agentic_generator.py +1561 -0
- agent_evolve/ports/archive_context.py +136 -0
- agent_evolve/ports/artifact_sanitizer.py +44 -0
- agent_evolve/ports/artifact_store.py +225 -0
- agent_evolve/ports/clock.py +13 -0
- agent_evolve/ports/contextual_search_allocation.py +827 -0
- agent_evolve/ports/decision_metric_projection.py +258 -0
- agent_evolve/ports/event_store.py +55 -0
- agent_evolve/ports/executable_hypothesis.py +557 -0
- agent_evolve/ports/finite_acquisition.py +377 -0
- agent_evolve/ports/finite_acquisition_batch.py +296 -0
- agent_evolve/ports/finite_acquisition_batch_json.py +164 -0
- agent_evolve/ports/finite_acquisition_json.py +247 -0
- agent_evolve/ports/finite_acquisition_space.py +168 -0
- agent_evolve/ports/finite_action_selection.py +348 -0
- agent_evolve/ports/finite_action_set.py +256 -0
- agent_evolve/ports/frontier_target.py +396 -0
- agent_evolve/ports/generation_failure.py +43 -0
- agent_evolve/ports/hard_feasibility.py +233 -0
- agent_evolve/ports/id_factory.py +34 -0
- agent_evolve/ports/llm_task_queue.py +93 -0
- agent_evolve/ports/objective_resolution.py +419 -0
- agent_evolve/ports/paired_allocation_comparison.py +401 -0
- agent_evolve/ports/paired_block_schedule.py +475 -0
- agent_evolve/ports/parent_measurement.py +336 -0
- agent_evolve/ports/portfolio_memory_dose.py +643 -0
- agent_evolve/ports/portfolio_selection.py +3169 -0
- agent_evolve/ports/postcommit_rank_authority.py +467 -0
- agent_evolve/ports/presented_action_evidence.py +794 -0
- agent_evolve/ports/resource_lease.py +162 -0
- agent_evolve/ports/structured_generator.py +734 -0
- agent_evolve/ports/structured_output_budget.py +120 -0
- agent_evolve/ports/subprocess_boundary.py +138 -0
- agent_evolve/ports/treatment_assignment.py +466 -0
- agent_evolve/ports/variation_catalog.py +76 -0
- agent_evolve/ports/variation_source.py +226 -0
- agent_evolve/proposal_mode.py +157 -0
- agent_evolve/proposers/__init__.py +10 -0
- agent_evolve/proposers/random_proposer.py +188 -0
- agent_evolve/provider_accounting.py +163 -0
- agent_evolve/py.typed +0 -0
- agent_evolve/reference_method.py +1570 -0
- agent_evolve/session/__init__.py +11 -0
- agent_evolve/session/authorship.py +864 -0
- agent_evolve/session/evaluate.py +236 -0
- agent_evolve/session/fidelity.py +237 -0
- agent_evolve/session/genetic_loop.py +742 -0
- agent_evolve/session/loop.py +803 -0
- agent_evolve/session/screening.py +671 -0
- agent_evolve/settings.py +376 -0
- agent_evolve/workload_kit.py +368 -0
- agent_evolve/workload_prompt.py +398 -0
- agentevolve_optimizer-0.5.0.dist-info/METADATA +599 -0
- agentevolve_optimizer-0.5.0.dist-info/RECORD +414 -0
- agentevolve_optimizer-0.5.0.dist-info/WHEEL +5 -0
- agentevolve_optimizer-0.5.0.dist-info/entry_points.txt +2 -0
- agentevolve_optimizer-0.5.0.dist-info/licenses/LICENSE +21 -0
- agentevolve_optimizer-0.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,737 @@
|
|
|
1
|
+
"""Framework-free occurrence, parentage, and variation-case contracts."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import re
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from enum import Enum
|
|
9
|
+
|
|
10
|
+
from agent_evolve.domain.ids import CandidateId, InsightId, OperatorInvocationId
|
|
11
|
+
from agent_evolve.domain.insight import InsightRef
|
|
12
|
+
from agent_evolve.domain.patch import (
|
|
13
|
+
ArrayIndex,
|
|
14
|
+
JsonPath,
|
|
15
|
+
ObjectKey,
|
|
16
|
+
TypedPatch,
|
|
17
|
+
canonical_path_bytes,
|
|
18
|
+
require_sha256,
|
|
19
|
+
validate_json_path,
|
|
20
|
+
validate_typed_patch,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
_OPERATOR_TOKEN = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
|
|
25
|
+
MAX_REQUESTED_CHILDREN = 1024
|
|
26
|
+
MAX_SELECTED_INSIGHTS = 1024
|
|
27
|
+
MAX_PRESERVATION_OBLIGATIONS = 4096
|
|
28
|
+
_PRESERVATION_OBLIGATION_DOMAIN = b"agent-evolve:preservation-obligation:v1\x00"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class VariationKind(str, Enum):
|
|
32
|
+
REPRODUCTION = "reproduction"
|
|
33
|
+
TYPED_MUTATION = "typed_mutation"
|
|
34
|
+
TWO_PARENT_CROSSOVER = "two_parent_crossover"
|
|
35
|
+
THREE_WAY_RECOMBINATION = "three_way_recombination"
|
|
36
|
+
REPAIR = "repair"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ParentRole(str, Enum):
|
|
40
|
+
REPRODUCTION_SOURCE = "reproduction_source"
|
|
41
|
+
MUTATION_PARENT = "mutation_parent"
|
|
42
|
+
CROSSOVER_LEFT = "crossover_left"
|
|
43
|
+
CROSSOVER_RIGHT = "crossover_right"
|
|
44
|
+
COMMON_ANCESTOR = "common_ancestor"
|
|
45
|
+
REPAIR_TARGET = "repair_target"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class PreservationSource(str, Enum):
|
|
49
|
+
"""Exact branch provenance of one factory-derived preservation obligation."""
|
|
50
|
+
|
|
51
|
+
LEFT_BRANCH = "left_branch"
|
|
52
|
+
RIGHT_BRANCH = "right_branch"
|
|
53
|
+
IDENTICAL_NEUTRAL = "identical_neutral"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class PreservationExpectation(str, Enum):
|
|
57
|
+
PRESENT = "present"
|
|
58
|
+
ABSENT = "absent"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class AbsenceContextKind(str, Enum):
|
|
62
|
+
OBJECT = "object"
|
|
63
|
+
ARRAY = "array"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class AbsenceFailureKind(str, Enum):
|
|
67
|
+
MISSING_OBJECT_KEY = "missing_object_key"
|
|
68
|
+
ARRAY_INDEX_OUT_OF_BOUNDS = "array_index_out_of_bounds"
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _validate_candidate_id(value: CandidateId, name: str) -> None:
|
|
72
|
+
if type(value) is not CandidateId:
|
|
73
|
+
raise TypeError(f"{name} must be an exact CandidateId")
|
|
74
|
+
CandidateId.__post_init__(value)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _validate_operator_invocation_id(
|
|
78
|
+
value: OperatorInvocationId,
|
|
79
|
+
name: str,
|
|
80
|
+
) -> None:
|
|
81
|
+
if type(value) is not OperatorInvocationId:
|
|
82
|
+
raise TypeError(f"{name} must be an exact OperatorInvocationId")
|
|
83
|
+
OperatorInvocationId.__post_init__(value)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
87
|
+
class CandidateOccurrence:
|
|
88
|
+
"""One proposal occurrence, distinct even when candidate content repeats."""
|
|
89
|
+
|
|
90
|
+
candidate_id: CandidateId
|
|
91
|
+
configuration_hash: str
|
|
92
|
+
configuration_artifact_hash: str
|
|
93
|
+
proposal_sequence: int
|
|
94
|
+
operator_invocation_id: OperatorInvocationId | None = None
|
|
95
|
+
|
|
96
|
+
def __post_init__(self) -> None:
|
|
97
|
+
_validate_candidate_id(self.candidate_id, "candidate_id")
|
|
98
|
+
require_sha256(self.configuration_hash, "configuration_hash")
|
|
99
|
+
require_sha256(
|
|
100
|
+
self.configuration_artifact_hash,
|
|
101
|
+
"configuration_artifact_hash",
|
|
102
|
+
)
|
|
103
|
+
if type(self.proposal_sequence) is not int or self.proposal_sequence < 0:
|
|
104
|
+
raise ValueError("proposal_sequence must be a non-negative exact integer")
|
|
105
|
+
if self.operator_invocation_id is not None and type(
|
|
106
|
+
self.operator_invocation_id
|
|
107
|
+
) is not OperatorInvocationId:
|
|
108
|
+
raise TypeError(
|
|
109
|
+
"operator_invocation_id must be an exact OperatorInvocationId or None"
|
|
110
|
+
)
|
|
111
|
+
if self.operator_invocation_id is not None:
|
|
112
|
+
_validate_operator_invocation_id(
|
|
113
|
+
self.operator_invocation_id,
|
|
114
|
+
"operator_invocation_id",
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
def _validated_values(self) -> tuple[str, str, str, int, str | None]:
|
|
118
|
+
if type(self) is not CandidateOccurrence:
|
|
119
|
+
raise TypeError("occurrence must be an exact CandidateOccurrence")
|
|
120
|
+
CandidateOccurrence.__post_init__(self)
|
|
121
|
+
return (
|
|
122
|
+
self.candidate_id.value,
|
|
123
|
+
self.configuration_hash,
|
|
124
|
+
self.configuration_artifact_hash,
|
|
125
|
+
self.proposal_sequence,
|
|
126
|
+
None
|
|
127
|
+
if self.operator_invocation_id is None
|
|
128
|
+
else self.operator_invocation_id.value,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
def __eq__(self, other: object) -> bool:
|
|
132
|
+
if type(self) is not CandidateOccurrence or type(other) is not CandidateOccurrence:
|
|
133
|
+
return False
|
|
134
|
+
return self._validated_values() == other._validated_values()
|
|
135
|
+
|
|
136
|
+
__hash__ = None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
140
|
+
class VariationParent:
|
|
141
|
+
role: ParentRole
|
|
142
|
+
occurrence: CandidateOccurrence
|
|
143
|
+
|
|
144
|
+
def __post_init__(self) -> None:
|
|
145
|
+
if type(self.role) is not ParentRole:
|
|
146
|
+
raise TypeError("role must be a ParentRole")
|
|
147
|
+
if type(self.occurrence) is not CandidateOccurrence:
|
|
148
|
+
raise TypeError("occurrence must be an exact CandidateOccurrence")
|
|
149
|
+
CandidateOccurrence.__post_init__(self.occurrence)
|
|
150
|
+
if self.role is ParentRole.COMMON_ANCESTOR:
|
|
151
|
+
raise ValueError("common ancestors use VariationCase.common_ancestor")
|
|
152
|
+
|
|
153
|
+
def _validated_values(self) -> tuple[str, tuple[str, str, str, int, str | None]]:
|
|
154
|
+
if type(self) is not VariationParent:
|
|
155
|
+
raise TypeError("parent must be an exact VariationParent")
|
|
156
|
+
VariationParent.__post_init__(self)
|
|
157
|
+
return self.role.value, self.occurrence._validated_values()
|
|
158
|
+
|
|
159
|
+
def __eq__(self, other: object) -> bool:
|
|
160
|
+
if type(self) is not VariationParent or type(other) is not VariationParent:
|
|
161
|
+
return False
|
|
162
|
+
return self._validated_values() == other._validated_values()
|
|
163
|
+
|
|
164
|
+
__hash__ = None
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
168
|
+
class ParentEdge:
|
|
169
|
+
"""A verified occurrence edge carrying its exact parent-to-child patch."""
|
|
170
|
+
|
|
171
|
+
role: ParentRole
|
|
172
|
+
parent: CandidateOccurrence
|
|
173
|
+
child: CandidateOccurrence
|
|
174
|
+
patch: TypedPatch
|
|
175
|
+
|
|
176
|
+
def __post_init__(self) -> None:
|
|
177
|
+
if type(self.role) is not ParentRole:
|
|
178
|
+
raise TypeError("role must be a ParentRole")
|
|
179
|
+
if self.role is ParentRole.COMMON_ANCESTOR:
|
|
180
|
+
raise ValueError("COMMON_ANCESTOR is not a direct parent edge role")
|
|
181
|
+
if type(self.parent) is not CandidateOccurrence or type(
|
|
182
|
+
self.child
|
|
183
|
+
) is not CandidateOccurrence:
|
|
184
|
+
raise TypeError("parent and child must be exact CandidateOccurrence values")
|
|
185
|
+
CandidateOccurrence.__post_init__(self.parent)
|
|
186
|
+
CandidateOccurrence.__post_init__(self.child)
|
|
187
|
+
if self.parent.candidate_id == self.child.candidate_id:
|
|
188
|
+
raise ValueError("a lineage edge cannot be self-referential")
|
|
189
|
+
if self.parent.proposal_sequence >= self.child.proposal_sequence:
|
|
190
|
+
raise ValueError("a lineage edge must point to a later proposal sequence")
|
|
191
|
+
validate_typed_patch(self.patch)
|
|
192
|
+
if (
|
|
193
|
+
self.patch.base_candidate_id != self.parent.candidate_id
|
|
194
|
+
or self.patch.target_candidate_id != self.child.candidate_id
|
|
195
|
+
or self.patch.base_hash != self.parent.configuration_hash
|
|
196
|
+
or self.patch.target_hash != self.child.configuration_hash
|
|
197
|
+
):
|
|
198
|
+
raise ValueError("parent edge endpoints do not match its exact patch")
|
|
199
|
+
|
|
200
|
+
def __eq__(self, other: object) -> bool:
|
|
201
|
+
if type(self) is not ParentEdge or type(other) is not ParentEdge:
|
|
202
|
+
return False
|
|
203
|
+
ParentEdge.__post_init__(self)
|
|
204
|
+
ParentEdge.__post_init__(other)
|
|
205
|
+
return (
|
|
206
|
+
self.role.value,
|
|
207
|
+
self.parent._validated_values(),
|
|
208
|
+
self.child._validated_values(),
|
|
209
|
+
self.patch.patch_hash,
|
|
210
|
+
) == (
|
|
211
|
+
other.role.value,
|
|
212
|
+
other.parent._validated_values(),
|
|
213
|
+
other.child._validated_values(),
|
|
214
|
+
other.patch.patch_hash,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
__hash__ = None
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
221
|
+
class PreservationClaim:
|
|
222
|
+
"""An output claim referencing one immutable predeclared obligation."""
|
|
223
|
+
|
|
224
|
+
obligation_id: str
|
|
225
|
+
|
|
226
|
+
def __post_init__(self) -> None:
|
|
227
|
+
require_sha256(self.obligation_id, "obligation_id")
|
|
228
|
+
|
|
229
|
+
def __eq__(self, other: object) -> bool:
|
|
230
|
+
if type(self) is not PreservationClaim or type(other) is not PreservationClaim:
|
|
231
|
+
return False
|
|
232
|
+
PreservationClaim.__post_init__(self)
|
|
233
|
+
PreservationClaim.__post_init__(other)
|
|
234
|
+
return self.obligation_id == other.obligation_id
|
|
235
|
+
|
|
236
|
+
__hash__ = None
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
240
|
+
class PreservationObligation:
|
|
241
|
+
"""A replay-derived exact branch effect that a child is asked to preserve.
|
|
242
|
+
|
|
243
|
+
The identity binds the source branch patch, operation effect, three-way
|
|
244
|
+
relation, path, and both ancestor and expected presence-aware states. A
|
|
245
|
+
branch-specific obligation therefore cannot describe unchanged ancestor
|
|
246
|
+
content. Identical branch effects are represented once as neutral evidence
|
|
247
|
+
and never count as use of either individual parent.
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
source: PreservationSource
|
|
251
|
+
source_parent_candidate_ids: tuple[CandidateId, ...]
|
|
252
|
+
branch_patch_hashes: tuple[str, ...]
|
|
253
|
+
operation_effect_hashes: tuple[str, ...]
|
|
254
|
+
relation_id: str
|
|
255
|
+
path: JsonPath
|
|
256
|
+
expected_state: PreservationExpectation
|
|
257
|
+
expected_value_hash: str | None
|
|
258
|
+
ancestor_state: PreservationExpectation
|
|
259
|
+
ancestor_value_hash: str | None
|
|
260
|
+
absence_context_path: JsonPath | None = None
|
|
261
|
+
absence_context_kind: AbsenceContextKind | None = None
|
|
262
|
+
absence_context_shape_hash: str | None = None
|
|
263
|
+
absence_failure_kind: AbsenceFailureKind | None = None
|
|
264
|
+
|
|
265
|
+
def __post_init__(self) -> None:
|
|
266
|
+
if type(self.source) is not PreservationSource:
|
|
267
|
+
raise TypeError("source must be a PreservationSource")
|
|
268
|
+
if type(self.source_parent_candidate_ids) is not tuple:
|
|
269
|
+
raise TypeError("source_parent_candidate_ids must be an exact CandidateId tuple")
|
|
270
|
+
required_sources = (
|
|
271
|
+
2 if self.source is PreservationSource.IDENTICAL_NEUTRAL else 1
|
|
272
|
+
)
|
|
273
|
+
if len(self.source_parent_candidate_ids) != required_sources:
|
|
274
|
+
raise ValueError("preservation source has the wrong number of parent identities")
|
|
275
|
+
if any(
|
|
276
|
+
type(value) is not CandidateId
|
|
277
|
+
for value in self.source_parent_candidate_ids
|
|
278
|
+
):
|
|
279
|
+
raise TypeError("source_parent_candidate_ids must be an exact CandidateId tuple")
|
|
280
|
+
for value in self.source_parent_candidate_ids:
|
|
281
|
+
_validate_candidate_id(value, "source_parent_candidate_id")
|
|
282
|
+
if len(set(self.source_parent_candidate_ids)) != len(
|
|
283
|
+
self.source_parent_candidate_ids
|
|
284
|
+
):
|
|
285
|
+
raise ValueError("preservation source parent identities must be distinct")
|
|
286
|
+
for name, values in (
|
|
287
|
+
("branch_patch_hashes", self.branch_patch_hashes),
|
|
288
|
+
("operation_effect_hashes", self.operation_effect_hashes),
|
|
289
|
+
):
|
|
290
|
+
if type(values) is not tuple or len(values) != required_sources:
|
|
291
|
+
raise TypeError(f"{name} must be an exact tuple of source-aligned hashes")
|
|
292
|
+
for value in values:
|
|
293
|
+
require_sha256(value, name)
|
|
294
|
+
require_sha256(self.relation_id, "relation_id")
|
|
295
|
+
validate_json_path(self.path)
|
|
296
|
+
self._validate_state(
|
|
297
|
+
self.expected_state,
|
|
298
|
+
self.expected_value_hash,
|
|
299
|
+
name="expected",
|
|
300
|
+
)
|
|
301
|
+
self._validate_state(
|
|
302
|
+
self.ancestor_state,
|
|
303
|
+
self.ancestor_value_hash,
|
|
304
|
+
name="ancestor",
|
|
305
|
+
)
|
|
306
|
+
if (
|
|
307
|
+
self.expected_state is self.ancestor_state
|
|
308
|
+
and self.expected_value_hash == self.ancestor_value_hash
|
|
309
|
+
):
|
|
310
|
+
raise ValueError(
|
|
311
|
+
"a preservation obligation must bind an actual change from the ancestor"
|
|
312
|
+
)
|
|
313
|
+
absence_values = (
|
|
314
|
+
self.absence_context_path,
|
|
315
|
+
self.absence_context_kind,
|
|
316
|
+
self.absence_context_shape_hash,
|
|
317
|
+
self.absence_failure_kind,
|
|
318
|
+
)
|
|
319
|
+
if self.expected_state is PreservationExpectation.PRESENT:
|
|
320
|
+
if any(value is not None for value in absence_values):
|
|
321
|
+
raise ValueError(
|
|
322
|
+
"present preservation state cannot carry an absence-context receipt"
|
|
323
|
+
)
|
|
324
|
+
else:
|
|
325
|
+
if any(value is None for value in absence_values):
|
|
326
|
+
raise ValueError(
|
|
327
|
+
"absent preservation state requires a complete context receipt"
|
|
328
|
+
)
|
|
329
|
+
validate_json_path(self.absence_context_path) # type: ignore[arg-type]
|
|
330
|
+
if not self.absence_context_path.is_prefix_of(self.path) or len(
|
|
331
|
+
self.absence_context_path.segments
|
|
332
|
+
) >= len(self.path.segments):
|
|
333
|
+
raise ValueError(
|
|
334
|
+
"absence context must be a strict prefix of the obligation path"
|
|
335
|
+
)
|
|
336
|
+
if type(self.absence_context_kind) is not AbsenceContextKind:
|
|
337
|
+
raise TypeError("absence_context_kind must be an AbsenceContextKind")
|
|
338
|
+
if type(self.absence_failure_kind) is not AbsenceFailureKind:
|
|
339
|
+
raise TypeError("absence_failure_kind must be an AbsenceFailureKind")
|
|
340
|
+
require_sha256(
|
|
341
|
+
self.absence_context_shape_hash, # type: ignore[arg-type]
|
|
342
|
+
"absence_context_shape_hash",
|
|
343
|
+
)
|
|
344
|
+
failed_segment = self.path.segments[
|
|
345
|
+
len(self.absence_context_path.segments)
|
|
346
|
+
]
|
|
347
|
+
expected_pair = (
|
|
348
|
+
AbsenceContextKind.OBJECT,
|
|
349
|
+
AbsenceFailureKind.MISSING_OBJECT_KEY,
|
|
350
|
+
ObjectKey,
|
|
351
|
+
)
|
|
352
|
+
if self.absence_context_kind is AbsenceContextKind.ARRAY:
|
|
353
|
+
expected_pair = (
|
|
354
|
+
AbsenceContextKind.ARRAY,
|
|
355
|
+
AbsenceFailureKind.ARRAY_INDEX_OUT_OF_BOUNDS,
|
|
356
|
+
ArrayIndex,
|
|
357
|
+
)
|
|
358
|
+
if (
|
|
359
|
+
self.absence_context_kind is not expected_pair[0]
|
|
360
|
+
or self.absence_failure_kind is not expected_pair[1]
|
|
361
|
+
or type(failed_segment) is not expected_pair[2]
|
|
362
|
+
):
|
|
363
|
+
raise ValueError(
|
|
364
|
+
"absence receipt kind does not match its failing path segment"
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
@staticmethod
|
|
368
|
+
def _validate_state(
|
|
369
|
+
state: PreservationExpectation,
|
|
370
|
+
value_hash: str | None,
|
|
371
|
+
*,
|
|
372
|
+
name: str,
|
|
373
|
+
) -> None:
|
|
374
|
+
if type(state) is not PreservationExpectation:
|
|
375
|
+
raise TypeError(f"{name}_state must be a PreservationExpectation")
|
|
376
|
+
if state is PreservationExpectation.PRESENT:
|
|
377
|
+
if value_hash is None:
|
|
378
|
+
raise ValueError(f"{name} present state requires a value hash")
|
|
379
|
+
require_sha256(value_hash, f"{name}_value_hash")
|
|
380
|
+
elif value_hash is not None:
|
|
381
|
+
raise ValueError(f"{name} absent state cannot carry a value hash")
|
|
382
|
+
|
|
383
|
+
@property
|
|
384
|
+
def obligation_id(self) -> str:
|
|
385
|
+
if type(self) is not PreservationObligation:
|
|
386
|
+
raise TypeError("obligation must be an exact PreservationObligation")
|
|
387
|
+
PreservationObligation.__post_init__(self)
|
|
388
|
+
digest = hashlib.sha256()
|
|
389
|
+
digest.update(_PRESERVATION_OBLIGATION_DOMAIN)
|
|
390
|
+
digest.update(self.source.value.encode("ascii", errors="strict"))
|
|
391
|
+
digest.update(len(self.source_parent_candidate_ids).to_bytes(8, "big"))
|
|
392
|
+
for candidate_id in self.source_parent_candidate_ids:
|
|
393
|
+
encoded = candidate_id.value.encode("ascii", errors="strict")
|
|
394
|
+
digest.update(len(encoded).to_bytes(8, "big"))
|
|
395
|
+
digest.update(encoded)
|
|
396
|
+
for values in (self.branch_patch_hashes, self.operation_effect_hashes):
|
|
397
|
+
digest.update(len(values).to_bytes(8, "big"))
|
|
398
|
+
for value in values:
|
|
399
|
+
digest.update(bytes.fromhex(value))
|
|
400
|
+
digest.update(bytes.fromhex(self.relation_id))
|
|
401
|
+
path_bytes = canonical_path_bytes(self.path)
|
|
402
|
+
digest.update(len(path_bytes).to_bytes(8, "big"))
|
|
403
|
+
digest.update(path_bytes)
|
|
404
|
+
for state, value_hash in (
|
|
405
|
+
(self.expected_state, self.expected_value_hash),
|
|
406
|
+
(self.ancestor_state, self.ancestor_value_hash),
|
|
407
|
+
):
|
|
408
|
+
digest.update(state.value.encode("ascii", errors="strict"))
|
|
409
|
+
digest.update(b"\x00" if value_hash is None else b"\x01")
|
|
410
|
+
if value_hash is not None:
|
|
411
|
+
digest.update(bytes.fromhex(value_hash))
|
|
412
|
+
if self.absence_context_path is None:
|
|
413
|
+
digest.update(b"\x00")
|
|
414
|
+
else:
|
|
415
|
+
digest.update(b"\x01")
|
|
416
|
+
context_path = canonical_path_bytes(self.absence_context_path)
|
|
417
|
+
digest.update(len(context_path).to_bytes(8, "big"))
|
|
418
|
+
digest.update(context_path)
|
|
419
|
+
digest.update(self.absence_context_kind.value.encode("ascii"))
|
|
420
|
+
digest.update(bytes.fromhex(self.absence_context_shape_hash))
|
|
421
|
+
digest.update(self.absence_failure_kind.value.encode("ascii"))
|
|
422
|
+
return digest.hexdigest()
|
|
423
|
+
|
|
424
|
+
def __eq__(self, other: object) -> bool:
|
|
425
|
+
if (
|
|
426
|
+
type(self) is not PreservationObligation
|
|
427
|
+
or type(other) is not PreservationObligation
|
|
428
|
+
):
|
|
429
|
+
return False
|
|
430
|
+
PreservationObligation.__post_init__(self)
|
|
431
|
+
PreservationObligation.__post_init__(other)
|
|
432
|
+
return self.obligation_id == other.obligation_id
|
|
433
|
+
|
|
434
|
+
__hash__ = None
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def _validate_obligation_path_overlaps(
|
|
438
|
+
obligations: tuple[PreservationObligation, ...],
|
|
439
|
+
) -> None:
|
|
440
|
+
"""Reject parent-local equal/prefix paths in linear total path length."""
|
|
441
|
+
|
|
442
|
+
terminal = object()
|
|
443
|
+
roots: dict[CandidateId, dict[object, object]] = {}
|
|
444
|
+
for obligation in obligations:
|
|
445
|
+
for parent_id in obligation.source_parent_candidate_ids:
|
|
446
|
+
node = roots.setdefault(parent_id, {})
|
|
447
|
+
for segment in obligation.path.segments:
|
|
448
|
+
if terminal in node:
|
|
449
|
+
raise ValueError(
|
|
450
|
+
"preservation obligation paths cannot overlap within one parent"
|
|
451
|
+
)
|
|
452
|
+
child = node.setdefault(segment, {})
|
|
453
|
+
if type(child) is not dict: # pragma: no cover - local trie invariant.
|
|
454
|
+
raise AssertionError("invalid preservation-path trie")
|
|
455
|
+
node = child
|
|
456
|
+
if terminal in node or node:
|
|
457
|
+
raise ValueError(
|
|
458
|
+
"preservation obligation paths cannot overlap within one parent"
|
|
459
|
+
)
|
|
460
|
+
node[terminal] = True
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
464
|
+
class VariationCase:
|
|
465
|
+
"""Frozen causal inputs for one isolated variation-policy invocation.
|
|
466
|
+
|
|
467
|
+
This first slice deliberately contains no prompt, provider, evaluator, or
|
|
468
|
+
event object. Those identities remain a later application-layer concern.
|
|
469
|
+
"""
|
|
470
|
+
|
|
471
|
+
operator_invocation_id: OperatorInvocationId
|
|
472
|
+
variation_kind: VariationKind
|
|
473
|
+
operator_id: str
|
|
474
|
+
operator_version: int
|
|
475
|
+
parents: tuple[VariationParent, ...]
|
|
476
|
+
requested_child_count: int
|
|
477
|
+
context_stratum_hash: str
|
|
478
|
+
reward_definition_hash: str
|
|
479
|
+
common_ancestor: CandidateOccurrence | None = None
|
|
480
|
+
ancestor_to_parent_patches: tuple[TypedPatch, ...] = ()
|
|
481
|
+
selected_insights: tuple[InsightRef, ...] = ()
|
|
482
|
+
preservation_obligations: tuple[PreservationObligation, ...] = ()
|
|
483
|
+
|
|
484
|
+
def __post_init__(self) -> None:
|
|
485
|
+
_validate_operator_invocation_id(
|
|
486
|
+
self.operator_invocation_id,
|
|
487
|
+
"operator_invocation_id",
|
|
488
|
+
)
|
|
489
|
+
if type(self.variation_kind) is not VariationKind:
|
|
490
|
+
raise TypeError("variation_kind must be a VariationKind")
|
|
491
|
+
if type(self.operator_id) is not str or _OPERATOR_TOKEN.fullmatch(
|
|
492
|
+
self.operator_id
|
|
493
|
+
) is None:
|
|
494
|
+
raise ValueError("operator_id must use the closed lowercase token grammar")
|
|
495
|
+
if type(self.operator_version) is not int or self.operator_version <= 0:
|
|
496
|
+
raise ValueError("operator_version must be a positive exact integer")
|
|
497
|
+
if type(self.parents) is not tuple:
|
|
498
|
+
raise TypeError("parents must be an exact tuple of VariationParent values")
|
|
499
|
+
# Every closed variation kind consumes either one or two parents. Bound
|
|
500
|
+
# the container before inspecting its elements so an oversized hostile
|
|
501
|
+
# tuple cannot force an unbounded validation scan.
|
|
502
|
+
if not 1 <= len(self.parents) <= 2:
|
|
503
|
+
raise ValueError("parents must contain one or two variation parents")
|
|
504
|
+
if any(type(parent) is not VariationParent for parent in self.parents):
|
|
505
|
+
raise TypeError("parents must be an exact tuple of VariationParent values")
|
|
506
|
+
for parent in self.parents:
|
|
507
|
+
VariationParent.__post_init__(parent)
|
|
508
|
+
if type(self.requested_child_count) is not int:
|
|
509
|
+
raise TypeError("requested_child_count must be an exact integer")
|
|
510
|
+
if not 1 <= self.requested_child_count <= MAX_REQUESTED_CHILDREN:
|
|
511
|
+
raise ValueError(
|
|
512
|
+
f"requested_child_count must lie in [1, {MAX_REQUESTED_CHILDREN}]"
|
|
513
|
+
)
|
|
514
|
+
require_sha256(self.context_stratum_hash, "context_stratum_hash")
|
|
515
|
+
require_sha256(self.reward_definition_hash, "reward_definition_hash")
|
|
516
|
+
|
|
517
|
+
parent_ids = tuple(parent.occurrence.candidate_id for parent in self.parents)
|
|
518
|
+
roles = tuple(parent.role for parent in self.parents)
|
|
519
|
+
if len(set(parent_ids)) != len(parent_ids):
|
|
520
|
+
raise ValueError("variation parents must be distinct occurrences")
|
|
521
|
+
if len(set(roles)) != len(roles):
|
|
522
|
+
raise ValueError("variation parent roles must be unique")
|
|
523
|
+
expected_roles = {
|
|
524
|
+
VariationKind.REPRODUCTION: (ParentRole.REPRODUCTION_SOURCE,),
|
|
525
|
+
VariationKind.TYPED_MUTATION: (ParentRole.MUTATION_PARENT,),
|
|
526
|
+
VariationKind.TWO_PARENT_CROSSOVER: (
|
|
527
|
+
ParentRole.CROSSOVER_LEFT,
|
|
528
|
+
ParentRole.CROSSOVER_RIGHT,
|
|
529
|
+
),
|
|
530
|
+
VariationKind.THREE_WAY_RECOMBINATION: (
|
|
531
|
+
ParentRole.CROSSOVER_LEFT,
|
|
532
|
+
ParentRole.CROSSOVER_RIGHT,
|
|
533
|
+
),
|
|
534
|
+
VariationKind.REPAIR: (ParentRole.REPAIR_TARGET,),
|
|
535
|
+
}[self.variation_kind]
|
|
536
|
+
if roles != expected_roles:
|
|
537
|
+
raise ValueError(
|
|
538
|
+
"parents must appear in the exact role order required by variation_kind"
|
|
539
|
+
)
|
|
540
|
+
if any(
|
|
541
|
+
parent.occurrence.operator_invocation_id == self.operator_invocation_id
|
|
542
|
+
for parent in self.parents
|
|
543
|
+
):
|
|
544
|
+
raise ValueError(
|
|
545
|
+
"an operator invocation cannot consume an occurrence it produced itself"
|
|
546
|
+
)
|
|
547
|
+
|
|
548
|
+
if type(self.ancestor_to_parent_patches) is not tuple:
|
|
549
|
+
raise TypeError(
|
|
550
|
+
"ancestor_to_parent_patches must be an exact tuple of TypedPatch values"
|
|
551
|
+
)
|
|
552
|
+
if len(self.ancestor_to_parent_patches) > 2:
|
|
553
|
+
raise ValueError("ancestor_to_parent_patches cannot contain more than two patches")
|
|
554
|
+
if any(
|
|
555
|
+
type(patch) is not TypedPatch
|
|
556
|
+
for patch in self.ancestor_to_parent_patches
|
|
557
|
+
):
|
|
558
|
+
raise TypeError(
|
|
559
|
+
"ancestor_to_parent_patches must be an exact tuple of TypedPatch values"
|
|
560
|
+
)
|
|
561
|
+
for patch in self.ancestor_to_parent_patches:
|
|
562
|
+
validate_typed_patch(patch)
|
|
563
|
+
if self.variation_kind is VariationKind.THREE_WAY_RECOMBINATION:
|
|
564
|
+
if type(self.common_ancestor) is not CandidateOccurrence:
|
|
565
|
+
raise ValueError("three-way recombination requires one common ancestor")
|
|
566
|
+
CandidateOccurrence.__post_init__(self.common_ancestor)
|
|
567
|
+
if self.common_ancestor.candidate_id in parent_ids:
|
|
568
|
+
raise ValueError("common ancestor must be a distinct occurrence")
|
|
569
|
+
if self.common_ancestor.operator_invocation_id == self.operator_invocation_id:
|
|
570
|
+
raise ValueError(
|
|
571
|
+
"an operator invocation cannot consume its own common ancestor"
|
|
572
|
+
)
|
|
573
|
+
if any(
|
|
574
|
+
self.common_ancestor.proposal_sequence
|
|
575
|
+
>= parent.occurrence.proposal_sequence
|
|
576
|
+
for parent in self.parents
|
|
577
|
+
):
|
|
578
|
+
raise ValueError(
|
|
579
|
+
"common ancestor must precede both branch-parent occurrences"
|
|
580
|
+
)
|
|
581
|
+
if len(self.ancestor_to_parent_patches) != 2:
|
|
582
|
+
raise ValueError("three-way recombination requires exactly two branch patches")
|
|
583
|
+
if (
|
|
584
|
+
self.ancestor_to_parent_patches[0].limits
|
|
585
|
+
!= self.ancestor_to_parent_patches[1].limits
|
|
586
|
+
):
|
|
587
|
+
raise ValueError(
|
|
588
|
+
"three-way branch patches must share exact algebra limits"
|
|
589
|
+
)
|
|
590
|
+
expected_targets = parent_ids
|
|
591
|
+
actual_targets = tuple(
|
|
592
|
+
patch.target_candidate_id for patch in self.ancestor_to_parent_patches
|
|
593
|
+
)
|
|
594
|
+
if actual_targets != expected_targets:
|
|
595
|
+
raise ValueError("branch patches must follow left/right parent order")
|
|
596
|
+
for parent, patch in zip(
|
|
597
|
+
self.parents,
|
|
598
|
+
self.ancestor_to_parent_patches,
|
|
599
|
+
):
|
|
600
|
+
if (
|
|
601
|
+
patch.base_candidate_id != self.common_ancestor.candidate_id
|
|
602
|
+
or patch.base_hash != self.common_ancestor.configuration_hash
|
|
603
|
+
or patch.target_candidate_id != parent.occurrence.candidate_id
|
|
604
|
+
or patch.target_hash != parent.occurrence.configuration_hash
|
|
605
|
+
):
|
|
606
|
+
raise ValueError("ancestor branch patch endpoints do not match the case")
|
|
607
|
+
elif self.common_ancestor is not None or self.ancestor_to_parent_patches:
|
|
608
|
+
raise ValueError(
|
|
609
|
+
"common ancestor and branch patches are exclusive to three-way recombination"
|
|
610
|
+
)
|
|
611
|
+
|
|
612
|
+
if type(self.selected_insights) is not tuple:
|
|
613
|
+
raise TypeError("selected_insights must be an exact tuple of InsightRef values")
|
|
614
|
+
if len(self.selected_insights) > MAX_SELECTED_INSIGHTS:
|
|
615
|
+
raise ValueError("selected_insights exceeds MAX_SELECTED_INSIGHTS")
|
|
616
|
+
if any(type(reference) is not InsightRef for reference in self.selected_insights):
|
|
617
|
+
raise TypeError("selected_insights must be an exact tuple of InsightRef values")
|
|
618
|
+
for reference in self.selected_insights:
|
|
619
|
+
InsightRef.__post_init__(reference)
|
|
620
|
+
if type(reference.insight_id) is not InsightId:
|
|
621
|
+
raise TypeError("selected insight IDs must be exact InsightId values")
|
|
622
|
+
InsightId.__post_init__(reference.insight_id)
|
|
623
|
+
if len(set(self.selected_insights)) != len(self.selected_insights):
|
|
624
|
+
raise ValueError("selected_insights cannot contain duplicate exact versions")
|
|
625
|
+
|
|
626
|
+
if type(self.preservation_obligations) is not tuple:
|
|
627
|
+
raise TypeError(
|
|
628
|
+
"preservation_obligations must be an exact tuple of PreservationObligation values"
|
|
629
|
+
)
|
|
630
|
+
if len(self.preservation_obligations) > MAX_PRESERVATION_OBLIGATIONS:
|
|
631
|
+
raise ValueError(
|
|
632
|
+
"preservation_obligations exceeds MAX_PRESERVATION_OBLIGATIONS"
|
|
633
|
+
)
|
|
634
|
+
if any(
|
|
635
|
+
type(obligation) is not PreservationObligation
|
|
636
|
+
for obligation in self.preservation_obligations
|
|
637
|
+
):
|
|
638
|
+
raise TypeError(
|
|
639
|
+
"preservation_obligations must be an exact tuple of PreservationObligation values"
|
|
640
|
+
)
|
|
641
|
+
for obligation in self.preservation_obligations:
|
|
642
|
+
PreservationObligation.__post_init__(obligation)
|
|
643
|
+
if (
|
|
644
|
+
self.preservation_obligations
|
|
645
|
+
and self.variation_kind is not VariationKind.THREE_WAY_RECOMBINATION
|
|
646
|
+
):
|
|
647
|
+
raise ValueError(
|
|
648
|
+
"this slice admits preservation obligations only for verified three-way cases"
|
|
649
|
+
)
|
|
650
|
+
canonical_obligations = tuple(
|
|
651
|
+
sorted(
|
|
652
|
+
self.preservation_obligations,
|
|
653
|
+
key=lambda obligation: obligation.obligation_id,
|
|
654
|
+
)
|
|
655
|
+
)
|
|
656
|
+
if self.preservation_obligations != canonical_obligations:
|
|
657
|
+
raise ValueError(
|
|
658
|
+
"preservation_obligations must use canonical obligation-id order"
|
|
659
|
+
)
|
|
660
|
+
obligation_ids = tuple(
|
|
661
|
+
obligation.obligation_id for obligation in self.preservation_obligations
|
|
662
|
+
)
|
|
663
|
+
if len(set(obligation_ids)) != len(obligation_ids):
|
|
664
|
+
raise ValueError("preservation_obligations cannot duplicate an identity")
|
|
665
|
+
for obligation in self.preservation_obligations:
|
|
666
|
+
expected_source_ids = {
|
|
667
|
+
PreservationSource.LEFT_BRANCH: (parent_ids[0],),
|
|
668
|
+
PreservationSource.RIGHT_BRANCH: (parent_ids[1],),
|
|
669
|
+
PreservationSource.IDENTICAL_NEUTRAL: parent_ids,
|
|
670
|
+
}[obligation.source]
|
|
671
|
+
if obligation.source_parent_candidate_ids != expected_source_ids:
|
|
672
|
+
raise ValueError(
|
|
673
|
+
"preservation obligation branch provenance does not match case roles"
|
|
674
|
+
)
|
|
675
|
+
_validate_obligation_path_overlaps(self.preservation_obligations)
|
|
676
|
+
|
|
677
|
+
def __eq__(self, other: object) -> bool:
|
|
678
|
+
if type(self) is not VariationCase or type(other) is not VariationCase:
|
|
679
|
+
return False
|
|
680
|
+
VariationCase.__post_init__(self)
|
|
681
|
+
VariationCase.__post_init__(other)
|
|
682
|
+
|
|
683
|
+
def projection(value: VariationCase) -> tuple[object, ...]:
|
|
684
|
+
return (
|
|
685
|
+
value.operator_invocation_id.value,
|
|
686
|
+
value.variation_kind.value,
|
|
687
|
+
value.operator_id,
|
|
688
|
+
value.operator_version,
|
|
689
|
+
tuple(parent._validated_values() for parent in value.parents),
|
|
690
|
+
value.requested_child_count,
|
|
691
|
+
value.context_stratum_hash,
|
|
692
|
+
value.reward_definition_hash,
|
|
693
|
+
None
|
|
694
|
+
if value.common_ancestor is None
|
|
695
|
+
else value.common_ancestor._validated_values(),
|
|
696
|
+
tuple(patch.patch_hash for patch in value.ancestor_to_parent_patches),
|
|
697
|
+
tuple(
|
|
698
|
+
(reference.insight_id.value, reference.version)
|
|
699
|
+
for reference in value.selected_insights
|
|
700
|
+
),
|
|
701
|
+
tuple(
|
|
702
|
+
obligation.obligation_id
|
|
703
|
+
for obligation in value.preservation_obligations
|
|
704
|
+
),
|
|
705
|
+
)
|
|
706
|
+
|
|
707
|
+
return projection(self) == projection(other)
|
|
708
|
+
|
|
709
|
+
__hash__ = None
|
|
710
|
+
|
|
711
|
+
|
|
712
|
+
def validate_variation_case(value: VariationCase) -> None:
|
|
713
|
+
"""Revalidate the complete immutable variation-case graph."""
|
|
714
|
+
|
|
715
|
+
if type(value) is not VariationCase:
|
|
716
|
+
raise TypeError("variation_case must be an exact VariationCase")
|
|
717
|
+
VariationCase.__post_init__(value)
|
|
718
|
+
|
|
719
|
+
|
|
720
|
+
__all__ = [
|
|
721
|
+
"AbsenceContextKind",
|
|
722
|
+
"AbsenceFailureKind",
|
|
723
|
+
"MAX_PRESERVATION_OBLIGATIONS",
|
|
724
|
+
"MAX_REQUESTED_CHILDREN",
|
|
725
|
+
"MAX_SELECTED_INSIGHTS",
|
|
726
|
+
"CandidateOccurrence",
|
|
727
|
+
"ParentEdge",
|
|
728
|
+
"ParentRole",
|
|
729
|
+
"PreservationClaim",
|
|
730
|
+
"PreservationExpectation",
|
|
731
|
+
"PreservationObligation",
|
|
732
|
+
"PreservationSource",
|
|
733
|
+
"VariationCase",
|
|
734
|
+
"VariationKind",
|
|
735
|
+
"VariationParent",
|
|
736
|
+
"validate_variation_case",
|
|
737
|
+
]
|