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,571 @@
|
|
|
1
|
+
"""Provider-neutral orchestration strategies for structured reflection calls.
|
|
2
|
+
|
|
3
|
+
The evolutionary engine owns evidence construction and memory publication.
|
|
4
|
+
This module owns only how an already-frozen reflection batch is divided into
|
|
5
|
+
logical model calls. Keeping that seam in the application layer lets an
|
|
6
|
+
experiment change reflection topology without teaching the provider adapter or
|
|
7
|
+
any benchmark about the change.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import asyncio
|
|
13
|
+
import math
|
|
14
|
+
import re
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from typing import Protocol, runtime_checkable
|
|
18
|
+
|
|
19
|
+
from agent_evolve.domain.ids import LLMCallId
|
|
20
|
+
from agent_evolve.ports.agentic_generator import (
|
|
21
|
+
AgenticGenerator,
|
|
22
|
+
InsightDraft,
|
|
23
|
+
ReflectionGenerationRequest,
|
|
24
|
+
ReflectionGenerationResult,
|
|
25
|
+
ReflectionInsightContract,
|
|
26
|
+
validate_reflection_insight_draft,
|
|
27
|
+
)
|
|
28
|
+
from agent_evolve.ports.generation_failure import (
|
|
29
|
+
GenerationFailureDisposition,
|
|
30
|
+
classify_generation_failure,
|
|
31
|
+
)
|
|
32
|
+
from agent_evolve.ports.id_factory import IdFactory
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
_LOWER_SHA256 = re.compile(r"^[0-9a-f]{64}$")
|
|
36
|
+
_SPACE = re.compile(r"\s+")
|
|
37
|
+
ReflectionCallPlannedSink = Callable[
|
|
38
|
+
["PlannedReflectionCall | PlannedReflectionBatchCall"], None
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True, slots=True)
|
|
43
|
+
class ReflectionPromptShard:
|
|
44
|
+
"""One exact engine-derived contrast and its self-contained prompt."""
|
|
45
|
+
|
|
46
|
+
contrast_id: str
|
|
47
|
+
prompt: str
|
|
48
|
+
|
|
49
|
+
def __post_init__(self) -> None:
|
|
50
|
+
if (
|
|
51
|
+
type(self.contrast_id) is not str
|
|
52
|
+
or _LOWER_SHA256.fullmatch(self.contrast_id) is None
|
|
53
|
+
):
|
|
54
|
+
raise ValueError("contrast_id must be a lowercase SHA-256 digest")
|
|
55
|
+
if type(self.prompt) is not str or not self.prompt.strip():
|
|
56
|
+
raise ValueError("reflection shard prompt must be non-empty")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass(frozen=True, slots=True)
|
|
60
|
+
class ReflectionWorkflowRequest:
|
|
61
|
+
"""A complete staged reflection batch before any call ID is allocated."""
|
|
62
|
+
|
|
63
|
+
operation: str
|
|
64
|
+
shards: tuple[ReflectionPromptShard, ...]
|
|
65
|
+
max_output_tokens: int
|
|
66
|
+
temperature: float | None = None
|
|
67
|
+
insight_contract: ReflectionInsightContract | None = None
|
|
68
|
+
batch_prompt: str | None = None
|
|
69
|
+
|
|
70
|
+
def __post_init__(self) -> None:
|
|
71
|
+
if type(self.operation) is not str or not self.operation.strip():
|
|
72
|
+
raise ValueError("reflection operation must be non-empty")
|
|
73
|
+
if type(self.shards) is not tuple or not self.shards:
|
|
74
|
+
raise ValueError("reflection workflow requires at least one shard")
|
|
75
|
+
for shard in self.shards:
|
|
76
|
+
if type(shard) is not ReflectionPromptShard:
|
|
77
|
+
raise TypeError("shards must contain exact ReflectionPromptShard values")
|
|
78
|
+
ReflectionPromptShard.__post_init__(shard)
|
|
79
|
+
contrast_ids = tuple(shard.contrast_id for shard in self.shards)
|
|
80
|
+
if len(set(contrast_ids)) != len(contrast_ids):
|
|
81
|
+
raise ValueError("reflection workflow contrast IDs must be unique")
|
|
82
|
+
if type(self.max_output_tokens) is not int or self.max_output_tokens <= 0:
|
|
83
|
+
raise ValueError("max_output_tokens must be positive")
|
|
84
|
+
if self.temperature is not None and (
|
|
85
|
+
isinstance(self.temperature, bool)
|
|
86
|
+
or not isinstance(self.temperature, (int, float))
|
|
87
|
+
or not math.isfinite(float(self.temperature))
|
|
88
|
+
or float(self.temperature) < 0
|
|
89
|
+
):
|
|
90
|
+
raise ValueError("temperature must be finite and non-negative or None")
|
|
91
|
+
if self.insight_contract is not None:
|
|
92
|
+
if type(self.insight_contract) is not ReflectionInsightContract:
|
|
93
|
+
raise TypeError(
|
|
94
|
+
"insight_contract must be an exact ReflectionInsightContract"
|
|
95
|
+
)
|
|
96
|
+
ReflectionInsightContract.__post_init__(self.insight_contract)
|
|
97
|
+
if self.batch_prompt is not None and (
|
|
98
|
+
type(self.batch_prompt) is not str or not self.batch_prompt.strip()
|
|
99
|
+
):
|
|
100
|
+
raise ValueError("batch_prompt must be non-empty exact text or None")
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@dataclass(frozen=True, slots=True)
|
|
104
|
+
class PlannedReflectionCall:
|
|
105
|
+
"""One deterministic logical call allocated before concurrent execution."""
|
|
106
|
+
|
|
107
|
+
contrast_id: str
|
|
108
|
+
request: ReflectionGenerationRequest
|
|
109
|
+
|
|
110
|
+
def __post_init__(self) -> None:
|
|
111
|
+
if (
|
|
112
|
+
type(self.contrast_id) is not str
|
|
113
|
+
or _LOWER_SHA256.fullmatch(self.contrast_id) is None
|
|
114
|
+
):
|
|
115
|
+
raise ValueError("contrast_id must be a lowercase SHA-256 digest")
|
|
116
|
+
if type(self.request) is not ReflectionGenerationRequest:
|
|
117
|
+
raise TypeError("request must be an exact ReflectionGenerationRequest")
|
|
118
|
+
ReflectionGenerationRequest.__post_init__(self.request)
|
|
119
|
+
if self.request.available_contrast_ids != (self.contrast_id,):
|
|
120
|
+
raise ValueError("a sharded call must expose exactly its assigned contrast")
|
|
121
|
+
if self.request.min_insights != 1 or self.request.max_insights != 1:
|
|
122
|
+
raise ValueError("a sharded call must require exactly one insight")
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def call_id(self) -> LLMCallId:
|
|
126
|
+
return self.request.call_id
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass(frozen=True, slots=True)
|
|
130
|
+
class PlannedReflectionBatchCall:
|
|
131
|
+
"""One deterministic logical call covering an exact contrast batch."""
|
|
132
|
+
|
|
133
|
+
contrast_ids: tuple[str, ...]
|
|
134
|
+
request: ReflectionGenerationRequest
|
|
135
|
+
|
|
136
|
+
def __post_init__(self) -> None:
|
|
137
|
+
if type(self.contrast_ids) is not tuple or not self.contrast_ids:
|
|
138
|
+
raise ValueError("a batched reflection call requires contrast IDs")
|
|
139
|
+
if self.contrast_ids != tuple(sorted(set(self.contrast_ids))):
|
|
140
|
+
raise ValueError("batched contrast IDs must be unique and canonical")
|
|
141
|
+
if any(_LOWER_SHA256.fullmatch(item) is None for item in self.contrast_ids):
|
|
142
|
+
raise ValueError("batched contrast IDs must be lowercase SHA-256 digests")
|
|
143
|
+
if type(self.request) is not ReflectionGenerationRequest:
|
|
144
|
+
raise TypeError("request must be an exact ReflectionGenerationRequest")
|
|
145
|
+
ReflectionGenerationRequest.__post_init__(self.request)
|
|
146
|
+
if self.request.available_contrast_ids != self.contrast_ids:
|
|
147
|
+
raise ValueError("batched request exposes the wrong contrast set")
|
|
148
|
+
expected_count = len(self.contrast_ids)
|
|
149
|
+
if (
|
|
150
|
+
self.request.min_insights != expected_count
|
|
151
|
+
or self.request.max_insights != expected_count
|
|
152
|
+
):
|
|
153
|
+
raise ValueError("batched request must require one card per contrast")
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def call_id(self) -> LLMCallId:
|
|
157
|
+
return self.request.call_id
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@dataclass(frozen=True, slots=True)
|
|
161
|
+
class ReflectionShardResult:
|
|
162
|
+
"""One contrast-bound card and the logical call that produced it.
|
|
163
|
+
|
|
164
|
+
A contrast-sharded workflow has one singleton generation result per card.
|
|
165
|
+
A strict batched workflow deliberately shares one multi-card generation
|
|
166
|
+
result across every returned card. In both cases the exact draft must be
|
|
167
|
+
present in the bound result and must cite only this contrast.
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
contrast_id: str
|
|
171
|
+
call_id: LLMCallId
|
|
172
|
+
draft: InsightDraft
|
|
173
|
+
generation_result: ReflectionGenerationResult
|
|
174
|
+
|
|
175
|
+
def __post_init__(self) -> None:
|
|
176
|
+
if (
|
|
177
|
+
type(self.contrast_id) is not str
|
|
178
|
+
or _LOWER_SHA256.fullmatch(self.contrast_id) is None
|
|
179
|
+
):
|
|
180
|
+
raise ValueError("contrast_id must be a lowercase SHA-256 digest")
|
|
181
|
+
if not isinstance(self.call_id, LLMCallId):
|
|
182
|
+
raise TypeError("call_id must be an LLMCallId")
|
|
183
|
+
if type(self.draft) is not InsightDraft:
|
|
184
|
+
raise TypeError("draft must be an exact InsightDraft")
|
|
185
|
+
InsightDraft.__post_init__(self.draft)
|
|
186
|
+
if self.draft.evidence_contrast_ids != (self.contrast_id,):
|
|
187
|
+
raise ValueError("accepted shard card must cite exactly its origin contrast")
|
|
188
|
+
if type(self.generation_result) is not ReflectionGenerationResult:
|
|
189
|
+
raise TypeError(
|
|
190
|
+
"generation_result must be an exact ReflectionGenerationResult"
|
|
191
|
+
)
|
|
192
|
+
if self.draft not in self.generation_result.insights:
|
|
193
|
+
raise ValueError("generation result does not contain its accepted card")
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@dataclass(frozen=True, slots=True)
|
|
197
|
+
class ReflectionWorkflowResult:
|
|
198
|
+
"""A complete validated batch, still staged outside durable memory."""
|
|
199
|
+
|
|
200
|
+
shards: tuple[ReflectionShardResult, ...]
|
|
201
|
+
|
|
202
|
+
def __post_init__(self) -> None:
|
|
203
|
+
if type(self.shards) is not tuple or not self.shards:
|
|
204
|
+
raise ValueError("reflection workflow result requires accepted shards")
|
|
205
|
+
if any(type(shard) is not ReflectionShardResult for shard in self.shards):
|
|
206
|
+
raise TypeError("shards must contain exact ReflectionShardResult values")
|
|
207
|
+
for shard in self.shards:
|
|
208
|
+
ReflectionShardResult.__post_init__(shard)
|
|
209
|
+
contrast_ids = tuple(shard.contrast_id for shard in self.shards)
|
|
210
|
+
if contrast_ids != tuple(sorted(set(contrast_ids))):
|
|
211
|
+
raise ValueError("accepted shards must use unique canonical contrast order")
|
|
212
|
+
|
|
213
|
+
@property
|
|
214
|
+
def logical_llm_calls_used(self) -> int:
|
|
215
|
+
return len({shard.call_id for shard in self.shards})
|
|
216
|
+
|
|
217
|
+
@property
|
|
218
|
+
def call_ids(self) -> tuple[LLMCallId, ...]:
|
|
219
|
+
"""Return unique call identities in first-card canonical order."""
|
|
220
|
+
|
|
221
|
+
return tuple(dict.fromkeys(shard.call_id for shard in self.shards))
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@dataclass(frozen=True, slots=True)
|
|
225
|
+
class ReflectionShardFailure:
|
|
226
|
+
"""Content-free terminal status retained after all sibling calls settle."""
|
|
227
|
+
|
|
228
|
+
contrast_id: str
|
|
229
|
+
call_id: LLMCallId
|
|
230
|
+
error_type: str
|
|
231
|
+
disposition: GenerationFailureDisposition
|
|
232
|
+
|
|
233
|
+
def __post_init__(self) -> None:
|
|
234
|
+
if (
|
|
235
|
+
type(self.contrast_id) is not str
|
|
236
|
+
or _LOWER_SHA256.fullmatch(self.contrast_id) is None
|
|
237
|
+
):
|
|
238
|
+
raise ValueError("contrast_id must be a lowercase SHA-256 digest")
|
|
239
|
+
if not isinstance(self.call_id, LLMCallId):
|
|
240
|
+
raise TypeError("call_id must be an LLMCallId")
|
|
241
|
+
if type(self.error_type) is not str or not self.error_type:
|
|
242
|
+
raise ValueError("error_type must be non-empty")
|
|
243
|
+
if type(self.disposition) is not GenerationFailureDisposition:
|
|
244
|
+
raise TypeError("disposition must be a GenerationFailureDisposition")
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
class ReflectionCardContractError(ValueError):
|
|
248
|
+
"""A terminal model card escaped a shard's exact typed contract."""
|
|
249
|
+
|
|
250
|
+
@property
|
|
251
|
+
def generation_failure_disposition(self) -> GenerationFailureDisposition:
|
|
252
|
+
return GenerationFailureDisposition.MODEL_OR_SCHEMA_FAILURE
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
class ReflectionWorkflowExecutionError(RuntimeError):
|
|
256
|
+
"""One or more calls failed after every concurrently submitted shard settled."""
|
|
257
|
+
|
|
258
|
+
def __init__(
|
|
259
|
+
self,
|
|
260
|
+
*,
|
|
261
|
+
failures: tuple[ReflectionShardFailure, ...],
|
|
262
|
+
completed: tuple[ReflectionShardResult, ...],
|
|
263
|
+
) -> None:
|
|
264
|
+
if not failures:
|
|
265
|
+
raise ValueError("workflow execution error requires at least one failure")
|
|
266
|
+
self.failures = failures
|
|
267
|
+
self.completed = completed
|
|
268
|
+
super().__init__("contrast-sharded reflection did not yield a complete batch")
|
|
269
|
+
|
|
270
|
+
@property
|
|
271
|
+
def generation_failure_disposition(self) -> GenerationFailureDisposition:
|
|
272
|
+
if all(
|
|
273
|
+
failure.disposition
|
|
274
|
+
is GenerationFailureDisposition.MODEL_OR_SCHEMA_FAILURE
|
|
275
|
+
for failure in self.failures
|
|
276
|
+
):
|
|
277
|
+
return GenerationFailureDisposition.MODEL_OR_SCHEMA_FAILURE
|
|
278
|
+
return GenerationFailureDisposition.INFRASTRUCTURE_FAILURE
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
@runtime_checkable
|
|
282
|
+
class ReflectionWorkflow(Protocol):
|
|
283
|
+
"""Application seam for changing reflection topology independently of a domain."""
|
|
284
|
+
|
|
285
|
+
async def run(
|
|
286
|
+
self,
|
|
287
|
+
request: ReflectionWorkflowRequest,
|
|
288
|
+
*,
|
|
289
|
+
generator: AgenticGenerator,
|
|
290
|
+
id_factory: IdFactory,
|
|
291
|
+
call_planned_sink: ReflectionCallPlannedSink | None = None,
|
|
292
|
+
) -> ReflectionWorkflowResult: ...
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
class ContrastShardedReflectionWorkflow:
|
|
296
|
+
"""Generate one strict card per contrast with deterministic concurrent fan-out."""
|
|
297
|
+
|
|
298
|
+
policy_id = "contrast_sharded_reflection"
|
|
299
|
+
policy_version = 1
|
|
300
|
+
|
|
301
|
+
async def run(
|
|
302
|
+
self,
|
|
303
|
+
request: ReflectionWorkflowRequest,
|
|
304
|
+
*,
|
|
305
|
+
generator: AgenticGenerator,
|
|
306
|
+
id_factory: IdFactory,
|
|
307
|
+
call_planned_sink: ReflectionCallPlannedSink | None = None,
|
|
308
|
+
) -> ReflectionWorkflowResult:
|
|
309
|
+
if type(request) is not ReflectionWorkflowRequest:
|
|
310
|
+
raise TypeError("request must be an exact ReflectionWorkflowRequest")
|
|
311
|
+
ReflectionWorkflowRequest.__post_init__(request)
|
|
312
|
+
if not isinstance(generator, AgenticGenerator):
|
|
313
|
+
raise TypeError("generator must implement AgenticGenerator")
|
|
314
|
+
if not isinstance(id_factory, IdFactory):
|
|
315
|
+
raise TypeError("id_factory must implement IdFactory")
|
|
316
|
+
if call_planned_sink is not None and not callable(call_planned_sink):
|
|
317
|
+
raise TypeError("call_planned_sink must be callable or None")
|
|
318
|
+
|
|
319
|
+
planned: list[PlannedReflectionCall] = []
|
|
320
|
+
for shard in sorted(request.shards, key=lambda value: value.contrast_id):
|
|
321
|
+
call = PlannedReflectionCall(
|
|
322
|
+
contrast_id=shard.contrast_id,
|
|
323
|
+
request=ReflectionGenerationRequest(
|
|
324
|
+
call_id=id_factory.new_llm_call_id(),
|
|
325
|
+
operation=request.operation,
|
|
326
|
+
prompt=shard.prompt,
|
|
327
|
+
max_insights=1,
|
|
328
|
+
min_insights=1,
|
|
329
|
+
max_output_tokens=request.max_output_tokens,
|
|
330
|
+
temperature=request.temperature,
|
|
331
|
+
available_contrast_ids=(shard.contrast_id,),
|
|
332
|
+
insight_contract=request.insight_contract,
|
|
333
|
+
),
|
|
334
|
+
)
|
|
335
|
+
planned.append(call)
|
|
336
|
+
if call_planned_sink is not None:
|
|
337
|
+
call_planned_sink(call)
|
|
338
|
+
|
|
339
|
+
raw_results = await asyncio.gather(
|
|
340
|
+
*(generator.reflect(call.request) for call in planned),
|
|
341
|
+
return_exceptions=True,
|
|
342
|
+
)
|
|
343
|
+
completed: list[ReflectionShardResult] = []
|
|
344
|
+
failures: list[ReflectionShardFailure] = []
|
|
345
|
+
for call, raw in zip(planned, raw_results, strict=True):
|
|
346
|
+
if isinstance(raw, asyncio.CancelledError):
|
|
347
|
+
raise raw
|
|
348
|
+
if isinstance(raw, BaseException):
|
|
349
|
+
failures.append(
|
|
350
|
+
ReflectionShardFailure(
|
|
351
|
+
contrast_id=call.contrast_id,
|
|
352
|
+
call_id=call.call_id,
|
|
353
|
+
error_type=type(raw).__name__,
|
|
354
|
+
disposition=classify_generation_failure(raw),
|
|
355
|
+
)
|
|
356
|
+
)
|
|
357
|
+
continue
|
|
358
|
+
try:
|
|
359
|
+
if type(raw) is not ReflectionGenerationResult:
|
|
360
|
+
raise TypeError(
|
|
361
|
+
"generator returned a non-reflection result for a shard"
|
|
362
|
+
)
|
|
363
|
+
if len(raw.insights) != 1:
|
|
364
|
+
raise ReflectionCardContractError(
|
|
365
|
+
"a contrast shard must return exactly one insight"
|
|
366
|
+
)
|
|
367
|
+
draft = raw.insights[0]
|
|
368
|
+
if type(draft) is not InsightDraft:
|
|
369
|
+
raise TypeError("generator returned a non-InsightDraft card")
|
|
370
|
+
InsightDraft.__post_init__(draft)
|
|
371
|
+
if draft.evidence_contrast_ids != (call.contrast_id,):
|
|
372
|
+
raise ReflectionCardContractError(
|
|
373
|
+
"a contrast shard must cite exactly its assigned contrast"
|
|
374
|
+
)
|
|
375
|
+
if request.insight_contract is not None:
|
|
376
|
+
try:
|
|
377
|
+
validate_reflection_insight_draft(
|
|
378
|
+
draft,
|
|
379
|
+
request.insight_contract,
|
|
380
|
+
)
|
|
381
|
+
except (TypeError, ValueError) as exc:
|
|
382
|
+
raise ReflectionCardContractError(
|
|
383
|
+
"a contrast shard violated the insight contract"
|
|
384
|
+
) from exc
|
|
385
|
+
completed.append(
|
|
386
|
+
ReflectionShardResult(
|
|
387
|
+
contrast_id=call.contrast_id,
|
|
388
|
+
call_id=call.call_id,
|
|
389
|
+
draft=draft,
|
|
390
|
+
generation_result=raw,
|
|
391
|
+
)
|
|
392
|
+
)
|
|
393
|
+
except BaseException as error:
|
|
394
|
+
if isinstance(error, asyncio.CancelledError):
|
|
395
|
+
raise
|
|
396
|
+
failures.append(
|
|
397
|
+
ReflectionShardFailure(
|
|
398
|
+
contrast_id=call.contrast_id,
|
|
399
|
+
call_id=call.call_id,
|
|
400
|
+
error_type=type(error).__name__,
|
|
401
|
+
disposition=classify_generation_failure(error),
|
|
402
|
+
)
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
canonical_completed = tuple(
|
|
406
|
+
sorted(completed, key=lambda value: value.contrast_id)
|
|
407
|
+
)
|
|
408
|
+
if failures:
|
|
409
|
+
raise ReflectionWorkflowExecutionError(
|
|
410
|
+
failures=tuple(sorted(failures, key=lambda value: value.contrast_id)),
|
|
411
|
+
completed=canonical_completed,
|
|
412
|
+
)
|
|
413
|
+
normalized_claims = tuple(
|
|
414
|
+
_SPACE.sub(" ", shard.draft.claim.strip().casefold())
|
|
415
|
+
for shard in canonical_completed
|
|
416
|
+
)
|
|
417
|
+
if len(set(normalized_claims)) != len(normalized_claims):
|
|
418
|
+
raise ReflectionCardContractError(
|
|
419
|
+
"contrast shards produced duplicate normalized claims"
|
|
420
|
+
)
|
|
421
|
+
return ReflectionWorkflowResult(canonical_completed)
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
class StrictBatchedReflectionWorkflow:
|
|
425
|
+
"""Generate one exact card per contrast in one atomic logical call.
|
|
426
|
+
|
|
427
|
+
This topology is intended for evaluator-limited loops where a separate
|
|
428
|
+
provider call per contrast would dominate the resource budget. It accepts
|
|
429
|
+
a batch only when the model returns exactly one card for every contrast,
|
|
430
|
+
every card cites exactly one distinct available contrast, all cards satisfy
|
|
431
|
+
the shared insight contract, and normalized claims are unique. Nothing is
|
|
432
|
+
returned to durable memory on partial coverage.
|
|
433
|
+
"""
|
|
434
|
+
|
|
435
|
+
policy_id = "strict_batched_reflection"
|
|
436
|
+
policy_version = 1
|
|
437
|
+
|
|
438
|
+
async def run(
|
|
439
|
+
self,
|
|
440
|
+
request: ReflectionWorkflowRequest,
|
|
441
|
+
*,
|
|
442
|
+
generator: AgenticGenerator,
|
|
443
|
+
id_factory: IdFactory,
|
|
444
|
+
call_planned_sink: ReflectionCallPlannedSink | None = None,
|
|
445
|
+
) -> ReflectionWorkflowResult:
|
|
446
|
+
if type(request) is not ReflectionWorkflowRequest:
|
|
447
|
+
raise TypeError("request must be an exact ReflectionWorkflowRequest")
|
|
448
|
+
ReflectionWorkflowRequest.__post_init__(request)
|
|
449
|
+
if not isinstance(generator, AgenticGenerator):
|
|
450
|
+
raise TypeError("generator must implement AgenticGenerator")
|
|
451
|
+
if not isinstance(id_factory, IdFactory):
|
|
452
|
+
raise TypeError("id_factory must implement IdFactory")
|
|
453
|
+
if call_planned_sink is not None and not callable(call_planned_sink):
|
|
454
|
+
raise TypeError("call_planned_sink must be callable or None")
|
|
455
|
+
if request.batch_prompt is None:
|
|
456
|
+
raise ValueError("strict batched reflection requires batch_prompt")
|
|
457
|
+
|
|
458
|
+
contrast_ids = tuple(sorted(shard.contrast_id for shard in request.shards))
|
|
459
|
+
batched_request = ReflectionGenerationRequest(
|
|
460
|
+
call_id=id_factory.new_llm_call_id(),
|
|
461
|
+
operation=request.operation,
|
|
462
|
+
prompt=request.batch_prompt,
|
|
463
|
+
max_insights=len(contrast_ids),
|
|
464
|
+
min_insights=len(contrast_ids),
|
|
465
|
+
max_output_tokens=request.max_output_tokens,
|
|
466
|
+
temperature=request.temperature,
|
|
467
|
+
available_contrast_ids=contrast_ids,
|
|
468
|
+
insight_contract=request.insight_contract,
|
|
469
|
+
)
|
|
470
|
+
call = PlannedReflectionBatchCall(
|
|
471
|
+
contrast_ids=contrast_ids,
|
|
472
|
+
request=batched_request,
|
|
473
|
+
)
|
|
474
|
+
if call_planned_sink is not None:
|
|
475
|
+
call_planned_sink(call)
|
|
476
|
+
|
|
477
|
+
try:
|
|
478
|
+
raw = await generator.reflect(batched_request)
|
|
479
|
+
except asyncio.CancelledError:
|
|
480
|
+
raise
|
|
481
|
+
except BaseException as error:
|
|
482
|
+
raise ReflectionWorkflowExecutionError(
|
|
483
|
+
failures=tuple(
|
|
484
|
+
ReflectionShardFailure(
|
|
485
|
+
contrast_id=contrast_id,
|
|
486
|
+
call_id=batched_request.call_id,
|
|
487
|
+
error_type=type(error).__name__,
|
|
488
|
+
disposition=classify_generation_failure(error),
|
|
489
|
+
)
|
|
490
|
+
for contrast_id in contrast_ids
|
|
491
|
+
),
|
|
492
|
+
completed=(),
|
|
493
|
+
) from error
|
|
494
|
+
|
|
495
|
+
if type(raw) is not ReflectionGenerationResult:
|
|
496
|
+
raise ReflectionCardContractError(
|
|
497
|
+
"generator returned a non-reflection batched result"
|
|
498
|
+
)
|
|
499
|
+
if len(raw.insights) != len(contrast_ids):
|
|
500
|
+
raise ReflectionCardContractError(
|
|
501
|
+
"batched reflection must return exactly one card per contrast"
|
|
502
|
+
)
|
|
503
|
+
|
|
504
|
+
by_contrast: dict[str, InsightDraft] = {}
|
|
505
|
+
for draft in raw.insights:
|
|
506
|
+
if type(draft) is not InsightDraft:
|
|
507
|
+
raise ReflectionCardContractError(
|
|
508
|
+
"batched reflection returned a non-InsightDraft card"
|
|
509
|
+
)
|
|
510
|
+
InsightDraft.__post_init__(draft)
|
|
511
|
+
if len(draft.evidence_contrast_ids) != 1:
|
|
512
|
+
raise ReflectionCardContractError(
|
|
513
|
+
"every batched card must cite exactly one contrast"
|
|
514
|
+
)
|
|
515
|
+
contrast_id = draft.evidence_contrast_ids[0]
|
|
516
|
+
if contrast_id not in contrast_ids or contrast_id in by_contrast:
|
|
517
|
+
raise ReflectionCardContractError(
|
|
518
|
+
"batched reflection has foreign or duplicate contrast coverage"
|
|
519
|
+
)
|
|
520
|
+
if request.insight_contract is not None:
|
|
521
|
+
try:
|
|
522
|
+
validate_reflection_insight_draft(
|
|
523
|
+
draft,
|
|
524
|
+
request.insight_contract,
|
|
525
|
+
)
|
|
526
|
+
except (TypeError, ValueError) as exc:
|
|
527
|
+
raise ReflectionCardContractError(
|
|
528
|
+
"a batched card violated the insight contract"
|
|
529
|
+
) from exc
|
|
530
|
+
by_contrast[contrast_id] = draft
|
|
531
|
+
|
|
532
|
+
if tuple(sorted(by_contrast)) != contrast_ids:
|
|
533
|
+
raise ReflectionCardContractError(
|
|
534
|
+
"batched reflection did not cover the exact contrast set"
|
|
535
|
+
)
|
|
536
|
+
normalized_claims = tuple(
|
|
537
|
+
_SPACE.sub(" ", by_contrast[item].claim.strip().casefold())
|
|
538
|
+
for item in contrast_ids
|
|
539
|
+
)
|
|
540
|
+
if len(set(normalized_claims)) != len(normalized_claims):
|
|
541
|
+
raise ReflectionCardContractError(
|
|
542
|
+
"batched reflection produced duplicate normalized claims"
|
|
543
|
+
)
|
|
544
|
+
return ReflectionWorkflowResult(
|
|
545
|
+
tuple(
|
|
546
|
+
ReflectionShardResult(
|
|
547
|
+
contrast_id=contrast_id,
|
|
548
|
+
call_id=batched_request.call_id,
|
|
549
|
+
draft=by_contrast[contrast_id],
|
|
550
|
+
generation_result=raw,
|
|
551
|
+
)
|
|
552
|
+
for contrast_id in contrast_ids
|
|
553
|
+
)
|
|
554
|
+
)
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
__all__ = [
|
|
558
|
+
"ContrastShardedReflectionWorkflow",
|
|
559
|
+
"PlannedReflectionCall",
|
|
560
|
+
"PlannedReflectionBatchCall",
|
|
561
|
+
"ReflectionCallPlannedSink",
|
|
562
|
+
"ReflectionCardContractError",
|
|
563
|
+
"ReflectionPromptShard",
|
|
564
|
+
"ReflectionShardFailure",
|
|
565
|
+
"ReflectionShardResult",
|
|
566
|
+
"ReflectionWorkflow",
|
|
567
|
+
"ReflectionWorkflowExecutionError",
|
|
568
|
+
"ReflectionWorkflowRequest",
|
|
569
|
+
"ReflectionWorkflowResult",
|
|
570
|
+
"StrictBatchedReflectionWorkflow",
|
|
571
|
+
]
|