- 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
72 lines
2.7 KiB
Python
72 lines
2.7 KiB
Python
"""
|
|
Field propagation — the generation heartbeat.
|
|
|
|
Each step: F <- versor_apply(V, F)
|
|
|
|
V is the rotor for the current node's outgoing edge in the vocab manifold.
|
|
No correction. No normalization. No conditional branching. The loop is tight.
|
|
|
|
Energy recomputation: after each versor step the EnergyProfile carried in
|
|
FieldState is refreshed. The refresh uses only the structural inputs that
|
|
are available without external context (activation_count tracks steps taken;
|
|
cycle is the new step index). Convergence density and morphology features
|
|
are not available inside propagate_step — they are set at the injection gate
|
|
and carried forward unchanged. Coherence residual is zero inside a clean
|
|
propagation path (no corrective pass is applied here). This is intentional:
|
|
propagation is not correction.
|
|
|
|
Hot path routes through algebra.backend, which dispatches to the Rust
|
|
extension (core_rs) when available and falls back to pure Python silently.
|
|
"""
|
|
|
|
from algebra.backend import versor_apply
|
|
from core.physics.energy import FieldEnergyOperator
|
|
from field.state import FieldState
|
|
|
|
_energy_op = FieldEnergyOperator()
|
|
|
|
|
|
def propagate_step(state: FieldState, V) -> FieldState:
|
|
"""
|
|
Apply one versor transition and refresh the energy profile.
|
|
|
|
V is the edge rotor from the current node.
|
|
Returns a new FieldState one step forward on the manifold.
|
|
|
|
Energy recomputation policy:
|
|
- activation_count increments by 1 per step (field is actively propagating).
|
|
- current_cycle = new step index (monotonic proxy for time).
|
|
- last_activation_cycle stays at the value set at injection (the gate
|
|
records when this region was first injected; propagation does not reset
|
|
that anchor).
|
|
- coherence_residual = 0.0 (propagation is not a corrective pass).
|
|
- convergence_density and morphology_features are inherited from the
|
|
existing EnergyProfile when one is present; otherwise defaults apply.
|
|
- anchor_adjacent is inherited unchanged.
|
|
"""
|
|
new_F = versor_apply(V, state.F)
|
|
new_step = state.step + 1
|
|
|
|
if state.energy is not None:
|
|
ep = state.energy
|
|
new_energy = _energy_op.compute(
|
|
convergence_density=ep.convergence_density,
|
|
activation_count=ep.activation_count + 1,
|
|
current_cycle=new_step,
|
|
last_activation_cycle=ep.last_activation_cycle,
|
|
coherence_residual=0.0,
|
|
morphology_features=None,
|
|
anchor_adjacent=ep.anchor_adjacent,
|
|
carry_aspect_weight=ep.aspect_weight,
|
|
)
|
|
else:
|
|
new_energy = None
|
|
|
|
return FieldState(
|
|
F=new_F,
|
|
node=state.node,
|
|
step=new_step,
|
|
holonomy=state.holonomy,
|
|
energy=new_energy,
|
|
valence=state.valence,
|
|
)
|