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,1017 @@
|
|
|
1
|
+
"""Outcome-blind branch planning and an authenticated lineage pilot gate.
|
|
2
|
+
|
|
3
|
+
The planner freezes three requirements against one sealed proposal universe:
|
|
4
|
+
|
|
5
|
+
* a small recursive-lineage pilot;
|
|
6
|
+
* a complete slate whose ordinary score lanes exclude recursive actions; and
|
|
7
|
+
* a complete slate whose ordinary score lanes explicitly admit them.
|
|
8
|
+
|
|
9
|
+
Both complete slates exist before a pilot is evaluated. The only
|
|
10
|
+
outcome-conditioned operation is a typed gate choosing one already-frozen
|
|
11
|
+
branch from authenticated pilot marginal utility. No workload, objective,
|
|
12
|
+
model, provider, configuration field, or prompt content enters this module.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import asyncio
|
|
18
|
+
import hashlib
|
|
19
|
+
import json
|
|
20
|
+
import math
|
|
21
|
+
import re
|
|
22
|
+
from dataclasses import dataclass, field
|
|
23
|
+
from enum import Enum
|
|
24
|
+
from typing import Protocol, runtime_checkable
|
|
25
|
+
|
|
26
|
+
from agent_evolve.application.agentic_evolution import EvolutionCandidate
|
|
27
|
+
from agent_evolve.application.candidate_archive_consequence import (
|
|
28
|
+
CandidateArchiveConsequenceUtilityPort,
|
|
29
|
+
validate_candidate_archive_consequence_utility,
|
|
30
|
+
)
|
|
31
|
+
from agent_evolve.application.materialized_action_broker import (
|
|
32
|
+
MaterializedActionAllocationRequirement,
|
|
33
|
+
)
|
|
34
|
+
from agent_evolve.application.residual_portfolio_evolution import (
|
|
35
|
+
MaterializedActionAllocationPolicyPort,
|
|
36
|
+
MaterializedActionEvaluation,
|
|
37
|
+
MaterializedActionProposalBatch,
|
|
38
|
+
ResidualPortfolioDecisionRequest,
|
|
39
|
+
)
|
|
40
|
+
from agent_evolve.domain.patch import require_sha256
|
|
41
|
+
from agent_evolve.domain.typed_json import (
|
|
42
|
+
FrozenJsonObject,
|
|
43
|
+
freeze_json,
|
|
44
|
+
thaw_json,
|
|
45
|
+
typed_json_sha256,
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
SEQUENTIAL_LINEAGE_PLANNER_ID = "sequential_lineage_branch_planner"
|
|
50
|
+
SEQUENTIAL_LINEAGE_PLANNER_VERSION = 1
|
|
51
|
+
ANY_POSITIVE_LINEAGE_GATE_ID = "any_positive_lineage_pilot_gate"
|
|
52
|
+
ANY_POSITIVE_LINEAGE_GATE_VERSION = 1
|
|
53
|
+
MARGINAL_PILOT_OUTCOME_PROJECTOR_ID = (
|
|
54
|
+
"candidate_archive_marginal_pilot_outcome"
|
|
55
|
+
)
|
|
56
|
+
MARGINAL_PILOT_OUTCOME_PROJECTOR_VERSION = 1
|
|
57
|
+
|
|
58
|
+
_TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
|
|
59
|
+
_PLAN_DOMAIN = b"agent-evolve:sequential-lineage-plan:v1\x00"
|
|
60
|
+
_PILOT_OUTCOME_DOMAIN = b"agent-evolve:lineage-pilot-outcome:v1\x00"
|
|
61
|
+
_PILOT_BATCH_DOMAIN = b"agent-evolve:lineage-pilot-outcome-batch:v1\x00"
|
|
62
|
+
_GATE_DOMAIN = b"agent-evolve:lineage-pilot-gate:v1\x00"
|
|
63
|
+
_PLANNER_DEFINITION_DOMAIN = (
|
|
64
|
+
b"agent-evolve:sequential-lineage-planner-definition:v1\x00"
|
|
65
|
+
)
|
|
66
|
+
_PROJECTOR_DEFINITION_DOMAIN = (
|
|
67
|
+
b"agent-evolve:marginal-pilot-projector-definition:v1\x00"
|
|
68
|
+
)
|
|
69
|
+
_PILOT_REQUIREMENT_DEFINITION_DOMAIN = (
|
|
70
|
+
b"agent-evolve:sequential-lineage-pilot-requirement:v1\x00"
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _canonical_json(value: object) -> bytes:
|
|
75
|
+
return json.dumps(
|
|
76
|
+
value,
|
|
77
|
+
allow_nan=False,
|
|
78
|
+
ensure_ascii=True,
|
|
79
|
+
separators=(",", ":"),
|
|
80
|
+
sort_keys=True,
|
|
81
|
+
).encode("ascii", errors="strict")
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _hash(domain: bytes, value: object) -> str:
|
|
85
|
+
return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _require_token(value: str, *, name: str) -> None:
|
|
89
|
+
if type(value) is not str or _TOKEN.fullmatch(value) is None:
|
|
90
|
+
raise ValueError(f"{name} must use the closed token grammar")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _policy_identity(
|
|
94
|
+
policy: MaterializedActionAllocationPolicyPort,
|
|
95
|
+
) -> tuple[str, int, str]:
|
|
96
|
+
if not isinstance(policy, MaterializedActionAllocationPolicyPort):
|
|
97
|
+
raise TypeError(
|
|
98
|
+
"allocation policy must implement its application port"
|
|
99
|
+
)
|
|
100
|
+
identity = (
|
|
101
|
+
getattr(policy, "policy_id", None),
|
|
102
|
+
getattr(policy, "policy_version", None),
|
|
103
|
+
getattr(policy, "definition_sha256", None),
|
|
104
|
+
)
|
|
105
|
+
_require_token(identity[0], name="allocation policy_id")
|
|
106
|
+
if type(identity[1]) is not int or identity[1] <= 0:
|
|
107
|
+
raise ValueError("allocation policy_version must be positive")
|
|
108
|
+
require_sha256(identity[2], "allocation policy definition_sha256")
|
|
109
|
+
return identity # type: ignore[return-value]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _requirement_trace(
|
|
113
|
+
requirement: MaterializedActionAllocationRequirement,
|
|
114
|
+
) -> tuple[dict[str, object], ...]:
|
|
115
|
+
requirement.__post_init__()
|
|
116
|
+
record = thaw_json(requirement.evidence)
|
|
117
|
+
if type(record) is not dict:
|
|
118
|
+
raise TypeError("allocation evidence must have an object root")
|
|
119
|
+
raw_trace = record.get("selection_trace")
|
|
120
|
+
if type(raw_trace) is not list:
|
|
121
|
+
raise ValueError("allocation evidence lacks a selection trace")
|
|
122
|
+
result: list[dict[str, object]] = []
|
|
123
|
+
for raw in raw_trace:
|
|
124
|
+
if type(raw) is not dict:
|
|
125
|
+
raise TypeError("selection trace rows must be objects")
|
|
126
|
+
action_sha256 = raw.get("action_sha256")
|
|
127
|
+
allocation_kind = raw.get("allocation_kind")
|
|
128
|
+
if type(action_sha256) is not str or type(allocation_kind) is not str:
|
|
129
|
+
raise ValueError("selection trace row is malformed")
|
|
130
|
+
require_sha256(action_sha256, "trace action_sha256")
|
|
131
|
+
result.append(dict(raw))
|
|
132
|
+
return tuple(result)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
@dataclass(frozen=True, slots=True)
|
|
136
|
+
class SequentialLineageAllocationPlan:
|
|
137
|
+
"""Two frozen complete slates plus their common lineage pilot."""
|
|
138
|
+
|
|
139
|
+
planner_id: str
|
|
140
|
+
planner_version: int
|
|
141
|
+
planner_definition_sha256: str
|
|
142
|
+
residual_request_sha256: str
|
|
143
|
+
proposal_sha256s: tuple[str, ...]
|
|
144
|
+
evaluation_slots: int
|
|
145
|
+
pilot_requirement: MaterializedActionAllocationRequirement
|
|
146
|
+
locked_requirement: MaterializedActionAllocationRequirement
|
|
147
|
+
unlocked_requirement: MaterializedActionAllocationRequirement
|
|
148
|
+
candidate_outcomes_observed: bool
|
|
149
|
+
evidence: FrozenJsonObject
|
|
150
|
+
plan_sha256: str = field(init=False)
|
|
151
|
+
|
|
152
|
+
def __post_init__(self) -> None:
|
|
153
|
+
_require_token(self.planner_id, name="planner_id")
|
|
154
|
+
if type(self.planner_version) is not int or self.planner_version <= 0:
|
|
155
|
+
raise ValueError("planner_version must be positive")
|
|
156
|
+
require_sha256(
|
|
157
|
+
self.planner_definition_sha256,
|
|
158
|
+
"planner_definition_sha256",
|
|
159
|
+
)
|
|
160
|
+
require_sha256(
|
|
161
|
+
self.residual_request_sha256,
|
|
162
|
+
"residual_request_sha256",
|
|
163
|
+
)
|
|
164
|
+
if (
|
|
165
|
+
type(self.proposal_sha256s) is not tuple
|
|
166
|
+
or not self.proposal_sha256s
|
|
167
|
+
or self.proposal_sha256s
|
|
168
|
+
!= tuple(sorted(set(self.proposal_sha256s)))
|
|
169
|
+
):
|
|
170
|
+
raise ValueError("proposal_sha256s must be non-empty and canonical")
|
|
171
|
+
for value in self.proposal_sha256s:
|
|
172
|
+
require_sha256(value, "proposal_sha256")
|
|
173
|
+
if type(self.evaluation_slots) is not int or self.evaluation_slots <= 0:
|
|
174
|
+
raise ValueError("evaluation_slots must be positive")
|
|
175
|
+
for requirement in (
|
|
176
|
+
self.pilot_requirement,
|
|
177
|
+
self.locked_requirement,
|
|
178
|
+
self.unlocked_requirement,
|
|
179
|
+
):
|
|
180
|
+
if type(requirement) is not MaterializedActionAllocationRequirement:
|
|
181
|
+
raise TypeError("plan requirements must be exact")
|
|
182
|
+
requirement.__post_init__()
|
|
183
|
+
if (
|
|
184
|
+
requirement.residual_request_sha256
|
|
185
|
+
!= self.residual_request_sha256
|
|
186
|
+
or requirement.proposal_sha256s != self.proposal_sha256s
|
|
187
|
+
):
|
|
188
|
+
raise ValueError("plan requirement targets another universe")
|
|
189
|
+
pilot = set(self.pilot_requirement.required_action_sha256s)
|
|
190
|
+
locked = set(self.locked_requirement.required_action_sha256s)
|
|
191
|
+
unlocked = set(self.unlocked_requirement.required_action_sha256s)
|
|
192
|
+
if (
|
|
193
|
+
len(locked) != self.evaluation_slots
|
|
194
|
+
or len(unlocked) != self.evaluation_slots
|
|
195
|
+
):
|
|
196
|
+
raise ValueError("both plan branches must fill evaluation capacity")
|
|
197
|
+
if not pilot.issubset(locked) or not pilot.issubset(unlocked):
|
|
198
|
+
raise ValueError("both complete branches must retain every pilot")
|
|
199
|
+
if type(self.candidate_outcomes_observed) is not bool:
|
|
200
|
+
raise TypeError("candidate_outcomes_observed must be exact")
|
|
201
|
+
if self.candidate_outcomes_observed:
|
|
202
|
+
raise ValueError("a sequential plan cannot observe candidate outcomes")
|
|
203
|
+
if (
|
|
204
|
+
type(self.evidence) is not FrozenJsonObject
|
|
205
|
+
or freeze_json(self.evidence) is not self.evidence
|
|
206
|
+
):
|
|
207
|
+
raise TypeError("plan evidence must be an exact frozen object")
|
|
208
|
+
object.__setattr__(
|
|
209
|
+
self,
|
|
210
|
+
"plan_sha256",
|
|
211
|
+
_hash(_PLAN_DOMAIN, self._unsigned_record()),
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
@property
|
|
215
|
+
def pilot_action_sha256s(self) -> tuple[str, ...]:
|
|
216
|
+
return self.pilot_requirement.required_action_sha256s
|
|
217
|
+
|
|
218
|
+
@property
|
|
219
|
+
def frozen_branch_ids(self) -> tuple[str, ...]:
|
|
220
|
+
return tuple(value.value for value in SequentialLineageBranch)
|
|
221
|
+
|
|
222
|
+
@property
|
|
223
|
+
def frozen_requirements(
|
|
224
|
+
self,
|
|
225
|
+
) -> tuple[MaterializedActionAllocationRequirement, ...]:
|
|
226
|
+
return (self.locked_requirement, self.unlocked_requirement)
|
|
227
|
+
|
|
228
|
+
def requirement_for(
|
|
229
|
+
self,
|
|
230
|
+
branch_id: str,
|
|
231
|
+
) -> MaterializedActionAllocationRequirement:
|
|
232
|
+
_require_token(branch_id, name="branch_id")
|
|
233
|
+
try:
|
|
234
|
+
branch = SequentialLineageBranch(branch_id)
|
|
235
|
+
except ValueError as error:
|
|
236
|
+
raise ValueError("branch_id is not frozen in this plan") from error
|
|
237
|
+
return self.branch_requirement(branch)
|
|
238
|
+
|
|
239
|
+
def branch_requirement(
|
|
240
|
+
self,
|
|
241
|
+
branch: "SequentialLineageBranch",
|
|
242
|
+
) -> MaterializedActionAllocationRequirement:
|
|
243
|
+
if type(branch) is not SequentialLineageBranch:
|
|
244
|
+
raise TypeError("branch must be an exact SequentialLineageBranch")
|
|
245
|
+
return (
|
|
246
|
+
self.unlocked_requirement
|
|
247
|
+
if branch is SequentialLineageBranch.UNLOCKED
|
|
248
|
+
else self.locked_requirement
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
252
|
+
return {
|
|
253
|
+
"schema_version": 1,
|
|
254
|
+
"planner": {
|
|
255
|
+
"planner_id": self.planner_id,
|
|
256
|
+
"planner_version": self.planner_version,
|
|
257
|
+
"definition_sha256": self.planner_definition_sha256,
|
|
258
|
+
},
|
|
259
|
+
"residual_request_sha256": self.residual_request_sha256,
|
|
260
|
+
"proposal_sha256s": list(self.proposal_sha256s),
|
|
261
|
+
"evaluation_slots": self.evaluation_slots,
|
|
262
|
+
"pilot_requirement_sha256": (
|
|
263
|
+
self.pilot_requirement.requirement_sha256
|
|
264
|
+
),
|
|
265
|
+
"locked_requirement_sha256": (
|
|
266
|
+
self.locked_requirement.requirement_sha256
|
|
267
|
+
),
|
|
268
|
+
"unlocked_requirement_sha256": (
|
|
269
|
+
self.unlocked_requirement.requirement_sha256
|
|
270
|
+
),
|
|
271
|
+
"candidate_outcomes_observed": self.candidate_outcomes_observed,
|
|
272
|
+
"evidence_sha256": typed_json_sha256(self.evidence),
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
|
|
276
|
+
self.__post_init__()
|
|
277
|
+
record = {
|
|
278
|
+
**self._unsigned_record(),
|
|
279
|
+
"pilot_requirement": self.pilot_requirement.to_record(
|
|
280
|
+
include_evidence=include_evidence
|
|
281
|
+
),
|
|
282
|
+
"locked_requirement": self.locked_requirement.to_record(
|
|
283
|
+
include_evidence=include_evidence
|
|
284
|
+
),
|
|
285
|
+
"unlocked_requirement": self.unlocked_requirement.to_record(
|
|
286
|
+
include_evidence=include_evidence
|
|
287
|
+
),
|
|
288
|
+
"plan_sha256": self.plan_sha256,
|
|
289
|
+
}
|
|
290
|
+
if include_evidence:
|
|
291
|
+
record["evidence"] = thaw_json(self.evidence)
|
|
292
|
+
return record
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
@runtime_checkable
|
|
296
|
+
class SequentialAllocationPlanPort(Protocol):
|
|
297
|
+
"""A pilot plus one or more complete slates frozen before outcomes."""
|
|
298
|
+
|
|
299
|
+
planner_id: str
|
|
300
|
+
planner_version: int
|
|
301
|
+
planner_definition_sha256: str
|
|
302
|
+
residual_request_sha256: str
|
|
303
|
+
proposal_sha256s: tuple[str, ...]
|
|
304
|
+
evaluation_slots: int
|
|
305
|
+
pilot_requirement: MaterializedActionAllocationRequirement
|
|
306
|
+
candidate_outcomes_observed: bool
|
|
307
|
+
evidence: FrozenJsonObject
|
|
308
|
+
plan_sha256: str
|
|
309
|
+
|
|
310
|
+
@property
|
|
311
|
+
def pilot_action_sha256s(self) -> tuple[str, ...]: ...
|
|
312
|
+
|
|
313
|
+
@property
|
|
314
|
+
def frozen_branch_ids(self) -> tuple[str, ...]: ...
|
|
315
|
+
|
|
316
|
+
@property
|
|
317
|
+
def frozen_requirements(
|
|
318
|
+
self,
|
|
319
|
+
) -> tuple[MaterializedActionAllocationRequirement, ...]: ...
|
|
320
|
+
|
|
321
|
+
def requirement_for(
|
|
322
|
+
self,
|
|
323
|
+
branch_id: str,
|
|
324
|
+
) -> MaterializedActionAllocationRequirement: ...
|
|
325
|
+
|
|
326
|
+
def to_record(
|
|
327
|
+
self,
|
|
328
|
+
*,
|
|
329
|
+
include_evidence: bool = False,
|
|
330
|
+
) -> dict[str, object]: ...
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
@runtime_checkable
|
|
334
|
+
class SequentialLineageAllocationPlannerPort(Protocol):
|
|
335
|
+
"""Freeze a pilot and complete slates before current outcomes exist."""
|
|
336
|
+
|
|
337
|
+
planner_id: str
|
|
338
|
+
planner_version: int
|
|
339
|
+
definition_sha256: str
|
|
340
|
+
|
|
341
|
+
async def plan(
|
|
342
|
+
self,
|
|
343
|
+
request: ResidualPortfolioDecisionRequest,
|
|
344
|
+
proposals: tuple[MaterializedActionProposalBatch, ...],
|
|
345
|
+
) -> SequentialAllocationPlanPort: ...
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
@dataclass(frozen=True, slots=True)
|
|
349
|
+
class FrozenBranchSequentialLineagePlanner:
|
|
350
|
+
"""Compose locked and unlocked outcome-blind allocation policies."""
|
|
351
|
+
|
|
352
|
+
locked_policy: MaterializedActionAllocationPolicyPort = field(
|
|
353
|
+
repr=False,
|
|
354
|
+
compare=False,
|
|
355
|
+
)
|
|
356
|
+
unlocked_policy: MaterializedActionAllocationPolicyPort = field(
|
|
357
|
+
repr=False,
|
|
358
|
+
compare=False,
|
|
359
|
+
)
|
|
360
|
+
pilot_allocation_kind: str = "recursive_lineage_cell"
|
|
361
|
+
planner_id: str = SEQUENTIAL_LINEAGE_PLANNER_ID
|
|
362
|
+
planner_version: int = SEQUENTIAL_LINEAGE_PLANNER_VERSION
|
|
363
|
+
definition_sha256: str = field(init=False)
|
|
364
|
+
|
|
365
|
+
def __post_init__(self) -> None:
|
|
366
|
+
locked = _policy_identity(self.locked_policy)
|
|
367
|
+
unlocked = _policy_identity(self.unlocked_policy)
|
|
368
|
+
_require_token(self.pilot_allocation_kind, name="pilot_allocation_kind")
|
|
369
|
+
_require_token(self.planner_id, name="planner_id")
|
|
370
|
+
if self.planner_version != SEQUENTIAL_LINEAGE_PLANNER_VERSION:
|
|
371
|
+
raise ValueError("planner_version is immutable")
|
|
372
|
+
object.__setattr__(
|
|
373
|
+
self,
|
|
374
|
+
"definition_sha256",
|
|
375
|
+
_hash(
|
|
376
|
+
_PLANNER_DEFINITION_DOMAIN,
|
|
377
|
+
{
|
|
378
|
+
"schema_version": 1,
|
|
379
|
+
"planner_id": self.planner_id,
|
|
380
|
+
"planner_version": self.planner_version,
|
|
381
|
+
"locked_policy": {
|
|
382
|
+
"policy_id": locked[0],
|
|
383
|
+
"policy_version": locked[1],
|
|
384
|
+
"definition_sha256": locked[2],
|
|
385
|
+
},
|
|
386
|
+
"unlocked_policy": {
|
|
387
|
+
"policy_id": unlocked[0],
|
|
388
|
+
"policy_version": unlocked[1],
|
|
389
|
+
"definition_sha256": unlocked[2],
|
|
390
|
+
},
|
|
391
|
+
"pilot_allocation_kind": self.pilot_allocation_kind,
|
|
392
|
+
"branches_frozen_before_outcomes": True,
|
|
393
|
+
"workload_model_provider_branches": False,
|
|
394
|
+
},
|
|
395
|
+
),
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
async def plan(
|
|
399
|
+
self,
|
|
400
|
+
request: ResidualPortfolioDecisionRequest,
|
|
401
|
+
proposals: tuple[MaterializedActionProposalBatch, ...],
|
|
402
|
+
) -> SequentialLineageAllocationPlan:
|
|
403
|
+
self.__post_init__()
|
|
404
|
+
if type(request) is not ResidualPortfolioDecisionRequest:
|
|
405
|
+
raise TypeError("request must be exact")
|
|
406
|
+
request.__post_init__()
|
|
407
|
+
if type(proposals) is not tuple or not proposals:
|
|
408
|
+
raise ValueError("proposals must be a non-empty exact tuple")
|
|
409
|
+
for proposal in proposals:
|
|
410
|
+
if type(proposal) is not MaterializedActionProposalBatch:
|
|
411
|
+
raise TypeError("proposals must contain exact batches")
|
|
412
|
+
proposal.__post_init__()
|
|
413
|
+
proposal.require_request(request)
|
|
414
|
+
locked, unlocked = await asyncio.gather(
|
|
415
|
+
self.locked_policy.require(request, proposals),
|
|
416
|
+
self.unlocked_policy.require(request, proposals),
|
|
417
|
+
)
|
|
418
|
+
for requirement in (locked, unlocked):
|
|
419
|
+
if type(requirement) is not MaterializedActionAllocationRequirement:
|
|
420
|
+
raise TypeError("branch policy returned a foreign requirement")
|
|
421
|
+
requirement.__post_init__()
|
|
422
|
+
locked_trace = _requirement_trace(locked)
|
|
423
|
+
unlocked_trace = _requirement_trace(unlocked)
|
|
424
|
+
locked_pilot = tuple(
|
|
425
|
+
str(value["action_sha256"])
|
|
426
|
+
for value in locked_trace
|
|
427
|
+
if value["allocation_kind"] == self.pilot_allocation_kind
|
|
428
|
+
)
|
|
429
|
+
unlocked_pilot = tuple(
|
|
430
|
+
str(value["action_sha256"])
|
|
431
|
+
for value in unlocked_trace
|
|
432
|
+
if value["allocation_kind"] == self.pilot_allocation_kind
|
|
433
|
+
)
|
|
434
|
+
if locked_pilot != unlocked_pilot:
|
|
435
|
+
raise ValueError("branch policies disagree on the frozen pilot")
|
|
436
|
+
proposal_sha256s = tuple(
|
|
437
|
+
sorted(value.proposal_sha256 for value in proposals)
|
|
438
|
+
)
|
|
439
|
+
pilot_definition_sha256 = _hash(
|
|
440
|
+
_PILOT_REQUIREMENT_DEFINITION_DOMAIN,
|
|
441
|
+
{
|
|
442
|
+
"planner_definition_sha256": self.definition_sha256,
|
|
443
|
+
"pilot_allocation_kind": self.pilot_allocation_kind,
|
|
444
|
+
},
|
|
445
|
+
)
|
|
446
|
+
pilot_requirement = MaterializedActionAllocationRequirement(
|
|
447
|
+
policy_id="sequential_lineage_pilot",
|
|
448
|
+
policy_version=1,
|
|
449
|
+
policy_definition_sha256=pilot_definition_sha256,
|
|
450
|
+
residual_request_sha256=request.request_sha256,
|
|
451
|
+
proposal_sha256s=proposal_sha256s,
|
|
452
|
+
required_action_sha256s=tuple(sorted(locked_pilot)),
|
|
453
|
+
candidate_outcomes_observed=False,
|
|
454
|
+
evidence=freeze_json(
|
|
455
|
+
{
|
|
456
|
+
"planner_definition_sha256": self.definition_sha256,
|
|
457
|
+
"locked_requirement_sha256": locked.requirement_sha256,
|
|
458
|
+
"unlocked_requirement_sha256": unlocked.requirement_sha256,
|
|
459
|
+
"pilot_trace": [
|
|
460
|
+
value
|
|
461
|
+
for value in locked_trace
|
|
462
|
+
if value["allocation_kind"]
|
|
463
|
+
== self.pilot_allocation_kind
|
|
464
|
+
],
|
|
465
|
+
"candidate_outcomes_observed": False,
|
|
466
|
+
"workload_model_provider_branches": False,
|
|
467
|
+
}
|
|
468
|
+
),
|
|
469
|
+
)
|
|
470
|
+
locked_identity = _policy_identity(self.locked_policy)
|
|
471
|
+
unlocked_identity = _policy_identity(self.unlocked_policy)
|
|
472
|
+
return SequentialLineageAllocationPlan(
|
|
473
|
+
planner_id=self.planner_id,
|
|
474
|
+
planner_version=self.planner_version,
|
|
475
|
+
planner_definition_sha256=self.definition_sha256,
|
|
476
|
+
residual_request_sha256=request.request_sha256,
|
|
477
|
+
proposal_sha256s=proposal_sha256s,
|
|
478
|
+
evaluation_slots=request.evaluation_slots,
|
|
479
|
+
pilot_requirement=pilot_requirement,
|
|
480
|
+
locked_requirement=locked,
|
|
481
|
+
unlocked_requirement=unlocked,
|
|
482
|
+
candidate_outcomes_observed=False,
|
|
483
|
+
evidence=freeze_json(
|
|
484
|
+
{
|
|
485
|
+
"locked_policy": {
|
|
486
|
+
"policy_id": locked_identity[0],
|
|
487
|
+
"policy_version": locked_identity[1],
|
|
488
|
+
"definition_sha256": locked_identity[2],
|
|
489
|
+
"requirement_sha256": locked.requirement_sha256,
|
|
490
|
+
},
|
|
491
|
+
"unlocked_policy": {
|
|
492
|
+
"policy_id": unlocked_identity[0],
|
|
493
|
+
"policy_version": unlocked_identity[1],
|
|
494
|
+
"definition_sha256": unlocked_identity[2],
|
|
495
|
+
"requirement_sha256": unlocked.requirement_sha256,
|
|
496
|
+
},
|
|
497
|
+
"pilot_action_sha256s": list(sorted(locked_pilot)),
|
|
498
|
+
"both_complete_branches_frozen_before_pilot": True,
|
|
499
|
+
"candidate_outcomes_observed": False,
|
|
500
|
+
"workload_model_provider_branches": False,
|
|
501
|
+
}
|
|
502
|
+
),
|
|
503
|
+
)
|
|
504
|
+
|
|
505
|
+
|
|
506
|
+
@dataclass(frozen=True, slots=True)
|
|
507
|
+
class SequentialPilotActionOutcome:
|
|
508
|
+
"""One pilot's real marginal archive contribution against the prior."""
|
|
509
|
+
|
|
510
|
+
action_sha256: str
|
|
511
|
+
evaluation_sha256: str
|
|
512
|
+
feasible: bool
|
|
513
|
+
marginal_archive_gain: float
|
|
514
|
+
positive_marginal_utility: bool
|
|
515
|
+
outcome_sha256: str = field(init=False)
|
|
516
|
+
|
|
517
|
+
def __post_init__(self) -> None:
|
|
518
|
+
require_sha256(self.action_sha256, "action_sha256")
|
|
519
|
+
require_sha256(self.evaluation_sha256, "evaluation_sha256")
|
|
520
|
+
if type(self.feasible) is not bool:
|
|
521
|
+
raise TypeError("feasible must be an exact bool")
|
|
522
|
+
if (
|
|
523
|
+
type(self.marginal_archive_gain) is not float
|
|
524
|
+
or not math.isfinite(self.marginal_archive_gain)
|
|
525
|
+
or self.marginal_archive_gain < 0.0
|
|
526
|
+
):
|
|
527
|
+
raise ValueError(
|
|
528
|
+
"marginal_archive_gain must be finite and non-negative"
|
|
529
|
+
)
|
|
530
|
+
if type(self.positive_marginal_utility) is not bool:
|
|
531
|
+
raise TypeError("positive_marginal_utility must be an exact bool")
|
|
532
|
+
if self.positive_marginal_utility != (
|
|
533
|
+
self.marginal_archive_gain > 0.0
|
|
534
|
+
):
|
|
535
|
+
raise ValueError("positive verdict differs from marginal gain")
|
|
536
|
+
if not self.feasible and (
|
|
537
|
+
self.marginal_archive_gain != 0.0
|
|
538
|
+
or self.positive_marginal_utility
|
|
539
|
+
):
|
|
540
|
+
raise ValueError("an infeasible pilot cannot have positive return")
|
|
541
|
+
object.__setattr__(
|
|
542
|
+
self,
|
|
543
|
+
"outcome_sha256",
|
|
544
|
+
_hash(_PILOT_OUTCOME_DOMAIN, self._unsigned_record()),
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
548
|
+
return {
|
|
549
|
+
"schema_version": 1,
|
|
550
|
+
"action_sha256": self.action_sha256,
|
|
551
|
+
"evaluation_sha256": self.evaluation_sha256,
|
|
552
|
+
"feasible": self.feasible,
|
|
553
|
+
"marginal_archive_gain_hex": self.marginal_archive_gain.hex(),
|
|
554
|
+
"positive_marginal_utility": self.positive_marginal_utility,
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
def to_record(self) -> dict[str, object]:
|
|
558
|
+
self.__post_init__()
|
|
559
|
+
return {
|
|
560
|
+
**self._unsigned_record(),
|
|
561
|
+
"outcome_sha256": self.outcome_sha256,
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
|
|
565
|
+
@dataclass(frozen=True, slots=True)
|
|
566
|
+
class SequentialPilotOutcomeBatch:
|
|
567
|
+
"""Authenticated complete outcomes for one plan's pilot action set."""
|
|
568
|
+
|
|
569
|
+
projector_id: str
|
|
570
|
+
projector_version: int
|
|
571
|
+
projector_definition_sha256: str
|
|
572
|
+
plan_sha256: str
|
|
573
|
+
residual_request_sha256: str
|
|
574
|
+
outcomes: tuple[SequentialPilotActionOutcome, ...]
|
|
575
|
+
evidence: FrozenJsonObject
|
|
576
|
+
batch_sha256: str = field(init=False)
|
|
577
|
+
|
|
578
|
+
def __post_init__(self) -> None:
|
|
579
|
+
_require_token(self.projector_id, name="projector_id")
|
|
580
|
+
if type(self.projector_version) is not int or self.projector_version <= 0:
|
|
581
|
+
raise ValueError("projector_version must be positive")
|
|
582
|
+
require_sha256(
|
|
583
|
+
self.projector_definition_sha256,
|
|
584
|
+
"projector_definition_sha256",
|
|
585
|
+
)
|
|
586
|
+
require_sha256(self.plan_sha256, "plan_sha256")
|
|
587
|
+
require_sha256(
|
|
588
|
+
self.residual_request_sha256,
|
|
589
|
+
"residual_request_sha256",
|
|
590
|
+
)
|
|
591
|
+
if type(self.outcomes) is not tuple:
|
|
592
|
+
raise TypeError("outcomes must be an exact tuple")
|
|
593
|
+
for value in self.outcomes:
|
|
594
|
+
if type(value) is not SequentialPilotActionOutcome:
|
|
595
|
+
raise TypeError("outcomes must contain exact values")
|
|
596
|
+
value.__post_init__()
|
|
597
|
+
action_ids = tuple(value.action_sha256 for value in self.outcomes)
|
|
598
|
+
if action_ids != tuple(sorted(set(action_ids))):
|
|
599
|
+
raise ValueError("pilot outcomes must be action-canonical")
|
|
600
|
+
if (
|
|
601
|
+
type(self.evidence) is not FrozenJsonObject
|
|
602
|
+
or freeze_json(self.evidence) is not self.evidence
|
|
603
|
+
):
|
|
604
|
+
raise TypeError("outcome evidence must be an exact frozen object")
|
|
605
|
+
object.__setattr__(
|
|
606
|
+
self,
|
|
607
|
+
"batch_sha256",
|
|
608
|
+
_hash(_PILOT_BATCH_DOMAIN, self._unsigned_record()),
|
|
609
|
+
)
|
|
610
|
+
|
|
611
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
612
|
+
return {
|
|
613
|
+
"schema_version": 1,
|
|
614
|
+
"projector": {
|
|
615
|
+
"projector_id": self.projector_id,
|
|
616
|
+
"projector_version": self.projector_version,
|
|
617
|
+
"definition_sha256": self.projector_definition_sha256,
|
|
618
|
+
},
|
|
619
|
+
"plan_sha256": self.plan_sha256,
|
|
620
|
+
"residual_request_sha256": self.residual_request_sha256,
|
|
621
|
+
"outcomes": [value.to_record() for value in self.outcomes],
|
|
622
|
+
"evidence_sha256": typed_json_sha256(self.evidence),
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
|
|
626
|
+
self.__post_init__()
|
|
627
|
+
record = {**self._unsigned_record(), "batch_sha256": self.batch_sha256}
|
|
628
|
+
if include_evidence:
|
|
629
|
+
record["evidence"] = thaw_json(self.evidence)
|
|
630
|
+
return record
|
|
631
|
+
|
|
632
|
+
|
|
633
|
+
@runtime_checkable
|
|
634
|
+
class SequentialPilotOutcomeProjectorPort(Protocol):
|
|
635
|
+
"""Project only the real pilot evidence needed by a branch gate."""
|
|
636
|
+
|
|
637
|
+
projector_id: str
|
|
638
|
+
projector_version: int
|
|
639
|
+
definition_sha256: str
|
|
640
|
+
|
|
641
|
+
def project(
|
|
642
|
+
self,
|
|
643
|
+
plan: SequentialAllocationPlanPort,
|
|
644
|
+
evaluations: tuple[MaterializedActionEvaluation, ...],
|
|
645
|
+
) -> SequentialPilotOutcomeBatch: ...
|
|
646
|
+
|
|
647
|
+
|
|
648
|
+
@dataclass(frozen=True, slots=True)
|
|
649
|
+
class CandidateArchiveMarginalPilotOutcomeProjector:
|
|
650
|
+
"""Use an injected archive utility to adjudicate pilot positivity."""
|
|
651
|
+
|
|
652
|
+
prior_candidates: tuple[EvolutionCandidate, ...]
|
|
653
|
+
utility: CandidateArchiveConsequenceUtilityPort = field(
|
|
654
|
+
repr=False,
|
|
655
|
+
compare=False,
|
|
656
|
+
)
|
|
657
|
+
projector_id: str = MARGINAL_PILOT_OUTCOME_PROJECTOR_ID
|
|
658
|
+
projector_version: int = MARGINAL_PILOT_OUTCOME_PROJECTOR_VERSION
|
|
659
|
+
definition_sha256: str = field(init=False)
|
|
660
|
+
|
|
661
|
+
def __post_init__(self) -> None:
|
|
662
|
+
if (
|
|
663
|
+
type(self.prior_candidates) is not tuple
|
|
664
|
+
or any(
|
|
665
|
+
type(value) is not EvolutionCandidate
|
|
666
|
+
for value in self.prior_candidates
|
|
667
|
+
)
|
|
668
|
+
):
|
|
669
|
+
raise TypeError("prior_candidates must be an exact candidate tuple")
|
|
670
|
+
for value in self.prior_candidates:
|
|
671
|
+
value.__post_init__()
|
|
672
|
+
utility_identity = validate_candidate_archive_consequence_utility(
|
|
673
|
+
self.utility
|
|
674
|
+
)
|
|
675
|
+
_require_token(self.projector_id, name="projector_id")
|
|
676
|
+
if self.projector_version != MARGINAL_PILOT_OUTCOME_PROJECTOR_VERSION:
|
|
677
|
+
raise ValueError("projector_version is immutable")
|
|
678
|
+
object.__setattr__(
|
|
679
|
+
self,
|
|
680
|
+
"definition_sha256",
|
|
681
|
+
_hash(
|
|
682
|
+
_PROJECTOR_DEFINITION_DOMAIN,
|
|
683
|
+
{
|
|
684
|
+
"schema_version": 1,
|
|
685
|
+
"projector_id": self.projector_id,
|
|
686
|
+
"projector_version": self.projector_version,
|
|
687
|
+
"utility": {
|
|
688
|
+
"utility_id": utility_identity[0],
|
|
689
|
+
"utility_version": utility_identity[1],
|
|
690
|
+
"definition_sha256": utility_identity[2],
|
|
691
|
+
},
|
|
692
|
+
"prior_candidate_ids": [
|
|
693
|
+
value.candidate_id.value
|
|
694
|
+
for value in self.prior_candidates
|
|
695
|
+
],
|
|
696
|
+
"admission": (
|
|
697
|
+
"valid_and_operator_and_evidence_compliant"
|
|
698
|
+
),
|
|
699
|
+
"gate_currency": "positive_individual_marginal_utility",
|
|
700
|
+
},
|
|
701
|
+
),
|
|
702
|
+
)
|
|
703
|
+
|
|
704
|
+
def project(
|
|
705
|
+
self,
|
|
706
|
+
plan: SequentialAllocationPlanPort,
|
|
707
|
+
evaluations: tuple[MaterializedActionEvaluation, ...],
|
|
708
|
+
) -> SequentialPilotOutcomeBatch:
|
|
709
|
+
self.__post_init__()
|
|
710
|
+
if not isinstance(plan, SequentialAllocationPlanPort):
|
|
711
|
+
raise TypeError("plan must implement its application port")
|
|
712
|
+
if (
|
|
713
|
+
type(evaluations) is not tuple
|
|
714
|
+
or any(
|
|
715
|
+
type(value) is not MaterializedActionEvaluation
|
|
716
|
+
for value in evaluations
|
|
717
|
+
)
|
|
718
|
+
):
|
|
719
|
+
raise TypeError("evaluations must be an exact tuple")
|
|
720
|
+
by_action: dict[str, MaterializedActionEvaluation] = {}
|
|
721
|
+
for value in evaluations:
|
|
722
|
+
value.__post_init__()
|
|
723
|
+
if value.action.action_sha256 in by_action:
|
|
724
|
+
raise ValueError("pilot evaluations repeat an action")
|
|
725
|
+
by_action[value.action.action_sha256] = value
|
|
726
|
+
if set(by_action) != set(plan.pilot_action_sha256s):
|
|
727
|
+
raise ValueError("evaluations do not exactly cover the pilot")
|
|
728
|
+
outcomes: list[SequentialPilotActionOutcome] = []
|
|
729
|
+
for action_sha256 in sorted(by_action):
|
|
730
|
+
evaluation = by_action[action_sha256]
|
|
731
|
+
candidate = evaluation.candidate
|
|
732
|
+
feasible = bool(
|
|
733
|
+
candidate.valid
|
|
734
|
+
and candidate.operator_compliant
|
|
735
|
+
and candidate.evidence_compliant
|
|
736
|
+
)
|
|
737
|
+
gain = (
|
|
738
|
+
0.0
|
|
739
|
+
if not feasible
|
|
740
|
+
else self.utility.marginal_utility(
|
|
741
|
+
self.prior_candidates,
|
|
742
|
+
candidate.objective_map,
|
|
743
|
+
)
|
|
744
|
+
)
|
|
745
|
+
if (
|
|
746
|
+
type(gain) is not float
|
|
747
|
+
or not math.isfinite(gain)
|
|
748
|
+
or gain < 0.0
|
|
749
|
+
):
|
|
750
|
+
raise ValueError(
|
|
751
|
+
"pilot utility returned a non-finite or negative gain"
|
|
752
|
+
)
|
|
753
|
+
outcomes.append(
|
|
754
|
+
SequentialPilotActionOutcome(
|
|
755
|
+
action_sha256=action_sha256,
|
|
756
|
+
evaluation_sha256=evaluation.evaluation_sha256,
|
|
757
|
+
feasible=feasible,
|
|
758
|
+
marginal_archive_gain=float(gain),
|
|
759
|
+
positive_marginal_utility=gain > 0.0,
|
|
760
|
+
)
|
|
761
|
+
)
|
|
762
|
+
return SequentialPilotOutcomeBatch(
|
|
763
|
+
projector_id=self.projector_id,
|
|
764
|
+
projector_version=self.projector_version,
|
|
765
|
+
projector_definition_sha256=self.definition_sha256,
|
|
766
|
+
plan_sha256=plan.plan_sha256,
|
|
767
|
+
residual_request_sha256=plan.residual_request_sha256,
|
|
768
|
+
outcomes=tuple(outcomes),
|
|
769
|
+
evidence=freeze_json(
|
|
770
|
+
{
|
|
771
|
+
"prior_candidate_count": len(self.prior_candidates),
|
|
772
|
+
"utility_definition_sha256": (
|
|
773
|
+
self.utility.definition_sha256
|
|
774
|
+
),
|
|
775
|
+
"individual_marginal_against_common_prior": True,
|
|
776
|
+
"only_pilot_outcomes_observed": True,
|
|
777
|
+
"workload_model_provider_branches": False,
|
|
778
|
+
}
|
|
779
|
+
),
|
|
780
|
+
)
|
|
781
|
+
|
|
782
|
+
|
|
783
|
+
class SequentialLineageBranch(str, Enum):
|
|
784
|
+
LOCKED = "locked"
|
|
785
|
+
UNLOCKED = "unlocked"
|
|
786
|
+
|
|
787
|
+
|
|
788
|
+
@dataclass(frozen=True, slots=True)
|
|
789
|
+
class SequentialLineageGateDecision:
|
|
790
|
+
"""Outcome-conditioned choice between two pre-existing branch receipts."""
|
|
791
|
+
|
|
792
|
+
gate_id: str
|
|
793
|
+
gate_version: int
|
|
794
|
+
gate_definition_sha256: str
|
|
795
|
+
plan_sha256: str
|
|
796
|
+
pilot_outcome_batch_sha256: str
|
|
797
|
+
branch: SequentialLineageBranch
|
|
798
|
+
selected_requirement_sha256: str
|
|
799
|
+
positive_pilot_count: int
|
|
800
|
+
pilot_count: int
|
|
801
|
+
evidence: FrozenJsonObject
|
|
802
|
+
decision_sha256: str = field(init=False)
|
|
803
|
+
|
|
804
|
+
def __post_init__(self) -> None:
|
|
805
|
+
_require_token(self.gate_id, name="gate_id")
|
|
806
|
+
if type(self.gate_version) is not int or self.gate_version <= 0:
|
|
807
|
+
raise ValueError("gate_version must be positive")
|
|
808
|
+
require_sha256(
|
|
809
|
+
self.gate_definition_sha256,
|
|
810
|
+
"gate_definition_sha256",
|
|
811
|
+
)
|
|
812
|
+
for value, name in (
|
|
813
|
+
(self.plan_sha256, "plan_sha256"),
|
|
814
|
+
(
|
|
815
|
+
self.pilot_outcome_batch_sha256,
|
|
816
|
+
"pilot_outcome_batch_sha256",
|
|
817
|
+
),
|
|
818
|
+
(
|
|
819
|
+
self.selected_requirement_sha256,
|
|
820
|
+
"selected_requirement_sha256",
|
|
821
|
+
),
|
|
822
|
+
):
|
|
823
|
+
require_sha256(value, name)
|
|
824
|
+
if type(self.branch) is not SequentialLineageBranch:
|
|
825
|
+
raise TypeError("branch must be an exact SequentialLineageBranch")
|
|
826
|
+
if (
|
|
827
|
+
type(self.positive_pilot_count) is not int
|
|
828
|
+
or type(self.pilot_count) is not int
|
|
829
|
+
or not 0
|
|
830
|
+
<= self.positive_pilot_count
|
|
831
|
+
<= self.pilot_count
|
|
832
|
+
):
|
|
833
|
+
raise ValueError("pilot counts are inconsistent")
|
|
834
|
+
if (
|
|
835
|
+
type(self.evidence) is not FrozenJsonObject
|
|
836
|
+
or freeze_json(self.evidence) is not self.evidence
|
|
837
|
+
):
|
|
838
|
+
raise TypeError("gate evidence must be an exact frozen object")
|
|
839
|
+
object.__setattr__(
|
|
840
|
+
self,
|
|
841
|
+
"decision_sha256",
|
|
842
|
+
_hash(_GATE_DOMAIN, self._unsigned_record()),
|
|
843
|
+
)
|
|
844
|
+
|
|
845
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
846
|
+
return {
|
|
847
|
+
"schema_version": 1,
|
|
848
|
+
"gate": {
|
|
849
|
+
"gate_id": self.gate_id,
|
|
850
|
+
"gate_version": self.gate_version,
|
|
851
|
+
"definition_sha256": self.gate_definition_sha256,
|
|
852
|
+
},
|
|
853
|
+
"plan_sha256": self.plan_sha256,
|
|
854
|
+
"pilot_outcome_batch_sha256": (
|
|
855
|
+
self.pilot_outcome_batch_sha256
|
|
856
|
+
),
|
|
857
|
+
"branch": self.branch.value,
|
|
858
|
+
"selected_requirement_sha256": (
|
|
859
|
+
self.selected_requirement_sha256
|
|
860
|
+
),
|
|
861
|
+
"positive_pilot_count": self.positive_pilot_count,
|
|
862
|
+
"pilot_count": self.pilot_count,
|
|
863
|
+
"evidence_sha256": typed_json_sha256(self.evidence),
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
@property
|
|
867
|
+
def selected_branch_id(self) -> str:
|
|
868
|
+
return self.branch.value
|
|
869
|
+
|
|
870
|
+
def to_record(self, *, include_evidence: bool = False) -> dict[str, object]:
|
|
871
|
+
self.__post_init__()
|
|
872
|
+
record = {
|
|
873
|
+
**self._unsigned_record(),
|
|
874
|
+
"decision_sha256": self.decision_sha256,
|
|
875
|
+
}
|
|
876
|
+
if include_evidence:
|
|
877
|
+
record["evidence"] = thaw_json(self.evidence)
|
|
878
|
+
return record
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
@runtime_checkable
|
|
882
|
+
class SequentialAllocationGateDecisionPort(Protocol):
|
|
883
|
+
"""Authenticated selection of one branch frozen in a sequential plan."""
|
|
884
|
+
|
|
885
|
+
gate_id: str
|
|
886
|
+
gate_version: int
|
|
887
|
+
gate_definition_sha256: str
|
|
888
|
+
plan_sha256: str
|
|
889
|
+
pilot_outcome_batch_sha256: str
|
|
890
|
+
selected_requirement_sha256: str
|
|
891
|
+
positive_pilot_count: int
|
|
892
|
+
pilot_count: int
|
|
893
|
+
evidence: FrozenJsonObject
|
|
894
|
+
decision_sha256: str
|
|
895
|
+
|
|
896
|
+
@property
|
|
897
|
+
def selected_branch_id(self) -> str: ...
|
|
898
|
+
|
|
899
|
+
def to_record(
|
|
900
|
+
self,
|
|
901
|
+
*,
|
|
902
|
+
include_evidence: bool = False,
|
|
903
|
+
) -> dict[str, object]: ...
|
|
904
|
+
|
|
905
|
+
|
|
906
|
+
@runtime_checkable
|
|
907
|
+
class SequentialAllocationGatePort(Protocol):
|
|
908
|
+
"""Choose one already-frozen complete slate from pilot evidence."""
|
|
909
|
+
|
|
910
|
+
gate_id: str
|
|
911
|
+
gate_version: int
|
|
912
|
+
definition_sha256: str
|
|
913
|
+
|
|
914
|
+
def decide(
|
|
915
|
+
self,
|
|
916
|
+
plan: SequentialAllocationPlanPort,
|
|
917
|
+
outcomes: SequentialPilotOutcomeBatch,
|
|
918
|
+
) -> SequentialAllocationGateDecisionPort: ...
|
|
919
|
+
|
|
920
|
+
|
|
921
|
+
@dataclass(frozen=True, slots=True)
|
|
922
|
+
class AnyPositiveSequentialLineageGate:
|
|
923
|
+
"""Unlock recursive score-lane competition after any positive pilot."""
|
|
924
|
+
|
|
925
|
+
gate_id: str = ANY_POSITIVE_LINEAGE_GATE_ID
|
|
926
|
+
gate_version: int = ANY_POSITIVE_LINEAGE_GATE_VERSION
|
|
927
|
+
definition_sha256: str = field(init=False)
|
|
928
|
+
|
|
929
|
+
def __post_init__(self) -> None:
|
|
930
|
+
_require_token(self.gate_id, name="gate_id")
|
|
931
|
+
if self.gate_version != ANY_POSITIVE_LINEAGE_GATE_VERSION:
|
|
932
|
+
raise ValueError("gate_version is immutable")
|
|
933
|
+
object.__setattr__(
|
|
934
|
+
self,
|
|
935
|
+
"definition_sha256",
|
|
936
|
+
hashlib.sha256(
|
|
937
|
+
b"agent-evolve:any-positive-lineage-pilot-gate:v1;"
|
|
938
|
+
b"unlock=any-pilot-positive-individual-marginal-utility;"
|
|
939
|
+
b"zero-pilot=locked;branches-frozen-before-outcomes=true;"
|
|
940
|
+
b"workload-model-provider-branches=false"
|
|
941
|
+
).hexdigest(),
|
|
942
|
+
)
|
|
943
|
+
|
|
944
|
+
def decide(
|
|
945
|
+
self,
|
|
946
|
+
plan: SequentialLineageAllocationPlan,
|
|
947
|
+
outcomes: SequentialPilotOutcomeBatch,
|
|
948
|
+
) -> SequentialLineageGateDecision:
|
|
949
|
+
self.__post_init__()
|
|
950
|
+
if type(plan) is not SequentialLineageAllocationPlan:
|
|
951
|
+
raise TypeError("plan must be exact")
|
|
952
|
+
plan.__post_init__()
|
|
953
|
+
if type(outcomes) is not SequentialPilotOutcomeBatch:
|
|
954
|
+
raise TypeError("outcomes must be exact")
|
|
955
|
+
outcomes.__post_init__()
|
|
956
|
+
if (
|
|
957
|
+
outcomes.plan_sha256 != plan.plan_sha256
|
|
958
|
+
or outcomes.residual_request_sha256
|
|
959
|
+
!= plan.residual_request_sha256
|
|
960
|
+
or tuple(value.action_sha256 for value in outcomes.outcomes)
|
|
961
|
+
!= plan.pilot_action_sha256s
|
|
962
|
+
):
|
|
963
|
+
raise ValueError("pilot outcomes differ from their plan")
|
|
964
|
+
positive_count = sum(
|
|
965
|
+
value.positive_marginal_utility for value in outcomes.outcomes
|
|
966
|
+
)
|
|
967
|
+
branch = (
|
|
968
|
+
SequentialLineageBranch.UNLOCKED
|
|
969
|
+
if positive_count > 0
|
|
970
|
+
else SequentialLineageBranch.LOCKED
|
|
971
|
+
)
|
|
972
|
+
selected = plan.branch_requirement(branch)
|
|
973
|
+
return SequentialLineageGateDecision(
|
|
974
|
+
gate_id=self.gate_id,
|
|
975
|
+
gate_version=self.gate_version,
|
|
976
|
+
gate_definition_sha256=self.definition_sha256,
|
|
977
|
+
plan_sha256=plan.plan_sha256,
|
|
978
|
+
pilot_outcome_batch_sha256=outcomes.batch_sha256,
|
|
979
|
+
branch=branch,
|
|
980
|
+
selected_requirement_sha256=selected.requirement_sha256,
|
|
981
|
+
positive_pilot_count=positive_count,
|
|
982
|
+
pilot_count=len(outcomes.outcomes),
|
|
983
|
+
evidence=freeze_json(
|
|
984
|
+
{
|
|
985
|
+
"rule": "unlock_if_any_pilot_positive",
|
|
986
|
+
"only_pilot_outcomes_observed": True,
|
|
987
|
+
"selected_branch_frozen_before_pilot": True,
|
|
988
|
+
"selected_requirement_sha256": (
|
|
989
|
+
selected.requirement_sha256
|
|
990
|
+
),
|
|
991
|
+
"workload_model_provider_branches": False,
|
|
992
|
+
}
|
|
993
|
+
),
|
|
994
|
+
)
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
__all__ = [
|
|
998
|
+
"ANY_POSITIVE_LINEAGE_GATE_ID",
|
|
999
|
+
"ANY_POSITIVE_LINEAGE_GATE_VERSION",
|
|
1000
|
+
"AnyPositiveSequentialLineageGate",
|
|
1001
|
+
"CandidateArchiveMarginalPilotOutcomeProjector",
|
|
1002
|
+
"FrozenBranchSequentialLineagePlanner",
|
|
1003
|
+
"MARGINAL_PILOT_OUTCOME_PROJECTOR_ID",
|
|
1004
|
+
"MARGINAL_PILOT_OUTCOME_PROJECTOR_VERSION",
|
|
1005
|
+
"SEQUENTIAL_LINEAGE_PLANNER_ID",
|
|
1006
|
+
"SEQUENTIAL_LINEAGE_PLANNER_VERSION",
|
|
1007
|
+
"SequentialAllocationGateDecisionPort",
|
|
1008
|
+
"SequentialAllocationGatePort",
|
|
1009
|
+
"SequentialAllocationPlanPort",
|
|
1010
|
+
"SequentialLineageAllocationPlan",
|
|
1011
|
+
"SequentialLineageAllocationPlannerPort",
|
|
1012
|
+
"SequentialLineageBranch",
|
|
1013
|
+
"SequentialLineageGateDecision",
|
|
1014
|
+
"SequentialPilotActionOutcome",
|
|
1015
|
+
"SequentialPilotOutcomeBatch",
|
|
1016
|
+
"SequentialPilotOutcomeProjectorPort",
|
|
1017
|
+
]
|