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,1303 @@
|
|
|
1
|
+
"""V9 candidate composition: v8lite_r2 plus config-gated R1/R2/R3 arms.
|
|
2
|
+
|
|
3
|
+
The frozen ``v8lite_r2`` composition stays the reference; this module
|
|
4
|
+
never modifies it. Three independently config-gated refinements from the
|
|
5
|
+
jul28 pareto defect theory compose OVER it, each ablatable on its own:
|
|
6
|
+
|
|
7
|
+
* R1 (``region_conditional_credit``) — the continuation challenger's
|
|
8
|
+
conversion credit moves from (engine x rank band) cells to
|
|
9
|
+
(engine x parent-front-region x radius class) cells with the same
|
|
10
|
+
Beta-shrinkage hierarchy, plus a learned demote-only forecast-trust
|
|
11
|
+
channel;
|
|
12
|
+
* R2 (``head_mass_conditional_seat``) — when the calibrated model's
|
|
13
|
+
predicted positive mass concentrates on one candidate strictly above a
|
|
14
|
+
threshold, the FIRST seat becomes the deterministic argmax (an exact
|
|
15
|
+
point-mass, propensity one) instead of a sampled pilot seat; and
|
|
16
|
+
* R3 (``geometry_conditional_elasticity``) — pilot lane selection walks
|
|
17
|
+
D'Hondt over elastic per-lane bids (parent distance-to-front, forecast
|
|
18
|
+
self-overlap saturation, revealed conversion) instead of the fixed
|
|
19
|
+
coverage floor; the within-engine seat design (bands, blocked
|
|
20
|
+
randomization, epsilon floor, exact rational propensities) is delegated
|
|
21
|
+
unchanged to the sequential adaptive pilot.
|
|
22
|
+
|
|
23
|
+
With every flag off, every decision is delegated verbatim to the inner
|
|
24
|
+
``v8lite_r2`` policy, so the base arm is bit-identical to the reference.
|
|
25
|
+
Terminal seats are ALWAYS delegated through the inner policy, which itself
|
|
26
|
+
delegates to the frozen V7 terminal hierarchical-exploitation rule: no arm
|
|
27
|
+
alters the V7 terminal rule. These arms carry NO live authority; they
|
|
28
|
+
exist for provider-free replay evaluation (gate M-lite v3).
|
|
29
|
+
|
|
30
|
+
The policy knows no workload, objective name, model, provider, or prompt.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import hashlib
|
|
36
|
+
import json
|
|
37
|
+
import re
|
|
38
|
+
from dataclasses import dataclass, field
|
|
39
|
+
|
|
40
|
+
from agent_evolve.application.calibrated_positive_gain_opportunity import (
|
|
41
|
+
ObjectivePoint,
|
|
42
|
+
ObservedConversionOutcome,
|
|
43
|
+
PositiveGainCandidate,
|
|
44
|
+
PositiveGainForecast,
|
|
45
|
+
_require_objective_point,
|
|
46
|
+
)
|
|
47
|
+
from agent_evolve.application.geometry_conditional_elasticity import (
|
|
48
|
+
ElasticSeatBidder,
|
|
49
|
+
ElasticSeatConfig,
|
|
50
|
+
LaneGeometryEvidence,
|
|
51
|
+
)
|
|
52
|
+
from agent_evolve.application.head_mass_conditional_seat import (
|
|
53
|
+
HeadMassSeatAssessor,
|
|
54
|
+
HeadMassSeatConfig,
|
|
55
|
+
)
|
|
56
|
+
from agent_evolve.application.outcome_adaptive_action_racing import (
|
|
57
|
+
AdaptiveActionDescriptor,
|
|
58
|
+
AdaptiveActionOutcome,
|
|
59
|
+
AdaptiveActionSetOutcome,
|
|
60
|
+
)
|
|
61
|
+
from agent_evolve.application.rank_balanced_causal_pilot import (
|
|
62
|
+
PilotSeatObservation,
|
|
63
|
+
RankBalancedPilotCandidate,
|
|
64
|
+
)
|
|
65
|
+
from agent_evolve.application.region_conditional_credit import (
|
|
66
|
+
RegionConditionalChallengerPolicy,
|
|
67
|
+
RegionConditionalOutcome,
|
|
68
|
+
RegionCreditConfig,
|
|
69
|
+
RegionFeatures,
|
|
70
|
+
RegionScoredCandidate,
|
|
71
|
+
parent_front_distance,
|
|
72
|
+
)
|
|
73
|
+
from agent_evolve.application.sequential_market_replay import (
|
|
74
|
+
MarketRecord,
|
|
75
|
+
ReplaySelection,
|
|
76
|
+
ReplayStepReceipt,
|
|
77
|
+
V8LiteReplayPolicy,
|
|
78
|
+
_clamped_gain,
|
|
79
|
+
_corpus_action_sha256,
|
|
80
|
+
_normalized_point,
|
|
81
|
+
)
|
|
82
|
+
from agent_evolve.application.v8lite_allocation_policy import (
|
|
83
|
+
V8LITE_ALLOCATION_POLICY_VERSION_ID_R2,
|
|
84
|
+
V8LITE_PHASE_ADAPTIVE,
|
|
85
|
+
V8LITE_PHASE_PILOT,
|
|
86
|
+
V8LITE_PHASE_PROTECTED_FALLBACK,
|
|
87
|
+
V8LiteAllocationConfig,
|
|
88
|
+
V8LiteAllocationPolicy,
|
|
89
|
+
V8LiteDecision,
|
|
90
|
+
)
|
|
91
|
+
from agent_evolve.domain.patch import require_sha256
|
|
92
|
+
from agent_evolve.domain.typed_json import freeze_json
|
|
93
|
+
|
|
94
|
+
V9_CANDIDATE_POLICY_ID = "v9_candidate_allocation"
|
|
95
|
+
V9_CANDIDATE_POLICY_VERSION = 1
|
|
96
|
+
_TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
|
|
97
|
+
_DEFINITION_DOMAIN = b"agent-evolve:v9-candidate-definition:v1\x00"
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _canonical_json(value: object) -> bytes:
|
|
101
|
+
return json.dumps(
|
|
102
|
+
value,
|
|
103
|
+
allow_nan=False,
|
|
104
|
+
ensure_ascii=True,
|
|
105
|
+
separators=(",", ":"),
|
|
106
|
+
sort_keys=True,
|
|
107
|
+
).encode("ascii", errors="strict")
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _hash(domain: bytes, value: object) -> str:
|
|
111
|
+
return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def v9_arm_version_id(*, r1: bool, r2: bool, r3: bool) -> str:
|
|
115
|
+
"""Deterministic arm token for one flag combination."""
|
|
116
|
+
|
|
117
|
+
suffix = "".join(
|
|
118
|
+
token
|
|
119
|
+
for token, enabled in (("r1", r1), ("r2", r2), ("r3", r3))
|
|
120
|
+
if enabled
|
|
121
|
+
)
|
|
122
|
+
return f"v9_{suffix}" if suffix else "v9_base"
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@dataclass(frozen=True, slots=True)
|
|
126
|
+
class V9CandidateConfig:
|
|
127
|
+
"""Flags and component configs; the inner v8lite config is shared."""
|
|
128
|
+
|
|
129
|
+
r1_region_conditional_credit: bool = False
|
|
130
|
+
r2_head_mass_conditional_seat: bool = False
|
|
131
|
+
r3_geometry_conditional_elasticity: bool = False
|
|
132
|
+
base: V8LiteAllocationConfig = V8LiteAllocationConfig()
|
|
133
|
+
credit: RegionCreditConfig = RegionCreditConfig()
|
|
134
|
+
head: HeadMassSeatConfig = HeadMassSeatConfig()
|
|
135
|
+
elastic: ElasticSeatConfig = ElasticSeatConfig()
|
|
136
|
+
|
|
137
|
+
def __post_init__(self) -> None:
|
|
138
|
+
for name in (
|
|
139
|
+
"r1_region_conditional_credit",
|
|
140
|
+
"r2_head_mass_conditional_seat",
|
|
141
|
+
"r3_geometry_conditional_elasticity",
|
|
142
|
+
):
|
|
143
|
+
if type(getattr(self, name)) is not bool:
|
|
144
|
+
raise TypeError(f"{name} must be exact")
|
|
145
|
+
if type(self.base) is not V8LiteAllocationConfig:
|
|
146
|
+
raise TypeError("base must be an exact v8lite config")
|
|
147
|
+
self.base.__post_init__()
|
|
148
|
+
if type(self.credit) is not RegionCreditConfig:
|
|
149
|
+
raise TypeError("credit must be exact")
|
|
150
|
+
self.credit.__post_init__()
|
|
151
|
+
if type(self.head) is not HeadMassSeatConfig:
|
|
152
|
+
raise TypeError("head must be exact")
|
|
153
|
+
self.head.__post_init__()
|
|
154
|
+
if type(self.elastic) is not ElasticSeatConfig:
|
|
155
|
+
raise TypeError("elastic must be exact")
|
|
156
|
+
self.elastic.__post_init__()
|
|
157
|
+
|
|
158
|
+
@property
|
|
159
|
+
def arm_version_id(self) -> str:
|
|
160
|
+
return v9_arm_version_id(
|
|
161
|
+
r1=self.r1_region_conditional_credit,
|
|
162
|
+
r2=self.r2_head_mass_conditional_seat,
|
|
163
|
+
r3=self.r3_geometry_conditional_elasticity,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
def flags_record(self) -> dict[str, bool]:
|
|
167
|
+
return {
|
|
168
|
+
"r1": self.r1_region_conditional_credit,
|
|
169
|
+
"r2": self.r2_head_mass_conditional_seat,
|
|
170
|
+
"r3": self.r3_geometry_conditional_elasticity,
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _validated_feature_map(
|
|
175
|
+
region_features: tuple[tuple[str, RegionFeatures], ...],
|
|
176
|
+
) -> dict[str, RegionFeatures]:
|
|
177
|
+
if type(region_features) is not tuple:
|
|
178
|
+
raise TypeError("region_features must be an exact tuple")
|
|
179
|
+
result: dict[str, RegionFeatures] = {}
|
|
180
|
+
for value in region_features:
|
|
181
|
+
if type(value) is not tuple or len(value) != 2:
|
|
182
|
+
raise TypeError(
|
|
183
|
+
"region_features must pair action and features"
|
|
184
|
+
)
|
|
185
|
+
action_sha256, features = value
|
|
186
|
+
require_sha256(action_sha256, "feature action_sha256")
|
|
187
|
+
if type(features) is not RegionFeatures:
|
|
188
|
+
raise TypeError("features must be exact")
|
|
189
|
+
features.__post_init__()
|
|
190
|
+
if action_sha256 in result:
|
|
191
|
+
raise ValueError("region_features repeat an action")
|
|
192
|
+
result[action_sha256] = features
|
|
193
|
+
return result
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def _validated_forecast_map(
|
|
197
|
+
forecasts: tuple[tuple[str, PositiveGainForecast], ...],
|
|
198
|
+
) -> dict[str, PositiveGainForecast]:
|
|
199
|
+
if type(forecasts) is not tuple:
|
|
200
|
+
raise TypeError("forecasts must be an exact tuple")
|
|
201
|
+
result: dict[str, PositiveGainForecast] = {}
|
|
202
|
+
for value in forecasts:
|
|
203
|
+
if type(value) is not tuple or len(value) != 2:
|
|
204
|
+
raise TypeError("forecasts must pair action and forecast")
|
|
205
|
+
action_sha256, forecast = value
|
|
206
|
+
require_sha256(action_sha256, "forecast action_sha256")
|
|
207
|
+
if type(forecast) is not PositiveGainForecast:
|
|
208
|
+
raise TypeError("forecast must be exact")
|
|
209
|
+
forecast.__post_init__()
|
|
210
|
+
if action_sha256 in result:
|
|
211
|
+
raise ValueError("forecasts repeat an action")
|
|
212
|
+
result[action_sha256] = forecast
|
|
213
|
+
return result
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def _validated_point_map(
|
|
217
|
+
revealed_objective_points: tuple[tuple[str, ObjectivePoint], ...],
|
|
218
|
+
) -> dict[str, ObjectivePoint]:
|
|
219
|
+
if type(revealed_objective_points) is not tuple:
|
|
220
|
+
raise TypeError(
|
|
221
|
+
"revealed_objective_points must be an exact tuple"
|
|
222
|
+
)
|
|
223
|
+
result: dict[str, ObjectivePoint] = {}
|
|
224
|
+
for value in revealed_objective_points:
|
|
225
|
+
if type(value) is not tuple or len(value) != 2:
|
|
226
|
+
raise TypeError(
|
|
227
|
+
"revealed_objective_points must pair action and point"
|
|
228
|
+
)
|
|
229
|
+
action_sha256, point = value
|
|
230
|
+
require_sha256(action_sha256, "revealed action_sha256")
|
|
231
|
+
_require_objective_point(point, name="revealed point")
|
|
232
|
+
if action_sha256 in result:
|
|
233
|
+
raise ValueError(
|
|
234
|
+
"revealed_objective_points repeat an action"
|
|
235
|
+
)
|
|
236
|
+
result[action_sha256] = point
|
|
237
|
+
return result
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
@dataclass(frozen=True, slots=True)
|
|
241
|
+
class V9CandidatePolicy:
|
|
242
|
+
"""Compose config-gated R1/R2/R3 over the frozen v8lite_r2 inner."""
|
|
243
|
+
|
|
244
|
+
archive_gain_utility: object = field(repr=False, compare=False)
|
|
245
|
+
config: V9CandidateConfig = V9CandidateConfig()
|
|
246
|
+
policy_id: str = V9_CANDIDATE_POLICY_ID
|
|
247
|
+
policy_version_id: str = field(init=False)
|
|
248
|
+
definition_sha256: str = field(init=False)
|
|
249
|
+
|
|
250
|
+
def __post_init__(self) -> None:
|
|
251
|
+
if type(self.config) is not V9CandidateConfig:
|
|
252
|
+
raise TypeError("config must be an exact v9 config")
|
|
253
|
+
self.config.__post_init__()
|
|
254
|
+
if (
|
|
255
|
+
type(self.policy_id) is not str
|
|
256
|
+
or _TOKEN.fullmatch(self.policy_id) is None
|
|
257
|
+
or self.policy_id != V9_CANDIDATE_POLICY_ID
|
|
258
|
+
):
|
|
259
|
+
raise ValueError("policy identity is immutable")
|
|
260
|
+
object.__setattr__(
|
|
261
|
+
self,
|
|
262
|
+
"policy_version_id",
|
|
263
|
+
self.config.arm_version_id,
|
|
264
|
+
)
|
|
265
|
+
inner = self.inner_policy()
|
|
266
|
+
challenger = self.region_challenger()
|
|
267
|
+
assessor = self.head_assessor()
|
|
268
|
+
bidder = self.elastic_bidder()
|
|
269
|
+
object.__setattr__(
|
|
270
|
+
self,
|
|
271
|
+
"definition_sha256",
|
|
272
|
+
_hash(
|
|
273
|
+
_DEFINITION_DOMAIN,
|
|
274
|
+
{
|
|
275
|
+
"schema_version": 1,
|
|
276
|
+
"policy_id": self.policy_id,
|
|
277
|
+
"policy_version": V9_CANDIDATE_POLICY_VERSION,
|
|
278
|
+
"policy_version_id": self.policy_version_id,
|
|
279
|
+
"flags": self.config.flags_record(),
|
|
280
|
+
"inner": {
|
|
281
|
+
"policy_id": inner.policy_id,
|
|
282
|
+
"policy_version_id": inner.policy_version_id,
|
|
283
|
+
"definition_sha256": inner.definition_sha256,
|
|
284
|
+
},
|
|
285
|
+
"components": {
|
|
286
|
+
"r1_region_conditional_credit": {
|
|
287
|
+
"policy_id": challenger.policy_id,
|
|
288
|
+
"policy_version": (
|
|
289
|
+
challenger.policy_version
|
|
290
|
+
),
|
|
291
|
+
"definition_sha256": (
|
|
292
|
+
challenger.definition_sha256
|
|
293
|
+
),
|
|
294
|
+
},
|
|
295
|
+
"r2_head_mass_conditional_seat": {
|
|
296
|
+
"policy_id": assessor.policy_id,
|
|
297
|
+
"policy_version": assessor.policy_version,
|
|
298
|
+
"definition_sha256": (
|
|
299
|
+
assessor.definition_sha256
|
|
300
|
+
),
|
|
301
|
+
},
|
|
302
|
+
"r3_geometry_conditional_elasticity": {
|
|
303
|
+
"policy_id": bidder.policy_id,
|
|
304
|
+
"policy_version": bidder.policy_version,
|
|
305
|
+
"definition_sha256": (
|
|
306
|
+
bidder.definition_sha256
|
|
307
|
+
),
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
"base_arm_bit_identical_to_inner": True,
|
|
311
|
+
"v7_terminal_rule_altered": False,
|
|
312
|
+
"live_authority": False,
|
|
313
|
+
"workload_objective_model_provider_prompt_branches": (
|
|
314
|
+
False
|
|
315
|
+
),
|
|
316
|
+
},
|
|
317
|
+
),
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
@property
|
|
321
|
+
def r1(self) -> bool:
|
|
322
|
+
return self.config.r1_region_conditional_credit
|
|
323
|
+
|
|
324
|
+
@property
|
|
325
|
+
def r2(self) -> bool:
|
|
326
|
+
return self.config.r2_head_mass_conditional_seat
|
|
327
|
+
|
|
328
|
+
@property
|
|
329
|
+
def r3(self) -> bool:
|
|
330
|
+
return self.config.r3_geometry_conditional_elasticity
|
|
331
|
+
|
|
332
|
+
def inner_policy(self) -> V8LiteAllocationPolicy:
|
|
333
|
+
return V8LiteAllocationPolicy(
|
|
334
|
+
archive_gain_utility=self.archive_gain_utility,
|
|
335
|
+
policy_version_id=(
|
|
336
|
+
V8LITE_ALLOCATION_POLICY_VERSION_ID_R2
|
|
337
|
+
),
|
|
338
|
+
config=self.config.base,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
def region_challenger(self) -> RegionConditionalChallengerPolicy:
|
|
342
|
+
return RegionConditionalChallengerPolicy(
|
|
343
|
+
base=self.inner_policy().challenger_policy(),
|
|
344
|
+
credit=self.config.credit,
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
def head_assessor(self) -> HeadMassSeatAssessor:
|
|
348
|
+
return HeadMassSeatAssessor(config=self.config.head)
|
|
349
|
+
|
|
350
|
+
def elastic_bidder(self) -> ElasticSeatBidder:
|
|
351
|
+
return ElasticSeatBidder(
|
|
352
|
+
config=self.config.elastic,
|
|
353
|
+
prior_strength=self.config.base.prior_strength,
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
def identity_record(self) -> dict[str, object]:
|
|
357
|
+
"""Public identity dict for one arm combination."""
|
|
358
|
+
|
|
359
|
+
self.__post_init__()
|
|
360
|
+
inner = self.inner_policy()
|
|
361
|
+
challenger = self.region_challenger()
|
|
362
|
+
assessor = self.head_assessor()
|
|
363
|
+
bidder = self.elastic_bidder()
|
|
364
|
+
return {
|
|
365
|
+
"policy_id": self.policy_id,
|
|
366
|
+
"policy_version": V9_CANDIDATE_POLICY_VERSION,
|
|
367
|
+
"policy_version_id": self.policy_version_id,
|
|
368
|
+
"flags": self.config.flags_record(),
|
|
369
|
+
"definition_sha256": self.definition_sha256,
|
|
370
|
+
"inner": inner.identity_record(),
|
|
371
|
+
"components": {
|
|
372
|
+
"r1_region_conditional_credit": {
|
|
373
|
+
"enabled": self.r1,
|
|
374
|
+
"policy_id": challenger.policy_id,
|
|
375
|
+
"definition_sha256": (
|
|
376
|
+
challenger.definition_sha256
|
|
377
|
+
),
|
|
378
|
+
},
|
|
379
|
+
"r2_head_mass_conditional_seat": {
|
|
380
|
+
"enabled": self.r2,
|
|
381
|
+
"policy_id": assessor.policy_id,
|
|
382
|
+
"definition_sha256": assessor.definition_sha256,
|
|
383
|
+
},
|
|
384
|
+
"r3_geometry_conditional_elasticity": {
|
|
385
|
+
"enabled": self.r3,
|
|
386
|
+
"policy_id": bidder.policy_id,
|
|
387
|
+
"definition_sha256": bidder.definition_sha256,
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
"v7_terminal_rule_altered": False,
|
|
391
|
+
"live_authority": False,
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
# ------------------------------------------------------------------
|
|
395
|
+
# Evidence construction shared by R1 scoring and R2 head assessment.
|
|
396
|
+
# ------------------------------------------------------------------
|
|
397
|
+
|
|
398
|
+
def _region_outcomes(
|
|
399
|
+
self,
|
|
400
|
+
*,
|
|
401
|
+
by_action: dict[str, AdaptiveActionDescriptor],
|
|
402
|
+
selected_action_sha256s: tuple[str, ...],
|
|
403
|
+
outcomes: tuple[AdaptiveActionOutcome, ...],
|
|
404
|
+
archive_points: tuple[ObjectivePoint, ...],
|
|
405
|
+
reference_point: ObjectivePoint,
|
|
406
|
+
feature_map: dict[str, RegionFeatures],
|
|
407
|
+
forecast_map: dict[str, PositiveGainForecast],
|
|
408
|
+
point_map: dict[str, ObjectivePoint],
|
|
409
|
+
prior_conversion_outcomes: tuple[
|
|
410
|
+
ObservedConversionOutcome,
|
|
411
|
+
...,
|
|
412
|
+
],
|
|
413
|
+
) -> tuple[RegionConditionalOutcome, ...]:
|
|
414
|
+
"""Prior evidence first, then within-market revealed outcomes.
|
|
415
|
+
|
|
416
|
+
Prior (pre-market) evidence carries no comparable parent
|
|
417
|
+
geometry, so it enters the hierarchy at the global and engine
|
|
418
|
+
levels only (``region_id=None``). Within-market outcomes are
|
|
419
|
+
classified against the CURRENT archive; when the outcome's
|
|
420
|
+
candidate carried a forecast, the (predicted, actual) direction
|
|
421
|
+
pair versus the same base archive feeds the trust channel.
|
|
422
|
+
"""
|
|
423
|
+
|
|
424
|
+
challenger = self.region_challenger()
|
|
425
|
+
gain_port = self.archive_gain_utility
|
|
426
|
+
result: list[RegionConditionalOutcome] = []
|
|
427
|
+
for ordinal, value in enumerate(
|
|
428
|
+
prior_conversion_outcomes,
|
|
429
|
+
start=1,
|
|
430
|
+
):
|
|
431
|
+
if type(value) is not ObservedConversionOutcome:
|
|
432
|
+
raise TypeError(
|
|
433
|
+
"prior_conversion_outcomes must contain exact "
|
|
434
|
+
"conversion outcomes"
|
|
435
|
+
)
|
|
436
|
+
result.append(
|
|
437
|
+
RegionConditionalOutcome(
|
|
438
|
+
observation_ordinal=ordinal,
|
|
439
|
+
engine_id=value.engine_id,
|
|
440
|
+
feasible=value.feasible,
|
|
441
|
+
marginal_archive_gain=(
|
|
442
|
+
value.marginal_archive_gain
|
|
443
|
+
),
|
|
444
|
+
)
|
|
445
|
+
)
|
|
446
|
+
outcome_by_action = {
|
|
447
|
+
value.action_sha256: value for value in outcomes
|
|
448
|
+
}
|
|
449
|
+
for ordinal, action_sha256 in enumerate(
|
|
450
|
+
sorted(selected_action_sha256s),
|
|
451
|
+
start=len(result) + 1,
|
|
452
|
+
):
|
|
453
|
+
outcome = outcome_by_action[action_sha256]
|
|
454
|
+
descriptor = by_action[action_sha256]
|
|
455
|
+
region_id, radius_class_id = challenger.region_for(
|
|
456
|
+
archive_points=archive_points,
|
|
457
|
+
reference_point=reference_point,
|
|
458
|
+
features=feature_map.get(
|
|
459
|
+
action_sha256,
|
|
460
|
+
RegionFeatures(),
|
|
461
|
+
),
|
|
462
|
+
)
|
|
463
|
+
forecast = forecast_map.get(action_sha256)
|
|
464
|
+
predicted: bool | None = None
|
|
465
|
+
actual: bool | None = None
|
|
466
|
+
if forecast is not None:
|
|
467
|
+
predicted = (
|
|
468
|
+
gain_port.marginal_archive_gain(
|
|
469
|
+
archive_points,
|
|
470
|
+
forecast.point("p50"),
|
|
471
|
+
)
|
|
472
|
+
> 0.0
|
|
473
|
+
)
|
|
474
|
+
point = point_map.get(action_sha256)
|
|
475
|
+
actual = (
|
|
476
|
+
point is not None
|
|
477
|
+
and gain_port.marginal_archive_gain(
|
|
478
|
+
archive_points,
|
|
479
|
+
point,
|
|
480
|
+
)
|
|
481
|
+
> 0.0
|
|
482
|
+
)
|
|
483
|
+
result.append(
|
|
484
|
+
RegionConditionalOutcome(
|
|
485
|
+
observation_ordinal=ordinal,
|
|
486
|
+
engine_id=descriptor.lane_id,
|
|
487
|
+
feasible=outcome.feasible,
|
|
488
|
+
marginal_archive_gain=(
|
|
489
|
+
outcome.marginal_archive_gain
|
|
490
|
+
),
|
|
491
|
+
region_id=region_id,
|
|
492
|
+
radius_class_id=radius_class_id,
|
|
493
|
+
forecast_predicted_positive=predicted,
|
|
494
|
+
forecast_actual_positive=actual,
|
|
495
|
+
)
|
|
496
|
+
)
|
|
497
|
+
return tuple(result)
|
|
498
|
+
|
|
499
|
+
def _score_candidates(
|
|
500
|
+
self,
|
|
501
|
+
*,
|
|
502
|
+
candidates: tuple[AdaptiveActionDescriptor, ...],
|
|
503
|
+
archive_points: tuple[ObjectivePoint, ...],
|
|
504
|
+
reference_point: ObjectivePoint,
|
|
505
|
+
feature_map: dict[str, RegionFeatures],
|
|
506
|
+
forecast_map: dict[str, PositiveGainForecast],
|
|
507
|
+
observed_outcomes: tuple[RegionConditionalOutcome, ...],
|
|
508
|
+
future_seats_remaining: int,
|
|
509
|
+
horizon_total: int,
|
|
510
|
+
frozen_fit_training_run_count: int,
|
|
511
|
+
):
|
|
512
|
+
"""Rank candidates with the arm's active calibrated model.
|
|
513
|
+
|
|
514
|
+
With R1 on, the region-conditional challenger scores with full
|
|
515
|
+
region evidence and learned trust. With R1 off, the SAME
|
|
516
|
+
scorer runs with features and leaf evidence stripped, so every
|
|
517
|
+
estimate collapses to the engine/global levels of the shrinkage
|
|
518
|
+
hierarchy and the trust multiplier stays exactly one.
|
|
519
|
+
"""
|
|
520
|
+
|
|
521
|
+
challenger = self.region_challenger()
|
|
522
|
+
scored = tuple(
|
|
523
|
+
RegionScoredCandidate(
|
|
524
|
+
candidate=PositiveGainCandidate(
|
|
525
|
+
action_sha256=value.action_sha256,
|
|
526
|
+
engine_id=value.lane_id,
|
|
527
|
+
native_rank=value.native_rank,
|
|
528
|
+
lane_size=value.lane_size,
|
|
529
|
+
forecast=forecast_map.get(value.action_sha256),
|
|
530
|
+
frozen_score=value.prior_score,
|
|
531
|
+
),
|
|
532
|
+
features=(
|
|
533
|
+
feature_map.get(
|
|
534
|
+
value.action_sha256,
|
|
535
|
+
RegionFeatures(),
|
|
536
|
+
)
|
|
537
|
+
if self.r1
|
|
538
|
+
else RegionFeatures()
|
|
539
|
+
),
|
|
540
|
+
)
|
|
541
|
+
for value in candidates
|
|
542
|
+
)
|
|
543
|
+
outcomes = (
|
|
544
|
+
observed_outcomes
|
|
545
|
+
if self.r1
|
|
546
|
+
else tuple(
|
|
547
|
+
RegionConditionalOutcome(
|
|
548
|
+
observation_ordinal=value.observation_ordinal,
|
|
549
|
+
engine_id=value.engine_id,
|
|
550
|
+
feasible=value.feasible,
|
|
551
|
+
marginal_archive_gain=(
|
|
552
|
+
value.marginal_archive_gain
|
|
553
|
+
),
|
|
554
|
+
)
|
|
555
|
+
for value in observed_outcomes
|
|
556
|
+
)
|
|
557
|
+
)
|
|
558
|
+
return challenger.score_market(
|
|
559
|
+
candidates=scored,
|
|
560
|
+
archive_points=archive_points,
|
|
561
|
+
reference_point=reference_point,
|
|
562
|
+
observed_outcomes=outcomes,
|
|
563
|
+
future_seats_remaining=future_seats_remaining,
|
|
564
|
+
horizon_total=horizon_total,
|
|
565
|
+
frozen_fit_training_run_count=(
|
|
566
|
+
frozen_fit_training_run_count
|
|
567
|
+
),
|
|
568
|
+
)
|
|
569
|
+
|
|
570
|
+
# ------------------------------------------------------------------
|
|
571
|
+
# Pilot seats.
|
|
572
|
+
# ------------------------------------------------------------------
|
|
573
|
+
|
|
574
|
+
def design_pilot_seat(
|
|
575
|
+
self,
|
|
576
|
+
*,
|
|
577
|
+
residual_request_sha256: str,
|
|
578
|
+
actions: tuple[AdaptiveActionDescriptor, ...],
|
|
579
|
+
evaluation_slots: int,
|
|
580
|
+
selected_action_sha256s: tuple[str, ...],
|
|
581
|
+
outcomes: tuple[AdaptiveActionOutcome, ...],
|
|
582
|
+
archive_points: tuple[ObjectivePoint, ...] = (),
|
|
583
|
+
reference_point: ObjectivePoint | None = None,
|
|
584
|
+
region_features: tuple[
|
|
585
|
+
tuple[str, RegionFeatures],
|
|
586
|
+
...,
|
|
587
|
+
] = (),
|
|
588
|
+
forecasts: tuple[
|
|
589
|
+
tuple[str, PositiveGainForecast],
|
|
590
|
+
...,
|
|
591
|
+
] = (),
|
|
592
|
+
prior_conversion_outcomes: tuple[
|
|
593
|
+
ObservedConversionOutcome,
|
|
594
|
+
...,
|
|
595
|
+
] = (),
|
|
596
|
+
frozen_fit_training_run_count: int = 0,
|
|
597
|
+
) -> V8LiteDecision:
|
|
598
|
+
"""One pilot seat under the arm's gated pilot refinements."""
|
|
599
|
+
|
|
600
|
+
self.__post_init__()
|
|
601
|
+
inner = self.inner_policy()
|
|
602
|
+
if not (self.r2 or self.r3):
|
|
603
|
+
return inner.design_pilot_seat(
|
|
604
|
+
residual_request_sha256=residual_request_sha256,
|
|
605
|
+
actions=actions,
|
|
606
|
+
evaluation_slots=evaluation_slots,
|
|
607
|
+
selected_action_sha256s=selected_action_sha256s,
|
|
608
|
+
outcomes=outcomes,
|
|
609
|
+
)
|
|
610
|
+
feature_map = _validated_feature_map(region_features)
|
|
611
|
+
forecast_map = _validated_forecast_map(forecasts)
|
|
612
|
+
by_action = {value.action_sha256: value for value in actions}
|
|
613
|
+
seat_ordinal = len(selected_action_sha256s) + 1
|
|
614
|
+
pilot_width = inner.pilot_width_for(
|
|
615
|
+
evaluation_slots=evaluation_slots,
|
|
616
|
+
engine_count=len(
|
|
617
|
+
{value.lane_id for value in actions}
|
|
618
|
+
),
|
|
619
|
+
)
|
|
620
|
+
if len(selected_action_sha256s) >= pilot_width:
|
|
621
|
+
raise ValueError("the pilot is already complete")
|
|
622
|
+
|
|
623
|
+
if (
|
|
624
|
+
self.r2
|
|
625
|
+
and seat_ordinal == 1
|
|
626
|
+
and archive_points
|
|
627
|
+
and reference_point is not None
|
|
628
|
+
):
|
|
629
|
+
ranking = self._score_candidates(
|
|
630
|
+
candidates=actions,
|
|
631
|
+
archive_points=archive_points,
|
|
632
|
+
reference_point=reference_point,
|
|
633
|
+
feature_map=feature_map,
|
|
634
|
+
forecast_map=forecast_map,
|
|
635
|
+
observed_outcomes=self._region_outcomes(
|
|
636
|
+
by_action=by_action,
|
|
637
|
+
selected_action_sha256s=(),
|
|
638
|
+
outcomes=(),
|
|
639
|
+
archive_points=archive_points,
|
|
640
|
+
reference_point=reference_point,
|
|
641
|
+
feature_map=feature_map,
|
|
642
|
+
forecast_map=forecast_map,
|
|
643
|
+
point_map={},
|
|
644
|
+
prior_conversion_outcomes=(
|
|
645
|
+
prior_conversion_outcomes
|
|
646
|
+
),
|
|
647
|
+
),
|
|
648
|
+
future_seats_remaining=evaluation_slots - 1,
|
|
649
|
+
horizon_total=evaluation_slots,
|
|
650
|
+
frozen_fit_training_run_count=(
|
|
651
|
+
frozen_fit_training_run_count
|
|
652
|
+
),
|
|
653
|
+
)
|
|
654
|
+
assessment = self.head_assessor().assess(ranking)
|
|
655
|
+
if assessment.fired:
|
|
656
|
+
return V8LiteDecision(
|
|
657
|
+
policy_id=self.policy_id,
|
|
658
|
+
policy_version_id=self.policy_version_id,
|
|
659
|
+
policy_definition_sha256=self.definition_sha256,
|
|
660
|
+
residual_request_sha256=(
|
|
661
|
+
residual_request_sha256
|
|
662
|
+
),
|
|
663
|
+
phase=V8LITE_PHASE_PILOT,
|
|
664
|
+
authority_policy_id=(
|
|
665
|
+
self.head_assessor().policy_id
|
|
666
|
+
),
|
|
667
|
+
selected_action_sha256s=(
|
|
668
|
+
assessment.argmax_action_sha256,
|
|
669
|
+
),
|
|
670
|
+
selection_propensity=1.0,
|
|
671
|
+
evidence=freeze_json(
|
|
672
|
+
{
|
|
673
|
+
"head_mass_seat": (
|
|
674
|
+
assessment.to_record()
|
|
675
|
+
),
|
|
676
|
+
"seat_ordinal": 1,
|
|
677
|
+
"deterministic_argmax_seat": True,
|
|
678
|
+
"support_propensities": [
|
|
679
|
+
{
|
|
680
|
+
"action_sha256": (
|
|
681
|
+
assessment.argmax_action_sha256
|
|
682
|
+
),
|
|
683
|
+
"propensity_hex": (1.0).hex(),
|
|
684
|
+
}
|
|
685
|
+
],
|
|
686
|
+
"remaining_seats_stochastic": True,
|
|
687
|
+
"candidate_outcomes_observed": False,
|
|
688
|
+
}
|
|
689
|
+
),
|
|
690
|
+
)
|
|
691
|
+
|
|
692
|
+
if not self.r3:
|
|
693
|
+
return inner.design_pilot_seat(
|
|
694
|
+
residual_request_sha256=residual_request_sha256,
|
|
695
|
+
actions=actions,
|
|
696
|
+
evaluation_slots=evaluation_slots,
|
|
697
|
+
selected_action_sha256s=selected_action_sha256s,
|
|
698
|
+
outcomes=outcomes,
|
|
699
|
+
)
|
|
700
|
+
|
|
701
|
+
# R3: elastic lane bids choose the engine; the within-engine
|
|
702
|
+
# seat is delegated to the inner sequential adaptive pilot over
|
|
703
|
+
# the chosen lane only (band adaptation therefore pools within
|
|
704
|
+
# the lane, which the definition sha records).
|
|
705
|
+
selected = set(selected_action_sha256s)
|
|
706
|
+
outcome_by_action = {
|
|
707
|
+
value.action_sha256: value for value in outcomes
|
|
708
|
+
}
|
|
709
|
+
lanes: dict[str, list[AdaptiveActionDescriptor]] = {}
|
|
710
|
+
for value in actions:
|
|
711
|
+
lanes.setdefault(value.lane_id, []).append(value)
|
|
712
|
+
gain_port = self.archive_gain_utility
|
|
713
|
+
lane_evidence: list[LaneGeometryEvidence] = []
|
|
714
|
+
for engine_id in sorted(lanes):
|
|
715
|
+
members = lanes[engine_id]
|
|
716
|
+
distances: list[float] = []
|
|
717
|
+
predicted: list[bool] = []
|
|
718
|
+
revealed: list[bool] = []
|
|
719
|
+
for value in members:
|
|
720
|
+
features = feature_map.get(value.action_sha256)
|
|
721
|
+
if (
|
|
722
|
+
features is not None
|
|
723
|
+
and features.parent_point is not None
|
|
724
|
+
):
|
|
725
|
+
distances.append(
|
|
726
|
+
parent_front_distance(
|
|
727
|
+
archive_points,
|
|
728
|
+
features.parent_point,
|
|
729
|
+
)
|
|
730
|
+
)
|
|
731
|
+
forecast = forecast_map.get(value.action_sha256)
|
|
732
|
+
if forecast is not None and archive_points:
|
|
733
|
+
predicted.append(
|
|
734
|
+
gain_port.marginal_archive_gain(
|
|
735
|
+
archive_points,
|
|
736
|
+
forecast.point("p50"),
|
|
737
|
+
)
|
|
738
|
+
<= 0.0
|
|
739
|
+
)
|
|
740
|
+
outcome = outcome_by_action.get(value.action_sha256)
|
|
741
|
+
if outcome is not None:
|
|
742
|
+
revealed.append(
|
|
743
|
+
outcome.marginal_archive_gain > 0.0
|
|
744
|
+
)
|
|
745
|
+
lane_evidence.append(
|
|
746
|
+
LaneGeometryEvidence(
|
|
747
|
+
engine_id=engine_id,
|
|
748
|
+
parent_front_distances=tuple(distances),
|
|
749
|
+
predicted_dominated=tuple(predicted),
|
|
750
|
+
revealed_positive=tuple(revealed),
|
|
751
|
+
)
|
|
752
|
+
)
|
|
753
|
+
bidder = self.elastic_bidder()
|
|
754
|
+
bids = bidder.lane_bids(tuple(lane_evidence))
|
|
755
|
+
seats_awarded = {
|
|
756
|
+
engine_id: sum(
|
|
757
|
+
by_action[value].lane_id == engine_id
|
|
758
|
+
for value in selected_action_sha256s
|
|
759
|
+
)
|
|
760
|
+
for engine_id in lanes
|
|
761
|
+
}
|
|
762
|
+
open_engine_ids = frozenset(
|
|
763
|
+
engine_id
|
|
764
|
+
for engine_id, members in lanes.items()
|
|
765
|
+
if any(
|
|
766
|
+
value.action_sha256 not in selected
|
|
767
|
+
for value in members
|
|
768
|
+
)
|
|
769
|
+
)
|
|
770
|
+
engine_id = bidder.choose_engine(
|
|
771
|
+
bids=bids,
|
|
772
|
+
seats_awarded=seats_awarded,
|
|
773
|
+
open_engine_ids=open_engine_ids,
|
|
774
|
+
)
|
|
775
|
+
lane_members = sorted(
|
|
776
|
+
lanes[engine_id],
|
|
777
|
+
key=lambda value: (
|
|
778
|
+
value.native_rank,
|
|
779
|
+
value.action_sha256,
|
|
780
|
+
),
|
|
781
|
+
)
|
|
782
|
+
lane_candidates = tuple(
|
|
783
|
+
RankBalancedPilotCandidate(
|
|
784
|
+
action_sha256=value.action_sha256,
|
|
785
|
+
engine_id=value.lane_id,
|
|
786
|
+
native_rank=value.native_rank,
|
|
787
|
+
frozen_score=value.prior_score,
|
|
788
|
+
)
|
|
789
|
+
for value in lane_members
|
|
790
|
+
)
|
|
791
|
+
lane_selected = tuple(
|
|
792
|
+
sorted(
|
|
793
|
+
value
|
|
794
|
+
for value in selected_action_sha256s
|
|
795
|
+
if by_action[value].lane_id == engine_id
|
|
796
|
+
)
|
|
797
|
+
)
|
|
798
|
+
lane_observations = tuple(
|
|
799
|
+
PilotSeatObservation(
|
|
800
|
+
action_sha256=value,
|
|
801
|
+
feasible=outcome_by_action[value].feasible,
|
|
802
|
+
marginal_archive_gain=(
|
|
803
|
+
outcome_by_action[value].marginal_archive_gain
|
|
804
|
+
),
|
|
805
|
+
)
|
|
806
|
+
for value in lane_selected
|
|
807
|
+
if value in outcome_by_action
|
|
808
|
+
)
|
|
809
|
+
seat = inner.pilot_policy().design_seat(
|
|
810
|
+
residual_request_sha256=residual_request_sha256,
|
|
811
|
+
candidates=lane_candidates,
|
|
812
|
+
selected_action_sha256s=lane_selected,
|
|
813
|
+
observations=lane_observations,
|
|
814
|
+
seat_ordinal=seat_ordinal,
|
|
815
|
+
)
|
|
816
|
+
return V8LiteDecision(
|
|
817
|
+
policy_id=self.policy_id,
|
|
818
|
+
policy_version_id=self.policy_version_id,
|
|
819
|
+
policy_definition_sha256=self.definition_sha256,
|
|
820
|
+
residual_request_sha256=residual_request_sha256,
|
|
821
|
+
phase=V8LITE_PHASE_PILOT,
|
|
822
|
+
authority_policy_id=self.elastic_bidder().policy_id,
|
|
823
|
+
selected_action_sha256s=(
|
|
824
|
+
seat.selected_action_sha256,
|
|
825
|
+
),
|
|
826
|
+
selection_propensity=seat.selection_propensity,
|
|
827
|
+
evidence=freeze_json(
|
|
828
|
+
{
|
|
829
|
+
"elastic_lane_bids": [
|
|
830
|
+
value.to_record() for value in bids
|
|
831
|
+
],
|
|
832
|
+
"chosen_engine_id": engine_id,
|
|
833
|
+
"seats_awarded_before": {
|
|
834
|
+
key: value
|
|
835
|
+
for key, value in sorted(
|
|
836
|
+
seats_awarded.items()
|
|
837
|
+
)
|
|
838
|
+
},
|
|
839
|
+
"pilot_seat": seat.to_record(),
|
|
840
|
+
"seat_ordinal": seat_ordinal,
|
|
841
|
+
"fixed_coverage_floor_used": False,
|
|
842
|
+
"candidate_outcomes_observed_before_seat": len(
|
|
843
|
+
outcomes
|
|
844
|
+
),
|
|
845
|
+
}
|
|
846
|
+
),
|
|
847
|
+
)
|
|
848
|
+
|
|
849
|
+
# ------------------------------------------------------------------
|
|
850
|
+
# Continuation seats.
|
|
851
|
+
# ------------------------------------------------------------------
|
|
852
|
+
|
|
853
|
+
def select_next(
|
|
854
|
+
self,
|
|
855
|
+
*,
|
|
856
|
+
residual_request_sha256: str,
|
|
857
|
+
actions: tuple[AdaptiveActionDescriptor, ...],
|
|
858
|
+
evaluation_slots: int,
|
|
859
|
+
diagnostic_action_sha256s: tuple[str, ...],
|
|
860
|
+
diagnostic_joint_gain: float,
|
|
861
|
+
selected_action_sha256s: tuple[str, ...],
|
|
862
|
+
outcomes: tuple[AdaptiveActionOutcome, ...],
|
|
863
|
+
archive_points: tuple[ObjectivePoint, ...],
|
|
864
|
+
reference_point: ObjectivePoint | None = None,
|
|
865
|
+
region_features: tuple[
|
|
866
|
+
tuple[str, RegionFeatures],
|
|
867
|
+
...,
|
|
868
|
+
] = (),
|
|
869
|
+
forecasts: tuple[
|
|
870
|
+
tuple[str, PositiveGainForecast],
|
|
871
|
+
...,
|
|
872
|
+
] = (),
|
|
873
|
+
revealed_objective_points: tuple[
|
|
874
|
+
tuple[str, ObjectivePoint],
|
|
875
|
+
...,
|
|
876
|
+
] = (),
|
|
877
|
+
frozen_fit_training_run_count: int = 0,
|
|
878
|
+
prior_conversion_outcomes: tuple[
|
|
879
|
+
ObservedConversionOutcome,
|
|
880
|
+
...,
|
|
881
|
+
] = (),
|
|
882
|
+
set_outcomes: tuple[AdaptiveActionSetOutcome, ...] = (),
|
|
883
|
+
) -> V8LiteDecision:
|
|
884
|
+
"""Select one continuation action at the current cutoff."""
|
|
885
|
+
|
|
886
|
+
self.__post_init__()
|
|
887
|
+
inner = self.inner_policy()
|
|
888
|
+
seats_left = evaluation_slots - len(selected_action_sha256s)
|
|
889
|
+
terminal = (
|
|
890
|
+
seats_left <= self.config.base.terminal_hierarchical_slots
|
|
891
|
+
)
|
|
892
|
+
if terminal or not self.r1 or reference_point is None:
|
|
893
|
+
# Terminal seats: EXACT V7 delegation through the inner
|
|
894
|
+
# policy; non-R1 arms: the inner challenger unchanged.
|
|
895
|
+
return inner.select_next(
|
|
896
|
+
residual_request_sha256=residual_request_sha256,
|
|
897
|
+
actions=actions,
|
|
898
|
+
evaluation_slots=evaluation_slots,
|
|
899
|
+
diagnostic_action_sha256s=diagnostic_action_sha256s,
|
|
900
|
+
diagnostic_joint_gain=diagnostic_joint_gain,
|
|
901
|
+
selected_action_sha256s=selected_action_sha256s,
|
|
902
|
+
outcomes=outcomes,
|
|
903
|
+
archive_points=archive_points,
|
|
904
|
+
forecasts=forecasts,
|
|
905
|
+
frozen_fit_training_run_count=(
|
|
906
|
+
frozen_fit_training_run_count
|
|
907
|
+
),
|
|
908
|
+
prior_conversion_outcomes=(
|
|
909
|
+
prior_conversion_outcomes
|
|
910
|
+
),
|
|
911
|
+
set_outcomes=set_outcomes,
|
|
912
|
+
)
|
|
913
|
+
feature_map = _validated_feature_map(region_features)
|
|
914
|
+
forecast_map = _validated_forecast_map(forecasts)
|
|
915
|
+
point_map = _validated_point_map(revealed_objective_points)
|
|
916
|
+
by_action = {value.action_sha256: value for value in actions}
|
|
917
|
+
outcome_by_action = {
|
|
918
|
+
value.action_sha256: value for value in outcomes
|
|
919
|
+
}
|
|
920
|
+
if set(outcome_by_action) != set(selected_action_sha256s):
|
|
921
|
+
raise ValueError(
|
|
922
|
+
"observations must exactly cover all previously "
|
|
923
|
+
"selected actions"
|
|
924
|
+
)
|
|
925
|
+
if not set(selected_action_sha256s) <= set(by_action):
|
|
926
|
+
raise ValueError(
|
|
927
|
+
"selected action is outside the sealed market"
|
|
928
|
+
)
|
|
929
|
+
selected_phenotypes = {
|
|
930
|
+
by_action[value].phenotype_sha256
|
|
931
|
+
for value in selected_action_sha256s
|
|
932
|
+
}
|
|
933
|
+
remaining = tuple(
|
|
934
|
+
value
|
|
935
|
+
for value in actions
|
|
936
|
+
if value.action_sha256 not in outcome_by_action
|
|
937
|
+
and value.phenotype_sha256 not in selected_phenotypes
|
|
938
|
+
)
|
|
939
|
+
if not remaining:
|
|
940
|
+
raise ValueError(
|
|
941
|
+
"no unevaluated action can fill the slate"
|
|
942
|
+
)
|
|
943
|
+
observed = self._region_outcomes(
|
|
944
|
+
by_action=by_action,
|
|
945
|
+
selected_action_sha256s=selected_action_sha256s,
|
|
946
|
+
outcomes=outcomes,
|
|
947
|
+
archive_points=archive_points,
|
|
948
|
+
reference_point=reference_point,
|
|
949
|
+
feature_map=feature_map,
|
|
950
|
+
forecast_map=forecast_map,
|
|
951
|
+
point_map=point_map,
|
|
952
|
+
prior_conversion_outcomes=prior_conversion_outcomes,
|
|
953
|
+
)
|
|
954
|
+
ranking = self._score_candidates(
|
|
955
|
+
candidates=remaining,
|
|
956
|
+
archive_points=archive_points,
|
|
957
|
+
reference_point=reference_point,
|
|
958
|
+
feature_map=feature_map,
|
|
959
|
+
forecast_map=forecast_map,
|
|
960
|
+
observed_outcomes=observed,
|
|
961
|
+
future_seats_remaining=seats_left - 1,
|
|
962
|
+
horizon_total=evaluation_slots,
|
|
963
|
+
frozen_fit_training_run_count=(
|
|
964
|
+
frozen_fit_training_run_count
|
|
965
|
+
),
|
|
966
|
+
)
|
|
967
|
+
top_action_sha256 = ranking.ranked_action_sha256s[0]
|
|
968
|
+
top_score = ranking.score_for(top_action_sha256)
|
|
969
|
+
if top_score.score > 0.0:
|
|
970
|
+
return V8LiteDecision(
|
|
971
|
+
policy_id=self.policy_id,
|
|
972
|
+
policy_version_id=self.policy_version_id,
|
|
973
|
+
policy_definition_sha256=self.definition_sha256,
|
|
974
|
+
residual_request_sha256=residual_request_sha256,
|
|
975
|
+
phase=V8LITE_PHASE_ADAPTIVE,
|
|
976
|
+
authority_policy_id=ranking.policy_id,
|
|
977
|
+
selected_action_sha256s=(top_action_sha256,),
|
|
978
|
+
selection_propensity=1.0,
|
|
979
|
+
evidence=freeze_json(
|
|
980
|
+
{
|
|
981
|
+
"challenger_ranking": ranking.to_record(
|
|
982
|
+
include_scores=True
|
|
983
|
+
),
|
|
984
|
+
"selected_score_sha256": (
|
|
985
|
+
top_score.score_sha256
|
|
986
|
+
),
|
|
987
|
+
"protected_fallback_used": False,
|
|
988
|
+
"region_conditional_credit": True,
|
|
989
|
+
"seats_left_before_decision": seats_left,
|
|
990
|
+
"prior_conversion_evidence_count": len(
|
|
991
|
+
prior_conversion_outcomes
|
|
992
|
+
),
|
|
993
|
+
"unobserved_candidate_outcomes_available": (
|
|
994
|
+
False
|
|
995
|
+
),
|
|
996
|
+
}
|
|
997
|
+
),
|
|
998
|
+
challenger_ranking=ranking,
|
|
999
|
+
)
|
|
1000
|
+
# Protected fallback: the frozen V7 incumbent decides, exactly
|
|
1001
|
+
# as the inner v8lite composition falls back.
|
|
1002
|
+
delegated = inner.terminal_policy().select_next(
|
|
1003
|
+
residual_request_sha256=residual_request_sha256,
|
|
1004
|
+
actions=actions,
|
|
1005
|
+
evaluation_slots=evaluation_slots,
|
|
1006
|
+
diagnostic_action_sha256s=diagnostic_action_sha256s,
|
|
1007
|
+
diagnostic_joint_gain=diagnostic_joint_gain,
|
|
1008
|
+
selected_action_sha256s=selected_action_sha256s,
|
|
1009
|
+
outcomes=outcomes,
|
|
1010
|
+
set_outcomes=set_outcomes,
|
|
1011
|
+
)
|
|
1012
|
+
return V8LiteDecision(
|
|
1013
|
+
policy_id=self.policy_id,
|
|
1014
|
+
policy_version_id=self.policy_version_id,
|
|
1015
|
+
policy_definition_sha256=self.definition_sha256,
|
|
1016
|
+
residual_request_sha256=residual_request_sha256,
|
|
1017
|
+
phase=V8LITE_PHASE_PROTECTED_FALLBACK,
|
|
1018
|
+
authority_policy_id=delegated.policy_id,
|
|
1019
|
+
selected_action_sha256s=(
|
|
1020
|
+
delegated.selected_action_sha256s
|
|
1021
|
+
),
|
|
1022
|
+
selection_propensity=delegated.selection_propensity,
|
|
1023
|
+
evidence=freeze_json(
|
|
1024
|
+
{
|
|
1025
|
+
"protected_fallback_used": True,
|
|
1026
|
+
"fallback_reason": (
|
|
1027
|
+
"challenger_top_score_non_positive"
|
|
1028
|
+
),
|
|
1029
|
+
"region_conditional_credit": True,
|
|
1030
|
+
"challenger_ranking": ranking.to_record(
|
|
1031
|
+
include_scores=True
|
|
1032
|
+
),
|
|
1033
|
+
"seats_left_before_decision": seats_left,
|
|
1034
|
+
"delegated_decision": delegated.to_record(
|
|
1035
|
+
include_evidence=True
|
|
1036
|
+
),
|
|
1037
|
+
}
|
|
1038
|
+
),
|
|
1039
|
+
delegated_decision=delegated,
|
|
1040
|
+
challenger_ranking=ranking,
|
|
1041
|
+
)
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
class V9ReplayPolicy:
|
|
1045
|
+
"""Drive one V9 arm inside the sealed-market replay boundary.
|
|
1046
|
+
|
|
1047
|
+
The universe, descriptors, and outcome-blind request identity are
|
|
1048
|
+
built by the SAME code the v8lite adapter uses (delegated to an
|
|
1049
|
+
internal ``V8LiteReplayPolicy``), so the base arm is bit-identical
|
|
1050
|
+
to the reference. Region features, forecasts, and revealed
|
|
1051
|
+
objective points are keyed by action and passed through outcome-
|
|
1052
|
+
blind: revealed points cover only already-revealed candidates.
|
|
1053
|
+
"""
|
|
1054
|
+
|
|
1055
|
+
def __init__(
|
|
1056
|
+
self,
|
|
1057
|
+
policy: V9CandidatePolicy,
|
|
1058
|
+
*,
|
|
1059
|
+
frozen_fit_training_run_count: int = 0,
|
|
1060
|
+
prior_conversion_outcomes: tuple[
|
|
1061
|
+
ObservedConversionOutcome,
|
|
1062
|
+
...,
|
|
1063
|
+
] = (),
|
|
1064
|
+
region_features: tuple[
|
|
1065
|
+
tuple[str, RegionFeatures],
|
|
1066
|
+
...,
|
|
1067
|
+
] = (),
|
|
1068
|
+
) -> None:
|
|
1069
|
+
if type(policy) is not V9CandidatePolicy:
|
|
1070
|
+
raise TypeError("policy must be an exact V9 policy")
|
|
1071
|
+
policy.__post_init__()
|
|
1072
|
+
self.policy_id = (
|
|
1073
|
+
f"replay_adapter.{policy.policy_version_id}"
|
|
1074
|
+
)
|
|
1075
|
+
self._policy = policy
|
|
1076
|
+
self._frozen_fit_training_run_count = (
|
|
1077
|
+
frozen_fit_training_run_count
|
|
1078
|
+
)
|
|
1079
|
+
self._prior_conversion_outcomes = prior_conversion_outcomes
|
|
1080
|
+
self._region_features = _validated_feature_map(
|
|
1081
|
+
region_features
|
|
1082
|
+
)
|
|
1083
|
+
self._helper = V8LiteReplayPolicy(
|
|
1084
|
+
policy.inner_policy(),
|
|
1085
|
+
frozen_fit_training_run_count=(
|
|
1086
|
+
frozen_fit_training_run_count
|
|
1087
|
+
),
|
|
1088
|
+
prior_conversion_outcomes=prior_conversion_outcomes,
|
|
1089
|
+
)
|
|
1090
|
+
|
|
1091
|
+
def select(
|
|
1092
|
+
self,
|
|
1093
|
+
*,
|
|
1094
|
+
record: MarketRecord,
|
|
1095
|
+
revealed: tuple[ReplayStepReceipt, ...],
|
|
1096
|
+
selectable_action_sha256s: tuple[str, ...],
|
|
1097
|
+
step_index: int,
|
|
1098
|
+
budget: int,
|
|
1099
|
+
) -> ReplaySelection:
|
|
1100
|
+
universe_ids = tuple(
|
|
1101
|
+
sorted(
|
|
1102
|
+
{
|
|
1103
|
+
*selectable_action_sha256s,
|
|
1104
|
+
*(value.action_sha256 for value in revealed),
|
|
1105
|
+
}
|
|
1106
|
+
)
|
|
1107
|
+
)
|
|
1108
|
+
descriptors = self._helper._descriptors(record, universe_ids)
|
|
1109
|
+
request_sha256 = self._helper._outcome_blind_request_sha256(
|
|
1110
|
+
record,
|
|
1111
|
+
universe_ids,
|
|
1112
|
+
)
|
|
1113
|
+
pilot_width = self._policy.inner_policy().pilot_width_for(
|
|
1114
|
+
evaluation_slots=budget,
|
|
1115
|
+
engine_count=len(
|
|
1116
|
+
{value.lane_id for value in descriptors}
|
|
1117
|
+
),
|
|
1118
|
+
)
|
|
1119
|
+
if pilot_width <= 0:
|
|
1120
|
+
raise ValueError("replay budget leaves no pilot")
|
|
1121
|
+
selected_ids = tuple(
|
|
1122
|
+
sorted(value.action_sha256 for value in revealed)
|
|
1123
|
+
)
|
|
1124
|
+
outcome_by_action = {
|
|
1125
|
+
value.action_sha256: value for value in revealed
|
|
1126
|
+
}
|
|
1127
|
+
outcomes = tuple(
|
|
1128
|
+
AdaptiveActionOutcome(
|
|
1129
|
+
action_sha256=action_sha256,
|
|
1130
|
+
evaluation_sha256=hashlib.sha256(
|
|
1131
|
+
f"replay-evaluation:{action_sha256}".encode(
|
|
1132
|
+
"ascii"
|
|
1133
|
+
)
|
|
1134
|
+
).hexdigest(),
|
|
1135
|
+
feasible=outcome_by_action[action_sha256].feasible,
|
|
1136
|
+
marginal_archive_gain=(
|
|
1137
|
+
outcome_by_action[action_sha256].marginal_gain
|
|
1138
|
+
),
|
|
1139
|
+
)
|
|
1140
|
+
for action_sha256 in selected_ids
|
|
1141
|
+
)
|
|
1142
|
+
forecasts = tuple(
|
|
1143
|
+
(value.action_sha256, value.forecast)
|
|
1144
|
+
for value in (
|
|
1145
|
+
record.candidate(item) for item in universe_ids
|
|
1146
|
+
)
|
|
1147
|
+
if value.forecast is not None
|
|
1148
|
+
)
|
|
1149
|
+
region_features = tuple(
|
|
1150
|
+
sorted(
|
|
1151
|
+
(action_sha256, features)
|
|
1152
|
+
for action_sha256, features in (
|
|
1153
|
+
self._region_features.items()
|
|
1154
|
+
)
|
|
1155
|
+
if action_sha256 in set(universe_ids)
|
|
1156
|
+
)
|
|
1157
|
+
)
|
|
1158
|
+
if step_index < pilot_width:
|
|
1159
|
+
decision = self._policy.design_pilot_seat(
|
|
1160
|
+
residual_request_sha256=request_sha256,
|
|
1161
|
+
actions=descriptors,
|
|
1162
|
+
evaluation_slots=budget,
|
|
1163
|
+
selected_action_sha256s=selected_ids,
|
|
1164
|
+
outcomes=outcomes,
|
|
1165
|
+
archive_points=record.archive_points,
|
|
1166
|
+
reference_point=record.hv_reference_point,
|
|
1167
|
+
region_features=region_features,
|
|
1168
|
+
forecasts=forecasts,
|
|
1169
|
+
prior_conversion_outcomes=(
|
|
1170
|
+
self._prior_conversion_outcomes
|
|
1171
|
+
),
|
|
1172
|
+
frozen_fit_training_run_count=(
|
|
1173
|
+
self._frozen_fit_training_run_count
|
|
1174
|
+
),
|
|
1175
|
+
)
|
|
1176
|
+
return ReplaySelection(
|
|
1177
|
+
action_sha256=decision.selected_action_sha256s[0],
|
|
1178
|
+
selection_propensity=decision.selection_propensity,
|
|
1179
|
+
evidence={
|
|
1180
|
+
"phase": decision.phase,
|
|
1181
|
+
"authority_policy_id": (
|
|
1182
|
+
decision.authority_policy_id
|
|
1183
|
+
),
|
|
1184
|
+
},
|
|
1185
|
+
)
|
|
1186
|
+
pilot_ids = tuple(
|
|
1187
|
+
sorted(
|
|
1188
|
+
value.action_sha256
|
|
1189
|
+
for value in revealed[:pilot_width]
|
|
1190
|
+
)
|
|
1191
|
+
)
|
|
1192
|
+
pilot_points = tuple(
|
|
1193
|
+
record.candidate(value).objectives
|
|
1194
|
+
for value in pilot_ids
|
|
1195
|
+
if record.candidate(value).objectives is not None
|
|
1196
|
+
)
|
|
1197
|
+
diagnostic_joint_gain = _clamped_gain(
|
|
1198
|
+
float(
|
|
1199
|
+
record.hypervolume(pilot_points)
|
|
1200
|
+
- record.hypervolume()
|
|
1201
|
+
)
|
|
1202
|
+
)
|
|
1203
|
+
revealed_objective_points = tuple(
|
|
1204
|
+
(value, record.candidate(value).objectives)
|
|
1205
|
+
for value in selected_ids
|
|
1206
|
+
if record.candidate(value).objectives is not None
|
|
1207
|
+
)
|
|
1208
|
+
decision = self._policy.select_next(
|
|
1209
|
+
residual_request_sha256=request_sha256,
|
|
1210
|
+
actions=descriptors,
|
|
1211
|
+
evaluation_slots=budget,
|
|
1212
|
+
diagnostic_action_sha256s=pilot_ids,
|
|
1213
|
+
diagnostic_joint_gain=diagnostic_joint_gain,
|
|
1214
|
+
selected_action_sha256s=selected_ids,
|
|
1215
|
+
outcomes=outcomes,
|
|
1216
|
+
archive_points=record.archive_points,
|
|
1217
|
+
reference_point=record.hv_reference_point,
|
|
1218
|
+
region_features=region_features,
|
|
1219
|
+
forecasts=forecasts,
|
|
1220
|
+
revealed_objective_points=revealed_objective_points,
|
|
1221
|
+
frozen_fit_training_run_count=(
|
|
1222
|
+
self._frozen_fit_training_run_count
|
|
1223
|
+
),
|
|
1224
|
+
prior_conversion_outcomes=(
|
|
1225
|
+
self._prior_conversion_outcomes
|
|
1226
|
+
),
|
|
1227
|
+
)
|
|
1228
|
+
return ReplaySelection(
|
|
1229
|
+
action_sha256=decision.selected_action_sha256s[0],
|
|
1230
|
+
selection_propensity=decision.selection_propensity,
|
|
1231
|
+
evidence={
|
|
1232
|
+
"phase": decision.phase,
|
|
1233
|
+
"authority_policy_id": (
|
|
1234
|
+
decision.authority_policy_id
|
|
1235
|
+
),
|
|
1236
|
+
},
|
|
1237
|
+
)
|
|
1238
|
+
|
|
1239
|
+
|
|
1240
|
+
def region_features_from_corpus(
|
|
1241
|
+
payload: dict[str, object],
|
|
1242
|
+
) -> tuple[tuple[str, RegionFeatures], ...]:
|
|
1243
|
+
"""Outcome-blind provenance features from one corpus market payload.
|
|
1244
|
+
|
|
1245
|
+
Parent objective points are normalized onto the SAME axes frame the
|
|
1246
|
+
replay loader uses; candidates without a recorded parent objective
|
|
1247
|
+
vector or radius degrade to absent features (region ``no_parent``,
|
|
1248
|
+
radius class ``none``), so markets without provenance stay at the
|
|
1249
|
+
hierarchy's engine level by construction.
|
|
1250
|
+
"""
|
|
1251
|
+
|
|
1252
|
+
market_id = str(payload["market_id"])
|
|
1253
|
+
axes = tuple(payload["hv_reference_point"]["axes"])
|
|
1254
|
+
metric_ids = tuple(
|
|
1255
|
+
sorted(str(axis["metric_id"]) for axis in axes)
|
|
1256
|
+
)
|
|
1257
|
+
result: list[tuple[str, RegionFeatures]] = []
|
|
1258
|
+
for raw in payload["candidates"]:
|
|
1259
|
+
action_sha256 = _corpus_action_sha256(market_id, raw)
|
|
1260
|
+
parent = raw.get("parent")
|
|
1261
|
+
parent_point: ObjectivePoint | None = None
|
|
1262
|
+
if isinstance(parent, dict):
|
|
1263
|
+
parent_objectives = parent.get("objectives")
|
|
1264
|
+
if isinstance(parent_objectives, dict) and set(
|
|
1265
|
+
metric_ids
|
|
1266
|
+
) <= set(parent_objectives):
|
|
1267
|
+
parent_point = _normalized_point(
|
|
1268
|
+
{
|
|
1269
|
+
metric_id: float(
|
|
1270
|
+
parent_objectives[metric_id]
|
|
1271
|
+
)
|
|
1272
|
+
for metric_id in metric_ids
|
|
1273
|
+
},
|
|
1274
|
+
axes,
|
|
1275
|
+
)
|
|
1276
|
+
radius = raw.get("radius")
|
|
1277
|
+
result.append(
|
|
1278
|
+
(
|
|
1279
|
+
action_sha256,
|
|
1280
|
+
RegionFeatures(
|
|
1281
|
+
parent_point=parent_point,
|
|
1282
|
+
radius=(
|
|
1283
|
+
int(radius)
|
|
1284
|
+
if isinstance(radius, int)
|
|
1285
|
+
and not isinstance(radius, bool)
|
|
1286
|
+
and radius >= 0
|
|
1287
|
+
else None
|
|
1288
|
+
),
|
|
1289
|
+
),
|
|
1290
|
+
)
|
|
1291
|
+
)
|
|
1292
|
+
return tuple(sorted(result))
|
|
1293
|
+
|
|
1294
|
+
|
|
1295
|
+
__all__ = [
|
|
1296
|
+
"V9_CANDIDATE_POLICY_ID",
|
|
1297
|
+
"V9_CANDIDATE_POLICY_VERSION",
|
|
1298
|
+
"V9CandidateConfig",
|
|
1299
|
+
"V9CandidatePolicy",
|
|
1300
|
+
"V9ReplayPolicy",
|
|
1301
|
+
"region_features_from_corpus",
|
|
1302
|
+
"v9_arm_version_id",
|
|
1303
|
+
]
|