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,91 @@
|
|
|
1
|
+
"""Quality-first allocation that evaluates an entire calibrated slate.
|
|
2
|
+
|
|
3
|
+
The model-facing proposal contract and the evaluator-facing portfolio width
|
|
4
|
+
are deliberately separate concerns. This policy closes that gap by selecting
|
|
5
|
+
every authenticated proposal in model order. It is useful while a campaign is
|
|
6
|
+
still collecting enough outcome evidence to justify a narrower learned
|
|
7
|
+
allocator, and it avoids silently converting proposal quality into an
|
|
8
|
+
allocation failure.
|
|
9
|
+
|
|
10
|
+
The policy is workload neutral: it sees only :class:`SlateAllocationRequest`
|
|
11
|
+
and never inspects option names, workload identifiers, configurations, or
|
|
12
|
+
outcomes.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import hashlib
|
|
18
|
+
from dataclasses import dataclass
|
|
19
|
+
|
|
20
|
+
from agent_evolve.policies.selection.calibrated_slate import (
|
|
21
|
+
SlateAllocationDecision,
|
|
22
|
+
SlateAllocationMode,
|
|
23
|
+
SlateAllocationRequest,
|
|
24
|
+
TraceCalibratedSlatePolicy,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
POLICY_ID = "full_support_calibrated_slate"
|
|
29
|
+
POLICY_VERSION = 1
|
|
30
|
+
POLICY_DEFINITION_SHA256 = hashlib.sha256(
|
|
31
|
+
b"agent-evolve:full-support-calibrated-slate:v1;"
|
|
32
|
+
b"select-entire-authenticated-slate=true;model-order-preserved=true;"
|
|
33
|
+
b"outcome-blind=true;workload-identifiers-unused=true;"
|
|
34
|
+
b"quality-first-evidence-acquisition=true"
|
|
35
|
+
).hexdigest()
|
|
36
|
+
CONFIGURATION_SHA256 = hashlib.sha256(
|
|
37
|
+
b"agent-evolve:full-support-calibrated-slate-configuration:v1;"
|
|
38
|
+
b"selection-scope=entire-authenticated-slate;"
|
|
39
|
+
b"outcome-access=false;workload-identifier-access=false"
|
|
40
|
+
).hexdigest()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True, slots=True)
|
|
44
|
+
class FullSupportSlatePolicy:
|
|
45
|
+
"""Select every member of a finite calibrated slate in model order."""
|
|
46
|
+
|
|
47
|
+
policy_id = POLICY_ID
|
|
48
|
+
policy_version = POLICY_VERSION
|
|
49
|
+
definition_sha256 = POLICY_DEFINITION_SHA256
|
|
50
|
+
configuration_sha256 = CONFIGURATION_SHA256
|
|
51
|
+
|
|
52
|
+
def __post_init__(self) -> None:
|
|
53
|
+
if type(self) is not FullSupportSlatePolicy:
|
|
54
|
+
raise TypeError("full-support policy must be exact")
|
|
55
|
+
|
|
56
|
+
def revalidate(self) -> None:
|
|
57
|
+
self.__post_init__()
|
|
58
|
+
|
|
59
|
+
def select(self, request: SlateAllocationRequest) -> SlateAllocationDecision:
|
|
60
|
+
self.__post_init__()
|
|
61
|
+
if type(request) is not SlateAllocationRequest:
|
|
62
|
+
raise TypeError("request must be exact SlateAllocationRequest")
|
|
63
|
+
request.revalidate()
|
|
64
|
+
if request.portfolio_size != len(request.slate.members):
|
|
65
|
+
raise ValueError(
|
|
66
|
+
"full-support allocation requires portfolio_size equal to slate size"
|
|
67
|
+
)
|
|
68
|
+
return TraceCalibratedSlatePolicy(
|
|
69
|
+
SlateAllocationMode.DIRECT_MODEL_TOP_K
|
|
70
|
+
).select(request)
|
|
71
|
+
|
|
72
|
+
def to_record(self) -> dict[str, object]:
|
|
73
|
+
self.__post_init__()
|
|
74
|
+
return {
|
|
75
|
+
"policy_id": self.policy_id,
|
|
76
|
+
"policy_version": self.policy_version,
|
|
77
|
+
"definition_sha256": self.definition_sha256,
|
|
78
|
+
"configuration_sha256": self.configuration_sha256,
|
|
79
|
+
"selection_scope": "entire_authenticated_slate",
|
|
80
|
+
"outcome_access": False,
|
|
81
|
+
"workload_identifier_access": False,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
__all__ = [
|
|
86
|
+
"CONFIGURATION_SHA256",
|
|
87
|
+
"POLICY_DEFINITION_SHA256",
|
|
88
|
+
"POLICY_ID",
|
|
89
|
+
"POLICY_VERSION",
|
|
90
|
+
"FullSupportSlatePolicy",
|
|
91
|
+
]
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"""Workload-neutral adjudication of meaningful metric directions.
|
|
2
|
+
|
|
3
|
+
Benchmarks publish one explicit absolute resolution per metric. The policy
|
|
4
|
+
turns an exact parent/child contrast into the categorical vocabulary used by
|
|
5
|
+
forecast calibration. This is an identified scientific policy, not a
|
|
6
|
+
universal floating-point epsilon.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import hashlib
|
|
12
|
+
import json
|
|
13
|
+
import math
|
|
14
|
+
import re
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
|
|
17
|
+
from agent_evolve.core.optimization_semantics import OptimizationSemantics
|
|
18
|
+
from agent_evolve.domain.patch import require_sha256
|
|
19
|
+
from agent_evolve.policies.selection.forecast_calibration import (
|
|
20
|
+
MeaningfulDirectionAdjudicationReceipt,
|
|
21
|
+
MeaningfulDirectionRequest,
|
|
22
|
+
)
|
|
23
|
+
from agent_evolve.ports.agentic_generator import MetricEffectDirection
|
|
24
|
+
from agent_evolve.ports.decision_metric_projection import DecisionMetricProjection
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
_METRIC = re.compile(r"^[a-z][a-z0-9_.:-]{0,191}$")
|
|
28
|
+
_DEFINITION_DOMAIN = b"agent-evolve:absolute-metric-direction:def:v1\x00"
|
|
29
|
+
POLICY_ID = "absolute_tolerance_metric_direction"
|
|
30
|
+
POLICY_VERSION = 1
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _canonical_json(value: object) -> bytes:
|
|
34
|
+
return json.dumps(
|
|
35
|
+
value,
|
|
36
|
+
allow_nan=False,
|
|
37
|
+
ensure_ascii=True,
|
|
38
|
+
separators=(",", ":"),
|
|
39
|
+
sort_keys=True,
|
|
40
|
+
).encode("ascii", errors="strict")
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass(frozen=True, slots=True)
|
|
44
|
+
class MetricDirectionResolution:
|
|
45
|
+
"""One metric's prospectively declared indistinguishable change band."""
|
|
46
|
+
|
|
47
|
+
metric_id: str
|
|
48
|
+
absolute_tolerance: float
|
|
49
|
+
|
|
50
|
+
def __post_init__(self) -> None:
|
|
51
|
+
if type(self.metric_id) is not str or _METRIC.fullmatch(self.metric_id) is None:
|
|
52
|
+
raise ValueError("metric_id must use the closed metric grammar")
|
|
53
|
+
if (
|
|
54
|
+
type(self.absolute_tolerance) is not float
|
|
55
|
+
or not math.isfinite(self.absolute_tolerance)
|
|
56
|
+
or self.absolute_tolerance < 0.0
|
|
57
|
+
):
|
|
58
|
+
raise ValueError("absolute_tolerance must be a finite non-negative float")
|
|
59
|
+
|
|
60
|
+
def to_record(self) -> dict[str, str]:
|
|
61
|
+
self.__post_init__()
|
|
62
|
+
return {
|
|
63
|
+
"metric_id": self.metric_id,
|
|
64
|
+
"absolute_tolerance_hex": self.absolute_tolerance.hex(),
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
@dataclass(frozen=True, slots=True)
|
|
69
|
+
class AbsoluteToleranceDirectionAdjudicator:
|
|
70
|
+
"""Classify exact parent/child deltas under declared metric resolutions."""
|
|
71
|
+
|
|
72
|
+
benchmark_sha256: str
|
|
73
|
+
session_sha256: str
|
|
74
|
+
resolutions: tuple[MetricDirectionResolution, ...]
|
|
75
|
+
policy_id: str = field(init=False, default=POLICY_ID)
|
|
76
|
+
policy_version: int = field(init=False, default=POLICY_VERSION)
|
|
77
|
+
definition_sha256: str = field(init=False, default="")
|
|
78
|
+
|
|
79
|
+
def __post_init__(self) -> None:
|
|
80
|
+
require_sha256(self.benchmark_sha256, "benchmark_sha256")
|
|
81
|
+
require_sha256(self.session_sha256, "session_sha256")
|
|
82
|
+
if (
|
|
83
|
+
type(self.resolutions) is not tuple
|
|
84
|
+
or not self.resolutions
|
|
85
|
+
or any(
|
|
86
|
+
type(value) is not MetricDirectionResolution
|
|
87
|
+
for value in self.resolutions
|
|
88
|
+
)
|
|
89
|
+
):
|
|
90
|
+
raise ValueError("resolutions must contain exact metric resolutions")
|
|
91
|
+
for value in self.resolutions:
|
|
92
|
+
value.__post_init__()
|
|
93
|
+
if self.resolutions != tuple(
|
|
94
|
+
sorted(self.resolutions, key=lambda value: value.metric_id)
|
|
95
|
+
):
|
|
96
|
+
raise ValueError("resolutions must use canonical metric order")
|
|
97
|
+
if len({value.metric_id for value in self.resolutions}) != len(
|
|
98
|
+
self.resolutions
|
|
99
|
+
):
|
|
100
|
+
raise ValueError("resolutions cannot repeat a metric")
|
|
101
|
+
definition = {
|
|
102
|
+
"schema_version": 1,
|
|
103
|
+
"policy_id": self.policy_id,
|
|
104
|
+
"policy_version": self.policy_version,
|
|
105
|
+
"comparison": "absolute_child_minus_parent",
|
|
106
|
+
"unchanged_rule": "absolute_delta_lte_declared_tolerance",
|
|
107
|
+
"resolutions": [value.to_record() for value in self.resolutions],
|
|
108
|
+
}
|
|
109
|
+
computed = hashlib.sha256(
|
|
110
|
+
_DEFINITION_DOMAIN + _canonical_json(definition)
|
|
111
|
+
).hexdigest()
|
|
112
|
+
if self.definition_sha256 not in ("", computed):
|
|
113
|
+
raise ValueError("definition_sha256 differs from the resolution policy")
|
|
114
|
+
object.__setattr__(self, "definition_sha256", computed)
|
|
115
|
+
|
|
116
|
+
@classmethod
|
|
117
|
+
def from_optimization_semantics(
|
|
118
|
+
cls,
|
|
119
|
+
*,
|
|
120
|
+
benchmark_sha256: str,
|
|
121
|
+
session_sha256: str,
|
|
122
|
+
semantics: OptimizationSemantics,
|
|
123
|
+
) -> "AbsoluteToleranceDirectionAdjudicator":
|
|
124
|
+
"""Bind every projected decision metric with an explicit tolerance.
|
|
125
|
+
|
|
126
|
+
Objective-only semantics retain the historical unprefixed objective
|
|
127
|
+
names. Mixed objective/violation/constraint semantics use their exact
|
|
128
|
+
role-prefixed IDs through :class:`DecisionMetricProjection`.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
if type(semantics) is not OptimizationSemantics:
|
|
132
|
+
raise TypeError("semantics must be exact OptimizationSemantics")
|
|
133
|
+
semantics.__post_init__()
|
|
134
|
+
return cls.from_decision_metric_projection(
|
|
135
|
+
benchmark_sha256=benchmark_sha256,
|
|
136
|
+
session_sha256=session_sha256,
|
|
137
|
+
projection=DecisionMetricProjection.from_optimization_semantics(semantics),
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
@classmethod
|
|
141
|
+
def from_decision_metric_projection(
|
|
142
|
+
cls,
|
|
143
|
+
*,
|
|
144
|
+
benchmark_sha256: str,
|
|
145
|
+
session_sha256: str,
|
|
146
|
+
projection: DecisionMetricProjection,
|
|
147
|
+
) -> "AbsoluteToleranceDirectionAdjudicator":
|
|
148
|
+
"""Construct the adjudicator from the same projection used at feedback."""
|
|
149
|
+
|
|
150
|
+
if type(projection) is not DecisionMetricProjection:
|
|
151
|
+
raise TypeError("projection must be exact DecisionMetricProjection")
|
|
152
|
+
projection.__post_init__()
|
|
153
|
+
missing = tuple(
|
|
154
|
+
metric.metric_id
|
|
155
|
+
for metric in projection.metrics
|
|
156
|
+
if metric.absolute_tolerance is None
|
|
157
|
+
)
|
|
158
|
+
if missing:
|
|
159
|
+
raise ValueError(
|
|
160
|
+
"decision metrics require explicit direction tolerances: "
|
|
161
|
+
+ ", ".join(sorted(missing))
|
|
162
|
+
)
|
|
163
|
+
return cls(
|
|
164
|
+
benchmark_sha256=benchmark_sha256,
|
|
165
|
+
session_sha256=session_sha256,
|
|
166
|
+
resolutions=tuple(
|
|
167
|
+
sorted(
|
|
168
|
+
(
|
|
169
|
+
MetricDirectionResolution(
|
|
170
|
+
metric_id=metric.metric_id,
|
|
171
|
+
absolute_tolerance=float(metric.absolute_tolerance),
|
|
172
|
+
)
|
|
173
|
+
for metric in projection.metrics
|
|
174
|
+
),
|
|
175
|
+
key=lambda value: value.metric_id,
|
|
176
|
+
)
|
|
177
|
+
),
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
def to_record(self) -> dict[str, object]:
|
|
181
|
+
self.__post_init__()
|
|
182
|
+
return {
|
|
183
|
+
"policy_id": self.policy_id,
|
|
184
|
+
"policy_version": self.policy_version,
|
|
185
|
+
"definition_sha256": self.definition_sha256,
|
|
186
|
+
"benchmark_sha256": self.benchmark_sha256,
|
|
187
|
+
"session_sha256": self.session_sha256,
|
|
188
|
+
"resolutions": [value.to_record() for value in self.resolutions],
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
def adjudicate(
|
|
192
|
+
self,
|
|
193
|
+
request: MeaningfulDirectionRequest,
|
|
194
|
+
) -> MeaningfulDirectionAdjudicationReceipt:
|
|
195
|
+
self.__post_init__()
|
|
196
|
+
if type(request) is not MeaningfulDirectionRequest:
|
|
197
|
+
raise TypeError("request must be exact MeaningfulDirectionRequest")
|
|
198
|
+
request.revalidate()
|
|
199
|
+
if (
|
|
200
|
+
request.benchmark_sha256 != self.benchmark_sha256
|
|
201
|
+
or request.session_sha256 != self.session_sha256
|
|
202
|
+
):
|
|
203
|
+
raise ValueError("direction request belongs to a foreign benchmark session")
|
|
204
|
+
tolerance_by_metric = {
|
|
205
|
+
value.metric_id: value.absolute_tolerance for value in self.resolutions
|
|
206
|
+
}
|
|
207
|
+
if request.metric_id not in tolerance_by_metric:
|
|
208
|
+
raise ValueError("direction request names an undeclared metric")
|
|
209
|
+
delta = request.child_metric_value - request.parent_metric_value
|
|
210
|
+
tolerance = tolerance_by_metric[request.metric_id]
|
|
211
|
+
if abs(delta) <= tolerance:
|
|
212
|
+
direction = MetricEffectDirection.UNCHANGED
|
|
213
|
+
elif delta < 0.0:
|
|
214
|
+
direction = MetricEffectDirection.DECREASE
|
|
215
|
+
else:
|
|
216
|
+
direction = MetricEffectDirection.INCREASE
|
|
217
|
+
return MeaningfulDirectionAdjudicationReceipt(
|
|
218
|
+
request_sha256=request.request_sha256,
|
|
219
|
+
benchmark_sha256=request.benchmark_sha256,
|
|
220
|
+
session_sha256=request.session_sha256,
|
|
221
|
+
wave_index=request.wave_index,
|
|
222
|
+
parent_candidate_identity_sha256=(request.parent_candidate_identity_sha256),
|
|
223
|
+
option_id=request.option_id,
|
|
224
|
+
option_identity_sha256=request.option_identity_sha256,
|
|
225
|
+
metric_id=request.metric_id,
|
|
226
|
+
parent_outcome_sha256=request.parent_outcome_sha256,
|
|
227
|
+
child_outcome_sha256=request.child_outcome_sha256,
|
|
228
|
+
actual_direction=direction,
|
|
229
|
+
adjudicator_policy_id=self.policy_id,
|
|
230
|
+
adjudicator_policy_version=self.policy_version,
|
|
231
|
+
adjudicator_definition_sha256=self.definition_sha256,
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
__all__ = [
|
|
236
|
+
"AbsoluteToleranceDirectionAdjudicator",
|
|
237
|
+
"MetricDirectionResolution",
|
|
238
|
+
"POLICY_ID",
|
|
239
|
+
"POLICY_VERSION",
|
|
240
|
+
]
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"""Workload-neutral exact feasibility for bounded memory-dose attribution.
|
|
2
|
+
|
|
3
|
+
The portfolio reconciler must know whether a structural evaluation subset can
|
|
4
|
+
also carry the prospectively declared card dose. This module answers only
|
|
5
|
+
that finite constraint question. It never sees objective values, workload
|
|
6
|
+
identifiers, model/provider metadata, or natural-language card content.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
import hashlib
|
|
12
|
+
import json
|
|
13
|
+
from dataclasses import dataclass, field
|
|
14
|
+
from itertools import combinations
|
|
15
|
+
|
|
16
|
+
from agent_evolve.domain.patch import require_sha256
|
|
17
|
+
from agent_evolve.ports.portfolio_memory_dose import (
|
|
18
|
+
BoundedPortfolioMemoryDoseContract,
|
|
19
|
+
PortfolioMemoryDoseStage,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
POLICY_ID = "exact_bounded_memory_dose_attribution_feasibility"
|
|
24
|
+
POLICY_VERSION = 1
|
|
25
|
+
POLICY_DEFINITION_SHA256 = hashlib.sha256(
|
|
26
|
+
b"agent-evolve:exact-bounded-memory-dose-attribution-feasibility:v1;"
|
|
27
|
+
b"input=finite-option-identities,bounded-card-support-contract,stage;"
|
|
28
|
+
b"constraints=compatibility,member-bounds,unattributed-floor,max-cards,card-cover;"
|
|
29
|
+
b"objective=first-canonical-minimum-dose-witness;"
|
|
30
|
+
b"objective-values=false;workload-model-provider-identifiers=false"
|
|
31
|
+
).hexdigest()
|
|
32
|
+
_DOMAIN = b"agent-evolve:memory-dose-attribution-feasibility-witness:v1\x00"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _canonical_json(value: object) -> bytes:
|
|
36
|
+
return json.dumps(
|
|
37
|
+
value,
|
|
38
|
+
allow_nan=False,
|
|
39
|
+
ensure_ascii=True,
|
|
40
|
+
separators=(",", ":"),
|
|
41
|
+
sort_keys=True,
|
|
42
|
+
).encode("ascii", errors="strict")
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True, slots=True)
|
|
46
|
+
class MemoryDoseAttributionFeasibilityWitness:
|
|
47
|
+
"""One exact card assignment for a fixed finite member subset."""
|
|
48
|
+
|
|
49
|
+
contract_sha256: str
|
|
50
|
+
stage: PortfolioMemoryDoseStage
|
|
51
|
+
member_option_identities: tuple[tuple[str, str], ...]
|
|
52
|
+
attributions: tuple[tuple[str, tuple[str, ...]], ...]
|
|
53
|
+
witness_sha256: str = field(init=False)
|
|
54
|
+
|
|
55
|
+
def __post_init__(self) -> None:
|
|
56
|
+
require_sha256(self.contract_sha256, "contract_sha256")
|
|
57
|
+
if type(self.stage) is not PortfolioMemoryDoseStage:
|
|
58
|
+
raise TypeError("stage must be exact PortfolioMemoryDoseStage")
|
|
59
|
+
if type(self.member_option_identities) is not tuple or any(
|
|
60
|
+
type(value) is not tuple
|
|
61
|
+
or len(value) != 2
|
|
62
|
+
or type(value[0]) is not str
|
|
63
|
+
or not value[0]
|
|
64
|
+
or type(value[1]) is not str
|
|
65
|
+
for value in self.member_option_identities
|
|
66
|
+
):
|
|
67
|
+
raise TypeError("member_option_identities must contain exact pairs")
|
|
68
|
+
for _, identity_sha256 in self.member_option_identities:
|
|
69
|
+
require_sha256(identity_sha256, "option_identity_sha256")
|
|
70
|
+
if self.member_option_identities != tuple(
|
|
71
|
+
sorted(set(self.member_option_identities))
|
|
72
|
+
):
|
|
73
|
+
raise ValueError(
|
|
74
|
+
"member_option_identities must be unique and canonical"
|
|
75
|
+
)
|
|
76
|
+
option_ids = tuple(value[0] for value in self.member_option_identities)
|
|
77
|
+
identity_sha256s = tuple(
|
|
78
|
+
value[1] for value in self.member_option_identities
|
|
79
|
+
)
|
|
80
|
+
if len(set(option_ids)) != len(option_ids):
|
|
81
|
+
raise ValueError("member option IDs must be unique")
|
|
82
|
+
if len(set(identity_sha256s)) != len(identity_sha256s):
|
|
83
|
+
raise ValueError("member option identities must be unique")
|
|
84
|
+
if type(self.attributions) is not tuple or any(
|
|
85
|
+
type(value) is not tuple
|
|
86
|
+
or len(value) != 2
|
|
87
|
+
or type(value[0]) is not str
|
|
88
|
+
or not value[0]
|
|
89
|
+
or type(value[1]) is not tuple
|
|
90
|
+
or any(type(card) is not str or not card for card in value[1])
|
|
91
|
+
or value[1] != tuple(sorted(set(value[1])))
|
|
92
|
+
for value in self.attributions
|
|
93
|
+
):
|
|
94
|
+
raise TypeError("attributions must contain canonical exact values")
|
|
95
|
+
if tuple(value[0] for value in self.attributions) != tuple(
|
|
96
|
+
value[0] for value in self.member_option_identities
|
|
97
|
+
):
|
|
98
|
+
raise ValueError("attributions differ from the witnessed members")
|
|
99
|
+
object.__setattr__(
|
|
100
|
+
self,
|
|
101
|
+
"witness_sha256",
|
|
102
|
+
hashlib.sha256(_DOMAIN + _canonical_json(self._unsigned_record())).hexdigest(),
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def supported_member_count(self) -> int:
|
|
107
|
+
return sum(bool(cards) for _, cards in self.attributions)
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def unattributed_member_count(self) -> int:
|
|
111
|
+
return len(self.attributions) - self.supported_member_count
|
|
112
|
+
|
|
113
|
+
@property
|
|
114
|
+
def covered_card_keys(self) -> tuple[str, ...]:
|
|
115
|
+
return tuple(
|
|
116
|
+
sorted({card for _, cards in self.attributions for card in cards})
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
120
|
+
return {
|
|
121
|
+
"schema_version": 1,
|
|
122
|
+
"policy": {
|
|
123
|
+
"policy_id": POLICY_ID,
|
|
124
|
+
"policy_version": POLICY_VERSION,
|
|
125
|
+
"definition_sha256": POLICY_DEFINITION_SHA256,
|
|
126
|
+
},
|
|
127
|
+
"contract_sha256": self.contract_sha256,
|
|
128
|
+
"stage": self.stage.value,
|
|
129
|
+
"members": [
|
|
130
|
+
{
|
|
131
|
+
"option_id": option_id,
|
|
132
|
+
"option_identity_sha256": identity_sha256,
|
|
133
|
+
"supporting_card_keys": list(cards),
|
|
134
|
+
}
|
|
135
|
+
for (option_id, identity_sha256), (_, cards) in zip(
|
|
136
|
+
self.member_option_identities,
|
|
137
|
+
self.attributions,
|
|
138
|
+
strict=True,
|
|
139
|
+
)
|
|
140
|
+
],
|
|
141
|
+
"supported_member_count": self.supported_member_count,
|
|
142
|
+
"unattributed_member_count": self.unattributed_member_count,
|
|
143
|
+
"covered_card_keys": list(self.covered_card_keys),
|
|
144
|
+
"objective_values_consulted": False,
|
|
145
|
+
"workload_model_provider_identifiers_consulted": False,
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
def to_record(self) -> dict[str, object]:
|
|
149
|
+
self.__post_init__()
|
|
150
|
+
return {**self._unsigned_record(), "witness_sha256": self.witness_sha256}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def find_memory_dose_attribution_feasibility_witness(
|
|
154
|
+
contract: BoundedPortfolioMemoryDoseContract,
|
|
155
|
+
*,
|
|
156
|
+
stage: PortfolioMemoryDoseStage,
|
|
157
|
+
member_option_identities: tuple[tuple[str, str], ...],
|
|
158
|
+
) -> MemoryDoseAttributionFeasibilityWitness | None:
|
|
159
|
+
"""Return the first canonical exact attribution, or ``None`` if impossible."""
|
|
160
|
+
|
|
161
|
+
if type(contract) is not BoundedPortfolioMemoryDoseContract:
|
|
162
|
+
raise TypeError("contract must be exact BoundedPortfolioMemoryDoseContract")
|
|
163
|
+
contract.__post_init__()
|
|
164
|
+
if type(stage) is not PortfolioMemoryDoseStage:
|
|
165
|
+
raise TypeError("stage must be exact PortfolioMemoryDoseStage")
|
|
166
|
+
if type(member_option_identities) is not tuple or any(
|
|
167
|
+
type(value) is not tuple or len(value) != 2 for value in member_option_identities
|
|
168
|
+
):
|
|
169
|
+
raise TypeError("member_option_identities must contain exact pairs")
|
|
170
|
+
members = tuple(sorted(member_option_identities))
|
|
171
|
+
# Construction performs the complete boundary validation once.
|
|
172
|
+
provisional = MemoryDoseAttributionFeasibilityWitness(
|
|
173
|
+
contract_sha256=contract.contract_sha256,
|
|
174
|
+
stage=stage,
|
|
175
|
+
member_option_identities=members,
|
|
176
|
+
attributions=tuple((option_id, ()) for option_id, _ in members),
|
|
177
|
+
)
|
|
178
|
+
del provisional
|
|
179
|
+
|
|
180
|
+
lower, upper = contract.bounds_for(stage)
|
|
181
|
+
maximum_supported = min(
|
|
182
|
+
upper,
|
|
183
|
+
len(members) - contract.minimum_unattributed_for(stage),
|
|
184
|
+
)
|
|
185
|
+
if lower > maximum_supported:
|
|
186
|
+
return None
|
|
187
|
+
assigned_cards = contract.assigned_card_keys
|
|
188
|
+
support_by_card = {value.card_key: value for value in contract.card_supports}
|
|
189
|
+
choices: list[tuple[tuple[str, ...], ...]] = []
|
|
190
|
+
for option_id, identity_sha256 in members:
|
|
191
|
+
compatible = tuple(
|
|
192
|
+
card_key
|
|
193
|
+
for card_key in assigned_cards
|
|
194
|
+
if support_by_card[card_key].supports(option_id, identity_sha256)
|
|
195
|
+
)
|
|
196
|
+
option_choices: list[tuple[str, ...]] = [()]
|
|
197
|
+
for count in range(
|
|
198
|
+
1,
|
|
199
|
+
min(len(compatible), contract.maximum_cards_per_member) + 1,
|
|
200
|
+
):
|
|
201
|
+
option_choices.extend(combinations(compatible, count))
|
|
202
|
+
choices.append(tuple(option_choices))
|
|
203
|
+
|
|
204
|
+
selected: list[tuple[str, ...]] = []
|
|
205
|
+
result: MemoryDoseAttributionFeasibilityWitness | None = None
|
|
206
|
+
|
|
207
|
+
def search(index: int, supported_count: int, covered: frozenset[str]) -> bool:
|
|
208
|
+
nonlocal result
|
|
209
|
+
remaining = len(members) - index
|
|
210
|
+
if supported_count > maximum_supported:
|
|
211
|
+
return False
|
|
212
|
+
if supported_count + remaining < lower:
|
|
213
|
+
return False
|
|
214
|
+
if contract.require_every_assigned_card:
|
|
215
|
+
future_cover = set(covered)
|
|
216
|
+
for future_choices in choices[index:]:
|
|
217
|
+
for candidate in future_choices:
|
|
218
|
+
future_cover.update(candidate)
|
|
219
|
+
if not set(assigned_cards).issubset(future_cover):
|
|
220
|
+
return False
|
|
221
|
+
if index == len(members):
|
|
222
|
+
if not lower <= supported_count <= maximum_supported:
|
|
223
|
+
return False
|
|
224
|
+
if contract.require_every_assigned_card and set(covered) != set(
|
|
225
|
+
assigned_cards
|
|
226
|
+
):
|
|
227
|
+
return False
|
|
228
|
+
result = MemoryDoseAttributionFeasibilityWitness(
|
|
229
|
+
contract_sha256=contract.contract_sha256,
|
|
230
|
+
stage=stage,
|
|
231
|
+
member_option_identities=members,
|
|
232
|
+
attributions=tuple(
|
|
233
|
+
(option_id, cards)
|
|
234
|
+
for (option_id, _), cards in zip(members, selected, strict=True)
|
|
235
|
+
),
|
|
236
|
+
)
|
|
237
|
+
return True
|
|
238
|
+
for candidate in choices[index]:
|
|
239
|
+
selected.append(candidate)
|
|
240
|
+
if search(
|
|
241
|
+
index + 1,
|
|
242
|
+
supported_count + bool(candidate),
|
|
243
|
+
covered.union(candidate),
|
|
244
|
+
):
|
|
245
|
+
return True
|
|
246
|
+
selected.pop()
|
|
247
|
+
return False
|
|
248
|
+
|
|
249
|
+
search(0, 0, frozenset())
|
|
250
|
+
return result
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
__all__ = [
|
|
254
|
+
"MemoryDoseAttributionFeasibilityWitness",
|
|
255
|
+
"POLICY_DEFINITION_SHA256",
|
|
256
|
+
"POLICY_ID",
|
|
257
|
+
"POLICY_VERSION",
|
|
258
|
+
"find_memory_dose_attribution_feasibility_witness",
|
|
259
|
+
]
|