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,714 @@
|
|
|
1
|
+
"""Outcome-blind candidate opportunity against an observed archive prefix.
|
|
2
|
+
|
|
3
|
+
Forecast geometry is sealed before the current candidates are evaluated.
|
|
4
|
+
After each real evaluation wave, this policy may observe only the accepted
|
|
5
|
+
prefix and recompute the conditional archive value of every still-unobserved
|
|
6
|
+
forecast. Workload semantics remain behind the injected archive-utility port.
|
|
7
|
+
|
|
8
|
+
The result is a recommendation, not evaluation authority. A caller can keep
|
|
9
|
+
an existing controller as a protected fallback whenever this policy abstains.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import hashlib
|
|
15
|
+
import json
|
|
16
|
+
import math
|
|
17
|
+
import re
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
from typing import Protocol, runtime_checkable
|
|
20
|
+
|
|
21
|
+
from agent_evolve.application.agentic_evolution import EvolutionCandidate
|
|
22
|
+
from agent_evolve.application.candidate_archive_consequence import (
|
|
23
|
+
CandidateArchivePortfolioConsequenceUtilityPort,
|
|
24
|
+
validate_candidate_archive_portfolio_consequence_utility,
|
|
25
|
+
)
|
|
26
|
+
from agent_evolve.application.forecast_geometry_portfolio import (
|
|
27
|
+
MaterializedForecastGeometryBatch,
|
|
28
|
+
MaterializedForecastGeometryMember,
|
|
29
|
+
)
|
|
30
|
+
from agent_evolve.application.prequential_archive_opportunity_calibration import (
|
|
31
|
+
ArchiveOpportunityActionContext,
|
|
32
|
+
ArchiveOpportunityCalibrationResult,
|
|
33
|
+
)
|
|
34
|
+
from agent_evolve.domain.patch import require_sha256
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
CURRENT_PREFIX_FORECAST_OPPORTUNITY_POLICY_ID = (
|
|
38
|
+
"current_prefix_forecast_opportunity"
|
|
39
|
+
)
|
|
40
|
+
CURRENT_PREFIX_FORECAST_OPPORTUNITY_POLICY_VERSION = 1
|
|
41
|
+
_TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
|
|
42
|
+
_POLICY_DOMAIN = b"agent-evolve:current-prefix-opportunity-policy:v1\x00"
|
|
43
|
+
_ARCHIVE_DOMAIN = b"agent-evolve:current-prefix-opportunity-archive:v1\x00"
|
|
44
|
+
_SCORE_DOMAIN = b"agent-evolve:current-prefix-opportunity-score:v1\x00"
|
|
45
|
+
_RANKING_DOMAIN = b"agent-evolve:current-prefix-opportunity-ranking:v1\x00"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _canonical_json(value: object) -> bytes:
|
|
49
|
+
return json.dumps(
|
|
50
|
+
value,
|
|
51
|
+
allow_nan=False,
|
|
52
|
+
ensure_ascii=True,
|
|
53
|
+
separators=(",", ":"),
|
|
54
|
+
sort_keys=True,
|
|
55
|
+
).encode("ascii", errors="strict")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _hash(domain: bytes, value: object) -> str:
|
|
59
|
+
return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _require_token(value: str, *, name: str) -> None:
|
|
63
|
+
if type(value) is not str or _TOKEN.fullmatch(value) is None:
|
|
64
|
+
raise ValueError(f"{name} must use the closed token grammar")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def _candidate_record(candidate: EvolutionCandidate) -> dict[str, object]:
|
|
68
|
+
candidate.__post_init__()
|
|
69
|
+
return {
|
|
70
|
+
"candidate_id": candidate.candidate_id.value,
|
|
71
|
+
"configuration_sha256": candidate.occurrence.configuration_hash,
|
|
72
|
+
"generation": candidate.generation,
|
|
73
|
+
"valid": candidate.valid,
|
|
74
|
+
"operator_compliant": candidate.operator_compliant,
|
|
75
|
+
"evidence_compliant": candidate.evidence_compliant,
|
|
76
|
+
"objectives": [
|
|
77
|
+
{"metric_id": metric_id, "value_hex": value.hex()}
|
|
78
|
+
for metric_id, value in candidate.objectives
|
|
79
|
+
],
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _archive_sha256(
|
|
84
|
+
prior_candidates: tuple[EvolutionCandidate, ...],
|
|
85
|
+
current_prefix_candidates: tuple[EvolutionCandidate, ...],
|
|
86
|
+
) -> str:
|
|
87
|
+
return _hash(
|
|
88
|
+
_ARCHIVE_DOMAIN,
|
|
89
|
+
{
|
|
90
|
+
"prior": [
|
|
91
|
+
_candidate_record(value)
|
|
92
|
+
for value in sorted(
|
|
93
|
+
prior_candidates,
|
|
94
|
+
key=lambda item: item.candidate_id.value,
|
|
95
|
+
)
|
|
96
|
+
],
|
|
97
|
+
"current_prefix": [
|
|
98
|
+
_candidate_record(value)
|
|
99
|
+
for value in sorted(
|
|
100
|
+
current_prefix_candidates,
|
|
101
|
+
key=lambda item: item.candidate_id.value,
|
|
102
|
+
)
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@dataclass(frozen=True, slots=True)
|
|
109
|
+
class CurrentPrefixForecastOpportunityScore:
|
|
110
|
+
"""Authenticated candidate-specific conditional opportunity evidence."""
|
|
111
|
+
|
|
112
|
+
action_sha256: str
|
|
113
|
+
phenotype_identity_sha256: str
|
|
114
|
+
reliability: float
|
|
115
|
+
adverse_gain: float
|
|
116
|
+
central_gain: float
|
|
117
|
+
favorable_gain: float
|
|
118
|
+
robust_gain: float
|
|
119
|
+
exploration_gain: float
|
|
120
|
+
acquisition_value: float
|
|
121
|
+
abstained: bool
|
|
122
|
+
abstention_reason: str | None
|
|
123
|
+
source_member_sha256: str
|
|
124
|
+
raw_acquisition_value: float | None = None
|
|
125
|
+
calibration_result: ArchiveOpportunityCalibrationResult | None = field(
|
|
126
|
+
default=None,
|
|
127
|
+
repr=False,
|
|
128
|
+
compare=False,
|
|
129
|
+
)
|
|
130
|
+
score_sha256: str = field(init=False)
|
|
131
|
+
|
|
132
|
+
def __post_init__(self) -> None:
|
|
133
|
+
require_sha256(self.action_sha256, "action_sha256")
|
|
134
|
+
require_sha256(
|
|
135
|
+
self.phenotype_identity_sha256,
|
|
136
|
+
"phenotype_identity_sha256",
|
|
137
|
+
)
|
|
138
|
+
require_sha256(self.source_member_sha256, "source_member_sha256")
|
|
139
|
+
if (
|
|
140
|
+
type(self.reliability) is not float
|
|
141
|
+
or not math.isfinite(self.reliability)
|
|
142
|
+
or not 0.0 <= self.reliability <= 1.0
|
|
143
|
+
):
|
|
144
|
+
raise ValueError("reliability must lie in [0, 1]")
|
|
145
|
+
for name in (
|
|
146
|
+
"adverse_gain",
|
|
147
|
+
"central_gain",
|
|
148
|
+
"favorable_gain",
|
|
149
|
+
"robust_gain",
|
|
150
|
+
"exploration_gain",
|
|
151
|
+
"acquisition_value",
|
|
152
|
+
):
|
|
153
|
+
value = getattr(self, name)
|
|
154
|
+
if type(value) is not float or not math.isfinite(value) or value < 0.0:
|
|
155
|
+
raise ValueError(f"{name} must be finite and non-negative")
|
|
156
|
+
if type(self.abstained) is not bool:
|
|
157
|
+
raise TypeError("abstained must be exact")
|
|
158
|
+
if self.abstained:
|
|
159
|
+
if self.abstention_reason is None:
|
|
160
|
+
raise ValueError("an abstention must have a reason")
|
|
161
|
+
_require_token(self.abstention_reason, name="abstention_reason")
|
|
162
|
+
elif self.abstention_reason is not None:
|
|
163
|
+
raise ValueError("a recommendation cannot have an abstention reason")
|
|
164
|
+
if (self.raw_acquisition_value is None) != (
|
|
165
|
+
self.calibration_result is None
|
|
166
|
+
):
|
|
167
|
+
raise ValueError(
|
|
168
|
+
"raw acquisition and calibration result must be jointly present"
|
|
169
|
+
)
|
|
170
|
+
if self.calibration_result is not None:
|
|
171
|
+
if (
|
|
172
|
+
type(self.calibration_result)
|
|
173
|
+
is not ArchiveOpportunityCalibrationResult
|
|
174
|
+
):
|
|
175
|
+
raise TypeError("calibration_result must be exact")
|
|
176
|
+
self.calibration_result.__post_init__()
|
|
177
|
+
raw_acquisition_valid = (
|
|
178
|
+
type(self.raw_acquisition_value) is float
|
|
179
|
+
and math.isfinite(self.raw_acquisition_value)
|
|
180
|
+
and self.raw_acquisition_value >= 0.0
|
|
181
|
+
)
|
|
182
|
+
if not raw_acquisition_valid:
|
|
183
|
+
raise ValueError(
|
|
184
|
+
"raw_acquisition_value must be finite and non-negative"
|
|
185
|
+
)
|
|
186
|
+
if (
|
|
187
|
+
self.calibration_result.action_sha256
|
|
188
|
+
!= self.action_sha256
|
|
189
|
+
or not math.isclose(
|
|
190
|
+
self.acquisition_value,
|
|
191
|
+
self.calibration_result.calibrated_acquisition_value,
|
|
192
|
+
rel_tol=1e-12,
|
|
193
|
+
abs_tol=1e-15,
|
|
194
|
+
)
|
|
195
|
+
):
|
|
196
|
+
raise ValueError(
|
|
197
|
+
"calibration result differs from the scored action"
|
|
198
|
+
)
|
|
199
|
+
object.__setattr__(
|
|
200
|
+
self,
|
|
201
|
+
"score_sha256",
|
|
202
|
+
_hash(_SCORE_DOMAIN, self._unsigned_record()),
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
206
|
+
record: dict[str, object] = {
|
|
207
|
+
"schema_version": 1,
|
|
208
|
+
"action_sha256": self.action_sha256,
|
|
209
|
+
"phenotype_identity_sha256": self.phenotype_identity_sha256,
|
|
210
|
+
"reliability_hex": self.reliability.hex(),
|
|
211
|
+
"adverse_gain_hex": self.adverse_gain.hex(),
|
|
212
|
+
"central_gain_hex": self.central_gain.hex(),
|
|
213
|
+
"favorable_gain_hex": self.favorable_gain.hex(),
|
|
214
|
+
"robust_gain_hex": self.robust_gain.hex(),
|
|
215
|
+
"exploration_gain_hex": self.exploration_gain.hex(),
|
|
216
|
+
"acquisition_value_hex": self.acquisition_value.hex(),
|
|
217
|
+
"abstained": self.abstained,
|
|
218
|
+
"abstention_reason": self.abstention_reason,
|
|
219
|
+
"source_member_sha256": self.source_member_sha256,
|
|
220
|
+
"eligible_candidate_outcome_observed": False,
|
|
221
|
+
}
|
|
222
|
+
if self.calibration_result is not None:
|
|
223
|
+
record["schema_version"] = 2
|
|
224
|
+
record["raw_acquisition_value_hex"] = (
|
|
225
|
+
self.raw_acquisition_value.hex()
|
|
226
|
+
)
|
|
227
|
+
record["calibration_result_sha256"] = (
|
|
228
|
+
self.calibration_result.result_sha256
|
|
229
|
+
)
|
|
230
|
+
return record
|
|
231
|
+
|
|
232
|
+
def to_record(self) -> dict[str, object]:
|
|
233
|
+
self.__post_init__()
|
|
234
|
+
result = {
|
|
235
|
+
**self._unsigned_record(),
|
|
236
|
+
"score_sha256": self.score_sha256,
|
|
237
|
+
}
|
|
238
|
+
if self.calibration_result is not None:
|
|
239
|
+
result["calibration_result"] = (
|
|
240
|
+
self.calibration_result.to_record()
|
|
241
|
+
)
|
|
242
|
+
return result
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
@dataclass(frozen=True, slots=True)
|
|
246
|
+
class CurrentPrefixForecastOpportunityRanking:
|
|
247
|
+
"""One cutoff-bound ranking over an unobserved sealed action market."""
|
|
248
|
+
|
|
249
|
+
policy_id: str
|
|
250
|
+
policy_version: int
|
|
251
|
+
policy_definition_sha256: str
|
|
252
|
+
geometry_batch_sha256: str
|
|
253
|
+
archive_sha256: str
|
|
254
|
+
consumed_action_sha256s: tuple[str, ...]
|
|
255
|
+
eligible_action_sha256s: tuple[str, ...]
|
|
256
|
+
scores: tuple[CurrentPrefixForecastOpportunityScore, ...]
|
|
257
|
+
recommended_action_sha256s: tuple[str, ...]
|
|
258
|
+
current_prefix_outcomes_observed: bool
|
|
259
|
+
eligible_candidate_outcomes_observed: bool
|
|
260
|
+
ranking_sha256: str = field(init=False)
|
|
261
|
+
|
|
262
|
+
def __post_init__(self) -> None:
|
|
263
|
+
_require_token(self.policy_id, name="policy_id")
|
|
264
|
+
if type(self.policy_version) is not int or self.policy_version <= 0:
|
|
265
|
+
raise ValueError("policy_version must be positive")
|
|
266
|
+
for value, name in (
|
|
267
|
+
(self.policy_definition_sha256, "policy_definition_sha256"),
|
|
268
|
+
(self.geometry_batch_sha256, "geometry_batch_sha256"),
|
|
269
|
+
(self.archive_sha256, "archive_sha256"),
|
|
270
|
+
):
|
|
271
|
+
require_sha256(value, name)
|
|
272
|
+
for values, name in (
|
|
273
|
+
(self.consumed_action_sha256s, "consumed_action_sha256s"),
|
|
274
|
+
(self.eligible_action_sha256s, "eligible_action_sha256s"),
|
|
275
|
+
(self.recommended_action_sha256s, "recommended_action_sha256s"),
|
|
276
|
+
):
|
|
277
|
+
if type(values) is not tuple or values != tuple(sorted(set(values))):
|
|
278
|
+
raise ValueError(f"{name} must be unique and canonical")
|
|
279
|
+
for value in values:
|
|
280
|
+
require_sha256(value, name[:-1])
|
|
281
|
+
if (
|
|
282
|
+
type(self.scores) is not tuple
|
|
283
|
+
or any(
|
|
284
|
+
type(value) is not CurrentPrefixForecastOpportunityScore
|
|
285
|
+
for value in self.scores
|
|
286
|
+
)
|
|
287
|
+
):
|
|
288
|
+
raise TypeError("scores must contain exact opportunity scores")
|
|
289
|
+
for value in self.scores:
|
|
290
|
+
value.__post_init__()
|
|
291
|
+
action_ids = tuple(value.action_sha256 for value in self.scores)
|
|
292
|
+
if action_ids != tuple(sorted(set(action_ids))):
|
|
293
|
+
raise ValueError("scores must be action-canonical")
|
|
294
|
+
if action_ids != self.eligible_action_sha256s:
|
|
295
|
+
raise ValueError("scores must cover the exact eligible market")
|
|
296
|
+
if not set(self.recommended_action_sha256s) <= set(action_ids):
|
|
297
|
+
raise ValueError("recommendations escape the eligible market")
|
|
298
|
+
score_by_action = {
|
|
299
|
+
value.action_sha256: value for value in self.scores
|
|
300
|
+
}
|
|
301
|
+
if any(
|
|
302
|
+
score_by_action[action_sha256].abstained
|
|
303
|
+
for action_sha256 in self.recommended_action_sha256s
|
|
304
|
+
):
|
|
305
|
+
raise ValueError("recommendations cannot include abstentions")
|
|
306
|
+
recommended_phenotypes = tuple(
|
|
307
|
+
score_by_action[value].phenotype_identity_sha256
|
|
308
|
+
for value in self.recommended_action_sha256s
|
|
309
|
+
)
|
|
310
|
+
if len(recommended_phenotypes) != len(set(recommended_phenotypes)):
|
|
311
|
+
raise ValueError("recommendations repeat a phenotype")
|
|
312
|
+
if type(self.current_prefix_outcomes_observed) is not bool:
|
|
313
|
+
raise TypeError("current_prefix_outcomes_observed must be exact")
|
|
314
|
+
if type(self.eligible_candidate_outcomes_observed) is not bool:
|
|
315
|
+
raise TypeError("eligible_candidate_outcomes_observed must be exact")
|
|
316
|
+
if self.eligible_candidate_outcomes_observed:
|
|
317
|
+
raise ValueError("eligible candidate outcomes must remain hidden")
|
|
318
|
+
object.__setattr__(
|
|
319
|
+
self,
|
|
320
|
+
"ranking_sha256",
|
|
321
|
+
_hash(_RANKING_DOMAIN, self._unsigned_record()),
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
325
|
+
return {
|
|
326
|
+
"schema_version": 1,
|
|
327
|
+
"policy": {
|
|
328
|
+
"policy_id": self.policy_id,
|
|
329
|
+
"policy_version": self.policy_version,
|
|
330
|
+
"definition_sha256": self.policy_definition_sha256,
|
|
331
|
+
},
|
|
332
|
+
"geometry_batch_sha256": self.geometry_batch_sha256,
|
|
333
|
+
"archive_sha256": self.archive_sha256,
|
|
334
|
+
"consumed_action_sha256s": list(self.consumed_action_sha256s),
|
|
335
|
+
"eligible_action_sha256s": list(self.eligible_action_sha256s),
|
|
336
|
+
"score_sha256s": [value.score_sha256 for value in self.scores],
|
|
337
|
+
"recommended_action_sha256s": list(
|
|
338
|
+
self.recommended_action_sha256s
|
|
339
|
+
),
|
|
340
|
+
"current_prefix_outcomes_observed": (
|
|
341
|
+
self.current_prefix_outcomes_observed
|
|
342
|
+
),
|
|
343
|
+
"eligible_candidate_outcomes_observed": (
|
|
344
|
+
self.eligible_candidate_outcomes_observed
|
|
345
|
+
),
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
def to_record(self, *, include_scores: bool = False) -> dict[str, object]:
|
|
349
|
+
self.__post_init__()
|
|
350
|
+
result = {
|
|
351
|
+
**self._unsigned_record(),
|
|
352
|
+
"ranking_sha256": self.ranking_sha256,
|
|
353
|
+
}
|
|
354
|
+
if include_scores:
|
|
355
|
+
result["scores"] = [value.to_record() for value in self.scores]
|
|
356
|
+
return result
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
@runtime_checkable
|
|
360
|
+
class CurrentPrefixForecastOpportunityPolicyPort(Protocol):
|
|
361
|
+
"""Inverted API for raw or calibrated current-prefix opportunity."""
|
|
362
|
+
|
|
363
|
+
policy_id: str
|
|
364
|
+
policy_version: int
|
|
365
|
+
definition_sha256: str
|
|
366
|
+
|
|
367
|
+
def rank(
|
|
368
|
+
self,
|
|
369
|
+
*,
|
|
370
|
+
prior_candidates: tuple[EvolutionCandidate, ...],
|
|
371
|
+
current_prefix_candidates: tuple[EvolutionCandidate, ...],
|
|
372
|
+
geometry: MaterializedForecastGeometryBatch,
|
|
373
|
+
consumed_action_sha256s: tuple[str, ...] = (),
|
|
374
|
+
eligible_action_sha256s: tuple[str, ...] | None = None,
|
|
375
|
+
recommendation_count: int = 1,
|
|
376
|
+
action_contexts: tuple[
|
|
377
|
+
ArchiveOpportunityActionContext,
|
|
378
|
+
...,
|
|
379
|
+
] = (),
|
|
380
|
+
) -> CurrentPrefixForecastOpportunityRanking: ...
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def validate_current_prefix_forecast_opportunity_policy(
|
|
384
|
+
value: CurrentPrefixForecastOpportunityPolicyPort,
|
|
385
|
+
) -> tuple[str, int, str]:
|
|
386
|
+
if not isinstance(
|
|
387
|
+
value,
|
|
388
|
+
CurrentPrefixForecastOpportunityPolicyPort,
|
|
389
|
+
):
|
|
390
|
+
raise TypeError(
|
|
391
|
+
"opportunity policy must implement its application port"
|
|
392
|
+
)
|
|
393
|
+
identity = (
|
|
394
|
+
value.policy_id,
|
|
395
|
+
value.policy_version,
|
|
396
|
+
value.definition_sha256,
|
|
397
|
+
)
|
|
398
|
+
_require_token(identity[0], name="opportunity policy_id")
|
|
399
|
+
if type(identity[1]) is not int or identity[1] <= 0:
|
|
400
|
+
raise ValueError("opportunity policy_version must be positive")
|
|
401
|
+
require_sha256(identity[2], "opportunity policy definition_sha256")
|
|
402
|
+
return identity
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
@dataclass(frozen=True, slots=True)
|
|
406
|
+
class CurrentPrefixForecastOpportunityPolicy:
|
|
407
|
+
"""Rank forecasts by conditional archive lift after an observed prefix."""
|
|
408
|
+
|
|
409
|
+
archive_utility: CandidateArchivePortfolioConsequenceUtilityPort = field(
|
|
410
|
+
repr=False,
|
|
411
|
+
compare=False,
|
|
412
|
+
)
|
|
413
|
+
central_scenario_id: str = "median"
|
|
414
|
+
adverse_scenario_id: str = "adverse"
|
|
415
|
+
favorable_scenario_id: str = "favorable"
|
|
416
|
+
risk_aversion: float = 0.25
|
|
417
|
+
exploration_weight: float = 0.0
|
|
418
|
+
minimum_reliability: float = 0.0
|
|
419
|
+
minimum_acquisition_value: float = 0.0
|
|
420
|
+
policy_id: str = CURRENT_PREFIX_FORECAST_OPPORTUNITY_POLICY_ID
|
|
421
|
+
policy_version: int = CURRENT_PREFIX_FORECAST_OPPORTUNITY_POLICY_VERSION
|
|
422
|
+
definition_sha256: str = field(init=False)
|
|
423
|
+
|
|
424
|
+
def __post_init__(self) -> None:
|
|
425
|
+
utility_identity = (
|
|
426
|
+
validate_candidate_archive_portfolio_consequence_utility(
|
|
427
|
+
self.archive_utility
|
|
428
|
+
)
|
|
429
|
+
)
|
|
430
|
+
for value, name in (
|
|
431
|
+
(self.central_scenario_id, "central_scenario_id"),
|
|
432
|
+
(self.adverse_scenario_id, "adverse_scenario_id"),
|
|
433
|
+
(self.favorable_scenario_id, "favorable_scenario_id"),
|
|
434
|
+
(self.policy_id, "policy_id"),
|
|
435
|
+
):
|
|
436
|
+
_require_token(value, name=name)
|
|
437
|
+
if self.policy_id != CURRENT_PREFIX_FORECAST_OPPORTUNITY_POLICY_ID:
|
|
438
|
+
raise ValueError("policy_id is immutable")
|
|
439
|
+
if self.policy_version != CURRENT_PREFIX_FORECAST_OPPORTUNITY_POLICY_VERSION:
|
|
440
|
+
raise ValueError("policy_version is immutable")
|
|
441
|
+
for name in (
|
|
442
|
+
"risk_aversion",
|
|
443
|
+
"exploration_weight",
|
|
444
|
+
"minimum_acquisition_value",
|
|
445
|
+
):
|
|
446
|
+
value = getattr(self, name)
|
|
447
|
+
if type(value) is not float or not math.isfinite(value) or value < 0.0:
|
|
448
|
+
raise ValueError(f"{name} must be finite and non-negative")
|
|
449
|
+
if (
|
|
450
|
+
type(self.minimum_reliability) is not float
|
|
451
|
+
or not math.isfinite(self.minimum_reliability)
|
|
452
|
+
or not 0.0 <= self.minimum_reliability <= 1.0
|
|
453
|
+
):
|
|
454
|
+
raise ValueError("minimum_reliability must lie in [0, 1]")
|
|
455
|
+
object.__setattr__(
|
|
456
|
+
self,
|
|
457
|
+
"definition_sha256",
|
|
458
|
+
_hash(
|
|
459
|
+
_POLICY_DOMAIN,
|
|
460
|
+
{
|
|
461
|
+
"schema_version": 1,
|
|
462
|
+
"policy_id": self.policy_id,
|
|
463
|
+
"policy_version": self.policy_version,
|
|
464
|
+
"archive_utility": {
|
|
465
|
+
"utility_id": utility_identity[0],
|
|
466
|
+
"utility_version": utility_identity[1],
|
|
467
|
+
"definition_sha256": utility_identity[2],
|
|
468
|
+
},
|
|
469
|
+
"central_scenario_id": self.central_scenario_id,
|
|
470
|
+
"adverse_scenario_id": self.adverse_scenario_id,
|
|
471
|
+
"favorable_scenario_id": self.favorable_scenario_id,
|
|
472
|
+
"risk_aversion_hex": self.risk_aversion.hex(),
|
|
473
|
+
"exploration_weight_hex": self.exploration_weight.hex(),
|
|
474
|
+
"minimum_reliability_hex": self.minimum_reliability.hex(),
|
|
475
|
+
"minimum_acquisition_value_hex": (
|
|
476
|
+
self.minimum_acquisition_value.hex()
|
|
477
|
+
),
|
|
478
|
+
"selection_currency": (
|
|
479
|
+
"current_prefix_conditional_archive_opportunity"
|
|
480
|
+
),
|
|
481
|
+
"eligible_candidate_outcomes_observed": False,
|
|
482
|
+
"workload_model_provider_branches": False,
|
|
483
|
+
},
|
|
484
|
+
),
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
def _gain(
|
|
488
|
+
self,
|
|
489
|
+
archive: tuple[EvolutionCandidate, ...],
|
|
490
|
+
member: MaterializedForecastGeometryMember,
|
|
491
|
+
scenario_id: str,
|
|
492
|
+
) -> float:
|
|
493
|
+
result = self.archive_utility.portfolio_marginal_utility(
|
|
494
|
+
archive,
|
|
495
|
+
(member.scenario(scenario_id).as_mapping(),),
|
|
496
|
+
)
|
|
497
|
+
if type(result) is not float or not math.isfinite(result) or result < 0.0:
|
|
498
|
+
raise ValueError("archive utility returned an invalid opportunity")
|
|
499
|
+
return result
|
|
500
|
+
|
|
501
|
+
def rank(
|
|
502
|
+
self,
|
|
503
|
+
*,
|
|
504
|
+
prior_candidates: tuple[EvolutionCandidate, ...],
|
|
505
|
+
current_prefix_candidates: tuple[EvolutionCandidate, ...],
|
|
506
|
+
geometry: MaterializedForecastGeometryBatch,
|
|
507
|
+
consumed_action_sha256s: tuple[str, ...] = (),
|
|
508
|
+
eligible_action_sha256s: tuple[str, ...] | None = None,
|
|
509
|
+
recommendation_count: int = 1,
|
|
510
|
+
action_contexts: tuple[
|
|
511
|
+
ArchiveOpportunityActionContext,
|
|
512
|
+
...,
|
|
513
|
+
] = (),
|
|
514
|
+
) -> CurrentPrefixForecastOpportunityRanking:
|
|
515
|
+
"""Score only unobserved actions against the real accepted prefix."""
|
|
516
|
+
|
|
517
|
+
self.__post_init__()
|
|
518
|
+
for values, name in (
|
|
519
|
+
(prior_candidates, "prior_candidates"),
|
|
520
|
+
(current_prefix_candidates, "current_prefix_candidates"),
|
|
521
|
+
):
|
|
522
|
+
if (
|
|
523
|
+
type(values) is not tuple
|
|
524
|
+
or any(type(value) is not EvolutionCandidate for value in values)
|
|
525
|
+
):
|
|
526
|
+
raise TypeError(f"{name} must be an exact candidate tuple")
|
|
527
|
+
for value in values:
|
|
528
|
+
value.__post_init__()
|
|
529
|
+
archive = (*prior_candidates, *current_prefix_candidates)
|
|
530
|
+
candidate_ids = tuple(value.candidate_id for value in archive)
|
|
531
|
+
if len(candidate_ids) != len(set(candidate_ids)):
|
|
532
|
+
raise ValueError("prior and current-prefix candidates overlap")
|
|
533
|
+
if type(geometry) is not MaterializedForecastGeometryBatch:
|
|
534
|
+
raise TypeError("geometry must be an exact batch")
|
|
535
|
+
geometry.__post_init__()
|
|
536
|
+
all_action_ids = tuple(value.action_sha256 for value in geometry.members)
|
|
537
|
+
if (
|
|
538
|
+
type(consumed_action_sha256s) is not tuple
|
|
539
|
+
or consumed_action_sha256s
|
|
540
|
+
!= tuple(sorted(set(consumed_action_sha256s)))
|
|
541
|
+
):
|
|
542
|
+
raise ValueError("consumed action hashes must be unique and canonical")
|
|
543
|
+
for value in consumed_action_sha256s:
|
|
544
|
+
require_sha256(value, "consumed_action_sha256")
|
|
545
|
+
if not set(consumed_action_sha256s) <= set(all_action_ids):
|
|
546
|
+
raise ValueError("consumed actions escape the sealed geometry")
|
|
547
|
+
member_by_action = {
|
|
548
|
+
value.action_sha256: value for value in geometry.members
|
|
549
|
+
}
|
|
550
|
+
consumed_phenotypes = {
|
|
551
|
+
member_by_action[value].phenotype_identity_sha256
|
|
552
|
+
for value in consumed_action_sha256s
|
|
553
|
+
}
|
|
554
|
+
eligible = (
|
|
555
|
+
tuple(
|
|
556
|
+
value
|
|
557
|
+
for value in all_action_ids
|
|
558
|
+
if (
|
|
559
|
+
value not in set(consumed_action_sha256s)
|
|
560
|
+
and member_by_action[
|
|
561
|
+
value
|
|
562
|
+
].phenotype_identity_sha256 not in consumed_phenotypes
|
|
563
|
+
)
|
|
564
|
+
)
|
|
565
|
+
if eligible_action_sha256s is None
|
|
566
|
+
else eligible_action_sha256s
|
|
567
|
+
)
|
|
568
|
+
if type(eligible) is not tuple or eligible != tuple(sorted(set(eligible))):
|
|
569
|
+
raise ValueError("eligible action hashes must be unique and canonical")
|
|
570
|
+
for value in eligible:
|
|
571
|
+
require_sha256(value, "eligible_action_sha256")
|
|
572
|
+
if not set(eligible) <= set(all_action_ids) - set(consumed_action_sha256s):
|
|
573
|
+
raise ValueError("eligible actions are not unconsumed sealed actions")
|
|
574
|
+
if any(
|
|
575
|
+
member_by_action[value].phenotype_identity_sha256
|
|
576
|
+
in consumed_phenotypes
|
|
577
|
+
for value in eligible
|
|
578
|
+
):
|
|
579
|
+
raise ValueError("eligible actions repeat a consumed phenotype")
|
|
580
|
+
if type(recommendation_count) is not int or recommendation_count < 0:
|
|
581
|
+
raise ValueError("recommendation_count must be non-negative")
|
|
582
|
+
if (
|
|
583
|
+
type(action_contexts) is not tuple
|
|
584
|
+
or any(
|
|
585
|
+
type(value) is not ArchiveOpportunityActionContext
|
|
586
|
+
for value in action_contexts
|
|
587
|
+
)
|
|
588
|
+
):
|
|
589
|
+
raise TypeError(
|
|
590
|
+
"action_contexts must contain exact generic contexts"
|
|
591
|
+
)
|
|
592
|
+
for value in action_contexts:
|
|
593
|
+
value.__post_init__()
|
|
594
|
+
context_action_ids = tuple(
|
|
595
|
+
value.action_sha256 for value in action_contexts
|
|
596
|
+
)
|
|
597
|
+
if context_action_ids and context_action_ids != tuple(
|
|
598
|
+
sorted(set(context_action_ids))
|
|
599
|
+
):
|
|
600
|
+
raise ValueError(
|
|
601
|
+
"action_contexts must be unique and action canonical"
|
|
602
|
+
)
|
|
603
|
+
if context_action_ids and set(context_action_ids) != set(eligible):
|
|
604
|
+
raise ValueError(
|
|
605
|
+
"action_contexts must cover the exact eligible market"
|
|
606
|
+
)
|
|
607
|
+
|
|
608
|
+
required_scenarios = {
|
|
609
|
+
self.central_scenario_id,
|
|
610
|
+
self.adverse_scenario_id,
|
|
611
|
+
self.favorable_scenario_id,
|
|
612
|
+
}
|
|
613
|
+
scores: list[CurrentPrefixForecastOpportunityScore] = []
|
|
614
|
+
for action_sha256 in eligible:
|
|
615
|
+
member = member_by_action[action_sha256]
|
|
616
|
+
if not required_scenarios <= {
|
|
617
|
+
value.scenario_id for value in member.scenarios
|
|
618
|
+
}:
|
|
619
|
+
raise ValueError("forecast geometry omits an opportunity scenario")
|
|
620
|
+
adverse = self._gain(
|
|
621
|
+
archive,
|
|
622
|
+
member,
|
|
623
|
+
self.adverse_scenario_id,
|
|
624
|
+
)
|
|
625
|
+
central = self._gain(
|
|
626
|
+
archive,
|
|
627
|
+
member,
|
|
628
|
+
self.central_scenario_id,
|
|
629
|
+
)
|
|
630
|
+
favorable = self._gain(
|
|
631
|
+
archive,
|
|
632
|
+
member,
|
|
633
|
+
self.favorable_scenario_id,
|
|
634
|
+
)
|
|
635
|
+
robust = max(
|
|
636
|
+
0.0,
|
|
637
|
+
central
|
|
638
|
+
- self.risk_aversion * max(0.0, central - adverse),
|
|
639
|
+
)
|
|
640
|
+
exploration = max(0.0, favorable - central)
|
|
641
|
+
acquisition = member.reliability * (
|
|
642
|
+
robust + self.exploration_weight * exploration
|
|
643
|
+
)
|
|
644
|
+
if member.reliability < self.minimum_reliability:
|
|
645
|
+
abstention_reason = "below_reliability_floor"
|
|
646
|
+
elif acquisition <= self.minimum_acquisition_value:
|
|
647
|
+
abstention_reason = "no_identified_conditional_opportunity"
|
|
648
|
+
else:
|
|
649
|
+
abstention_reason = None
|
|
650
|
+
scores.append(
|
|
651
|
+
CurrentPrefixForecastOpportunityScore(
|
|
652
|
+
action_sha256=action_sha256,
|
|
653
|
+
phenotype_identity_sha256=(
|
|
654
|
+
member.phenotype_identity_sha256
|
|
655
|
+
),
|
|
656
|
+
reliability=member.reliability,
|
|
657
|
+
adverse_gain=float(adverse),
|
|
658
|
+
central_gain=float(central),
|
|
659
|
+
favorable_gain=float(favorable),
|
|
660
|
+
robust_gain=float(robust),
|
|
661
|
+
exploration_gain=float(exploration),
|
|
662
|
+
acquisition_value=float(acquisition),
|
|
663
|
+
abstained=abstention_reason is not None,
|
|
664
|
+
abstention_reason=abstention_reason,
|
|
665
|
+
source_member_sha256=member.member_sha256,
|
|
666
|
+
)
|
|
667
|
+
)
|
|
668
|
+
scores.sort(key=lambda value: value.action_sha256)
|
|
669
|
+
ranked = sorted(
|
|
670
|
+
(value for value in scores if not value.abstained),
|
|
671
|
+
key=lambda value: (
|
|
672
|
+
-value.acquisition_value,
|
|
673
|
+
-value.central_gain,
|
|
674
|
+
-value.reliability,
|
|
675
|
+
value.action_sha256,
|
|
676
|
+
),
|
|
677
|
+
)
|
|
678
|
+
recommended: list[str] = []
|
|
679
|
+
phenotypes: set[str] = set()
|
|
680
|
+
if recommendation_count:
|
|
681
|
+
for value in ranked:
|
|
682
|
+
if value.phenotype_identity_sha256 in phenotypes:
|
|
683
|
+
continue
|
|
684
|
+
recommended.append(value.action_sha256)
|
|
685
|
+
phenotypes.add(value.phenotype_identity_sha256)
|
|
686
|
+
if len(recommended) == recommendation_count:
|
|
687
|
+
break
|
|
688
|
+
return CurrentPrefixForecastOpportunityRanking(
|
|
689
|
+
policy_id=self.policy_id,
|
|
690
|
+
policy_version=self.policy_version,
|
|
691
|
+
policy_definition_sha256=self.definition_sha256,
|
|
692
|
+
geometry_batch_sha256=geometry.batch_sha256,
|
|
693
|
+
archive_sha256=_archive_sha256(
|
|
694
|
+
prior_candidates,
|
|
695
|
+
current_prefix_candidates,
|
|
696
|
+
),
|
|
697
|
+
consumed_action_sha256s=consumed_action_sha256s,
|
|
698
|
+
eligible_action_sha256s=eligible,
|
|
699
|
+
scores=tuple(scores),
|
|
700
|
+
recommended_action_sha256s=tuple(sorted(recommended)),
|
|
701
|
+
current_prefix_outcomes_observed=bool(current_prefix_candidates),
|
|
702
|
+
eligible_candidate_outcomes_observed=False,
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
|
|
706
|
+
__all__ = [
|
|
707
|
+
"CURRENT_PREFIX_FORECAST_OPPORTUNITY_POLICY_ID",
|
|
708
|
+
"CURRENT_PREFIX_FORECAST_OPPORTUNITY_POLICY_VERSION",
|
|
709
|
+
"CurrentPrefixForecastOpportunityPolicy",
|
|
710
|
+
"CurrentPrefixForecastOpportunityPolicyPort",
|
|
711
|
+
"CurrentPrefixForecastOpportunityRanking",
|
|
712
|
+
"CurrentPrefixForecastOpportunityScore",
|
|
713
|
+
"validate_current_prefix_forecast_opportunity_policy",
|
|
714
|
+
]
|