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,952 @@
|
|
|
1
|
+
"""Generic bridge from typed LLM plans to the materialized-action market.
|
|
2
|
+
|
|
3
|
+
The model selects a parent and one or two opaque finite-action identifiers.
|
|
4
|
+
Trusted engine code materializes those plans, a benchmark-owned phenotype port
|
|
5
|
+
deduplicates executable behavior, and an authoritative evaluation port is
|
|
6
|
+
invoked only for the downstream broker's selected subset.
|
|
7
|
+
|
|
8
|
+
No workload objective, configuration schema, model, provider, or simulator
|
|
9
|
+
identity is interpreted here. A new workload supplies:
|
|
10
|
+
|
|
11
|
+
* a parent-bound :class:`CrossParentFiniteActionSchema`;
|
|
12
|
+
* a phenotype identity projection;
|
|
13
|
+
* canonical parent-position cells;
|
|
14
|
+
* an authoritative selected-action evaluator; and
|
|
15
|
+
* an opaque proposal context containing its scientific semantics and evidence.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import asyncio
|
|
21
|
+
from dataclasses import dataclass, field
|
|
22
|
+
from decimal import Decimal
|
|
23
|
+
import hashlib
|
|
24
|
+
import math
|
|
25
|
+
import re
|
|
26
|
+
from typing import Callable, Protocol, runtime_checkable
|
|
27
|
+
|
|
28
|
+
from agent_evolve.application.materialized_action_broker import (
|
|
29
|
+
MaterializedActionContext,
|
|
30
|
+
MaterializedActionDescriptor,
|
|
31
|
+
)
|
|
32
|
+
from agent_evolve.application.residual_portfolio_evolution import (
|
|
33
|
+
DISJOINT_ACTION_EVALUATION_WAVES_V1,
|
|
34
|
+
DisjointActionEvaluationLedger,
|
|
35
|
+
MaterializedActionEvaluation,
|
|
36
|
+
MaterializedActionEvaluationBatch,
|
|
37
|
+
MaterializedActionProposalBatch,
|
|
38
|
+
ResidualPortfolioDecisionRequest,
|
|
39
|
+
)
|
|
40
|
+
from agent_evolve.application.residual_reachability import (
|
|
41
|
+
CrossParentFiniteActionSchema,
|
|
42
|
+
HierarchicalResidualPlan,
|
|
43
|
+
MaterializedResidualProposal,
|
|
44
|
+
ResidualProposalRole,
|
|
45
|
+
materialize_hierarchical_residual_plan,
|
|
46
|
+
)
|
|
47
|
+
from agent_evolve.domain.ids import CandidateId, LLMCallId
|
|
48
|
+
from agent_evolve.domain.patch import require_sha256
|
|
49
|
+
from agent_evolve.domain.typed_json import (
|
|
50
|
+
FrozenJsonObject,
|
|
51
|
+
freeze_json,
|
|
52
|
+
)
|
|
53
|
+
from agent_evolve.integrations.pydantic_ai.residual_reachability import (
|
|
54
|
+
HierarchicalResidualMetricForecast,
|
|
55
|
+
HierarchicalResidualProposalRequest,
|
|
56
|
+
HierarchicalResidualProposalSelection,
|
|
57
|
+
)
|
|
58
|
+
from agent_evolve.ports.agentic_generator import AgenticCallTelemetry
|
|
59
|
+
from agent_evolve.ports.structured_generator import MAX_OUTPUT_TOKENS
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_ID = (
|
|
63
|
+
"pydantic_ai_materialized_hierarchical_residual_expert"
|
|
64
|
+
)
|
|
65
|
+
MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_VERSION = 2
|
|
66
|
+
MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_DEFINITION_SHA256 = (
|
|
67
|
+
hashlib.sha256(
|
|
68
|
+
b"agent-evolve:pydantic-ai-materialized-hierarchical-residual-expert:v2;"
|
|
69
|
+
b"proposal=parent-plus-one-or-two-opaque-finite-action-ids;"
|
|
70
|
+
b"materialization=trusted-engine-only;"
|
|
71
|
+
b"novelty=benchmark-phenotype-identity;"
|
|
72
|
+
b"evaluation=broker-selected-disjoint-action-subset-waves;"
|
|
73
|
+
b"exactly-once-boundary=action-not-proposal;"
|
|
74
|
+
b"reservation=fail-closed-before-authoritative-evaluator-await;"
|
|
75
|
+
b"context=generic-role-radius-parent-cell;"
|
|
76
|
+
b"workload-model-provider-branches=false"
|
|
77
|
+
).hexdigest()
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
_TOKEN = re.compile(r"^[a-z][a-z0-9_.:-]{0,255}$")
|
|
81
|
+
_OPERATION = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
|
|
82
|
+
_PHENOTYPE_PROJECTION_DOMAIN = (
|
|
83
|
+
b"agent-evolve:materialized-phenotype-projection-port:v1\x00"
|
|
84
|
+
)
|
|
85
|
+
_EVALUATION_PORT_DOMAIN = (
|
|
86
|
+
b"agent-evolve:materialized-action-evaluation-port:v1\x00"
|
|
87
|
+
)
|
|
88
|
+
_BOUND_EXPERT_DEFINITION_DOMAIN = (
|
|
89
|
+
b"agent-evolve:materialized-hierarchical-residual-expert-bound:v1\x00"
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _token(value: str, *, name: str) -> None:
|
|
94
|
+
if type(value) is not str or _TOKEN.fullmatch(value) is None:
|
|
95
|
+
raise ValueError(f"{name} must use the closed token grammar")
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _operation(value: str, *, name: str) -> None:
|
|
99
|
+
if type(value) is not str or _OPERATION.fullmatch(value) is None:
|
|
100
|
+
raise ValueError(f"{name} must use the operation token grammar")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def _port_identity(
|
|
104
|
+
value: object,
|
|
105
|
+
*,
|
|
106
|
+
id_name: str,
|
|
107
|
+
version_name: str,
|
|
108
|
+
definition_name: str,
|
|
109
|
+
domain: bytes,
|
|
110
|
+
) -> tuple[str, int, str]:
|
|
111
|
+
port_id = getattr(value, id_name, None)
|
|
112
|
+
version = getattr(value, version_name, None)
|
|
113
|
+
definition_sha256 = getattr(value, definition_name, None)
|
|
114
|
+
_token(port_id, name=id_name)
|
|
115
|
+
if type(version) is not int or version <= 0:
|
|
116
|
+
raise ValueError(f"{version_name} must be positive")
|
|
117
|
+
require_sha256(definition_sha256, definition_name)
|
|
118
|
+
# Bind the three public fields before returning. This also prevents a
|
|
119
|
+
# malformed dynamic object from accidentally sharing a valid definition.
|
|
120
|
+
hashlib.sha256(
|
|
121
|
+
domain
|
|
122
|
+
+ port_id.encode("ascii")
|
|
123
|
+
+ version.to_bytes(8, "big")
|
|
124
|
+
+ bytes.fromhex(definition_sha256)
|
|
125
|
+
).digest()
|
|
126
|
+
return port_id, version, definition_sha256
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def _bound_expert_definition_sha256(
|
|
130
|
+
source_definition_sha256: str,
|
|
131
|
+
) -> str:
|
|
132
|
+
require_sha256(
|
|
133
|
+
source_definition_sha256,
|
|
134
|
+
"source expert_definition_sha256",
|
|
135
|
+
)
|
|
136
|
+
return hashlib.sha256(
|
|
137
|
+
_BOUND_EXPERT_DEFINITION_DOMAIN
|
|
138
|
+
+ bytes.fromhex(source_definition_sha256)
|
|
139
|
+
+ bytes.fromhex(
|
|
140
|
+
MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_DEFINITION_SHA256
|
|
141
|
+
)
|
|
142
|
+
).hexdigest()
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
@dataclass(frozen=True, slots=True)
|
|
146
|
+
class HierarchicalResidualExpertSpec:
|
|
147
|
+
"""Provider-neutral configuration for one proposal lane."""
|
|
148
|
+
|
|
149
|
+
expert_id: str
|
|
150
|
+
expert_version: int
|
|
151
|
+
expert_definition_sha256: str
|
|
152
|
+
instruction: str
|
|
153
|
+
proposal_count: int
|
|
154
|
+
allowed_radii: tuple[int, ...]
|
|
155
|
+
allowed_roles: tuple[ResidualProposalRole, ...]
|
|
156
|
+
required_metric_ids: tuple[str, ...]
|
|
157
|
+
minimum_distinct_parents: int
|
|
158
|
+
max_output_tokens: int
|
|
159
|
+
temperature: float
|
|
160
|
+
operation: str = "propose_residual_plans"
|
|
161
|
+
|
|
162
|
+
def __post_init__(self) -> None:
|
|
163
|
+
_operation(self.expert_id, name="expert_id")
|
|
164
|
+
if type(self.expert_version) is not int or self.expert_version <= 0:
|
|
165
|
+
raise ValueError("expert_version must be positive")
|
|
166
|
+
require_sha256(
|
|
167
|
+
self.expert_definition_sha256,
|
|
168
|
+
"expert_definition_sha256",
|
|
169
|
+
)
|
|
170
|
+
if (
|
|
171
|
+
type(self.instruction) is not str
|
|
172
|
+
or not self.instruction.strip()
|
|
173
|
+
or len(self.instruction.encode("utf-8")) > 32_768
|
|
174
|
+
):
|
|
175
|
+
raise ValueError("instruction must be non-empty and bounded")
|
|
176
|
+
if (
|
|
177
|
+
type(self.proposal_count) is not int
|
|
178
|
+
or not 1 <= self.proposal_count <= 32
|
|
179
|
+
):
|
|
180
|
+
raise ValueError("proposal_count must lie in [1, 32]")
|
|
181
|
+
if (
|
|
182
|
+
type(self.allowed_radii) is not tuple
|
|
183
|
+
or not self.allowed_radii
|
|
184
|
+
or self.allowed_radii
|
|
185
|
+
!= tuple(sorted(set(self.allowed_radii)))
|
|
186
|
+
or not set(self.allowed_radii).issubset({1, 2})
|
|
187
|
+
):
|
|
188
|
+
raise ValueError(
|
|
189
|
+
"allowed_radii must be a canonical subset of {1, 2}"
|
|
190
|
+
)
|
|
191
|
+
if (
|
|
192
|
+
type(self.allowed_roles) is not tuple
|
|
193
|
+
or not self.allowed_roles
|
|
194
|
+
or any(
|
|
195
|
+
type(value) is not ResidualProposalRole
|
|
196
|
+
for value in self.allowed_roles
|
|
197
|
+
)
|
|
198
|
+
or self.allowed_roles
|
|
199
|
+
!= tuple(
|
|
200
|
+
sorted(
|
|
201
|
+
set(self.allowed_roles),
|
|
202
|
+
key=lambda value: value.value,
|
|
203
|
+
)
|
|
204
|
+
)
|
|
205
|
+
):
|
|
206
|
+
raise ValueError(
|
|
207
|
+
"allowed_roles must be a canonical non-empty tuple"
|
|
208
|
+
)
|
|
209
|
+
if (
|
|
210
|
+
type(self.required_metric_ids) is not tuple
|
|
211
|
+
or not self.required_metric_ids
|
|
212
|
+
or self.required_metric_ids
|
|
213
|
+
!= tuple(sorted(set(self.required_metric_ids)))
|
|
214
|
+
):
|
|
215
|
+
raise ValueError(
|
|
216
|
+
"required_metric_ids must be non-empty and canonical"
|
|
217
|
+
)
|
|
218
|
+
for metric_id in self.required_metric_ids:
|
|
219
|
+
_token(metric_id, name="required metric_id")
|
|
220
|
+
if (
|
|
221
|
+
type(self.minimum_distinct_parents) is not int
|
|
222
|
+
or not 1
|
|
223
|
+
<= self.minimum_distinct_parents
|
|
224
|
+
<= self.proposal_count
|
|
225
|
+
):
|
|
226
|
+
raise ValueError(
|
|
227
|
+
"minimum_distinct_parents must fit proposal_count"
|
|
228
|
+
)
|
|
229
|
+
if (
|
|
230
|
+
type(self.max_output_tokens) is not int
|
|
231
|
+
or not 1 <= self.max_output_tokens <= MAX_OUTPUT_TOKENS
|
|
232
|
+
):
|
|
233
|
+
raise ValueError("max_output_tokens is outside the generic bound")
|
|
234
|
+
if (
|
|
235
|
+
type(self.temperature) is not float
|
|
236
|
+
or not math.isfinite(self.temperature)
|
|
237
|
+
):
|
|
238
|
+
raise TypeError("temperature must be a finite exact float")
|
|
239
|
+
_operation(self.operation, name="operation")
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@dataclass(frozen=True, slots=True)
|
|
243
|
+
class ResidualParentActionContext:
|
|
244
|
+
"""One workload-neutral parent-position label for broker conditioning."""
|
|
245
|
+
|
|
246
|
+
parent_candidate_id: CandidateId
|
|
247
|
+
position_cell: str
|
|
248
|
+
|
|
249
|
+
def __post_init__(self) -> None:
|
|
250
|
+
if type(self.parent_candidate_id) is not CandidateId:
|
|
251
|
+
raise TypeError("parent_candidate_id must be exact")
|
|
252
|
+
CandidateId.__post_init__(self.parent_candidate_id)
|
|
253
|
+
_token(self.position_cell, name="position_cell")
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
@runtime_checkable
|
|
257
|
+
class MaterializedPhenotypeProjectionPort(Protocol):
|
|
258
|
+
"""Project an executable configuration onto benchmark-semantic identity."""
|
|
259
|
+
|
|
260
|
+
projection_id: str
|
|
261
|
+
projection_version: int
|
|
262
|
+
definition_sha256: str
|
|
263
|
+
|
|
264
|
+
def project(self, configuration: FrozenJsonObject) -> str: ...
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
@runtime_checkable
|
|
268
|
+
class SelectedMaterializedActionEvaluationPort(Protocol):
|
|
269
|
+
"""Run exactly one broker-selected action through authoritative truth."""
|
|
270
|
+
|
|
271
|
+
evaluator_id: str
|
|
272
|
+
evaluator_version: int
|
|
273
|
+
definition_sha256: str
|
|
274
|
+
|
|
275
|
+
async def evaluate(
|
|
276
|
+
self,
|
|
277
|
+
action: MaterializedActionDescriptor,
|
|
278
|
+
) -> MaterializedActionEvaluation: ...
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@runtime_checkable
|
|
282
|
+
class HierarchicalResidualProposalPolicyPort(Protocol):
|
|
283
|
+
"""Select typed residual plans; queueing and providers remain injected."""
|
|
284
|
+
|
|
285
|
+
async def select(
|
|
286
|
+
self,
|
|
287
|
+
request: HierarchicalResidualProposalRequest,
|
|
288
|
+
) -> HierarchicalResidualProposalSelection: ...
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
@dataclass(frozen=True, slots=True)
|
|
292
|
+
class MaterializedHierarchicalResidualActionEvidence:
|
|
293
|
+
"""Typed, pre-evaluation semantic claims for one compiled action."""
|
|
294
|
+
|
|
295
|
+
action: MaterializedActionDescriptor
|
|
296
|
+
plan: HierarchicalResidualPlan
|
|
297
|
+
materialized: MaterializedResidualProposal
|
|
298
|
+
provider_rank: int
|
|
299
|
+
materialized_rank: int
|
|
300
|
+
probability_valid: float
|
|
301
|
+
effect_predictions: tuple[
|
|
302
|
+
HierarchicalResidualMetricForecast,
|
|
303
|
+
...,
|
|
304
|
+
]
|
|
305
|
+
rationale: str
|
|
306
|
+
|
|
307
|
+
def __post_init__(self) -> None:
|
|
308
|
+
if type(self.action) is not MaterializedActionDescriptor:
|
|
309
|
+
raise TypeError("action must be exact")
|
|
310
|
+
self.action.__post_init__()
|
|
311
|
+
if type(self.plan) is not HierarchicalResidualPlan:
|
|
312
|
+
raise TypeError("plan must be exact")
|
|
313
|
+
self.plan.__post_init__()
|
|
314
|
+
if type(self.materialized) is not MaterializedResidualProposal:
|
|
315
|
+
raise TypeError("materialized must be exact")
|
|
316
|
+
self.materialized.__post_init__()
|
|
317
|
+
if (
|
|
318
|
+
self.materialized.plan != self.plan
|
|
319
|
+
or self.action.target_candidate_id
|
|
320
|
+
!= self.materialized.target_candidate_id
|
|
321
|
+
or self.action.configuration_sha256
|
|
322
|
+
!= self.materialized.configuration_sha256
|
|
323
|
+
):
|
|
324
|
+
raise ValueError(
|
|
325
|
+
"semantic action evidence does not join its materialization"
|
|
326
|
+
)
|
|
327
|
+
if self.provider_rank != self.plan.native_rank:
|
|
328
|
+
raise ValueError("provider_rank differs from the source plan")
|
|
329
|
+
if (
|
|
330
|
+
type(self.materialized_rank) is not int
|
|
331
|
+
or self.materialized_rank <= 0
|
|
332
|
+
):
|
|
333
|
+
raise ValueError("materialized_rank must be positive")
|
|
334
|
+
if (
|
|
335
|
+
type(self.probability_valid) is not float
|
|
336
|
+
or not 0.0 <= self.probability_valid <= 1.0
|
|
337
|
+
):
|
|
338
|
+
raise ValueError("probability_valid must lie in [0, 1]")
|
|
339
|
+
if (
|
|
340
|
+
type(self.effect_predictions) is not tuple
|
|
341
|
+
or not self.effect_predictions
|
|
342
|
+
or any(
|
|
343
|
+
type(value) is not HierarchicalResidualMetricForecast
|
|
344
|
+
for value in self.effect_predictions
|
|
345
|
+
)
|
|
346
|
+
):
|
|
347
|
+
raise TypeError("effect_predictions must contain exact forecasts")
|
|
348
|
+
for value in self.effect_predictions:
|
|
349
|
+
value.__post_init__()
|
|
350
|
+
metric_ids = tuple(
|
|
351
|
+
value.metric_id for value in self.effect_predictions
|
|
352
|
+
)
|
|
353
|
+
if metric_ids != tuple(sorted(set(metric_ids))):
|
|
354
|
+
raise ValueError("forecast metrics must be canonical")
|
|
355
|
+
if type(self.rationale) is not str or not self.rationale.strip():
|
|
356
|
+
raise ValueError("rationale must be non-empty")
|
|
357
|
+
|
|
358
|
+
def to_record(self) -> dict[str, object]:
|
|
359
|
+
self.__post_init__()
|
|
360
|
+
return {
|
|
361
|
+
"action_sha256": self.action.action_sha256,
|
|
362
|
+
"target_candidate_id": self.action.target_candidate_id.value,
|
|
363
|
+
"parent_candidate_id": self.plan.parent_candidate_id.value,
|
|
364
|
+
"plan_sha256": self.plan.plan_sha256,
|
|
365
|
+
"component_option_ids": list(self.plan.component_option_ids),
|
|
366
|
+
"role": self.plan.role.value,
|
|
367
|
+
"radius": self.plan.radius,
|
|
368
|
+
"provider_rank": self.provider_rank,
|
|
369
|
+
"materialized_rank": self.materialized_rank,
|
|
370
|
+
"probability_valid_hex": self.probability_valid.hex(),
|
|
371
|
+
"effect_predictions": [
|
|
372
|
+
value.to_record() for value in self.effect_predictions
|
|
373
|
+
],
|
|
374
|
+
"rationale": self.rationale,
|
|
375
|
+
"configuration_sha256": self.action.configuration_sha256,
|
|
376
|
+
"phenotype_identity_sha256": (
|
|
377
|
+
self.action.phenotype_identity_sha256
|
|
378
|
+
),
|
|
379
|
+
"materialization_receipt_sha256": (
|
|
380
|
+
self.materialized.engine_materialization_receipt_sha256
|
|
381
|
+
),
|
|
382
|
+
"candidate_outcomes_observed": False,
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
|
|
386
|
+
@runtime_checkable
|
|
387
|
+
class MaterializedHierarchicalResidualActionEvidencePort(Protocol):
|
|
388
|
+
"""Expose sealed pre-evaluation semantics without evaluator outcomes."""
|
|
389
|
+
|
|
390
|
+
expert_id: str
|
|
391
|
+
|
|
392
|
+
def evidence_for(
|
|
393
|
+
self,
|
|
394
|
+
action_sha256: str,
|
|
395
|
+
) -> MaterializedHierarchicalResidualActionEvidence | None: ...
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
def _telemetry_record(value: AgenticCallTelemetry) -> dict[str, object]:
|
|
399
|
+
if type(value) is not AgenticCallTelemetry:
|
|
400
|
+
raise TypeError("telemetry must be exact")
|
|
401
|
+
value.__post_init__()
|
|
402
|
+
return {
|
|
403
|
+
"requested_model": value.requested_model,
|
|
404
|
+
"resolved_model": value.resolved_model,
|
|
405
|
+
"resolved_provider": value.resolved_provider,
|
|
406
|
+
"provider_response_id": value.provider_response_id,
|
|
407
|
+
"finish_reason": value.finish_reason,
|
|
408
|
+
"input_tokens": value.input_tokens,
|
|
409
|
+
"output_tokens": value.output_tokens,
|
|
410
|
+
"reasoning_tokens": value.reasoning_tokens,
|
|
411
|
+
"cache_read_tokens": value.cache_read_tokens,
|
|
412
|
+
"cache_write_tokens": value.cache_write_tokens,
|
|
413
|
+
"cost_usd": (
|
|
414
|
+
None
|
|
415
|
+
if value.cost_usd is None
|
|
416
|
+
else str(Decimal(value.cost_usd))
|
|
417
|
+
),
|
|
418
|
+
"latency_ns": value.latency_ns,
|
|
419
|
+
"attempt_count": value.attempt_count,
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
|
|
423
|
+
@dataclass(slots=True)
|
|
424
|
+
class PydanticAIMaterializedHierarchicalResidualExpert:
|
|
425
|
+
"""Workload-neutral, broker-compatible hierarchical proposal expert."""
|
|
426
|
+
|
|
427
|
+
spec: HierarchicalResidualExpertSpec
|
|
428
|
+
policy: HierarchicalResidualProposalPolicyPort = field(
|
|
429
|
+
repr=False,
|
|
430
|
+
compare=False,
|
|
431
|
+
)
|
|
432
|
+
action_schema: CrossParentFiniteActionSchema = field(
|
|
433
|
+
repr=False,
|
|
434
|
+
compare=False,
|
|
435
|
+
)
|
|
436
|
+
phenotype_projection: MaterializedPhenotypeProjectionPort = field(
|
|
437
|
+
repr=False,
|
|
438
|
+
compare=False,
|
|
439
|
+
)
|
|
440
|
+
evaluator: SelectedMaterializedActionEvaluationPort = field(
|
|
441
|
+
repr=False,
|
|
442
|
+
compare=False,
|
|
443
|
+
)
|
|
444
|
+
parent_contexts: tuple[ResidualParentActionContext, ...]
|
|
445
|
+
observed_phenotype_sha256s: tuple[str, ...]
|
|
446
|
+
memory_dose_bin: int = 0
|
|
447
|
+
telemetry_validator: Callable[[AgenticCallTelemetry], None] | None = field(
|
|
448
|
+
default=None,
|
|
449
|
+
repr=False,
|
|
450
|
+
compare=False,
|
|
451
|
+
)
|
|
452
|
+
selection_sink: Callable[[dict[str, object]], None] | None = field(
|
|
453
|
+
default=None,
|
|
454
|
+
repr=False,
|
|
455
|
+
compare=False,
|
|
456
|
+
)
|
|
457
|
+
materialization_failure_sink: (
|
|
458
|
+
Callable[[dict[str, object]], None] | None
|
|
459
|
+
) = field(default=None, repr=False, compare=False)
|
|
460
|
+
expert_id: str = field(init=False)
|
|
461
|
+
expert_version: int = field(init=False)
|
|
462
|
+
definition_sha256: str = field(init=False)
|
|
463
|
+
result: HierarchicalResidualProposalSelection | None = field(
|
|
464
|
+
init=False,
|
|
465
|
+
default=None,
|
|
466
|
+
)
|
|
467
|
+
action_evidence_by_sha256: dict[
|
|
468
|
+
str,
|
|
469
|
+
MaterializedHierarchicalResidualActionEvidence,
|
|
470
|
+
] = field(init=False, default_factory=dict)
|
|
471
|
+
_proposal: MaterializedActionProposalBatch | None = field(
|
|
472
|
+
init=False,
|
|
473
|
+
default=None,
|
|
474
|
+
)
|
|
475
|
+
evaluation_wave_semantics: str = field(
|
|
476
|
+
init=False,
|
|
477
|
+
default=DISJOINT_ACTION_EVALUATION_WAVES_V1,
|
|
478
|
+
)
|
|
479
|
+
_evaluation_ledger: DisjointActionEvaluationLedger = field(
|
|
480
|
+
init=False,
|
|
481
|
+
default_factory=DisjointActionEvaluationLedger,
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
def __post_init__(self) -> None:
|
|
485
|
+
if type(self.spec) is not HierarchicalResidualExpertSpec:
|
|
486
|
+
raise TypeError("spec must be exact")
|
|
487
|
+
self.spec.__post_init__()
|
|
488
|
+
if not isinstance(
|
|
489
|
+
self.policy,
|
|
490
|
+
HierarchicalResidualProposalPolicyPort,
|
|
491
|
+
):
|
|
492
|
+
raise TypeError("policy must implement its proposal port")
|
|
493
|
+
if type(self.action_schema) is not CrossParentFiniteActionSchema:
|
|
494
|
+
raise TypeError("action_schema must be exact")
|
|
495
|
+
self.action_schema.__post_init__()
|
|
496
|
+
if not isinstance(
|
|
497
|
+
self.phenotype_projection,
|
|
498
|
+
MaterializedPhenotypeProjectionPort,
|
|
499
|
+
):
|
|
500
|
+
raise TypeError(
|
|
501
|
+
"phenotype_projection must implement its runtime port"
|
|
502
|
+
)
|
|
503
|
+
_port_identity(
|
|
504
|
+
self.phenotype_projection,
|
|
505
|
+
id_name="projection_id",
|
|
506
|
+
version_name="projection_version",
|
|
507
|
+
definition_name="definition_sha256",
|
|
508
|
+
domain=_PHENOTYPE_PROJECTION_DOMAIN,
|
|
509
|
+
)
|
|
510
|
+
if not isinstance(
|
|
511
|
+
self.evaluator,
|
|
512
|
+
SelectedMaterializedActionEvaluationPort,
|
|
513
|
+
):
|
|
514
|
+
raise TypeError("evaluator must implement its runtime port")
|
|
515
|
+
_port_identity(
|
|
516
|
+
self.evaluator,
|
|
517
|
+
id_name="evaluator_id",
|
|
518
|
+
version_name="evaluator_version",
|
|
519
|
+
definition_name="definition_sha256",
|
|
520
|
+
domain=_EVALUATION_PORT_DOMAIN,
|
|
521
|
+
)
|
|
522
|
+
if (
|
|
523
|
+
type(self.parent_contexts) is not tuple
|
|
524
|
+
or not self.parent_contexts
|
|
525
|
+
or any(
|
|
526
|
+
type(value) is not ResidualParentActionContext
|
|
527
|
+
for value in self.parent_contexts
|
|
528
|
+
)
|
|
529
|
+
):
|
|
530
|
+
raise TypeError(
|
|
531
|
+
"parent_contexts must contain exact non-empty values"
|
|
532
|
+
)
|
|
533
|
+
for value in self.parent_contexts:
|
|
534
|
+
value.__post_init__()
|
|
535
|
+
parent_ids = tuple(
|
|
536
|
+
value.parent_candidate_id.value
|
|
537
|
+
for value in self.parent_contexts
|
|
538
|
+
)
|
|
539
|
+
if parent_ids != tuple(sorted(set(parent_ids))):
|
|
540
|
+
raise ValueError("parent_contexts must be unique and canonical")
|
|
541
|
+
schema_parent_ids = tuple(
|
|
542
|
+
value.parent_candidate_id.value
|
|
543
|
+
for value in self.action_schema.bindings
|
|
544
|
+
)
|
|
545
|
+
if parent_ids != schema_parent_ids:
|
|
546
|
+
raise ValueError(
|
|
547
|
+
"parent_contexts must exactly cover the action schema"
|
|
548
|
+
)
|
|
549
|
+
if (
|
|
550
|
+
type(self.observed_phenotype_sha256s) is not tuple
|
|
551
|
+
or self.observed_phenotype_sha256s
|
|
552
|
+
!= tuple(sorted(set(self.observed_phenotype_sha256s)))
|
|
553
|
+
):
|
|
554
|
+
raise ValueError(
|
|
555
|
+
"observed phenotype identities must be canonical"
|
|
556
|
+
)
|
|
557
|
+
for value in self.observed_phenotype_sha256s:
|
|
558
|
+
require_sha256(value, "observed phenotype identity")
|
|
559
|
+
if (
|
|
560
|
+
type(self.memory_dose_bin) is not int
|
|
561
|
+
or not 0 <= self.memory_dose_bin <= 15
|
|
562
|
+
):
|
|
563
|
+
raise ValueError("memory_dose_bin must lie in [0, 15]")
|
|
564
|
+
for value, name in (
|
|
565
|
+
(self.telemetry_validator, "telemetry_validator"),
|
|
566
|
+
(self.selection_sink, "selection_sink"),
|
|
567
|
+
(
|
|
568
|
+
self.materialization_failure_sink,
|
|
569
|
+
"materialization_failure_sink",
|
|
570
|
+
),
|
|
571
|
+
):
|
|
572
|
+
if value is not None and not callable(value):
|
|
573
|
+
raise TypeError(f"{name} must be callable or None")
|
|
574
|
+
if self.spec.minimum_distinct_parents > len(
|
|
575
|
+
self.action_schema.bindings
|
|
576
|
+
):
|
|
577
|
+
raise ValueError(
|
|
578
|
+
"minimum_distinct_parents exceeds schema parent count"
|
|
579
|
+
)
|
|
580
|
+
self.expert_id = self.spec.expert_id
|
|
581
|
+
self.expert_version = self.spec.expert_version
|
|
582
|
+
self.definition_sha256 = _bound_expert_definition_sha256(
|
|
583
|
+
self.spec.expert_definition_sha256
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
@property
|
|
587
|
+
def proposal_count(self) -> int:
|
|
588
|
+
return self.spec.proposal_count
|
|
589
|
+
|
|
590
|
+
def evidence_for(
|
|
591
|
+
self,
|
|
592
|
+
action_sha256: str,
|
|
593
|
+
) -> MaterializedHierarchicalResidualActionEvidence | None:
|
|
594
|
+
require_sha256(action_sha256, "action_sha256")
|
|
595
|
+
return self.action_evidence_by_sha256.get(action_sha256)
|
|
596
|
+
|
|
597
|
+
def _call_id(
|
|
598
|
+
self,
|
|
599
|
+
request: ResidualPortfolioDecisionRequest,
|
|
600
|
+
) -> LLMCallId:
|
|
601
|
+
digest = hashlib.sha256(
|
|
602
|
+
bytes.fromhex(request.request_sha256)
|
|
603
|
+
+ self.expert_id.encode("ascii")
|
|
604
|
+
).hexdigest()
|
|
605
|
+
return LLMCallId(
|
|
606
|
+
f"call_residual_d{request.decision_index:04d}_{digest[:24]}"
|
|
607
|
+
)
|
|
608
|
+
|
|
609
|
+
def _failure(
|
|
610
|
+
self,
|
|
611
|
+
*,
|
|
612
|
+
request: ResidualPortfolioDecisionRequest,
|
|
613
|
+
plan: HierarchicalResidualPlan,
|
|
614
|
+
error: Exception,
|
|
615
|
+
) -> None:
|
|
616
|
+
if self.materialization_failure_sink is None:
|
|
617
|
+
return
|
|
618
|
+
self.materialization_failure_sink(
|
|
619
|
+
{
|
|
620
|
+
"schema_version": 1,
|
|
621
|
+
"adapter_definition_sha256": (
|
|
622
|
+
MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_DEFINITION_SHA256
|
|
623
|
+
),
|
|
624
|
+
"residual_request_sha256": request.request_sha256,
|
|
625
|
+
"expert_id": self.expert_id,
|
|
626
|
+
"plan": plan.to_record(),
|
|
627
|
+
"failure_type": type(error).__name__,
|
|
628
|
+
"failure_message": str(error),
|
|
629
|
+
"candidate_outcomes_observed": False,
|
|
630
|
+
}
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
async def propose(
|
|
634
|
+
self,
|
|
635
|
+
request: ResidualPortfolioDecisionRequest,
|
|
636
|
+
) -> MaterializedActionProposalBatch:
|
|
637
|
+
self.__post_init__()
|
|
638
|
+
if type(request) is not ResidualPortfolioDecisionRequest:
|
|
639
|
+
raise TypeError("request must be exact")
|
|
640
|
+
request.__post_init__()
|
|
641
|
+
if self._proposal is not None:
|
|
642
|
+
raise ValueError("one stage expert can propose only once")
|
|
643
|
+
if request.proposal_slots_for(self.expert_id) != self.proposal_count:
|
|
644
|
+
raise ValueError(
|
|
645
|
+
"residual proposal capacity differs from the expert spec"
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
selection_request = HierarchicalResidualProposalRequest(
|
|
649
|
+
call_id=self._call_id(request),
|
|
650
|
+
operation=self.spec.operation,
|
|
651
|
+
instruction=self.spec.instruction,
|
|
652
|
+
context=request.proposal_context,
|
|
653
|
+
action_schema=self.action_schema,
|
|
654
|
+
proposal_count=self.spec.proposal_count,
|
|
655
|
+
allowed_radii=self.spec.allowed_radii,
|
|
656
|
+
allowed_roles=self.spec.allowed_roles,
|
|
657
|
+
required_metric_ids=self.spec.required_metric_ids,
|
|
658
|
+
minimum_distinct_parents=(
|
|
659
|
+
self.spec.minimum_distinct_parents
|
|
660
|
+
),
|
|
661
|
+
expert_id=self.expert_id,
|
|
662
|
+
expert_definition_sha256=self.definition_sha256,
|
|
663
|
+
max_output_tokens=self.spec.max_output_tokens,
|
|
664
|
+
temperature=self.spec.temperature,
|
|
665
|
+
)
|
|
666
|
+
result = await self.policy.select(selection_request)
|
|
667
|
+
if type(result) is not HierarchicalResidualProposalSelection:
|
|
668
|
+
raise TypeError("proposal policy returned a foreign selection")
|
|
669
|
+
result.__post_init__()
|
|
670
|
+
if result.request_sha256 != selection_request.request_sha256:
|
|
671
|
+
raise ValueError("proposal policy selected for another request")
|
|
672
|
+
if self.telemetry_validator is not None:
|
|
673
|
+
self.telemetry_validator(result.telemetry)
|
|
674
|
+
self.result = result
|
|
675
|
+
if self.selection_sink is not None:
|
|
676
|
+
self.selection_sink(
|
|
677
|
+
{
|
|
678
|
+
"schema_version": 1,
|
|
679
|
+
"adapter_definition_sha256": (
|
|
680
|
+
MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_DEFINITION_SHA256
|
|
681
|
+
),
|
|
682
|
+
"residual_request_sha256": request.request_sha256,
|
|
683
|
+
"selection": result.to_record(),
|
|
684
|
+
"telemetry": _telemetry_record(result.telemetry),
|
|
685
|
+
"candidate_outcomes_observed": False,
|
|
686
|
+
}
|
|
687
|
+
)
|
|
688
|
+
|
|
689
|
+
position_by_parent = {
|
|
690
|
+
value.parent_candidate_id: value.position_cell
|
|
691
|
+
for value in self.parent_contexts
|
|
692
|
+
}
|
|
693
|
+
observed = set(self.observed_phenotype_sha256s)
|
|
694
|
+
unique_by_phenotype: dict[
|
|
695
|
+
str,
|
|
696
|
+
tuple[
|
|
697
|
+
HierarchicalResidualPlan,
|
|
698
|
+
str,
|
|
699
|
+
float,
|
|
700
|
+
tuple[HierarchicalResidualMetricForecast, ...],
|
|
701
|
+
MaterializedResidualProposal,
|
|
702
|
+
],
|
|
703
|
+
] = {}
|
|
704
|
+
for plan, rationale, probability_valid, predictions in zip(
|
|
705
|
+
result.plans,
|
|
706
|
+
result.rationales,
|
|
707
|
+
result.probability_valid,
|
|
708
|
+
result.effect_predictions,
|
|
709
|
+
strict=True,
|
|
710
|
+
):
|
|
711
|
+
target = CandidateId(
|
|
712
|
+
"candidate_residual_"
|
|
713
|
+
f"d{request.decision_index:04d}_{plan.plan_sha256[:24]}"
|
|
714
|
+
)
|
|
715
|
+
try:
|
|
716
|
+
materialized = materialize_hierarchical_residual_plan(
|
|
717
|
+
schema=self.action_schema,
|
|
718
|
+
plan=plan,
|
|
719
|
+
target_candidate_id=target,
|
|
720
|
+
)
|
|
721
|
+
phenotype_sha256 = self.phenotype_projection.project(
|
|
722
|
+
materialized.configuration
|
|
723
|
+
)
|
|
724
|
+
require_sha256(
|
|
725
|
+
phenotype_sha256,
|
|
726
|
+
"projected phenotype identity",
|
|
727
|
+
)
|
|
728
|
+
except (TypeError, ValueError, RuntimeError) as error:
|
|
729
|
+
self._failure(
|
|
730
|
+
request=request,
|
|
731
|
+
plan=plan,
|
|
732
|
+
error=error,
|
|
733
|
+
)
|
|
734
|
+
continue
|
|
735
|
+
if phenotype_sha256 in observed:
|
|
736
|
+
continue
|
|
737
|
+
unique_by_phenotype.setdefault(
|
|
738
|
+
phenotype_sha256,
|
|
739
|
+
(
|
|
740
|
+
plan,
|
|
741
|
+
rationale,
|
|
742
|
+
probability_valid,
|
|
743
|
+
predictions,
|
|
744
|
+
materialized,
|
|
745
|
+
),
|
|
746
|
+
)
|
|
747
|
+
|
|
748
|
+
actions: list[MaterializedActionDescriptor] = []
|
|
749
|
+
evidence_rows: list[
|
|
750
|
+
MaterializedHierarchicalResidualActionEvidence
|
|
751
|
+
] = []
|
|
752
|
+
for rank, (
|
|
753
|
+
phenotype_sha256,
|
|
754
|
+
(
|
|
755
|
+
plan,
|
|
756
|
+
rationale,
|
|
757
|
+
probability_valid,
|
|
758
|
+
predictions,
|
|
759
|
+
materialized,
|
|
760
|
+
),
|
|
761
|
+
) in enumerate(unique_by_phenotype.items(), start=1):
|
|
762
|
+
role = plan.role.value
|
|
763
|
+
action = MaterializedActionDescriptor(
|
|
764
|
+
context=MaterializedActionContext(
|
|
765
|
+
campaign_scope_sha256=request.campaign_scope_sha256,
|
|
766
|
+
decision_index=request.decision_index,
|
|
767
|
+
phase=request.phase,
|
|
768
|
+
remaining_decisions=request.remaining_decisions,
|
|
769
|
+
remaining_evaluations=request.remaining_evaluations,
|
|
770
|
+
residual_frontier_cell=f"{role}.r{plan.radius}",
|
|
771
|
+
parent_position_cell=position_by_parent[
|
|
772
|
+
plan.parent_candidate_id
|
|
773
|
+
],
|
|
774
|
+
archive_relation_cell="unknown_pre_eval",
|
|
775
|
+
structural_signature_sha256=phenotype_sha256,
|
|
776
|
+
patch_compatibility_cell=(
|
|
777
|
+
"safe_disjoint"
|
|
778
|
+
if plan.radius == 2
|
|
779
|
+
else "atomic"
|
|
780
|
+
),
|
|
781
|
+
forecast_calibration_cell="trace_addressable",
|
|
782
|
+
source_distance_bin=plan.radius,
|
|
783
|
+
memory_dose_bin=self.memory_dose_bin,
|
|
784
|
+
),
|
|
785
|
+
configuration=materialized.configuration,
|
|
786
|
+
phenotype_identity_sha256=phenotype_sha256,
|
|
787
|
+
expert_id=self.expert_id,
|
|
788
|
+
native_rank=rank,
|
|
789
|
+
parent_ids=(plan.parent_candidate_id,),
|
|
790
|
+
operator_id=f"{role}.r{plan.radius}",
|
|
791
|
+
target_candidate_id=materialized.target_candidate_id,
|
|
792
|
+
role_id=role,
|
|
793
|
+
normalized_evaluation_cost=1.0,
|
|
794
|
+
reference_action=False,
|
|
795
|
+
)
|
|
796
|
+
evidence = MaterializedHierarchicalResidualActionEvidence(
|
|
797
|
+
action=action,
|
|
798
|
+
plan=plan,
|
|
799
|
+
materialized=materialized,
|
|
800
|
+
provider_rank=plan.native_rank,
|
|
801
|
+
materialized_rank=rank,
|
|
802
|
+
probability_valid=probability_valid,
|
|
803
|
+
effect_predictions=predictions,
|
|
804
|
+
rationale=rationale,
|
|
805
|
+
)
|
|
806
|
+
actions.append(action)
|
|
807
|
+
evidence_rows.append(evidence)
|
|
808
|
+
self.action_evidence_by_sha256[action.action_sha256] = evidence
|
|
809
|
+
if not actions:
|
|
810
|
+
raise RuntimeError(
|
|
811
|
+
f"{self.expert_id} produced no novel materialized action"
|
|
812
|
+
)
|
|
813
|
+
|
|
814
|
+
proposal = MaterializedActionProposalBatch(
|
|
815
|
+
request_sha256=request.request_sha256,
|
|
816
|
+
expert_id=self.expert_id,
|
|
817
|
+
expert_version=self.expert_version,
|
|
818
|
+
expert_definition_sha256=self.definition_sha256,
|
|
819
|
+
actions=tuple(actions),
|
|
820
|
+
evidence=freeze_json(
|
|
821
|
+
{
|
|
822
|
+
"schema_version": 1,
|
|
823
|
+
"adapter": {
|
|
824
|
+
"adapter_id": (
|
|
825
|
+
MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_ID
|
|
826
|
+
),
|
|
827
|
+
"adapter_version": (
|
|
828
|
+
MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_VERSION
|
|
829
|
+
),
|
|
830
|
+
"definition_sha256": (
|
|
831
|
+
MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_DEFINITION_SHA256
|
|
832
|
+
),
|
|
833
|
+
},
|
|
834
|
+
"selection_decision_sha256": result.decision_sha256,
|
|
835
|
+
"phenotype_projection": {
|
|
836
|
+
"projection_id": (
|
|
837
|
+
self.phenotype_projection.projection_id
|
|
838
|
+
),
|
|
839
|
+
"projection_version": (
|
|
840
|
+
self.phenotype_projection.projection_version
|
|
841
|
+
),
|
|
842
|
+
"definition_sha256": (
|
|
843
|
+
self.phenotype_projection.definition_sha256
|
|
844
|
+
),
|
|
845
|
+
},
|
|
846
|
+
"common_prior_state_sha256": (
|
|
847
|
+
request.prior_state_sha256
|
|
848
|
+
),
|
|
849
|
+
"members": [
|
|
850
|
+
value.to_record() for value in evidence_rows
|
|
851
|
+
],
|
|
852
|
+
"requested_member_count": self.proposal_count,
|
|
853
|
+
"materialized_novel_member_count": len(actions),
|
|
854
|
+
"real_evaluations": 0,
|
|
855
|
+
"broker_selected_subset_only": True,
|
|
856
|
+
"candidate_outcomes_observed": False,
|
|
857
|
+
}
|
|
858
|
+
),
|
|
859
|
+
)
|
|
860
|
+
self._proposal = proposal
|
|
861
|
+
return proposal
|
|
862
|
+
|
|
863
|
+
async def evaluate(
|
|
864
|
+
self,
|
|
865
|
+
proposal: MaterializedActionProposalBatch,
|
|
866
|
+
selected_action_sha256s: tuple[str, ...],
|
|
867
|
+
) -> MaterializedActionEvaluationBatch:
|
|
868
|
+
if proposal is not self._proposal:
|
|
869
|
+
raise ValueError("expert received a foreign proposal")
|
|
870
|
+
if (
|
|
871
|
+
type(selected_action_sha256s) is not tuple
|
|
872
|
+
or not selected_action_sha256s
|
|
873
|
+
or selected_action_sha256s
|
|
874
|
+
!= tuple(sorted(set(selected_action_sha256s)))
|
|
875
|
+
):
|
|
876
|
+
raise ValueError(
|
|
877
|
+
"selected action hashes must be non-empty and canonical"
|
|
878
|
+
)
|
|
879
|
+
action_by_sha256 = {
|
|
880
|
+
value.action_sha256: value for value in proposal.actions
|
|
881
|
+
}
|
|
882
|
+
try:
|
|
883
|
+
selected_actions = tuple(
|
|
884
|
+
action_by_sha256[value]
|
|
885
|
+
for value in selected_action_sha256s
|
|
886
|
+
)
|
|
887
|
+
except KeyError as error:
|
|
888
|
+
raise ValueError(
|
|
889
|
+
"broker selected outside the expert proposal"
|
|
890
|
+
) from error
|
|
891
|
+
wave = self._evaluation_ledger.reserve(
|
|
892
|
+
proposal,
|
|
893
|
+
selected_action_sha256s,
|
|
894
|
+
)
|
|
895
|
+
evaluations = tuple(
|
|
896
|
+
await asyncio.gather(
|
|
897
|
+
*(
|
|
898
|
+
self.evaluator.evaluate(action)
|
|
899
|
+
for action in selected_actions
|
|
900
|
+
)
|
|
901
|
+
)
|
|
902
|
+
)
|
|
903
|
+
for action, evaluation in zip(
|
|
904
|
+
selected_actions,
|
|
905
|
+
evaluations,
|
|
906
|
+
strict=True,
|
|
907
|
+
):
|
|
908
|
+
if type(evaluation) is not MaterializedActionEvaluation:
|
|
909
|
+
raise TypeError("evaluation port returned a foreign value")
|
|
910
|
+
evaluation.__post_init__()
|
|
911
|
+
if evaluation.action != action:
|
|
912
|
+
raise ValueError(
|
|
913
|
+
"evaluation port returned another selected action"
|
|
914
|
+
)
|
|
915
|
+
return MaterializedActionEvaluationBatch(
|
|
916
|
+
proposal_sha256=proposal.proposal_sha256,
|
|
917
|
+
expert_id=self.expert_id,
|
|
918
|
+
expert_version=self.expert_version,
|
|
919
|
+
expert_definition_sha256=self.definition_sha256,
|
|
920
|
+
selected_action_sha256s=selected_action_sha256s,
|
|
921
|
+
evaluations=evaluations,
|
|
922
|
+
evidence=freeze_json(
|
|
923
|
+
{
|
|
924
|
+
"schema_version": 1,
|
|
925
|
+
"evaluator": {
|
|
926
|
+
"evaluator_id": self.evaluator.evaluator_id,
|
|
927
|
+
"evaluator_version": self.evaluator.evaluator_version,
|
|
928
|
+
"definition_sha256": (
|
|
929
|
+
self.evaluator.definition_sha256
|
|
930
|
+
),
|
|
931
|
+
},
|
|
932
|
+
"real_evaluator_calls": len(evaluations),
|
|
933
|
+
"evaluation_wave": wave.to_record(),
|
|
934
|
+
"broker_selected_subset_only": True,
|
|
935
|
+
}
|
|
936
|
+
),
|
|
937
|
+
)
|
|
938
|
+
|
|
939
|
+
|
|
940
|
+
__all__ = [
|
|
941
|
+
"HierarchicalResidualExpertSpec",
|
|
942
|
+
"HierarchicalResidualProposalPolicyPort",
|
|
943
|
+
"MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_DEFINITION_SHA256",
|
|
944
|
+
"MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_ID",
|
|
945
|
+
"MATERIALIZED_HIERARCHICAL_RESIDUAL_EXPERT_ADAPTER_VERSION",
|
|
946
|
+
"MaterializedHierarchicalResidualActionEvidence",
|
|
947
|
+
"MaterializedHierarchicalResidualActionEvidencePort",
|
|
948
|
+
"MaterializedPhenotypeProjectionPort",
|
|
949
|
+
"PydanticAIMaterializedHierarchicalResidualExpert",
|
|
950
|
+
"ResidualParentActionContext",
|
|
951
|
+
"SelectedMaterializedActionEvaluationPort",
|
|
952
|
+
]
|