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,1374 @@
|
|
|
1
|
+
"""All-action, outcome-conditioned portfolio selection for real campaigns.
|
|
2
|
+
|
|
3
|
+
The policy is an adapter between the campaign's stable
|
|
4
|
+
``PortfolioSelectionPolicy`` port and the generic action-forecast/allocation
|
|
5
|
+
ports. It asks a model to forecast every action in a sealed, outcome-blind
|
|
6
|
+
candidate-pool projection (or the complete contract when no projection is
|
|
7
|
+
bound), optionally
|
|
8
|
+
overlays evaluator-independent exact metric projections, and lets trusted code
|
|
9
|
+
construct the final hard-feasible set. Workload adapters may enrich action
|
|
10
|
+
semantics or exact cheap metric cells, but never rank or select actions.
|
|
11
|
+
|
|
12
|
+
The implementation also reconciles the existing bounded memory-dose contract:
|
|
13
|
+
memory-supported options become explicit hard requirements, while a sealed
|
|
14
|
+
proposal witness is extended only as far as necessary to preserve the original
|
|
15
|
+
proposal/evaluation join. This keeps memory attribution causal and makes the
|
|
16
|
+
new selector usable in later generations rather than only in memory-free
|
|
17
|
+
assays.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
import hashlib
|
|
23
|
+
import itertools
|
|
24
|
+
import json
|
|
25
|
+
import math
|
|
26
|
+
import time
|
|
27
|
+
from dataclasses import dataclass
|
|
28
|
+
from decimal import Decimal
|
|
29
|
+
from typing import Callable
|
|
30
|
+
|
|
31
|
+
from agent_evolve.application.action_forecast_partitioning import (
|
|
32
|
+
PartitionedActionForecastPolicy,
|
|
33
|
+
ResolvedActionForecastHealthAssessment,
|
|
34
|
+
assess_resolved_action_forecast_health,
|
|
35
|
+
build_action_forecast_partition_layout,
|
|
36
|
+
lenient_action_forecast_health_policy,
|
|
37
|
+
)
|
|
38
|
+
from agent_evolve.application.action_metric_projection import (
|
|
39
|
+
ActionMetricProjectionOverlayResult,
|
|
40
|
+
apply_exact_action_metric_projections,
|
|
41
|
+
)
|
|
42
|
+
from agent_evolve.application.campaign_search_phase import (
|
|
43
|
+
resolve_campaign_search_phase_context,
|
|
44
|
+
)
|
|
45
|
+
from agent_evolve.application.campaign_variation_trace import (
|
|
46
|
+
project_finite_contract_proposal_topology,
|
|
47
|
+
)
|
|
48
|
+
from agent_evolve.application.contextual_action_allocation import (
|
|
49
|
+
contextual_action_arm_count_constraints,
|
|
50
|
+
contextual_allocation_realization,
|
|
51
|
+
selected_variation_source_ids,
|
|
52
|
+
)
|
|
53
|
+
from agent_evolve.application.empirical_consequence_calibration import (
|
|
54
|
+
ActionConsequenceCalibrationPolicy,
|
|
55
|
+
ActionConsequenceCalibrationResult,
|
|
56
|
+
)
|
|
57
|
+
from agent_evolve.application.global_wave_action_allocation import (
|
|
58
|
+
GlobalWaveActionAllocationCoordinator,
|
|
59
|
+
GlobalWaveActionAllocationLane,
|
|
60
|
+
GlobalWaveActionAllocationLaneResult,
|
|
61
|
+
RoleSlots,
|
|
62
|
+
)
|
|
63
|
+
from agent_evolve.application.target_conditioned_action_forecast import (
|
|
64
|
+
TargetConditionedActionForecastPlan,
|
|
65
|
+
allocate_target_conditioned_actions,
|
|
66
|
+
audit_target_conditioned_role_allocation,
|
|
67
|
+
build_target_conditioned_action_forecast_plan,
|
|
68
|
+
)
|
|
69
|
+
from agent_evolve.core.action_semantics import ActionSpaceSemantics
|
|
70
|
+
from agent_evolve.core.optimization_semantics import OptimizationSemantics
|
|
71
|
+
from agent_evolve.domain.finite_variation import FiniteVariationContract
|
|
72
|
+
from agent_evolve.domain.ids import LLMCallId
|
|
73
|
+
from agent_evolve.domain.typed_json import FrozenJsonObject, freeze_json, thaw_json
|
|
74
|
+
from agent_evolve.ports.action_allocation import ActionAllocationResult
|
|
75
|
+
from agent_evolve.ports.action_forecast import (
|
|
76
|
+
ActionForecastEvidenceMode,
|
|
77
|
+
ActionForecastPartitionPolicyBinding,
|
|
78
|
+
ResolvedActionForecast,
|
|
79
|
+
ResolvedActionForecastBatch,
|
|
80
|
+
)
|
|
81
|
+
from agent_evolve.ports.action_metric_projection import (
|
|
82
|
+
ActionMetricProjector,
|
|
83
|
+
ExactActionMetricProjectionBatch,
|
|
84
|
+
)
|
|
85
|
+
from agent_evolve.ports.contextual_search_allocation import (
|
|
86
|
+
ContextualPortfolioAllocationContract,
|
|
87
|
+
ContextualPortfolioAllocationRealization,
|
|
88
|
+
)
|
|
89
|
+
from agent_evolve.ports.agentic_generator import (
|
|
90
|
+
AgenticCallTelemetry,
|
|
91
|
+
MetricEffectDirection,
|
|
92
|
+
MetricEffectPrediction,
|
|
93
|
+
)
|
|
94
|
+
from agent_evolve.ports.portfolio_memory_dose import (
|
|
95
|
+
PortfolioMemoryDoseAssessment,
|
|
96
|
+
PortfolioMemoryDoseMember,
|
|
97
|
+
assess_evaluated_portfolio_memory_dose,
|
|
98
|
+
assess_proposed_portfolio_memory_dose,
|
|
99
|
+
)
|
|
100
|
+
from agent_evolve.ports.portfolio_selection import (
|
|
101
|
+
PortfolioMemberDraft,
|
|
102
|
+
PortfolioSelectionRequest,
|
|
103
|
+
PortfolioSelectionResult,
|
|
104
|
+
PortfolioSelectionSupplementalAudit,
|
|
105
|
+
resolve_ranked_portfolio_decision,
|
|
106
|
+
)
|
|
107
|
+
from agent_evolve.policies.selection.forecast_calibration import (
|
|
108
|
+
ForecastCalibrationScope,
|
|
109
|
+
ForecastConfidenceBin,
|
|
110
|
+
ForecastPredictionReceipt,
|
|
111
|
+
)
|
|
112
|
+
from agent_evolve.policies.selection.common_candidate_pool import (
|
|
113
|
+
CommonCandidatePoolDecision,
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
OUTCOME_CONDITIONED_PORTFOLIO_POLICY_ID = "outcome_conditioned_expert_portfolio"
|
|
118
|
+
OUTCOME_CONDITIONED_PORTFOLIO_POLICY_VERSION = 8
|
|
119
|
+
OUTCOME_CONDITIONED_PORTFOLIO_POLICY_DEFINITION_SHA256 = hashlib.sha256(
|
|
120
|
+
b"agent-evolve:outcome-conditioned-expert-portfolio:v8;"
|
|
121
|
+
b"proposal-universe=full-sealed-contract-with-outcome-blind-authenticated-"
|
|
122
|
+
b"candidate-pool-forecast-projection;"
|
|
123
|
+
b"consequence-source=partitioned-llm-plus-prior-only-calibration-port;"
|
|
124
|
+
b"optional-authority=evaluator-independent-exact-metric-projection;"
|
|
125
|
+
b"bootstrap-acquisition=target-closure-when-residual-cell-unidentified;"
|
|
126
|
+
b"nonterminal-residual-acquisition=role-factorized-exploit-bridge-probe;"
|
|
127
|
+
b"terminal-residual-acquisition=reliability-adjusted-expected-hypervolume;"
|
|
128
|
+
b"hard-constraints=family-patch-required-option-memory-dose-contextual-"
|
|
129
|
+
b"source-and-operator-marginals;"
|
|
130
|
+
b"forecast-health=model-authoritative-unprojected-cells-only;"
|
|
131
|
+
b"model-authors-consequences-not-selection;"
|
|
132
|
+
b"optional-wave-authority=global-role-budget-and-cross-lane-diversity;"
|
|
133
|
+
b"audit-proposal-topology=engine-authenticated-forecast-contract;"
|
|
134
|
+
b"workload-branches=false;real-current-future-outcomes=false"
|
|
135
|
+
).hexdigest()
|
|
136
|
+
_FORECAST_CALL_DOMAIN = b"agent-evolve:outcome-conditioned-forecast-call:v1\x00"
|
|
137
|
+
_BOUND_POLICY_DOMAIN = b"agent-evolve:outcome-conditioned-policy-binding:v1\x00"
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
ActionSemanticsFactory = Callable[[FiniteVariationContract], ActionSpaceSemantics]
|
|
141
|
+
ContextualAllocationProvider = Callable[
|
|
142
|
+
[PortfolioSelectionRequest], ContextualPortfolioAllocationContract | None
|
|
143
|
+
]
|
|
144
|
+
CandidatePoolProvider = Callable[
|
|
145
|
+
[PortfolioSelectionRequest], CommonCandidatePoolDecision | None
|
|
146
|
+
]
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def _forecast_contract_projection(
|
|
150
|
+
request: PortfolioSelectionRequest,
|
|
151
|
+
decision: CommonCandidatePoolDecision | None,
|
|
152
|
+
) -> tuple[FiniteVariationContract, dict[str, object]]:
|
|
153
|
+
"""Project the expensive forecast surface without hiding union support."""
|
|
154
|
+
|
|
155
|
+
source = request.finite_variation_contract
|
|
156
|
+
if decision is None:
|
|
157
|
+
return source, {
|
|
158
|
+
"mode": "complete_finite_contract",
|
|
159
|
+
"source_contract_sha256": source.identity_sha256,
|
|
160
|
+
"forecast_contract_sha256": source.identity_sha256,
|
|
161
|
+
"source_option_count": len(source.options),
|
|
162
|
+
"forecast_option_count": len(source.options),
|
|
163
|
+
"common_candidate_pool_decision_sha256": None,
|
|
164
|
+
}
|
|
165
|
+
if type(decision) is not CommonCandidatePoolDecision:
|
|
166
|
+
raise TypeError("candidate-pool provider returned a foreign decision")
|
|
167
|
+
decision.__post_init__()
|
|
168
|
+
if (
|
|
169
|
+
decision.finite_contract_sha256 != source.identity_sha256
|
|
170
|
+
or decision.parent_configuration_sha256
|
|
171
|
+
!= source.parent_configuration_sha256
|
|
172
|
+
or decision.evaluation_size != request.portfolio_size
|
|
173
|
+
):
|
|
174
|
+
raise ValueError("candidate-pool decision differs from the selection request")
|
|
175
|
+
options = {value.option_id: value for value in source.options}
|
|
176
|
+
try:
|
|
177
|
+
projected_options = tuple(options[value] for value in decision.option_ids)
|
|
178
|
+
except KeyError as error: # pragma: no cover - decision validation closes this.
|
|
179
|
+
raise ValueError("candidate-pool option escapes the source contract") from error
|
|
180
|
+
projected = FiniteVariationContract(
|
|
181
|
+
catalog_id=source.catalog_id,
|
|
182
|
+
catalog_version=source.catalog_version,
|
|
183
|
+
catalog_definition_sha256=source.catalog_definition_sha256,
|
|
184
|
+
parent_configuration=source.parent_configuration,
|
|
185
|
+
options=projected_options,
|
|
186
|
+
)
|
|
187
|
+
return projected, {
|
|
188
|
+
"mode": "authenticated_outcome_blind_candidate_pool",
|
|
189
|
+
"source_contract_sha256": source.identity_sha256,
|
|
190
|
+
"forecast_contract_sha256": projected.identity_sha256,
|
|
191
|
+
"source_option_count": len(source.options),
|
|
192
|
+
"forecast_option_count": len(projected.options),
|
|
193
|
+
"common_candidate_pool_decision_sha256": decision.decision_sha256,
|
|
194
|
+
"common_candidate_pool_state_identity_sha256": (
|
|
195
|
+
decision.state_identity_sha256
|
|
196
|
+
),
|
|
197
|
+
"common_candidate_pool_task_identity_sha256": decision.task_identity_sha256,
|
|
198
|
+
"forecast_option_ids": list(decision.option_ids),
|
|
199
|
+
"outcomes_consulted": False,
|
|
200
|
+
"model_or_provider_fields_consulted": False,
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _identified_outcome_conditioned_acquisition(
|
|
205
|
+
*,
|
|
206
|
+
residual_cell_identified: bool,
|
|
207
|
+
terminal: bool,
|
|
208
|
+
) -> tuple[str, str]:
|
|
209
|
+
"""Choose only an acquisition whose geometric estimand is identified."""
|
|
210
|
+
|
|
211
|
+
if type(residual_cell_identified) is not bool or type(terminal) is not bool:
|
|
212
|
+
raise TypeError("acquisition evidence flags must be exact bools")
|
|
213
|
+
if not residual_cell_identified:
|
|
214
|
+
return "target_closure", "directional_affine_bootstrap"
|
|
215
|
+
if terminal:
|
|
216
|
+
return (
|
|
217
|
+
"reliability_adjusted_expected_hypervolume",
|
|
218
|
+
"residual_frontier_cell",
|
|
219
|
+
)
|
|
220
|
+
return "role_factorized", "residual_frontier_cell"
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def _canonical_json(value: object) -> bytes:
|
|
224
|
+
return json.dumps(
|
|
225
|
+
value,
|
|
226
|
+
allow_nan=False,
|
|
227
|
+
ensure_ascii=True,
|
|
228
|
+
separators=(",", ":"),
|
|
229
|
+
sort_keys=True,
|
|
230
|
+
).encode("ascii", errors="strict")
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _object(value: dict[str, object]) -> FrozenJsonObject:
|
|
234
|
+
frozen = freeze_json(value)
|
|
235
|
+
if type(frozen) is not FrozenJsonObject: # pragma: no cover - closed root.
|
|
236
|
+
raise AssertionError("selector audit did not freeze to an object")
|
|
237
|
+
return frozen
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _plain_global_allocation_audit(
|
|
241
|
+
value: GlobalWaveActionAllocationLaneResult | None,
|
|
242
|
+
) -> dict[str, object] | None:
|
|
243
|
+
"""Cross the immutable typed-JSON boundary exactly once for nesting."""
|
|
244
|
+
|
|
245
|
+
if value is None:
|
|
246
|
+
return None
|
|
247
|
+
if type(value) is not GlobalWaveActionAllocationLaneResult:
|
|
248
|
+
raise TypeError("global allocation must be an exact lane result or None")
|
|
249
|
+
value.__post_init__()
|
|
250
|
+
record = thaw_json(value.audit)
|
|
251
|
+
if type(record) is not dict: # pragma: no cover - frozen root is closed.
|
|
252
|
+
raise AssertionError("global allocation audit did not thaw to an object")
|
|
253
|
+
return record
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def _forecast_call_id(request: PortfolioSelectionRequest) -> LLMCallId:
|
|
257
|
+
digest = hashlib.sha256(
|
|
258
|
+
_FORECAST_CALL_DOMAIN + bytes.fromhex(request.request_sha256)
|
|
259
|
+
).hexdigest()
|
|
260
|
+
return LLMCallId(f"call_outcome_forecast_{digest[:40]}")
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
def _resolve_model_authority_health(
|
|
264
|
+
*,
|
|
265
|
+
request_forecasts: ResolvedActionForecastBatch,
|
|
266
|
+
health: ResolvedActionForecastHealthAssessment,
|
|
267
|
+
exact_projections: ExactActionMetricProjectionBatch | None,
|
|
268
|
+
) -> tuple[bool, dict[str, object]]:
|
|
269
|
+
"""Apply collapse gates only where the model retains metric authority.
|
|
270
|
+
|
|
271
|
+
A complete exact projection removes the language model's decision
|
|
272
|
+
authority for one metric. Collapsed raw values for that metric remain in
|
|
273
|
+
the audit but cannot veto the wave. A partial projection grants no such
|
|
274
|
+
exemption.
|
|
275
|
+
"""
|
|
276
|
+
|
|
277
|
+
if type(request_forecasts) is not ResolvedActionForecastBatch:
|
|
278
|
+
raise TypeError("request_forecasts must be an exact resolved batch")
|
|
279
|
+
request_forecasts.__post_init__()
|
|
280
|
+
if type(health) is not ResolvedActionForecastHealthAssessment:
|
|
281
|
+
raise TypeError("health must be an exact resolved assessment")
|
|
282
|
+
health.__post_init__()
|
|
283
|
+
option_ids = {value.option_id for value in request_forecasts.forecasts}
|
|
284
|
+
projected_by_metric: dict[str, set[str]] = {}
|
|
285
|
+
if exact_projections is not None:
|
|
286
|
+
if type(exact_projections) is not ExactActionMetricProjectionBatch:
|
|
287
|
+
raise TypeError("exact_projections must be an exact batch or None")
|
|
288
|
+
exact_projections.__post_init__()
|
|
289
|
+
for value in exact_projections.projections:
|
|
290
|
+
projected_by_metric.setdefault(value.metric_id, set()).add(value.option_id)
|
|
291
|
+
fully_projected = tuple(
|
|
292
|
+
sorted(
|
|
293
|
+
metric_id
|
|
294
|
+
for metric_id, projected_options in projected_by_metric.items()
|
|
295
|
+
if projected_options == option_ids
|
|
296
|
+
)
|
|
297
|
+
)
|
|
298
|
+
assessment_by_metric = {
|
|
299
|
+
value.metric_id: value for value in health.metric_assessments
|
|
300
|
+
}
|
|
301
|
+
authoritative = tuple(sorted(set(assessment_by_metric).difference(fully_projected)))
|
|
302
|
+
unresolved_failed = tuple(
|
|
303
|
+
metric_id
|
|
304
|
+
for metric_id in authoritative
|
|
305
|
+
if not assessment_by_metric[metric_id].passes
|
|
306
|
+
)
|
|
307
|
+
signatures: set[tuple[object, ...]] = set()
|
|
308
|
+
if authoritative:
|
|
309
|
+
for forecast in request_forecasts.forecasts:
|
|
310
|
+
metrics = {value.metric_id: value for value in forecast.metric_forecasts}
|
|
311
|
+
signatures.add(
|
|
312
|
+
(
|
|
313
|
+
forecast.probability_valid.hex(),
|
|
314
|
+
*(
|
|
315
|
+
(
|
|
316
|
+
metrics[metric_id].p10_delta.hex(),
|
|
317
|
+
metrics[metric_id].p50_delta.hex(),
|
|
318
|
+
metrics[metric_id].p90_delta.hex(),
|
|
319
|
+
metrics[metric_id].confidence.hex(),
|
|
320
|
+
)
|
|
321
|
+
for metric_id in authoritative
|
|
322
|
+
),
|
|
323
|
+
)
|
|
324
|
+
)
|
|
325
|
+
threshold_applied = (
|
|
326
|
+
len(request_forecasts.forecasts) >= health.health_policy.minimum_rows
|
|
327
|
+
)
|
|
328
|
+
signature_passes = (
|
|
329
|
+
not authoritative
|
|
330
|
+
or not threshold_applied
|
|
331
|
+
or len(signatures) >= health.health_policy.minimum_distinct_signatures
|
|
332
|
+
)
|
|
333
|
+
passes = signature_passes and not unresolved_failed
|
|
334
|
+
return passes, {
|
|
335
|
+
"schema_version": 1,
|
|
336
|
+
"raw_health_passes": health.passes,
|
|
337
|
+
"fully_projected_metric_ids": list(fully_projected),
|
|
338
|
+
"model_authoritative_metric_ids": list(authoritative),
|
|
339
|
+
"unresolved_failed_metric_ids": list(unresolved_failed),
|
|
340
|
+
"model_authoritative_distinct_row_signature_count": len(signatures),
|
|
341
|
+
"threshold_applied": threshold_applied,
|
|
342
|
+
"signature_gate_passes": signature_passes,
|
|
343
|
+
"passes": passes,
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def _evidence_mode(request: PortfolioSelectionRequest) -> ActionForecastEvidenceMode:
|
|
348
|
+
if (
|
|
349
|
+
request.source_registry is not None
|
|
350
|
+
and request.experimental_view_receipt is not None
|
|
351
|
+
and all(card.source_binding is not None for card in request.cards)
|
|
352
|
+
and any(card.finite_action_evidence for card in request.cards)
|
|
353
|
+
):
|
|
354
|
+
return ActionForecastEvidenceMode.GROUNDED
|
|
355
|
+
return ActionForecastEvidenceMode.CATALOG_ONLY
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def _telemetry_record(value: AgenticCallTelemetry) -> dict[str, object]:
|
|
359
|
+
value.__post_init__()
|
|
360
|
+
return {
|
|
361
|
+
"requested_model": value.requested_model,
|
|
362
|
+
"resolved_model": value.resolved_model,
|
|
363
|
+
"resolved_provider": value.resolved_provider,
|
|
364
|
+
"provider_response_id": value.provider_response_id,
|
|
365
|
+
"finish_reason": value.finish_reason,
|
|
366
|
+
"input_tokens": value.input_tokens,
|
|
367
|
+
"output_tokens": value.output_tokens,
|
|
368
|
+
"reasoning_tokens": value.reasoning_tokens,
|
|
369
|
+
"cache_read_tokens": value.cache_read_tokens,
|
|
370
|
+
"cache_write_tokens": value.cache_write_tokens,
|
|
371
|
+
"cost_usd": None if value.cost_usd is None else str(value.cost_usd),
|
|
372
|
+
"latency_ns": value.latency_ns,
|
|
373
|
+
"attempt_count": value.attempt_count,
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def _aggregate_telemetry(
|
|
378
|
+
values: tuple[AgenticCallTelemetry, ...],
|
|
379
|
+
*,
|
|
380
|
+
wall_latency_ns: int,
|
|
381
|
+
) -> AgenticCallTelemetry:
|
|
382
|
+
if not values:
|
|
383
|
+
raise ValueError("partitioned portfolio selection requires call telemetry")
|
|
384
|
+
for value in values:
|
|
385
|
+
value.__post_init__()
|
|
386
|
+
requested_models = {value.requested_model for value in values}
|
|
387
|
+
resolved_models = {value.resolved_model for value in values}
|
|
388
|
+
resolved_providers = {value.resolved_provider for value in values}
|
|
389
|
+
if (
|
|
390
|
+
len(requested_models) != 1
|
|
391
|
+
or len(resolved_models) != 1
|
|
392
|
+
or len(resolved_providers) != 1
|
|
393
|
+
):
|
|
394
|
+
raise ValueError("physical forecast blocks resolved to heterogeneous models")
|
|
395
|
+
costs = tuple(value.cost_usd for value in values)
|
|
396
|
+
cost: Decimal | None
|
|
397
|
+
if any(value is None for value in costs):
|
|
398
|
+
cost = None
|
|
399
|
+
else:
|
|
400
|
+
cost = sum((value for value in costs if value is not None), Decimal(0))
|
|
401
|
+
finish_reasons = {value.finish_reason for value in values}
|
|
402
|
+
return AgenticCallTelemetry(
|
|
403
|
+
requested_model=next(iter(requested_models)),
|
|
404
|
+
resolved_model=next(iter(resolved_models)),
|
|
405
|
+
resolved_provider=next(iter(resolved_providers)),
|
|
406
|
+
provider_response_id=None,
|
|
407
|
+
finish_reason=(
|
|
408
|
+
next(iter(finish_reasons)) if len(finish_reasons) == 1 else None
|
|
409
|
+
),
|
|
410
|
+
input_tokens=sum(value.input_tokens for value in values),
|
|
411
|
+
output_tokens=sum(value.output_tokens for value in values),
|
|
412
|
+
reasoning_tokens=sum(value.reasoning_tokens for value in values),
|
|
413
|
+
cache_read_tokens=sum(value.cache_read_tokens for value in values),
|
|
414
|
+
cache_write_tokens=sum(value.cache_write_tokens for value in values),
|
|
415
|
+
cost_usd=cost,
|
|
416
|
+
latency_ns=wall_latency_ns,
|
|
417
|
+
# Physical block count is recorded separately. ``attempt_count`` keeps
|
|
418
|
+
# its established retry meaning for the logical receipt.
|
|
419
|
+
attempt_count=max(value.attempt_count for value in values),
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
def _direction(metric: object) -> MetricEffectDirection:
|
|
424
|
+
p10 = getattr(metric, "p10_delta")
|
|
425
|
+
p50 = getattr(metric, "p50_delta")
|
|
426
|
+
p90 = getattr(metric, "p90_delta")
|
|
427
|
+
if any(
|
|
428
|
+
type(value) is not float or not math.isfinite(value)
|
|
429
|
+
for value in (p10, p50, p90)
|
|
430
|
+
):
|
|
431
|
+
raise TypeError("resolved forecast deltas must be finite exact floats")
|
|
432
|
+
if p10 == p50 == p90 == 0.0:
|
|
433
|
+
return MetricEffectDirection.UNCHANGED
|
|
434
|
+
if p90 < 0.0:
|
|
435
|
+
return MetricEffectDirection.DECREASE
|
|
436
|
+
if p10 > 0.0:
|
|
437
|
+
return MetricEffectDirection.INCREASE
|
|
438
|
+
return MetricEffectDirection.UNKNOWN
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def _selected_card_keys(forecast: ResolvedActionForecast) -> tuple[str, ...]:
|
|
442
|
+
return tuple(
|
|
443
|
+
sorted(
|
|
444
|
+
{
|
|
445
|
+
citation.card_key
|
|
446
|
+
for metric in forecast.metric_forecasts
|
|
447
|
+
for citation in metric.citations
|
|
448
|
+
}
|
|
449
|
+
)
|
|
450
|
+
)
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def _preference_scores(
|
|
454
|
+
plan: TargetConditionedActionForecastPlan,
|
|
455
|
+
forecasts: ResolvedActionForecastBatch,
|
|
456
|
+
) -> dict[str, float]:
|
|
457
|
+
"""Cheap deterministic ordering for memory witnesses and proposal padding."""
|
|
458
|
+
|
|
459
|
+
scores: dict[str, float] = {}
|
|
460
|
+
for value in plan.assess(forecasts):
|
|
461
|
+
p50 = value.scenarios[1]
|
|
462
|
+
score = value.probability_valid * p50.shortfall_reduction_l1
|
|
463
|
+
if not math.isfinite(score): # pragma: no cover - typed inputs close this.
|
|
464
|
+
raise RuntimeError("target preference score became non-finite")
|
|
465
|
+
scores[value.option_id] = float(score)
|
|
466
|
+
return scores
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
def _memory_assignment_candidates(
|
|
470
|
+
request: PortfolioSelectionRequest,
|
|
471
|
+
*,
|
|
472
|
+
preference: dict[str, float],
|
|
473
|
+
max_options_per_card: int,
|
|
474
|
+
max_assignments: int,
|
|
475
|
+
) -> tuple[dict[str, str], ...]:
|
|
476
|
+
"""Enumerate bounded card-to-distinct-option matchings, best first."""
|
|
477
|
+
|
|
478
|
+
dose = request.memory_dose_contract
|
|
479
|
+
if dose is None:
|
|
480
|
+
return ({},)
|
|
481
|
+
dose.__post_init__()
|
|
482
|
+
if dose.maximum_cards_per_member < 1:
|
|
483
|
+
raise ValueError("memory dose cannot attribute any selected member")
|
|
484
|
+
supports = dose.card_supports
|
|
485
|
+
evaluated_lower, evaluated_upper = dose.evaluated_supported_member_bounds
|
|
486
|
+
proposed_lower, proposed_upper = dose.proposed_supported_member_bounds
|
|
487
|
+
if dose.require_every_assigned_card:
|
|
488
|
+
subset_sizes = (len(supports),)
|
|
489
|
+
else:
|
|
490
|
+
low = max(evaluated_lower, proposed_lower)
|
|
491
|
+
high = min(evaluated_upper, proposed_upper, len(supports))
|
|
492
|
+
subset_sizes = tuple(range(low, high + 1))
|
|
493
|
+
results: list[dict[str, str]] = []
|
|
494
|
+
for size in subset_sizes:
|
|
495
|
+
if (
|
|
496
|
+
not evaluated_lower <= size <= evaluated_upper
|
|
497
|
+
or not proposed_lower <= size <= proposed_upper
|
|
498
|
+
or request.portfolio_size - size
|
|
499
|
+
< dose.minimum_unattributed_evaluated_members
|
|
500
|
+
):
|
|
501
|
+
continue
|
|
502
|
+
for selected_supports in itertools.combinations(supports, size):
|
|
503
|
+
option_lists = tuple(
|
|
504
|
+
tuple(
|
|
505
|
+
option_id
|
|
506
|
+
for option_id, _identity in sorted(
|
|
507
|
+
support.compatible_options,
|
|
508
|
+
key=lambda item: (
|
|
509
|
+
-preference.get(item[0], float("-inf")),
|
|
510
|
+
item[1],
|
|
511
|
+
item[0],
|
|
512
|
+
),
|
|
513
|
+
)[:max_options_per_card]
|
|
514
|
+
)
|
|
515
|
+
for support in selected_supports
|
|
516
|
+
)
|
|
517
|
+
for option_ids in itertools.product(*option_lists):
|
|
518
|
+
if len(set(option_ids)) != len(option_ids):
|
|
519
|
+
continue
|
|
520
|
+
results.append(
|
|
521
|
+
{
|
|
522
|
+
option_id: support.card_key
|
|
523
|
+
for support, option_id in zip(
|
|
524
|
+
selected_supports,
|
|
525
|
+
option_ids,
|
|
526
|
+
strict=True,
|
|
527
|
+
)
|
|
528
|
+
}
|
|
529
|
+
)
|
|
530
|
+
if len(results) >= max_assignments:
|
|
531
|
+
return tuple(results)
|
|
532
|
+
if not results:
|
|
533
|
+
raise ValueError("bounded memory dose has no candidate attribution matching")
|
|
534
|
+
return tuple(results)
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
def _memory_assessments(
|
|
538
|
+
request: PortfolioSelectionRequest,
|
|
539
|
+
*,
|
|
540
|
+
allocation: ActionAllocationResult,
|
|
541
|
+
card_by_option: dict[str, str],
|
|
542
|
+
preference: dict[str, float],
|
|
543
|
+
) -> tuple[
|
|
544
|
+
dict[str, tuple[str, ...]],
|
|
545
|
+
PortfolioMemoryDoseAssessment | None,
|
|
546
|
+
PortfolioMemoryDoseAssessment | None,
|
|
547
|
+
]:
|
|
548
|
+
selected = allocation.decision.members
|
|
549
|
+
selected_support = {
|
|
550
|
+
value.option_id: (
|
|
551
|
+
()
|
|
552
|
+
if value.option_id not in card_by_option
|
|
553
|
+
else (card_by_option[value.option_id],)
|
|
554
|
+
)
|
|
555
|
+
for value in selected
|
|
556
|
+
}
|
|
557
|
+
dose = request.memory_dose_contract
|
|
558
|
+
if dose is None:
|
|
559
|
+
return selected_support, None, None
|
|
560
|
+
supported_count = sum(bool(value) for value in selected_support.values())
|
|
561
|
+
proposed_size = max(
|
|
562
|
+
request.portfolio_size,
|
|
563
|
+
supported_count + dose.minimum_unattributed_proposed_members,
|
|
564
|
+
)
|
|
565
|
+
contract = request.finite_variation_contract
|
|
566
|
+
if proposed_size > len(contract.options):
|
|
567
|
+
raise ValueError("memory-dose proposal witness exceeds the finite contract")
|
|
568
|
+
selected_ids = {value.option_id for value in selected}
|
|
569
|
+
extras = sorted(
|
|
570
|
+
(value for value in contract.options if value.option_id not in selected_ids),
|
|
571
|
+
key=lambda value: (
|
|
572
|
+
-preference.get(value.option_id, float("-inf")),
|
|
573
|
+
value.identity_sha256,
|
|
574
|
+
value.option_id,
|
|
575
|
+
),
|
|
576
|
+
)[: proposed_size - len(selected)]
|
|
577
|
+
identities = {value.option_id: value.identity_sha256 for value in contract.options}
|
|
578
|
+
proposal_ids = tuple(value.option_id for value in selected) + tuple(
|
|
579
|
+
value.option_id for value in extras
|
|
580
|
+
)
|
|
581
|
+
proposed_members = tuple(
|
|
582
|
+
PortfolioMemoryDoseMember(
|
|
583
|
+
rank=rank,
|
|
584
|
+
option_id=option_id,
|
|
585
|
+
option_identity_sha256=identities[option_id],
|
|
586
|
+
supporting_card_keys=selected_support.get(option_id, ()),
|
|
587
|
+
)
|
|
588
|
+
for rank, option_id in enumerate(proposal_ids, start=1)
|
|
589
|
+
)
|
|
590
|
+
proposed = assess_proposed_portfolio_memory_dose(dose, proposed_members)
|
|
591
|
+
if not proposed.passed:
|
|
592
|
+
raise ValueError("constructed all-action proposal violates memory dose")
|
|
593
|
+
evaluated_members = tuple(
|
|
594
|
+
PortfolioMemoryDoseMember(
|
|
595
|
+
rank=rank,
|
|
596
|
+
option_id=value.option_id,
|
|
597
|
+
option_identity_sha256=value.option_identity_sha256,
|
|
598
|
+
supporting_card_keys=selected_support[value.option_id],
|
|
599
|
+
)
|
|
600
|
+
for rank, value in enumerate(selected, start=1)
|
|
601
|
+
)
|
|
602
|
+
evaluated = assess_evaluated_portfolio_memory_dose(
|
|
603
|
+
dose,
|
|
604
|
+
evaluated_members,
|
|
605
|
+
proposal_assessment=proposed,
|
|
606
|
+
)
|
|
607
|
+
if not evaluated.passed:
|
|
608
|
+
raise ValueError("allocated all-action portfolio violates memory dose")
|
|
609
|
+
return selected_support, proposed, evaluated
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
def _bound_policy_definition(
|
|
613
|
+
*,
|
|
614
|
+
plan: TargetConditionedActionForecastPlan,
|
|
615
|
+
partition_policy: ActionForecastPartitionPolicyBinding,
|
|
616
|
+
consequence_calibration: ActionConsequenceCalibrationResult | None,
|
|
617
|
+
metric_projection: ActionMetricProjectionOverlayResult | None,
|
|
618
|
+
risk_aversion: float,
|
|
619
|
+
diversity_weight: float,
|
|
620
|
+
beam_width: int,
|
|
621
|
+
global_allocation_receipt_sha256: str | None,
|
|
622
|
+
contextual_allocation_contract_sha256: str | None,
|
|
623
|
+
common_candidate_pool_decision_sha256: str | None,
|
|
624
|
+
) -> str:
|
|
625
|
+
return hashlib.sha256(
|
|
626
|
+
_BOUND_POLICY_DOMAIN
|
|
627
|
+
+ _canonical_json(
|
|
628
|
+
{
|
|
629
|
+
"base_definition_sha256": (
|
|
630
|
+
OUTCOME_CONDITIONED_PORTFOLIO_POLICY_DEFINITION_SHA256
|
|
631
|
+
),
|
|
632
|
+
"optimization_semantics_definition_sha256": (
|
|
633
|
+
plan.request.optimization_semantics.definition_sha256
|
|
634
|
+
),
|
|
635
|
+
"action_semantics_definition_sha256": (
|
|
636
|
+
plan.request.action_semantics.definition_sha256
|
|
637
|
+
),
|
|
638
|
+
"partition_policy_sha256": partition_policy.binding_sha256,
|
|
639
|
+
"consequence_calibration_receipt_sha256": (
|
|
640
|
+
None
|
|
641
|
+
if consequence_calibration is None
|
|
642
|
+
else consequence_calibration.receipt_sha256
|
|
643
|
+
),
|
|
644
|
+
"metric_projection_receipt_sha256": (
|
|
645
|
+
None
|
|
646
|
+
if metric_projection is None
|
|
647
|
+
else metric_projection.projection_receipt_sha256
|
|
648
|
+
),
|
|
649
|
+
"risk_aversion_hex": risk_aversion.hex(),
|
|
650
|
+
"diversity_weight_hex": diversity_weight.hex(),
|
|
651
|
+
"beam_width": beam_width,
|
|
652
|
+
"global_allocation_receipt_sha256": (global_allocation_receipt_sha256),
|
|
653
|
+
"contextual_allocation_contract_sha256": (
|
|
654
|
+
contextual_allocation_contract_sha256
|
|
655
|
+
),
|
|
656
|
+
"common_candidate_pool_decision_sha256": (
|
|
657
|
+
common_candidate_pool_decision_sha256
|
|
658
|
+
),
|
|
659
|
+
}
|
|
660
|
+
)
|
|
661
|
+
).hexdigest()
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
def _confidence_bin(value: float) -> ForecastConfidenceBin:
|
|
665
|
+
if type(value) is not float or not math.isfinite(value):
|
|
666
|
+
raise TypeError("forecast confidence must be a finite exact float")
|
|
667
|
+
if value >= 0.75:
|
|
668
|
+
return ForecastConfidenceBin.HIGH
|
|
669
|
+
if value >= 0.4:
|
|
670
|
+
return ForecastConfidenceBin.MEDIUM
|
|
671
|
+
if value > 0.0:
|
|
672
|
+
return ForecastConfidenceBin.LOW
|
|
673
|
+
return ForecastConfidenceBin.UNKNOWN
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
def outcome_conditioned_selected_predictions(
|
|
677
|
+
*,
|
|
678
|
+
scope: ForecastCalibrationScope,
|
|
679
|
+
wave: object,
|
|
680
|
+
result: object,
|
|
681
|
+
) -> tuple[ForecastPredictionReceipt, ...]:
|
|
682
|
+
"""Decode selected categorical forecasts without integration-specific state."""
|
|
683
|
+
|
|
684
|
+
from agent_evolve.application.portfolio_evolution import (
|
|
685
|
+
PortfolioVariationWaveRequest,
|
|
686
|
+
PortfolioVariationWaveResult,
|
|
687
|
+
)
|
|
688
|
+
|
|
689
|
+
if type(scope) is not ForecastCalibrationScope:
|
|
690
|
+
raise TypeError("scope must be an exact ForecastCalibrationScope")
|
|
691
|
+
scope.revalidate()
|
|
692
|
+
if type(wave) is not PortfolioVariationWaveRequest:
|
|
693
|
+
raise TypeError("wave must be an exact PortfolioVariationWaveRequest")
|
|
694
|
+
wave.__post_init__()
|
|
695
|
+
if type(result) is not PortfolioVariationWaveResult:
|
|
696
|
+
raise TypeError("result must be an exact PortfolioVariationWaveResult")
|
|
697
|
+
result.__post_init__()
|
|
698
|
+
if (
|
|
699
|
+
result.receipt.request_sha256 != wave.selection_request.request_sha256
|
|
700
|
+
or result.selection_decision.decision_sha256 != result.receipt.decision_sha256
|
|
701
|
+
):
|
|
702
|
+
raise ValueError("portfolio result differs from its selection wave")
|
|
703
|
+
audit = result.supplemental_selection_audit
|
|
704
|
+
if (
|
|
705
|
+
audit is None
|
|
706
|
+
or audit.audit_kind != "outcome_conditioned_expert_portfolio"
|
|
707
|
+
or audit.request_sha256 != wave.selection_request.request_sha256
|
|
708
|
+
or audit.decision_sha256 != result.selection_decision.decision_sha256
|
|
709
|
+
):
|
|
710
|
+
raise ValueError("portfolio result omits its outcome-conditioned audit")
|
|
711
|
+
payload = thaw_json(audit.payload)
|
|
712
|
+
if type(payload) is not dict: # pragma: no cover - frozen root is closed.
|
|
713
|
+
raise AssertionError("outcome-conditioned audit did not thaw to an object")
|
|
714
|
+
aliases_raw = payload.get("metric_aliases")
|
|
715
|
+
selected_raw = payload.get("selected_forecasts")
|
|
716
|
+
if type(aliases_raw) is not list or type(selected_raw) is not list:
|
|
717
|
+
raise TypeError("outcome-conditioned audit omits forecast decoding data")
|
|
718
|
+
alias_by_target: dict[str, str] = {}
|
|
719
|
+
for row in aliases_raw:
|
|
720
|
+
if type(row) is not dict:
|
|
721
|
+
raise TypeError("metric alias audit rows must be objects")
|
|
722
|
+
values = row
|
|
723
|
+
target_id = values.get("target_metric_id")
|
|
724
|
+
forecast_id = values.get("forecast_metric_id")
|
|
725
|
+
if type(target_id) is not str or type(forecast_id) is not str:
|
|
726
|
+
raise TypeError("metric alias audit row is malformed")
|
|
727
|
+
alias_by_target[target_id] = forecast_id
|
|
728
|
+
selected_confidence: dict[tuple[str, str], float] = {}
|
|
729
|
+
for row in selected_raw:
|
|
730
|
+
if type(row) is not dict:
|
|
731
|
+
raise TypeError("selected forecast audit rows must be objects")
|
|
732
|
+
values = row
|
|
733
|
+
option_id = values.get("option_id")
|
|
734
|
+
metrics = values.get("metric_forecasts")
|
|
735
|
+
if type(option_id) is not str or type(metrics) is not list:
|
|
736
|
+
raise TypeError("selected forecast audit row is malformed")
|
|
737
|
+
for metric in metrics:
|
|
738
|
+
if type(metric) is not dict:
|
|
739
|
+
raise TypeError("selected metric audit row must be an object")
|
|
740
|
+
metric_values = metric
|
|
741
|
+
metric_id = metric_values.get("metric_id")
|
|
742
|
+
confidence_hex = metric_values.get("confidence_hex")
|
|
743
|
+
if type(metric_id) is not str or type(confidence_hex) is not str:
|
|
744
|
+
raise TypeError("selected metric audit row is malformed")
|
|
745
|
+
confidence = float.fromhex(confidence_hex)
|
|
746
|
+
if not math.isfinite(confidence):
|
|
747
|
+
raise ValueError("selected metric confidence is non-finite")
|
|
748
|
+
selected_confidence[(option_id, metric_id)] = confidence
|
|
749
|
+
predictions: list[ForecastPredictionReceipt] = []
|
|
750
|
+
for member in result.selection_decision.members:
|
|
751
|
+
effects = {value.metric_id: value for value in member.effect_predictions}
|
|
752
|
+
for target_metric_id in wave.selection_request.required_metric_ids:
|
|
753
|
+
effect = effects[target_metric_id]
|
|
754
|
+
forecast_metric_id = alias_by_target[target_metric_id]
|
|
755
|
+
confidence = selected_confidence[(member.option_id, forecast_metric_id)]
|
|
756
|
+
predictions.append(
|
|
757
|
+
ForecastPredictionReceipt(
|
|
758
|
+
scope=scope,
|
|
759
|
+
wave_index=wave.generation,
|
|
760
|
+
selector_decision_sha256=(
|
|
761
|
+
result.selection_decision.decision_sha256
|
|
762
|
+
),
|
|
763
|
+
parent_candidate_identity_sha256=(
|
|
764
|
+
wave.parent.occurrence.configuration_hash
|
|
765
|
+
),
|
|
766
|
+
option_id=member.option_id,
|
|
767
|
+
option_identity_sha256=member.option_identity_sha256,
|
|
768
|
+
family=member.family,
|
|
769
|
+
metric_id=target_metric_id,
|
|
770
|
+
asserted_direction=effect.direction,
|
|
771
|
+
confidence=_confidence_bin(confidence),
|
|
772
|
+
)
|
|
773
|
+
)
|
|
774
|
+
return tuple(predictions)
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
def outcome_conditioned_selected_source_ids(
|
|
778
|
+
*,
|
|
779
|
+
wave: object,
|
|
780
|
+
result: object,
|
|
781
|
+
) -> tuple[str, ...]:
|
|
782
|
+
"""Decode evaluated proposal-source arms from sealed finite metadata."""
|
|
783
|
+
|
|
784
|
+
from agent_evolve.application.portfolio_evolution import (
|
|
785
|
+
PortfolioVariationWaveRequest,
|
|
786
|
+
PortfolioVariationWaveResult,
|
|
787
|
+
)
|
|
788
|
+
|
|
789
|
+
if type(wave) is not PortfolioVariationWaveRequest:
|
|
790
|
+
raise TypeError("wave must be an exact PortfolioVariationWaveRequest")
|
|
791
|
+
wave.__post_init__()
|
|
792
|
+
if type(result) is not PortfolioVariationWaveResult:
|
|
793
|
+
raise TypeError("result must be an exact PortfolioVariationWaveResult")
|
|
794
|
+
result.__post_init__()
|
|
795
|
+
if (
|
|
796
|
+
result.receipt.request_sha256 != wave.selection_request.request_sha256
|
|
797
|
+
or result.selection_decision.decision_sha256 != result.receipt.decision_sha256
|
|
798
|
+
):
|
|
799
|
+
raise ValueError("portfolio result differs from its selection wave")
|
|
800
|
+
return selected_variation_source_ids(
|
|
801
|
+
finite_contract=wave.selection_request.finite_variation_contract,
|
|
802
|
+
selected_option_ids=tuple(
|
|
803
|
+
value.option_id for value in result.selection_decision.members
|
|
804
|
+
),
|
|
805
|
+
)
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
def outcome_conditioned_contextual_allocation_realization(
|
|
809
|
+
*,
|
|
810
|
+
allocation: ContextualPortfolioAllocationContract | None,
|
|
811
|
+
wave: object,
|
|
812
|
+
result: object,
|
|
813
|
+
) -> ContextualPortfolioAllocationRealization | None:
|
|
814
|
+
"""Decode exact requested-to-realized source/operator exposure evidence."""
|
|
815
|
+
|
|
816
|
+
from agent_evolve.application.portfolio_evolution import (
|
|
817
|
+
PortfolioVariationWaveRequest,
|
|
818
|
+
PortfolioVariationWaveResult,
|
|
819
|
+
)
|
|
820
|
+
|
|
821
|
+
if type(wave) is not PortfolioVariationWaveRequest:
|
|
822
|
+
raise TypeError("wave must be an exact PortfolioVariationWaveRequest")
|
|
823
|
+
wave.__post_init__()
|
|
824
|
+
if type(result) is not PortfolioVariationWaveResult:
|
|
825
|
+
raise TypeError("result must be an exact PortfolioVariationWaveResult")
|
|
826
|
+
result.__post_init__()
|
|
827
|
+
if (
|
|
828
|
+
result.receipt.request_sha256 != wave.selection_request.request_sha256
|
|
829
|
+
or result.selection_decision.decision_sha256 != result.receipt.decision_sha256
|
|
830
|
+
):
|
|
831
|
+
raise ValueError("portfolio result differs from its selection wave")
|
|
832
|
+
return contextual_allocation_realization(
|
|
833
|
+
finite_contract=wave.selection_request.finite_variation_contract,
|
|
834
|
+
allocation=allocation,
|
|
835
|
+
selected_option_ids=tuple(
|
|
836
|
+
value.option_id for value in result.selection_decision.members
|
|
837
|
+
),
|
|
838
|
+
)
|
|
839
|
+
|
|
840
|
+
|
|
841
|
+
@dataclass(slots=True)
|
|
842
|
+
class OutcomeConditionedPortfolioSelectionPolicy:
|
|
843
|
+
"""Portable all-action selector implementing the campaign selection port."""
|
|
844
|
+
|
|
845
|
+
forecaster: PartitionedActionForecastPolicy
|
|
846
|
+
optimization_semantics: OptimizationSemantics
|
|
847
|
+
partition_policy: ActionForecastPartitionPolicyBinding
|
|
848
|
+
action_semantics_factory: ActionSemanticsFactory | None = None
|
|
849
|
+
consequence_calibrator: ActionConsequenceCalibrationPolicy | None = None
|
|
850
|
+
metric_projector: ActionMetricProjector | None = None
|
|
851
|
+
wave_action_coordinator: GlobalWaveActionAllocationCoordinator | None = None
|
|
852
|
+
contextual_allocation_provider: ContextualAllocationProvider | None = None
|
|
853
|
+
candidate_pool_provider: CandidatePoolProvider | None = None
|
|
854
|
+
risk_aversion: float = 0.5
|
|
855
|
+
diversity_weight: float = 0.05
|
|
856
|
+
beam_width: int = 256
|
|
857
|
+
require_healthy_forecast: bool = True
|
|
858
|
+
max_memory_options_per_card: int = 16
|
|
859
|
+
max_memory_assignment_trials: int = 128
|
|
860
|
+
|
|
861
|
+
def __post_init__(self) -> None:
|
|
862
|
+
if not callable(getattr(self.forecaster, "forecast_partitioned", None)):
|
|
863
|
+
raise TypeError("forecaster must satisfy PartitionedActionForecastPolicy")
|
|
864
|
+
if type(self.optimization_semantics) is not OptimizationSemantics:
|
|
865
|
+
raise TypeError("optimization_semantics must be exact")
|
|
866
|
+
self.optimization_semantics.__post_init__()
|
|
867
|
+
if type(self.partition_policy) is not ActionForecastPartitionPolicyBinding:
|
|
868
|
+
raise TypeError("partition_policy must be exact")
|
|
869
|
+
self.partition_policy.__post_init__()
|
|
870
|
+
if self.action_semantics_factory is not None and not callable(
|
|
871
|
+
self.action_semantics_factory
|
|
872
|
+
):
|
|
873
|
+
raise TypeError("action_semantics_factory must be callable or None")
|
|
874
|
+
if self.consequence_calibrator is not None and not isinstance(
|
|
875
|
+
self.consequence_calibrator,
|
|
876
|
+
ActionConsequenceCalibrationPolicy,
|
|
877
|
+
):
|
|
878
|
+
raise TypeError(
|
|
879
|
+
"consequence_calibrator must satisfy the calibration port or be None"
|
|
880
|
+
)
|
|
881
|
+
if self.metric_projector is not None and not callable(
|
|
882
|
+
getattr(self.metric_projector, "project", None)
|
|
883
|
+
):
|
|
884
|
+
raise TypeError("metric_projector must expose project or be None")
|
|
885
|
+
if self.wave_action_coordinator is not None and not isinstance(
|
|
886
|
+
self.wave_action_coordinator,
|
|
887
|
+
GlobalWaveActionAllocationCoordinator,
|
|
888
|
+
):
|
|
889
|
+
raise TypeError(
|
|
890
|
+
"wave_action_coordinator must satisfy the global allocation port"
|
|
891
|
+
)
|
|
892
|
+
if self.contextual_allocation_provider is not None and not callable(
|
|
893
|
+
self.contextual_allocation_provider
|
|
894
|
+
):
|
|
895
|
+
raise TypeError("contextual_allocation_provider must be callable or None")
|
|
896
|
+
if self.candidate_pool_provider is not None and not callable(
|
|
897
|
+
self.candidate_pool_provider
|
|
898
|
+
):
|
|
899
|
+
raise TypeError("candidate_pool_provider must be callable or None")
|
|
900
|
+
for name in ("risk_aversion", "diversity_weight"):
|
|
901
|
+
value = getattr(self, name)
|
|
902
|
+
if type(value) is not float or not math.isfinite(value) or value < 0.0:
|
|
903
|
+
raise ValueError(f"{name} must be a finite non-negative float")
|
|
904
|
+
for name in (
|
|
905
|
+
"beam_width",
|
|
906
|
+
"max_memory_options_per_card",
|
|
907
|
+
"max_memory_assignment_trials",
|
|
908
|
+
):
|
|
909
|
+
value = getattr(self, name)
|
|
910
|
+
if type(value) is not int or value <= 0:
|
|
911
|
+
raise ValueError(f"{name} must be a positive exact integer")
|
|
912
|
+
if type(self.require_healthy_forecast) is not bool:
|
|
913
|
+
raise TypeError("require_healthy_forecast must be exact bool")
|
|
914
|
+
|
|
915
|
+
def render(self, request: PortfolioSelectionRequest) -> str:
|
|
916
|
+
"""Render the logical request audited above its physical block calls."""
|
|
917
|
+
|
|
918
|
+
self.__post_init__()
|
|
919
|
+
if type(request) is not PortfolioSelectionRequest:
|
|
920
|
+
raise TypeError("request must be an exact PortfolioSelectionRequest")
|
|
921
|
+
request.__post_init__()
|
|
922
|
+
return (
|
|
923
|
+
"OUTCOME-CONDITIONED ALL-ACTION PORTFOLIO REQUEST\n"
|
|
924
|
+
"The model forecasts every sealed action in bounded physical blocks; "
|
|
925
|
+
"trusted code performs hard-feasible set allocation.\n"
|
|
926
|
+
+ json.dumps(
|
|
927
|
+
{
|
|
928
|
+
"selection_request": request.to_record(),
|
|
929
|
+
"partition_policy": self.partition_policy.to_record(),
|
|
930
|
+
"base_policy_definition_sha256": (
|
|
931
|
+
OUTCOME_CONDITIONED_PORTFOLIO_POLICY_DEFINITION_SHA256
|
|
932
|
+
),
|
|
933
|
+
},
|
|
934
|
+
allow_nan=False,
|
|
935
|
+
ensure_ascii=True,
|
|
936
|
+
separators=(",", ":"),
|
|
937
|
+
sort_keys=True,
|
|
938
|
+
)
|
|
939
|
+
)
|
|
940
|
+
|
|
941
|
+
async def select(
|
|
942
|
+
self,
|
|
943
|
+
request: PortfolioSelectionRequest,
|
|
944
|
+
) -> PortfolioSelectionResult:
|
|
945
|
+
self.__post_init__()
|
|
946
|
+
if type(request) is not PortfolioSelectionRequest:
|
|
947
|
+
raise TypeError("request must be an exact PortfolioSelectionRequest")
|
|
948
|
+
request.__post_init__()
|
|
949
|
+
phase = resolve_campaign_search_phase_context(request.context)
|
|
950
|
+
contextual_allocation = (
|
|
951
|
+
None
|
|
952
|
+
if self.contextual_allocation_provider is None
|
|
953
|
+
else self.contextual_allocation_provider(request)
|
|
954
|
+
)
|
|
955
|
+
if contextual_allocation is not None:
|
|
956
|
+
if type(contextual_allocation) is not (
|
|
957
|
+
ContextualPortfolioAllocationContract
|
|
958
|
+
):
|
|
959
|
+
raise TypeError(
|
|
960
|
+
"contextual allocation provider returned a foreign contract"
|
|
961
|
+
)
|
|
962
|
+
contextual_allocation.__post_init__()
|
|
963
|
+
if (
|
|
964
|
+
contextual_allocation.campaign_generation != phase.campaign_generation
|
|
965
|
+
or contextual_allocation.evaluation_slots != request.portfolio_size
|
|
966
|
+
):
|
|
967
|
+
raise ValueError(
|
|
968
|
+
"contextual allocation differs from the selection wave"
|
|
969
|
+
)
|
|
970
|
+
candidate_pool = (
|
|
971
|
+
None
|
|
972
|
+
if self.candidate_pool_provider is None
|
|
973
|
+
else self.candidate_pool_provider(request)
|
|
974
|
+
)
|
|
975
|
+
forecast_contract, forecast_universe_projection = (
|
|
976
|
+
_forecast_contract_projection(request, candidate_pool)
|
|
977
|
+
)
|
|
978
|
+
exact_arm_count_constraints = contextual_action_arm_count_constraints(
|
|
979
|
+
finite_contract=forecast_contract,
|
|
980
|
+
allocation=contextual_allocation,
|
|
981
|
+
portfolio_size=request.portfolio_size,
|
|
982
|
+
)
|
|
983
|
+
action_semantics = (
|
|
984
|
+
None
|
|
985
|
+
if self.action_semantics_factory is None
|
|
986
|
+
else self.action_semantics_factory(forecast_contract)
|
|
987
|
+
)
|
|
988
|
+
plan = build_target_conditioned_action_forecast_plan(
|
|
989
|
+
selection_request=request,
|
|
990
|
+
optimization_semantics=self.optimization_semantics,
|
|
991
|
+
call_id=_forecast_call_id(request),
|
|
992
|
+
forecast_contract=forecast_contract,
|
|
993
|
+
action_semantics=action_semantics,
|
|
994
|
+
evidence_mode=_evidence_mode(request),
|
|
995
|
+
max_output_tokens=request.max_output_tokens,
|
|
996
|
+
temperature=request.temperature,
|
|
997
|
+
)
|
|
998
|
+
if (
|
|
999
|
+
contextual_allocation is not None
|
|
1000
|
+
and contextual_allocation.slice_id != plan.campaign_target.lane_id
|
|
1001
|
+
):
|
|
1002
|
+
raise ValueError("contextual allocation differs from the target lane")
|
|
1003
|
+
layout = build_action_forecast_partition_layout(
|
|
1004
|
+
plan.request,
|
|
1005
|
+
self.partition_policy,
|
|
1006
|
+
)
|
|
1007
|
+
started_ns = time.perf_counter_ns()
|
|
1008
|
+
partitioned = await self.forecaster.forecast_partitioned(
|
|
1009
|
+
plan.request,
|
|
1010
|
+
layout,
|
|
1011
|
+
)
|
|
1012
|
+
wall_latency_ns = time.perf_counter_ns() - started_ns
|
|
1013
|
+
physical_telemetry = tuple(
|
|
1014
|
+
value.telemetry
|
|
1015
|
+
for value in partitioned.block_results
|
|
1016
|
+
if value.telemetry is not None
|
|
1017
|
+
)
|
|
1018
|
+
telemetry = _aggregate_telemetry(
|
|
1019
|
+
physical_telemetry,
|
|
1020
|
+
wall_latency_ns=wall_latency_ns,
|
|
1021
|
+
)
|
|
1022
|
+
health = assess_resolved_action_forecast_health(
|
|
1023
|
+
plan.request,
|
|
1024
|
+
partitioned.forecasts,
|
|
1025
|
+
member_id="outcome_conditioned_selector",
|
|
1026
|
+
health_policy=lenient_action_forecast_health_policy(),
|
|
1027
|
+
)
|
|
1028
|
+
consequence_calibration = None
|
|
1029
|
+
metric_projection = None
|
|
1030
|
+
exact_projections = None
|
|
1031
|
+
decision_forecasts = partitioned.forecasts
|
|
1032
|
+
if self.consequence_calibrator is not None:
|
|
1033
|
+
consequence_calibration = self.consequence_calibrator.calibrate(
|
|
1034
|
+
request=plan.request,
|
|
1035
|
+
forecasts=partitioned.forecasts,
|
|
1036
|
+
cutoff_wave_index_exclusive=phase.campaign_generation,
|
|
1037
|
+
metric_aliases=plan.aliases,
|
|
1038
|
+
)
|
|
1039
|
+
if type(consequence_calibration) is not ActionConsequenceCalibrationResult:
|
|
1040
|
+
raise TypeError("consequence calibrator returned a foreign result type")
|
|
1041
|
+
decision_forecasts = consequence_calibration.forecasts
|
|
1042
|
+
if self.metric_projector is not None:
|
|
1043
|
+
exact_projections = self.metric_projector.project(plan.request)
|
|
1044
|
+
metric_projection = apply_exact_action_metric_projections(
|
|
1045
|
+
request=plan.request,
|
|
1046
|
+
forecasts=decision_forecasts,
|
|
1047
|
+
projections=exact_projections,
|
|
1048
|
+
)
|
|
1049
|
+
decision_forecasts = metric_projection.forecasts
|
|
1050
|
+
health_passes, health_resolution = _resolve_model_authority_health(
|
|
1051
|
+
request_forecasts=partitioned.forecasts,
|
|
1052
|
+
health=health,
|
|
1053
|
+
exact_projections=exact_projections,
|
|
1054
|
+
)
|
|
1055
|
+
if self.require_healthy_forecast and not health_passes:
|
|
1056
|
+
failed = health_resolution["unresolved_failed_metric_ids"]
|
|
1057
|
+
raise ValueError(
|
|
1058
|
+
"all-action forecast failed its model-authority health gate; "
|
|
1059
|
+
f"unresolved_metrics={failed}"
|
|
1060
|
+
)
|
|
1061
|
+
|
|
1062
|
+
utility_mode, target_kind = _identified_outcome_conditioned_acquisition(
|
|
1063
|
+
residual_cell_identified=plan.residual_cell is not None,
|
|
1064
|
+
terminal=phase.terminal,
|
|
1065
|
+
)
|
|
1066
|
+
preference = _preference_scores(plan, decision_forecasts)
|
|
1067
|
+
memory_candidates = _memory_assignment_candidates(
|
|
1068
|
+
request,
|
|
1069
|
+
preference=preference,
|
|
1070
|
+
max_options_per_card=self.max_memory_options_per_card,
|
|
1071
|
+
max_assignments=self.max_memory_assignment_trials,
|
|
1072
|
+
)
|
|
1073
|
+
global_allocation: GlobalWaveActionAllocationLaneResult | None = None
|
|
1074
|
+
role_slots: RoleSlots | None = None
|
|
1075
|
+
if self.wave_action_coordinator is not None:
|
|
1076
|
+
global_allocation = await self.wave_action_coordinator.allocate(
|
|
1077
|
+
GlobalWaveActionAllocationLane(
|
|
1078
|
+
generation=phase.campaign_generation,
|
|
1079
|
+
request=request,
|
|
1080
|
+
plan=plan,
|
|
1081
|
+
forecasts=decision_forecasts,
|
|
1082
|
+
utility_mode=utility_mode,
|
|
1083
|
+
target_kind=target_kind,
|
|
1084
|
+
memory_assignments=tuple(
|
|
1085
|
+
tuple(sorted(value.items())) for value in memory_candidates
|
|
1086
|
+
),
|
|
1087
|
+
risk_aversion=self.risk_aversion,
|
|
1088
|
+
diversity_weight=self.diversity_weight,
|
|
1089
|
+
beam_width=self.beam_width,
|
|
1090
|
+
contextual_allocation=contextual_allocation,
|
|
1091
|
+
)
|
|
1092
|
+
)
|
|
1093
|
+
allocation = global_allocation.allocation
|
|
1094
|
+
card_by_option = dict(global_allocation.memory_assignment)
|
|
1095
|
+
role_slots = global_allocation.role_slots
|
|
1096
|
+
else:
|
|
1097
|
+
best: tuple[ActionAllocationResult, dict[str, str]] | None = None
|
|
1098
|
+
failures: list[str] = []
|
|
1099
|
+
for card_by_option in memory_candidates:
|
|
1100
|
+
required = tuple(
|
|
1101
|
+
sorted(
|
|
1102
|
+
{
|
|
1103
|
+
*request.candidate_pool_required_option_ids,
|
|
1104
|
+
*card_by_option,
|
|
1105
|
+
}
|
|
1106
|
+
)
|
|
1107
|
+
)
|
|
1108
|
+
try:
|
|
1109
|
+
allocation = allocate_target_conditioned_actions(
|
|
1110
|
+
plan=plan,
|
|
1111
|
+
forecasts=decision_forecasts,
|
|
1112
|
+
portfolio_size=request.portfolio_size,
|
|
1113
|
+
risk_aversion=self.risk_aversion,
|
|
1114
|
+
diversity_weight=self.diversity_weight,
|
|
1115
|
+
beam_width=self.beam_width,
|
|
1116
|
+
utility_mode=utility_mode,
|
|
1117
|
+
required_option_ids=required,
|
|
1118
|
+
exact_arm_count_constraints=(exact_arm_count_constraints),
|
|
1119
|
+
minimum_single_path_interventions=(
|
|
1120
|
+
0
|
|
1121
|
+
if contextual_allocation is None
|
|
1122
|
+
else contextual_allocation.minimum_single_path_interventions
|
|
1123
|
+
),
|
|
1124
|
+
minimum_disjoint_parent_patch_pairs=(
|
|
1125
|
+
0
|
|
1126
|
+
if contextual_allocation is None
|
|
1127
|
+
else contextual_allocation.minimum_disjoint_parent_patch_pairs
|
|
1128
|
+
),
|
|
1129
|
+
)
|
|
1130
|
+
except (TypeError, ValueError, RuntimeError) as error:
|
|
1131
|
+
failures.append(f"{type(error).__name__}:{error}")
|
|
1132
|
+
continue
|
|
1133
|
+
if best is None or allocation.decision.final_score.total_utility > (
|
|
1134
|
+
best[0].decision.final_score.total_utility
|
|
1135
|
+
):
|
|
1136
|
+
best = allocation, card_by_option
|
|
1137
|
+
if best is None:
|
|
1138
|
+
detail = "; ".join(failures[:4])
|
|
1139
|
+
raise ValueError(
|
|
1140
|
+
"no hard-feasible outcome-conditioned memory assignment"
|
|
1141
|
+
+ ("; " + detail if detail else "")
|
|
1142
|
+
)
|
|
1143
|
+
allocation, card_by_option = best
|
|
1144
|
+
selected_support, proposed_dose, evaluated_dose = _memory_assessments(
|
|
1145
|
+
request,
|
|
1146
|
+
allocation=allocation,
|
|
1147
|
+
card_by_option=card_by_option,
|
|
1148
|
+
preference=preference,
|
|
1149
|
+
)
|
|
1150
|
+
selected_required_option_ids = tuple(
|
|
1151
|
+
sorted(
|
|
1152
|
+
{
|
|
1153
|
+
*request.candidate_pool_required_option_ids,
|
|
1154
|
+
*card_by_option,
|
|
1155
|
+
}
|
|
1156
|
+
)
|
|
1157
|
+
)
|
|
1158
|
+
|
|
1159
|
+
forecast_by_id = {
|
|
1160
|
+
value.option_id: value for value in decision_forecasts.forecasts
|
|
1161
|
+
}
|
|
1162
|
+
alias_by_target = {
|
|
1163
|
+
value.target_metric_id: value.forecast_metric_id for value in plan.aliases
|
|
1164
|
+
}
|
|
1165
|
+
role_audit = (
|
|
1166
|
+
()
|
|
1167
|
+
if utility_mode != "role_factorized"
|
|
1168
|
+
else audit_target_conditioned_role_allocation(
|
|
1169
|
+
plan=plan,
|
|
1170
|
+
forecasts=decision_forecasts,
|
|
1171
|
+
decision=allocation.decision,
|
|
1172
|
+
eligible_option_ids=(
|
|
1173
|
+
None
|
|
1174
|
+
if global_allocation is None
|
|
1175
|
+
else global_allocation.eligible_option_ids
|
|
1176
|
+
),
|
|
1177
|
+
role_slots=role_slots,
|
|
1178
|
+
exact_arm_count_constraints=exact_arm_count_constraints,
|
|
1179
|
+
required_option_ids=selected_required_option_ids,
|
|
1180
|
+
minimum_single_path_interventions=(
|
|
1181
|
+
0
|
|
1182
|
+
if contextual_allocation is None
|
|
1183
|
+
else contextual_allocation.minimum_single_path_interventions
|
|
1184
|
+
),
|
|
1185
|
+
minimum_disjoint_parent_patch_pairs=(
|
|
1186
|
+
0
|
|
1187
|
+
if contextual_allocation is None
|
|
1188
|
+
else contextual_allocation.minimum_disjoint_parent_patch_pairs
|
|
1189
|
+
),
|
|
1190
|
+
)
|
|
1191
|
+
)
|
|
1192
|
+
role_by_option: dict[str, str] = {}
|
|
1193
|
+
if role_audit:
|
|
1194
|
+
p50 = role_audit[1]
|
|
1195
|
+
role_by_option = {
|
|
1196
|
+
value.option_id: value.role.value for value in p50.assignments
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
drafts: list[PortfolioMemberDraft] = []
|
|
1200
|
+
for member in allocation.decision.members:
|
|
1201
|
+
forecast = forecast_by_id[member.option_id]
|
|
1202
|
+
supporting = selected_support[member.option_id]
|
|
1203
|
+
if request.memory_dose_contract is None:
|
|
1204
|
+
supporting = _selected_card_keys(forecast)
|
|
1205
|
+
if request.require_supporting_cards and not supporting:
|
|
1206
|
+
raise ValueError(
|
|
1207
|
+
"grounded all-action selection produced an uncited member"
|
|
1208
|
+
)
|
|
1209
|
+
metrics = {value.metric_id: value for value in forecast.metric_forecasts}
|
|
1210
|
+
effects = tuple(
|
|
1211
|
+
MetricEffectPrediction(
|
|
1212
|
+
metric_id=target_metric_id,
|
|
1213
|
+
direction=_direction(metrics[alias_by_target[target_metric_id]]),
|
|
1214
|
+
)
|
|
1215
|
+
for target_metric_id in request.required_metric_ids
|
|
1216
|
+
)
|
|
1217
|
+
fallback_role = (
|
|
1218
|
+
"directional_bootstrap"
|
|
1219
|
+
if utility_mode == "target_closure"
|
|
1220
|
+
else "terminal_exploit"
|
|
1221
|
+
)
|
|
1222
|
+
role = role_by_option.get(member.option_id, fallback_role)
|
|
1223
|
+
drafts.append(
|
|
1224
|
+
PortfolioMemberDraft(
|
|
1225
|
+
option_id=member.option_id,
|
|
1226
|
+
supporting_card_keys=supporting,
|
|
1227
|
+
effect_predictions=effects,
|
|
1228
|
+
design_rationale=(
|
|
1229
|
+
f"Trusted outcome-conditioned allocation role={role}; "
|
|
1230
|
+
f"utility={utility_mode}; rank={member.rank}; "
|
|
1231
|
+
"numeric consequences were forecast for the sealed action "
|
|
1232
|
+
"and selection was performed by hard-feasible trusted code."
|
|
1233
|
+
),
|
|
1234
|
+
)
|
|
1235
|
+
)
|
|
1236
|
+
|
|
1237
|
+
policy_definition_sha256 = _bound_policy_definition(
|
|
1238
|
+
plan=plan,
|
|
1239
|
+
partition_policy=self.partition_policy,
|
|
1240
|
+
consequence_calibration=consequence_calibration,
|
|
1241
|
+
metric_projection=metric_projection,
|
|
1242
|
+
risk_aversion=self.risk_aversion,
|
|
1243
|
+
diversity_weight=self.diversity_weight,
|
|
1244
|
+
beam_width=self.beam_width,
|
|
1245
|
+
global_allocation_receipt_sha256=(
|
|
1246
|
+
None
|
|
1247
|
+
if global_allocation is None
|
|
1248
|
+
else global_allocation.global_receipt_sha256
|
|
1249
|
+
),
|
|
1250
|
+
contextual_allocation_contract_sha256=(
|
|
1251
|
+
None
|
|
1252
|
+
if contextual_allocation is None
|
|
1253
|
+
else contextual_allocation.contract_sha256
|
|
1254
|
+
),
|
|
1255
|
+
common_candidate_pool_decision_sha256=(
|
|
1256
|
+
None if candidate_pool is None else candidate_pool.decision_sha256
|
|
1257
|
+
),
|
|
1258
|
+
)
|
|
1259
|
+
decision = resolve_ranked_portfolio_decision(
|
|
1260
|
+
request,
|
|
1261
|
+
tuple(drafts),
|
|
1262
|
+
policy_id=OUTCOME_CONDITIONED_PORTFOLIO_POLICY_ID,
|
|
1263
|
+
policy_version=OUTCOME_CONDITIONED_PORTFOLIO_POLICY_VERSION,
|
|
1264
|
+
policy_definition_sha256=policy_definition_sha256,
|
|
1265
|
+
memory_dose_assessment=evaluated_dose,
|
|
1266
|
+
)
|
|
1267
|
+
selected_ids = {value.option_id for value in allocation.decision.members}
|
|
1268
|
+
contextual_realization = contextual_allocation_realization(
|
|
1269
|
+
finite_contract=request.finite_variation_contract,
|
|
1270
|
+
allocation=contextual_allocation,
|
|
1271
|
+
selected_option_ids=tuple(
|
|
1272
|
+
value.option_id for value in allocation.decision.members
|
|
1273
|
+
),
|
|
1274
|
+
)
|
|
1275
|
+
selected_forecasts = tuple(
|
|
1276
|
+
value.to_record()
|
|
1277
|
+
for value in decision_forecasts.forecasts
|
|
1278
|
+
if value.option_id in selected_ids
|
|
1279
|
+
)
|
|
1280
|
+
audit = PortfolioSelectionSupplementalAudit(
|
|
1281
|
+
audit_kind="outcome_conditioned_expert_portfolio",
|
|
1282
|
+
request_sha256=request.request_sha256,
|
|
1283
|
+
decision_sha256=decision.decision_sha256,
|
|
1284
|
+
payload=_object(
|
|
1285
|
+
{
|
|
1286
|
+
"schema_version": 2,
|
|
1287
|
+
"phase": phase.to_record(),
|
|
1288
|
+
"evidence_mode": plan.request.evidence_mode.value,
|
|
1289
|
+
"forecast_request_sha256": plan.request.request_sha256,
|
|
1290
|
+
"forecast_universe_projection": forecast_universe_projection,
|
|
1291
|
+
"proposal_topology": project_finite_contract_proposal_topology(
|
|
1292
|
+
source_contract=request.finite_variation_contract,
|
|
1293
|
+
proposal_contract=forecast_contract,
|
|
1294
|
+
),
|
|
1295
|
+
"partitioned_forecast": partitioned.to_record(),
|
|
1296
|
+
"physical_call_count": len(partitioned.block_results),
|
|
1297
|
+
"physical_call_telemetry": [
|
|
1298
|
+
_telemetry_record(value) for value in physical_telemetry
|
|
1299
|
+
],
|
|
1300
|
+
"forecast_health": health.to_record(),
|
|
1301
|
+
"forecast_health_authority_resolution": health_resolution,
|
|
1302
|
+
"raw_forecast_receipt_sha256": (
|
|
1303
|
+
partitioned.forecasts.receipt_sha256
|
|
1304
|
+
),
|
|
1305
|
+
"decision_forecast_receipt_sha256": (
|
|
1306
|
+
decision_forecasts.receipt_sha256
|
|
1307
|
+
),
|
|
1308
|
+
"consequence_calibration": (
|
|
1309
|
+
None
|
|
1310
|
+
if consequence_calibration is None
|
|
1311
|
+
else consequence_calibration.to_record()
|
|
1312
|
+
),
|
|
1313
|
+
"metric_projection": (
|
|
1314
|
+
None
|
|
1315
|
+
if metric_projection is None
|
|
1316
|
+
else metric_projection.to_record()
|
|
1317
|
+
),
|
|
1318
|
+
"utility_mode": utility_mode,
|
|
1319
|
+
"target_kind": target_kind,
|
|
1320
|
+
"allocation": allocation.decision.to_record(),
|
|
1321
|
+
"global_wave_allocation": _plain_global_allocation_audit(
|
|
1322
|
+
global_allocation
|
|
1323
|
+
),
|
|
1324
|
+
"contextual_allocation": (
|
|
1325
|
+
None
|
|
1326
|
+
if contextual_allocation is None
|
|
1327
|
+
else contextual_allocation.to_record()
|
|
1328
|
+
),
|
|
1329
|
+
"contextual_allocation_realization": (
|
|
1330
|
+
None
|
|
1331
|
+
if contextual_realization is None
|
|
1332
|
+
else contextual_realization.to_record()
|
|
1333
|
+
),
|
|
1334
|
+
"role_assignment_audits": [
|
|
1335
|
+
value.to_record() for value in role_audit
|
|
1336
|
+
],
|
|
1337
|
+
"selected_forecasts": list(selected_forecasts),
|
|
1338
|
+
"metric_aliases": [
|
|
1339
|
+
{
|
|
1340
|
+
"target_metric_id": value.target_metric_id,
|
|
1341
|
+
"forecast_metric_id": value.forecast_metric_id,
|
|
1342
|
+
}
|
|
1343
|
+
for value in plan.aliases
|
|
1344
|
+
],
|
|
1345
|
+
"required_option_ids": list(selected_required_option_ids),
|
|
1346
|
+
"memory_card_by_option": dict(sorted(card_by_option.items())),
|
|
1347
|
+
"proposed_memory_dose_assessment": (
|
|
1348
|
+
None if proposed_dose is None else proposed_dose.to_record()
|
|
1349
|
+
),
|
|
1350
|
+
"evaluated_memory_dose_assessment": (
|
|
1351
|
+
None if evaluated_dose is None else evaluated_dose.to_record()
|
|
1352
|
+
),
|
|
1353
|
+
"policy_definition_sha256": policy_definition_sha256,
|
|
1354
|
+
}
|
|
1355
|
+
),
|
|
1356
|
+
)
|
|
1357
|
+
return PortfolioSelectionResult(
|
|
1358
|
+
decision=decision,
|
|
1359
|
+
telemetry=telemetry,
|
|
1360
|
+
supplemental_audit=audit,
|
|
1361
|
+
)
|
|
1362
|
+
|
|
1363
|
+
|
|
1364
|
+
__all__ = [
|
|
1365
|
+
"OUTCOME_CONDITIONED_PORTFOLIO_POLICY_DEFINITION_SHA256",
|
|
1366
|
+
"OUTCOME_CONDITIONED_PORTFOLIO_POLICY_ID",
|
|
1367
|
+
"OUTCOME_CONDITIONED_PORTFOLIO_POLICY_VERSION",
|
|
1368
|
+
"ActionSemanticsFactory",
|
|
1369
|
+
"ContextualAllocationProvider",
|
|
1370
|
+
"OutcomeConditionedPortfolioSelectionPolicy",
|
|
1371
|
+
"outcome_conditioned_contextual_allocation_realization",
|
|
1372
|
+
"outcome_conditioned_selected_predictions",
|
|
1373
|
+
"outcome_conditioned_selected_source_ids",
|
|
1374
|
+
]
|