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,479 @@
|
|
|
1
|
+
"""Deterministic exploit/coverage choice over replay-verified disjoint pairs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import json
|
|
7
|
+
import math
|
|
8
|
+
import re
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
from numbers import Real
|
|
11
|
+
from typing import ClassVar, Sequence
|
|
12
|
+
|
|
13
|
+
from agent_evolve.domain.ids import CandidateId
|
|
14
|
+
from agent_evolve.domain.patch import require_sha256
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
POLICY_ID = "disjoint_parent_pair_exploit_coverage"
|
|
18
|
+
POLICY_VERSION = 1
|
|
19
|
+
_DECISION_DOMAIN = b"agent-evolve:disjoint-parent-pair-decision:v1\x00"
|
|
20
|
+
_TOKEN = re.compile(r"^[a-z][a-z0-9_.-]{0,127}$")
|
|
21
|
+
_MAX_EXPOSURE = (1 << 63) - 1
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _token(value: str, *, name: str) -> None:
|
|
25
|
+
if type(value) is not str or _TOKEN.fullmatch(value) is None:
|
|
26
|
+
raise ValueError(f"{name} must use the closed lowercase token grammar")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _finite_float(value: Real, *, name: str) -> float:
|
|
30
|
+
if isinstance(value, bool) or not isinstance(value, Real):
|
|
31
|
+
raise TypeError(f"{name} must be a real number")
|
|
32
|
+
result = float(value)
|
|
33
|
+
if not math.isfinite(result):
|
|
34
|
+
raise ValueError(f"{name} must be finite")
|
|
35
|
+
return result
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def _count(value: int, *, name: str) -> None:
|
|
39
|
+
if type(value) is not int or not 0 <= value <= _MAX_EXPOSURE:
|
|
40
|
+
raise ValueError(f"{name} must be an exact non-negative int63")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True, slots=True)
|
|
44
|
+
class DisjointBranchFacts:
|
|
45
|
+
"""Pre-outcome facts for one valid, operator-compliant G1 branch."""
|
|
46
|
+
|
|
47
|
+
candidate_id: CandidateId
|
|
48
|
+
reward: float
|
|
49
|
+
role: str
|
|
50
|
+
family: str
|
|
51
|
+
path_family_exposure: int
|
|
52
|
+
|
|
53
|
+
def __post_init__(self) -> None:
|
|
54
|
+
if type(self.candidate_id) is not CandidateId:
|
|
55
|
+
raise TypeError("candidate_id must be an exact CandidateId")
|
|
56
|
+
CandidateId.__post_init__(self.candidate_id)
|
|
57
|
+
canonical_reward = _finite_float(self.reward, name="branch reward")
|
|
58
|
+
if type(self.reward) is not float or self.reward != canonical_reward:
|
|
59
|
+
raise TypeError("branch reward must already be a canonical float")
|
|
60
|
+
_token(self.role, name="role")
|
|
61
|
+
_token(self.family, name="family")
|
|
62
|
+
_count(self.path_family_exposure, name="path_family_exposure")
|
|
63
|
+
|
|
64
|
+
def revalidate(self) -> None:
|
|
65
|
+
if type(self) is not DisjointBranchFacts:
|
|
66
|
+
raise TypeError("branch facts must be exact DisjointBranchFacts")
|
|
67
|
+
DisjointBranchFacts.__post_init__(self)
|
|
68
|
+
|
|
69
|
+
def to_trace_record(self) -> dict[str, object]:
|
|
70
|
+
self.revalidate()
|
|
71
|
+
return {
|
|
72
|
+
"candidate_id": self.candidate_id.value,
|
|
73
|
+
"reward": self.reward,
|
|
74
|
+
"role": self.role,
|
|
75
|
+
"family": self.family,
|
|
76
|
+
"path_family_exposure": self.path_family_exposure,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass(frozen=True, slots=True)
|
|
81
|
+
class ReplayVerifiedDisjointPair:
|
|
82
|
+
"""One safe pair plus the exact materialization evidence it produced."""
|
|
83
|
+
|
|
84
|
+
left: DisjointBranchFacts
|
|
85
|
+
right: DisjointBranchFacts
|
|
86
|
+
target_configuration_sha256: str
|
|
87
|
+
materialization_receipt_sha256: str
|
|
88
|
+
|
|
89
|
+
def __post_init__(self) -> None:
|
|
90
|
+
if type(self.left) is not DisjointBranchFacts:
|
|
91
|
+
raise TypeError("left must be exact DisjointBranchFacts")
|
|
92
|
+
if type(self.right) is not DisjointBranchFacts:
|
|
93
|
+
raise TypeError("right must be exact DisjointBranchFacts")
|
|
94
|
+
self.left.revalidate()
|
|
95
|
+
self.right.revalidate()
|
|
96
|
+
if self.left.candidate_id >= self.right.candidate_id:
|
|
97
|
+
raise ValueError(
|
|
98
|
+
"pair branches must be distinct and canonically ordered by candidate ID"
|
|
99
|
+
)
|
|
100
|
+
require_sha256(
|
|
101
|
+
self.target_configuration_sha256,
|
|
102
|
+
"target_configuration_sha256",
|
|
103
|
+
)
|
|
104
|
+
require_sha256(
|
|
105
|
+
self.materialization_receipt_sha256,
|
|
106
|
+
"materialization_receipt_sha256",
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
def revalidate(self) -> None:
|
|
110
|
+
if type(self) is not ReplayVerifiedDisjointPair:
|
|
111
|
+
raise TypeError("eligible pair must be an exact ReplayVerifiedDisjointPair")
|
|
112
|
+
ReplayVerifiedDisjointPair.__post_init__(self)
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def pair_ids(self) -> tuple[CandidateId, CandidateId]:
|
|
116
|
+
self.revalidate()
|
|
117
|
+
return self.left.candidate_id, self.right.candidate_id
|
|
118
|
+
|
|
119
|
+
def to_trace_record(self) -> dict[str, object]:
|
|
120
|
+
self.revalidate()
|
|
121
|
+
return {
|
|
122
|
+
"left": self.left.to_trace_record(),
|
|
123
|
+
"right": self.right.to_trace_record(),
|
|
124
|
+
"target_configuration_sha256": self.target_configuration_sha256,
|
|
125
|
+
"materialization_receipt_sha256": (self.materialization_receipt_sha256),
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _pair_key(pair: ReplayVerifiedDisjointPair) -> tuple[str, str]:
|
|
130
|
+
pair.revalidate()
|
|
131
|
+
return pair.left.candidate_id.value, pair.right.candidate_id.value
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
135
|
+
class DisjointPairScoreRow:
|
|
136
|
+
"""Complete score row under both frozen G2 selection rules."""
|
|
137
|
+
|
|
138
|
+
pair: ReplayVerifiedDisjointPair
|
|
139
|
+
branch_reward_sum: float
|
|
140
|
+
distinct_role_count: int
|
|
141
|
+
distinct_family_count: int
|
|
142
|
+
path_family_exposure_sum: int
|
|
143
|
+
|
|
144
|
+
def __post_init__(self) -> None:
|
|
145
|
+
if type(self.pair) is not ReplayVerifiedDisjointPair:
|
|
146
|
+
raise TypeError("pair must be an exact ReplayVerifiedDisjointPair")
|
|
147
|
+
self.pair.revalidate()
|
|
148
|
+
expected_reward = self.pair.left.reward + self.pair.right.reward
|
|
149
|
+
if not math.isfinite(expected_reward):
|
|
150
|
+
raise ValueError("branch reward sum must be finite")
|
|
151
|
+
if type(self.branch_reward_sum) is not float:
|
|
152
|
+
raise TypeError("branch_reward_sum must be a canonical float")
|
|
153
|
+
if self.branch_reward_sum != expected_reward:
|
|
154
|
+
raise ValueError("branch_reward_sum does not match the branch facts")
|
|
155
|
+
expected_roles = len({self.pair.left.role, self.pair.right.role})
|
|
156
|
+
if (
|
|
157
|
+
type(self.distinct_role_count) is not int
|
|
158
|
+
or self.distinct_role_count != expected_roles
|
|
159
|
+
):
|
|
160
|
+
raise ValueError("distinct_role_count does not match the branch facts")
|
|
161
|
+
expected_families = len({self.pair.left.family, self.pair.right.family})
|
|
162
|
+
if (
|
|
163
|
+
type(self.distinct_family_count) is not int
|
|
164
|
+
or self.distinct_family_count != expected_families
|
|
165
|
+
):
|
|
166
|
+
raise ValueError("distinct_family_count does not match the branch facts")
|
|
167
|
+
expected_exposure = (
|
|
168
|
+
self.pair.left.path_family_exposure + self.pair.right.path_family_exposure
|
|
169
|
+
)
|
|
170
|
+
_count(expected_exposure, name="aggregated pair exposure")
|
|
171
|
+
if (
|
|
172
|
+
type(self.path_family_exposure_sum) is not int
|
|
173
|
+
or self.path_family_exposure_sum != expected_exposure
|
|
174
|
+
):
|
|
175
|
+
raise ValueError("path_family_exposure_sum does not match the branch facts")
|
|
176
|
+
|
|
177
|
+
def revalidate(self) -> None:
|
|
178
|
+
if type(self) is not DisjointPairScoreRow:
|
|
179
|
+
raise TypeError("score row must be an exact DisjointPairScoreRow")
|
|
180
|
+
DisjointPairScoreRow.__post_init__(self)
|
|
181
|
+
|
|
182
|
+
@property
|
|
183
|
+
def pair_ids(self) -> tuple[CandidateId, CandidateId]:
|
|
184
|
+
self.revalidate()
|
|
185
|
+
return self.pair.pair_ids
|
|
186
|
+
|
|
187
|
+
def _key(self) -> tuple[object, ...]:
|
|
188
|
+
self.revalidate()
|
|
189
|
+
return (
|
|
190
|
+
*_pair_key(self.pair),
|
|
191
|
+
self.pair.target_configuration_sha256,
|
|
192
|
+
self.pair.materialization_receipt_sha256,
|
|
193
|
+
self.branch_reward_sum,
|
|
194
|
+
self.distinct_role_count,
|
|
195
|
+
self.distinct_family_count,
|
|
196
|
+
self.path_family_exposure_sum,
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
def __eq__(self, other: object) -> bool:
|
|
200
|
+
return (
|
|
201
|
+
type(self) is DisjointPairScoreRow
|
|
202
|
+
and type(other) is DisjointPairScoreRow
|
|
203
|
+
and self._key() == other._key()
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
__hash__ = None
|
|
207
|
+
|
|
208
|
+
def to_trace_record(
|
|
209
|
+
self,
|
|
210
|
+
*,
|
|
211
|
+
exploit_target_configuration_sha256: str | None,
|
|
212
|
+
) -> dict[str, object]:
|
|
213
|
+
self.revalidate()
|
|
214
|
+
if exploit_target_configuration_sha256 is not None:
|
|
215
|
+
require_sha256(
|
|
216
|
+
exploit_target_configuration_sha256,
|
|
217
|
+
"exploit_target_configuration_sha256",
|
|
218
|
+
)
|
|
219
|
+
return {
|
|
220
|
+
**self.pair.to_trace_record(),
|
|
221
|
+
"branch_reward_sum": self.branch_reward_sum,
|
|
222
|
+
"distinct_role_count": self.distinct_role_count,
|
|
223
|
+
"distinct_family_count": self.distinct_family_count,
|
|
224
|
+
"path_family_exposure_sum": self.path_family_exposure_sum,
|
|
225
|
+
"target_distinct_from_exploit": (
|
|
226
|
+
None
|
|
227
|
+
if exploit_target_configuration_sha256 is None
|
|
228
|
+
else self.pair.target_configuration_sha256
|
|
229
|
+
!= exploit_target_configuration_sha256
|
|
230
|
+
),
|
|
231
|
+
"exploit_tie_key": [
|
|
232
|
+
-self.branch_reward_sum,
|
|
233
|
+
-self.distinct_role_count,
|
|
234
|
+
self.pair.left.candidate_id.value,
|
|
235
|
+
self.pair.right.candidate_id.value,
|
|
236
|
+
],
|
|
237
|
+
"coverage_tie_key": [
|
|
238
|
+
-self.distinct_family_count,
|
|
239
|
+
-self.distinct_role_count,
|
|
240
|
+
self.path_family_exposure_sum,
|
|
241
|
+
self.pair.left.candidate_id.value,
|
|
242
|
+
self.pair.right.candidate_id.value,
|
|
243
|
+
],
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def _score_row(pair: ReplayVerifiedDisjointPair) -> DisjointPairScoreRow:
|
|
248
|
+
pair.revalidate()
|
|
249
|
+
reward_sum = pair.left.reward + pair.right.reward
|
|
250
|
+
if not math.isfinite(reward_sum):
|
|
251
|
+
raise ValueError("branch reward sum must be finite")
|
|
252
|
+
exposure_sum = pair.left.path_family_exposure + pair.right.path_family_exposure
|
|
253
|
+
_count(exposure_sum, name="aggregated pair exposure")
|
|
254
|
+
return DisjointPairScoreRow(
|
|
255
|
+
pair=pair,
|
|
256
|
+
branch_reward_sum=float(reward_sum),
|
|
257
|
+
distinct_role_count=len({pair.left.role, pair.right.role}),
|
|
258
|
+
distinct_family_count=len({pair.left.family, pair.right.family}),
|
|
259
|
+
path_family_exposure_sum=exposure_sum,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _canonical_rows(
|
|
264
|
+
pairs: Sequence[ReplayVerifiedDisjointPair],
|
|
265
|
+
) -> tuple[DisjointPairScoreRow, ...]:
|
|
266
|
+
if isinstance(pairs, (str, bytes)):
|
|
267
|
+
raise TypeError("eligible_pairs must be a finite pair sequence")
|
|
268
|
+
values = tuple(pairs)
|
|
269
|
+
for pair in values:
|
|
270
|
+
if type(pair) is not ReplayVerifiedDisjointPair:
|
|
271
|
+
raise TypeError(
|
|
272
|
+
"eligible_pairs must contain exact ReplayVerifiedDisjointPair values"
|
|
273
|
+
)
|
|
274
|
+
pair.revalidate()
|
|
275
|
+
keys = [_pair_key(pair) for pair in values]
|
|
276
|
+
if len(set(keys)) != len(keys):
|
|
277
|
+
raise ValueError("eligible pair candidate-ID sets must be unique")
|
|
278
|
+
receipts = [pair.materialization_receipt_sha256 for pair in values]
|
|
279
|
+
if len(set(receipts)) != len(receipts):
|
|
280
|
+
raise ValueError("materialization receipts must be unique across pairs")
|
|
281
|
+
|
|
282
|
+
candidate_facts: dict[str, DisjointBranchFacts] = {}
|
|
283
|
+
for pair in values:
|
|
284
|
+
for branch in (pair.left, pair.right):
|
|
285
|
+
candidate_key = branch.candidate_id.value
|
|
286
|
+
existing = candidate_facts.get(candidate_key)
|
|
287
|
+
if existing is not None and existing != branch:
|
|
288
|
+
raise ValueError(
|
|
289
|
+
"one candidate has inconsistent branch facts across eligible pairs"
|
|
290
|
+
)
|
|
291
|
+
candidate_facts[candidate_key] = branch
|
|
292
|
+
return tuple(
|
|
293
|
+
sorted(
|
|
294
|
+
(_score_row(pair) for pair in values), key=lambda row: _pair_key(row.pair)
|
|
295
|
+
)
|
|
296
|
+
)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
def _select_rows(
|
|
300
|
+
rows: tuple[DisjointPairScoreRow, ...],
|
|
301
|
+
) -> tuple[DisjointPairScoreRow | None, DisjointPairScoreRow | None]:
|
|
302
|
+
if not rows:
|
|
303
|
+
return None, None
|
|
304
|
+
exploit = min(
|
|
305
|
+
rows,
|
|
306
|
+
key=lambda row: (
|
|
307
|
+
-row.branch_reward_sum,
|
|
308
|
+
-row.distinct_role_count,
|
|
309
|
+
*_pair_key(row.pair),
|
|
310
|
+
),
|
|
311
|
+
)
|
|
312
|
+
coverage_pool = tuple(
|
|
313
|
+
row
|
|
314
|
+
for row in rows
|
|
315
|
+
if row.pair.target_configuration_sha256
|
|
316
|
+
!= exploit.pair.target_configuration_sha256
|
|
317
|
+
)
|
|
318
|
+
if not coverage_pool:
|
|
319
|
+
return exploit, None
|
|
320
|
+
coverage = min(
|
|
321
|
+
coverage_pool,
|
|
322
|
+
key=lambda row: (
|
|
323
|
+
-row.distinct_family_count,
|
|
324
|
+
-row.distinct_role_count,
|
|
325
|
+
row.path_family_exposure_sum,
|
|
326
|
+
*_pair_key(row.pair),
|
|
327
|
+
),
|
|
328
|
+
)
|
|
329
|
+
return exploit, coverage
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
333
|
+
class DisjointPairSelectionDecision:
|
|
334
|
+
"""All eligible score rows and the exact exploit/coverage selections."""
|
|
335
|
+
|
|
336
|
+
eligible_rows: tuple[DisjointPairScoreRow, ...]
|
|
337
|
+
exploit_pair_ids: tuple[CandidateId, CandidateId] | None
|
|
338
|
+
coverage_pair_ids: tuple[CandidateId, CandidateId] | None
|
|
339
|
+
|
|
340
|
+
policy_id: ClassVar[str] = POLICY_ID
|
|
341
|
+
policy_version: ClassVar[int] = POLICY_VERSION
|
|
342
|
+
|
|
343
|
+
def __post_init__(self) -> None:
|
|
344
|
+
if type(self.eligible_rows) is not tuple or any(
|
|
345
|
+
type(row) is not DisjointPairScoreRow for row in self.eligible_rows
|
|
346
|
+
):
|
|
347
|
+
raise TypeError(
|
|
348
|
+
"eligible_rows must contain exact DisjointPairScoreRow values"
|
|
349
|
+
)
|
|
350
|
+
expected_rows = _canonical_rows(tuple(row.pair for row in self.eligible_rows))
|
|
351
|
+
if self.eligible_rows != expected_rows:
|
|
352
|
+
raise ValueError("eligible_rows must be complete and canonically ordered")
|
|
353
|
+
exploit, coverage = _select_rows(expected_rows)
|
|
354
|
+
expected_exploit = None if exploit is None else exploit.pair_ids
|
|
355
|
+
expected_coverage = None if coverage is None else coverage.pair_ids
|
|
356
|
+
if self.exploit_pair_ids != expected_exploit:
|
|
357
|
+
raise ValueError("exploit_pair_ids do not match the exploit rule")
|
|
358
|
+
if self.coverage_pair_ids != expected_coverage:
|
|
359
|
+
raise ValueError("coverage_pair_ids do not match the coverage rule")
|
|
360
|
+
|
|
361
|
+
def revalidate(self) -> None:
|
|
362
|
+
if type(self) is not DisjointPairSelectionDecision:
|
|
363
|
+
raise TypeError("decision must be an exact DisjointPairSelectionDecision")
|
|
364
|
+
DisjointPairSelectionDecision.__post_init__(self)
|
|
365
|
+
|
|
366
|
+
def _row_for(
|
|
367
|
+
self,
|
|
368
|
+
pair_ids: tuple[CandidateId, CandidateId] | None,
|
|
369
|
+
) -> DisjointPairScoreRow | None:
|
|
370
|
+
if pair_ids is None:
|
|
371
|
+
return None
|
|
372
|
+
return next(row for row in self.eligible_rows if row.pair_ids == pair_ids)
|
|
373
|
+
|
|
374
|
+
@property
|
|
375
|
+
def exploit(self) -> DisjointPairScoreRow | None:
|
|
376
|
+
self.revalidate()
|
|
377
|
+
return self._row_for(self.exploit_pair_ids)
|
|
378
|
+
|
|
379
|
+
@property
|
|
380
|
+
def coverage(self) -> DisjointPairScoreRow | None:
|
|
381
|
+
self.revalidate()
|
|
382
|
+
return self._row_for(self.coverage_pair_ids)
|
|
383
|
+
|
|
384
|
+
def _trace_payload(self) -> dict[str, object]:
|
|
385
|
+
exploit = self._row_for(self.exploit_pair_ids)
|
|
386
|
+
coverage = self._row_for(self.coverage_pair_ids)
|
|
387
|
+
exploit_target = (
|
|
388
|
+
None if exploit is None else exploit.pair.target_configuration_sha256
|
|
389
|
+
)
|
|
390
|
+
return {
|
|
391
|
+
"event_type": "recombination_pair_selected",
|
|
392
|
+
"policy_id": self.policy_id,
|
|
393
|
+
"policy_version": self.policy_version,
|
|
394
|
+
"eligible_rows": [
|
|
395
|
+
row.to_trace_record(
|
|
396
|
+
exploit_target_configuration_sha256=exploit_target,
|
|
397
|
+
)
|
|
398
|
+
for row in self.eligible_rows
|
|
399
|
+
],
|
|
400
|
+
"exploit_pair_ids": (
|
|
401
|
+
None
|
|
402
|
+
if exploit is None
|
|
403
|
+
else [candidate_id.value for candidate_id in exploit.pair_ids]
|
|
404
|
+
),
|
|
405
|
+
"exploit_target_configuration_sha256": exploit_target,
|
|
406
|
+
"coverage_pair_ids": (
|
|
407
|
+
None
|
|
408
|
+
if coverage is None
|
|
409
|
+
else [candidate_id.value for candidate_id in coverage.pair_ids]
|
|
410
|
+
),
|
|
411
|
+
"coverage_target_configuration_sha256": (
|
|
412
|
+
None if coverage is None else coverage.pair.target_configuration_sha256
|
|
413
|
+
),
|
|
414
|
+
"exploit_rule": (
|
|
415
|
+
"maximum branch reward sum; maximum distinct roles; "
|
|
416
|
+
"canonical candidate IDs"
|
|
417
|
+
),
|
|
418
|
+
"coverage_rule": (
|
|
419
|
+
"target configuration distinct from exploit; maximum distinct "
|
|
420
|
+
"families; maximum distinct roles; minimum prior path/family "
|
|
421
|
+
"exposure; canonical candidate IDs"
|
|
422
|
+
),
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
@property
|
|
426
|
+
def decision_sha256(self) -> str:
|
|
427
|
+
self.revalidate()
|
|
428
|
+
encoded = json.dumps(
|
|
429
|
+
self._trace_payload(),
|
|
430
|
+
allow_nan=False,
|
|
431
|
+
ensure_ascii=True,
|
|
432
|
+
separators=(",", ":"),
|
|
433
|
+
sort_keys=True,
|
|
434
|
+
).encode("ascii")
|
|
435
|
+
return hashlib.sha256(_DECISION_DOMAIN + encoded).hexdigest()
|
|
436
|
+
|
|
437
|
+
def to_trace_record(self) -> dict[str, object]:
|
|
438
|
+
self.revalidate()
|
|
439
|
+
return {**self._trace_payload(), "decision_sha256": self.decision_sha256}
|
|
440
|
+
|
|
441
|
+
def __eq__(self, other: object) -> bool:
|
|
442
|
+
return (
|
|
443
|
+
type(self) is DisjointPairSelectionDecision
|
|
444
|
+
and type(other) is DisjointPairSelectionDecision
|
|
445
|
+
and self.decision_sha256 == other.decision_sha256
|
|
446
|
+
)
|
|
447
|
+
|
|
448
|
+
__hash__ = None
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
@dataclass(frozen=True, slots=True)
|
|
452
|
+
class DisjointParentPairPolicy:
|
|
453
|
+
"""Select exploit first and a target-distinct coverage pair second."""
|
|
454
|
+
|
|
455
|
+
policy_id: ClassVar[str] = POLICY_ID
|
|
456
|
+
policy_version: ClassVar[int] = POLICY_VERSION
|
|
457
|
+
|
|
458
|
+
def select(
|
|
459
|
+
self,
|
|
460
|
+
eligible_pairs: Sequence[ReplayVerifiedDisjointPair],
|
|
461
|
+
) -> DisjointPairSelectionDecision:
|
|
462
|
+
rows = _canonical_rows(eligible_pairs)
|
|
463
|
+
exploit, coverage = _select_rows(rows)
|
|
464
|
+
return DisjointPairSelectionDecision(
|
|
465
|
+
eligible_rows=rows,
|
|
466
|
+
exploit_pair_ids=None if exploit is None else exploit.pair_ids,
|
|
467
|
+
coverage_pair_ids=None if coverage is None else coverage.pair_ids,
|
|
468
|
+
)
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
__all__ = [
|
|
472
|
+
"DisjointBranchFacts",
|
|
473
|
+
"DisjointPairScoreRow",
|
|
474
|
+
"DisjointPairSelectionDecision",
|
|
475
|
+
"DisjointParentPairPolicy",
|
|
476
|
+
"POLICY_ID",
|
|
477
|
+
"POLICY_VERSION",
|
|
478
|
+
"ReplayVerifiedDisjointPair",
|
|
479
|
+
]
|