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,826 @@
|
|
|
1
|
+
"""Model-anchored, prior-calibrated allocation over a finite K8 slate.
|
|
2
|
+
|
|
3
|
+
This opt-in policy deliberately leaves :class:`TraceCalibratedSlatePolicy`
|
|
4
|
+
unchanged. It preserves as many members as possible from a configurable
|
|
5
|
+
model-ranked prefix, then fills the remaining K4 capacity using only a sealed
|
|
6
|
+
prior-wave calibration snapshot. Feasibility is always authoritative:
|
|
7
|
+
compatibility, family, and assigned-card constraints may displace anchors.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import hashlib
|
|
13
|
+
import json
|
|
14
|
+
import math
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
from enum import Enum
|
|
17
|
+
from itertools import combinations
|
|
18
|
+
from typing import ClassVar
|
|
19
|
+
|
|
20
|
+
from agent_evolve.domain.patch import require_sha256
|
|
21
|
+
from agent_evolve.policies.selection.calibrated_slate import (
|
|
22
|
+
CalibratedSlateMember,
|
|
23
|
+
MetricOptimizationGoal,
|
|
24
|
+
SlateAllocationRequest,
|
|
25
|
+
assess_allocated_slate_memory_dose,
|
|
26
|
+
)
|
|
27
|
+
from agent_evolve.policies.selection.forecast_calibration import (
|
|
28
|
+
ForecastCalibrationCell,
|
|
29
|
+
ForecastConfidenceBin,
|
|
30
|
+
)
|
|
31
|
+
from agent_evolve.ports.agentic_generator import MetricEffectDirection
|
|
32
|
+
from agent_evolve.ports.portfolio_memory_dose import (
|
|
33
|
+
PortfolioMemoryDoseAssessment,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
POLICY_ID = "model_anchored_prior_calibrated_slate"
|
|
38
|
+
POLICY_VERSION = 2
|
|
39
|
+
POLICY_DEFINITION_SHA256 = hashlib.sha256(
|
|
40
|
+
b"agent-evolve:model-anchored-prior-calibrated-slate:v2;"
|
|
41
|
+
b"slate-size=8;portfolio-size=4;model-prefix-anchor-count=configurable;"
|
|
42
|
+
b"full-model-top4-anchor-allowed=true;calibrated-fill=fallback-only;"
|
|
43
|
+
b"feasibility-before-ranking=true;maximize-retained-anchors=true;"
|
|
44
|
+
b"fill-score=prior-only-calibrated-exploitation-sum;"
|
|
45
|
+
b"ties=fill-score-vector,fill-structural-sum,diversity,anchor-ranks,"
|
|
46
|
+
b"selected-ranks,option-ids;card-administration=complete;"
|
|
47
|
+
b"calibration-cutoff-exclusive=true;outcome-blind=true"
|
|
48
|
+
).hexdigest()
|
|
49
|
+
|
|
50
|
+
_CONFIGURATION_DOMAIN = b"agent-evolve:model-anchored-slate-config:v1\x00"
|
|
51
|
+
_DECISION_DOMAIN = b"agent-evolve:model-anchored-slate-decision:v1\x00"
|
|
52
|
+
_SLATE_SIZE = 8
|
|
53
|
+
_PORTFOLIO_SIZE = 4
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _canonical_json(value: object) -> bytes:
|
|
57
|
+
return json.dumps(
|
|
58
|
+
value,
|
|
59
|
+
allow_nan=False,
|
|
60
|
+
ensure_ascii=True,
|
|
61
|
+
separators=(",", ":"),
|
|
62
|
+
sort_keys=True,
|
|
63
|
+
).encode("ascii", errors="strict")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _hash(domain: bytes, value: object) -> str:
|
|
67
|
+
return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _require_finite_float(value: float, *, name: str) -> None:
|
|
71
|
+
if type(value) is not float or not math.isfinite(value):
|
|
72
|
+
raise TypeError(f"{name} must be a finite canonical float")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class ModelAnchoredSlateRole(str, Enum):
|
|
76
|
+
"""Engine-owned provenance of a selected K4 member."""
|
|
77
|
+
|
|
78
|
+
MODEL_ANCHOR = "model_anchor"
|
|
79
|
+
PRIOR_CALIBRATED_FILL = "prior_calibrated_fill"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass(frozen=True, slots=True)
|
|
83
|
+
class ModelAnchoredMetricScoreRow:
|
|
84
|
+
"""One objective's prior-only contribution to exploitation."""
|
|
85
|
+
|
|
86
|
+
metric_id: str
|
|
87
|
+
goal: MetricOptimizationGoal
|
|
88
|
+
asserted_direction: MetricEffectDirection
|
|
89
|
+
confidence: ForecastConfidenceBin
|
|
90
|
+
weight: float
|
|
91
|
+
calibration_cell: ForecastCalibrationCell
|
|
92
|
+
calibration_source: str
|
|
93
|
+
favorable_assertion: bool
|
|
94
|
+
adverse_assertion: bool
|
|
95
|
+
signed_exploitation_score: float
|
|
96
|
+
|
|
97
|
+
def __post_init__(self) -> None:
|
|
98
|
+
if type(self.metric_id) is not str or not self.metric_id:
|
|
99
|
+
raise ValueError("metric_id must be a non-empty string")
|
|
100
|
+
if type(self.goal) is not MetricOptimizationGoal:
|
|
101
|
+
raise TypeError("goal must be exact MetricOptimizationGoal")
|
|
102
|
+
if type(self.asserted_direction) is not MetricEffectDirection:
|
|
103
|
+
raise TypeError("asserted_direction must be exact MetricEffectDirection")
|
|
104
|
+
if type(self.confidence) is not ForecastConfidenceBin:
|
|
105
|
+
raise TypeError("confidence must be exact ForecastConfidenceBin")
|
|
106
|
+
_require_finite_float(self.weight, name="weight")
|
|
107
|
+
if self.weight <= 0.0:
|
|
108
|
+
raise ValueError("weight must be strictly positive")
|
|
109
|
+
if type(self.calibration_cell) is not ForecastCalibrationCell:
|
|
110
|
+
raise TypeError("calibration_cell must be exact ForecastCalibrationCell")
|
|
111
|
+
self.calibration_cell.__post_init__()
|
|
112
|
+
if self.calibration_source not in {
|
|
113
|
+
"supported_family",
|
|
114
|
+
"metric_direction_confidence",
|
|
115
|
+
"declared_prior",
|
|
116
|
+
}:
|
|
117
|
+
raise ValueError("unsupported calibration_source")
|
|
118
|
+
if type(self.favorable_assertion) is not bool:
|
|
119
|
+
raise TypeError("favorable_assertion must be exact bool")
|
|
120
|
+
if type(self.adverse_assertion) is not bool:
|
|
121
|
+
raise TypeError("adverse_assertion must be exact bool")
|
|
122
|
+
if self.favorable_assertion and self.adverse_assertion:
|
|
123
|
+
raise ValueError("one assertion cannot be favorable and adverse")
|
|
124
|
+
_require_finite_float(
|
|
125
|
+
self.signed_exploitation_score,
|
|
126
|
+
name="signed_exploitation_score",
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
def to_record(self) -> dict[str, object]:
|
|
130
|
+
self.__post_init__()
|
|
131
|
+
return {
|
|
132
|
+
"metric_id": self.metric_id,
|
|
133
|
+
"goal": self.goal.value,
|
|
134
|
+
"asserted_direction": self.asserted_direction.value,
|
|
135
|
+
"confidence": self.confidence.value,
|
|
136
|
+
"weight_hex": self.weight.hex(),
|
|
137
|
+
"calibration_cell": self.calibration_cell.to_record(),
|
|
138
|
+
"calibration_source": self.calibration_source,
|
|
139
|
+
"favorable_assertion": self.favorable_assertion,
|
|
140
|
+
"adverse_assertion": self.adverse_assertion,
|
|
141
|
+
"signed_exploitation_score_hex": (
|
|
142
|
+
self.signed_exploitation_score.hex()
|
|
143
|
+
),
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@dataclass(frozen=True, slots=True)
|
|
148
|
+
class ModelAnchoredMemberScoreRow:
|
|
149
|
+
"""Prior-only exploitation and frozen structure for one slate member."""
|
|
150
|
+
|
|
151
|
+
option_id: str
|
|
152
|
+
option_identity_sha256: str
|
|
153
|
+
model_rank: int
|
|
154
|
+
metric_scores: tuple[ModelAnchoredMetricScoreRow, ...]
|
|
155
|
+
calibrated_exploitation_score: float
|
|
156
|
+
structural_coverage_score: float
|
|
157
|
+
supported_assigned_card_keys: tuple[str, ...]
|
|
158
|
+
|
|
159
|
+
def __post_init__(self) -> None:
|
|
160
|
+
if type(self.option_id) is not str or not self.option_id:
|
|
161
|
+
raise ValueError("option_id must be a non-empty string")
|
|
162
|
+
require_sha256(self.option_identity_sha256, "option_identity_sha256")
|
|
163
|
+
if type(self.model_rank) is not int or self.model_rank <= 0:
|
|
164
|
+
raise ValueError("model_rank must be a positive exact integer")
|
|
165
|
+
if type(self.metric_scores) is not tuple or not self.metric_scores or any(
|
|
166
|
+
type(value) is not ModelAnchoredMetricScoreRow
|
|
167
|
+
for value in self.metric_scores
|
|
168
|
+
):
|
|
169
|
+
raise ValueError("metric_scores must contain exact metric score rows")
|
|
170
|
+
for value in self.metric_scores:
|
|
171
|
+
value.__post_init__()
|
|
172
|
+
metric_ids = tuple(value.metric_id for value in self.metric_scores)
|
|
173
|
+
if metric_ids != tuple(sorted(set(metric_ids))):
|
|
174
|
+
raise ValueError("metric_scores must use canonical unique metric order")
|
|
175
|
+
_require_finite_float(
|
|
176
|
+
self.calibrated_exploitation_score,
|
|
177
|
+
name="calibrated_exploitation_score",
|
|
178
|
+
)
|
|
179
|
+
_require_finite_float(
|
|
180
|
+
self.structural_coverage_score,
|
|
181
|
+
name="structural_coverage_score",
|
|
182
|
+
)
|
|
183
|
+
if not 0.0 <= self.structural_coverage_score <= 1.0:
|
|
184
|
+
raise ValueError("structural_coverage_score must lie in [0, 1]")
|
|
185
|
+
if type(self.supported_assigned_card_keys) is not tuple or any(
|
|
186
|
+
type(value) is not str or not value
|
|
187
|
+
for value in self.supported_assigned_card_keys
|
|
188
|
+
):
|
|
189
|
+
raise TypeError("supported_assigned_card_keys must be an exact tuple")
|
|
190
|
+
if self.supported_assigned_card_keys != tuple(
|
|
191
|
+
sorted(set(self.supported_assigned_card_keys))
|
|
192
|
+
):
|
|
193
|
+
raise ValueError("supported_assigned_card_keys must be canonical")
|
|
194
|
+
|
|
195
|
+
def to_record(self) -> dict[str, object]:
|
|
196
|
+
self.__post_init__()
|
|
197
|
+
return {
|
|
198
|
+
"option_id": self.option_id,
|
|
199
|
+
"option_identity_sha256": self.option_identity_sha256,
|
|
200
|
+
"model_rank": self.model_rank,
|
|
201
|
+
"metric_scores": [value.to_record() for value in self.metric_scores],
|
|
202
|
+
"calibrated_exploitation_score_hex": (
|
|
203
|
+
self.calibrated_exploitation_score.hex()
|
|
204
|
+
),
|
|
205
|
+
"structural_coverage_score_hex": (
|
|
206
|
+
self.structural_coverage_score.hex()
|
|
207
|
+
),
|
|
208
|
+
"supported_assigned_card_keys": list(
|
|
209
|
+
self.supported_assigned_card_keys
|
|
210
|
+
),
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@dataclass(frozen=True, slots=True)
|
|
215
|
+
class ModelAnchoredAllocatedMember:
|
|
216
|
+
"""One selected member with auditable model/calibration provenance."""
|
|
217
|
+
|
|
218
|
+
role: ModelAnchoredSlateRole
|
|
219
|
+
option_id: str
|
|
220
|
+
option_identity_sha256: str
|
|
221
|
+
model_rank: int
|
|
222
|
+
calibrated_exploitation_score: float
|
|
223
|
+
|
|
224
|
+
def __post_init__(self) -> None:
|
|
225
|
+
if type(self.role) is not ModelAnchoredSlateRole:
|
|
226
|
+
raise TypeError("role must be exact ModelAnchoredSlateRole")
|
|
227
|
+
if type(self.option_id) is not str or not self.option_id:
|
|
228
|
+
raise ValueError("option_id must be a non-empty string")
|
|
229
|
+
require_sha256(self.option_identity_sha256, "option_identity_sha256")
|
|
230
|
+
if type(self.model_rank) is not int or self.model_rank <= 0:
|
|
231
|
+
raise ValueError("model_rank must be a positive exact integer")
|
|
232
|
+
_require_finite_float(
|
|
233
|
+
self.calibrated_exploitation_score,
|
|
234
|
+
name="calibrated_exploitation_score",
|
|
235
|
+
)
|
|
236
|
+
|
|
237
|
+
def to_record(self) -> dict[str, object]:
|
|
238
|
+
self.__post_init__()
|
|
239
|
+
return {
|
|
240
|
+
"role": self.role.value,
|
|
241
|
+
"option_id": self.option_id,
|
|
242
|
+
"option_identity_sha256": self.option_identity_sha256,
|
|
243
|
+
"model_rank": self.model_rank,
|
|
244
|
+
"calibrated_exploitation_score_hex": (
|
|
245
|
+
self.calibrated_exploitation_score.hex()
|
|
246
|
+
),
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
@dataclass(frozen=True, slots=True)
|
|
251
|
+
class _AnchoredAssignment:
|
|
252
|
+
selected: tuple[ModelAnchoredAllocatedMember, ...]
|
|
253
|
+
retained_anchor_option_ids: tuple[str, ...]
|
|
254
|
+
calibrated_fill_option_ids: tuple[str, ...]
|
|
255
|
+
calibrated_fill_exploitation_score: float
|
|
256
|
+
calibrated_fill_structural_score: float
|
|
257
|
+
distinct_family_count: int
|
|
258
|
+
distinct_locus_count: int
|
|
259
|
+
distinct_phenotype_count: int
|
|
260
|
+
administered_card_keys: tuple[str, ...]
|
|
261
|
+
feasible_subset_count: int
|
|
262
|
+
memory_dose_assessment: PortfolioMemoryDoseAssessment | None
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def _configuration_record(model_anchor_count: int) -> dict[str, object]:
|
|
266
|
+
return {
|
|
267
|
+
"schema_version": 1,
|
|
268
|
+
"model_anchor_count": model_anchor_count,
|
|
269
|
+
"slate_size": _SLATE_SIZE,
|
|
270
|
+
"portfolio_size": _PORTFOLIO_SIZE,
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def _favorable(
|
|
275
|
+
direction: MetricEffectDirection,
|
|
276
|
+
goal: MetricOptimizationGoal,
|
|
277
|
+
) -> tuple[bool, bool]:
|
|
278
|
+
if direction in {MetricEffectDirection.UNKNOWN, MetricEffectDirection.UNCHANGED}:
|
|
279
|
+
return False, False
|
|
280
|
+
favorable = (
|
|
281
|
+
goal is MetricOptimizationGoal.MINIMIZE
|
|
282
|
+
and direction is MetricEffectDirection.DECREASE
|
|
283
|
+
) or (
|
|
284
|
+
goal is MetricOptimizationGoal.MAXIMIZE
|
|
285
|
+
and direction is MetricEffectDirection.INCREASE
|
|
286
|
+
)
|
|
287
|
+
return favorable, not favorable
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def _score_member(
|
|
291
|
+
request: SlateAllocationRequest,
|
|
292
|
+
member: CalibratedSlateMember,
|
|
293
|
+
) -> ModelAnchoredMemberScoreRow:
|
|
294
|
+
snapshot = request.calibration_snapshot
|
|
295
|
+
if snapshot is None:
|
|
296
|
+
raise ValueError("model-anchored policy requires a calibration snapshot")
|
|
297
|
+
objective_by_metric = {value.metric_id: value for value in request.objectives}
|
|
298
|
+
metric_scores: list[ModelAnchoredMetricScoreRow] = []
|
|
299
|
+
weighted_score = 0.0
|
|
300
|
+
total_weight = sum(value.weight for value in request.objectives)
|
|
301
|
+
for prediction in member.predictions:
|
|
302
|
+
objective = objective_by_metric[prediction.metric_id]
|
|
303
|
+
cell, source = snapshot.lookup(
|
|
304
|
+
metric_id=prediction.metric_id,
|
|
305
|
+
asserted_direction=prediction.asserted_direction,
|
|
306
|
+
confidence=prediction.confidence,
|
|
307
|
+
family=member.family,
|
|
308
|
+
)
|
|
309
|
+
favorable, adverse = _favorable(
|
|
310
|
+
prediction.asserted_direction,
|
|
311
|
+
objective.goal,
|
|
312
|
+
)
|
|
313
|
+
probability = cell.posterior_correctness
|
|
314
|
+
signed_score = probability if favorable else -probability if adverse else 0.0
|
|
315
|
+
weighted_score += objective.weight * signed_score
|
|
316
|
+
metric_scores.append(
|
|
317
|
+
ModelAnchoredMetricScoreRow(
|
|
318
|
+
metric_id=prediction.metric_id,
|
|
319
|
+
goal=objective.goal,
|
|
320
|
+
asserted_direction=prediction.asserted_direction,
|
|
321
|
+
confidence=prediction.confidence,
|
|
322
|
+
weight=objective.weight,
|
|
323
|
+
calibration_cell=cell,
|
|
324
|
+
calibration_source=source,
|
|
325
|
+
favorable_assertion=favorable,
|
|
326
|
+
adverse_assertion=adverse,
|
|
327
|
+
signed_exploitation_score=signed_score,
|
|
328
|
+
)
|
|
329
|
+
)
|
|
330
|
+
supported_cards = tuple(
|
|
331
|
+
card
|
|
332
|
+
for card in request.assigned_card_keys
|
|
333
|
+
if card in member.supporting_card_keys
|
|
334
|
+
)
|
|
335
|
+
structural_score = (
|
|
336
|
+
member.structural_evidence.archive_novelty_score
|
|
337
|
+
+ member.structural_evidence.structural_coverage_score
|
|
338
|
+
) / 2.0
|
|
339
|
+
return ModelAnchoredMemberScoreRow(
|
|
340
|
+
option_id=member.option_id,
|
|
341
|
+
option_identity_sha256=member.option_identity_sha256,
|
|
342
|
+
model_rank=member.model_rank,
|
|
343
|
+
metric_scores=tuple(metric_scores),
|
|
344
|
+
calibrated_exploitation_score=weighted_score / total_weight,
|
|
345
|
+
structural_coverage_score=structural_score,
|
|
346
|
+
supported_assigned_card_keys=supported_cards,
|
|
347
|
+
)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _compatible(
|
|
351
|
+
members: tuple[CalibratedSlateMember, ...],
|
|
352
|
+
allowed_pairs: set[frozenset[str]] | None,
|
|
353
|
+
) -> bool:
|
|
354
|
+
if allowed_pairs is None:
|
|
355
|
+
return True
|
|
356
|
+
return all(
|
|
357
|
+
frozenset((left.option_id, right.option_id)) in allowed_pairs
|
|
358
|
+
for left_index, left in enumerate(members)
|
|
359
|
+
for right in members[left_index + 1 :]
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
def _best_anchored_assignment(
|
|
364
|
+
request: SlateAllocationRequest,
|
|
365
|
+
score_rows: tuple[ModelAnchoredMemberScoreRow, ...],
|
|
366
|
+
*,
|
|
367
|
+
model_anchor_count: int,
|
|
368
|
+
) -> _AnchoredAssignment:
|
|
369
|
+
score_by_id = {value.option_id: value for value in score_rows}
|
|
370
|
+
anchor_ids = {
|
|
371
|
+
value.option_id for value in request.slate.members[:model_anchor_count]
|
|
372
|
+
}
|
|
373
|
+
allowed_pairs = (
|
|
374
|
+
None
|
|
375
|
+
if request.pairwise_disjoint_option_id_pairs is None
|
|
376
|
+
else {
|
|
377
|
+
frozenset(value)
|
|
378
|
+
for value in request.pairwise_disjoint_option_id_pairs
|
|
379
|
+
}
|
|
380
|
+
)
|
|
381
|
+
feasible: list[
|
|
382
|
+
tuple[
|
|
383
|
+
tuple[object, ...],
|
|
384
|
+
tuple[CalibratedSlateMember, ...],
|
|
385
|
+
tuple[ModelAnchoredMemberScoreRow, ...],
|
|
386
|
+
tuple[ModelAnchoredMemberScoreRow, ...],
|
|
387
|
+
tuple[str, ...],
|
|
388
|
+
tuple[str, ...],
|
|
389
|
+
int,
|
|
390
|
+
int,
|
|
391
|
+
int,
|
|
392
|
+
PortfolioMemoryDoseAssessment | None,
|
|
393
|
+
]
|
|
394
|
+
] = []
|
|
395
|
+
for subset in combinations(request.slate.members, request.portfolio_size):
|
|
396
|
+
if not _compatible(subset, allowed_pairs):
|
|
397
|
+
continue
|
|
398
|
+
family_count = len({value.family for value in subset})
|
|
399
|
+
if (
|
|
400
|
+
request.min_distinct_families is not None
|
|
401
|
+
and family_count < request.min_distinct_families
|
|
402
|
+
):
|
|
403
|
+
continue
|
|
404
|
+
rows = tuple(score_by_id[value.option_id] for value in subset)
|
|
405
|
+
administered = tuple(
|
|
406
|
+
sorted(
|
|
407
|
+
{
|
|
408
|
+
card
|
|
409
|
+
for row in rows
|
|
410
|
+
for card in row.supported_assigned_card_keys
|
|
411
|
+
}
|
|
412
|
+
)
|
|
413
|
+
)
|
|
414
|
+
if administered != request.assigned_card_keys:
|
|
415
|
+
continue
|
|
416
|
+
memory_dose_assessment = (
|
|
417
|
+
None
|
|
418
|
+
if request.memory_dose_contract is None
|
|
419
|
+
else assess_allocated_slate_memory_dose(
|
|
420
|
+
request,
|
|
421
|
+
subset,
|
|
422
|
+
)
|
|
423
|
+
)
|
|
424
|
+
if (
|
|
425
|
+
memory_dose_assessment is not None
|
|
426
|
+
and not memory_dose_assessment.passed
|
|
427
|
+
):
|
|
428
|
+
continue
|
|
429
|
+
retained = tuple(value for value in rows if value.option_id in anchor_ids)
|
|
430
|
+
fills = tuple(value for value in rows if value.option_id not in anchor_ids)
|
|
431
|
+
fill_scores = tuple(
|
|
432
|
+
sorted(
|
|
433
|
+
(value.calibrated_exploitation_score for value in fills),
|
|
434
|
+
reverse=True,
|
|
435
|
+
)
|
|
436
|
+
)
|
|
437
|
+
fill_score = sum(fill_scores, 0.0)
|
|
438
|
+
fill_structural = sum(
|
|
439
|
+
(value.structural_coverage_score for value in fills),
|
|
440
|
+
0.0,
|
|
441
|
+
)
|
|
442
|
+
locus_count = len({value.locus_key for value in subset})
|
|
443
|
+
phenotype_count = len(
|
|
444
|
+
{value.phenotype_identity_sha256 for value in subset}
|
|
445
|
+
)
|
|
446
|
+
retained_ranks = tuple(value.model_rank for value in retained)
|
|
447
|
+
selected_ranks = tuple(value.model_rank for value in rows)
|
|
448
|
+
# ``min`` over this key implements the documented strict priority.
|
|
449
|
+
key: tuple[object, ...] = (
|
|
450
|
+
-len(retained),
|
|
451
|
+
-fill_score,
|
|
452
|
+
tuple(-value for value in fill_scores),
|
|
453
|
+
-fill_structural,
|
|
454
|
+
-family_count,
|
|
455
|
+
-locus_count,
|
|
456
|
+
-phenotype_count,
|
|
457
|
+
retained_ranks,
|
|
458
|
+
selected_ranks,
|
|
459
|
+
tuple(value.option_id for value in rows),
|
|
460
|
+
)
|
|
461
|
+
feasible.append(
|
|
462
|
+
(
|
|
463
|
+
key,
|
|
464
|
+
subset,
|
|
465
|
+
retained,
|
|
466
|
+
fills,
|
|
467
|
+
administered,
|
|
468
|
+
tuple(value.option_id for value in retained),
|
|
469
|
+
family_count,
|
|
470
|
+
locus_count,
|
|
471
|
+
phenotype_count,
|
|
472
|
+
memory_dose_assessment,
|
|
473
|
+
)
|
|
474
|
+
)
|
|
475
|
+
if not feasible:
|
|
476
|
+
raise ValueError(
|
|
477
|
+
"slate has no feasible K4 subset administering every assigned card"
|
|
478
|
+
)
|
|
479
|
+
(
|
|
480
|
+
_,
|
|
481
|
+
subset,
|
|
482
|
+
retained,
|
|
483
|
+
fills,
|
|
484
|
+
administered,
|
|
485
|
+
retained_ids,
|
|
486
|
+
family_count,
|
|
487
|
+
locus_count,
|
|
488
|
+
phenotype_count,
|
|
489
|
+
memory_dose_assessment,
|
|
490
|
+
) = min(feasible, key=lambda value: value[0])
|
|
491
|
+
fill_ids = tuple(value.option_id for value in fills)
|
|
492
|
+
selected = tuple(
|
|
493
|
+
ModelAnchoredAllocatedMember(
|
|
494
|
+
role=(
|
|
495
|
+
ModelAnchoredSlateRole.MODEL_ANCHOR
|
|
496
|
+
if member.option_id in anchor_ids
|
|
497
|
+
else ModelAnchoredSlateRole.PRIOR_CALIBRATED_FILL
|
|
498
|
+
),
|
|
499
|
+
option_id=member.option_id,
|
|
500
|
+
option_identity_sha256=member.option_identity_sha256,
|
|
501
|
+
model_rank=member.model_rank,
|
|
502
|
+
calibrated_exploitation_score=(
|
|
503
|
+
score_by_id[member.option_id].calibrated_exploitation_score
|
|
504
|
+
),
|
|
505
|
+
)
|
|
506
|
+
for member in subset
|
|
507
|
+
)
|
|
508
|
+
return _AnchoredAssignment(
|
|
509
|
+
selected=selected,
|
|
510
|
+
retained_anchor_option_ids=retained_ids,
|
|
511
|
+
calibrated_fill_option_ids=fill_ids,
|
|
512
|
+
calibrated_fill_exploitation_score=sum(
|
|
513
|
+
(value.calibrated_exploitation_score for value in fills),
|
|
514
|
+
0.0,
|
|
515
|
+
),
|
|
516
|
+
calibrated_fill_structural_score=sum(
|
|
517
|
+
(value.structural_coverage_score for value in fills),
|
|
518
|
+
0.0,
|
|
519
|
+
),
|
|
520
|
+
distinct_family_count=family_count,
|
|
521
|
+
distinct_locus_count=locus_count,
|
|
522
|
+
distinct_phenotype_count=phenotype_count,
|
|
523
|
+
administered_card_keys=administered,
|
|
524
|
+
feasible_subset_count=len(feasible),
|
|
525
|
+
memory_dose_assessment=memory_dose_assessment,
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
530
|
+
class ModelAnchoredSlateDecision:
|
|
531
|
+
"""Replayable receipt for one outcome-blind K8-to-K4 decision."""
|
|
532
|
+
|
|
533
|
+
request: SlateAllocationRequest
|
|
534
|
+
model_anchor_count: int
|
|
535
|
+
score_rows: tuple[ModelAnchoredMemberScoreRow, ...]
|
|
536
|
+
selected: tuple[ModelAnchoredAllocatedMember, ...]
|
|
537
|
+
retained_anchor_option_ids: tuple[str, ...]
|
|
538
|
+
calibrated_fill_option_ids: tuple[str, ...]
|
|
539
|
+
calibrated_fill_exploitation_score: float
|
|
540
|
+
calibrated_fill_structural_score: float
|
|
541
|
+
distinct_family_count: int
|
|
542
|
+
distinct_locus_count: int
|
|
543
|
+
distinct_phenotype_count: int
|
|
544
|
+
administered_card_keys: tuple[str, ...]
|
|
545
|
+
feasible_subset_count: int
|
|
546
|
+
memory_dose_assessment: PortfolioMemoryDoseAssessment | None = None
|
|
547
|
+
|
|
548
|
+
policy_id: ClassVar[str] = POLICY_ID
|
|
549
|
+
policy_version: ClassVar[int] = POLICY_VERSION
|
|
550
|
+
policy_definition_sha256: ClassVar[str] = POLICY_DEFINITION_SHA256
|
|
551
|
+
|
|
552
|
+
def __post_init__(self) -> None:
|
|
553
|
+
if type(self.request) is not SlateAllocationRequest:
|
|
554
|
+
raise TypeError("request must be exact SlateAllocationRequest")
|
|
555
|
+
self.request.revalidate()
|
|
556
|
+
_validate_policy_request(self.request, self.model_anchor_count)
|
|
557
|
+
if type(self.score_rows) is not tuple or any(
|
|
558
|
+
type(value) is not ModelAnchoredMemberScoreRow
|
|
559
|
+
for value in self.score_rows
|
|
560
|
+
):
|
|
561
|
+
raise TypeError("score_rows must contain exact member score rows")
|
|
562
|
+
for value in self.score_rows:
|
|
563
|
+
value.__post_init__()
|
|
564
|
+
if type(self.selected) is not tuple or any(
|
|
565
|
+
type(value) is not ModelAnchoredAllocatedMember
|
|
566
|
+
for value in self.selected
|
|
567
|
+
):
|
|
568
|
+
raise TypeError("selected must contain exact allocated members")
|
|
569
|
+
for value in self.selected:
|
|
570
|
+
value.__post_init__()
|
|
571
|
+
if self.memory_dose_assessment is not None:
|
|
572
|
+
if type(self.memory_dose_assessment) is not (
|
|
573
|
+
PortfolioMemoryDoseAssessment
|
|
574
|
+
):
|
|
575
|
+
raise TypeError("memory_dose_assessment must be exact or None")
|
|
576
|
+
self.memory_dose_assessment.__post_init__()
|
|
577
|
+
expected_rows = tuple(
|
|
578
|
+
_score_member(self.request, value)
|
|
579
|
+
for value in self.request.slate.members
|
|
580
|
+
)
|
|
581
|
+
if self.score_rows != expected_rows:
|
|
582
|
+
raise ValueError("score rows differ from sealed prior calibration")
|
|
583
|
+
expected = _best_anchored_assignment(
|
|
584
|
+
self.request,
|
|
585
|
+
expected_rows,
|
|
586
|
+
model_anchor_count=self.model_anchor_count,
|
|
587
|
+
)
|
|
588
|
+
observed = (
|
|
589
|
+
self.selected,
|
|
590
|
+
self.retained_anchor_option_ids,
|
|
591
|
+
self.calibrated_fill_option_ids,
|
|
592
|
+
self.calibrated_fill_exploitation_score,
|
|
593
|
+
self.calibrated_fill_structural_score,
|
|
594
|
+
self.distinct_family_count,
|
|
595
|
+
self.distinct_locus_count,
|
|
596
|
+
self.distinct_phenotype_count,
|
|
597
|
+
self.administered_card_keys,
|
|
598
|
+
self.feasible_subset_count,
|
|
599
|
+
self.memory_dose_assessment,
|
|
600
|
+
)
|
|
601
|
+
expected_values = (
|
|
602
|
+
expected.selected,
|
|
603
|
+
expected.retained_anchor_option_ids,
|
|
604
|
+
expected.calibrated_fill_option_ids,
|
|
605
|
+
expected.calibrated_fill_exploitation_score,
|
|
606
|
+
expected.calibrated_fill_structural_score,
|
|
607
|
+
expected.distinct_family_count,
|
|
608
|
+
expected.distinct_locus_count,
|
|
609
|
+
expected.distinct_phenotype_count,
|
|
610
|
+
expected.administered_card_keys,
|
|
611
|
+
expected.feasible_subset_count,
|
|
612
|
+
expected.memory_dose_assessment,
|
|
613
|
+
)
|
|
614
|
+
if observed != expected_values:
|
|
615
|
+
raise ValueError("decision differs from exact model-anchored allocation")
|
|
616
|
+
|
|
617
|
+
def revalidate(self) -> None:
|
|
618
|
+
if type(self) is not ModelAnchoredSlateDecision:
|
|
619
|
+
raise TypeError("decision must be exact ModelAnchoredSlateDecision")
|
|
620
|
+
ModelAnchoredSlateDecision.__post_init__(self)
|
|
621
|
+
|
|
622
|
+
@property
|
|
623
|
+
def policy_configuration_sha256(self) -> str:
|
|
624
|
+
return _hash(
|
|
625
|
+
_CONFIGURATION_DOMAIN,
|
|
626
|
+
_configuration_record(self.model_anchor_count),
|
|
627
|
+
)
|
|
628
|
+
|
|
629
|
+
@property
|
|
630
|
+
def prior_only(self) -> bool:
|
|
631
|
+
self.revalidate()
|
|
632
|
+
snapshot = self.request.calibration_snapshot
|
|
633
|
+
assert snapshot is not None
|
|
634
|
+
return all(
|
|
635
|
+
value.prediction.wave_index < self.request.slate.wave_index
|
|
636
|
+
for value in snapshot.observations
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
640
|
+
self.revalidate()
|
|
641
|
+
return {
|
|
642
|
+
"schema_version": 1,
|
|
643
|
+
"event_type": "model_anchored_prior_calibrated_slate_allocated",
|
|
644
|
+
"policy_id": self.policy_id,
|
|
645
|
+
"policy_version": self.policy_version,
|
|
646
|
+
"policy_definition_sha256": self.policy_definition_sha256,
|
|
647
|
+
"policy_configuration": _configuration_record(
|
|
648
|
+
self.model_anchor_count
|
|
649
|
+
),
|
|
650
|
+
"policy_configuration_sha256": (
|
|
651
|
+
self.policy_configuration_sha256
|
|
652
|
+
),
|
|
653
|
+
"request": self.request.to_record(),
|
|
654
|
+
"request_sha256": self.request.request_sha256,
|
|
655
|
+
"calibration_snapshot_sha256": (
|
|
656
|
+
self.request.calibration_snapshot.snapshot_sha256
|
|
657
|
+
if self.request.calibration_snapshot is not None
|
|
658
|
+
else None
|
|
659
|
+
),
|
|
660
|
+
"prior_only": self.prior_only,
|
|
661
|
+
"selection_priority": [
|
|
662
|
+
"retained_model_anchor_count",
|
|
663
|
+
"calibrated_fill_exploitation_sum",
|
|
664
|
+
"calibrated_fill_exploitation_vector",
|
|
665
|
+
"calibrated_fill_structural_sum",
|
|
666
|
+
"distinct_family_count",
|
|
667
|
+
"distinct_locus_count",
|
|
668
|
+
"distinct_phenotype_count",
|
|
669
|
+
"retained_anchor_model_ranks",
|
|
670
|
+
"selected_model_ranks",
|
|
671
|
+
"option_ids",
|
|
672
|
+
],
|
|
673
|
+
"score_rows": [value.to_record() for value in self.score_rows],
|
|
674
|
+
"selected": [value.to_record() for value in self.selected],
|
|
675
|
+
"retained_anchor_option_ids": list(
|
|
676
|
+
self.retained_anchor_option_ids
|
|
677
|
+
),
|
|
678
|
+
"calibrated_fill_option_ids": list(
|
|
679
|
+
self.calibrated_fill_option_ids
|
|
680
|
+
),
|
|
681
|
+
"calibrated_fill_exploitation_score_hex": (
|
|
682
|
+
self.calibrated_fill_exploitation_score.hex()
|
|
683
|
+
),
|
|
684
|
+
"calibrated_fill_structural_score_hex": (
|
|
685
|
+
self.calibrated_fill_structural_score.hex()
|
|
686
|
+
),
|
|
687
|
+
"distinct_family_count": self.distinct_family_count,
|
|
688
|
+
"distinct_locus_count": self.distinct_locus_count,
|
|
689
|
+
"distinct_phenotype_count": self.distinct_phenotype_count,
|
|
690
|
+
"administered_card_keys": list(self.administered_card_keys),
|
|
691
|
+
"feasible_subset_count": self.feasible_subset_count,
|
|
692
|
+
**(
|
|
693
|
+
{}
|
|
694
|
+
if self.memory_dose_assessment is None
|
|
695
|
+
else {
|
|
696
|
+
"memory_dose_assessment": (
|
|
697
|
+
self.memory_dose_assessment.to_record()
|
|
698
|
+
)
|
|
699
|
+
}
|
|
700
|
+
),
|
|
701
|
+
"claim_scope": (
|
|
702
|
+
"replayable_prior_only_allocation_not_efficacy_or_outcome_claim"
|
|
703
|
+
),
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
@property
|
|
707
|
+
def decision_sha256(self) -> str:
|
|
708
|
+
return _hash(_DECISION_DOMAIN, self._unsigned_record())
|
|
709
|
+
|
|
710
|
+
def to_record(self) -> dict[str, object]:
|
|
711
|
+
return {
|
|
712
|
+
**self._unsigned_record(),
|
|
713
|
+
"decision_sha256": self.decision_sha256,
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
def __eq__(self, other: object) -> bool:
|
|
717
|
+
return (
|
|
718
|
+
type(other) is ModelAnchoredSlateDecision
|
|
719
|
+
and self.decision_sha256 == other.decision_sha256
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
__hash__ = None
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
def _validate_policy_request(
|
|
726
|
+
request: SlateAllocationRequest,
|
|
727
|
+
model_anchor_count: int,
|
|
728
|
+
) -> None:
|
|
729
|
+
if type(model_anchor_count) is not int or not (
|
|
730
|
+
1 <= model_anchor_count <= _PORTFOLIO_SIZE
|
|
731
|
+
):
|
|
732
|
+
raise ValueError("model_anchor_count must lie in [1, 4]")
|
|
733
|
+
if len(request.slate.members) != _SLATE_SIZE:
|
|
734
|
+
raise ValueError("model-anchored policy requires exactly eight slate members")
|
|
735
|
+
if request.portfolio_size != _PORTFOLIO_SIZE:
|
|
736
|
+
raise ValueError("model-anchored policy requires exactly four evaluations")
|
|
737
|
+
snapshot = request.calibration_snapshot
|
|
738
|
+
if snapshot is None:
|
|
739
|
+
raise ValueError("model-anchored policy requires a calibration snapshot")
|
|
740
|
+
if snapshot.cutoff_wave_index_exclusive > request.slate.wave_index:
|
|
741
|
+
raise ValueError("calibration snapshot cutoff reaches beyond current wave")
|
|
742
|
+
if any(
|
|
743
|
+
value.prediction.wave_index >= request.slate.wave_index
|
|
744
|
+
for value in snapshot.observations
|
|
745
|
+
):
|
|
746
|
+
raise ValueError("calibration snapshot contains current-wave outcome evidence")
|
|
747
|
+
|
|
748
|
+
|
|
749
|
+
@dataclass(frozen=True, slots=True)
|
|
750
|
+
class ModelAnchoredCalibratedSlatePolicy:
|
|
751
|
+
"""Preserve model anchors, then use prior calibration for K4 fill slots."""
|
|
752
|
+
|
|
753
|
+
model_anchor_count: int = 3
|
|
754
|
+
|
|
755
|
+
policy_id: ClassVar[str] = POLICY_ID
|
|
756
|
+
policy_version: ClassVar[int] = POLICY_VERSION
|
|
757
|
+
definition_sha256: ClassVar[str] = POLICY_DEFINITION_SHA256
|
|
758
|
+
|
|
759
|
+
def __post_init__(self) -> None:
|
|
760
|
+
if type(self.model_anchor_count) is not int or not (
|
|
761
|
+
1 <= self.model_anchor_count <= _PORTFOLIO_SIZE
|
|
762
|
+
):
|
|
763
|
+
raise ValueError("model_anchor_count must lie in [1, 4]")
|
|
764
|
+
|
|
765
|
+
@property
|
|
766
|
+
def configuration_sha256(self) -> str:
|
|
767
|
+
self.__post_init__()
|
|
768
|
+
return _hash(
|
|
769
|
+
_CONFIGURATION_DOMAIN,
|
|
770
|
+
_configuration_record(self.model_anchor_count),
|
|
771
|
+
)
|
|
772
|
+
|
|
773
|
+
def select(self, request: SlateAllocationRequest) -> ModelAnchoredSlateDecision:
|
|
774
|
+
if type(request) is not SlateAllocationRequest:
|
|
775
|
+
raise TypeError("request must be exact SlateAllocationRequest")
|
|
776
|
+
request.revalidate()
|
|
777
|
+
_validate_policy_request(request, self.model_anchor_count)
|
|
778
|
+
rows = tuple(_score_member(request, value) for value in request.slate.members)
|
|
779
|
+
assignment = _best_anchored_assignment(
|
|
780
|
+
request,
|
|
781
|
+
rows,
|
|
782
|
+
model_anchor_count=self.model_anchor_count,
|
|
783
|
+
)
|
|
784
|
+
return ModelAnchoredSlateDecision(
|
|
785
|
+
request=request,
|
|
786
|
+
model_anchor_count=self.model_anchor_count,
|
|
787
|
+
score_rows=rows,
|
|
788
|
+
selected=assignment.selected,
|
|
789
|
+
retained_anchor_option_ids=assignment.retained_anchor_option_ids,
|
|
790
|
+
calibrated_fill_option_ids=assignment.calibrated_fill_option_ids,
|
|
791
|
+
calibrated_fill_exploitation_score=(
|
|
792
|
+
assignment.calibrated_fill_exploitation_score
|
|
793
|
+
),
|
|
794
|
+
calibrated_fill_structural_score=(
|
|
795
|
+
assignment.calibrated_fill_structural_score
|
|
796
|
+
),
|
|
797
|
+
distinct_family_count=assignment.distinct_family_count,
|
|
798
|
+
distinct_locus_count=assignment.distinct_locus_count,
|
|
799
|
+
distinct_phenotype_count=assignment.distinct_phenotype_count,
|
|
800
|
+
administered_card_keys=assignment.administered_card_keys,
|
|
801
|
+
feasible_subset_count=assignment.feasible_subset_count,
|
|
802
|
+
memory_dose_assessment=assignment.memory_dose_assessment,
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
def to_record(self) -> dict[str, object]:
|
|
806
|
+
self.__post_init__()
|
|
807
|
+
return {
|
|
808
|
+
"policy_id": self.policy_id,
|
|
809
|
+
"policy_version": self.policy_version,
|
|
810
|
+
"definition_sha256": self.definition_sha256,
|
|
811
|
+
"configuration": _configuration_record(self.model_anchor_count),
|
|
812
|
+
"configuration_sha256": self.configuration_sha256,
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
__all__ = [
|
|
817
|
+
"ModelAnchoredAllocatedMember",
|
|
818
|
+
"ModelAnchoredCalibratedSlatePolicy",
|
|
819
|
+
"ModelAnchoredMemberScoreRow",
|
|
820
|
+
"ModelAnchoredMetricScoreRow",
|
|
821
|
+
"ModelAnchoredSlateDecision",
|
|
822
|
+
"ModelAnchoredSlateRole",
|
|
823
|
+
"POLICY_DEFINITION_SHA256",
|
|
824
|
+
"POLICY_ID",
|
|
825
|
+
"POLICY_VERSION",
|
|
826
|
+
]
|