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,940 @@
|
|
|
1
|
+
"""Generic propose-once, evaluate-pilot, choose-branch residual evolution.
|
|
2
|
+
|
|
3
|
+
Every proposal, score, semantic cell, pilot action, and complete continuation
|
|
4
|
+
branch is sealed before the first current candidate is evaluated. A typed
|
|
5
|
+
pilot projector then exposes only real marginal archive contribution to a
|
|
6
|
+
small gate. The chosen pre-existing branch is evaluated without re-querying a
|
|
7
|
+
model or regenerating the universe.
|
|
8
|
+
|
|
9
|
+
This service is workload-, objective-, model-, provider-, and prompt-blind.
|
|
10
|
+
Those concerns remain behind proposal experts, the pilot-outcome projector,
|
|
11
|
+
and the already established archive/evaluator ports.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import hashlib
|
|
17
|
+
import json
|
|
18
|
+
import re
|
|
19
|
+
from dataclasses import dataclass, field
|
|
20
|
+
from enum import Enum
|
|
21
|
+
from typing import Protocol, runtime_checkable
|
|
22
|
+
|
|
23
|
+
from agent_evolve.application.materialized_action_broker import (
|
|
24
|
+
MaterializedActionBrokerRequest,
|
|
25
|
+
MaterializedSlateFeasibilityPort,
|
|
26
|
+
MaterializedSlateValuePort,
|
|
27
|
+
RegretBrokeredMaterializedActionPolicy,
|
|
28
|
+
)
|
|
29
|
+
from agent_evolve.application.residual_portfolio_evolution import (
|
|
30
|
+
DISJOINT_ACTION_EVALUATION_WAVES_V1,
|
|
31
|
+
MaterializedActionEvaluation,
|
|
32
|
+
MaterializedActionEvaluationBatch,
|
|
33
|
+
MaterializedActionProposalBatch,
|
|
34
|
+
MaterializedActionProposalExpertPort,
|
|
35
|
+
ResidualPortfolioDecisionRequest,
|
|
36
|
+
ResidualPortfolioEvolutionResult,
|
|
37
|
+
evaluate_materialized_action_subset,
|
|
38
|
+
propose_materialized_action_batches,
|
|
39
|
+
)
|
|
40
|
+
from agent_evolve.application.sequential_lineage_allocation import (
|
|
41
|
+
AnyPositiveSequentialLineageGate,
|
|
42
|
+
SequentialAllocationGateDecisionPort,
|
|
43
|
+
SequentialAllocationGatePort,
|
|
44
|
+
SequentialAllocationPlanPort,
|
|
45
|
+
SequentialLineageAllocationPlannerPort,
|
|
46
|
+
SequentialPilotOutcomeBatch,
|
|
47
|
+
SequentialPilotOutcomeProjectorPort,
|
|
48
|
+
)
|
|
49
|
+
from agent_evolve.domain.patch import require_sha256
|
|
50
|
+
from agent_evolve.domain.typed_json import (
|
|
51
|
+
FrozenJsonObject,
|
|
52
|
+
freeze_json,
|
|
53
|
+
thaw_json,
|
|
54
|
+
typed_json_sha256,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
SEQUENTIAL_RESIDUAL_PORTFOLIO_EVOLUTION_ID = (
|
|
59
|
+
"sequential_residual_portfolio_evolution"
|
|
60
|
+
)
|
|
61
|
+
SEQUENTIAL_RESIDUAL_PORTFOLIO_EVOLUTION_VERSION = 4
|
|
62
|
+
SEQUENTIAL_RESIDUAL_PORTFOLIO_EVOLUTION_DEFINITION_SHA256 = hashlib.sha256(
|
|
63
|
+
b"agent-evolve:sequential-residual-portfolio-evolution:v4;"
|
|
64
|
+
b"proposal-universe=sealed-once-before-current-outcomes;"
|
|
65
|
+
b"branches=one-or-more-complete-slates-frozen-before-pilot;"
|
|
66
|
+
b"pilot=planner-authenticated-action-subset;"
|
|
67
|
+
b"gate=injected-precommitted-branch-decision-port;"
|
|
68
|
+
b"continuation=no-regeneration-no-rescoring-no-provider-call;"
|
|
69
|
+
b"execution=pilot-then-chosen-remaining-actions;"
|
|
70
|
+
b"exactly-once-boundary=disjoint-actions-not-proposal-batches;"
|
|
71
|
+
b"failed-wave-reservation=fail-closed;"
|
|
72
|
+
b"archive-publication=combined-final-slate-only;"
|
|
73
|
+
b"durability=optional-or-required-plan-pilot-evaluated-adjudicated-final-commit-port;"
|
|
74
|
+
b"workload-objective-model-provider-prompt-branches=false"
|
|
75
|
+
).hexdigest()
|
|
76
|
+
|
|
77
|
+
_TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
|
|
78
|
+
_PHASE_RECEIPT_DOMAIN = (
|
|
79
|
+
b"agent-evolve:sequential-residual-phase-receipt:v1\x00"
|
|
80
|
+
)
|
|
81
|
+
_PHASE_ACK_DOMAIN = b"agent-evolve:sequential-residual-phase-ack:v1\x00"
|
|
82
|
+
_RESULT_DOMAIN = b"agent-evolve:sequential-residual-result:v1\x00"
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _canonical_json(value: object) -> bytes:
|
|
86
|
+
return json.dumps(
|
|
87
|
+
value,
|
|
88
|
+
allow_nan=False,
|
|
89
|
+
ensure_ascii=True,
|
|
90
|
+
separators=(",", ":"),
|
|
91
|
+
sort_keys=True,
|
|
92
|
+
).encode("ascii", errors="strict")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _hash(domain: bytes, value: object) -> str:
|
|
96
|
+
return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _require_token(value: str, *, name: str) -> None:
|
|
100
|
+
if type(value) is not str or _TOKEN.fullmatch(value) is None:
|
|
101
|
+
raise ValueError(f"{name} must use the closed token grammar")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _planner_identity(
|
|
105
|
+
value: SequentialLineageAllocationPlannerPort,
|
|
106
|
+
) -> tuple[str, int, str]:
|
|
107
|
+
if not isinstance(value, SequentialLineageAllocationPlannerPort):
|
|
108
|
+
raise TypeError("planner must implement its application port")
|
|
109
|
+
identity = (
|
|
110
|
+
getattr(value, "planner_id", None),
|
|
111
|
+
getattr(value, "planner_version", None),
|
|
112
|
+
getattr(value, "definition_sha256", None),
|
|
113
|
+
)
|
|
114
|
+
_require_token(identity[0], name="planner_id")
|
|
115
|
+
if type(identity[1]) is not int or identity[1] <= 0:
|
|
116
|
+
raise ValueError("planner_version must be positive")
|
|
117
|
+
require_sha256(identity[2], "planner definition_sha256")
|
|
118
|
+
return identity # type: ignore[return-value]
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _projector_identity(
|
|
122
|
+
value: SequentialPilotOutcomeProjectorPort,
|
|
123
|
+
) -> tuple[str, int, str]:
|
|
124
|
+
if not isinstance(value, SequentialPilotOutcomeProjectorPort):
|
|
125
|
+
raise TypeError("pilot projector must implement its application port")
|
|
126
|
+
identity = (
|
|
127
|
+
getattr(value, "projector_id", None),
|
|
128
|
+
getattr(value, "projector_version", None),
|
|
129
|
+
getattr(value, "definition_sha256", None),
|
|
130
|
+
)
|
|
131
|
+
_require_token(identity[0], name="projector_id")
|
|
132
|
+
if type(identity[1]) is not int or identity[1] <= 0:
|
|
133
|
+
raise ValueError("projector_version must be positive")
|
|
134
|
+
require_sha256(identity[2], "projector definition_sha256")
|
|
135
|
+
return identity # type: ignore[return-value]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _gate_identity(
|
|
139
|
+
value: SequentialAllocationGatePort,
|
|
140
|
+
) -> tuple[str, int, str]:
|
|
141
|
+
if not isinstance(value, SequentialAllocationGatePort):
|
|
142
|
+
raise TypeError("gate must implement its application port")
|
|
143
|
+
identity = (
|
|
144
|
+
getattr(value, "gate_id", None),
|
|
145
|
+
getattr(value, "gate_version", None),
|
|
146
|
+
getattr(value, "definition_sha256", None),
|
|
147
|
+
)
|
|
148
|
+
_require_token(identity[0], name="gate_id")
|
|
149
|
+
if type(identity[1]) is not int or identity[1] <= 0:
|
|
150
|
+
raise ValueError("gate_version must be positive")
|
|
151
|
+
require_sha256(identity[2], "gate definition_sha256")
|
|
152
|
+
return identity # type: ignore[return-value]
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
class SequentialResidualPhase(str, Enum):
|
|
156
|
+
PLAN_FROZEN = "plan_frozen"
|
|
157
|
+
PILOT_EVALUATED = "pilot_evaluated"
|
|
158
|
+
PILOT_ADJUDICATED = "pilot_adjudicated"
|
|
159
|
+
FINALIZED = "finalized"
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
@dataclass(frozen=True, slots=True)
|
|
163
|
+
class SequentialResidualPhaseReceipt:
|
|
164
|
+
"""One hash-bound interception boundary in a sequential stage."""
|
|
165
|
+
|
|
166
|
+
phase: SequentialResidualPhase
|
|
167
|
+
residual_request_sha256: str
|
|
168
|
+
plan_sha256: str
|
|
169
|
+
product_sha256s: tuple[str, ...]
|
|
170
|
+
evidence: FrozenJsonObject
|
|
171
|
+
receipt_sha256: str = field(init=False)
|
|
172
|
+
|
|
173
|
+
def __post_init__(self) -> None:
|
|
174
|
+
if type(self.phase) is not SequentialResidualPhase:
|
|
175
|
+
raise TypeError("phase must be an exact SequentialResidualPhase")
|
|
176
|
+
require_sha256(
|
|
177
|
+
self.residual_request_sha256,
|
|
178
|
+
"residual_request_sha256",
|
|
179
|
+
)
|
|
180
|
+
require_sha256(self.plan_sha256, "plan_sha256")
|
|
181
|
+
if (
|
|
182
|
+
type(self.product_sha256s) is not tuple
|
|
183
|
+
or not self.product_sha256s
|
|
184
|
+
):
|
|
185
|
+
raise ValueError("product_sha256s must be a non-empty exact tuple")
|
|
186
|
+
for value in self.product_sha256s:
|
|
187
|
+
require_sha256(value, "product_sha256")
|
|
188
|
+
if (
|
|
189
|
+
type(self.evidence) is not FrozenJsonObject
|
|
190
|
+
or freeze_json(self.evidence) is not self.evidence
|
|
191
|
+
):
|
|
192
|
+
raise TypeError("phase evidence must be an exact frozen object")
|
|
193
|
+
object.__setattr__(
|
|
194
|
+
self,
|
|
195
|
+
"receipt_sha256",
|
|
196
|
+
_hash(_PHASE_RECEIPT_DOMAIN, self._unsigned_record()),
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
200
|
+
return {
|
|
201
|
+
"schema_version": 1,
|
|
202
|
+
"phase": self.phase.value,
|
|
203
|
+
"residual_request_sha256": self.residual_request_sha256,
|
|
204
|
+
"plan_sha256": self.plan_sha256,
|
|
205
|
+
"product_sha256s": list(self.product_sha256s),
|
|
206
|
+
"evidence_sha256": typed_json_sha256(self.evidence),
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
|
|
210
|
+
self.__post_init__()
|
|
211
|
+
record = {
|
|
212
|
+
**self._unsigned_record(),
|
|
213
|
+
"receipt_sha256": self.receipt_sha256,
|
|
214
|
+
}
|
|
215
|
+
if include_evidence:
|
|
216
|
+
record["evidence"] = thaw_json(self.evidence)
|
|
217
|
+
return record
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
@dataclass(frozen=True, slots=True)
|
|
221
|
+
class SequentialResidualPhaseCommitAck:
|
|
222
|
+
"""Proof that a supplied interception boundary accepted one receipt."""
|
|
223
|
+
|
|
224
|
+
committer_id: str
|
|
225
|
+
committer_version: int
|
|
226
|
+
committer_definition_sha256: str
|
|
227
|
+
phase_receipt_sha256: str
|
|
228
|
+
durable: bool
|
|
229
|
+
evidence: FrozenJsonObject
|
|
230
|
+
ack_sha256: str = field(init=False)
|
|
231
|
+
|
|
232
|
+
def __post_init__(self) -> None:
|
|
233
|
+
_require_token(self.committer_id, name="committer_id")
|
|
234
|
+
if type(self.committer_version) is not int or self.committer_version <= 0:
|
|
235
|
+
raise ValueError("committer_version must be positive")
|
|
236
|
+
require_sha256(
|
|
237
|
+
self.committer_definition_sha256,
|
|
238
|
+
"committer_definition_sha256",
|
|
239
|
+
)
|
|
240
|
+
require_sha256(
|
|
241
|
+
self.phase_receipt_sha256,
|
|
242
|
+
"phase_receipt_sha256",
|
|
243
|
+
)
|
|
244
|
+
if type(self.durable) is not bool:
|
|
245
|
+
raise TypeError("durable must be an exact bool")
|
|
246
|
+
if (
|
|
247
|
+
type(self.evidence) is not FrozenJsonObject
|
|
248
|
+
or freeze_json(self.evidence) is not self.evidence
|
|
249
|
+
):
|
|
250
|
+
raise TypeError("commit evidence must be an exact frozen object")
|
|
251
|
+
object.__setattr__(
|
|
252
|
+
self,
|
|
253
|
+
"ack_sha256",
|
|
254
|
+
_hash(_PHASE_ACK_DOMAIN, self._unsigned_record()),
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
258
|
+
return {
|
|
259
|
+
"schema_version": 1,
|
|
260
|
+
"committer": {
|
|
261
|
+
"committer_id": self.committer_id,
|
|
262
|
+
"committer_version": self.committer_version,
|
|
263
|
+
"definition_sha256": self.committer_definition_sha256,
|
|
264
|
+
},
|
|
265
|
+
"phase_receipt_sha256": self.phase_receipt_sha256,
|
|
266
|
+
"durable": self.durable,
|
|
267
|
+
"evidence_sha256": typed_json_sha256(self.evidence),
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
|
|
271
|
+
self.__post_init__()
|
|
272
|
+
record = {**self._unsigned_record(), "ack_sha256": self.ack_sha256}
|
|
273
|
+
if include_evidence:
|
|
274
|
+
record["evidence"] = thaw_json(self.evidence)
|
|
275
|
+
return record
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
@runtime_checkable
|
|
279
|
+
class SequentialResidualPhaseCommitPort(Protocol):
|
|
280
|
+
"""Durably intercept a sequential phase before later evaluation authority."""
|
|
281
|
+
|
|
282
|
+
committer_id: str
|
|
283
|
+
committer_version: int
|
|
284
|
+
definition_sha256: str
|
|
285
|
+
|
|
286
|
+
async def commit(
|
|
287
|
+
self,
|
|
288
|
+
receipt: SequentialResidualPhaseReceipt,
|
|
289
|
+
) -> SequentialResidualPhaseCommitAck: ...
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
def _committer_identity(
|
|
293
|
+
value: SequentialResidualPhaseCommitPort,
|
|
294
|
+
) -> tuple[str, int, str]:
|
|
295
|
+
if not isinstance(value, SequentialResidualPhaseCommitPort):
|
|
296
|
+
raise TypeError("phase committer must implement its application port")
|
|
297
|
+
identity = (
|
|
298
|
+
getattr(value, "committer_id", None),
|
|
299
|
+
getattr(value, "committer_version", None),
|
|
300
|
+
getattr(value, "definition_sha256", None),
|
|
301
|
+
)
|
|
302
|
+
_require_token(identity[0], name="committer_id")
|
|
303
|
+
if type(identity[1]) is not int or identity[1] <= 0:
|
|
304
|
+
raise ValueError("committer_version must be positive")
|
|
305
|
+
require_sha256(identity[2], "committer definition_sha256")
|
|
306
|
+
return identity # type: ignore[return-value]
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
def _flatten_evaluations(
|
|
310
|
+
batches: tuple[MaterializedActionEvaluationBatch, ...],
|
|
311
|
+
) -> tuple[MaterializedActionEvaluation, ...]:
|
|
312
|
+
by_action = {
|
|
313
|
+
value.action.action_sha256: value
|
|
314
|
+
for batch in batches
|
|
315
|
+
for value in batch.evaluations
|
|
316
|
+
}
|
|
317
|
+
return tuple(by_action[value] for value in sorted(by_action))
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
def _merge_evaluation_waves(
|
|
321
|
+
proposals: tuple[MaterializedActionProposalBatch, ...],
|
|
322
|
+
pilot: tuple[MaterializedActionEvaluationBatch, ...],
|
|
323
|
+
continuation: tuple[MaterializedActionEvaluationBatch, ...],
|
|
324
|
+
) -> tuple[MaterializedActionEvaluationBatch, ...]:
|
|
325
|
+
"""Merge per-wave expert batches without erasing their source receipts."""
|
|
326
|
+
|
|
327
|
+
proposal_by_expert = {value.expert_id: value for value in proposals}
|
|
328
|
+
batches_by_expert: dict[
|
|
329
|
+
str, list[MaterializedActionEvaluationBatch]
|
|
330
|
+
] = {}
|
|
331
|
+
for batch in (*pilot, *continuation):
|
|
332
|
+
batches_by_expert.setdefault(batch.expert_id, []).append(batch)
|
|
333
|
+
merged: list[MaterializedActionEvaluationBatch] = []
|
|
334
|
+
for expert_id in sorted(batches_by_expert):
|
|
335
|
+
source = batches_by_expert[expert_id]
|
|
336
|
+
proposal = proposal_by_expert[expert_id]
|
|
337
|
+
evaluations = tuple(
|
|
338
|
+
sorted(
|
|
339
|
+
(
|
|
340
|
+
value
|
|
341
|
+
for batch in source
|
|
342
|
+
for value in batch.evaluations
|
|
343
|
+
),
|
|
344
|
+
key=lambda value: value.action.action_sha256,
|
|
345
|
+
)
|
|
346
|
+
)
|
|
347
|
+
action_ids = tuple(
|
|
348
|
+
value.action.action_sha256 for value in evaluations
|
|
349
|
+
)
|
|
350
|
+
if len(action_ids) != len(set(action_ids)):
|
|
351
|
+
raise ValueError("pilot and continuation repeat an evaluation")
|
|
352
|
+
merged.append(
|
|
353
|
+
MaterializedActionEvaluationBatch(
|
|
354
|
+
proposal_sha256=proposal.proposal_sha256,
|
|
355
|
+
expert_id=proposal.expert_id,
|
|
356
|
+
expert_version=proposal.expert_version,
|
|
357
|
+
expert_definition_sha256=(
|
|
358
|
+
proposal.expert_definition_sha256
|
|
359
|
+
),
|
|
360
|
+
selected_action_sha256s=action_ids,
|
|
361
|
+
evaluations=evaluations,
|
|
362
|
+
evidence=freeze_json(
|
|
363
|
+
{
|
|
364
|
+
"sequential_wave_batch_sha256s": [
|
|
365
|
+
value.batch_sha256 for value in source
|
|
366
|
+
],
|
|
367
|
+
"pilot_then_continuation": True,
|
|
368
|
+
"candidate_outcomes_reused": False,
|
|
369
|
+
}
|
|
370
|
+
),
|
|
371
|
+
)
|
|
372
|
+
)
|
|
373
|
+
return tuple(merged)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
@dataclass(frozen=True, slots=True)
|
|
377
|
+
class SequentialResidualPortfolioEvolutionResult:
|
|
378
|
+
"""Full sequential trace plus the standard combined downstream result."""
|
|
379
|
+
|
|
380
|
+
result: ResidualPortfolioEvolutionResult
|
|
381
|
+
allocation_plan: SequentialAllocationPlanPort
|
|
382
|
+
pilot_evaluation_batches: tuple[
|
|
383
|
+
MaterializedActionEvaluationBatch, ...
|
|
384
|
+
]
|
|
385
|
+
pilot_outcomes: SequentialPilotOutcomeBatch
|
|
386
|
+
gate_decision: SequentialAllocationGateDecisionPort
|
|
387
|
+
continuation_evaluation_batches: tuple[
|
|
388
|
+
MaterializedActionEvaluationBatch, ...
|
|
389
|
+
]
|
|
390
|
+
phase_receipts: tuple[SequentialResidualPhaseReceipt, ...]
|
|
391
|
+
phase_commit_acks: tuple[SequentialResidualPhaseCommitAck, ...]
|
|
392
|
+
method_definition_sha256: str = (
|
|
393
|
+
SEQUENTIAL_RESIDUAL_PORTFOLIO_EVOLUTION_DEFINITION_SHA256
|
|
394
|
+
)
|
|
395
|
+
sequential_result_sha256: str = field(init=False)
|
|
396
|
+
|
|
397
|
+
def __post_init__(self) -> None:
|
|
398
|
+
if type(self.result) is not ResidualPortfolioEvolutionResult:
|
|
399
|
+
raise TypeError("result must be exact")
|
|
400
|
+
self.result.__post_init__()
|
|
401
|
+
if not isinstance(
|
|
402
|
+
self.allocation_plan,
|
|
403
|
+
SequentialAllocationPlanPort,
|
|
404
|
+
):
|
|
405
|
+
raise TypeError(
|
|
406
|
+
"allocation_plan must implement its application port"
|
|
407
|
+
)
|
|
408
|
+
if (
|
|
409
|
+
self.allocation_plan.residual_request_sha256
|
|
410
|
+
!= self.result.request.request_sha256
|
|
411
|
+
or self.allocation_plan.proposal_sha256s
|
|
412
|
+
!= tuple(
|
|
413
|
+
sorted(
|
|
414
|
+
value.proposal_sha256 for value in self.result.proposals
|
|
415
|
+
)
|
|
416
|
+
)
|
|
417
|
+
):
|
|
418
|
+
raise ValueError("allocation plan differs from the combined result")
|
|
419
|
+
for batches, name in (
|
|
420
|
+
(self.pilot_evaluation_batches, "pilot_evaluation_batches"),
|
|
421
|
+
(
|
|
422
|
+
self.continuation_evaluation_batches,
|
|
423
|
+
"continuation_evaluation_batches",
|
|
424
|
+
),
|
|
425
|
+
):
|
|
426
|
+
if type(batches) is not tuple:
|
|
427
|
+
raise TypeError(f"{name} must be an exact tuple")
|
|
428
|
+
for value in batches:
|
|
429
|
+
if type(value) is not MaterializedActionEvaluationBatch:
|
|
430
|
+
raise TypeError(f"{name} must contain exact batches")
|
|
431
|
+
value.__post_init__()
|
|
432
|
+
if type(self.pilot_outcomes) is not SequentialPilotOutcomeBatch:
|
|
433
|
+
raise TypeError("pilot_outcomes must be exact")
|
|
434
|
+
self.pilot_outcomes.__post_init__()
|
|
435
|
+
if not isinstance(
|
|
436
|
+
self.gate_decision,
|
|
437
|
+
SequentialAllocationGateDecisionPort,
|
|
438
|
+
):
|
|
439
|
+
raise TypeError(
|
|
440
|
+
"gate_decision must implement its application port"
|
|
441
|
+
)
|
|
442
|
+
if (
|
|
443
|
+
self.pilot_outcomes.plan_sha256
|
|
444
|
+
!= self.allocation_plan.plan_sha256
|
|
445
|
+
or self.gate_decision.plan_sha256
|
|
446
|
+
!= self.allocation_plan.plan_sha256
|
|
447
|
+
or self.gate_decision.pilot_outcome_batch_sha256
|
|
448
|
+
!= self.pilot_outcomes.batch_sha256
|
|
449
|
+
):
|
|
450
|
+
raise ValueError("pilot outcome/gate trace does not join the plan")
|
|
451
|
+
selected_requirement = self.allocation_plan.requirement_for(
|
|
452
|
+
self.gate_decision.selected_branch_id
|
|
453
|
+
)
|
|
454
|
+
if (
|
|
455
|
+
self.gate_decision.selected_requirement_sha256
|
|
456
|
+
!= selected_requirement.requirement_sha256
|
|
457
|
+
or self.result.broker_decision.allocation_requirement
|
|
458
|
+
!= selected_requirement
|
|
459
|
+
):
|
|
460
|
+
raise ValueError("combined broker result differs from gate branch")
|
|
461
|
+
pilot_ids = {
|
|
462
|
+
value.action.action_sha256
|
|
463
|
+
for value in _flatten_evaluations(
|
|
464
|
+
self.pilot_evaluation_batches
|
|
465
|
+
)
|
|
466
|
+
}
|
|
467
|
+
continuation_ids = {
|
|
468
|
+
value.action.action_sha256
|
|
469
|
+
for value in _flatten_evaluations(
|
|
470
|
+
self.continuation_evaluation_batches
|
|
471
|
+
)
|
|
472
|
+
}
|
|
473
|
+
if pilot_ids != set(self.allocation_plan.pilot_action_sha256s):
|
|
474
|
+
raise ValueError("pilot evaluations differ from the plan")
|
|
475
|
+
if pilot_ids & continuation_ids:
|
|
476
|
+
raise ValueError("continuation reevaluates a pilot")
|
|
477
|
+
if pilot_ids | continuation_ids != set(
|
|
478
|
+
selected_requirement.required_action_sha256s
|
|
479
|
+
):
|
|
480
|
+
raise ValueError("two evaluation waves do not close the branch")
|
|
481
|
+
if (
|
|
482
|
+
type(self.phase_receipts) is not tuple
|
|
483
|
+
or tuple(value.phase for value in self.phase_receipts)
|
|
484
|
+
!= tuple(SequentialResidualPhase)
|
|
485
|
+
):
|
|
486
|
+
raise ValueError("phase receipts must cover canonical phase order")
|
|
487
|
+
for value in self.phase_receipts:
|
|
488
|
+
value.__post_init__()
|
|
489
|
+
if value.plan_sha256 != self.allocation_plan.plan_sha256:
|
|
490
|
+
raise ValueError("phase receipt names another plan")
|
|
491
|
+
if type(self.phase_commit_acks) is not tuple:
|
|
492
|
+
raise TypeError("phase_commit_acks must be an exact tuple")
|
|
493
|
+
for value in self.phase_commit_acks:
|
|
494
|
+
value.__post_init__()
|
|
495
|
+
if self.phase_commit_acks and tuple(
|
|
496
|
+
value.phase_receipt_sha256
|
|
497
|
+
for value in self.phase_commit_acks
|
|
498
|
+
) != tuple(value.receipt_sha256 for value in self.phase_receipts):
|
|
499
|
+
raise ValueError("phase commit acknowledgements do not close")
|
|
500
|
+
require_sha256(
|
|
501
|
+
self.method_definition_sha256,
|
|
502
|
+
"method_definition_sha256",
|
|
503
|
+
)
|
|
504
|
+
object.__setattr__(
|
|
505
|
+
self,
|
|
506
|
+
"sequential_result_sha256",
|
|
507
|
+
_hash(_RESULT_DOMAIN, self._unsigned_record()),
|
|
508
|
+
)
|
|
509
|
+
|
|
510
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
511
|
+
return {
|
|
512
|
+
"schema_version": 1,
|
|
513
|
+
"method": {
|
|
514
|
+
"method_id": SEQUENTIAL_RESIDUAL_PORTFOLIO_EVOLUTION_ID,
|
|
515
|
+
"method_version": (
|
|
516
|
+
SEQUENTIAL_RESIDUAL_PORTFOLIO_EVOLUTION_VERSION
|
|
517
|
+
),
|
|
518
|
+
"definition_sha256": self.method_definition_sha256,
|
|
519
|
+
},
|
|
520
|
+
"combined_result_sha256": self.result.result_sha256,
|
|
521
|
+
"allocation_plan_sha256": self.allocation_plan.plan_sha256,
|
|
522
|
+
"pilot_evaluation_batch_sha256s": [
|
|
523
|
+
value.batch_sha256
|
|
524
|
+
for value in self.pilot_evaluation_batches
|
|
525
|
+
],
|
|
526
|
+
"pilot_outcome_batch_sha256": self.pilot_outcomes.batch_sha256,
|
|
527
|
+
"gate_decision_sha256": self.gate_decision.decision_sha256,
|
|
528
|
+
"continuation_evaluation_batch_sha256s": [
|
|
529
|
+
value.batch_sha256
|
|
530
|
+
for value in self.continuation_evaluation_batches
|
|
531
|
+
],
|
|
532
|
+
"phase_receipt_sha256s": [
|
|
533
|
+
value.receipt_sha256 for value in self.phase_receipts
|
|
534
|
+
],
|
|
535
|
+
"phase_commit_ack_sha256s": [
|
|
536
|
+
value.ack_sha256 for value in self.phase_commit_acks
|
|
537
|
+
],
|
|
538
|
+
"archive_credit_in_combined_result": False,
|
|
539
|
+
"workload_objective_model_provider_prompt_branches": False,
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
|
|
543
|
+
self.__post_init__()
|
|
544
|
+
return {
|
|
545
|
+
**self._unsigned_record(),
|
|
546
|
+
"allocation_plan": self.allocation_plan.to_record(
|
|
547
|
+
include_evidence=include_evidence
|
|
548
|
+
),
|
|
549
|
+
"pilot_evaluation_batches": [
|
|
550
|
+
value.to_record(include_evidence=include_evidence)
|
|
551
|
+
for value in self.pilot_evaluation_batches
|
|
552
|
+
],
|
|
553
|
+
"pilot_outcomes": self.pilot_outcomes.to_record(
|
|
554
|
+
include_evidence=include_evidence
|
|
555
|
+
),
|
|
556
|
+
"gate_decision": self.gate_decision.to_record(
|
|
557
|
+
include_evidence=include_evidence
|
|
558
|
+
),
|
|
559
|
+
"continuation_evaluation_batches": [
|
|
560
|
+
value.to_record(include_evidence=include_evidence)
|
|
561
|
+
for value in self.continuation_evaluation_batches
|
|
562
|
+
],
|
|
563
|
+
"phase_receipts": [
|
|
564
|
+
value.to_record(include_evidence=include_evidence)
|
|
565
|
+
for value in self.phase_receipts
|
|
566
|
+
],
|
|
567
|
+
"phase_commit_acks": [
|
|
568
|
+
value.to_record(include_evidence=include_evidence)
|
|
569
|
+
for value in self.phase_commit_acks
|
|
570
|
+
],
|
|
571
|
+
"combined_result": self.result.to_record(),
|
|
572
|
+
"sequential_result_sha256": self.sequential_result_sha256,
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
@dataclass(frozen=True, slots=True)
|
|
577
|
+
class SequentialResidualPortfolioEvolution:
|
|
578
|
+
"""Execute one proposal universe through a K-pilot plus K-rest gate."""
|
|
579
|
+
|
|
580
|
+
experts: tuple[MaterializedActionProposalExpertPort, ...]
|
|
581
|
+
broker: RegretBrokeredMaterializedActionPolicy
|
|
582
|
+
planner: SequentialLineageAllocationPlannerPort = field(
|
|
583
|
+
repr=False,
|
|
584
|
+
compare=False,
|
|
585
|
+
)
|
|
586
|
+
pilot_outcome_projector: SequentialPilotOutcomeProjectorPort = field(
|
|
587
|
+
repr=False,
|
|
588
|
+
compare=False,
|
|
589
|
+
)
|
|
590
|
+
slate_value: MaterializedSlateValuePort = field(
|
|
591
|
+
repr=False,
|
|
592
|
+
compare=False,
|
|
593
|
+
)
|
|
594
|
+
slate_feasibility: MaterializedSlateFeasibilityPort = field(
|
|
595
|
+
repr=False,
|
|
596
|
+
compare=False,
|
|
597
|
+
)
|
|
598
|
+
gate: SequentialAllocationGatePort = field(
|
|
599
|
+
default_factory=AnyPositiveSequentialLineageGate,
|
|
600
|
+
repr=False,
|
|
601
|
+
compare=False,
|
|
602
|
+
)
|
|
603
|
+
phase_committer: SequentialResidualPhaseCommitPort | None = field(
|
|
604
|
+
default=None,
|
|
605
|
+
repr=False,
|
|
606
|
+
compare=False,
|
|
607
|
+
)
|
|
608
|
+
require_durable_phase_commits: bool = False
|
|
609
|
+
|
|
610
|
+
def __post_init__(self) -> None:
|
|
611
|
+
if type(self.experts) is not tuple or not self.experts:
|
|
612
|
+
raise ValueError("experts must be a non-empty exact tuple")
|
|
613
|
+
if any(
|
|
614
|
+
getattr(value, "evaluation_wave_semantics", None)
|
|
615
|
+
!= DISJOINT_ACTION_EVALUATION_WAVES_V1
|
|
616
|
+
for value in self.experts
|
|
617
|
+
):
|
|
618
|
+
raise ValueError(
|
|
619
|
+
"sequential experts must support disjoint action "
|
|
620
|
+
"evaluation waves"
|
|
621
|
+
)
|
|
622
|
+
if type(self.broker) is not RegretBrokeredMaterializedActionPolicy:
|
|
623
|
+
raise TypeError("broker must be an exact regret-broker policy")
|
|
624
|
+
self.broker.__post_init__()
|
|
625
|
+
_planner_identity(self.planner)
|
|
626
|
+
_projector_identity(self.pilot_outcome_projector)
|
|
627
|
+
if not isinstance(self.slate_value, MaterializedSlateValuePort):
|
|
628
|
+
raise TypeError("slate_value must implement its application port")
|
|
629
|
+
if not isinstance(
|
|
630
|
+
self.slate_feasibility,
|
|
631
|
+
MaterializedSlateFeasibilityPort,
|
|
632
|
+
):
|
|
633
|
+
raise TypeError(
|
|
634
|
+
"slate_feasibility must implement its application port"
|
|
635
|
+
)
|
|
636
|
+
require_sha256(
|
|
637
|
+
self.slate_value.definition_sha256,
|
|
638
|
+
"slate value definition_sha256",
|
|
639
|
+
)
|
|
640
|
+
require_sha256(
|
|
641
|
+
self.slate_feasibility.definition_sha256,
|
|
642
|
+
"slate feasibility definition_sha256",
|
|
643
|
+
)
|
|
644
|
+
_gate_identity(self.gate)
|
|
645
|
+
if self.phase_committer is not None:
|
|
646
|
+
_committer_identity(self.phase_committer)
|
|
647
|
+
if type(self.require_durable_phase_commits) is not bool:
|
|
648
|
+
raise TypeError("require_durable_phase_commits must be exact")
|
|
649
|
+
if (
|
|
650
|
+
self.require_durable_phase_commits
|
|
651
|
+
and self.phase_committer is None
|
|
652
|
+
):
|
|
653
|
+
raise ValueError(
|
|
654
|
+
"required durable phase commits need a committer"
|
|
655
|
+
)
|
|
656
|
+
|
|
657
|
+
async def _commit(
|
|
658
|
+
self,
|
|
659
|
+
receipt: SequentialResidualPhaseReceipt,
|
|
660
|
+
) -> SequentialResidualPhaseCommitAck | None:
|
|
661
|
+
if self.phase_committer is None:
|
|
662
|
+
return None
|
|
663
|
+
identity = _committer_identity(self.phase_committer)
|
|
664
|
+
ack = await self.phase_committer.commit(receipt)
|
|
665
|
+
if type(ack) is not SequentialResidualPhaseCommitAck:
|
|
666
|
+
raise TypeError("phase committer returned a foreign ack")
|
|
667
|
+
ack.__post_init__()
|
|
668
|
+
if (
|
|
669
|
+
ack.committer_id,
|
|
670
|
+
ack.committer_version,
|
|
671
|
+
ack.committer_definition_sha256,
|
|
672
|
+
) != identity:
|
|
673
|
+
raise ValueError("phase commit ack has a foreign identity")
|
|
674
|
+
if ack.phase_receipt_sha256 != receipt.receipt_sha256:
|
|
675
|
+
raise ValueError("phase commit ack targets another receipt")
|
|
676
|
+
if self.require_durable_phase_commits and not ack.durable:
|
|
677
|
+
raise ValueError("required phase commit was not durable")
|
|
678
|
+
return ack
|
|
679
|
+
|
|
680
|
+
async def run(
|
|
681
|
+
self,
|
|
682
|
+
request: ResidualPortfolioDecisionRequest,
|
|
683
|
+
) -> SequentialResidualPortfolioEvolutionResult:
|
|
684
|
+
self.__post_init__()
|
|
685
|
+
if type(request) is not ResidualPortfolioDecisionRequest:
|
|
686
|
+
raise TypeError("request must be exact")
|
|
687
|
+
request.__post_init__()
|
|
688
|
+
proposals = await propose_materialized_action_batches(
|
|
689
|
+
experts=self.experts,
|
|
690
|
+
request=request,
|
|
691
|
+
)
|
|
692
|
+
plan = await self.planner.plan(request, proposals)
|
|
693
|
+
if not isinstance(plan, SequentialAllocationPlanPort):
|
|
694
|
+
raise TypeError(
|
|
695
|
+
"planner returned a value outside the plan port"
|
|
696
|
+
)
|
|
697
|
+
plan_receipt = SequentialResidualPhaseReceipt(
|
|
698
|
+
phase=SequentialResidualPhase.PLAN_FROZEN,
|
|
699
|
+
residual_request_sha256=request.request_sha256,
|
|
700
|
+
plan_sha256=plan.plan_sha256,
|
|
701
|
+
product_sha256s=(
|
|
702
|
+
plan.pilot_requirement.requirement_sha256,
|
|
703
|
+
*(
|
|
704
|
+
value.requirement_sha256
|
|
705
|
+
for value in plan.frozen_requirements
|
|
706
|
+
),
|
|
707
|
+
),
|
|
708
|
+
evidence=freeze_json(
|
|
709
|
+
{
|
|
710
|
+
"proposal_sha256s": list(plan.proposal_sha256s),
|
|
711
|
+
"complete_branch_count": len(
|
|
712
|
+
plan.frozen_requirements
|
|
713
|
+
),
|
|
714
|
+
"all_complete_branches_frozen": True,
|
|
715
|
+
"current_candidate_outcomes_observed": False,
|
|
716
|
+
"allocation_plan": plan.to_record(
|
|
717
|
+
include_evidence=True
|
|
718
|
+
),
|
|
719
|
+
}
|
|
720
|
+
),
|
|
721
|
+
)
|
|
722
|
+
phase_receipts = [plan_receipt]
|
|
723
|
+
phase_acks: list[SequentialResidualPhaseCommitAck] = []
|
|
724
|
+
plan_ack = await self._commit(plan_receipt)
|
|
725
|
+
if plan_ack is not None:
|
|
726
|
+
phase_acks.append(plan_ack)
|
|
727
|
+
|
|
728
|
+
pilot_batches: tuple[MaterializedActionEvaluationBatch, ...]
|
|
729
|
+
if plan.pilot_action_sha256s:
|
|
730
|
+
pilot_batches = await evaluate_materialized_action_subset(
|
|
731
|
+
experts=self.experts,
|
|
732
|
+
proposals=proposals,
|
|
733
|
+
selected_action_sha256s=plan.pilot_action_sha256s,
|
|
734
|
+
)
|
|
735
|
+
else:
|
|
736
|
+
pilot_batches = ()
|
|
737
|
+
pilot_evaluations = _flatten_evaluations(pilot_batches)
|
|
738
|
+
pilot_outcomes = self.pilot_outcome_projector.project(
|
|
739
|
+
plan,
|
|
740
|
+
pilot_evaluations,
|
|
741
|
+
)
|
|
742
|
+
pilot_evaluated_receipt = SequentialResidualPhaseReceipt(
|
|
743
|
+
phase=SequentialResidualPhase.PILOT_EVALUATED,
|
|
744
|
+
residual_request_sha256=request.request_sha256,
|
|
745
|
+
plan_sha256=plan.plan_sha256,
|
|
746
|
+
product_sha256s=(
|
|
747
|
+
*(
|
|
748
|
+
value.batch_sha256 for value in pilot_batches
|
|
749
|
+
),
|
|
750
|
+
pilot_outcomes.batch_sha256,
|
|
751
|
+
),
|
|
752
|
+
evidence=freeze_json(
|
|
753
|
+
{
|
|
754
|
+
"pilot_action_sha256s": list(
|
|
755
|
+
plan.pilot_action_sha256s
|
|
756
|
+
),
|
|
757
|
+
"pilot_evaluation_count": len(
|
|
758
|
+
pilot_evaluations
|
|
759
|
+
),
|
|
760
|
+
"later_candidate_outcomes_observed": False,
|
|
761
|
+
"gate_decision_observed": False,
|
|
762
|
+
"pilot_evaluation_batches": [
|
|
763
|
+
value.to_record(include_evidence=True)
|
|
764
|
+
for value in pilot_batches
|
|
765
|
+
],
|
|
766
|
+
"pilot_outcomes": pilot_outcomes.to_record(
|
|
767
|
+
include_evidence=True
|
|
768
|
+
),
|
|
769
|
+
}
|
|
770
|
+
),
|
|
771
|
+
)
|
|
772
|
+
phase_receipts.append(pilot_evaluated_receipt)
|
|
773
|
+
pilot_evaluated_ack = await self._commit(
|
|
774
|
+
pilot_evaluated_receipt
|
|
775
|
+
)
|
|
776
|
+
if pilot_evaluated_ack is not None:
|
|
777
|
+
phase_acks.append(pilot_evaluated_ack)
|
|
778
|
+
|
|
779
|
+
gate_decision = self.gate.decide(plan, pilot_outcomes)
|
|
780
|
+
if not isinstance(
|
|
781
|
+
gate_decision,
|
|
782
|
+
SequentialAllocationGateDecisionPort,
|
|
783
|
+
):
|
|
784
|
+
raise TypeError("gate returned a value outside its decision port")
|
|
785
|
+
selected_requirement = plan.requirement_for(
|
|
786
|
+
gate_decision.selected_branch_id
|
|
787
|
+
)
|
|
788
|
+
if (
|
|
789
|
+
gate_decision.plan_sha256 != plan.plan_sha256
|
|
790
|
+
or gate_decision.pilot_outcome_batch_sha256
|
|
791
|
+
!= pilot_outcomes.batch_sha256
|
|
792
|
+
or gate_decision.selected_requirement_sha256
|
|
793
|
+
!= selected_requirement.requirement_sha256
|
|
794
|
+
):
|
|
795
|
+
raise ValueError("gate decision does not close the frozen plan")
|
|
796
|
+
pilot_receipt = SequentialResidualPhaseReceipt(
|
|
797
|
+
phase=SequentialResidualPhase.PILOT_ADJUDICATED,
|
|
798
|
+
residual_request_sha256=request.request_sha256,
|
|
799
|
+
plan_sha256=plan.plan_sha256,
|
|
800
|
+
product_sha256s=(
|
|
801
|
+
pilot_evaluated_receipt.receipt_sha256,
|
|
802
|
+
gate_decision.decision_sha256,
|
|
803
|
+
selected_requirement.requirement_sha256,
|
|
804
|
+
),
|
|
805
|
+
evidence=freeze_json(
|
|
806
|
+
{
|
|
807
|
+
"pilot_action_sha256s": list(
|
|
808
|
+
plan.pilot_action_sha256s
|
|
809
|
+
),
|
|
810
|
+
"positive_pilot_count": (
|
|
811
|
+
gate_decision.positive_pilot_count
|
|
812
|
+
),
|
|
813
|
+
"selected_branch": (
|
|
814
|
+
gate_decision.selected_branch_id
|
|
815
|
+
),
|
|
816
|
+
"later_candidate_outcomes_observed": False,
|
|
817
|
+
"pilot_evaluated_receipt_sha256": (
|
|
818
|
+
pilot_evaluated_receipt.receipt_sha256
|
|
819
|
+
),
|
|
820
|
+
"gate_decision": gate_decision.to_record(
|
|
821
|
+
include_evidence=True
|
|
822
|
+
),
|
|
823
|
+
"selected_requirement": (
|
|
824
|
+
selected_requirement.to_record(
|
|
825
|
+
include_evidence=True
|
|
826
|
+
)
|
|
827
|
+
),
|
|
828
|
+
}
|
|
829
|
+
),
|
|
830
|
+
)
|
|
831
|
+
phase_receipts.append(pilot_receipt)
|
|
832
|
+
pilot_ack = await self._commit(pilot_receipt)
|
|
833
|
+
if pilot_ack is not None:
|
|
834
|
+
phase_acks.append(pilot_ack)
|
|
835
|
+
|
|
836
|
+
pilot_ids = set(plan.pilot_action_sha256s)
|
|
837
|
+
continuation_ids = tuple(
|
|
838
|
+
value
|
|
839
|
+
for value in selected_requirement.required_action_sha256s
|
|
840
|
+
if value not in pilot_ids
|
|
841
|
+
)
|
|
842
|
+
if not continuation_ids:
|
|
843
|
+
raise ValueError("sequential branch leaves no continuation wave")
|
|
844
|
+
continuation_batches = await evaluate_materialized_action_subset(
|
|
845
|
+
experts=self.experts,
|
|
846
|
+
proposals=proposals,
|
|
847
|
+
selected_action_sha256s=continuation_ids,
|
|
848
|
+
)
|
|
849
|
+
actions = tuple(
|
|
850
|
+
action for proposal in proposals for action in proposal.actions
|
|
851
|
+
)
|
|
852
|
+
final_decision = self.broker.select(
|
|
853
|
+
MaterializedActionBrokerRequest(
|
|
854
|
+
actions=actions,
|
|
855
|
+
evaluation_slots=request.evaluation_slots,
|
|
856
|
+
slate_value=self.slate_value,
|
|
857
|
+
slate_feasibility=self.slate_feasibility,
|
|
858
|
+
reference_escrow_slots=request.reference_escrow_slots,
|
|
859
|
+
allocation_requirement=selected_requirement,
|
|
860
|
+
)
|
|
861
|
+
)
|
|
862
|
+
if tuple(
|
|
863
|
+
value.action_sha256 for value in final_decision.selected_actions
|
|
864
|
+
) != selected_requirement.required_action_sha256s:
|
|
865
|
+
raise ValueError("final broker did not honor the complete branch")
|
|
866
|
+
merged = _merge_evaluation_waves(
|
|
867
|
+
proposals,
|
|
868
|
+
pilot_batches,
|
|
869
|
+
continuation_batches,
|
|
870
|
+
)
|
|
871
|
+
combined = ResidualPortfolioEvolutionResult(
|
|
872
|
+
request=request,
|
|
873
|
+
proposals=proposals,
|
|
874
|
+
broker_decision=final_decision,
|
|
875
|
+
evaluation_batches=merged,
|
|
876
|
+
slate_value_definition_sha256=self.slate_value.definition_sha256,
|
|
877
|
+
slate_feasibility_definition_sha256=(
|
|
878
|
+
self.slate_feasibility.definition_sha256
|
|
879
|
+
),
|
|
880
|
+
)
|
|
881
|
+
final_receipt = SequentialResidualPhaseReceipt(
|
|
882
|
+
phase=SequentialResidualPhase.FINALIZED,
|
|
883
|
+
residual_request_sha256=request.request_sha256,
|
|
884
|
+
plan_sha256=plan.plan_sha256,
|
|
885
|
+
product_sha256s=(
|
|
886
|
+
*(
|
|
887
|
+
value.batch_sha256
|
|
888
|
+
for value in continuation_batches
|
|
889
|
+
),
|
|
890
|
+
final_decision.decision_sha256,
|
|
891
|
+
combined.result_sha256,
|
|
892
|
+
),
|
|
893
|
+
evidence=freeze_json(
|
|
894
|
+
{
|
|
895
|
+
"selected_branch": (
|
|
896
|
+
gate_decision.selected_branch_id
|
|
897
|
+
),
|
|
898
|
+
"selected_action_sha256s": list(
|
|
899
|
+
selected_requirement.required_action_sha256s
|
|
900
|
+
),
|
|
901
|
+
"pilot_evaluation_count": len(pilot_evaluations),
|
|
902
|
+
"continuation_evaluation_count": len(
|
|
903
|
+
_flatten_evaluations(continuation_batches)
|
|
904
|
+
),
|
|
905
|
+
"continuation_evaluation_batches": [
|
|
906
|
+
value.to_record(include_evidence=True)
|
|
907
|
+
for value in continuation_batches
|
|
908
|
+
],
|
|
909
|
+
"final_broker_decision": final_decision.to_record(),
|
|
910
|
+
"real_evaluation_budget_preserved": True,
|
|
911
|
+
}
|
|
912
|
+
),
|
|
913
|
+
)
|
|
914
|
+
phase_receipts.append(final_receipt)
|
|
915
|
+
final_ack = await self._commit(final_receipt)
|
|
916
|
+
if final_ack is not None:
|
|
917
|
+
phase_acks.append(final_ack)
|
|
918
|
+
return SequentialResidualPortfolioEvolutionResult(
|
|
919
|
+
result=combined,
|
|
920
|
+
allocation_plan=plan,
|
|
921
|
+
pilot_evaluation_batches=pilot_batches,
|
|
922
|
+
pilot_outcomes=pilot_outcomes,
|
|
923
|
+
gate_decision=gate_decision,
|
|
924
|
+
continuation_evaluation_batches=continuation_batches,
|
|
925
|
+
phase_receipts=tuple(phase_receipts),
|
|
926
|
+
phase_commit_acks=tuple(phase_acks),
|
|
927
|
+
)
|
|
928
|
+
|
|
929
|
+
|
|
930
|
+
__all__ = [
|
|
931
|
+
"SEQUENTIAL_RESIDUAL_PORTFOLIO_EVOLUTION_DEFINITION_SHA256",
|
|
932
|
+
"SEQUENTIAL_RESIDUAL_PORTFOLIO_EVOLUTION_ID",
|
|
933
|
+
"SEQUENTIAL_RESIDUAL_PORTFOLIO_EVOLUTION_VERSION",
|
|
934
|
+
"SequentialResidualPhase",
|
|
935
|
+
"SequentialResidualPhaseCommitAck",
|
|
936
|
+
"SequentialResidualPhaseCommitPort",
|
|
937
|
+
"SequentialResidualPhaseReceipt",
|
|
938
|
+
"SequentialResidualPortfolioEvolution",
|
|
939
|
+
"SequentialResidualPortfolioEvolutionResult",
|
|
940
|
+
]
|