Tighten hot-path backend consistency

- route SessionContext anchor CGA through algebra.backend
- move aspect-weight carry into FieldEnergyOperator.compute
- remove duplicated propagate_step threshold patch and per-step imports
- add carry_aspect_weight tests for parity, fallback, and propagation preservation
- preserve normalization, propagation, vault, Rust dispatch, and energy cadence semantics
This commit is contained in:
Shay 2026-05-15 08:14:38 -07:00 committed by GitHub
parent f973e61bc2
commit 15ed2cee89
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 48 additions and 33 deletions

View file

@ -87,12 +87,13 @@ class FieldEnergyOperator:
coherence_residual: float = 0.0,
morphology_features: Mapping[str, object] | None = None,
anchor_adjacent: bool = False,
carry_aspect_weight: float = 0.0,
) -> EnergyProfile:
convergence = min(log1p(max(0, convergence_density)) / log1p(8), 1.0)
age = max(0, int(current_cycle) - int(last_activation_cycle))
recency = min(max(0, activation_count), 8) / 8.0 * exp(-age / 12.0)
residual = min(max(0.0, float(coherence_residual)), 1.0)
aspect = aspect_weight(morphology_features)
aspect = carry_aspect_weight if carry_aspect_weight > 0.0 else aspect_weight(morphology_features)
raw = (0.35 * convergence) + (0.25 * recency) + (0.20 * residual) + (0.20 * aspect)
if anchor_adjacent and raw >= 0.72:
energy_class = EnergyClass.E4

View file

@ -55,38 +55,10 @@ def propagate_step(state: FieldState, V) -> FieldState:
current_cycle=new_step,
last_activation_cycle=ep.last_activation_cycle,
coherence_residual=0.0,
morphology_features=None, # aspect weight baked at injection; not re-read here
morphology_features=None,
anchor_adjacent=ep.anchor_adjacent,
carry_aspect_weight=ep.aspect_weight,
)
# Carry the baked aspect_weight forward: the operator won't re-derive
# it from morphology_features=None, so we patch the raw score to
# preserve the aspect contribution that was set at the gate.
if ep.aspect_weight > 0.0:
from dataclasses import replace as _replace
# Recompute with the original aspect weight patched back in:
# raw already accounts for convergence/recency/residual from above.
# We rebuild raw adding the aspect component the operator lost.
patched_raw = new_energy.raw + 0.20 * ep.aspect_weight
patched_raw = min(patched_raw, 1.0)
from core.physics.energy import EnergyClass as _EC
if ep.anchor_adjacent and patched_raw >= 0.72:
patched_class = _EC.E4
elif patched_raw >= 0.82:
patched_class = _EC.E4
elif patched_raw >= 0.62:
patched_class = _EC.E3
elif patched_raw >= 0.38:
patched_class = _EC.E2
elif patched_raw >= 0.16:
patched_class = _EC.E1
else:
patched_class = _EC.E0
new_energy = _replace(
new_energy,
raw=patched_raw,
energy_class=patched_class,
aspect_weight=ep.aspect_weight,
)
else:
new_energy = None

View file

@ -14,8 +14,8 @@ from __future__ import annotations
import numpy as np
from algebra.backend import versor_apply
from algebra.cga import cga_inner, outer_product
from algebra.backend import cga_inner, versor_apply
from algebra.cga import outer_product
from field.state import FieldState
from generate.dialogue import DialogueTurn
from generate.proposition import Proposition

View file

@ -344,6 +344,48 @@ class TestPropagateStepEnergyRecomputation:
assert state.energy.energy_class is not EnergyClass.E4
# ---------------------------------------------------------------------------
# carry_aspect_weight consolidation
# ---------------------------------------------------------------------------
class TestCarryAspectWeight:
def test_carry_aspect_matches_morphology_derived(self):
"""carry_aspect_weight produces identical raw/class as morphology-derived aspect."""
base_kw = dict(
convergence_density=4,
activation_count=4,
current_cycle=1,
last_activation_cycle=0,
coherence_residual=0.0,
anchor_adjacent=False,
)
from_morph = _op.compute(**base_kw, morphology_features={"mood": "imperative"})
from_carry = _op.compute(**base_kw, carry_aspect_weight=0.90)
assert from_carry.raw == pytest.approx(from_morph.raw)
assert from_carry.energy_class is from_morph.energy_class
assert from_carry.aspect_weight == pytest.approx(from_morph.aspect_weight)
def test_carry_zero_falls_back_to_morphology(self):
ep = _op.compute(
morphology_features={"aspect": "yiqtol"},
carry_aspect_weight=0.0,
)
assert ep.aspect_weight == pytest.approx(0.65)
def test_propagate_step_preserves_baked_aspect_weight(self):
"""Aspect weight injected at the gate survives propagation via carry."""
ep = _op.compute(
convergence_density=4,
activation_count=2,
current_cycle=0,
morphology_features={"mood": "imperative"},
)
state = FieldState(F=_clean_versor(), node=0, step=0, energy=ep)
new_state = propagate_step(state, _identity_rotor())
assert new_state.energy.aspect_weight == pytest.approx(0.90)
assert new_state.energy.raw > 0.0
# ---------------------------------------------------------------------------
# EnergyProfile field storage round-trip on FieldState
# ---------------------------------------------------------------------------