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,34 @@
|
|
|
1
|
+
"""ID allocation port."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Protocol, runtime_checkable
|
|
6
|
+
|
|
7
|
+
from agent_evolve.domain.ids import (
|
|
8
|
+
CandidateId,
|
|
9
|
+
CorrelationId,
|
|
10
|
+
EvaluationAttemptId,
|
|
11
|
+
EvaluationId,
|
|
12
|
+
EventId,
|
|
13
|
+
GenerationId,
|
|
14
|
+
InsightId,
|
|
15
|
+
LLMCallId,
|
|
16
|
+
OperatorInvocationId,
|
|
17
|
+
ProviderAttemptId,
|
|
18
|
+
RunId,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@runtime_checkable
|
|
23
|
+
class IdFactory(Protocol):
|
|
24
|
+
def new_run_id(self) -> RunId: ...
|
|
25
|
+
def new_event_id(self) -> EventId: ...
|
|
26
|
+
def new_generation_id(self) -> GenerationId: ...
|
|
27
|
+
def new_candidate_id(self) -> CandidateId: ...
|
|
28
|
+
def new_insight_id(self) -> InsightId: ...
|
|
29
|
+
def new_operator_invocation_id(self) -> OperatorInvocationId: ...
|
|
30
|
+
def new_llm_call_id(self) -> LLMCallId: ...
|
|
31
|
+
def new_provider_attempt_id(self) -> ProviderAttemptId: ...
|
|
32
|
+
def new_evaluation_id(self) -> EvaluationId: ...
|
|
33
|
+
def new_evaluation_attempt_id(self) -> EvaluationAttemptId: ...
|
|
34
|
+
def new_correlation_id(self) -> CorrelationId: ...
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""Provider-neutral ports consumed by the asynchronous LLM task queue."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Awaitable, Callable, Generic, Protocol, TypeVar, runtime_checkable
|
|
7
|
+
|
|
8
|
+
from agent_evolve.domain.llm_task_queue import (
|
|
9
|
+
AttemptRequestEvidence,
|
|
10
|
+
LLMAttemptContext,
|
|
11
|
+
RetryClassification,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
RequestT_contra = TypeVar("RequestT_contra", contravariant=True)
|
|
16
|
+
ResponseT_co = TypeVar("ResponseT_co", covariant=True)
|
|
17
|
+
AwaitedT = TypeVar("AwaitedT")
|
|
18
|
+
PreparedResponseT = TypeVar("PreparedResponseT")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ExecutorRetiredError(Exception):
|
|
22
|
+
"""Marker for an attempt failure that permanently retired its executor.
|
|
23
|
+
|
|
24
|
+
The queue uses this benchmark- and provider-neutral signal to close
|
|
25
|
+
admission and cancel sibling work instead of promoting or retrying tasks
|
|
26
|
+
against a transport that can no longer execute requests.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True, slots=True)
|
|
31
|
+
class PreparedLLMAttempt(Generic[PreparedResponseT]):
|
|
32
|
+
"""One already-derived attempt plus content-free request evidence."""
|
|
33
|
+
|
|
34
|
+
execute_once: Callable[[], Awaitable[PreparedResponseT]]
|
|
35
|
+
request_evidence: AttemptRequestEvidence
|
|
36
|
+
|
|
37
|
+
def __post_init__(self) -> None:
|
|
38
|
+
if not callable(self.execute_once):
|
|
39
|
+
raise TypeError("execute_once must be callable")
|
|
40
|
+
if type(self.request_evidence) is not AttemptRequestEvidence:
|
|
41
|
+
raise TypeError("request_evidence must be an AttemptRequestEvidence")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@runtime_checkable
|
|
45
|
+
class AsyncLLMTaskExecutor(Protocol[RequestT_contra, ResponseT_co]):
|
|
46
|
+
async def execute(
|
|
47
|
+
self,
|
|
48
|
+
request: RequestT_contra,
|
|
49
|
+
*,
|
|
50
|
+
context: LLMAttemptContext,
|
|
51
|
+
) -> ResponseT_co: ...
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@runtime_checkable
|
|
55
|
+
class AttemptPreparingExecutor(Protocol[RequestT_contra, ResponseT_co]):
|
|
56
|
+
def prepare_attempt(
|
|
57
|
+
self,
|
|
58
|
+
request: RequestT_contra,
|
|
59
|
+
*,
|
|
60
|
+
context: LLMAttemptContext,
|
|
61
|
+
) -> PreparedLLMAttempt[ResponseT_co]: ...
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@runtime_checkable
|
|
65
|
+
class RetryClassifier(Protocol):
|
|
66
|
+
def classify(
|
|
67
|
+
self,
|
|
68
|
+
error: Exception,
|
|
69
|
+
*,
|
|
70
|
+
context: LLMAttemptContext,
|
|
71
|
+
) -> RetryClassification: ...
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@runtime_checkable
|
|
75
|
+
class BackoffPolicy(Protocol):
|
|
76
|
+
def delay_ns(
|
|
77
|
+
self,
|
|
78
|
+
*,
|
|
79
|
+
task_id: str,
|
|
80
|
+
failed_attempt_number: int,
|
|
81
|
+
classification: RetryClassification,
|
|
82
|
+
) -> int: ...
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@runtime_checkable
|
|
86
|
+
class AsyncRuntime(Protocol):
|
|
87
|
+
async def sleep(self, delay_ns: int) -> None: ...
|
|
88
|
+
|
|
89
|
+
async def wait_for(
|
|
90
|
+
self,
|
|
91
|
+
awaitable: Awaitable[AwaitedT],
|
|
92
|
+
timeout_ns: int | None,
|
|
93
|
+
) -> AwaitedT: ...
|
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
"""Benchmark-neutral objective resolution at the evaluation boundary.
|
|
2
|
+
|
|
3
|
+
Evaluators report physical measurements. Optimizers need stable decision
|
|
4
|
+
values: repeated measurements that differ only below a benchmark-declared
|
|
5
|
+
resolution must not become artificial Pareto improvements. This port keeps
|
|
6
|
+
those two facts separate. A resolver receives the frozen configuration and
|
|
7
|
+
the complete raw objective vector, then returns the values used for selection.
|
|
8
|
+
|
|
9
|
+
The application calls a resolver repeatedly to fail closed on mutable,
|
|
10
|
+
non-deterministic, or non-idempotent policies. Raw measurements remain in an
|
|
11
|
+
immutable receipt even when the decision values are canonicalized.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import hashlib
|
|
17
|
+
import json
|
|
18
|
+
import math
|
|
19
|
+
import re
|
|
20
|
+
from dataclasses import dataclass, field
|
|
21
|
+
from typing import Protocol, runtime_checkable
|
|
22
|
+
|
|
23
|
+
from agent_evolve.core.problem import ObjectiveSpec, validate_objective_specs
|
|
24
|
+
from agent_evolve.domain.patch import require_sha256
|
|
25
|
+
from agent_evolve.domain.typed_json import (
|
|
26
|
+
FrozenJsonObject,
|
|
27
|
+
freeze_json,
|
|
28
|
+
thaw_json,
|
|
29
|
+
typed_json_sha256,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
_POLICY_ID = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
|
|
34
|
+
_REQUEST_DOMAIN = b"agent-evolve:objective-resolution-request:v1\x00"
|
|
35
|
+
_RECEIPT_DOMAIN = b"agent-evolve:objective-resolution-receipt:v1\x00"
|
|
36
|
+
|
|
37
|
+
EXACT_OBJECTIVE_RESOLUTION_POLICY_ID = "exact_objective_values"
|
|
38
|
+
EXACT_OBJECTIVE_RESOLUTION_POLICY_VERSION = 1
|
|
39
|
+
EXACT_OBJECTIVE_RESOLUTION_DEFINITION_SHA256 = hashlib.sha256(
|
|
40
|
+
b"agent-evolve:exact-objective-resolution:v1\x00"
|
|
41
|
+
b"decision_objectives=raw_objectives"
|
|
42
|
+
).hexdigest()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _canonical_json(value: object) -> bytes:
|
|
46
|
+
return json.dumps(
|
|
47
|
+
value,
|
|
48
|
+
allow_nan=False,
|
|
49
|
+
ensure_ascii=True,
|
|
50
|
+
separators=(",", ":"),
|
|
51
|
+
sort_keys=True,
|
|
52
|
+
).encode("ascii")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def _hash(domain: bytes, value: object) -> str:
|
|
56
|
+
return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _validate_objective_vector(
|
|
60
|
+
values: tuple[tuple[str, float], ...],
|
|
61
|
+
*,
|
|
62
|
+
name: str,
|
|
63
|
+
) -> tuple[str, ...]:
|
|
64
|
+
if type(values) is not tuple or not values:
|
|
65
|
+
raise ValueError(f"{name} must be a non-empty exact tuple")
|
|
66
|
+
metric_ids: list[str] = []
|
|
67
|
+
for item in values:
|
|
68
|
+
if type(item) is not tuple or len(item) != 2:
|
|
69
|
+
raise TypeError(f"{name} entries must be exact (metric_id, value) tuples")
|
|
70
|
+
metric_id, value = item
|
|
71
|
+
if type(metric_id) is not str or not metric_id.strip():
|
|
72
|
+
raise ValueError(f"{name} metric IDs must be non-empty exact strings")
|
|
73
|
+
if type(value) is not float or not math.isfinite(value):
|
|
74
|
+
raise TypeError(f"{name} values must be finite canonical floats")
|
|
75
|
+
metric_ids.append(metric_id)
|
|
76
|
+
if len(set(metric_ids)) != len(metric_ids):
|
|
77
|
+
raise ValueError(f"{name} metric IDs must be unique")
|
|
78
|
+
return tuple(metric_ids)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _objective_vector_record(
|
|
82
|
+
values: tuple[tuple[str, float], ...],
|
|
83
|
+
) -> list[dict[str, str]]:
|
|
84
|
+
return [
|
|
85
|
+
{"metric_id": metric_id, "value_hex": value.hex()}
|
|
86
|
+
for metric_id, value in values
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@dataclass(frozen=True, slots=True)
|
|
91
|
+
class ObjectiveResolutionRequest:
|
|
92
|
+
"""One complete raw evaluation projected into decision-value semantics."""
|
|
93
|
+
|
|
94
|
+
configuration: FrozenJsonObject
|
|
95
|
+
objectives: tuple[ObjectiveSpec, ...]
|
|
96
|
+
raw_objectives: tuple[tuple[str, float], ...]
|
|
97
|
+
|
|
98
|
+
def __post_init__(self) -> None:
|
|
99
|
+
if type(self.configuration) is not FrozenJsonObject:
|
|
100
|
+
raise TypeError("configuration must be an exact FrozenJsonObject")
|
|
101
|
+
if freeze_json(self.configuration) is not self.configuration:
|
|
102
|
+
raise TypeError("configuration must already be frozen typed JSON")
|
|
103
|
+
if type(self.objectives) is not tuple:
|
|
104
|
+
raise TypeError("objectives must be an exact tuple")
|
|
105
|
+
if any(type(value) is not ObjectiveSpec for value in self.objectives):
|
|
106
|
+
raise TypeError("objectives must contain exact ObjectiveSpec values")
|
|
107
|
+
validate_objective_specs(self.objectives)
|
|
108
|
+
metric_ids = _validate_objective_vector(
|
|
109
|
+
self.raw_objectives,
|
|
110
|
+
name="raw_objectives",
|
|
111
|
+
)
|
|
112
|
+
expected = tuple(value.name for value in self.objectives)
|
|
113
|
+
if metric_ids != expected:
|
|
114
|
+
raise ValueError(
|
|
115
|
+
"raw_objectives must be complete and follow objective declaration order"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
@property
|
|
119
|
+
def configuration_sha256(self) -> str:
|
|
120
|
+
self.__post_init__()
|
|
121
|
+
return typed_json_sha256(self.configuration)
|
|
122
|
+
|
|
123
|
+
def payload_record(self) -> dict[str, object]:
|
|
124
|
+
self.__post_init__()
|
|
125
|
+
return {
|
|
126
|
+
"schema_version": 1,
|
|
127
|
+
"configuration_sha256": self.configuration_sha256,
|
|
128
|
+
"objectives": [
|
|
129
|
+
{"metric_id": objective.name, "goal": objective.goal}
|
|
130
|
+
for objective in self.objectives
|
|
131
|
+
],
|
|
132
|
+
"raw_objectives": _objective_vector_record(self.raw_objectives),
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def request_sha256(self) -> str:
|
|
137
|
+
return _hash(_REQUEST_DOMAIN, self.payload_record())
|
|
138
|
+
|
|
139
|
+
def to_record(self) -> dict[str, object]:
|
|
140
|
+
return {**self.payload_record(), "request_sha256": self.request_sha256}
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@dataclass(frozen=True, slots=True)
|
|
144
|
+
class ObjectiveResolutionResult:
|
|
145
|
+
"""Untrusted policy output before application-owned receipt sealing."""
|
|
146
|
+
|
|
147
|
+
request_sha256: str
|
|
148
|
+
decision_objectives: tuple[tuple[str, float], ...]
|
|
149
|
+
evidence: FrozenJsonObject = field(default_factory=lambda: FrozenJsonObject(()))
|
|
150
|
+
|
|
151
|
+
def __post_init__(self) -> None:
|
|
152
|
+
require_sha256(self.request_sha256, "request_sha256")
|
|
153
|
+
_validate_objective_vector(
|
|
154
|
+
self.decision_objectives,
|
|
155
|
+
name="decision_objectives",
|
|
156
|
+
)
|
|
157
|
+
if type(self.evidence) is not FrozenJsonObject:
|
|
158
|
+
raise TypeError("evidence must be an exact FrozenJsonObject")
|
|
159
|
+
if freeze_json(self.evidence) is not self.evidence:
|
|
160
|
+
raise TypeError("evidence must already be frozen typed JSON")
|
|
161
|
+
|
|
162
|
+
def to_record(self) -> dict[str, object]:
|
|
163
|
+
self.__post_init__()
|
|
164
|
+
return {
|
|
165
|
+
"request_sha256": self.request_sha256,
|
|
166
|
+
"decision_objectives": _objective_vector_record(
|
|
167
|
+
self.decision_objectives
|
|
168
|
+
),
|
|
169
|
+
"evidence_sha256": typed_json_sha256(self.evidence),
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
@dataclass(frozen=True, slots=True)
|
|
174
|
+
class ObjectiveResolutionReceipt:
|
|
175
|
+
"""Application-sealed link between raw evidence and decision values."""
|
|
176
|
+
|
|
177
|
+
request_sha256: str
|
|
178
|
+
configuration_sha256: str
|
|
179
|
+
raw_objectives: tuple[tuple[str, float], ...]
|
|
180
|
+
decision_objectives: tuple[tuple[str, float], ...]
|
|
181
|
+
policy_id: str
|
|
182
|
+
policy_version: int
|
|
183
|
+
policy_definition_sha256: str
|
|
184
|
+
evidence: FrozenJsonObject = field(default_factory=lambda: FrozenJsonObject(()))
|
|
185
|
+
|
|
186
|
+
def __post_init__(self) -> None:
|
|
187
|
+
require_sha256(self.request_sha256, "request_sha256")
|
|
188
|
+
require_sha256(self.configuration_sha256, "configuration_sha256")
|
|
189
|
+
raw_ids = _validate_objective_vector(
|
|
190
|
+
self.raw_objectives,
|
|
191
|
+
name="raw_objectives",
|
|
192
|
+
)
|
|
193
|
+
decision_ids = _validate_objective_vector(
|
|
194
|
+
self.decision_objectives,
|
|
195
|
+
name="decision_objectives",
|
|
196
|
+
)
|
|
197
|
+
if raw_ids != decision_ids:
|
|
198
|
+
raise ValueError(
|
|
199
|
+
"raw and decision objective vectors must have identical metric order"
|
|
200
|
+
)
|
|
201
|
+
_validate_policy_identity(
|
|
202
|
+
self.policy_id,
|
|
203
|
+
self.policy_version,
|
|
204
|
+
self.policy_definition_sha256,
|
|
205
|
+
)
|
|
206
|
+
if type(self.evidence) is not FrozenJsonObject:
|
|
207
|
+
raise TypeError("evidence must be an exact FrozenJsonObject")
|
|
208
|
+
if freeze_json(self.evidence) is not self.evidence:
|
|
209
|
+
raise TypeError("evidence must already be frozen typed JSON")
|
|
210
|
+
|
|
211
|
+
@property
|
|
212
|
+
def policy_identity(self) -> tuple[str, int, str]:
|
|
213
|
+
self.__post_init__()
|
|
214
|
+
return (
|
|
215
|
+
self.policy_id,
|
|
216
|
+
self.policy_version,
|
|
217
|
+
self.policy_definition_sha256,
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
def payload_record(self) -> dict[str, object]:
|
|
221
|
+
self.__post_init__()
|
|
222
|
+
return {
|
|
223
|
+
"schema_version": 1,
|
|
224
|
+
"request_sha256": self.request_sha256,
|
|
225
|
+
"configuration_sha256": self.configuration_sha256,
|
|
226
|
+
"raw_objectives": _objective_vector_record(self.raw_objectives),
|
|
227
|
+
"decision_objectives": _objective_vector_record(
|
|
228
|
+
self.decision_objectives
|
|
229
|
+
),
|
|
230
|
+
"policy": {
|
|
231
|
+
"policy_id": self.policy_id,
|
|
232
|
+
"policy_version": self.policy_version,
|
|
233
|
+
"definition_sha256": self.policy_definition_sha256,
|
|
234
|
+
},
|
|
235
|
+
"evidence_sha256": typed_json_sha256(self.evidence),
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
@property
|
|
239
|
+
def receipt_sha256(self) -> str:
|
|
240
|
+
return _hash(_RECEIPT_DOMAIN, self.payload_record())
|
|
241
|
+
|
|
242
|
+
def to_record(self) -> dict[str, object]:
|
|
243
|
+
return {
|
|
244
|
+
**self.payload_record(),
|
|
245
|
+
"evidence": thaw_json(self.evidence),
|
|
246
|
+
"receipt_sha256": self.receipt_sha256,
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
def revalidate(self) -> None:
|
|
250
|
+
self.__post_init__()
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
@runtime_checkable
|
|
254
|
+
class ObjectiveResolutionPort(Protocol):
|
|
255
|
+
"""Resolve stable decision values from raw benchmark measurements."""
|
|
256
|
+
|
|
257
|
+
@property
|
|
258
|
+
def policy_id(self) -> str: ...
|
|
259
|
+
|
|
260
|
+
@property
|
|
261
|
+
def policy_version(self) -> int: ...
|
|
262
|
+
|
|
263
|
+
@property
|
|
264
|
+
def definition_sha256(self) -> str: ...
|
|
265
|
+
|
|
266
|
+
def resolve(
|
|
267
|
+
self,
|
|
268
|
+
request: ObjectiveResolutionRequest,
|
|
269
|
+
) -> ObjectiveResolutionResult: ...
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def _validate_policy_identity(
|
|
273
|
+
policy_id: object,
|
|
274
|
+
policy_version: object,
|
|
275
|
+
definition_sha256: object,
|
|
276
|
+
) -> tuple[str, int, str]:
|
|
277
|
+
if type(policy_id) is not str or _POLICY_ID.fullmatch(policy_id) is None:
|
|
278
|
+
raise ValueError("objective-resolution policy_id is not canonical")
|
|
279
|
+
if type(policy_version) is not int or policy_version <= 0:
|
|
280
|
+
raise ValueError("objective-resolution policy_version must be positive")
|
|
281
|
+
require_sha256(definition_sha256, "objective-resolution definition_sha256")
|
|
282
|
+
return policy_id, policy_version, definition_sha256
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def objective_resolution_policy_metadata(
|
|
286
|
+
policy: ObjectiveResolutionPort,
|
|
287
|
+
) -> tuple[str, int, str]:
|
|
288
|
+
"""Validate and return the immutable scientific identity of a resolver."""
|
|
289
|
+
|
|
290
|
+
if not isinstance(policy, ObjectiveResolutionPort):
|
|
291
|
+
raise TypeError(
|
|
292
|
+
"objective_resolution must implement ObjectiveResolutionPort"
|
|
293
|
+
)
|
|
294
|
+
return _validate_policy_identity(
|
|
295
|
+
policy.policy_id,
|
|
296
|
+
policy.policy_version,
|
|
297
|
+
policy.definition_sha256,
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def _validated_result(
|
|
302
|
+
result: object,
|
|
303
|
+
request: ObjectiveResolutionRequest,
|
|
304
|
+
) -> ObjectiveResolutionResult:
|
|
305
|
+
if type(result) is not ObjectiveResolutionResult:
|
|
306
|
+
raise TypeError("objective-resolution policy must return an exact result")
|
|
307
|
+
ObjectiveResolutionResult.__post_init__(result)
|
|
308
|
+
if result.request_sha256 != request.request_sha256:
|
|
309
|
+
raise ValueError("objective-resolution result is bound to another request")
|
|
310
|
+
expected = tuple(objective.name for objective in request.objectives)
|
|
311
|
+
actual = tuple(metric_id for metric_id, _ in result.decision_objectives)
|
|
312
|
+
if actual != expected:
|
|
313
|
+
raise ValueError(
|
|
314
|
+
"decision_objectives must be complete and follow declaration order"
|
|
315
|
+
)
|
|
316
|
+
return result
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def _resolve_twice(
|
|
320
|
+
policy: ObjectiveResolutionPort,
|
|
321
|
+
request: ObjectiveResolutionRequest,
|
|
322
|
+
metadata: tuple[str, int, str],
|
|
323
|
+
) -> ObjectiveResolutionResult:
|
|
324
|
+
first = _validated_result(policy.resolve(request), request)
|
|
325
|
+
second = _validated_result(policy.resolve(request), request)
|
|
326
|
+
if first.to_record() != second.to_record():
|
|
327
|
+
raise ValueError("objective-resolution policy must be deterministic")
|
|
328
|
+
if objective_resolution_policy_metadata(policy) != metadata:
|
|
329
|
+
raise ValueError(
|
|
330
|
+
"objective-resolution policy metadata changed during resolution"
|
|
331
|
+
)
|
|
332
|
+
return first
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def resolve_objectives(
|
|
336
|
+
policy: ObjectiveResolutionPort,
|
|
337
|
+
request: ObjectiveResolutionRequest,
|
|
338
|
+
) -> ObjectiveResolutionReceipt:
|
|
339
|
+
"""Resolve, verify, and seal decision values for one raw evaluation.
|
|
340
|
+
|
|
341
|
+
Idempotence is checked by resolving the first decision vector again. This
|
|
342
|
+
rejects drift-prone transforms (for example ``value + epsilon``) before
|
|
343
|
+
they can corrupt archive ordering or hypervolume accounting.
|
|
344
|
+
"""
|
|
345
|
+
|
|
346
|
+
if type(request) is not ObjectiveResolutionRequest:
|
|
347
|
+
raise TypeError("request must be an exact ObjectiveResolutionRequest")
|
|
348
|
+
ObjectiveResolutionRequest.__post_init__(request)
|
|
349
|
+
metadata = objective_resolution_policy_metadata(policy)
|
|
350
|
+
first = _resolve_twice(policy, request, metadata)
|
|
351
|
+
idempotence_request = ObjectiveResolutionRequest(
|
|
352
|
+
configuration=request.configuration,
|
|
353
|
+
objectives=request.objectives,
|
|
354
|
+
raw_objectives=first.decision_objectives,
|
|
355
|
+
)
|
|
356
|
+
idempotent = _resolve_twice(policy, idempotence_request, metadata)
|
|
357
|
+
if _objective_vector_record(
|
|
358
|
+
idempotent.decision_objectives
|
|
359
|
+
) != _objective_vector_record(first.decision_objectives):
|
|
360
|
+
raise ValueError("objective-resolution policy must be idempotent")
|
|
361
|
+
policy_id, policy_version, definition_sha256 = metadata
|
|
362
|
+
return ObjectiveResolutionReceipt(
|
|
363
|
+
request_sha256=request.request_sha256,
|
|
364
|
+
configuration_sha256=request.configuration_sha256,
|
|
365
|
+
raw_objectives=request.raw_objectives,
|
|
366
|
+
decision_objectives=first.decision_objectives,
|
|
367
|
+
policy_id=policy_id,
|
|
368
|
+
policy_version=policy_version,
|
|
369
|
+
policy_definition_sha256=definition_sha256,
|
|
370
|
+
evidence=first.evidence,
|
|
371
|
+
)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
@dataclass(frozen=True, slots=True)
|
|
375
|
+
class ExactObjectiveResolution:
|
|
376
|
+
"""Identity resolver for explicit experiments and compatibility checks."""
|
|
377
|
+
|
|
378
|
+
policy_id: str = EXACT_OBJECTIVE_RESOLUTION_POLICY_ID
|
|
379
|
+
policy_version: int = EXACT_OBJECTIVE_RESOLUTION_POLICY_VERSION
|
|
380
|
+
definition_sha256: str = EXACT_OBJECTIVE_RESOLUTION_DEFINITION_SHA256
|
|
381
|
+
|
|
382
|
+
def __post_init__(self) -> None:
|
|
383
|
+
identity = _validate_policy_identity(
|
|
384
|
+
self.policy_id,
|
|
385
|
+
self.policy_version,
|
|
386
|
+
self.definition_sha256,
|
|
387
|
+
)
|
|
388
|
+
if identity != (
|
|
389
|
+
EXACT_OBJECTIVE_RESOLUTION_POLICY_ID,
|
|
390
|
+
EXACT_OBJECTIVE_RESOLUTION_POLICY_VERSION,
|
|
391
|
+
EXACT_OBJECTIVE_RESOLUTION_DEFINITION_SHA256,
|
|
392
|
+
):
|
|
393
|
+
raise ValueError("ExactObjectiveResolution identity is closed")
|
|
394
|
+
|
|
395
|
+
def resolve(
|
|
396
|
+
self,
|
|
397
|
+
request: ObjectiveResolutionRequest,
|
|
398
|
+
) -> ObjectiveResolutionResult:
|
|
399
|
+
if type(request) is not ObjectiveResolutionRequest:
|
|
400
|
+
raise TypeError("request must be an exact ObjectiveResolutionRequest")
|
|
401
|
+
ObjectiveResolutionRequest.__post_init__(request)
|
|
402
|
+
return ObjectiveResolutionResult(
|
|
403
|
+
request_sha256=request.request_sha256,
|
|
404
|
+
decision_objectives=request.raw_objectives,
|
|
405
|
+
)
|
|
406
|
+
|
|
407
|
+
|
|
408
|
+
__all__ = [
|
|
409
|
+
"EXACT_OBJECTIVE_RESOLUTION_DEFINITION_SHA256",
|
|
410
|
+
"EXACT_OBJECTIVE_RESOLUTION_POLICY_ID",
|
|
411
|
+
"EXACT_OBJECTIVE_RESOLUTION_POLICY_VERSION",
|
|
412
|
+
"ExactObjectiveResolution",
|
|
413
|
+
"ObjectiveResolutionPort",
|
|
414
|
+
"ObjectiveResolutionReceipt",
|
|
415
|
+
"ObjectiveResolutionRequest",
|
|
416
|
+
"ObjectiveResolutionResult",
|
|
417
|
+
"objective_resolution_policy_metadata",
|
|
418
|
+
"resolve_objectives",
|
|
419
|
+
]
|