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,762 @@
|
|
|
1
|
+
"""Archive-aware exploit and structural-coverage disjoint pair selection.
|
|
2
|
+
|
|
3
|
+
The legacy disjoint-pair policy ranks exploit pairs by parent-relative branch
|
|
4
|
+
rewards. Those rewards need not agree with multiobjective archive progress.
|
|
5
|
+
This module provides an opt-in policy that instead consumes an authenticated
|
|
6
|
+
table of marginal branch utilities and exact joint utilities for every pair of
|
|
7
|
+
*observed source branches*, all evaluated against one frozen pre-generation
|
|
8
|
+
archive snapshot.
|
|
9
|
+
|
|
10
|
+
The exploit key is the utility of adding both observed sources jointly to the
|
|
11
|
+
frozen archive. It is not the arithmetic sum of marginal utilities, which can
|
|
12
|
+
double-count overlapping archive gain. It is deliberately not represented as
|
|
13
|
+
a prediction of the unseen recombination child's utility. Coverage remains a
|
|
14
|
+
separately identified structural-diversity role.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from __future__ import annotations
|
|
18
|
+
|
|
19
|
+
import hashlib
|
|
20
|
+
import json
|
|
21
|
+
import math
|
|
22
|
+
import re
|
|
23
|
+
from dataclasses import dataclass
|
|
24
|
+
from itertools import combinations
|
|
25
|
+
from typing import ClassVar, Sequence
|
|
26
|
+
|
|
27
|
+
from agent_evolve.domain.ids import CandidateId
|
|
28
|
+
from agent_evolve.domain.patch import require_sha256
|
|
29
|
+
from agent_evolve.policies.selection.disjoint_pairs import (
|
|
30
|
+
DisjointParentPairPolicy,
|
|
31
|
+
ReplayVerifiedDisjointPair,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
POLICY_ID = "frozen_archive_exact_joint_source_utility_disjoint_pair"
|
|
36
|
+
POLICY_VERSION = 2
|
|
37
|
+
_CONTEXT_DOMAIN = b"agent-evolve:frozen-archive-source-utility-context:v1\x00"
|
|
38
|
+
_RECEIPT_DOMAIN = b"agent-evolve:frozen-archive-source-utility-receipt:v1\x00"
|
|
39
|
+
_DECISION_DOMAIN = b"agent-evolve:frozen-archive-disjoint-pair-decision:v2\x00"
|
|
40
|
+
_TOKEN = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
|
|
41
|
+
_MAX_GENERATION = (1 << 63) - 1
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _canonical_json(value: object) -> bytes:
|
|
45
|
+
return json.dumps(
|
|
46
|
+
value,
|
|
47
|
+
allow_nan=False,
|
|
48
|
+
ensure_ascii=True,
|
|
49
|
+
separators=(",", ":"),
|
|
50
|
+
sort_keys=True,
|
|
51
|
+
).encode("ascii", errors="strict")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _hash(domain: bytes, value: object) -> str:
|
|
55
|
+
return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _require_token(value: str, *, name: str) -> None:
|
|
59
|
+
if type(value) is not str or _TOKEN.fullmatch(value) is None:
|
|
60
|
+
raise ValueError(f"{name} must use the closed lowercase token grammar")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _require_generation(value: int, *, name: str) -> None:
|
|
64
|
+
if type(value) is not int or not 1 <= value <= _MAX_GENERATION:
|
|
65
|
+
raise ValueError(f"{name} must be an exact positive int63")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _require_utility(value: float, *, name: str) -> None:
|
|
69
|
+
if type(value) is not float or not math.isfinite(value):
|
|
70
|
+
raise TypeError(f"{name} must be a finite canonical float")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _pair_key(pair: ReplayVerifiedDisjointPair) -> tuple[str, str]:
|
|
74
|
+
pair.revalidate()
|
|
75
|
+
return pair.left.candidate_id.value, pair.right.candidate_id.value
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass(frozen=True, slots=True)
|
|
79
|
+
class FrozenArchiveSourceUtilityContext:
|
|
80
|
+
"""Identity of one workload-owned utility and frozen archive cutoff."""
|
|
81
|
+
|
|
82
|
+
utility_id: str
|
|
83
|
+
utility_version: int
|
|
84
|
+
utility_definition_sha256: str
|
|
85
|
+
benchmark_sha256: str
|
|
86
|
+
archive_cutoff_sha256: str
|
|
87
|
+
archive_snapshot_sha256: str
|
|
88
|
+
snapshot_generation: int
|
|
89
|
+
|
|
90
|
+
def __post_init__(self) -> None:
|
|
91
|
+
_require_token(self.utility_id, name="utility_id")
|
|
92
|
+
if type(self.utility_version) is not int or self.utility_version <= 0:
|
|
93
|
+
raise ValueError("utility_version must be a positive exact integer")
|
|
94
|
+
for name in (
|
|
95
|
+
"utility_definition_sha256",
|
|
96
|
+
"benchmark_sha256",
|
|
97
|
+
"archive_cutoff_sha256",
|
|
98
|
+
"archive_snapshot_sha256",
|
|
99
|
+
):
|
|
100
|
+
require_sha256(getattr(self, name), name)
|
|
101
|
+
_require_generation(self.snapshot_generation, name="snapshot_generation")
|
|
102
|
+
|
|
103
|
+
def revalidate(self) -> None:
|
|
104
|
+
if type(self) is not FrozenArchiveSourceUtilityContext:
|
|
105
|
+
raise TypeError("context must be exact FrozenArchiveSourceUtilityContext")
|
|
106
|
+
FrozenArchiveSourceUtilityContext.__post_init__(self)
|
|
107
|
+
|
|
108
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
109
|
+
self.revalidate()
|
|
110
|
+
return {
|
|
111
|
+
"schema_version": 1,
|
|
112
|
+
"utility_id": self.utility_id,
|
|
113
|
+
"utility_version": self.utility_version,
|
|
114
|
+
"utility_definition_sha256": self.utility_definition_sha256,
|
|
115
|
+
"benchmark_sha256": self.benchmark_sha256,
|
|
116
|
+
"archive_cutoff_sha256": self.archive_cutoff_sha256,
|
|
117
|
+
"archive_snapshot_sha256": self.archive_snapshot_sha256,
|
|
118
|
+
"snapshot_generation": self.snapshot_generation,
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def context_sha256(self) -> str:
|
|
123
|
+
return _hash(_CONTEXT_DOMAIN, self._unsigned_record())
|
|
124
|
+
|
|
125
|
+
def to_record(self) -> dict[str, object]:
|
|
126
|
+
return {**self._unsigned_record(), "context_sha256": self.context_sha256}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass(frozen=True, slots=True)
|
|
130
|
+
class ObservedSourceBranch:
|
|
131
|
+
"""Exact evaluated source occurrence to which utility is attributed."""
|
|
132
|
+
|
|
133
|
+
source_rank: int
|
|
134
|
+
candidate_id: CandidateId
|
|
135
|
+
candidate_configuration_sha256: str
|
|
136
|
+
source_outcome_sha256: str
|
|
137
|
+
|
|
138
|
+
def __post_init__(self) -> None:
|
|
139
|
+
if type(self.source_rank) is not int or self.source_rank <= 0:
|
|
140
|
+
raise ValueError("source_rank must be a positive exact integer")
|
|
141
|
+
if type(self.candidate_id) is not CandidateId:
|
|
142
|
+
raise TypeError("candidate_id must be an exact CandidateId")
|
|
143
|
+
CandidateId.__post_init__(self.candidate_id)
|
|
144
|
+
require_sha256(
|
|
145
|
+
self.candidate_configuration_sha256,
|
|
146
|
+
"candidate_configuration_sha256",
|
|
147
|
+
)
|
|
148
|
+
require_sha256(self.source_outcome_sha256, "source_outcome_sha256")
|
|
149
|
+
|
|
150
|
+
def revalidate(self) -> None:
|
|
151
|
+
if type(self) is not ObservedSourceBranch:
|
|
152
|
+
raise TypeError("source branch must be exact ObservedSourceBranch")
|
|
153
|
+
ObservedSourceBranch.__post_init__(self)
|
|
154
|
+
|
|
155
|
+
def to_record(self) -> dict[str, object]:
|
|
156
|
+
self.revalidate()
|
|
157
|
+
return {
|
|
158
|
+
"source_rank": self.source_rank,
|
|
159
|
+
"candidate_id": self.candidate_id.value,
|
|
160
|
+
"candidate_configuration_sha256": (self.candidate_configuration_sha256),
|
|
161
|
+
"source_outcome_sha256": self.source_outcome_sha256,
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@dataclass(frozen=True, slots=True)
|
|
166
|
+
class FrozenArchiveBranchUtility:
|
|
167
|
+
"""One observed source branch's marginal utility under the shared snapshot."""
|
|
168
|
+
|
|
169
|
+
source: ObservedSourceBranch
|
|
170
|
+
marginal_utility: float
|
|
171
|
+
|
|
172
|
+
def __post_init__(self) -> None:
|
|
173
|
+
if type(self.source) is not ObservedSourceBranch:
|
|
174
|
+
raise TypeError("source must be exact ObservedSourceBranch")
|
|
175
|
+
self.source.revalidate()
|
|
176
|
+
_require_utility(self.marginal_utility, name="marginal_utility")
|
|
177
|
+
|
|
178
|
+
def revalidate(self) -> None:
|
|
179
|
+
if type(self) is not FrozenArchiveBranchUtility:
|
|
180
|
+
raise TypeError("branch utility must be exact FrozenArchiveBranchUtility")
|
|
181
|
+
FrozenArchiveBranchUtility.__post_init__(self)
|
|
182
|
+
|
|
183
|
+
@property
|
|
184
|
+
def candidate_id(self) -> CandidateId:
|
|
185
|
+
self.revalidate()
|
|
186
|
+
return self.source.candidate_id
|
|
187
|
+
|
|
188
|
+
def to_record(self) -> dict[str, object]:
|
|
189
|
+
self.revalidate()
|
|
190
|
+
return {
|
|
191
|
+
"source": self.source.to_record(),
|
|
192
|
+
"marginal_utility_hex": self.marginal_utility.hex(),
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@dataclass(frozen=True, slots=True)
|
|
197
|
+
class FrozenArchiveSourcePairUtility:
|
|
198
|
+
"""Exact utility of two observed sources jointly augmenting the archive."""
|
|
199
|
+
|
|
200
|
+
pair_ids: tuple[CandidateId, CandidateId]
|
|
201
|
+
exact_joint_utility: float
|
|
202
|
+
|
|
203
|
+
def __post_init__(self) -> None:
|
|
204
|
+
if (
|
|
205
|
+
type(self.pair_ids) is not tuple
|
|
206
|
+
or len(self.pair_ids) != 2
|
|
207
|
+
or any(type(value) is not CandidateId for value in self.pair_ids)
|
|
208
|
+
):
|
|
209
|
+
raise TypeError("pair_ids must contain two exact CandidateId values")
|
|
210
|
+
for value in self.pair_ids:
|
|
211
|
+
CandidateId.__post_init__(value)
|
|
212
|
+
if self.pair_ids[0] >= self.pair_ids[1]:
|
|
213
|
+
raise ValueError("source utility pair IDs must use canonical order")
|
|
214
|
+
_require_utility(self.exact_joint_utility, name="exact_joint_utility")
|
|
215
|
+
|
|
216
|
+
def revalidate(self) -> None:
|
|
217
|
+
if type(self) is not FrozenArchiveSourcePairUtility:
|
|
218
|
+
raise TypeError("pair utility must be exact FrozenArchiveSourcePairUtility")
|
|
219
|
+
FrozenArchiveSourcePairUtility.__post_init__(self)
|
|
220
|
+
|
|
221
|
+
def to_record(self) -> dict[str, object]:
|
|
222
|
+
self.revalidate()
|
|
223
|
+
return {
|
|
224
|
+
"pair_ids": [value.value for value in self.pair_ids],
|
|
225
|
+
"exact_joint_utility_hex": self.exact_joint_utility.hex(),
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
@dataclass(frozen=True, slots=True)
|
|
230
|
+
class FrozenArchiveSourceUtilityReceipt:
|
|
231
|
+
"""Complete source and pair utility tables under one archive snapshot."""
|
|
232
|
+
|
|
233
|
+
context: FrozenArchiveSourceUtilityContext
|
|
234
|
+
source_wave_receipt_sha256: str
|
|
235
|
+
source_request_sha256: str
|
|
236
|
+
source_decision_sha256: str
|
|
237
|
+
source_contract_sha256: str
|
|
238
|
+
source_generation: int
|
|
239
|
+
branches: tuple[FrozenArchiveBranchUtility, ...]
|
|
240
|
+
pair_utilities: tuple[FrozenArchiveSourcePairUtility, ...]
|
|
241
|
+
|
|
242
|
+
def __post_init__(self) -> None:
|
|
243
|
+
if type(self.context) is not FrozenArchiveSourceUtilityContext:
|
|
244
|
+
raise TypeError("context must be exact FrozenArchiveSourceUtilityContext")
|
|
245
|
+
self.context.revalidate()
|
|
246
|
+
for name in (
|
|
247
|
+
"source_wave_receipt_sha256",
|
|
248
|
+
"source_request_sha256",
|
|
249
|
+
"source_decision_sha256",
|
|
250
|
+
"source_contract_sha256",
|
|
251
|
+
):
|
|
252
|
+
require_sha256(getattr(self, name), name)
|
|
253
|
+
_require_generation(self.source_generation, name="source_generation")
|
|
254
|
+
if self.context.snapshot_generation != self.source_generation:
|
|
255
|
+
raise ValueError(
|
|
256
|
+
"archive utility snapshot is stale or foreign to the source generation"
|
|
257
|
+
)
|
|
258
|
+
if type(self.branches) is not tuple or any(
|
|
259
|
+
type(value) is not FrozenArchiveBranchUtility for value in self.branches
|
|
260
|
+
):
|
|
261
|
+
raise TypeError("branches must contain exact branch utilities")
|
|
262
|
+
for value in self.branches:
|
|
263
|
+
value.revalidate()
|
|
264
|
+
source_ranks = tuple(value.source.source_rank for value in self.branches)
|
|
265
|
+
if source_ranks != tuple(sorted(set(source_ranks))):
|
|
266
|
+
raise ValueError(
|
|
267
|
+
"branch utilities must preserve canonical scored source-rank order"
|
|
268
|
+
)
|
|
269
|
+
ids = tuple(value.candidate_id for value in self.branches)
|
|
270
|
+
if len(set(ids)) != len(ids):
|
|
271
|
+
raise ValueError("branch utility candidate IDs must be unique")
|
|
272
|
+
if type(self.pair_utilities) is not tuple or any(
|
|
273
|
+
type(value) is not FrozenArchiveSourcePairUtility
|
|
274
|
+
for value in self.pair_utilities
|
|
275
|
+
):
|
|
276
|
+
raise TypeError("pair_utilities must contain exact pair utilities")
|
|
277
|
+
for value in self.pair_utilities:
|
|
278
|
+
value.revalidate()
|
|
279
|
+
expected_pairs = tuple(combinations(sorted(ids), 2))
|
|
280
|
+
if tuple(value.pair_ids for value in self.pair_utilities) != expected_pairs:
|
|
281
|
+
raise ValueError(
|
|
282
|
+
"pair_utilities must completely enumerate source pairs in canonical order"
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
def revalidate(self) -> None:
|
|
286
|
+
if type(self) is not FrozenArchiveSourceUtilityReceipt:
|
|
287
|
+
raise TypeError("receipt must be exact FrozenArchiveSourceUtilityReceipt")
|
|
288
|
+
FrozenArchiveSourceUtilityReceipt.__post_init__(self)
|
|
289
|
+
|
|
290
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
291
|
+
self.revalidate()
|
|
292
|
+
return {
|
|
293
|
+
"schema_version": 1,
|
|
294
|
+
"context": self.context.to_record(),
|
|
295
|
+
"source_wave_receipt_sha256": self.source_wave_receipt_sha256,
|
|
296
|
+
"source_request_sha256": self.source_request_sha256,
|
|
297
|
+
"source_decision_sha256": self.source_decision_sha256,
|
|
298
|
+
"source_contract_sha256": self.source_contract_sha256,
|
|
299
|
+
"source_generation": self.source_generation,
|
|
300
|
+
"branches": [value.to_record() for value in self.branches],
|
|
301
|
+
"pair_utilities": [value.to_record() for value in self.pair_utilities],
|
|
302
|
+
"utility_semantics": (
|
|
303
|
+
"marginal_branch_diagnostics_and_exact_joint_observed_source_pair_"
|
|
304
|
+
"utility_against_one_frozen_archive; not_a_recombination_child_"
|
|
305
|
+
"prediction"
|
|
306
|
+
),
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
@property
|
|
310
|
+
def receipt_sha256(self) -> str:
|
|
311
|
+
return _hash(_RECEIPT_DOMAIN, self._unsigned_record())
|
|
312
|
+
|
|
313
|
+
def to_record(self) -> dict[str, object]:
|
|
314
|
+
return {**self._unsigned_record(), "receipt_sha256": self.receipt_sha256}
|
|
315
|
+
|
|
316
|
+
def marginal_utility_for(
|
|
317
|
+
self, candidate_id: CandidateId
|
|
318
|
+
) -> FrozenArchiveBranchUtility:
|
|
319
|
+
"""Resolve a committed source marginal or fail closed."""
|
|
320
|
+
|
|
321
|
+
self.revalidate()
|
|
322
|
+
if type(candidate_id) is not CandidateId:
|
|
323
|
+
raise TypeError("candidate_id must be an exact CandidateId")
|
|
324
|
+
CandidateId.__post_init__(candidate_id)
|
|
325
|
+
for value in self.branches:
|
|
326
|
+
if value.candidate_id == candidate_id:
|
|
327
|
+
return value
|
|
328
|
+
raise ValueError("eligible pair contains a foreign or unscored source branch")
|
|
329
|
+
|
|
330
|
+
def exact_joint_utility_for(
|
|
331
|
+
self,
|
|
332
|
+
pair_ids: tuple[CandidateId, CandidateId],
|
|
333
|
+
) -> FrozenArchiveSourcePairUtility:
|
|
334
|
+
"""Resolve the committed exact joint utility for one canonical pair."""
|
|
335
|
+
|
|
336
|
+
self.revalidate()
|
|
337
|
+
if (
|
|
338
|
+
type(pair_ids) is not tuple
|
|
339
|
+
or len(pair_ids) != 2
|
|
340
|
+
or any(type(value) is not CandidateId for value in pair_ids)
|
|
341
|
+
):
|
|
342
|
+
raise TypeError("pair_ids must contain two exact CandidateId values")
|
|
343
|
+
for value in self.pair_utilities:
|
|
344
|
+
if value.pair_ids == pair_ids:
|
|
345
|
+
return value
|
|
346
|
+
raise ValueError("eligible pair has no exact joint source utility")
|
|
347
|
+
|
|
348
|
+
def require_exact_context(
|
|
349
|
+
self,
|
|
350
|
+
*,
|
|
351
|
+
context: FrozenArchiveSourceUtilityContext,
|
|
352
|
+
source_wave_receipt_sha256: str,
|
|
353
|
+
source_request_sha256: str,
|
|
354
|
+
source_decision_sha256: str,
|
|
355
|
+
source_contract_sha256: str,
|
|
356
|
+
source_generation: int,
|
|
357
|
+
source_branches: Sequence[ObservedSourceBranch],
|
|
358
|
+
) -> None:
|
|
359
|
+
"""Authenticate the receipt against its calling source-wave boundary."""
|
|
360
|
+
|
|
361
|
+
self.revalidate()
|
|
362
|
+
if type(context) is not FrozenArchiveSourceUtilityContext:
|
|
363
|
+
raise TypeError("context must be exact FrozenArchiveSourceUtilityContext")
|
|
364
|
+
context.revalidate()
|
|
365
|
+
for name, value in (
|
|
366
|
+
("source_wave_receipt_sha256", source_wave_receipt_sha256),
|
|
367
|
+
("source_request_sha256", source_request_sha256),
|
|
368
|
+
("source_decision_sha256", source_decision_sha256),
|
|
369
|
+
("source_contract_sha256", source_contract_sha256),
|
|
370
|
+
):
|
|
371
|
+
require_sha256(value, name)
|
|
372
|
+
_require_generation(source_generation, name="source_generation")
|
|
373
|
+
if isinstance(source_branches, (str, bytes)):
|
|
374
|
+
raise TypeError("source_branches must be a finite branch sequence")
|
|
375
|
+
expected_branches = tuple(source_branches)
|
|
376
|
+
for value in expected_branches:
|
|
377
|
+
if type(value) is not ObservedSourceBranch:
|
|
378
|
+
raise TypeError(
|
|
379
|
+
"source_branches must contain exact ObservedSourceBranch values"
|
|
380
|
+
)
|
|
381
|
+
value.revalidate()
|
|
382
|
+
observed_branches = tuple(value.source for value in self.branches)
|
|
383
|
+
if self.context != context:
|
|
384
|
+
raise ValueError("source utility receipt has a foreign archive context")
|
|
385
|
+
if self.source_generation != source_generation:
|
|
386
|
+
raise ValueError("source utility receipt is stale for this generation")
|
|
387
|
+
supplied = (
|
|
388
|
+
self.source_wave_receipt_sha256,
|
|
389
|
+
self.source_request_sha256,
|
|
390
|
+
self.source_decision_sha256,
|
|
391
|
+
self.source_contract_sha256,
|
|
392
|
+
)
|
|
393
|
+
expected = (
|
|
394
|
+
source_wave_receipt_sha256,
|
|
395
|
+
source_request_sha256,
|
|
396
|
+
source_decision_sha256,
|
|
397
|
+
source_contract_sha256,
|
|
398
|
+
)
|
|
399
|
+
if supplied != expected:
|
|
400
|
+
raise ValueError("source utility receipt belongs to a foreign source wave")
|
|
401
|
+
if observed_branches != expected_branches:
|
|
402
|
+
raise ValueError("source utility receipt has foreign or tampered branches")
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
@dataclass(frozen=True, slots=True)
|
|
406
|
+
class ArchiveAwareDisjointPairScoreRow:
|
|
407
|
+
"""One safe pair under source utility and structural coverage scores."""
|
|
408
|
+
|
|
409
|
+
pair: ReplayVerifiedDisjointPair
|
|
410
|
+
left_marginal_utility: FrozenArchiveBranchUtility
|
|
411
|
+
right_marginal_utility: FrozenArchiveBranchUtility
|
|
412
|
+
exact_joint_source_utility: FrozenArchiveSourcePairUtility
|
|
413
|
+
distinct_role_count: int
|
|
414
|
+
distinct_family_count: int
|
|
415
|
+
path_family_exposure_sum: int
|
|
416
|
+
|
|
417
|
+
def __post_init__(self) -> None:
|
|
418
|
+
if type(self.pair) is not ReplayVerifiedDisjointPair:
|
|
419
|
+
raise TypeError("pair must be exact ReplayVerifiedDisjointPair")
|
|
420
|
+
self.pair.revalidate()
|
|
421
|
+
for name in ("left_marginal_utility", "right_marginal_utility"):
|
|
422
|
+
value = getattr(self, name)
|
|
423
|
+
if type(value) is not FrozenArchiveBranchUtility:
|
|
424
|
+
raise TypeError(f"{name} must be exact FrozenArchiveBranchUtility")
|
|
425
|
+
value.revalidate()
|
|
426
|
+
if self.left_marginal_utility.candidate_id != self.pair.left.candidate_id:
|
|
427
|
+
raise ValueError("left marginal belongs to a foreign source branch")
|
|
428
|
+
if self.right_marginal_utility.candidate_id != self.pair.right.candidate_id:
|
|
429
|
+
raise ValueError("right marginal belongs to a foreign source branch")
|
|
430
|
+
if type(self.exact_joint_source_utility) is not FrozenArchiveSourcePairUtility:
|
|
431
|
+
raise TypeError(
|
|
432
|
+
"exact_joint_source_utility must be exact FrozenArchiveSourcePairUtility"
|
|
433
|
+
)
|
|
434
|
+
self.exact_joint_source_utility.revalidate()
|
|
435
|
+
if self.exact_joint_source_utility.pair_ids != self.pair.pair_ids:
|
|
436
|
+
raise ValueError("exact joint utility belongs to a foreign source pair")
|
|
437
|
+
expected_roles = len({self.pair.left.role, self.pair.right.role})
|
|
438
|
+
if (
|
|
439
|
+
type(self.distinct_role_count) is not int
|
|
440
|
+
or self.distinct_role_count != expected_roles
|
|
441
|
+
):
|
|
442
|
+
raise ValueError("distinct_role_count differs from pair facts")
|
|
443
|
+
expected_families = len({self.pair.left.family, self.pair.right.family})
|
|
444
|
+
if (
|
|
445
|
+
type(self.distinct_family_count) is not int
|
|
446
|
+
or self.distinct_family_count != expected_families
|
|
447
|
+
):
|
|
448
|
+
raise ValueError("distinct_family_count differs from pair facts")
|
|
449
|
+
expected_exposure = (
|
|
450
|
+
self.pair.left.path_family_exposure + self.pair.right.path_family_exposure
|
|
451
|
+
)
|
|
452
|
+
if (
|
|
453
|
+
type(self.path_family_exposure_sum) is not int
|
|
454
|
+
or self.path_family_exposure_sum != expected_exposure
|
|
455
|
+
):
|
|
456
|
+
raise ValueError("path_family_exposure_sum differs from pair facts")
|
|
457
|
+
|
|
458
|
+
def revalidate(self) -> None:
|
|
459
|
+
if type(self) is not ArchiveAwareDisjointPairScoreRow:
|
|
460
|
+
raise TypeError("score row must be exact ArchiveAwareDisjointPairScoreRow")
|
|
461
|
+
ArchiveAwareDisjointPairScoreRow.__post_init__(self)
|
|
462
|
+
|
|
463
|
+
@property
|
|
464
|
+
def pair_ids(self) -> tuple[CandidateId, CandidateId]:
|
|
465
|
+
self.revalidate()
|
|
466
|
+
return self.pair.pair_ids
|
|
467
|
+
|
|
468
|
+
def to_record(
|
|
469
|
+
self,
|
|
470
|
+
*,
|
|
471
|
+
exploit_pair_ids: tuple[CandidateId, CandidateId] | None,
|
|
472
|
+
exploit_target_configuration_sha256: str | None,
|
|
473
|
+
) -> dict[str, object]:
|
|
474
|
+
self.revalidate()
|
|
475
|
+
if exploit_pair_ids is not None:
|
|
476
|
+
if (
|
|
477
|
+
type(exploit_pair_ids) is not tuple
|
|
478
|
+
or len(exploit_pair_ids) != 2
|
|
479
|
+
or any(type(value) is not CandidateId for value in exploit_pair_ids)
|
|
480
|
+
):
|
|
481
|
+
raise TypeError("exploit_pair_ids must contain exact CandidateIds")
|
|
482
|
+
if exploit_target_configuration_sha256 is not None:
|
|
483
|
+
require_sha256(
|
|
484
|
+
exploit_target_configuration_sha256,
|
|
485
|
+
"exploit_target_configuration_sha256",
|
|
486
|
+
)
|
|
487
|
+
legacy_reward_sum = self.pair.left.reward + self.pair.right.reward
|
|
488
|
+
marginal_sum = (
|
|
489
|
+
self.left_marginal_utility.marginal_utility
|
|
490
|
+
+ self.right_marginal_utility.marginal_utility
|
|
491
|
+
)
|
|
492
|
+
return {
|
|
493
|
+
**self.pair.to_trace_record(),
|
|
494
|
+
"left_source_marginal_utility": self.left_marginal_utility.to_record(),
|
|
495
|
+
"right_source_marginal_utility": self.right_marginal_utility.to_record(),
|
|
496
|
+
"marginal_utility_sum_diagnostic_hex": float(marginal_sum).hex(),
|
|
497
|
+
"exact_joint_source_utility": self.exact_joint_source_utility.to_record(),
|
|
498
|
+
"legacy_branch_reward_sum_hex": float(legacy_reward_sum).hex(),
|
|
499
|
+
"distinct_role_count": self.distinct_role_count,
|
|
500
|
+
"distinct_family_count": self.distinct_family_count,
|
|
501
|
+
"path_family_exposure_sum": self.path_family_exposure_sum,
|
|
502
|
+
"pair_distinct_from_exploit": (
|
|
503
|
+
None if exploit_pair_ids is None else self.pair_ids != exploit_pair_ids
|
|
504
|
+
),
|
|
505
|
+
"target_distinct_from_exploit": (
|
|
506
|
+
None
|
|
507
|
+
if exploit_target_configuration_sha256 is None
|
|
508
|
+
else self.pair.target_configuration_sha256
|
|
509
|
+
!= exploit_target_configuration_sha256
|
|
510
|
+
),
|
|
511
|
+
"exploit_tie_key": [
|
|
512
|
+
-self.exact_joint_source_utility.exact_joint_utility,
|
|
513
|
+
-legacy_reward_sum,
|
|
514
|
+
-self.distinct_role_count,
|
|
515
|
+
self.pair.left.candidate_id.value,
|
|
516
|
+
self.pair.right.candidate_id.value,
|
|
517
|
+
],
|
|
518
|
+
"coverage_tie_key": [
|
|
519
|
+
(
|
|
520
|
+
None
|
|
521
|
+
if exploit_target_configuration_sha256 is None
|
|
522
|
+
else self.pair.target_configuration_sha256
|
|
523
|
+
== exploit_target_configuration_sha256
|
|
524
|
+
),
|
|
525
|
+
-self.distinct_family_count,
|
|
526
|
+
-self.distinct_role_count,
|
|
527
|
+
self.path_family_exposure_sum,
|
|
528
|
+
self.pair.left.candidate_id.value,
|
|
529
|
+
self.pair.right.candidate_id.value,
|
|
530
|
+
],
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
|
|
534
|
+
def _canonical_rows(
|
|
535
|
+
pairs: Sequence[ReplayVerifiedDisjointPair],
|
|
536
|
+
receipt: FrozenArchiveSourceUtilityReceipt,
|
|
537
|
+
) -> tuple[ArchiveAwareDisjointPairScoreRow, ...]:
|
|
538
|
+
if type(receipt) is not FrozenArchiveSourceUtilityReceipt:
|
|
539
|
+
raise TypeError("source_utilities must be an exact receipt")
|
|
540
|
+
receipt.revalidate()
|
|
541
|
+
legacy_rows = DisjointParentPairPolicy().select(pairs).eligible_rows
|
|
542
|
+
result: list[ArchiveAwareDisjointPairScoreRow] = []
|
|
543
|
+
for legacy in legacy_rows:
|
|
544
|
+
pair = legacy.pair
|
|
545
|
+
left = receipt.marginal_utility_for(pair.left.candidate_id)
|
|
546
|
+
right = receipt.marginal_utility_for(pair.right.candidate_id)
|
|
547
|
+
exact_joint = receipt.exact_joint_utility_for(pair.pair_ids)
|
|
548
|
+
result.append(
|
|
549
|
+
ArchiveAwareDisjointPairScoreRow(
|
|
550
|
+
pair=pair,
|
|
551
|
+
left_marginal_utility=left,
|
|
552
|
+
right_marginal_utility=right,
|
|
553
|
+
exact_joint_source_utility=exact_joint,
|
|
554
|
+
distinct_role_count=legacy.distinct_role_count,
|
|
555
|
+
distinct_family_count=legacy.distinct_family_count,
|
|
556
|
+
path_family_exposure_sum=legacy.path_family_exposure_sum,
|
|
557
|
+
)
|
|
558
|
+
)
|
|
559
|
+
return tuple(result)
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
def _select_rows(
|
|
563
|
+
rows: tuple[ArchiveAwareDisjointPairScoreRow, ...],
|
|
564
|
+
) -> tuple[
|
|
565
|
+
ArchiveAwareDisjointPairScoreRow | None,
|
|
566
|
+
ArchiveAwareDisjointPairScoreRow | None,
|
|
567
|
+
]:
|
|
568
|
+
if not rows:
|
|
569
|
+
return None, None
|
|
570
|
+
exploit = min(
|
|
571
|
+
rows,
|
|
572
|
+
key=lambda row: (
|
|
573
|
+
-row.exact_joint_source_utility.exact_joint_utility,
|
|
574
|
+
-(row.pair.left.reward + row.pair.right.reward),
|
|
575
|
+
-row.distinct_role_count,
|
|
576
|
+
*_pair_key(row.pair),
|
|
577
|
+
),
|
|
578
|
+
)
|
|
579
|
+
coverage_pool = tuple(row for row in rows if row.pair_ids != exploit.pair_ids)
|
|
580
|
+
if not coverage_pool:
|
|
581
|
+
return exploit, None
|
|
582
|
+
coverage = min(
|
|
583
|
+
coverage_pool,
|
|
584
|
+
key=lambda row: (
|
|
585
|
+
row.pair.target_configuration_sha256
|
|
586
|
+
== exploit.pair.target_configuration_sha256,
|
|
587
|
+
-row.distinct_family_count,
|
|
588
|
+
-row.distinct_role_count,
|
|
589
|
+
row.path_family_exposure_sum,
|
|
590
|
+
*_pair_key(row.pair),
|
|
591
|
+
),
|
|
592
|
+
)
|
|
593
|
+
return exploit, coverage
|
|
594
|
+
|
|
595
|
+
|
|
596
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
597
|
+
class ArchiveAwareDisjointPairSelectionDecision:
|
|
598
|
+
"""Trace-complete source-utility exploit and structural coverage choice."""
|
|
599
|
+
|
|
600
|
+
source_utilities: FrozenArchiveSourceUtilityReceipt
|
|
601
|
+
eligible_rows: tuple[ArchiveAwareDisjointPairScoreRow, ...]
|
|
602
|
+
exploit_pair_ids: tuple[CandidateId, CandidateId] | None
|
|
603
|
+
coverage_pair_ids: tuple[CandidateId, CandidateId] | None
|
|
604
|
+
|
|
605
|
+
policy_id: ClassVar[str] = POLICY_ID
|
|
606
|
+
policy_version: ClassVar[int] = POLICY_VERSION
|
|
607
|
+
|
|
608
|
+
def __post_init__(self) -> None:
|
|
609
|
+
if type(self.source_utilities) is not FrozenArchiveSourceUtilityReceipt:
|
|
610
|
+
raise TypeError("source_utilities must be an exact receipt")
|
|
611
|
+
self.source_utilities.revalidate()
|
|
612
|
+
if type(self.eligible_rows) is not tuple or any(
|
|
613
|
+
type(value) is not ArchiveAwareDisjointPairScoreRow
|
|
614
|
+
for value in self.eligible_rows
|
|
615
|
+
):
|
|
616
|
+
raise TypeError("eligible_rows must contain exact archive-aware rows")
|
|
617
|
+
expected_rows = _canonical_rows(
|
|
618
|
+
tuple(value.pair for value in self.eligible_rows),
|
|
619
|
+
self.source_utilities,
|
|
620
|
+
)
|
|
621
|
+
if self.eligible_rows != expected_rows:
|
|
622
|
+
raise ValueError("eligible_rows differ from utility and pair evidence")
|
|
623
|
+
exploit, coverage = _select_rows(expected_rows)
|
|
624
|
+
expected_exploit = None if exploit is None else exploit.pair_ids
|
|
625
|
+
expected_coverage = None if coverage is None else coverage.pair_ids
|
|
626
|
+
if self.exploit_pair_ids != expected_exploit:
|
|
627
|
+
raise ValueError("exploit_pair_ids do not match frozen source utility")
|
|
628
|
+
if self.coverage_pair_ids != expected_coverage:
|
|
629
|
+
raise ValueError("coverage_pair_ids do not match structural coverage")
|
|
630
|
+
|
|
631
|
+
def revalidate(self) -> None:
|
|
632
|
+
if type(self) is not ArchiveAwareDisjointPairSelectionDecision:
|
|
633
|
+
raise TypeError("decision must be exact archive-aware decision")
|
|
634
|
+
ArchiveAwareDisjointPairSelectionDecision.__post_init__(self)
|
|
635
|
+
|
|
636
|
+
def _row_for(
|
|
637
|
+
self,
|
|
638
|
+
pair_ids: tuple[CandidateId, CandidateId] | None,
|
|
639
|
+
) -> ArchiveAwareDisjointPairScoreRow | None:
|
|
640
|
+
if pair_ids is None:
|
|
641
|
+
return None
|
|
642
|
+
return next(value for value in self.eligible_rows if value.pair_ids == pair_ids)
|
|
643
|
+
|
|
644
|
+
@property
|
|
645
|
+
def exploit(self) -> ArchiveAwareDisjointPairScoreRow | None:
|
|
646
|
+
self.revalidate()
|
|
647
|
+
return self._row_for(self.exploit_pair_ids)
|
|
648
|
+
|
|
649
|
+
@property
|
|
650
|
+
def coverage(self) -> ArchiveAwareDisjointPairScoreRow | None:
|
|
651
|
+
self.revalidate()
|
|
652
|
+
return self._row_for(self.coverage_pair_ids)
|
|
653
|
+
|
|
654
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
655
|
+
self.revalidate()
|
|
656
|
+
exploit = self._row_for(self.exploit_pair_ids)
|
|
657
|
+
coverage = self._row_for(self.coverage_pair_ids)
|
|
658
|
+
exploit_target = (
|
|
659
|
+
None if exploit is None else exploit.pair.target_configuration_sha256
|
|
660
|
+
)
|
|
661
|
+
return {
|
|
662
|
+
"schema_version": 1,
|
|
663
|
+
"event_type": "archive_aware_recombination_pair_selected",
|
|
664
|
+
"policy_id": self.policy_id,
|
|
665
|
+
"policy_version": self.policy_version,
|
|
666
|
+
"source_utility_receipt": self.source_utilities.to_record(),
|
|
667
|
+
"source_utility_receipt_sha256": self.source_utilities.receipt_sha256,
|
|
668
|
+
"eligible_rows": [
|
|
669
|
+
value.to_record(
|
|
670
|
+
exploit_pair_ids=self.exploit_pair_ids,
|
|
671
|
+
exploit_target_configuration_sha256=exploit_target,
|
|
672
|
+
)
|
|
673
|
+
for value in self.eligible_rows
|
|
674
|
+
],
|
|
675
|
+
"exploit_pair_ids": (
|
|
676
|
+
None if exploit is None else [value.value for value in exploit.pair_ids]
|
|
677
|
+
),
|
|
678
|
+
"exploit_exact_joint_source_utility_hex": (
|
|
679
|
+
None
|
|
680
|
+
if exploit is None
|
|
681
|
+
else exploit.exact_joint_source_utility.exact_joint_utility.hex()
|
|
682
|
+
),
|
|
683
|
+
"coverage_pair_ids": (
|
|
684
|
+
None
|
|
685
|
+
if coverage is None
|
|
686
|
+
else [value.value for value in coverage.pair_ids]
|
|
687
|
+
),
|
|
688
|
+
"exploit_rule": (
|
|
689
|
+
"maximum exact utility of the two observed sources jointly added "
|
|
690
|
+
"to one frozen archive; maximum observed parent-relative branch-"
|
|
691
|
+
"reward sum only within an exact archive-utility tie; maximum "
|
|
692
|
+
"distinct source roles; canonical candidate IDs"
|
|
693
|
+
),
|
|
694
|
+
"coverage_rule": (
|
|
695
|
+
"exclude exploit pair; prefer a target-distinct pair; maximum "
|
|
696
|
+
"distinct families; maximum distinct roles; minimum prior "
|
|
697
|
+
"path/family exposure; canonical candidate IDs"
|
|
698
|
+
),
|
|
699
|
+
"utility_scope": (
|
|
700
|
+
"exact_joint_observed_sources_only_not_unseen_recombination_child_"
|
|
701
|
+
"performance; branch_reward_sum_is_secondary_exact_tie_break_only; "
|
|
702
|
+
"marginal_utility_sum_is_diagnostic_only"
|
|
703
|
+
),
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
@property
|
|
707
|
+
def decision_sha256(self) -> str:
|
|
708
|
+
return _hash(_DECISION_DOMAIN, self._unsigned_record())
|
|
709
|
+
|
|
710
|
+
def to_record(self) -> dict[str, object]:
|
|
711
|
+
return {**self._unsigned_record(), "decision_sha256": self.decision_sha256}
|
|
712
|
+
|
|
713
|
+
def to_trace_record(self) -> dict[str, object]:
|
|
714
|
+
"""Match the trace surface of the legacy disjoint-pair decision."""
|
|
715
|
+
|
|
716
|
+
return self.to_record()
|
|
717
|
+
|
|
718
|
+
def __eq__(self, other: object) -> bool:
|
|
719
|
+
return (
|
|
720
|
+
type(self) is ArchiveAwareDisjointPairSelectionDecision
|
|
721
|
+
and type(other) is ArchiveAwareDisjointPairSelectionDecision
|
|
722
|
+
and self.decision_sha256 == other.decision_sha256
|
|
723
|
+
)
|
|
724
|
+
|
|
725
|
+
__hash__ = None
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
@dataclass(frozen=True, slots=True)
|
|
729
|
+
class ArchiveAwareDisjointParentPairPolicy:
|
|
730
|
+
"""Select utility exploit first and independent structural coverage second."""
|
|
731
|
+
|
|
732
|
+
policy_id: ClassVar[str] = POLICY_ID
|
|
733
|
+
policy_version: ClassVar[int] = POLICY_VERSION
|
|
734
|
+
|
|
735
|
+
def select(
|
|
736
|
+
self,
|
|
737
|
+
eligible_pairs: Sequence[ReplayVerifiedDisjointPair],
|
|
738
|
+
*,
|
|
739
|
+
source_utilities: FrozenArchiveSourceUtilityReceipt,
|
|
740
|
+
) -> ArchiveAwareDisjointPairSelectionDecision:
|
|
741
|
+
rows = _canonical_rows(eligible_pairs, source_utilities)
|
|
742
|
+
exploit, coverage = _select_rows(rows)
|
|
743
|
+
return ArchiveAwareDisjointPairSelectionDecision(
|
|
744
|
+
source_utilities=source_utilities,
|
|
745
|
+
eligible_rows=rows,
|
|
746
|
+
exploit_pair_ids=None if exploit is None else exploit.pair_ids,
|
|
747
|
+
coverage_pair_ids=None if coverage is None else coverage.pair_ids,
|
|
748
|
+
)
|
|
749
|
+
|
|
750
|
+
|
|
751
|
+
__all__ = [
|
|
752
|
+
"ArchiveAwareDisjointPairScoreRow",
|
|
753
|
+
"ArchiveAwareDisjointPairSelectionDecision",
|
|
754
|
+
"ArchiveAwareDisjointParentPairPolicy",
|
|
755
|
+
"FrozenArchiveBranchUtility",
|
|
756
|
+
"FrozenArchiveSourcePairUtility",
|
|
757
|
+
"FrozenArchiveSourceUtilityContext",
|
|
758
|
+
"FrozenArchiveSourceUtilityReceipt",
|
|
759
|
+
"ObservedSourceBranch",
|
|
760
|
+
"POLICY_ID",
|
|
761
|
+
"POLICY_VERSION",
|
|
762
|
+
]
|