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,611 @@
|
|
|
1
|
+
"""Deterministic model-free union of strictly disjoint typed patches.
|
|
2
|
+
|
|
3
|
+
The three-way patch algebra deliberately classifies rather than merges. This
|
|
4
|
+
module provides the narrower policy that is safe to automate: two branches may
|
|
5
|
+
be united only when replay classifies every branch effect as either identical
|
|
6
|
+
or disjoint. Conflicts, prefix invalidation, and semantic-component coupling
|
|
7
|
+
remain explicit failures for a higher-authority operator to resolve.
|
|
8
|
+
|
|
9
|
+
The policy depends only on immutable domain values and the typed-patch policy.
|
|
10
|
+
It has no generator, evaluator, archive, or application dependency.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import hashlib
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from enum import Enum
|
|
18
|
+
from typing import ClassVar
|
|
19
|
+
|
|
20
|
+
from agent_evolve.domain.ids import CandidateId
|
|
21
|
+
from agent_evolve.domain.patch import (
|
|
22
|
+
DEFAULT_PATCH_LIMITS,
|
|
23
|
+
DeleteSequenceItem,
|
|
24
|
+
InsertSequenceItem,
|
|
25
|
+
JsonPath,
|
|
26
|
+
PatchLimits,
|
|
27
|
+
PatchOperation,
|
|
28
|
+
PermuteSequence,
|
|
29
|
+
ReplaceScalar,
|
|
30
|
+
ReplaceSubtree,
|
|
31
|
+
TypedPatch,
|
|
32
|
+
canonical_path_bytes,
|
|
33
|
+
operation_effect_bytes,
|
|
34
|
+
operation_effect_sha256,
|
|
35
|
+
operation_occurrence_bytes,
|
|
36
|
+
operation_sort_key,
|
|
37
|
+
require_sha256,
|
|
38
|
+
validate_json_path,
|
|
39
|
+
validate_patch_limits,
|
|
40
|
+
validate_patch_operation,
|
|
41
|
+
validate_typed_patch,
|
|
42
|
+
)
|
|
43
|
+
from agent_evolve.domain.typed_json import (
|
|
44
|
+
FrozenJsonValue,
|
|
45
|
+
freeze_json,
|
|
46
|
+
typed_json_equal,
|
|
47
|
+
typed_json_sha256,
|
|
48
|
+
)
|
|
49
|
+
from agent_evolve.policies.variation.typed_patch import (
|
|
50
|
+
ComponentTagAssignment,
|
|
51
|
+
ThreeWayPatchClassification,
|
|
52
|
+
ThreeWayRelationKind,
|
|
53
|
+
apply_patch,
|
|
54
|
+
classify_three_way_patches,
|
|
55
|
+
derive_patch,
|
|
56
|
+
replace_existing_path,
|
|
57
|
+
value_at_path,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
POLICY_ID = "disjoint_patch_union"
|
|
62
|
+
POLICY_VERSION = 1
|
|
63
|
+
_RECEIPT_DOMAIN = b"agent-evolve:disjoint-patch-union-receipt:v1\x00"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class DisjointPatchRecombinationError(ValueError):
|
|
67
|
+
"""The requested branches do not admit the policy's exact safe union."""
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
class RecombinationBranch(str, Enum):
|
|
71
|
+
"""A branch whose replay-verified effect appears in the union."""
|
|
72
|
+
|
|
73
|
+
LEFT = "left"
|
|
74
|
+
RIGHT = "right"
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
_CANONICAL_BOTH_BRANCHES = (
|
|
78
|
+
RecombinationBranch.LEFT,
|
|
79
|
+
RecombinationBranch.RIGHT,
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _frame(value: bytes) -> bytes:
|
|
84
|
+
if type(value) is not bytes:
|
|
85
|
+
raise TypeError("receipt components must be exact bytes")
|
|
86
|
+
return len(value).to_bytes(8, "big", signed=False) + value
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _validate_candidate_id(value: CandidateId, *, name: str) -> None:
|
|
90
|
+
if type(value) is not CandidateId:
|
|
91
|
+
raise TypeError(f"{name} must be an exact CandidateId")
|
|
92
|
+
CandidateId.__post_init__(value)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _validate_sources(values: tuple[RecombinationBranch, ...]) -> None:
|
|
96
|
+
if type(values) is not tuple or any(
|
|
97
|
+
type(value) is not RecombinationBranch for value in values
|
|
98
|
+
):
|
|
99
|
+
raise TypeError("sources must be an exact tuple of RecombinationBranch values")
|
|
100
|
+
if values not in {
|
|
101
|
+
(RecombinationBranch.LEFT,),
|
|
102
|
+
(RecombinationBranch.RIGHT,),
|
|
103
|
+
_CANONICAL_BOTH_BRANCHES,
|
|
104
|
+
}:
|
|
105
|
+
raise ValueError("sources must be a non-empty canonical branch set")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
109
|
+
class SystemPatchAttribution:
|
|
110
|
+
"""System-derived provenance for one exact union-patch effect.
|
|
111
|
+
|
|
112
|
+
``sources`` contains both branches only for a replay-classified identical
|
|
113
|
+
relation. The relation and effect digests make this evidence independently
|
|
114
|
+
bindable without relying on model-authored path strings or explanations.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
path: JsonPath
|
|
118
|
+
sources: tuple[RecombinationBranch, ...]
|
|
119
|
+
relation_id: str
|
|
120
|
+
effect_sha256: str
|
|
121
|
+
|
|
122
|
+
def __post_init__(self) -> None:
|
|
123
|
+
validate_json_path(self.path)
|
|
124
|
+
_validate_sources(self.sources)
|
|
125
|
+
require_sha256(self.relation_id, "relation_id")
|
|
126
|
+
require_sha256(self.effect_sha256, "effect_sha256")
|
|
127
|
+
|
|
128
|
+
def revalidate(self) -> None:
|
|
129
|
+
if type(self) is not SystemPatchAttribution:
|
|
130
|
+
raise TypeError("attribution must be an exact SystemPatchAttribution")
|
|
131
|
+
SystemPatchAttribution.__post_init__(self)
|
|
132
|
+
|
|
133
|
+
def __eq__(self, other: object) -> bool:
|
|
134
|
+
if (
|
|
135
|
+
type(self) is not SystemPatchAttribution
|
|
136
|
+
or type(other) is not SystemPatchAttribution
|
|
137
|
+
):
|
|
138
|
+
return False
|
|
139
|
+
self.revalidate()
|
|
140
|
+
other.revalidate()
|
|
141
|
+
return _attribution_fingerprint(self) == _attribution_fingerprint(other)
|
|
142
|
+
|
|
143
|
+
__hash__ = None
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def _attribution_fingerprint(
|
|
147
|
+
value: SystemPatchAttribution,
|
|
148
|
+
) -> tuple[bytes, tuple[str, ...], str, str]:
|
|
149
|
+
value.revalidate()
|
|
150
|
+
return (
|
|
151
|
+
canonical_path_bytes(value.path),
|
|
152
|
+
tuple(source.value for source in value.sources),
|
|
153
|
+
value.relation_id,
|
|
154
|
+
value.effect_sha256,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def _attribution_sort_key(
|
|
159
|
+
value: SystemPatchAttribution,
|
|
160
|
+
) -> tuple[bytes, str, tuple[str, ...], str]:
|
|
161
|
+
value.revalidate()
|
|
162
|
+
return (
|
|
163
|
+
canonical_path_bytes(value.path),
|
|
164
|
+
value.effect_sha256,
|
|
165
|
+
tuple(source.value for source in value.sources),
|
|
166
|
+
value.relation_id,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def _operation_before_after(
|
|
171
|
+
operation: PatchOperation,
|
|
172
|
+
) -> tuple[FrozenJsonValue, FrozenJsonValue]:
|
|
173
|
+
validate_patch_operation(operation)
|
|
174
|
+
if type(operation) in (ReplaceScalar, ReplaceSubtree):
|
|
175
|
+
return operation.old_value, operation.new_value
|
|
176
|
+
if type(operation) in (
|
|
177
|
+
InsertSequenceItem,
|
|
178
|
+
DeleteSequenceItem,
|
|
179
|
+
PermuteSequence,
|
|
180
|
+
):
|
|
181
|
+
return operation.before_sequence, operation.after_sequence
|
|
182
|
+
raise TypeError("unsupported patch operation type")
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def _safe_relations(
|
|
186
|
+
classification: ThreeWayPatchClassification,
|
|
187
|
+
) -> tuple[PatchOperation, ...]:
|
|
188
|
+
"""Return the canonical union operations or reject the classification."""
|
|
189
|
+
|
|
190
|
+
if type(classification) is not ThreeWayPatchClassification:
|
|
191
|
+
raise TypeError("classification must be an exact ThreeWayPatchClassification")
|
|
192
|
+
classification.revalidate()
|
|
193
|
+
rejected = tuple(
|
|
194
|
+
relation.kind
|
|
195
|
+
for relation in classification.relations
|
|
196
|
+
if relation.kind
|
|
197
|
+
not in {ThreeWayRelationKind.IDENTICAL, ThreeWayRelationKind.DISJOINT}
|
|
198
|
+
)
|
|
199
|
+
if rejected:
|
|
200
|
+
kinds = ", ".join(sorted({kind.value for kind in rejected}))
|
|
201
|
+
raise DisjointPatchRecombinationError(
|
|
202
|
+
f"branch classification contains unsafe relation kinds: {kinds}"
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
left_unique = False
|
|
206
|
+
right_unique = False
|
|
207
|
+
operations: list[PatchOperation] = []
|
|
208
|
+
for relation in classification.relations:
|
|
209
|
+
if relation.kind is ThreeWayRelationKind.IDENTICAL:
|
|
210
|
+
# Relation validation proves these are the exact same effect. The
|
|
211
|
+
# operation occurrence also has the same common-ancestor source, so
|
|
212
|
+
# choosing the left representation is deterministic and lossless.
|
|
213
|
+
operations.append(relation.left_operations[0])
|
|
214
|
+
elif relation.kind is ThreeWayRelationKind.DISJOINT:
|
|
215
|
+
if relation.left_operations:
|
|
216
|
+
left_unique = True
|
|
217
|
+
operations.append(relation.left_operations[0])
|
|
218
|
+
else:
|
|
219
|
+
right_unique = True
|
|
220
|
+
operations.append(relation.right_operations[0])
|
|
221
|
+
else: # pragma: no cover - rejected above and enum closes the cases.
|
|
222
|
+
raise AssertionError("unsafe relation passed the fail-closed gate")
|
|
223
|
+
if not left_unique or not right_unique:
|
|
224
|
+
missing = "left" if not left_unique else "right"
|
|
225
|
+
if not left_unique and not right_unique:
|
|
226
|
+
missing = "left and right"
|
|
227
|
+
raise DisjointPatchRecombinationError(
|
|
228
|
+
f"{missing} branch lacks a non-identical disjoint effect"
|
|
229
|
+
)
|
|
230
|
+
return tuple(sorted(operations, key=operation_sort_key))
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _expected_attribution(
|
|
234
|
+
classification: ThreeWayPatchClassification,
|
|
235
|
+
) -> tuple[SystemPatchAttribution, ...]:
|
|
236
|
+
classification.revalidate()
|
|
237
|
+
values: list[SystemPatchAttribution] = []
|
|
238
|
+
for relation in classification.relations:
|
|
239
|
+
if relation.kind is ThreeWayRelationKind.IDENTICAL:
|
|
240
|
+
operation = relation.left_operations[0]
|
|
241
|
+
sources = _CANONICAL_BOTH_BRANCHES
|
|
242
|
+
elif relation.kind is ThreeWayRelationKind.DISJOINT:
|
|
243
|
+
if relation.left_operations:
|
|
244
|
+
operation = relation.left_operations[0]
|
|
245
|
+
sources = (RecombinationBranch.LEFT,)
|
|
246
|
+
else:
|
|
247
|
+
operation = relation.right_operations[0]
|
|
248
|
+
sources = (RecombinationBranch.RIGHT,)
|
|
249
|
+
else:
|
|
250
|
+
raise DisjointPatchRecombinationError(
|
|
251
|
+
"system attribution cannot represent an unsafe relation"
|
|
252
|
+
)
|
|
253
|
+
values.append(
|
|
254
|
+
SystemPatchAttribution(
|
|
255
|
+
path=operation.path,
|
|
256
|
+
sources=sources,
|
|
257
|
+
relation_id=relation.relation_id,
|
|
258
|
+
effect_sha256=operation_effect_sha256(
|
|
259
|
+
operation,
|
|
260
|
+
limits=classification.left_patch.limits.json_limits,
|
|
261
|
+
),
|
|
262
|
+
)
|
|
263
|
+
)
|
|
264
|
+
return tuple(sorted(values, key=_attribution_sort_key))
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def _construct_target(
|
|
268
|
+
ancestor: FrozenJsonValue,
|
|
269
|
+
operations: tuple[PatchOperation, ...],
|
|
270
|
+
*,
|
|
271
|
+
limits: PatchLimits,
|
|
272
|
+
) -> FrozenJsonValue:
|
|
273
|
+
"""Construct an endpoint using only exact old/new operation states."""
|
|
274
|
+
|
|
275
|
+
validate_patch_limits(limits)
|
|
276
|
+
frozen_ancestor = freeze_json(ancestor, limits=limits.json_limits)
|
|
277
|
+
if frozen_ancestor is not ancestor:
|
|
278
|
+
raise TypeError("ancestor must already be frozen typed JSON")
|
|
279
|
+
current = frozen_ancestor
|
|
280
|
+
for operation in operations:
|
|
281
|
+
validate_patch_operation(operation)
|
|
282
|
+
before, after = _operation_before_after(operation)
|
|
283
|
+
observed = value_at_path(current, operation.path)
|
|
284
|
+
if not typed_json_equal(observed, before, limits=limits.json_limits):
|
|
285
|
+
raise DisjointPatchRecombinationError(
|
|
286
|
+
"canonical union encountered a stale operation precondition"
|
|
287
|
+
)
|
|
288
|
+
current = replace_existing_path(current, operation.path, after)
|
|
289
|
+
if not typed_json_equal(
|
|
290
|
+
value_at_path(current, operation.path),
|
|
291
|
+
after,
|
|
292
|
+
limits=limits.json_limits,
|
|
293
|
+
):
|
|
294
|
+
raise DisjointPatchRecombinationError(
|
|
295
|
+
"canonical union did not install an exact operation effect"
|
|
296
|
+
)
|
|
297
|
+
return current
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
def _effect_fingerprint(
|
|
301
|
+
patch: TypedPatch,
|
|
302
|
+
) -> tuple[bytes, ...]:
|
|
303
|
+
validate_typed_patch(patch)
|
|
304
|
+
return tuple(
|
|
305
|
+
operation_effect_bytes(operation, limits=patch.limits.json_limits)
|
|
306
|
+
for operation in patch.operations
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
def _validate_materialization(
|
|
311
|
+
value: "DisjointPatchMaterialization",
|
|
312
|
+
) -> None:
|
|
313
|
+
if type(value.union_patch) is not TypedPatch:
|
|
314
|
+
raise TypeError("union_patch must be an exact TypedPatch")
|
|
315
|
+
if type(value.classification) is not ThreeWayPatchClassification:
|
|
316
|
+
raise TypeError("classification must be an exact ThreeWayPatchClassification")
|
|
317
|
+
validate_typed_patch(value.union_patch)
|
|
318
|
+
value.classification.revalidate()
|
|
319
|
+
configuration = freeze_json(
|
|
320
|
+
value.configuration,
|
|
321
|
+
limits=value.union_patch.limits.json_limits,
|
|
322
|
+
)
|
|
323
|
+
if configuration is not value.configuration:
|
|
324
|
+
raise TypeError("configuration must already be frozen typed JSON")
|
|
325
|
+
classification = value.classification
|
|
326
|
+
union_patch = value.union_patch
|
|
327
|
+
if union_patch.limits != classification.left_patch.limits:
|
|
328
|
+
raise ValueError("union patch and branch patches must share exact limits")
|
|
329
|
+
if (
|
|
330
|
+
union_patch.base_candidate_id != classification.ancestor_candidate_id
|
|
331
|
+
or union_patch.base_hash != classification.ancestor_hash
|
|
332
|
+
):
|
|
333
|
+
raise ValueError("union patch does not bind the classified ancestor")
|
|
334
|
+
if union_patch.target_candidate_id in {
|
|
335
|
+
classification.ancestor_candidate_id,
|
|
336
|
+
classification.left_patch.target_candidate_id,
|
|
337
|
+
classification.right_patch.target_candidate_id,
|
|
338
|
+
}:
|
|
339
|
+
raise ValueError("union target must be a distinct candidate occurrence")
|
|
340
|
+
expected_operations = _safe_relations(classification)
|
|
341
|
+
if tuple(
|
|
342
|
+
operation_occurrence_bytes(
|
|
343
|
+
operation,
|
|
344
|
+
limits=union_patch.limits.json_limits,
|
|
345
|
+
)
|
|
346
|
+
for operation in union_patch.operations
|
|
347
|
+
) != tuple(
|
|
348
|
+
operation_occurrence_bytes(
|
|
349
|
+
operation,
|
|
350
|
+
limits=union_patch.limits.json_limits,
|
|
351
|
+
)
|
|
352
|
+
for operation in expected_operations
|
|
353
|
+
):
|
|
354
|
+
raise ValueError(
|
|
355
|
+
"union patch does not contain the canonical classified effects"
|
|
356
|
+
)
|
|
357
|
+
replayed = apply_patch(classification.ancestor, union_patch)
|
|
358
|
+
if not typed_json_equal(
|
|
359
|
+
replayed,
|
|
360
|
+
configuration,
|
|
361
|
+
limits=union_patch.limits.json_limits,
|
|
362
|
+
):
|
|
363
|
+
raise ValueError("configuration does not equal the replayed union patch")
|
|
364
|
+
|
|
365
|
+
rediff = derive_patch(
|
|
366
|
+
classification.ancestor,
|
|
367
|
+
configuration,
|
|
368
|
+
base_candidate_id=classification.ancestor_candidate_id,
|
|
369
|
+
target_candidate_id=union_patch.target_candidate_id,
|
|
370
|
+
limits=union_patch.limits,
|
|
371
|
+
)
|
|
372
|
+
if _effect_fingerprint(rediff) != _effect_fingerprint(union_patch):
|
|
373
|
+
raise ValueError(
|
|
374
|
+
"union endpoint does not re-diff to the exact classified effects"
|
|
375
|
+
)
|
|
376
|
+
if rediff.patch_hash != union_patch.patch_hash:
|
|
377
|
+
raise ValueError("union endpoint does not re-diff to the canonical union patch")
|
|
378
|
+
|
|
379
|
+
if type(value.system_attribution) is not tuple or any(
|
|
380
|
+
type(item) is not SystemPatchAttribution for item in value.system_attribution
|
|
381
|
+
):
|
|
382
|
+
raise TypeError(
|
|
383
|
+
"system_attribution must be an exact tuple of SystemPatchAttribution values"
|
|
384
|
+
)
|
|
385
|
+
for item in value.system_attribution:
|
|
386
|
+
item.revalidate()
|
|
387
|
+
if value.system_attribution != tuple(
|
|
388
|
+
sorted(value.system_attribution, key=_attribution_sort_key)
|
|
389
|
+
):
|
|
390
|
+
raise ValueError("system_attribution must use canonical order")
|
|
391
|
+
expected_attribution = _expected_attribution(classification)
|
|
392
|
+
if tuple(map(_attribution_fingerprint, value.system_attribution)) != tuple(
|
|
393
|
+
map(_attribution_fingerprint, expected_attribution)
|
|
394
|
+
):
|
|
395
|
+
raise ValueError(
|
|
396
|
+
"system_attribution does not exactly bind every classified union effect"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
@dataclass(frozen=True, slots=True, eq=False)
|
|
401
|
+
class DisjointPatchMaterialization:
|
|
402
|
+
"""Immutable, replay-complete output of deterministic recombination."""
|
|
403
|
+
|
|
404
|
+
configuration: FrozenJsonValue
|
|
405
|
+
union_patch: TypedPatch
|
|
406
|
+
classification: ThreeWayPatchClassification
|
|
407
|
+
system_attribution: tuple[SystemPatchAttribution, ...]
|
|
408
|
+
|
|
409
|
+
policy_id: ClassVar[str] = POLICY_ID
|
|
410
|
+
policy_version: ClassVar[int] = POLICY_VERSION
|
|
411
|
+
|
|
412
|
+
def __post_init__(self) -> None:
|
|
413
|
+
if type(self.union_patch) is not TypedPatch:
|
|
414
|
+
raise TypeError("union_patch must be an exact TypedPatch")
|
|
415
|
+
frozen = freeze_json(
|
|
416
|
+
self.configuration,
|
|
417
|
+
limits=self.union_patch.limits.json_limits,
|
|
418
|
+
)
|
|
419
|
+
object.__setattr__(self, "configuration", frozen)
|
|
420
|
+
_validate_materialization(self)
|
|
421
|
+
|
|
422
|
+
def revalidate(self) -> None:
|
|
423
|
+
if type(self) is not DisjointPatchMaterialization:
|
|
424
|
+
raise TypeError(
|
|
425
|
+
"materialization must be an exact DisjointPatchMaterialization"
|
|
426
|
+
)
|
|
427
|
+
_validate_materialization(self)
|
|
428
|
+
|
|
429
|
+
@property
|
|
430
|
+
def receipt_sha256(self) -> str:
|
|
431
|
+
"""Digest binding the policy, endpoints, effects, and provenance."""
|
|
432
|
+
|
|
433
|
+
self.revalidate()
|
|
434
|
+
digest = hashlib.sha256()
|
|
435
|
+
digest.update(_RECEIPT_DOMAIN)
|
|
436
|
+
digest.update(_frame(self.policy_id.encode("ascii", errors="strict")))
|
|
437
|
+
digest.update(self.policy_version.to_bytes(8, "big", signed=False))
|
|
438
|
+
for candidate_id in (
|
|
439
|
+
self.classification.ancestor_candidate_id,
|
|
440
|
+
self.classification.left_patch.target_candidate_id,
|
|
441
|
+
self.classification.right_patch.target_candidate_id,
|
|
442
|
+
self.union_patch.target_candidate_id,
|
|
443
|
+
):
|
|
444
|
+
digest.update(_frame(candidate_id.value.encode("ascii", errors="strict")))
|
|
445
|
+
digest.update(bytes.fromhex(self.classification.left_patch_hash))
|
|
446
|
+
digest.update(bytes.fromhex(self.classification.right_patch_hash))
|
|
447
|
+
digest.update(bytes.fromhex(self.union_patch.patch_hash))
|
|
448
|
+
digest.update(
|
|
449
|
+
bytes.fromhex(
|
|
450
|
+
typed_json_sha256(
|
|
451
|
+
self.configuration,
|
|
452
|
+
limits=self.union_patch.limits.json_limits,
|
|
453
|
+
)
|
|
454
|
+
)
|
|
455
|
+
)
|
|
456
|
+
digest.update(len(self.classification.relations).to_bytes(8, "big"))
|
|
457
|
+
for relation in self.classification.relations:
|
|
458
|
+
digest.update(bytes.fromhex(relation.relation_id))
|
|
459
|
+
digest.update(len(self.system_attribution).to_bytes(8, "big"))
|
|
460
|
+
for attribution in self.system_attribution:
|
|
461
|
+
digest.update(_frame(canonical_path_bytes(attribution.path)))
|
|
462
|
+
digest.update(len(attribution.sources).to_bytes(8, "big"))
|
|
463
|
+
for source in attribution.sources:
|
|
464
|
+
digest.update(_frame(source.value.encode("ascii", errors="strict")))
|
|
465
|
+
digest.update(bytes.fromhex(attribution.relation_id))
|
|
466
|
+
digest.update(bytes.fromhex(attribution.effect_sha256))
|
|
467
|
+
return digest.hexdigest()
|
|
468
|
+
|
|
469
|
+
def __eq__(self, other: object) -> bool:
|
|
470
|
+
if (
|
|
471
|
+
type(self) is not DisjointPatchMaterialization
|
|
472
|
+
or type(other) is not DisjointPatchMaterialization
|
|
473
|
+
):
|
|
474
|
+
return False
|
|
475
|
+
return self.receipt_sha256 == other.receipt_sha256
|
|
476
|
+
|
|
477
|
+
__hash__ = None
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
@dataclass(frozen=True, slots=True)
|
|
481
|
+
class DisjointPatchRecombiner:
|
|
482
|
+
"""Materialize the exact union of two safe ancestor-relative branches."""
|
|
483
|
+
|
|
484
|
+
limits: PatchLimits = DEFAULT_PATCH_LIMITS
|
|
485
|
+
|
|
486
|
+
policy_id: ClassVar[str] = POLICY_ID
|
|
487
|
+
policy_version: ClassVar[int] = POLICY_VERSION
|
|
488
|
+
|
|
489
|
+
def __post_init__(self) -> None:
|
|
490
|
+
validate_patch_limits(self.limits)
|
|
491
|
+
|
|
492
|
+
def materialize(
|
|
493
|
+
self,
|
|
494
|
+
*,
|
|
495
|
+
ancestor: object,
|
|
496
|
+
ancestor_candidate_id: CandidateId,
|
|
497
|
+
left: object,
|
|
498
|
+
left_candidate_id: CandidateId,
|
|
499
|
+
right: object,
|
|
500
|
+
right_candidate_id: CandidateId,
|
|
501
|
+
target_candidate_id: CandidateId,
|
|
502
|
+
left_component_tags: tuple[ComponentTagAssignment, ...] = (),
|
|
503
|
+
right_component_tags: tuple[ComponentTagAssignment, ...] = (),
|
|
504
|
+
) -> DisjointPatchMaterialization:
|
|
505
|
+
"""Derive, classify, construct, replay, and independently re-diff.
|
|
506
|
+
|
|
507
|
+
All four occurrence IDs must be distinct. Component tags are optional
|
|
508
|
+
benchmark semantics; when they induce a same-component relation, this
|
|
509
|
+
mechanical policy intentionally refuses to decide whether combination
|
|
510
|
+
is safe.
|
|
511
|
+
"""
|
|
512
|
+
|
|
513
|
+
validate_patch_limits(self.limits)
|
|
514
|
+
identifiers = (
|
|
515
|
+
(ancestor_candidate_id, "ancestor_candidate_id"),
|
|
516
|
+
(left_candidate_id, "left_candidate_id"),
|
|
517
|
+
(right_candidate_id, "right_candidate_id"),
|
|
518
|
+
(target_candidate_id, "target_candidate_id"),
|
|
519
|
+
)
|
|
520
|
+
for candidate_id, name in identifiers:
|
|
521
|
+
_validate_candidate_id(candidate_id, name=name)
|
|
522
|
+
if len({candidate_id for candidate_id, _ in identifiers}) != len(identifiers):
|
|
523
|
+
raise ValueError("recombination occurrence IDs must be pairwise distinct")
|
|
524
|
+
|
|
525
|
+
frozen_ancestor = freeze_json(ancestor, limits=self.limits.json_limits)
|
|
526
|
+
frozen_left = freeze_json(left, limits=self.limits.json_limits)
|
|
527
|
+
frozen_right = freeze_json(right, limits=self.limits.json_limits)
|
|
528
|
+
left_patch = derive_patch(
|
|
529
|
+
frozen_ancestor,
|
|
530
|
+
frozen_left,
|
|
531
|
+
base_candidate_id=ancestor_candidate_id,
|
|
532
|
+
target_candidate_id=left_candidate_id,
|
|
533
|
+
component_tags=left_component_tags,
|
|
534
|
+
limits=self.limits,
|
|
535
|
+
)
|
|
536
|
+
right_patch = derive_patch(
|
|
537
|
+
frozen_ancestor,
|
|
538
|
+
frozen_right,
|
|
539
|
+
base_candidate_id=ancestor_candidate_id,
|
|
540
|
+
target_candidate_id=right_candidate_id,
|
|
541
|
+
component_tags=right_component_tags,
|
|
542
|
+
limits=self.limits,
|
|
543
|
+
)
|
|
544
|
+
classification = classify_three_way_patches(
|
|
545
|
+
frozen_ancestor,
|
|
546
|
+
left_patch,
|
|
547
|
+
right_patch,
|
|
548
|
+
)
|
|
549
|
+
union_operations = _safe_relations(classification)
|
|
550
|
+
provisional_target = _construct_target(
|
|
551
|
+
frozen_ancestor,
|
|
552
|
+
union_operations,
|
|
553
|
+
limits=self.limits,
|
|
554
|
+
)
|
|
555
|
+
union_patch = TypedPatch(
|
|
556
|
+
base_candidate_id=ancestor_candidate_id,
|
|
557
|
+
target_candidate_id=target_candidate_id,
|
|
558
|
+
base_hash=classification.ancestor_hash,
|
|
559
|
+
target_hash=typed_json_sha256(
|
|
560
|
+
provisional_target,
|
|
561
|
+
limits=self.limits.json_limits,
|
|
562
|
+
),
|
|
563
|
+
operations=union_operations,
|
|
564
|
+
limits=self.limits,
|
|
565
|
+
)
|
|
566
|
+
|
|
567
|
+
# Replay is an independent whole-patch check after the local, safe
|
|
568
|
+
# construction above. Re-diff then proves the endpoint did not merely
|
|
569
|
+
# happen to match while hiding a different canonical effect script.
|
|
570
|
+
replayed = apply_patch(frozen_ancestor, union_patch)
|
|
571
|
+
if not typed_json_equal(
|
|
572
|
+
replayed,
|
|
573
|
+
provisional_target,
|
|
574
|
+
limits=self.limits.json_limits,
|
|
575
|
+
):
|
|
576
|
+
raise DisjointPatchRecombinationError(
|
|
577
|
+
"union patch replay disagrees with safe construction"
|
|
578
|
+
)
|
|
579
|
+
rediff = derive_patch(
|
|
580
|
+
frozen_ancestor,
|
|
581
|
+
replayed,
|
|
582
|
+
base_candidate_id=ancestor_candidate_id,
|
|
583
|
+
target_candidate_id=target_candidate_id,
|
|
584
|
+
limits=self.limits,
|
|
585
|
+
)
|
|
586
|
+
if _effect_fingerprint(rediff) != _effect_fingerprint(union_patch):
|
|
587
|
+
raise DisjointPatchRecombinationError(
|
|
588
|
+
"replayed union does not re-diff to the exact classified effects"
|
|
589
|
+
)
|
|
590
|
+
if rediff.patch_hash != union_patch.patch_hash:
|
|
591
|
+
raise DisjointPatchRecombinationError(
|
|
592
|
+
"replayed union does not re-diff to the canonical union patch"
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
return DisjointPatchMaterialization(
|
|
596
|
+
configuration=replayed,
|
|
597
|
+
union_patch=union_patch,
|
|
598
|
+
classification=classification,
|
|
599
|
+
system_attribution=_expected_attribution(classification),
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
|
|
603
|
+
__all__ = [
|
|
604
|
+
"DisjointPatchMaterialization",
|
|
605
|
+
"DisjointPatchRecombinationError",
|
|
606
|
+
"DisjointPatchRecombiner",
|
|
607
|
+
"POLICY_ID",
|
|
608
|
+
"POLICY_VERSION",
|
|
609
|
+
"RecombinationBranch",
|
|
610
|
+
"SystemPatchAttribution",
|
|
611
|
+
]
|