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,1544 @@
|
|
|
1
|
+
"""Conserved, workload-opaque learning of residual evolutionary headroom.
|
|
2
|
+
|
|
3
|
+
The ledger closes a gap between one-stage outcome-adaptive racing and a
|
|
4
|
+
multi-generation optimizer. It converts authenticated conditional set gains
|
|
5
|
+
into conserved action credit, learns decayed posteriors over opaque action
|
|
6
|
+
cells, and exposes those posteriors through an optional adaptive-market
|
|
7
|
+
projector. It never inspects workload names, objective names, configuration
|
|
8
|
+
fields, prompts, providers, or model-name strings.
|
|
9
|
+
|
|
10
|
+
The module deliberately separates three responsibilities:
|
|
11
|
+
|
|
12
|
+
* ``ConservedResidualHeadroomProjector`` closes one evaluated stage without
|
|
13
|
+
manufacturing more credit than the stage actually earned;
|
|
14
|
+
* ``ConservedResidualHeadroomLedger`` stores immutable closures and estimates
|
|
15
|
+
context-conditioned residual value; and
|
|
16
|
+
* ``ResidualHeadroomAdaptiveMarketProjector`` injects the prior-only estimate
|
|
17
|
+
into any existing adaptive market without changing the workload adapter.
|
|
18
|
+
|
|
19
|
+
Predicted values are selection evidence only. They never enter an
|
|
20
|
+
authoritative archive or replace a real evaluator outcome.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
import hashlib
|
|
26
|
+
import json
|
|
27
|
+
import math
|
|
28
|
+
from dataclasses import dataclass, field, replace
|
|
29
|
+
|
|
30
|
+
from agent_evolve.application.materialized_action_broker import (
|
|
31
|
+
BrokerActionScore,
|
|
32
|
+
MaterializedActionDescriptor,
|
|
33
|
+
)
|
|
34
|
+
from agent_evolve.application.outcome_adaptive_action_racing import (
|
|
35
|
+
AdaptiveActionDescriptor,
|
|
36
|
+
AdaptiveActionFactorCell,
|
|
37
|
+
AdaptiveActionOutcome,
|
|
38
|
+
AdaptiveActionRacingDecision,
|
|
39
|
+
AdaptiveActionSetOutcome,
|
|
40
|
+
)
|
|
41
|
+
from agent_evolve.application.outcome_adaptive_residual_portfolio_evolution import (
|
|
42
|
+
AdaptiveActionMarketProjectorPort,
|
|
43
|
+
)
|
|
44
|
+
from agent_evolve.application.residual_portfolio_evolution import (
|
|
45
|
+
MaterializedActionProposalBatch,
|
|
46
|
+
ResidualPortfolioDecisionRequest,
|
|
47
|
+
)
|
|
48
|
+
from agent_evolve.domain.patch import require_sha256
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
RESIDUAL_HEADROOM_LEDGER_ID = "conserved_residual_headroom_ledger"
|
|
52
|
+
RESIDUAL_HEADROOM_LEDGER_VERSION = 1
|
|
53
|
+
RESIDUAL_HEADROOM_LEDGER_DEFINITION_SHA256 = hashlib.sha256(
|
|
54
|
+
b"agent-evolve:conserved-residual-headroom-ledger:v1;"
|
|
55
|
+
b"evidence=authenticated-real-action-and-conditional-set-outcomes;"
|
|
56
|
+
b"credit=wave-conditional-gain-proportional-to-isolated-real-gain;"
|
|
57
|
+
b"conservation=sum-action-credit-equals-sum-conditional-set-gain;"
|
|
58
|
+
b"attribution=equal-share-over-opaque-portable-action-cells;"
|
|
59
|
+
b"posterior=context-conditioned-decayed-clipped-ipw;"
|
|
60
|
+
b"headroom=expected-gain-plus-uncertainty-plus-late-bloom;"
|
|
61
|
+
b"risk=redundancy-plus-saturation-plus-invalidity;"
|
|
62
|
+
b"archive-authority=real-evaluations-only;"
|
|
63
|
+
b"workload-objective-model-provider-prompt-config-branches=false"
|
|
64
|
+
).hexdigest()
|
|
65
|
+
|
|
66
|
+
RESIDUAL_HEADROOM_ADAPTIVE_MARKET_PROJECTOR_ID = (
|
|
67
|
+
"residual_headroom_adaptive_market_projector"
|
|
68
|
+
)
|
|
69
|
+
RESIDUAL_HEADROOM_ADAPTIVE_MARKET_PROJECTOR_VERSION = 1
|
|
70
|
+
|
|
71
|
+
_OBSERVATION_DOMAIN = b"agent-evolve:residual-headroom-observation:v1\x00"
|
|
72
|
+
_CLOSURE_DOMAIN = b"agent-evolve:residual-headroom-stage-closure:v1\x00"
|
|
73
|
+
_STATE_DOMAIN = b"agent-evolve:residual-headroom-ledger-state:v1\x00"
|
|
74
|
+
_CONFIG_DOMAIN = b"agent-evolve:residual-headroom-ledger-config:v1\x00"
|
|
75
|
+
_ESTIMATE_DOMAIN = b"agent-evolve:residual-headroom-estimate:v1\x00"
|
|
76
|
+
_MARKET_PROJECTOR_DOMAIN = (
|
|
77
|
+
b"agent-evolve:residual-headroom-market-projector:v1\x00"
|
|
78
|
+
)
|
|
79
|
+
_MARKET_STATE_DOMAIN = (
|
|
80
|
+
b"agent-evolve:residual-headroom-market-projector-state:v1\x00"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def _canonical_json(value: object) -> bytes:
|
|
85
|
+
return json.dumps(
|
|
86
|
+
value,
|
|
87
|
+
allow_nan=False,
|
|
88
|
+
ensure_ascii=True,
|
|
89
|
+
separators=(",", ":"),
|
|
90
|
+
sort_keys=True,
|
|
91
|
+
).encode("ascii", errors="strict")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _hash(domain: bytes, value: object) -> str:
|
|
95
|
+
return hashlib.sha256(domain + _canonical_json(value)).hexdigest()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _close(left: float, right: float) -> bool:
|
|
99
|
+
return math.isclose(left, right, rel_tol=1e-12, abs_tol=1e-15)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _require_nonnegative(value: float, *, name: str) -> None:
|
|
103
|
+
if (
|
|
104
|
+
type(value) is not float
|
|
105
|
+
or not math.isfinite(value)
|
|
106
|
+
or value < 0.0
|
|
107
|
+
):
|
|
108
|
+
raise ValueError(f"{name} must be finite and non-negative")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def _attribution_cells(
|
|
112
|
+
action: AdaptiveActionDescriptor,
|
|
113
|
+
) -> tuple[AdaptiveActionFactorCell, ...]:
|
|
114
|
+
"""Project one portable action into conserved-credit attribution cells."""
|
|
115
|
+
|
|
116
|
+
action.__post_init__()
|
|
117
|
+
cells = set(action.factor_cells)
|
|
118
|
+
cells.add(
|
|
119
|
+
AdaptiveActionFactorCell(
|
|
120
|
+
family_id="portable_lane",
|
|
121
|
+
level_id=action.lane_id,
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
cells.add(
|
|
125
|
+
AdaptiveActionFactorCell(
|
|
126
|
+
family_id="portable_operator",
|
|
127
|
+
level_id=action.operator_id,
|
|
128
|
+
)
|
|
129
|
+
)
|
|
130
|
+
cells.add(
|
|
131
|
+
AdaptiveActionFactorCell(
|
|
132
|
+
family_id="portable_parent_origin",
|
|
133
|
+
level_id=(
|
|
134
|
+
"current_run"
|
|
135
|
+
if action.parent_generated_in_current_run
|
|
136
|
+
else "prior_archive"
|
|
137
|
+
),
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
if not any(
|
|
141
|
+
value.family_id == "materialized_rank_layer"
|
|
142
|
+
for value in cells
|
|
143
|
+
):
|
|
144
|
+
layer = min(
|
|
145
|
+
2,
|
|
146
|
+
((action.native_rank - 1) * 3) // action.lane_size,
|
|
147
|
+
)
|
|
148
|
+
cells.add(
|
|
149
|
+
AdaptiveActionFactorCell(
|
|
150
|
+
family_id="materialized_rank_layer",
|
|
151
|
+
level_id=f"layer{layer}",
|
|
152
|
+
)
|
|
153
|
+
)
|
|
154
|
+
for value in action.semantic_cell_ids:
|
|
155
|
+
cells.add(
|
|
156
|
+
AdaptiveActionFactorCell(
|
|
157
|
+
family_id="portable_semantic_cell",
|
|
158
|
+
level_id=value,
|
|
159
|
+
)
|
|
160
|
+
)
|
|
161
|
+
return tuple(sorted(cells))
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@dataclass(frozen=True, slots=True)
|
|
165
|
+
class ResidualHeadroomObservation:
|
|
166
|
+
"""One action's conserved share of a real conditional wave gain."""
|
|
167
|
+
|
|
168
|
+
context_sha256: str
|
|
169
|
+
residual_request_sha256: str
|
|
170
|
+
generation_index: int
|
|
171
|
+
wave_index: int
|
|
172
|
+
action_sha256: str
|
|
173
|
+
evaluation_sha256: str
|
|
174
|
+
outcome_sha256: str
|
|
175
|
+
set_outcome_sha256: str
|
|
176
|
+
decision_sha256: str
|
|
177
|
+
selection_propensity: float
|
|
178
|
+
propensity_identified: bool
|
|
179
|
+
feasible: bool
|
|
180
|
+
isolated_gain: float
|
|
181
|
+
conditional_credit: float
|
|
182
|
+
normalized_conditional_credit: float
|
|
183
|
+
redundancy_fraction: float
|
|
184
|
+
synergy_fraction: float
|
|
185
|
+
attribution_cells: tuple[AdaptiveActionFactorCell, ...]
|
|
186
|
+
observation_sha256: str = field(init=False)
|
|
187
|
+
|
|
188
|
+
def __post_init__(self) -> None:
|
|
189
|
+
for name in (
|
|
190
|
+
"context_sha256",
|
|
191
|
+
"residual_request_sha256",
|
|
192
|
+
"action_sha256",
|
|
193
|
+
"evaluation_sha256",
|
|
194
|
+
"outcome_sha256",
|
|
195
|
+
"set_outcome_sha256",
|
|
196
|
+
"decision_sha256",
|
|
197
|
+
):
|
|
198
|
+
require_sha256(getattr(self, name), name)
|
|
199
|
+
if type(self.generation_index) is not int or self.generation_index < 0:
|
|
200
|
+
raise ValueError("generation_index must be non-negative")
|
|
201
|
+
if type(self.wave_index) is not int or self.wave_index < 0:
|
|
202
|
+
raise ValueError("wave_index must be non-negative")
|
|
203
|
+
if (
|
|
204
|
+
type(self.selection_propensity) is not float
|
|
205
|
+
or not math.isfinite(self.selection_propensity)
|
|
206
|
+
or not 0.0 < self.selection_propensity <= 1.0
|
|
207
|
+
):
|
|
208
|
+
raise ValueError("selection_propensity must lie in (0, 1]")
|
|
209
|
+
if type(self.propensity_identified) is not bool:
|
|
210
|
+
raise TypeError("propensity_identified must be exact")
|
|
211
|
+
if type(self.feasible) is not bool:
|
|
212
|
+
raise TypeError("feasible must be exact")
|
|
213
|
+
for name in (
|
|
214
|
+
"isolated_gain",
|
|
215
|
+
"conditional_credit",
|
|
216
|
+
"normalized_conditional_credit",
|
|
217
|
+
"redundancy_fraction",
|
|
218
|
+
"synergy_fraction",
|
|
219
|
+
):
|
|
220
|
+
_require_nonnegative(getattr(self, name), name=name)
|
|
221
|
+
for name in ("redundancy_fraction", "synergy_fraction"):
|
|
222
|
+
if getattr(self, name) > 1.0:
|
|
223
|
+
raise ValueError(f"{name} must not exceed one")
|
|
224
|
+
if not self.feasible and (
|
|
225
|
+
self.isolated_gain != 0.0
|
|
226
|
+
or self.conditional_credit != 0.0
|
|
227
|
+
):
|
|
228
|
+
raise ValueError("infeasible actions cannot receive positive credit")
|
|
229
|
+
if (
|
|
230
|
+
type(self.attribution_cells) is not tuple
|
|
231
|
+
or not self.attribution_cells
|
|
232
|
+
or self.attribution_cells
|
|
233
|
+
!= tuple(sorted(set(self.attribution_cells)))
|
|
234
|
+
):
|
|
235
|
+
raise ValueError(
|
|
236
|
+
"attribution_cells must be non-empty, unique, and canonical"
|
|
237
|
+
)
|
|
238
|
+
for value in self.attribution_cells:
|
|
239
|
+
if type(value) is not AdaptiveActionFactorCell:
|
|
240
|
+
raise TypeError("attribution cells must be exact")
|
|
241
|
+
value.__post_init__()
|
|
242
|
+
object.__setattr__(
|
|
243
|
+
self,
|
|
244
|
+
"observation_sha256",
|
|
245
|
+
_hash(_OBSERVATION_DOMAIN, self._unsigned_record()),
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
249
|
+
return {
|
|
250
|
+
"schema_version": 1,
|
|
251
|
+
"context_sha256": self.context_sha256,
|
|
252
|
+
"residual_request_sha256": self.residual_request_sha256,
|
|
253
|
+
"generation_index": self.generation_index,
|
|
254
|
+
"wave_index": self.wave_index,
|
|
255
|
+
"action_sha256": self.action_sha256,
|
|
256
|
+
"evaluation_sha256": self.evaluation_sha256,
|
|
257
|
+
"outcome_sha256": self.outcome_sha256,
|
|
258
|
+
"set_outcome_sha256": self.set_outcome_sha256,
|
|
259
|
+
"decision_sha256": self.decision_sha256,
|
|
260
|
+
"selection_propensity_hex": self.selection_propensity.hex(),
|
|
261
|
+
"propensity_identified": self.propensity_identified,
|
|
262
|
+
"feasible": self.feasible,
|
|
263
|
+
"isolated_gain_hex": self.isolated_gain.hex(),
|
|
264
|
+
"conditional_credit_hex": self.conditional_credit.hex(),
|
|
265
|
+
"normalized_conditional_credit_hex": (
|
|
266
|
+
self.normalized_conditional_credit.hex()
|
|
267
|
+
),
|
|
268
|
+
"redundancy_fraction_hex": self.redundancy_fraction.hex(),
|
|
269
|
+
"synergy_fraction_hex": self.synergy_fraction.hex(),
|
|
270
|
+
"attribution_cells": [
|
|
271
|
+
value.to_record() for value in self.attribution_cells
|
|
272
|
+
],
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
def to_record(self) -> dict[str, object]:
|
|
276
|
+
self.__post_init__()
|
|
277
|
+
return {
|
|
278
|
+
**self._unsigned_record(),
|
|
279
|
+
"observation_sha256": self.observation_sha256,
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@classmethod
|
|
283
|
+
def from_record(
|
|
284
|
+
cls,
|
|
285
|
+
record: dict[str, object],
|
|
286
|
+
) -> "ResidualHeadroomObservation":
|
|
287
|
+
if type(record) is not dict:
|
|
288
|
+
raise TypeError("observation record must be an exact object")
|
|
289
|
+
cells = record["attribution_cells"]
|
|
290
|
+
if (
|
|
291
|
+
type(cells) is not list
|
|
292
|
+
or any(type(value) is not dict for value in cells)
|
|
293
|
+
):
|
|
294
|
+
raise TypeError("attribution_cells record must be a list")
|
|
295
|
+
value = cls(
|
|
296
|
+
context_sha256=str(record["context_sha256"]),
|
|
297
|
+
residual_request_sha256=str(
|
|
298
|
+
record["residual_request_sha256"]
|
|
299
|
+
),
|
|
300
|
+
generation_index=int(record["generation_index"]),
|
|
301
|
+
wave_index=int(record["wave_index"]),
|
|
302
|
+
action_sha256=str(record["action_sha256"]),
|
|
303
|
+
evaluation_sha256=str(record["evaluation_sha256"]),
|
|
304
|
+
outcome_sha256=str(record["outcome_sha256"]),
|
|
305
|
+
set_outcome_sha256=str(record["set_outcome_sha256"]),
|
|
306
|
+
decision_sha256=str(record["decision_sha256"]),
|
|
307
|
+
selection_propensity=float.fromhex(
|
|
308
|
+
str(record["selection_propensity_hex"])
|
|
309
|
+
),
|
|
310
|
+
propensity_identified=bool(record["propensity_identified"]),
|
|
311
|
+
feasible=bool(record["feasible"]),
|
|
312
|
+
isolated_gain=float.fromhex(
|
|
313
|
+
str(record["isolated_gain_hex"])
|
|
314
|
+
),
|
|
315
|
+
conditional_credit=float.fromhex(
|
|
316
|
+
str(record["conditional_credit_hex"])
|
|
317
|
+
),
|
|
318
|
+
normalized_conditional_credit=float.fromhex(
|
|
319
|
+
str(record["normalized_conditional_credit_hex"])
|
|
320
|
+
),
|
|
321
|
+
redundancy_fraction=float.fromhex(
|
|
322
|
+
str(record["redundancy_fraction_hex"])
|
|
323
|
+
),
|
|
324
|
+
synergy_fraction=float.fromhex(
|
|
325
|
+
str(record["synergy_fraction_hex"])
|
|
326
|
+
),
|
|
327
|
+
attribution_cells=tuple(
|
|
328
|
+
AdaptiveActionFactorCell(
|
|
329
|
+
family_id=str(cell["family_id"]),
|
|
330
|
+
level_id=str(cell["level_id"]),
|
|
331
|
+
)
|
|
332
|
+
for cell in cells
|
|
333
|
+
),
|
|
334
|
+
)
|
|
335
|
+
if value.observation_sha256 != str(
|
|
336
|
+
record["observation_sha256"]
|
|
337
|
+
):
|
|
338
|
+
raise ValueError("observation record hash does not authenticate")
|
|
339
|
+
return value
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
@dataclass(frozen=True, slots=True)
|
|
343
|
+
class ResidualHeadroomStageClosure:
|
|
344
|
+
"""Authenticated, conserved learning evidence for one real stage."""
|
|
345
|
+
|
|
346
|
+
context_sha256: str
|
|
347
|
+
residual_request_sha256: str
|
|
348
|
+
generation_index: int
|
|
349
|
+
reference_gain_scale: float
|
|
350
|
+
reference_gain_evidence_sha256: str
|
|
351
|
+
decision_sha256s: tuple[str, ...]
|
|
352
|
+
set_outcome_sha256s: tuple[str, ...]
|
|
353
|
+
observations: tuple[ResidualHeadroomObservation, ...]
|
|
354
|
+
total_conditional_gain: float
|
|
355
|
+
closure_sha256: str = field(init=False)
|
|
356
|
+
|
|
357
|
+
def __post_init__(self) -> None:
|
|
358
|
+
for name in (
|
|
359
|
+
"context_sha256",
|
|
360
|
+
"residual_request_sha256",
|
|
361
|
+
"reference_gain_evidence_sha256",
|
|
362
|
+
):
|
|
363
|
+
require_sha256(getattr(self, name), name)
|
|
364
|
+
if type(self.generation_index) is not int or self.generation_index < 0:
|
|
365
|
+
raise ValueError("generation_index must be non-negative")
|
|
366
|
+
if (
|
|
367
|
+
type(self.reference_gain_scale) is not float
|
|
368
|
+
or not math.isfinite(self.reference_gain_scale)
|
|
369
|
+
or self.reference_gain_scale <= 0.0
|
|
370
|
+
):
|
|
371
|
+
raise ValueError("reference_gain_scale must be positive")
|
|
372
|
+
for values, name in (
|
|
373
|
+
(self.decision_sha256s, "decision_sha256s"),
|
|
374
|
+
(self.set_outcome_sha256s, "set_outcome_sha256s"),
|
|
375
|
+
):
|
|
376
|
+
if (
|
|
377
|
+
type(values) is not tuple
|
|
378
|
+
or not values
|
|
379
|
+
or values != tuple(dict.fromkeys(values))
|
|
380
|
+
):
|
|
381
|
+
raise ValueError(f"{name} must be non-empty and ordered unique")
|
|
382
|
+
for value in values:
|
|
383
|
+
require_sha256(value, name)
|
|
384
|
+
if len(self.decision_sha256s) != len(self.set_outcome_sha256s):
|
|
385
|
+
raise ValueError("each decision must bind one set outcome")
|
|
386
|
+
if type(self.observations) is not tuple or not self.observations:
|
|
387
|
+
raise ValueError("observations must be a non-empty exact tuple")
|
|
388
|
+
identities: list[str] = []
|
|
389
|
+
for value in self.observations:
|
|
390
|
+
if type(value) is not ResidualHeadroomObservation:
|
|
391
|
+
raise TypeError("observations must contain exact values")
|
|
392
|
+
value.__post_init__()
|
|
393
|
+
if (
|
|
394
|
+
value.context_sha256 != self.context_sha256
|
|
395
|
+
or value.residual_request_sha256
|
|
396
|
+
!= self.residual_request_sha256
|
|
397
|
+
or value.generation_index != self.generation_index
|
|
398
|
+
or value.decision_sha256
|
|
399
|
+
not in self.decision_sha256s
|
|
400
|
+
or value.set_outcome_sha256
|
|
401
|
+
not in self.set_outcome_sha256s
|
|
402
|
+
):
|
|
403
|
+
raise ValueError("an observation names another stage closure")
|
|
404
|
+
if not _close(
|
|
405
|
+
value.normalized_conditional_credit,
|
|
406
|
+
value.conditional_credit / self.reference_gain_scale,
|
|
407
|
+
):
|
|
408
|
+
raise ValueError("normalized credit differs from stage scale")
|
|
409
|
+
identities.append(value.action_sha256)
|
|
410
|
+
if len(identities) != len(set(identities)):
|
|
411
|
+
raise ValueError("stage closure repeats an action")
|
|
412
|
+
_require_nonnegative(
|
|
413
|
+
self.total_conditional_gain,
|
|
414
|
+
name="total_conditional_gain",
|
|
415
|
+
)
|
|
416
|
+
attributed = math.fsum(
|
|
417
|
+
value.conditional_credit for value in self.observations
|
|
418
|
+
)
|
|
419
|
+
if not _close(attributed, self.total_conditional_gain):
|
|
420
|
+
raise ValueError("action credit does not conserve conditional gain")
|
|
421
|
+
object.__setattr__(
|
|
422
|
+
self,
|
|
423
|
+
"closure_sha256",
|
|
424
|
+
_hash(_CLOSURE_DOMAIN, self._unsigned_record()),
|
|
425
|
+
)
|
|
426
|
+
|
|
427
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
428
|
+
return {
|
|
429
|
+
"schema_version": 1,
|
|
430
|
+
"ledger_definition_sha256": (
|
|
431
|
+
RESIDUAL_HEADROOM_LEDGER_DEFINITION_SHA256
|
|
432
|
+
),
|
|
433
|
+
"context_sha256": self.context_sha256,
|
|
434
|
+
"residual_request_sha256": self.residual_request_sha256,
|
|
435
|
+
"generation_index": self.generation_index,
|
|
436
|
+
"reference_gain_scale_hex": self.reference_gain_scale.hex(),
|
|
437
|
+
"reference_gain_evidence_sha256": (
|
|
438
|
+
self.reference_gain_evidence_sha256
|
|
439
|
+
),
|
|
440
|
+
"decision_sha256s": list(self.decision_sha256s),
|
|
441
|
+
"set_outcome_sha256s": list(self.set_outcome_sha256s),
|
|
442
|
+
"observation_sha256s": [
|
|
443
|
+
value.observation_sha256 for value in self.observations
|
|
444
|
+
],
|
|
445
|
+
"total_conditional_gain_hex": (
|
|
446
|
+
self.total_conditional_gain.hex()
|
|
447
|
+
),
|
|
448
|
+
"credit_conserved": True,
|
|
449
|
+
"predicted_values_admitted_to_archive": False,
|
|
450
|
+
"workload_objective_model_provider_prompt_config_fields": False,
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
def to_record(self) -> dict[str, object]:
|
|
454
|
+
self.__post_init__()
|
|
455
|
+
return {
|
|
456
|
+
**self._unsigned_record(),
|
|
457
|
+
"observations": [
|
|
458
|
+
value.to_record() for value in self.observations
|
|
459
|
+
],
|
|
460
|
+
"closure_sha256": self.closure_sha256,
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
@classmethod
|
|
464
|
+
def from_record(
|
|
465
|
+
cls,
|
|
466
|
+
record: dict[str, object],
|
|
467
|
+
) -> "ResidualHeadroomStageClosure":
|
|
468
|
+
if type(record) is not dict:
|
|
469
|
+
raise TypeError("closure record must be an exact object")
|
|
470
|
+
observations = record["observations"]
|
|
471
|
+
if (
|
|
472
|
+
type(observations) is not list
|
|
473
|
+
or any(type(value) is not dict for value in observations)
|
|
474
|
+
):
|
|
475
|
+
raise TypeError("closure observations must be exact objects")
|
|
476
|
+
value = cls(
|
|
477
|
+
context_sha256=str(record["context_sha256"]),
|
|
478
|
+
residual_request_sha256=str(
|
|
479
|
+
record["residual_request_sha256"]
|
|
480
|
+
),
|
|
481
|
+
generation_index=int(record["generation_index"]),
|
|
482
|
+
reference_gain_scale=float.fromhex(
|
|
483
|
+
str(record["reference_gain_scale_hex"])
|
|
484
|
+
),
|
|
485
|
+
reference_gain_evidence_sha256=str(
|
|
486
|
+
record["reference_gain_evidence_sha256"]
|
|
487
|
+
),
|
|
488
|
+
decision_sha256s=tuple(
|
|
489
|
+
str(item) for item in record["decision_sha256s"]
|
|
490
|
+
),
|
|
491
|
+
set_outcome_sha256s=tuple(
|
|
492
|
+
str(item) for item in record["set_outcome_sha256s"]
|
|
493
|
+
),
|
|
494
|
+
observations=tuple(
|
|
495
|
+
ResidualHeadroomObservation.from_record(value)
|
|
496
|
+
for value in observations
|
|
497
|
+
),
|
|
498
|
+
total_conditional_gain=float.fromhex(
|
|
499
|
+
str(record["total_conditional_gain_hex"])
|
|
500
|
+
),
|
|
501
|
+
)
|
|
502
|
+
if value.closure_sha256 != str(record["closure_sha256"]):
|
|
503
|
+
raise ValueError("closure record hash does not authenticate")
|
|
504
|
+
return value
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
@dataclass(frozen=True, slots=True)
|
|
508
|
+
class ConservedResidualHeadroomProjector:
|
|
509
|
+
"""Compile one outcome-adaptive stage into conserved ledger evidence."""
|
|
510
|
+
|
|
511
|
+
def project(
|
|
512
|
+
self,
|
|
513
|
+
*,
|
|
514
|
+
context_sha256: str,
|
|
515
|
+
generation_index: int,
|
|
516
|
+
reference_gain_scale: float,
|
|
517
|
+
reference_gain_evidence_sha256: str,
|
|
518
|
+
actions: tuple[AdaptiveActionDescriptor, ...],
|
|
519
|
+
diagnostic_decision: AdaptiveActionRacingDecision,
|
|
520
|
+
continuation_decisions: tuple[
|
|
521
|
+
AdaptiveActionRacingDecision, ...
|
|
522
|
+
],
|
|
523
|
+
outcomes: tuple[AdaptiveActionOutcome, ...],
|
|
524
|
+
set_outcomes: tuple[AdaptiveActionSetOutcome, ...],
|
|
525
|
+
) -> ResidualHeadroomStageClosure:
|
|
526
|
+
require_sha256(context_sha256, "context_sha256")
|
|
527
|
+
require_sha256(
|
|
528
|
+
reference_gain_evidence_sha256,
|
|
529
|
+
"reference_gain_evidence_sha256",
|
|
530
|
+
)
|
|
531
|
+
if type(generation_index) is not int or generation_index < 0:
|
|
532
|
+
raise ValueError("generation_index must be non-negative")
|
|
533
|
+
if (
|
|
534
|
+
type(reference_gain_scale) is not float
|
|
535
|
+
or not math.isfinite(reference_gain_scale)
|
|
536
|
+
or reference_gain_scale <= 0.0
|
|
537
|
+
):
|
|
538
|
+
raise ValueError("reference_gain_scale must be positive")
|
|
539
|
+
if type(actions) is not tuple or not actions:
|
|
540
|
+
raise ValueError("actions must be a non-empty exact tuple")
|
|
541
|
+
action_by_sha256: dict[str, AdaptiveActionDescriptor] = {}
|
|
542
|
+
for value in actions:
|
|
543
|
+
if type(value) is not AdaptiveActionDescriptor:
|
|
544
|
+
raise TypeError("actions must contain exact values")
|
|
545
|
+
value.__post_init__()
|
|
546
|
+
action_by_sha256[value.action_sha256] = value
|
|
547
|
+
if len(action_by_sha256) != len(actions):
|
|
548
|
+
raise ValueError("actions repeat an identity")
|
|
549
|
+
if type(diagnostic_decision) is not AdaptiveActionRacingDecision:
|
|
550
|
+
raise TypeError("diagnostic_decision must be exact")
|
|
551
|
+
diagnostic_decision.__post_init__()
|
|
552
|
+
if type(continuation_decisions) is not tuple:
|
|
553
|
+
raise TypeError("continuation_decisions must be an exact tuple")
|
|
554
|
+
decisions = (diagnostic_decision, *continuation_decisions)
|
|
555
|
+
for value in decisions:
|
|
556
|
+
if type(value) is not AdaptiveActionRacingDecision:
|
|
557
|
+
raise TypeError("continuation decisions must be exact")
|
|
558
|
+
value.__post_init__()
|
|
559
|
+
request_sha256 = diagnostic_decision.residual_request_sha256
|
|
560
|
+
if any(
|
|
561
|
+
value.residual_request_sha256 != request_sha256
|
|
562
|
+
for value in decisions
|
|
563
|
+
):
|
|
564
|
+
raise ValueError("decisions name different residual requests")
|
|
565
|
+
if (
|
|
566
|
+
type(outcomes) is not tuple
|
|
567
|
+
or not outcomes
|
|
568
|
+
or any(type(value) is not AdaptiveActionOutcome for value in outcomes)
|
|
569
|
+
):
|
|
570
|
+
raise ValueError("outcomes must be a non-empty exact tuple")
|
|
571
|
+
outcome_by_action: dict[str, AdaptiveActionOutcome] = {}
|
|
572
|
+
for value in outcomes:
|
|
573
|
+
value.__post_init__()
|
|
574
|
+
outcome_by_action[value.action_sha256] = value
|
|
575
|
+
if len(outcome_by_action) != len(outcomes):
|
|
576
|
+
raise ValueError("outcomes repeat an action")
|
|
577
|
+
if (
|
|
578
|
+
type(set_outcomes) is not tuple
|
|
579
|
+
or len(set_outcomes) != len(decisions)
|
|
580
|
+
):
|
|
581
|
+
raise ValueError("each decision requires one ordered set outcome")
|
|
582
|
+
|
|
583
|
+
observations: list[ResidualHeadroomObservation] = []
|
|
584
|
+
for wave_index, (decision, set_outcome) in enumerate(
|
|
585
|
+
zip(decisions, set_outcomes, strict=True)
|
|
586
|
+
):
|
|
587
|
+
if type(set_outcome) is not AdaptiveActionSetOutcome:
|
|
588
|
+
raise TypeError("set outcomes must contain exact values")
|
|
589
|
+
set_outcome.__post_init__()
|
|
590
|
+
selected = tuple(
|
|
591
|
+
value[0]
|
|
592
|
+
for value in set_outcome.current_action_evaluation_bindings
|
|
593
|
+
)
|
|
594
|
+
if set(selected) != set(decision.selected_action_sha256s):
|
|
595
|
+
raise ValueError(
|
|
596
|
+
"decision selection differs from its real set outcome"
|
|
597
|
+
)
|
|
598
|
+
wave_outcomes: list[AdaptiveActionOutcome] = []
|
|
599
|
+
for action_sha256, evaluation_sha256 in (
|
|
600
|
+
set_outcome.current_action_evaluation_bindings
|
|
601
|
+
):
|
|
602
|
+
action = action_by_sha256.get(action_sha256)
|
|
603
|
+
outcome = outcome_by_action.get(action_sha256)
|
|
604
|
+
if (
|
|
605
|
+
action is None
|
|
606
|
+
or outcome is None
|
|
607
|
+
or outcome.evaluation_sha256 != evaluation_sha256
|
|
608
|
+
):
|
|
609
|
+
raise ValueError(
|
|
610
|
+
"set outcome lacks its action/evaluation binding"
|
|
611
|
+
)
|
|
612
|
+
wave_outcomes.append(outcome)
|
|
613
|
+
isolated_sum = math.fsum(
|
|
614
|
+
value.marginal_archive_gain for value in wave_outcomes
|
|
615
|
+
)
|
|
616
|
+
conditional = set_outcome.conditional_set_gain
|
|
617
|
+
if conditional == 0.0:
|
|
618
|
+
credits = [0.0 for _ in wave_outcomes]
|
|
619
|
+
elif isolated_sum > 0.0:
|
|
620
|
+
credits = [
|
|
621
|
+
conditional
|
|
622
|
+
* value.marginal_archive_gain
|
|
623
|
+
/ isolated_sum
|
|
624
|
+
for value in wave_outcomes
|
|
625
|
+
]
|
|
626
|
+
else:
|
|
627
|
+
credits = [
|
|
628
|
+
conditional / len(wave_outcomes)
|
|
629
|
+
for _ in wave_outcomes
|
|
630
|
+
]
|
|
631
|
+
if credits:
|
|
632
|
+
credits[-1] = max(
|
|
633
|
+
0.0,
|
|
634
|
+
conditional - math.fsum(credits[:-1]),
|
|
635
|
+
)
|
|
636
|
+
fixed = set_outcome.current_wave_fixed_set_gain
|
|
637
|
+
redundancy_fraction = (
|
|
638
|
+
0.0
|
|
639
|
+
if fixed <= 0.0
|
|
640
|
+
else min(
|
|
641
|
+
set_outcome.prior_conditioned_redundancy / fixed,
|
|
642
|
+
1.0,
|
|
643
|
+
)
|
|
644
|
+
)
|
|
645
|
+
synergy_fraction = (
|
|
646
|
+
0.0
|
|
647
|
+
if conditional <= 0.0
|
|
648
|
+
else min(
|
|
649
|
+
set_outcome.prior_conditioned_synergy / conditional,
|
|
650
|
+
1.0,
|
|
651
|
+
)
|
|
652
|
+
)
|
|
653
|
+
identified = (
|
|
654
|
+
len(decision.selected_action_sha256s) == 1
|
|
655
|
+
or decision.selection_propensity == 1.0
|
|
656
|
+
)
|
|
657
|
+
effective_propensity = (
|
|
658
|
+
decision.selection_propensity if identified else 1.0
|
|
659
|
+
)
|
|
660
|
+
for outcome, credit in zip(
|
|
661
|
+
wave_outcomes,
|
|
662
|
+
credits,
|
|
663
|
+
strict=True,
|
|
664
|
+
):
|
|
665
|
+
observations.append(
|
|
666
|
+
ResidualHeadroomObservation(
|
|
667
|
+
context_sha256=context_sha256,
|
|
668
|
+
residual_request_sha256=request_sha256,
|
|
669
|
+
generation_index=generation_index,
|
|
670
|
+
wave_index=wave_index,
|
|
671
|
+
action_sha256=outcome.action_sha256,
|
|
672
|
+
evaluation_sha256=outcome.evaluation_sha256,
|
|
673
|
+
outcome_sha256=outcome.outcome_sha256,
|
|
674
|
+
set_outcome_sha256=(
|
|
675
|
+
set_outcome.set_outcome_sha256
|
|
676
|
+
),
|
|
677
|
+
decision_sha256=decision.decision_sha256,
|
|
678
|
+
selection_propensity=effective_propensity,
|
|
679
|
+
propensity_identified=identified,
|
|
680
|
+
feasible=outcome.feasible,
|
|
681
|
+
isolated_gain=outcome.marginal_archive_gain,
|
|
682
|
+
conditional_credit=float(credit),
|
|
683
|
+
normalized_conditional_credit=float(
|
|
684
|
+
credit / reference_gain_scale
|
|
685
|
+
),
|
|
686
|
+
redundancy_fraction=redundancy_fraction,
|
|
687
|
+
synergy_fraction=synergy_fraction,
|
|
688
|
+
attribution_cells=_attribution_cells(
|
|
689
|
+
action_by_sha256[outcome.action_sha256]
|
|
690
|
+
),
|
|
691
|
+
)
|
|
692
|
+
)
|
|
693
|
+
total_conditional_gain = math.fsum(
|
|
694
|
+
value.conditional_set_gain for value in set_outcomes
|
|
695
|
+
)
|
|
696
|
+
return ResidualHeadroomStageClosure(
|
|
697
|
+
context_sha256=context_sha256,
|
|
698
|
+
residual_request_sha256=request_sha256,
|
|
699
|
+
generation_index=generation_index,
|
|
700
|
+
reference_gain_scale=reference_gain_scale,
|
|
701
|
+
reference_gain_evidence_sha256=(
|
|
702
|
+
reference_gain_evidence_sha256
|
|
703
|
+
),
|
|
704
|
+
decision_sha256s=tuple(
|
|
705
|
+
value.decision_sha256 for value in decisions
|
|
706
|
+
),
|
|
707
|
+
set_outcome_sha256s=tuple(
|
|
708
|
+
value.set_outcome_sha256 for value in set_outcomes
|
|
709
|
+
),
|
|
710
|
+
observations=tuple(observations),
|
|
711
|
+
total_conditional_gain=float(total_conditional_gain),
|
|
712
|
+
)
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
@dataclass(frozen=True, slots=True)
|
|
716
|
+
class ResidualHeadroomLedgerConfig:
|
|
717
|
+
"""Portable posterior and risk controls for residual-headroom learning."""
|
|
718
|
+
|
|
719
|
+
generation_decay: float = 0.85
|
|
720
|
+
cross_context_weight: float = 0.0
|
|
721
|
+
maximum_inverse_propensity: float = 10.0
|
|
722
|
+
prior_strength: float = 2.0
|
|
723
|
+
prior_normalized_gain: float = 1.0
|
|
724
|
+
positive_prior_alpha: float = 1.0
|
|
725
|
+
positive_prior_beta: float = 1.0
|
|
726
|
+
invalid_prior_alpha: float = 1.0
|
|
727
|
+
invalid_prior_beta: float = 9.0
|
|
728
|
+
uncertainty_strength: float = 1.0
|
|
729
|
+
late_bloom_strength: float = 0.5
|
|
730
|
+
saturation_strength: float = 0.5
|
|
731
|
+
redundancy_strength: float = 0.5
|
|
732
|
+
invalidity_strength: float = 0.5
|
|
733
|
+
exploration_floor: float = 0.25
|
|
734
|
+
maximum_abs_slope: float = 2.0
|
|
735
|
+
definition_sha256: str = field(init=False)
|
|
736
|
+
|
|
737
|
+
def __post_init__(self) -> None:
|
|
738
|
+
if (
|
|
739
|
+
type(self.generation_decay) is not float
|
|
740
|
+
or not math.isfinite(self.generation_decay)
|
|
741
|
+
or not 0.0 < self.generation_decay <= 1.0
|
|
742
|
+
):
|
|
743
|
+
raise ValueError("generation_decay must lie in (0, 1]")
|
|
744
|
+
if (
|
|
745
|
+
type(self.cross_context_weight) is not float
|
|
746
|
+
or not math.isfinite(self.cross_context_weight)
|
|
747
|
+
or not 0.0 <= self.cross_context_weight <= 1.0
|
|
748
|
+
):
|
|
749
|
+
raise ValueError("cross_context_weight must lie in [0, 1]")
|
|
750
|
+
for value, name, positive in (
|
|
751
|
+
(
|
|
752
|
+
self.maximum_inverse_propensity,
|
|
753
|
+
"maximum_inverse_propensity",
|
|
754
|
+
True,
|
|
755
|
+
),
|
|
756
|
+
(self.prior_strength, "prior_strength", True),
|
|
757
|
+
(
|
|
758
|
+
self.prior_normalized_gain,
|
|
759
|
+
"prior_normalized_gain",
|
|
760
|
+
False,
|
|
761
|
+
),
|
|
762
|
+
(
|
|
763
|
+
self.positive_prior_alpha,
|
|
764
|
+
"positive_prior_alpha",
|
|
765
|
+
True,
|
|
766
|
+
),
|
|
767
|
+
(
|
|
768
|
+
self.positive_prior_beta,
|
|
769
|
+
"positive_prior_beta",
|
|
770
|
+
True,
|
|
771
|
+
),
|
|
772
|
+
(
|
|
773
|
+
self.invalid_prior_alpha,
|
|
774
|
+
"invalid_prior_alpha",
|
|
775
|
+
True,
|
|
776
|
+
),
|
|
777
|
+
(
|
|
778
|
+
self.invalid_prior_beta,
|
|
779
|
+
"invalid_prior_beta",
|
|
780
|
+
True,
|
|
781
|
+
),
|
|
782
|
+
(
|
|
783
|
+
self.uncertainty_strength,
|
|
784
|
+
"uncertainty_strength",
|
|
785
|
+
False,
|
|
786
|
+
),
|
|
787
|
+
(
|
|
788
|
+
self.late_bloom_strength,
|
|
789
|
+
"late_bloom_strength",
|
|
790
|
+
False,
|
|
791
|
+
),
|
|
792
|
+
(
|
|
793
|
+
self.saturation_strength,
|
|
794
|
+
"saturation_strength",
|
|
795
|
+
False,
|
|
796
|
+
),
|
|
797
|
+
(
|
|
798
|
+
self.redundancy_strength,
|
|
799
|
+
"redundancy_strength",
|
|
800
|
+
False,
|
|
801
|
+
),
|
|
802
|
+
(
|
|
803
|
+
self.invalidity_strength,
|
|
804
|
+
"invalidity_strength",
|
|
805
|
+
False,
|
|
806
|
+
),
|
|
807
|
+
(
|
|
808
|
+
self.exploration_floor,
|
|
809
|
+
"exploration_floor",
|
|
810
|
+
False,
|
|
811
|
+
),
|
|
812
|
+
(
|
|
813
|
+
self.maximum_abs_slope,
|
|
814
|
+
"maximum_abs_slope",
|
|
815
|
+
True,
|
|
816
|
+
),
|
|
817
|
+
):
|
|
818
|
+
if (
|
|
819
|
+
type(value) is not float
|
|
820
|
+
or not math.isfinite(value)
|
|
821
|
+
or value < 0.0
|
|
822
|
+
or (positive and value <= 0.0)
|
|
823
|
+
):
|
|
824
|
+
qualifier = "positive" if positive else "non-negative"
|
|
825
|
+
raise ValueError(f"{name} must be finite and {qualifier}")
|
|
826
|
+
object.__setattr__(
|
|
827
|
+
self,
|
|
828
|
+
"definition_sha256",
|
|
829
|
+
_hash(_CONFIG_DOMAIN, self._unsigned_record()),
|
|
830
|
+
)
|
|
831
|
+
|
|
832
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
833
|
+
return {
|
|
834
|
+
"schema_version": 1,
|
|
835
|
+
"ledger_id": RESIDUAL_HEADROOM_LEDGER_ID,
|
|
836
|
+
"ledger_version": RESIDUAL_HEADROOM_LEDGER_VERSION,
|
|
837
|
+
"ledger_definition_sha256": (
|
|
838
|
+
RESIDUAL_HEADROOM_LEDGER_DEFINITION_SHA256
|
|
839
|
+
),
|
|
840
|
+
"generation_decay_hex": self.generation_decay.hex(),
|
|
841
|
+
"cross_context_weight_hex": self.cross_context_weight.hex(),
|
|
842
|
+
"maximum_inverse_propensity_hex": (
|
|
843
|
+
self.maximum_inverse_propensity.hex()
|
|
844
|
+
),
|
|
845
|
+
"prior_strength_hex": self.prior_strength.hex(),
|
|
846
|
+
"prior_normalized_gain_hex": (
|
|
847
|
+
self.prior_normalized_gain.hex()
|
|
848
|
+
),
|
|
849
|
+
"positive_prior_alpha_hex": (
|
|
850
|
+
self.positive_prior_alpha.hex()
|
|
851
|
+
),
|
|
852
|
+
"positive_prior_beta_hex": self.positive_prior_beta.hex(),
|
|
853
|
+
"invalid_prior_alpha_hex": self.invalid_prior_alpha.hex(),
|
|
854
|
+
"invalid_prior_beta_hex": self.invalid_prior_beta.hex(),
|
|
855
|
+
"uncertainty_strength_hex": self.uncertainty_strength.hex(),
|
|
856
|
+
"late_bloom_strength_hex": self.late_bloom_strength.hex(),
|
|
857
|
+
"saturation_strength_hex": self.saturation_strength.hex(),
|
|
858
|
+
"redundancy_strength_hex": self.redundancy_strength.hex(),
|
|
859
|
+
"invalidity_strength_hex": self.invalidity_strength.hex(),
|
|
860
|
+
"exploration_floor_hex": self.exploration_floor.hex(),
|
|
861
|
+
"maximum_abs_slope_hex": self.maximum_abs_slope.hex(),
|
|
862
|
+
"workload_objective_model_provider_prompt_config_branches": False,
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
def to_record(self) -> dict[str, object]:
|
|
866
|
+
self.__post_init__()
|
|
867
|
+
return {
|
|
868
|
+
**self._unsigned_record(),
|
|
869
|
+
"definition_sha256": self.definition_sha256,
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
|
|
873
|
+
@dataclass(frozen=True, slots=True)
|
|
874
|
+
class ResidualHeadroomLedgerState:
|
|
875
|
+
"""Immutable append-only set of conserved stage closures."""
|
|
876
|
+
|
|
877
|
+
config_definition_sha256: str
|
|
878
|
+
closures: tuple[ResidualHeadroomStageClosure, ...] = ()
|
|
879
|
+
state_sha256: str = field(init=False)
|
|
880
|
+
|
|
881
|
+
def __post_init__(self) -> None:
|
|
882
|
+
require_sha256(
|
|
883
|
+
self.config_definition_sha256,
|
|
884
|
+
"config_definition_sha256",
|
|
885
|
+
)
|
|
886
|
+
if type(self.closures) is not tuple:
|
|
887
|
+
raise TypeError("closures must be an exact tuple")
|
|
888
|
+
closure_ids: list[str] = []
|
|
889
|
+
stage_ids: list[tuple[str, str]] = []
|
|
890
|
+
latest_generation_by_context: dict[str, int] = {}
|
|
891
|
+
for value in self.closures:
|
|
892
|
+
if type(value) is not ResidualHeadroomStageClosure:
|
|
893
|
+
raise TypeError("closures must contain exact values")
|
|
894
|
+
value.__post_init__()
|
|
895
|
+
prior = latest_generation_by_context.get(value.context_sha256)
|
|
896
|
+
if prior is not None and value.generation_index < prior:
|
|
897
|
+
raise ValueError(
|
|
898
|
+
"closure generations must not regress within a context"
|
|
899
|
+
)
|
|
900
|
+
latest_generation_by_context[value.context_sha256] = (
|
|
901
|
+
value.generation_index
|
|
902
|
+
)
|
|
903
|
+
closure_ids.append(value.closure_sha256)
|
|
904
|
+
stage_ids.append(
|
|
905
|
+
(value.context_sha256, value.residual_request_sha256)
|
|
906
|
+
)
|
|
907
|
+
if len(closure_ids) != len(set(closure_ids)):
|
|
908
|
+
raise ValueError("ledger repeats a closure")
|
|
909
|
+
if len(stage_ids) != len(set(stage_ids)):
|
|
910
|
+
raise ValueError("ledger repeats a context/request stage")
|
|
911
|
+
object.__setattr__(
|
|
912
|
+
self,
|
|
913
|
+
"state_sha256",
|
|
914
|
+
_hash(_STATE_DOMAIN, self._unsigned_record()),
|
|
915
|
+
)
|
|
916
|
+
|
|
917
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
918
|
+
return {
|
|
919
|
+
"schema_version": 1,
|
|
920
|
+
"ledger_definition_sha256": (
|
|
921
|
+
RESIDUAL_HEADROOM_LEDGER_DEFINITION_SHA256
|
|
922
|
+
),
|
|
923
|
+
"config_definition_sha256": self.config_definition_sha256,
|
|
924
|
+
"closure_sha256s": [
|
|
925
|
+
value.closure_sha256 for value in self.closures
|
|
926
|
+
],
|
|
927
|
+
"append_only": True,
|
|
928
|
+
"predicted_values_admitted_to_archive": False,
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
def to_record(self, *, include_closures: bool = False) -> dict[str, object]:
|
|
932
|
+
self.__post_init__()
|
|
933
|
+
record = {
|
|
934
|
+
**self._unsigned_record(),
|
|
935
|
+
"state_sha256": self.state_sha256,
|
|
936
|
+
}
|
|
937
|
+
if include_closures:
|
|
938
|
+
record["closures"] = [
|
|
939
|
+
value.to_record() for value in self.closures
|
|
940
|
+
]
|
|
941
|
+
return record
|
|
942
|
+
|
|
943
|
+
|
|
944
|
+
@dataclass(frozen=True, slots=True)
|
|
945
|
+
class ResidualHeadroomCellPosterior:
|
|
946
|
+
cell: AdaptiveActionFactorCell
|
|
947
|
+
posterior_mean: float
|
|
948
|
+
uncertainty: float
|
|
949
|
+
positive_probability: float
|
|
950
|
+
invalid_probability: float
|
|
951
|
+
redundancy_fraction: float
|
|
952
|
+
late_bloom_slope: float
|
|
953
|
+
saturation_slope: float
|
|
954
|
+
effective_sample_size: float
|
|
955
|
+
raw_observation_count: int
|
|
956
|
+
|
|
957
|
+
def __post_init__(self) -> None:
|
|
958
|
+
if type(self.cell) is not AdaptiveActionFactorCell:
|
|
959
|
+
raise TypeError("cell must be exact")
|
|
960
|
+
self.cell.__post_init__()
|
|
961
|
+
for name in (
|
|
962
|
+
"posterior_mean",
|
|
963
|
+
"uncertainty",
|
|
964
|
+
"positive_probability",
|
|
965
|
+
"invalid_probability",
|
|
966
|
+
"redundancy_fraction",
|
|
967
|
+
"late_bloom_slope",
|
|
968
|
+
"saturation_slope",
|
|
969
|
+
"effective_sample_size",
|
|
970
|
+
):
|
|
971
|
+
_require_nonnegative(getattr(self, name), name=name)
|
|
972
|
+
for name in (
|
|
973
|
+
"positive_probability",
|
|
974
|
+
"invalid_probability",
|
|
975
|
+
"redundancy_fraction",
|
|
976
|
+
):
|
|
977
|
+
if getattr(self, name) > 1.0:
|
|
978
|
+
raise ValueError(f"{name} must not exceed one")
|
|
979
|
+
if (
|
|
980
|
+
type(self.raw_observation_count) is not int
|
|
981
|
+
or self.raw_observation_count < 0
|
|
982
|
+
):
|
|
983
|
+
raise ValueError("raw_observation_count must be non-negative")
|
|
984
|
+
|
|
985
|
+
def to_record(self) -> dict[str, object]:
|
|
986
|
+
self.__post_init__()
|
|
987
|
+
return {
|
|
988
|
+
"cell": self.cell.to_record(),
|
|
989
|
+
"posterior_mean_hex": self.posterior_mean.hex(),
|
|
990
|
+
"uncertainty_hex": self.uncertainty.hex(),
|
|
991
|
+
"positive_probability_hex": (
|
|
992
|
+
self.positive_probability.hex()
|
|
993
|
+
),
|
|
994
|
+
"invalid_probability_hex": self.invalid_probability.hex(),
|
|
995
|
+
"redundancy_fraction_hex": self.redundancy_fraction.hex(),
|
|
996
|
+
"late_bloom_slope_hex": self.late_bloom_slope.hex(),
|
|
997
|
+
"saturation_slope_hex": self.saturation_slope.hex(),
|
|
998
|
+
"effective_sample_size_hex": (
|
|
999
|
+
self.effective_sample_size.hex()
|
|
1000
|
+
),
|
|
1001
|
+
"raw_observation_count": self.raw_observation_count,
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
@dataclass(frozen=True, slots=True)
|
|
1006
|
+
class ResidualHeadroomEstimate:
|
|
1007
|
+
context_sha256: str
|
|
1008
|
+
action_sha256: str
|
|
1009
|
+
generation_index: int
|
|
1010
|
+
expected_normalized_gain: float
|
|
1011
|
+
uncertainty: float
|
|
1012
|
+
positive_probability: float
|
|
1013
|
+
invalid_probability: float
|
|
1014
|
+
redundancy_fraction: float
|
|
1015
|
+
late_bloom_headroom: float
|
|
1016
|
+
saturation_risk: float
|
|
1017
|
+
acquisition_score: float
|
|
1018
|
+
cell_posteriors: tuple[ResidualHeadroomCellPosterior, ...]
|
|
1019
|
+
ledger_state_sha256: str
|
|
1020
|
+
config_definition_sha256: str
|
|
1021
|
+
estimate_sha256: str = field(init=False)
|
|
1022
|
+
|
|
1023
|
+
def __post_init__(self) -> None:
|
|
1024
|
+
for name in (
|
|
1025
|
+
"context_sha256",
|
|
1026
|
+
"action_sha256",
|
|
1027
|
+
"ledger_state_sha256",
|
|
1028
|
+
"config_definition_sha256",
|
|
1029
|
+
):
|
|
1030
|
+
require_sha256(getattr(self, name), name)
|
|
1031
|
+
if type(self.generation_index) is not int or self.generation_index < 0:
|
|
1032
|
+
raise ValueError("generation_index must be non-negative")
|
|
1033
|
+
for name in (
|
|
1034
|
+
"expected_normalized_gain",
|
|
1035
|
+
"uncertainty",
|
|
1036
|
+
"positive_probability",
|
|
1037
|
+
"invalid_probability",
|
|
1038
|
+
"redundancy_fraction",
|
|
1039
|
+
"late_bloom_headroom",
|
|
1040
|
+
"saturation_risk",
|
|
1041
|
+
"acquisition_score",
|
|
1042
|
+
):
|
|
1043
|
+
_require_nonnegative(getattr(self, name), name=name)
|
|
1044
|
+
for name in (
|
|
1045
|
+
"positive_probability",
|
|
1046
|
+
"invalid_probability",
|
|
1047
|
+
"redundancy_fraction",
|
|
1048
|
+
):
|
|
1049
|
+
if getattr(self, name) > 1.0:
|
|
1050
|
+
raise ValueError(f"{name} must not exceed one")
|
|
1051
|
+
if (
|
|
1052
|
+
type(self.cell_posteriors) is not tuple
|
|
1053
|
+
or not self.cell_posteriors
|
|
1054
|
+
or tuple(value.cell for value in self.cell_posteriors)
|
|
1055
|
+
!= tuple(sorted({value.cell for value in self.cell_posteriors}))
|
|
1056
|
+
):
|
|
1057
|
+
raise ValueError("cell posteriors must be non-empty and canonical")
|
|
1058
|
+
for value in self.cell_posteriors:
|
|
1059
|
+
if type(value) is not ResidualHeadroomCellPosterior:
|
|
1060
|
+
raise TypeError("cell posteriors must be exact")
|
|
1061
|
+
value.__post_init__()
|
|
1062
|
+
object.__setattr__(
|
|
1063
|
+
self,
|
|
1064
|
+
"estimate_sha256",
|
|
1065
|
+
_hash(_ESTIMATE_DOMAIN, self._unsigned_record()),
|
|
1066
|
+
)
|
|
1067
|
+
|
|
1068
|
+
def _unsigned_record(self) -> dict[str, object]:
|
|
1069
|
+
return {
|
|
1070
|
+
"schema_version": 1,
|
|
1071
|
+
"context_sha256": self.context_sha256,
|
|
1072
|
+
"action_sha256": self.action_sha256,
|
|
1073
|
+
"generation_index": self.generation_index,
|
|
1074
|
+
"expected_normalized_gain_hex": (
|
|
1075
|
+
self.expected_normalized_gain.hex()
|
|
1076
|
+
),
|
|
1077
|
+
"uncertainty_hex": self.uncertainty.hex(),
|
|
1078
|
+
"positive_probability_hex": (
|
|
1079
|
+
self.positive_probability.hex()
|
|
1080
|
+
),
|
|
1081
|
+
"invalid_probability_hex": self.invalid_probability.hex(),
|
|
1082
|
+
"redundancy_fraction_hex": self.redundancy_fraction.hex(),
|
|
1083
|
+
"late_bloom_headroom_hex": self.late_bloom_headroom.hex(),
|
|
1084
|
+
"saturation_risk_hex": self.saturation_risk.hex(),
|
|
1085
|
+
"acquisition_score_hex": self.acquisition_score.hex(),
|
|
1086
|
+
"cell_posteriors": [
|
|
1087
|
+
value.to_record() for value in self.cell_posteriors
|
|
1088
|
+
],
|
|
1089
|
+
"ledger_state_sha256": self.ledger_state_sha256,
|
|
1090
|
+
"config_definition_sha256": self.config_definition_sha256,
|
|
1091
|
+
"predicted_value_admitted_to_archive": False,
|
|
1092
|
+
}
|
|
1093
|
+
|
|
1094
|
+
def to_record(self) -> dict[str, object]:
|
|
1095
|
+
self.__post_init__()
|
|
1096
|
+
return {
|
|
1097
|
+
**self._unsigned_record(),
|
|
1098
|
+
"estimate_sha256": self.estimate_sha256,
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
|
|
1102
|
+
@dataclass(frozen=True, slots=True)
|
|
1103
|
+
class ConservedResidualHeadroomLedger:
|
|
1104
|
+
"""Fold conserved closures and query action-level residual headroom."""
|
|
1105
|
+
|
|
1106
|
+
config: ResidualHeadroomLedgerConfig = field(
|
|
1107
|
+
default_factory=ResidualHeadroomLedgerConfig
|
|
1108
|
+
)
|
|
1109
|
+
|
|
1110
|
+
def __post_init__(self) -> None:
|
|
1111
|
+
if type(self.config) is not ResidualHeadroomLedgerConfig:
|
|
1112
|
+
raise TypeError("config must be exact")
|
|
1113
|
+
self.config.__post_init__()
|
|
1114
|
+
|
|
1115
|
+
def empty_state(self) -> ResidualHeadroomLedgerState:
|
|
1116
|
+
self.__post_init__()
|
|
1117
|
+
return ResidualHeadroomLedgerState(
|
|
1118
|
+
config_definition_sha256=self.config.definition_sha256,
|
|
1119
|
+
)
|
|
1120
|
+
|
|
1121
|
+
def append(
|
|
1122
|
+
self,
|
|
1123
|
+
state: ResidualHeadroomLedgerState,
|
|
1124
|
+
closure: ResidualHeadroomStageClosure,
|
|
1125
|
+
) -> ResidualHeadroomLedgerState:
|
|
1126
|
+
self.__post_init__()
|
|
1127
|
+
if type(state) is not ResidualHeadroomLedgerState:
|
|
1128
|
+
raise TypeError("state must be exact")
|
|
1129
|
+
state.__post_init__()
|
|
1130
|
+
if (
|
|
1131
|
+
state.config_definition_sha256
|
|
1132
|
+
!= self.config.definition_sha256
|
|
1133
|
+
):
|
|
1134
|
+
raise ValueError("state belongs to another ledger configuration")
|
|
1135
|
+
if type(closure) is not ResidualHeadroomStageClosure:
|
|
1136
|
+
raise TypeError("closure must be exact")
|
|
1137
|
+
closure.__post_init__()
|
|
1138
|
+
return ResidualHeadroomLedgerState(
|
|
1139
|
+
config_definition_sha256=self.config.definition_sha256,
|
|
1140
|
+
closures=(*state.closures, closure),
|
|
1141
|
+
)
|
|
1142
|
+
|
|
1143
|
+
def _cell_posterior(
|
|
1144
|
+
self,
|
|
1145
|
+
*,
|
|
1146
|
+
state: ResidualHeadroomLedgerState,
|
|
1147
|
+
context_sha256: str,
|
|
1148
|
+
generation_index: int,
|
|
1149
|
+
cell: AdaptiveActionFactorCell,
|
|
1150
|
+
candidate_cell_count: int,
|
|
1151
|
+
) -> ResidualHeadroomCellPosterior:
|
|
1152
|
+
samples: list[tuple[ResidualHeadroomObservation, float, float]] = []
|
|
1153
|
+
for closure in state.closures:
|
|
1154
|
+
for observation in closure.observations:
|
|
1155
|
+
if cell not in observation.attribution_cells:
|
|
1156
|
+
continue
|
|
1157
|
+
if observation.context_sha256 == context_sha256:
|
|
1158
|
+
if observation.generation_index > generation_index:
|
|
1159
|
+
continue
|
|
1160
|
+
context_weight = 1.0
|
|
1161
|
+
decay = self.config.generation_decay ** (
|
|
1162
|
+
generation_index - observation.generation_index
|
|
1163
|
+
)
|
|
1164
|
+
else:
|
|
1165
|
+
context_weight = self.config.cross_context_weight
|
|
1166
|
+
decay = 1.0
|
|
1167
|
+
if context_weight == 0.0:
|
|
1168
|
+
continue
|
|
1169
|
+
inverse_propensity = (
|
|
1170
|
+
min(
|
|
1171
|
+
self.config.maximum_inverse_propensity,
|
|
1172
|
+
1.0 / observation.selection_propensity,
|
|
1173
|
+
)
|
|
1174
|
+
if observation.propensity_identified
|
|
1175
|
+
else 1.0
|
|
1176
|
+
)
|
|
1177
|
+
weight = context_weight * decay * inverse_propensity
|
|
1178
|
+
target = (
|
|
1179
|
+
observation.normalized_conditional_credit
|
|
1180
|
+
/ len(observation.attribution_cells)
|
|
1181
|
+
)
|
|
1182
|
+
samples.append((observation, weight, target))
|
|
1183
|
+
|
|
1184
|
+
prior_mean = (
|
|
1185
|
+
self.config.prior_normalized_gain / candidate_cell_count
|
|
1186
|
+
)
|
|
1187
|
+
weighted_count = math.fsum(value[1] for value in samples)
|
|
1188
|
+
denominator = self.config.prior_strength + weighted_count
|
|
1189
|
+
posterior_mean = (
|
|
1190
|
+
self.config.prior_strength * prior_mean
|
|
1191
|
+
+ math.fsum(weight * target for _, weight, target in samples)
|
|
1192
|
+
) / denominator
|
|
1193
|
+
variance = math.fsum(
|
|
1194
|
+
weight * (target - posterior_mean) ** 2
|
|
1195
|
+
for _, weight, target in samples
|
|
1196
|
+
) / denominator
|
|
1197
|
+
uncertainty = (
|
|
1198
|
+
math.sqrt(max(variance, 0.0) / denominator)
|
|
1199
|
+
+ max(prior_mean, 1.0e-12) / math.sqrt(denominator)
|
|
1200
|
+
)
|
|
1201
|
+
positive_probability = (
|
|
1202
|
+
self.config.positive_prior_alpha
|
|
1203
|
+
+ math.fsum(
|
|
1204
|
+
weight * float(observation.conditional_credit > 0.0)
|
|
1205
|
+
for observation, weight, _ in samples
|
|
1206
|
+
)
|
|
1207
|
+
) / (
|
|
1208
|
+
self.config.positive_prior_alpha
|
|
1209
|
+
+ self.config.positive_prior_beta
|
|
1210
|
+
+ weighted_count
|
|
1211
|
+
)
|
|
1212
|
+
invalid_probability = (
|
|
1213
|
+
self.config.invalid_prior_alpha
|
|
1214
|
+
+ math.fsum(
|
|
1215
|
+
weight * float(not observation.feasible)
|
|
1216
|
+
for observation, weight, _ in samples
|
|
1217
|
+
)
|
|
1218
|
+
) / (
|
|
1219
|
+
self.config.invalid_prior_alpha
|
|
1220
|
+
+ self.config.invalid_prior_beta
|
|
1221
|
+
+ weighted_count
|
|
1222
|
+
)
|
|
1223
|
+
redundancy_fraction = (
|
|
1224
|
+
0.0
|
|
1225
|
+
if weighted_count == 0.0
|
|
1226
|
+
else math.fsum(
|
|
1227
|
+
weight * observation.redundancy_fraction
|
|
1228
|
+
for observation, weight, _ in samples
|
|
1229
|
+
)
|
|
1230
|
+
/ weighted_count
|
|
1231
|
+
)
|
|
1232
|
+
slope = 0.0
|
|
1233
|
+
distinct_waves = {
|
|
1234
|
+
observation.wave_index for observation, _, _ in samples
|
|
1235
|
+
}
|
|
1236
|
+
if weighted_count > 0.0 and len(distinct_waves) >= 2:
|
|
1237
|
+
mean_wave = math.fsum(
|
|
1238
|
+
weight * observation.wave_index
|
|
1239
|
+
for observation, weight, _ in samples
|
|
1240
|
+
) / weighted_count
|
|
1241
|
+
mean_target = math.fsum(
|
|
1242
|
+
weight * target for _, weight, target in samples
|
|
1243
|
+
) / weighted_count
|
|
1244
|
+
wave_variance = math.fsum(
|
|
1245
|
+
weight * (observation.wave_index - mean_wave) ** 2
|
|
1246
|
+
for observation, weight, _ in samples
|
|
1247
|
+
)
|
|
1248
|
+
if wave_variance > 0.0:
|
|
1249
|
+
slope = math.fsum(
|
|
1250
|
+
weight
|
|
1251
|
+
* (observation.wave_index - mean_wave)
|
|
1252
|
+
* (target - mean_target)
|
|
1253
|
+
for observation, weight, target in samples
|
|
1254
|
+
) / wave_variance
|
|
1255
|
+
slope = max(
|
|
1256
|
+
-self.config.maximum_abs_slope,
|
|
1257
|
+
min(self.config.maximum_abs_slope, slope),
|
|
1258
|
+
)
|
|
1259
|
+
sum_weight_squared = math.fsum(
|
|
1260
|
+
weight * weight for _, weight, _ in samples
|
|
1261
|
+
)
|
|
1262
|
+
effective_sample_size = (
|
|
1263
|
+
0.0
|
|
1264
|
+
if sum_weight_squared == 0.0
|
|
1265
|
+
else weighted_count * weighted_count / sum_weight_squared
|
|
1266
|
+
)
|
|
1267
|
+
return ResidualHeadroomCellPosterior(
|
|
1268
|
+
cell=cell,
|
|
1269
|
+
posterior_mean=float(posterior_mean),
|
|
1270
|
+
uncertainty=float(uncertainty),
|
|
1271
|
+
positive_probability=float(positive_probability),
|
|
1272
|
+
invalid_probability=float(invalid_probability),
|
|
1273
|
+
redundancy_fraction=float(redundancy_fraction),
|
|
1274
|
+
late_bloom_slope=float(max(slope, 0.0)),
|
|
1275
|
+
saturation_slope=float(max(-slope, 0.0)),
|
|
1276
|
+
effective_sample_size=float(effective_sample_size),
|
|
1277
|
+
raw_observation_count=len(samples),
|
|
1278
|
+
)
|
|
1279
|
+
|
|
1280
|
+
def estimate(
|
|
1281
|
+
self,
|
|
1282
|
+
*,
|
|
1283
|
+
state: ResidualHeadroomLedgerState,
|
|
1284
|
+
context_sha256: str,
|
|
1285
|
+
generation_index: int,
|
|
1286
|
+
action: AdaptiveActionDescriptor,
|
|
1287
|
+
) -> ResidualHeadroomEstimate:
|
|
1288
|
+
self.__post_init__()
|
|
1289
|
+
if type(state) is not ResidualHeadroomLedgerState:
|
|
1290
|
+
raise TypeError("state must be exact")
|
|
1291
|
+
state.__post_init__()
|
|
1292
|
+
if (
|
|
1293
|
+
state.config_definition_sha256
|
|
1294
|
+
!= self.config.definition_sha256
|
|
1295
|
+
):
|
|
1296
|
+
raise ValueError("state belongs to another ledger configuration")
|
|
1297
|
+
require_sha256(context_sha256, "context_sha256")
|
|
1298
|
+
if type(generation_index) is not int or generation_index < 0:
|
|
1299
|
+
raise ValueError("generation_index must be non-negative")
|
|
1300
|
+
if type(action) is not AdaptiveActionDescriptor:
|
|
1301
|
+
raise TypeError("action must be exact")
|
|
1302
|
+
cells = _attribution_cells(action)
|
|
1303
|
+
posteriors = tuple(
|
|
1304
|
+
self._cell_posterior(
|
|
1305
|
+
state=state,
|
|
1306
|
+
context_sha256=context_sha256,
|
|
1307
|
+
generation_index=generation_index,
|
|
1308
|
+
cell=cell,
|
|
1309
|
+
candidate_cell_count=len(cells),
|
|
1310
|
+
)
|
|
1311
|
+
for cell in cells
|
|
1312
|
+
)
|
|
1313
|
+
expected = math.fsum(value.posterior_mean for value in posteriors)
|
|
1314
|
+
uncertainty = math.sqrt(
|
|
1315
|
+
math.fsum(value.uncertainty**2 for value in posteriors)
|
|
1316
|
+
)
|
|
1317
|
+
raw_count = sum(
|
|
1318
|
+
value.raw_observation_count for value in posteriors
|
|
1319
|
+
)
|
|
1320
|
+
uncertainty += self.config.exploration_floor / math.sqrt(
|
|
1321
|
+
1.0 + raw_count
|
|
1322
|
+
)
|
|
1323
|
+
positive_probability = math.fsum(
|
|
1324
|
+
value.positive_probability for value in posteriors
|
|
1325
|
+
) / len(posteriors)
|
|
1326
|
+
invalid_probability = math.fsum(
|
|
1327
|
+
value.invalid_probability for value in posteriors
|
|
1328
|
+
) / len(posteriors)
|
|
1329
|
+
redundancy = math.fsum(
|
|
1330
|
+
value.redundancy_fraction for value in posteriors
|
|
1331
|
+
) / len(posteriors)
|
|
1332
|
+
late_bloom = math.fsum(
|
|
1333
|
+
value.late_bloom_slope for value in posteriors
|
|
1334
|
+
)
|
|
1335
|
+
saturation = math.fsum(
|
|
1336
|
+
value.saturation_slope for value in posteriors
|
|
1337
|
+
)
|
|
1338
|
+
acquisition = max(
|
|
1339
|
+
0.0,
|
|
1340
|
+
expected
|
|
1341
|
+
+ self.config.uncertainty_strength * uncertainty
|
|
1342
|
+
+ self.config.late_bloom_strength * late_bloom
|
|
1343
|
+
- self.config.saturation_strength * saturation
|
|
1344
|
+
- self.config.redundancy_strength * expected * redundancy
|
|
1345
|
+
- self.config.invalidity_strength
|
|
1346
|
+
* max(self.config.prior_normalized_gain, expected)
|
|
1347
|
+
* invalid_probability,
|
|
1348
|
+
)
|
|
1349
|
+
return ResidualHeadroomEstimate(
|
|
1350
|
+
context_sha256=context_sha256,
|
|
1351
|
+
action_sha256=action.action_sha256,
|
|
1352
|
+
generation_index=generation_index,
|
|
1353
|
+
expected_normalized_gain=float(expected),
|
|
1354
|
+
uncertainty=float(uncertainty),
|
|
1355
|
+
positive_probability=float(positive_probability),
|
|
1356
|
+
invalid_probability=float(invalid_probability),
|
|
1357
|
+
redundancy_fraction=float(redundancy),
|
|
1358
|
+
late_bloom_headroom=float(late_bloom),
|
|
1359
|
+
saturation_risk=float(saturation),
|
|
1360
|
+
acquisition_score=float(acquisition),
|
|
1361
|
+
cell_posteriors=posteriors,
|
|
1362
|
+
ledger_state_sha256=state.state_sha256,
|
|
1363
|
+
config_definition_sha256=self.config.definition_sha256,
|
|
1364
|
+
)
|
|
1365
|
+
|
|
1366
|
+
|
|
1367
|
+
@dataclass(frozen=True, slots=True)
|
|
1368
|
+
class ResidualHeadroomAdaptiveMarketProjector:
|
|
1369
|
+
"""Blend prior-only headroom ranks into any portable adaptive market."""
|
|
1370
|
+
|
|
1371
|
+
delegate: AdaptiveActionMarketProjectorPort = field(
|
|
1372
|
+
repr=False,
|
|
1373
|
+
compare=False,
|
|
1374
|
+
)
|
|
1375
|
+
ledger: ConservedResidualHeadroomLedger = field(
|
|
1376
|
+
repr=False,
|
|
1377
|
+
compare=False,
|
|
1378
|
+
)
|
|
1379
|
+
ledger_state: ResidualHeadroomLedgerState
|
|
1380
|
+
context_sha256: str
|
|
1381
|
+
base_prior_weight: float = 1.0
|
|
1382
|
+
headroom_weight: float = 1.0
|
|
1383
|
+
projector_id: str = RESIDUAL_HEADROOM_ADAPTIVE_MARKET_PROJECTOR_ID
|
|
1384
|
+
projector_version: int = (
|
|
1385
|
+
RESIDUAL_HEADROOM_ADAPTIVE_MARKET_PROJECTOR_VERSION
|
|
1386
|
+
)
|
|
1387
|
+
definition_sha256: str = field(init=False)
|
|
1388
|
+
state_sha256: str = field(init=False)
|
|
1389
|
+
|
|
1390
|
+
def __post_init__(self) -> None:
|
|
1391
|
+
if not isinstance(self.delegate, AdaptiveActionMarketProjectorPort):
|
|
1392
|
+
raise TypeError("delegate must implement the adaptive market port")
|
|
1393
|
+
self.delegate.__post_init__()
|
|
1394
|
+
if type(self.ledger) is not ConservedResidualHeadroomLedger:
|
|
1395
|
+
raise TypeError("ledger must be exact")
|
|
1396
|
+
self.ledger.__post_init__()
|
|
1397
|
+
if type(self.ledger_state) is not ResidualHeadroomLedgerState:
|
|
1398
|
+
raise TypeError("ledger_state must be exact")
|
|
1399
|
+
self.ledger_state.__post_init__()
|
|
1400
|
+
if (
|
|
1401
|
+
self.ledger_state.config_definition_sha256
|
|
1402
|
+
!= self.ledger.config.definition_sha256
|
|
1403
|
+
):
|
|
1404
|
+
raise ValueError("ledger state belongs to another configuration")
|
|
1405
|
+
require_sha256(self.context_sha256, "context_sha256")
|
|
1406
|
+
for value, name in (
|
|
1407
|
+
(self.base_prior_weight, "base_prior_weight"),
|
|
1408
|
+
(self.headroom_weight, "headroom_weight"),
|
|
1409
|
+
):
|
|
1410
|
+
if (
|
|
1411
|
+
type(value) is not float
|
|
1412
|
+
or not math.isfinite(value)
|
|
1413
|
+
or value < 0.0
|
|
1414
|
+
):
|
|
1415
|
+
raise ValueError(f"{name} must be finite and non-negative")
|
|
1416
|
+
if self.base_prior_weight + self.headroom_weight <= 0.0:
|
|
1417
|
+
raise ValueError("at least one projector weight must be positive")
|
|
1418
|
+
if (
|
|
1419
|
+
self.projector_id
|
|
1420
|
+
!= RESIDUAL_HEADROOM_ADAPTIVE_MARKET_PROJECTOR_ID
|
|
1421
|
+
or self.projector_version
|
|
1422
|
+
!= RESIDUAL_HEADROOM_ADAPTIVE_MARKET_PROJECTOR_VERSION
|
|
1423
|
+
):
|
|
1424
|
+
raise ValueError("projector identity is immutable")
|
|
1425
|
+
object.__setattr__(
|
|
1426
|
+
self,
|
|
1427
|
+
"definition_sha256",
|
|
1428
|
+
_hash(
|
|
1429
|
+
_MARKET_PROJECTOR_DOMAIN,
|
|
1430
|
+
{
|
|
1431
|
+
"schema_version": 1,
|
|
1432
|
+
"projector_id": self.projector_id,
|
|
1433
|
+
"projector_version": self.projector_version,
|
|
1434
|
+
"delegate_definition_sha256": (
|
|
1435
|
+
self.delegate.definition_sha256
|
|
1436
|
+
),
|
|
1437
|
+
"ledger_config_definition_sha256": (
|
|
1438
|
+
self.ledger.config.definition_sha256
|
|
1439
|
+
),
|
|
1440
|
+
"base_prior_weight_hex": self.base_prior_weight.hex(),
|
|
1441
|
+
"headroom_weight_hex": self.headroom_weight.hex(),
|
|
1442
|
+
"normalization": (
|
|
1443
|
+
"within-sealed-market-tie-preserving-rank-percentile"
|
|
1444
|
+
),
|
|
1445
|
+
"candidate_outcomes_observed": False,
|
|
1446
|
+
"predicted_values_admitted_to_archive": False,
|
|
1447
|
+
"workload_objective_model_provider_prompt_config_branches": (
|
|
1448
|
+
False
|
|
1449
|
+
),
|
|
1450
|
+
},
|
|
1451
|
+
),
|
|
1452
|
+
)
|
|
1453
|
+
object.__setattr__(
|
|
1454
|
+
self,
|
|
1455
|
+
"state_sha256",
|
|
1456
|
+
_hash(
|
|
1457
|
+
_MARKET_STATE_DOMAIN,
|
|
1458
|
+
{
|
|
1459
|
+
"schema_version": 1,
|
|
1460
|
+
"projector_definition_sha256": self.definition_sha256,
|
|
1461
|
+
"delegate_state_sha256": self.delegate.state_sha256,
|
|
1462
|
+
"ledger_state_sha256": self.ledger_state.state_sha256,
|
|
1463
|
+
"context_sha256": self.context_sha256,
|
|
1464
|
+
},
|
|
1465
|
+
),
|
|
1466
|
+
)
|
|
1467
|
+
|
|
1468
|
+
@staticmethod
|
|
1469
|
+
def _rank_percentiles(
|
|
1470
|
+
values: dict[str, float],
|
|
1471
|
+
) -> dict[str, float]:
|
|
1472
|
+
unique = sorted(set(values.values()))
|
|
1473
|
+
if len(unique) == 1:
|
|
1474
|
+
return {key: 0.5 for key in values}
|
|
1475
|
+
percentile = {
|
|
1476
|
+
value: index / (len(unique) - 1)
|
|
1477
|
+
for index, value in enumerate(unique)
|
|
1478
|
+
}
|
|
1479
|
+
return {key: percentile[value] for key, value in values.items()}
|
|
1480
|
+
|
|
1481
|
+
async def project(
|
|
1482
|
+
self,
|
|
1483
|
+
request: ResidualPortfolioDecisionRequest,
|
|
1484
|
+
proposals: tuple[MaterializedActionProposalBatch, ...],
|
|
1485
|
+
actions: tuple[MaterializedActionDescriptor, ...],
|
|
1486
|
+
scores: tuple[BrokerActionScore, ...],
|
|
1487
|
+
required_action_sha256s: tuple[str, ...],
|
|
1488
|
+
) -> tuple[AdaptiveActionDescriptor, ...]:
|
|
1489
|
+
self.__post_init__()
|
|
1490
|
+
projected = await self.delegate.project(
|
|
1491
|
+
request,
|
|
1492
|
+
proposals,
|
|
1493
|
+
actions,
|
|
1494
|
+
scores,
|
|
1495
|
+
required_action_sha256s,
|
|
1496
|
+
)
|
|
1497
|
+
# A cold ledger contains no evidence with which to alter the existing
|
|
1498
|
+
# prior. Returning the delegate values exactly avoids manufacturing a
|
|
1499
|
+
# ranking from attribution-cardinality or hash tie breaks.
|
|
1500
|
+
if not self.ledger_state.closures:
|
|
1501
|
+
return projected
|
|
1502
|
+
estimates = {
|
|
1503
|
+
action.action_sha256: self.ledger.estimate(
|
|
1504
|
+
state=self.ledger_state,
|
|
1505
|
+
context_sha256=self.context_sha256,
|
|
1506
|
+
generation_index=request.decision_index,
|
|
1507
|
+
action=action,
|
|
1508
|
+
).acquisition_score
|
|
1509
|
+
for action in projected
|
|
1510
|
+
}
|
|
1511
|
+
headroom_percentiles = self._rank_percentiles(estimates)
|
|
1512
|
+
denominator = self.base_prior_weight + self.headroom_weight
|
|
1513
|
+
return tuple(
|
|
1514
|
+
replace(
|
|
1515
|
+
action,
|
|
1516
|
+
prior_score=float(
|
|
1517
|
+
(
|
|
1518
|
+
self.base_prior_weight * action.prior_score
|
|
1519
|
+
+ self.headroom_weight
|
|
1520
|
+
* headroom_percentiles[action.action_sha256]
|
|
1521
|
+
)
|
|
1522
|
+
/ denominator
|
|
1523
|
+
),
|
|
1524
|
+
)
|
|
1525
|
+
for action in projected
|
|
1526
|
+
)
|
|
1527
|
+
|
|
1528
|
+
|
|
1529
|
+
__all__ = [
|
|
1530
|
+
"ConservedResidualHeadroomLedger",
|
|
1531
|
+
"ConservedResidualHeadroomProjector",
|
|
1532
|
+
"ResidualHeadroomAdaptiveMarketProjector",
|
|
1533
|
+
"ResidualHeadroomCellPosterior",
|
|
1534
|
+
"ResidualHeadroomEstimate",
|
|
1535
|
+
"ResidualHeadroomLedgerConfig",
|
|
1536
|
+
"ResidualHeadroomLedgerState",
|
|
1537
|
+
"ResidualHeadroomObservation",
|
|
1538
|
+
"ResidualHeadroomStageClosure",
|
|
1539
|
+
"RESIDUAL_HEADROOM_ADAPTIVE_MARKET_PROJECTOR_ID",
|
|
1540
|
+
"RESIDUAL_HEADROOM_ADAPTIVE_MARKET_PROJECTOR_VERSION",
|
|
1541
|
+
"RESIDUAL_HEADROOM_LEDGER_DEFINITION_SHA256",
|
|
1542
|
+
"RESIDUAL_HEADROOM_LEDGER_ID",
|
|
1543
|
+
"RESIDUAL_HEADROOM_LEDGER_VERSION",
|
|
1544
|
+
]
|