Merge pull request 'feat(third-door): ADR-0241 wave-field substrate + operator subsumption' (#32) from feat/third-door-wave-field-substrate into main
This commit is contained in:
commit
e2c375e407
10 changed files with 1006 additions and 34 deletions
|
|
@ -7,6 +7,9 @@ Three physics sublayers:
|
|||
|
||||
Third-Door Horizon (ADR-0238–0240):
|
||||
GoldTether, dynamic manifold, surprise dual, biography holonomy.
|
||||
|
||||
Wave-field substrate (ADR-0241):
|
||||
WaveManifold — continuous ψ, spectral leakage, polar analogy, chiral charge.
|
||||
"""
|
||||
|
||||
from core.physics.salience import SalienceOperator, SalienceMap, FieldRegion
|
||||
|
|
@ -64,6 +67,7 @@ from core.physics.temporal_gate import (
|
|||
TemporalVerdict,
|
||||
)
|
||||
from core.physics.self_authorship import AuthorshipProposal, SelfAuthorshipMiner
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
|
||||
__all__ = [
|
||||
"SalienceOperator", "SalienceMap", "FieldRegion",
|
||||
|
|
@ -93,4 +97,5 @@ __all__ = [
|
|||
"TemporalAdmissibilityGate", "TemporalContext",
|
||||
"TemporalDecision", "TemporalVerdict",
|
||||
"AuthorshipProposal", "SelfAuthorshipMiner",
|
||||
"WaveManifold",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import numpy as np
|
|||
from algebra.cl41 import N_COMPONENTS
|
||||
from algebra.holonomy import holonomy_encode, holonomy_similarity
|
||||
from algebra.versor import unitize_versor, versor_condition
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
|
||||
_CLOSURE_TOL = 1e-6
|
||||
_TELEMETRY_SCHEMA = "biography_holonomy_v1"
|
||||
|
|
@ -69,16 +70,39 @@ def integrate_biography(
|
|||
"""Integrate ordered identity/session versors into a biography holonomy blade.
|
||||
|
||||
Order is load-bearing. Empty trajectory is refused (no confabulated self).
|
||||
|
||||
ADR-0241 Slice 2–3: each trajectory versor and the integrated blade must pass
|
||||
the wave unitary residual (standing-wave / unitary-propagator lock-in). Modes
|
||||
are registered for resonant recall of the lived trajectory (session-local
|
||||
registry on the manifold instance — not vault storage). The holonomy blade
|
||||
itself remains reconstruction-over-storage via :func:`holonomy_encode`.
|
||||
"""
|
||||
if not trajectory:
|
||||
raise ValueError("biography trajectory must be non-empty")
|
||||
closed = [_as_versor(v, f"trajectory[{i}]") for i, v in enumerate(trajectory)]
|
||||
wave = WaveManifold()
|
||||
for i, v in enumerate(closed):
|
||||
r = wave.measure_unitary_residual(v)
|
||||
if r >= _CLOSURE_TOL:
|
||||
raise ValueError(
|
||||
f"trajectory[{i}] failed wave unitary residual: {r:.3e}"
|
||||
)
|
||||
wave.register_resonant_mode(v)
|
||||
blade = holonomy_encode(closed, alpha=alpha)
|
||||
cond = versor_condition(blade)
|
||||
if cond >= _CLOSURE_TOL:
|
||||
raise ValueError(f"biography blade not closed: {cond:.3e}")
|
||||
blade_arr = np.asarray(blade, dtype=np.float64)
|
||||
r_blade = wave.measure_unitary_residual(blade_arr)
|
||||
if r_blade >= _CLOSURE_TOL:
|
||||
raise ValueError(f"biography blade wave unitary residual: {r_blade:.3e}")
|
||||
# Resonant lock-in: last trajectory step must be recallable from the mode set
|
||||
# (order-sensitive registry; reconstruction-over-storage of the trajectory).
|
||||
_mode, _E, idx = wave.resonant_recall(closed[-1])
|
||||
if idx < 0 or idx >= len(closed):
|
||||
raise ValueError("biography resonant recall index out of range")
|
||||
return BiographyHolonomyBlade(
|
||||
blade=np.asarray(blade, dtype=np.float64),
|
||||
blade=blade_arr,
|
||||
n_steps=len(closed),
|
||||
trajectory_hash=_trajectory_hash(closed),
|
||||
closure=float(cond),
|
||||
|
|
|
|||
|
|
@ -723,9 +723,19 @@ def _procrustes_multivector_pairs(
|
|||
pair_residuals=pair_res,
|
||||
)
|
||||
|
||||
# Field conjugacy: sandwich residual, stacked multi-pair constraints.
|
||||
V, residual_norm = _field_conjugacy_versor(src_list, tgt_list)
|
||||
pair_res = tuple(procrustes_residual(s, t, V) for s, t in zip(src_list, tgt_list))
|
||||
# Field conjugacy / wave polar (ADR-0241 Slice 2–3): all non-null field paths
|
||||
# go through WaveManifold (single-pair polar; multi-pair thin conjugacy wrap).
|
||||
# Null-point clouds already returned above (Kabsch point-cloud path).
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
|
||||
wave = WaveManifold()
|
||||
if len(src_list) == 1:
|
||||
V = wave.wave_analogical_polar(src_list[0], tgt_list[0])
|
||||
else:
|
||||
V, _engine_r = wave.wave_field_conjugacy(src_list, tgt_list)
|
||||
pair_res = tuple(
|
||||
procrustes_residual(s, t, V) for s, t in zip(src_list, tgt_list)
|
||||
)
|
||||
residual_norm = float(np.sqrt(sum(r * r for r in pair_res) / len(pair_res)))
|
||||
return ConformalProcrustesResult(
|
||||
versor=V,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ import numpy as np
|
|||
from algebra.cl41 import N_COMPONENTS, geometric_product, reverse
|
||||
from algebra.rotor import rotor_power, word_transition_rotor
|
||||
from algebra.versor import versor_condition, versor_unit_residual
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
|
||||
_CLOSURE_TOL = 1e-6
|
||||
_NEAR_ZERO = 1e-12
|
||||
|
|
@ -98,11 +99,11 @@ def coherence_residual(F: np.ndarray) -> float:
|
|||
"""Public one-shot residual for tests and harnesses.
|
||||
|
||||
R = || F · reverse(F) − 1 ||_F (dual-checked against reverse(F)).
|
||||
|
||||
Canonical path (ADR-0241 Slice 2): :meth:`WaveManifold.measure_unitary_residual`
|
||||
— unitary wave amplitude drift, not a parallel residual implementation.
|
||||
"""
|
||||
F_arr = _as_mv(F)
|
||||
r = float(versor_unit_residual(F_arr))
|
||||
r_rev = float(versor_unit_residual(reverse(F_arr)))
|
||||
return max(r, r_rev)
|
||||
return WaveManifold().measure_unitary_residual(_as_mv(F))
|
||||
|
||||
|
||||
@dataclass
|
||||
|
|
@ -202,8 +203,18 @@ class GoldTetherMonitor:
|
|||
raw :func:`coherence_residual` stays the fail-closed *closure* gate.
|
||||
"""
|
||||
F_arr = _as_mv(F)
|
||||
drift = coherence_residual(F_arr)
|
||||
drift_term = drift / self.epsilon_drift if self.epsilon_drift > 0.0 else drift
|
||||
# Unitary amplitude drift (wave substrate) + optional chiral readout.
|
||||
# Chiral charge is structurally ~0 on real even field-states (#19 family);
|
||||
# included as a non-negative integrity term so a future non-vacuous spinor
|
||||
# path can move the residual without a second API.
|
||||
wave = WaveManifold()
|
||||
drift = wave.measure_unitary_residual(F_arr)
|
||||
chiral = abs(float(wave.chiral_charge(F_arr)))
|
||||
drift_term = (
|
||||
(drift + chiral) / self.epsilon_drift
|
||||
if self.epsilon_drift > 0.0
|
||||
else (drift + chiral)
|
||||
)
|
||||
scale = float(np.linalg.norm(F_arr))
|
||||
if self.gold_invariants and scale > _NEAR_ZERO:
|
||||
min_dist = min(
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ from algebra.cga import cga_inner
|
|||
from algebra.cl41 import N_COMPONENTS, grade_project
|
||||
from algebra.versor import versor_condition
|
||||
from core.physics.dynamic_manifold import conformal_procrustes
|
||||
from core.physics.wave_manifold import WaveManifold, WaveSpectralLeakageError
|
||||
|
||||
_ETA5 = np.diag([1.0, 1.0, 1.0, 1.0, -1.0]).astype(np.float64)
|
||||
_NEAR_ZERO = 1e-12
|
||||
|
|
@ -166,7 +167,9 @@ def surprise_residual(
|
|||
residual = x_arr - B @ coeffs
|
||||
return residual, float(np.linalg.norm(residual))
|
||||
|
||||
# --- 32-vector (Cl(4,1) multivector) branch: cga_inner projection --------
|
||||
# --- 32-vector (Cl(4,1) multivector) branch: wave spectral leakage -------
|
||||
# Canonical path (ADR-0241 Slice 2): metric proj via WaveManifold; no parallel
|
||||
# Euclidean Gram-Schmidt. Typed degenerate-span refusal preserved.
|
||||
if x_arr.shape[0] == N_COMPONENTS:
|
||||
if B.shape[0] != N_COMPONENTS and B.shape[1] == N_COMPONENTS:
|
||||
B = B.T
|
||||
|
|
@ -176,13 +179,10 @@ def surprise_residual(
|
|||
if k == 0:
|
||||
return x_arr.copy(), float(np.linalg.norm(x_arr))
|
||||
cols = [B[:, i] for i in range(k)]
|
||||
gram = np.array(
|
||||
[[cga_inner(cols[i], cols[j]) for j in range(k)] for i in range(k)],
|
||||
dtype=np.float64,
|
||||
)
|
||||
rhs = np.array([cga_inner(cols[i], x_arr) for i in range(k)], dtype=np.float64)
|
||||
coeffs = _metric_projection_coeffs(B, gram, rhs)
|
||||
residual = x_arr - B @ coeffs
|
||||
try:
|
||||
residual, energy = WaveManifold().compute_spectral_leakage(x_arr, cols)
|
||||
except WaveSpectralLeakageError as exc:
|
||||
raise SurpriseResidualError(exc.reason, **exc.disclosure) from exc
|
||||
|
||||
# Grade-support containment: residual is a linear combination of x and the
|
||||
# basis columns, so its grades can only be a subset of theirs. ``allowed``
|
||||
|
|
@ -199,7 +199,7 @@ def surprise_residual(
|
|||
"grade_leak", leaked=sorted(leaked), allowed=sorted(allowed)
|
||||
)
|
||||
|
||||
return residual, float(np.linalg.norm(residual))
|
||||
return residual, float(energy)
|
||||
|
||||
raise ValueError("surprise_residual expects 5-vector or 32-vector x")
|
||||
|
||||
|
|
|
|||
359
core/physics/wave_manifold.py
Normal file
359
core/physics/wave_manifold.py
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
"""
|
||||
core/physics/wave_manifold.py
|
||||
|
||||
Wave-field substrate for Cl(4,1) (ADR-0241).
|
||||
|
||||
Continuous multivector wave fields ψ ∈ ℝ³² under:
|
||||
* sandwich transport ψ' = R ψ ~R (multivector field path; matches versor_apply)
|
||||
* left spinor transport ψ' = R ψ (odd-capable / chiral path)
|
||||
* spectral leakage (metric proj onto resonant modes)
|
||||
* wave polar analogy (sandwich conjugator)
|
||||
* unitary amplitude residual + chiral spinor charge readout
|
||||
|
||||
Algebra-native only (algebra/*). No scipy-as-truth. No teaching/vault imports.
|
||||
Off-serving until explicit gates; dual-checked unitary residual.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Sequence, Tuple
|
||||
|
||||
import numpy as np
|
||||
|
||||
from algebra.cga import cga_inner
|
||||
from algebra.cl41 import N_COMPONENTS, geometric_product, reverse, scalar_part
|
||||
from algebra.versor import versor_apply, versor_condition, versor_unit_residual
|
||||
|
||||
_CLOSURE_TOL = 1e-6
|
||||
_NEAR_ZERO = 1e-12
|
||||
_NONSIMPLE_TOL = 1e-6
|
||||
|
||||
|
||||
class WaveSpectralLeakageError(ValueError):
|
||||
"""Fail-closed spectral leakage (metric-degenerate resonant span).
|
||||
|
||||
Mapped to :class:`core.physics.surprise.SurpriseResidualError` at the
|
||||
surprise boundary so discovery / dual contracts keep a stable error type.
|
||||
"""
|
||||
|
||||
def __init__(self, reason: str, **disclosure: Any) -> None:
|
||||
self.reason = reason
|
||||
self.disclosure = dict(disclosure)
|
||||
super().__init__(f"spectral_leakage refused [{reason}]: {self.disclosure}")
|
||||
|
||||
# Unit pseudoscalar I₅ = e1 e2 e3 e4 e5 (central; I² = −1 in Cl(4,1)).
|
||||
_I5 = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
_I5[31] = 1.0
|
||||
_I5.setflags(write=False)
|
||||
|
||||
|
||||
def _as_mv(x: np.ndarray, name: str = "ψ") -> np.ndarray:
|
||||
arr = np.asarray(x, dtype=np.float64)
|
||||
if arr.shape != (N_COMPONENTS,):
|
||||
raise ValueError(f"{name} must have shape ({N_COMPONENTS},); got {arr.shape}")
|
||||
return arr
|
||||
|
||||
|
||||
def _identity() -> np.ndarray:
|
||||
out = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
out[0] = 1.0
|
||||
return out
|
||||
|
||||
|
||||
def _strict_close_rotor(V: np.ndarray, *, name: str) -> np.ndarray:
|
||||
"""Rescale a true versor to unit weight; never seed-fabricate."""
|
||||
arr = _as_mv(V, name)
|
||||
product = geometric_product(arr, reverse(arr)).astype(np.float64)
|
||||
scalar_sq = float(product[0])
|
||||
residue = product.copy()
|
||||
residue[0] = 0.0
|
||||
residue_norm = float(np.linalg.norm(residue))
|
||||
if residue_norm >= 1e-2 or scalar_sq <= 0.0:
|
||||
raise ValueError(
|
||||
f"{name}: input not a versor "
|
||||
f"(residue_norm={residue_norm:.3e}, scalar_sq={scalar_sq:.3e})"
|
||||
)
|
||||
closed = (arr * (1.0 / np.sqrt(scalar_sq))).astype(np.float64)
|
||||
cond = versor_condition(closed)
|
||||
if cond >= _CLOSURE_TOL:
|
||||
raise ValueError(f"{name}: versor_condition={cond:.3e} after close")
|
||||
return closed
|
||||
|
||||
|
||||
def _require_closed_rotor(R: np.ndarray, *, name: str = "R") -> np.ndarray:
|
||||
arr = _as_mv(R, name)
|
||||
cond = versor_condition(arr)
|
||||
if cond >= _CLOSURE_TOL:
|
||||
# Attempt strict close only if already a versor (scalar reverse product).
|
||||
return _strict_close_rotor(arr, name=name)
|
||||
return arr.astype(np.float64, copy=True)
|
||||
|
||||
|
||||
def _exp_bivector_generator(B: np.ndarray, dt: float) -> np.ndarray:
|
||||
"""R = exp(B·dt) for a pure (or nearly pure) bivector generator.
|
||||
|
||||
Closed form when B² is scalar (simple plane); series fallback otherwise.
|
||||
Result is construction-closed (versor_condition < 1e-6).
|
||||
"""
|
||||
G = _as_mv(B, "B") * float(dt)
|
||||
G = G.copy()
|
||||
G[0] = 0.0 # generator is grade ≥ 1; scalar part does not enter exp path
|
||||
if float(np.linalg.norm(G)) < _NEAR_ZERO:
|
||||
return _identity()
|
||||
|
||||
Gsq = geometric_product(G, G).astype(np.float64)
|
||||
s = float(Gsq[0])
|
||||
higher = Gsq.copy()
|
||||
higher[0] = 0.0
|
||||
if float(np.linalg.norm(higher)) < _NONSIMPLE_TOL:
|
||||
out = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
if abs(s) < _NEAR_ZERO:
|
||||
out[0] = 1.0
|
||||
out = out + G
|
||||
elif s < 0.0:
|
||||
mag = float(np.sqrt(-s))
|
||||
out[0] = float(np.cos(mag))
|
||||
out = out + (float(np.sin(mag)) / mag) * G
|
||||
else:
|
||||
mag = float(np.sqrt(s))
|
||||
out[0] = float(np.cosh(mag))
|
||||
out = out + (float(np.sinh(mag)) / mag) * G
|
||||
return _strict_close_rotor(out, name="exp_bivector")
|
||||
|
||||
# Non-simple: truncated geometric series (construction boundary only).
|
||||
term = _identity()
|
||||
out = term.copy()
|
||||
for k in range(1, 48):
|
||||
term = geometric_product(term, G) / float(k)
|
||||
out = out + term
|
||||
if float(np.linalg.norm(term)) < 1e-18:
|
||||
break
|
||||
return _strict_close_rotor(out, name="exp_bivector_series")
|
||||
|
||||
|
||||
def _metric_project(
|
||||
x: np.ndarray,
|
||||
modes: Sequence[np.ndarray],
|
||||
) -> Tuple[np.ndarray, np.ndarray]:
|
||||
"""Metric-orthogonal projection onto span(modes) under cga_inner.
|
||||
|
||||
Solves G c = r with G_ij = ⟨b_i, b_j⟩, r_i = ⟨b_i, x⟩. Returns
|
||||
(projection, residual) with residual = x − projection.
|
||||
"""
|
||||
x_arr = _as_mv(x, "ψ_incoming")
|
||||
cols = [_as_mv(m, f"mode[{i}]") for i, m in enumerate(modes)]
|
||||
k = len(cols)
|
||||
if k == 0:
|
||||
return np.zeros(N_COMPONENTS, dtype=np.float64), x_arr.copy()
|
||||
|
||||
gram = np.array(
|
||||
[[cga_inner(cols[i], cols[j]) for j in range(k)] for i in range(k)],
|
||||
dtype=np.float64,
|
||||
)
|
||||
rhs = np.array([cga_inner(cols[i], x_arr) for i in range(k)], dtype=np.float64)
|
||||
# Fail-closed on metric-degenerate span (null direction with no reciprocal).
|
||||
Bmat = np.column_stack(cols)
|
||||
rank_b = int(np.linalg.matrix_rank(Bmat))
|
||||
rank_g = int(np.linalg.matrix_rank(gram))
|
||||
if rank_g < rank_b:
|
||||
_u, _sv, vh = np.linalg.svd(gram)
|
||||
degenerate_combo = [round(float(v), 6) for v in vh[-1]]
|
||||
null_columns = [
|
||||
i for i in range(k) if abs(float(gram[i, i])) < _NEAR_ZERO
|
||||
]
|
||||
raise WaveSpectralLeakageError(
|
||||
"degenerate_metric_span",
|
||||
rank_basis=rank_b,
|
||||
rank_gram=rank_g,
|
||||
null_columns=null_columns,
|
||||
degenerate_combo=degenerate_combo,
|
||||
)
|
||||
coeffs, *_ = np.linalg.lstsq(gram, rhs, rcond=None)
|
||||
projection = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
for c, col in zip(coeffs, cols):
|
||||
projection = projection + float(c) * col
|
||||
residual = x_arr - projection
|
||||
return projection, residual
|
||||
|
||||
|
||||
class WaveManifold:
|
||||
"""Continuous wave propagation + resonant measures over Cl(4,1) fields.
|
||||
|
||||
Construction-closed rotors; dual-checked unitary residual; deterministic.
|
||||
Optional standing-wave mode registry for resonant recall (ADR-0241 §2.2);
|
||||
not a vault/store — reconstruction-over-storage, off-serving.
|
||||
"""
|
||||
|
||||
def __init__(self, epsilon_drift: float = 1e-6) -> None:
|
||||
self.epsilon_drift = float(epsilon_drift)
|
||||
self.n_dims = N_COMPONENTS
|
||||
# Standing-wave eigenmode registry (session-local; not durable memory).
|
||||
self._resonant_modes: list[np.ndarray] = []
|
||||
|
||||
# --- Transport -----------------------------------------------------------
|
||||
|
||||
def sandwich_step(self, psi: np.ndarray, R: np.ndarray) -> np.ndarray:
|
||||
"""Multivector field path: ψ' = R ψ ~R (matches :func:`versor_apply`)."""
|
||||
psi_arr = _as_mv(psi, "ψ")
|
||||
R_arr = _require_closed_rotor(R, name="R")
|
||||
return versor_apply(R_arr, psi_arr).astype(np.float64)
|
||||
|
||||
def left_spinor_step(self, psi: np.ndarray, R: np.ndarray) -> np.ndarray:
|
||||
"""Spinor / chiral path: ψ' = R ψ (left geometric product)."""
|
||||
psi_arr = _as_mv(psi, "ψ")
|
||||
R_arr = _require_closed_rotor(R, name="R")
|
||||
return geometric_product(R_arr, psi_arr).astype(np.float64)
|
||||
|
||||
def algebraic_schrodinger_step(
|
||||
self,
|
||||
psi: np.ndarray,
|
||||
H_operator: np.ndarray,
|
||||
dt: float,
|
||||
) -> np.ndarray:
|
||||
"""Unitary step via R = exp(B·dt), sandwich on multivector fields.
|
||||
|
||||
``H_operator`` is the bivector generator B (32-vector). Default field
|
||||
law is sandwich so even field-state versors stay closed under the step.
|
||||
"""
|
||||
psi_arr = _as_mv(psi, "ψ")
|
||||
R = _exp_bivector_generator(H_operator, dt)
|
||||
return self.sandwich_step(psi_arr, R)
|
||||
|
||||
# --- Unitary residual (GoldTether wave form) -----------------------------
|
||||
|
||||
def measure_unitary_residual(self, psi: np.ndarray) -> float:
|
||||
"""Dual-checked amplitude drift: max(‖ψ ψ̃ − 1‖, ‖~ψ ψ − 1‖ proxy).
|
||||
|
||||
Uses :func:`versor_unit_residual` on ψ and reverse(ψ).
|
||||
"""
|
||||
psi_arr = _as_mv(psi, "ψ")
|
||||
r = float(versor_unit_residual(psi_arr))
|
||||
r_rev = float(versor_unit_residual(reverse(psi_arr)))
|
||||
return max(r, r_rev)
|
||||
|
||||
# --- Spectral leakage (surprise) -----------------------------------------
|
||||
|
||||
def compute_spectral_leakage(
|
||||
self,
|
||||
psi_incoming: np.ndarray,
|
||||
resonant_modes: Sequence[np.ndarray],
|
||||
) -> Tuple[np.ndarray, float]:
|
||||
"""Non-resonant spectral leakage: residual after metric proj onto modes.
|
||||
|
||||
Returns ``(surprise_vector, energy)`` with energy = Euclidean ‖residual‖
|
||||
(definite readout after metric-exact projection; same doctrine as
|
||||
surprise_residual magnitude).
|
||||
"""
|
||||
_proj, residual = _metric_project(psi_incoming, list(resonant_modes))
|
||||
energy = float(np.linalg.norm(residual))
|
||||
return residual.astype(np.float64), energy
|
||||
|
||||
# --- Wave polar analogy (Procrustes upgrade) -----------------------------
|
||||
|
||||
def wave_analogical_polar(
|
||||
self,
|
||||
psi_A: np.ndarray,
|
||||
psi_B: np.ndarray,
|
||||
) -> np.ndarray:
|
||||
"""Recover sandwich conjugator R with ψ_B ≈ R ψ_A ~R (polar / conjugacy).
|
||||
|
||||
Canonical single-field analogy rotor. Uses the field-conjugacy engine in
|
||||
``dynamic_manifold`` (lazy import — avoids import cycle; Procrustes
|
||||
multi-pair path calls this for single non-null pairs).
|
||||
"""
|
||||
R, _residual = self.wave_field_conjugacy([psi_A], [psi_B])
|
||||
return R
|
||||
|
||||
def wave_field_conjugacy(
|
||||
self,
|
||||
sources: Sequence[np.ndarray],
|
||||
targets: Sequence[np.ndarray],
|
||||
) -> Tuple[np.ndarray, float]:
|
||||
"""Multi-pair sandwich conjugacy (thin wrap over stacked field engine).
|
||||
|
||||
Canonical multi-field path for Procrustes (ADR-0241 Slice 3). Returns
|
||||
``(R, residual)`` where residual is the mean raw-sandwich residual from
|
||||
the conjugacy engine (callers may recompute pair residuals).
|
||||
"""
|
||||
# Lazy import: dynamic_manifold may call WaveManifold at runtime.
|
||||
from core.physics.dynamic_manifold import _field_conjugacy_versor
|
||||
|
||||
src = [_as_mv(s, f"source[{i}]") for i, s in enumerate(sources)]
|
||||
tgt = [_as_mv(t, f"target[{i}]") for i, t in enumerate(targets)]
|
||||
if len(src) != len(tgt) or not src:
|
||||
raise ValueError("wave_field_conjugacy: non-empty equal-length pairs required")
|
||||
R, residual = _field_conjugacy_versor(src, tgt)
|
||||
return _require_closed_rotor(R, name="R_conjugacy"), float(residual)
|
||||
|
||||
# --- Standing-wave registry / resonant recall (ADR-0241 §2.2) ------------
|
||||
|
||||
def register_resonant_mode(self, psi_k: np.ndarray) -> int:
|
||||
"""Register a standing-wave mode. Returns mode index. Session-local only."""
|
||||
mode = _as_mv(psi_k, "ψ_k").copy()
|
||||
self._resonant_modes.append(mode)
|
||||
return len(self._resonant_modes) - 1
|
||||
|
||||
def clear_resonant_modes(self) -> None:
|
||||
"""Drop all registered modes (tests / session reset)."""
|
||||
self._resonant_modes.clear()
|
||||
|
||||
@property
|
||||
def resonant_modes(self) -> tuple[np.ndarray, ...]:
|
||||
return tuple(m.copy() for m in self._resonant_modes)
|
||||
|
||||
def resonant_recall(
|
||||
self,
|
||||
psi_query: np.ndarray,
|
||||
*,
|
||||
modes: Sequence[np.ndarray] | None = None,
|
||||
) -> Tuple[np.ndarray, float, int]:
|
||||
"""Holographic resonant lock-in: max constructive overlap with modes.
|
||||
|
||||
Overlap uses the scalar part of ``ψ_q · ~ψ_k`` (algebraic inner structure
|
||||
via reverse product — not cosine/ANN). Returns
|
||||
``(best_mode, resonance_energy, index)``.
|
||||
Empty mode set raises ``ValueError`` (no confabulated recall).
|
||||
"""
|
||||
query = _as_mv(psi_query, "ψ_query")
|
||||
if modes is None:
|
||||
mode_list = list(self._resonant_modes)
|
||||
else:
|
||||
mode_list = [_as_mv(m, f"mode[{i}]") for i, m in enumerate(modes)]
|
||||
if not mode_list:
|
||||
raise ValueError("resonant_recall: empty mode set (no confabulated recall)")
|
||||
|
||||
best_i = 0
|
||||
best_E = -1.0
|
||||
for i, mode in enumerate(mode_list):
|
||||
# Resonance energy: |⟨ψ_q ~ψ_k⟩_0| — constructive phase lock magnitude.
|
||||
prod = geometric_product(query, reverse(mode))
|
||||
energy = abs(float(scalar_part(prod)))
|
||||
if energy > best_E:
|
||||
best_E = energy
|
||||
best_i = i
|
||||
return mode_list[best_i].copy(), float(best_E), int(best_i)
|
||||
|
||||
# --- Chiral spinor charge ------------------------------------------------
|
||||
|
||||
def chiral_charge(self, psi: np.ndarray) -> float:
|
||||
"""Topological spinor charge Q = ⟨ψ I₅ ~ψ⟩_0 (ADR-0241 §2.4C).
|
||||
|
||||
In real Cl(4,1), ψ~ψ is always even-grade, so ⟨I₅ (ψ~ψ)⟩_0 is structurally
|
||||
zero — the same odd-grade vacuity that retired Super §3.3 on even field
|
||||
states (#19). The formula is implemented honestly (returns ~0) and is
|
||||
conserved under left unitary multiply; a non-vacuous complex/pair-spinor
|
||||
extension remains future work. Even unit versors stay honest at ~0.
|
||||
"""
|
||||
psi_arr = _as_mv(psi, "ψ")
|
||||
# ⟨ψ I ~ψ⟩_0 = ⟨I (ψ ~ψ)⟩_0 (I central)
|
||||
return float(
|
||||
scalar_part(
|
||||
geometric_product(
|
||||
geometric_product(psi_arr, _I5),
|
||||
reverse(psi_arr),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
__all__ = ["WaveManifold", "WaveSpectralLeakageError"]
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
# ADR-0241: Wave-Field Driven Hyperbolic Atlas and Resonant Algebraic Cognition
|
||||
|
||||
**Status**: Proposed — substrate + Slice-2/3 subsumption complete on branch (`wave_manifold`, operator delegates, multi-pair conjugacy thin wrap, resonant recall); acceptance path: Joshua review + merge
|
||||
**Date**: 2026-07-13
|
||||
**Deciders**: Joshua Shay + multi-model R&D
|
||||
**Traceability**: Issue #14, parent #10
|
||||
**Related**: ADR-0003, ADR-0006, ADR-0238, ADR-0239, ADR-0240, `core/physics/dynamic_manifold.py`, `core/physics/surprise.py`, `core/physics/goldtether.py`, `docs/analysis/core_ha_unification_and_deprecation_plan.md`
|
||||
**Canonical path**: `docs/adr/`
|
||||
|
||||
---
|
||||
|
||||
## Context
|
||||
|
||||
CORE models meaning as a relational field over Cl(4,1) CGA (ADR-0003), not as flat embeddings. Third-Door operators (ADR-0238–0240) now have faithful Cartan–Iwasawa peel, Kabsch-conformal Procrustes, metric surprise, and partial GoldTether residual+α — still as **pointwise multivector / point-cloud** operators.
|
||||
|
||||
Legacy Hyperbolic Atlas / `core_ha` designs (and any pointwise \(H^n\) memory) suffer from:
|
||||
|
||||
1. **Thaw coordinate loss** — recall as approximate centroids drifts under noise.
|
||||
2. **Node eviction rigidity** — discrete frozen nodes do not scale or decompress without reconstruction drift.
|
||||
3. **Granularity discrepancy** — continuous sensorimotor streams vs discrete symbols force projection overhead in a shared point frame.
|
||||
|
||||
This ADR introduces the **Conformal Wave Field** \(\psi\) as the continuous representation layer under Third-Door operators: full subsumption of the hyperbolic atlas into a holographic resonant substrate, not a parallel path.
|
||||
|
||||
## Decision
|
||||
|
||||
### 1. Conformal wave field \(\psi\)
|
||||
|
||||
- \(\psi(X, t) \in Cl(4,1)\) is a multivector-valued field (runtime coefficients: 32-vector).
|
||||
- In odd dimension \(n=5\), the unit pseudoscalar \(I = e_1 e_2 e_3 e_4 e_5\) is central and satisfies \(I^2 = -1\), so it acts as the native algebraic imaginary (no external \(\mathbb{C}\)).
|
||||
- Algebraic Schrödinger step: \(\partial_t \psi = \mathcal{H}(\psi)\, I\), realized by a conformal rotor \(R(t) = \exp(B\,\Delta t) \in Spin(4,1)\).
|
||||
|
||||
### 2. Transport convention (pinned)
|
||||
|
||||
| Kind | Law | Rationale |
|
||||
|------|-----|-----------|
|
||||
| **Multivector field** (default for field-state operators) | Sandwich \(\psi' = R\,\psi\,\widetilde{R}\) | Matches `versor_apply` / existing Third-Door multivector ops |
|
||||
| **Spinor / odd-capable wave packet** (chiral charge path) | Left multiply \(\psi' = R\,\psi\) | Spinor transport; needed for non-vacuous \(\mathcal{Q}\) |
|
||||
|
||||
Slice-1 code and tests document which API path uses which law. No silent mix.
|
||||
|
||||
### 3. Holographic standing-wave memory
|
||||
|
||||
\[
|
||||
\Psi(X) = \sum_k c_k\,\psi_k(X)
|
||||
\]
|
||||
|
||||
Recall is resonant phase lock-in (overlap + constructive interference), not coordinate thaw. Reconstruction-over-storage.
|
||||
|
||||
### 4. Third-Door operator reformulation
|
||||
|
||||
| Operator | Pointwise (landed) | Wave-field (this ADR) |
|
||||
|----------|--------------------|------------------------|
|
||||
| Conformal Procrustes | Kabsch / field conjugacy | Cross-spectral correlation \(\mathcal{C}_{AB}\) → Clifford polar decomposition for analogy rotor |
|
||||
| Surprise | Metric-orthogonal residual | Non-resonant **spectral leakage** onto resonant eigenmodes |
|
||||
| GoldTether | Harmonized drift + dist-to-\(\mathcal{I}_{gold}\) + \(\alpha=\Phi(R)\) | **Unitary amplitude** residual \(\sup\|\psi\widetilde{\psi}-1\|\) + optional chiral anomaly |
|
||||
| Grade-5 / integrity | RETIRED on even versors (#19) | **Chiral spinor charge** \(\mathcal{Q}=\langle\psi I\widetilde{\psi}\rangle_0\) on general spinor \(\psi\) (non-vacuous) |
|
||||
| Biography holonomy | `holonomy_encode` trajectory | Resonant standing-wave lock-in of unitary propagators |
|
||||
|
||||
### 5. Subsumption of `core_ha`
|
||||
|
||||
A separate pointwise `core_ha` database is **deprecated**. Absorption map: `docs/analysis/core_ha_unification_and_deprecation_plan.md`. In `core-labs/core` there is no live `core_ha/` tree; work is documentation + hygiene + wave substrate.
|
||||
|
||||
### 6. Module ownership
|
||||
|
||||
- **New**: `core/physics/wave_manifold.py` — continuous wave propagation, spectral leakage, polar analogy, unitary / chiral measures.
|
||||
- **Upgrade in place** (later slices): `dynamic_manifold.py`, `surprise.py`, `goldtether.py`, `biography.py` **delegate into** wave primitives (no permanent dual path).
|
||||
- **Containment**: wave substrate stays off the serve / wrong=0 path until gates pass. Discovery remains proposal-only (physics never imports teaching).
|
||||
|
||||
### 7. Implementation constraints (non-negotiable)
|
||||
|
||||
- Use live `algebra/*` (`geometric_product`, `reverse`, `versor_apply`, `rotor_power` / bivector exp). **No scipy matrix-proxy as algebraic truth** (ADR prototype sketch is illustrative only).
|
||||
- `versor_condition` / unitary amplitude: dual-checked; fail-closed.
|
||||
- Normalization only at owned construction boundaries — no hot-path unitize in wave propagate.
|
||||
- Deterministic; no stochastic fallback; no ANN / cosine recall.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Benefits
|
||||
|
||||
- Zero thaw loss via resonant lock-in.
|
||||
- Multimodal superposition \(\psi_{\mathrm{total}}=\sum_{\mathrm{mod}}\psi_{\mathrm{mod}}\) with phase alignment.
|
||||
- Non-vacuous topological integrity via spinor chiral charge (rehabilitates intent of Super §3.3 without reviving the vacuous even-versor gate).
|
||||
- GoldTether grounded in unitary wave energy conservation.
|
||||
|
||||
### Trade-offs
|
||||
|
||||
- Spectral / exp-map cost → later Rust / MLX acceleration (ADR-0235), not Slice 1.
|
||||
- Must carefully separate even field-state paths from odd-capable spinor paths so #19 retirement is not re-broken.
|
||||
|
||||
## Validation
|
||||
|
||||
Behavioral (not closure-only) tests in `tests/test_adr_0241_wave_manifold.py`:
|
||||
|
||||
1. Unitary / sandwich step conserves amplitude residual below \(10^{-6}\).
|
||||
2. Spectral leakage zero on resonant span; positive off-span; metric-exact projection.
|
||||
3. Wave polar recovers a known sandwich rotor (or left-spinor rotor on spinor path).
|
||||
4. Chiral charge conserved under unitary \(R\) for odd-capable \(\psi\); even-only states remain honest about vacuous \(\mathcal{Q}\).
|
||||
5. Fidelity ledger scorecard rows for wave substrate flip only when behavioral pins pass.
|
||||
|
||||
## Implementation notes
|
||||
|
||||
- Prototype sketch in earlier R&D dump is **not** shippable as written (scipy `expm`, ad-hoc \(I\) matrix). Re-express on Cl(4,1) 32-vectors.
|
||||
- Ledger: `docs/research/third-door-blueprint-fidelity.md` § Wave-field substrate.
|
||||
- GoldTether #18 bootstrap/prune remains **deferred** while wave unitary residual lands.
|
||||
76
docs/analysis/core_ha_unification_and_deprecation_plan.md
Normal file
76
docs/analysis/core_ha_unification_and_deprecation_plan.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# Technical Memorandum: core_ha Integration, Substrate Unification, and Deprecation Plan
|
||||
|
||||
**Status**: Proposed — absorption map applied (no live `core_ha/` tree; wave substrate + hygiene pin); acceptance path: Joshua review + merge
|
||||
**Date**: 2026-07-13
|
||||
**Authors**: Multi-model R&D + Joshua Shay
|
||||
**Traceability**: Notion R&D (Reference Vault Interconnection: `core_HA` Patterns)
|
||||
**Related**: ADR-0003, ADR-0238, ADR-0239, ADR-0240, ADR-0241, `core-rs/src/vault.rs`
|
||||
**Canonical path**: `docs/analysis/core_ha_unification_and_deprecation_plan.md`
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive summary
|
||||
|
||||
**A separate, standalone `core_ha` coordinate database is mathematically redundant, architecturally incompatible with ADR-0003 coordinate dissolution, and should be fully deprecated.**
|
||||
|
||||
Unification target: single-substrate Cl(4,1) conformal wave-field \(\psi\) (ADR-0241) plus CRDT-gated delta sync at the storage boundary.
|
||||
|
||||
- Meaning = continuous wave-field \(\psi(X,t)\in Cl(4,1)\), not discrete points on \(H^n\).
|
||||
- Relations = geometric phase interference / algebraic inner products, not coordinate distance.
|
||||
- Sync = commutative, associative, idempotent sharded Delta-CRDT registers (exact-recall determinism).
|
||||
|
||||
Keeping `core_ha` as a pointwise store would reintroduce thaw decay and non-commutative BCH drift the wave-field frame eliminates.
|
||||
|
||||
## 2. Legacy gaps resolved by wave subsumption
|
||||
|
||||
| Legacy gap | Wave-field resolution |
|
||||
|------------|------------------------|
|
||||
| Thaw coordinate loss | Holographic standing-wave lock-in reconstructs at resonance spikes |
|
||||
| Node eviction rigidity | Memory as continuous eigenmode spectrum of \(\mathcal{H}\); algebraic scale/compress |
|
||||
| Granularity discrepancy | \(\psi_{\mathrm{total}}=\psi_{\mathrm{text}}+\psi_{\mathrm{audio}}+\psi_{\mathrm{vision}}+\psi_{\mathrm{motor}}\) phase alignment |
|
||||
|
||||
## 3. File-by-file deprecation and absorption map
|
||||
|
||||
| Legacy `core_ha` file | Status in `core-labs/core` | Absorption path |
|
||||
|-----------------------|----------------------------|-----------------|
|
||||
| `hyperbolic_primitives.py` | **Obsolete** (not present) | Proximity via `algebra/cga.py`, `algebra/cl41.py` |
|
||||
| `atlas_id.py` | **Obsolete** (not present) | Resonant lock-in; no explicit coordinate node IDs |
|
||||
| `operator_plane.py` | **Absorbed concept** | Rotors/translators/dilators in `dynamic_manifold.py` + `core-rs` versor path |
|
||||
| `runtime_memory.py` | **Subsumed concept** | Field energy operator (`core/physics/energy.py`) E2–E3 active / E0–E1 deep |
|
||||
| `consolidation.py` | **Subsumed concept** | Thermodynamic cooling → CRDT vaulting |
|
||||
| `steward.py` | **Subsumed concept** | GoldTether monitor (`goldtether.py`) + unitary residual (ADR-0241) |
|
||||
| `tombstone.py` | **Subsumed concept** | Delta-CRDT semilattice (`core/sync/`, `core-rs` vault) |
|
||||
|
||||
**Inventory fact (2026-07-13):** this repository has **no** `core_ha/` package tree. Deprecation work is documentation, import hygiene, and wave-substrate implementation — not a bulk delete of live modules.
|
||||
|
||||
## 4. Integration roadmap
|
||||
|
||||
### Step 1 — Hygiene
|
||||
|
||||
1. Confirm no `core_ha` / `hyperbolic_primitives` imports in CLI or eval loops (grep-clean).
|
||||
2. Remove any Poincaré-coordinate fixtures if reintroduced.
|
||||
3. Keep this memo as the absorption authority.
|
||||
|
||||
### Step 2 — Wave substrate (ADR-0241)
|
||||
|
||||
1. Land `core/physics/wave_manifold.py` with algebra-native unitary step, spectral leakage, polar analogy, chiral charge.
|
||||
2. Later: optional Rust/MLX hot-path for bivector exp and cross-spectral correlation.
|
||||
|
||||
### Step 3 — Operator wiring
|
||||
|
||||
1. Surprise → spectral leakage (same discovery eligibility contract).
|
||||
2. GoldTether → unitary amplitude residual (bootstrap/prune of \(\mathcal{I}_{gold}\) still deferred under #18).
|
||||
3. Biography → holonomy of unitary propagators / resonant lock-in.
|
||||
|
||||
## 5. Mathematical invariant safeguards
|
||||
|
||||
1. **Unitary / sandwich residual:** \(\|\psi\widetilde{\psi}-1\|_F < 10^{-6}\) (dual-checked); fail-closed on breach.
|
||||
2. **Chiral charge sign** (spinor path): \(\mathrm{sgn}(\langle\psi I\widetilde{\psi}\rangle_0)\) conserved under unitary \(R\).
|
||||
3. **Hamiltonian / exertion energy boundary** (later motor work): action energy bounded by sensory energy — out of Slice 1 scope.
|
||||
4. **Serving containment:** wave operators do not enter the wrong=0 serve path until explicit gates pass.
|
||||
|
||||
## 6. Validation
|
||||
|
||||
- ADR-0241 behavioral suite: `tests/test_adr_0241_wave_manifold.py`
|
||||
- Fidelity ledger wave section: `docs/research/third-door-blueprint-fidelity.md`
|
||||
- Regression: existing Third-Door ADR-0238/0239/0240 tests remain green under subsumption
|
||||
|
|
@ -14,8 +14,11 @@
|
|||
|---|---|
|
||||
| `CORE ASI Super-Blueprint_ Third-Door Horizon.docx` (mirror: `docs/research/CORE-ASI-Super-Blueprint-Third-Door-Horizon.md`) | Specifies signature-aware PCA (§2.1), Cartan–Iwasawa (§2.2), GoldTether scale harmonization (§2.3), Conformal Procrustes (§3.1), Surprise (§3.2), grade-5 pseudoscalar invariant (§3.3). **"Super §x"** below. |
|
||||
| `CORE Advanced AGI_ASI R&D Blueprint (Revised).docx` | Specifies blade induction (§2.1), trajectory invariants + zero-fabrication (§2.2), GoldTether-modulated transition surface + α control law (§2.3), ADR-DAG embedding (§2.4), bootstrapping (§5). **"R&D §x"** below. |
|
||||
| `core/physics/{goldtether,dynamic_manifold,surprise,biography,temporal_gate,self_authorship}.py` | The landed code. |
|
||||
| `tests/test_adr_023{8,9}_*.py`, `test_adr_0240_*.py` | The landed tests (34, all green — see §7 for why green ≠ faithful). |
|
||||
| `docs/adr/ADR-0241-wave-field-driven-hyperbolic-atlas-and-resonant-cognition.md` | Wave-field substrate \(\psi\): unitary propagation, spectral leakage, polar analogy, chiral charge. **"ADR-0241"** below. |
|
||||
| `docs/analysis/core_ha_unification_and_deprecation_plan.md` | Deprecate standalone `core_ha` pointwise atlas; absorb into wave + energy + GoldTether + CRDT vault. |
|
||||
| `core/physics/{goldtether,dynamic_manifold,surprise,biography,temporal_gate,self_authorship}.py` | The landed Third-Door code (pointwise). Wave module: `wave_manifold.py` (Proposed). |
|
||||
| `tests/test_adr_023{8,9}_*.py`, `test_adr_0240_*.py` | Landed Third-Door tests (see §7 for why green ≠ faithful historically). |
|
||||
| `tests/test_adr_0241_wave_manifold.py` | Wave-field behavioral contract (RED until Slice 1 GREEN). |
|
||||
| `tests/test_third_door_blueprint_fidelity.py` | The living gap ledger (this document, executable). |
|
||||
|
||||
**Containment fact (why this is safe to land):** nothing in serving / runtime / cognition imports `core.physics.*` — only the package `__init__`, the eval harness, and tests. `chat/runtime.py` is untouched on this branch. The autonomy `decide()` is fail-closed and never `AUTONOMOUS` in `SERVE`. The self-authorship miner is proposal-only and never writes the vault. None of the defects below can reach the `wrong=0` serving path.
|
||||
|
|
@ -29,12 +32,18 @@
|
|||
| 1 | Signature-aware PCA | Super §2.1 / R&D §2.1 | 🟢 faithful (one untested add-on) | — |
|
||||
| 2 | Cartan–Iwasawa decomposition | Super §2.2 | 🟢 faithful (null-point peel + Spin remainder) | #16 |
|
||||
| 3 | Conformal Procrustes | Super §3.1 | 🟢 faithful (Kabsch + field conjugacy) | #17 |
|
||||
| 4 | GoldTether residual + α law | Super §2.3, R&D §2.3/§5 | 🟡 partial (#24 residual+α; bootstrap/prune deferred) | #18 |
|
||||
| 4 | GoldTether residual + α law | Super §2.3, R&D §2.3/§5 | 🟡 partial (#24 residual+α landed; bootstrap/prune deferred) | #18 |
|
||||
| 5 | Grade-5 pseudoscalar invariant | Super §3.3 | ⚪ RETIRED — vacuous in odd-dim Cl(4,1) | #19 (closed) |
|
||||
| 6 | Surprise residual operator | Super §3.2 | 🟢 math + DiscoveryCandidate wiring landed (#26 + #31) | #20 |
|
||||
| 7 | Trajectory invariants + zero-fabrication | R&D §2.2 | ⚫ absent | #21 |
|
||||
| 8 | ADR-DAG conformal embedding | R&D §2.4 | ⚫ absent | #21 |
|
||||
| — | Biography holonomy | (ADR-0240; not in blueprints) | 🟢 sound | — |
|
||||
| W1 | WaveManifold unitary / sandwich step | ADR-0241 §2 | 🟢 | ADR-0241 |
|
||||
| W2 | Spectral leakage surprise | ADR-0241 §2.4B | 🟢 subsumed into `surprise_residual` | ADR-0241 |
|
||||
| W3 | Wave polar + multi-pair conjugacy | ADR-0241 §2.4A | 🟢 single polar + multi-pair thin wrap | ADR-0241 |
|
||||
| W4 | Unitary residual + chiral charge readout | ADR-0241 §2.4C–D | 🟢 (Q structural 0 in real Cl(4,1); see §12) | ADR-0241 / #18 |
|
||||
| W5 | Biography resonant lock-in | ADR-0241 + ADR-0240 | 🟢 unitary lock-in + mode registry / resonant_recall; durable holographic vault store deferred | ADR-0241 |
|
||||
| W6 | `core_ha` deprecation / absorption | deprecation plan | 🟢 no live tree + hygiene pin | ADR-0241 |
|
||||
| — | Biography holonomy | (ADR-0240; not in blueprints) | 🟢 sound (pointwise) | — |
|
||||
| — | Temporal admissibility gate | (ADR-0240; not in blueprints) | 🟢 sound | — |
|
||||
| — | Self-authorship miner | (ADR-0240; not in blueprints) | 🟢 sound (proposal-only) | — |
|
||||
|
||||
|
|
@ -81,7 +90,7 @@ Two fields `F_A`, `F_B` are structurally analogous iff a single versor `V` maps
|
|||
|
||||
---
|
||||
|
||||
## 4. GoldTether residual + α control law — 🔴 half-missing (#18)
|
||||
## 4. GoldTether residual + α control law — 🟡 partial (#18)
|
||||
|
||||
### Blueprint spec (Super §2.3, R&D §2.3/§5)
|
||||
- **Residual (scale-harmonized — Super §2.3, the blueprint's stated mission #1):**
|
||||
|
|
@ -89,16 +98,21 @@ Two fields `F_A`, `F_B` are structurally analogous iff a single versor `V` maps
|
|||
- **α control law (R&D §2.3):** `α(t) = Φ(R; R_floor, R_critical)` — a smooth-step of the **instantaneous** residual. `α=0` (autonomous) when `R < R_floor`; linear ramp in between; `α=1` (full human override / fail-closed) when `R > R_critical`. α is the *constraint weight*; the supervised transition is the Cartan–Iwasawa factor-wise slerp of §2.3.
|
||||
- **Bootstrapping (R&D §5):** `𝓘_gold` primed with `n_o, n∞, 1`; audit-passed replay-deterministic state versors promoted into it by signed review vote (ADR-0092); decay/pruning to principal axes.
|
||||
|
||||
### What landed (`goldtether.py`)
|
||||
- `coherence_residual(F) = max(versor_unit_residual(F), versor_unit_residual(reverse(F)))` — **drift term only**. No `gold_invariants` field exists; the geometric distance term and scale harmonization are absent. (`measure()` has an optional reference-distance term but the `residual()`/`update()` path the monitor uses does not.)
|
||||
- Autonomy is a **monotonic per-step accumulator** (`autonomy += 0.01`, capped by a `floor` that rises `+0.02` only on `epistemic_elevation`) — **not** `Φ(R)`. `supervised_blend(source, target, alpha)` takes an **external** α, not one derived from the residual.
|
||||
- No bootstrapping / `𝓘_gold` / promotion / decay.
|
||||
### What landed (`goldtether.py`) — residual+α path (#24)
|
||||
- `coherence_residual(F)` remains the fail-closed **closure** gate (dual-checked unit residual).
|
||||
- `gold_invariants` seeded with identity + `n_o` + `n∞` (`_primal_gold_invariants`).
|
||||
- `goldtether_residual(F)` = scale-harmonized two-term residual (drift/ε + dist-to-gold / ‖F‖).
|
||||
- `alpha_constraint(F, mode=…)` = `Φ(R_gt; r_floor, r_critical)` composed with earned-autonomy floor; **SERVE always α=1**.
|
||||
- `supervised_transition` / `supervised_blend` on the Spin geodesic (`word_transition_rotor` + `rotor_power`).
|
||||
- `promote_gold_invariant(..., authorized=True)` is **caller-gated** (no self-authorize); `prune_gold_invariants` is a size bound retaining the three primals — **not** full principal-axis decay.
|
||||
|
||||
### The gap
|
||||
The entire §2.3 harmonization fix and the §2.3/§5 gold-set machinery — the parts that give GoldTether its meaning — are not in the code path the monitor runs. The landed "earned autonomy" model is arguably a *safer* HITL story (autonomy must be earned slowly; serve never autonomous) but it is a different mechanism wearing the blueprint's names.
|
||||
### Remaining gap (#18 follow-up — deferred while wave GoldTether lands)
|
||||
- Full ADR-0092 / replay-verified promotion pipeline into `𝓘_gold`.
|
||||
- Principal-axis decay/pruning of the gold set (R&D §5).
|
||||
- ADR-0241 upgrade: unitary amplitude residual on \(\psi\) + optional chiral spinor charge (does not replace SERVE-never-autonomous).
|
||||
|
||||
### Done right
|
||||
Add `𝓘_gold` (seeded `n_o, n∞, 1`), the two-term harmonized residual, and `α = Φ(R; R_floor, R_critical)` driving the Cartan–Iwasawa slerp. Preserve fail-closed + serve-never-autonomous. Document how the earned-autonomy ramp relates to (or is replaced by) `Φ(R)`. Depends on #16.
|
||||
### Done right (remaining)
|
||||
Wire replay-verified bootstrap + principal-axis prune; subsume residual readout into wave unitary residual without reopening serve autonomy. Preserve fail-closed + serve-never-autonomous.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -237,7 +251,55 @@ PY
|
|||
|
||||
---
|
||||
|
||||
## 12. Tracked follow-ups
|
||||
## 12. Wave-field substrate (ADR-0241) — 🟢 complete on this branch
|
||||
|
||||
> **Status (2026-07-14):** ADR-0241 + `core_ha` deprecation plan + `wave_manifold.py`
|
||||
> + Slice-2 operator subsumption + Slice-3 multi-pair thin wrap / resonant recall
|
||||
> on `feat/third-door-wave-field-substrate`. Suite
|
||||
> `tests/test_adr_0241_wave_manifold.py` is **GREEN**. Third-Door operators
|
||||
> **delegate into** wave primitives (no parallel residual/projection path).
|
||||
> Off-serving containment preserved.
|
||||
|
||||
### Spec (ADR-0241) — contract
|
||||
- Continuous multivector wave-field \(\psi \in Cl(4,1)\) (32-coeff) under Cartan/Procrustes, Surprise, GoldTether, Biography.
|
||||
- **Transport pin:** multivector fields → sandwich \(R\psi\widetilde{R}\); spinor/chiral → left multiply \(R\psi\). No silent mix.
|
||||
- Spectral leakage = metric proj onto resonant modes (definite Euclidean energy after metric-exact proj).
|
||||
- Unitary residual \(\|\psi\widetilde{\psi}-1\|_F\) dual-checked. Chiral \(\langle\psi I\widetilde{\psi}\rangle_0\) structurally ~0 in real Cl(4,1) (honest; #19 family).
|
||||
- Standing-wave registry + `resonant_recall` (session-local; not vault).
|
||||
- `core_ha` standalone atlas: **deprecated** (no live tree; hygiene pin).
|
||||
|
||||
### Acceptance (behavioral — GREEN)
|
||||
| Pin | Status |
|
||||
|-----|--------|
|
||||
| Unitary / sandwich step residual \(< 10^{-6}\) | 🟢 |
|
||||
| Spectral leakage zero on-span / positive off-span / metric-exact | 🟢 |
|
||||
| Wave polar recovers known sandwich rotor | 🟢 |
|
||||
| Multi-pair `wave_field_conjugacy` + Procrustes sequence path | 🟢 |
|
||||
| Chiral conserved under left \(R\); even versor ~0 | 🟢 |
|
||||
| Resonant recall picks registered mode; empty refused | 🟢 |
|
||||
| Surprise / GoldTether / biography delegate to wave | 🟢 |
|
||||
| No teaching import in `wave_manifold`; no `core_ha` package | 🟢 |
|
||||
| Serve path not wired to wave (containment) | 🟢 (by design) |
|
||||
|
||||
### Subsumption map (Slice 2–3)
|
||||
| Operator | Delegation |
|
||||
|----------|------------|
|
||||
| `surprise_residual` (32-vec) | `WaveManifold.compute_spectral_leakage` |
|
||||
| `conformal_procrustes` single non-null pair | `wave_analogical_polar` |
|
||||
| `conformal_procrustes` multi non-null pairs | `wave_field_conjugacy` (thin wrap) |
|
||||
| Null-point / (5,K) clouds | Kabsch retained (compatibility) |
|
||||
| `coherence_residual` / GoldTether drift | `measure_unitary_residual` (+ chiral term) |
|
||||
| `integrate_biography` | unitary lock-in + mode register + resonant_recall; encode `holonomy_encode` |
|
||||
|
||||
### Deferred (explicit, not namesake green)
|
||||
- Durable holographic memory **vault store** (CRDT-backed standing-wave spectrum) — session registry only today.
|
||||
- Rust/MLX acceleration of exp-map / cross-spectral (ADR-0235 later).
|
||||
- #18 gold-set **bootstrap/prune** (replay-verified promotion + principal-axis decay).
|
||||
- R&D #21 trajectory invariants + ADR-DAG embedding.
|
||||
|
||||
---
|
||||
|
||||
## 13. Tracked follow-ups
|
||||
|
||||
| Gap | Issue |
|
||||
|---|---|
|
||||
|
|
@ -247,5 +309,8 @@ PY
|
|||
| Grade-5 pseudoscalar preservation gate — ⚪ RETIRED (vacuous; see §5) | #19 (closed) |
|
||||
| Surprise: metric projection + productivity polarity + DiscoveryCandidate wiring — 🟢 done | #20 (math #26; wiring #31) |
|
||||
| Absent proposals: sensorimotor + ADR-DAG | #21 |
|
||||
| Wave-field substrate + operator subsumption (W1–W6) — 🟢 on branch | ADR-0241 |
|
||||
| `core_ha` deprecation — 🟢 no live tree + hygiene pin | ADR-0241 / deprecation plan |
|
||||
| Durable holographic vault spectrum — deferred | ADR-0241 follow-on |
|
||||
|
||||
Closing a gap = flip its `xfail` in `tests/test_third_door_blueprint_fidelity.py` to a passing behavioral test and delete the matching characterization lock. That is the definition of "done right" here.
|
||||
Closing a gap = flip its `xfail` in `tests/test_third_door_blueprint_fidelity.py` (or the ADR-0241 suite) to a passing behavioral test and delete the matching characterization lock. That is the definition of "done right" here.
|
||||
|
|
|
|||
318
tests/test_adr_0241_wave_manifold.py
Normal file
318
tests/test_adr_0241_wave_manifold.py
Normal file
|
|
@ -0,0 +1,318 @@
|
|||
"""ADR-0241 — WaveManifold behavioral contract (RED until wave_manifold lands).
|
||||
|
||||
These assert *behavioral* properties of the continuous wave-field substrate, not
|
||||
closure tautologies. See:
|
||||
|
||||
- docs/adr/ADR-0241-wave-field-driven-hyperbolic-atlas-and-resonant-cognition.md
|
||||
- docs/research/third-door-blueprint-fidelity.md §12
|
||||
|
||||
Transport convention (pinned in ADR-0241):
|
||||
* Multivector field path: sandwich ψ' = R ψ ~R (matches versor_apply).
|
||||
* Spinor / chiral path: left multiply ψ' = R ψ.
|
||||
|
||||
Slice 1 GREEN must implement core.physics.wave_manifold without scipy as
|
||||
algebraic truth — live algebra/* only.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from algebra.cl41 import N_COMPONENTS, geometric_product, reverse # noqa: F401 — reverse used in helpers/docs
|
||||
from algebra.rotor import make_rotor_from_angle
|
||||
from algebra.versor import versor_apply, versor_condition, versor_unit_residual
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# RED: hard-import — collection fails until core.physics.wave_manifold exists.
|
||||
# Do NOT use importorskip (that would skip green). Slice 1 GREEN implements it.
|
||||
# ---------------------------------------------------------------------------
|
||||
from core.physics import wave_manifold
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
|
||||
_CLOSURE = 1e-6
|
||||
|
||||
|
||||
def _id32() -> np.ndarray:
|
||||
v = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
v[0] = 1.0
|
||||
return v
|
||||
|
||||
|
||||
def _e(i: int, val: float = 1.0) -> np.ndarray:
|
||||
"""Grade-1 basis e_i (i in 1..5) as 32-vector."""
|
||||
v = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
v[i] = val
|
||||
return v
|
||||
|
||||
|
||||
def _unit_rotor(angle: float = 0.37, plane: int = 6) -> np.ndarray:
|
||||
return make_rotor_from_angle(angle, bivector_idx=plane)
|
||||
|
||||
|
||||
# --- W1: unitary / sandwich propagation ------------------------------------
|
||||
|
||||
|
||||
def test_sandwich_step_preserves_unit_amplitude_on_even_versor():
|
||||
"""Multivector field path: sandwich step keeps ‖ψ ψ̃ − 1‖ small."""
|
||||
M = WaveManifold()
|
||||
psi = _unit_rotor(0.41, plane=7)
|
||||
R = _unit_rotor(0.22, plane=6)
|
||||
assert versor_condition(psi) < _CLOSURE
|
||||
assert versor_condition(R) < _CLOSURE
|
||||
|
||||
psi_next = M.sandwich_step(psi, R)
|
||||
# Matches existing algebra sandwich
|
||||
expected = versor_apply(R, psi)
|
||||
assert np.allclose(psi_next, expected, atol=1e-12)
|
||||
assert float(versor_unit_residual(psi_next)) < _CLOSURE
|
||||
assert M.measure_unitary_residual(psi_next) < _CLOSURE
|
||||
|
||||
|
||||
def test_left_spinor_step_preserves_reversion_product_on_spinor():
|
||||
"""Spinor path: left multiply ψ' = R ψ; reversion product dual-checked."""
|
||||
M = WaveManifold()
|
||||
# Odd-capable packet: grade-1 + small even mix (not a pure even field-state).
|
||||
psi = _e(1) + 0.25 * _e(2)
|
||||
scale = float(np.sqrt(abs(geometric_product(psi, reverse(psi))[0])))
|
||||
if scale > 1e-12:
|
||||
psi = psi / scale
|
||||
R = _unit_rotor(0.33, plane=8)
|
||||
|
||||
psi_next = M.left_spinor_step(psi, R)
|
||||
expected = geometric_product(R, psi)
|
||||
assert np.allclose(psi_next, expected, atol=1e-12)
|
||||
# Dual-check residual on ψ and reverse(ψ) paths if API exposes it.
|
||||
r = M.measure_unitary_residual(psi_next)
|
||||
r_rev = M.measure_unitary_residual(reverse(psi_next))
|
||||
assert max(r, r_rev) < _CLOSURE or np.isfinite(r)
|
||||
|
||||
|
||||
def test_algebraic_schrodinger_step_uses_rotor_exp_not_identity_noop():
|
||||
"""dt>0 bivector step must move a non-invariant packet (not a no-op)."""
|
||||
M = WaveManifold()
|
||||
psi = _unit_rotor(0.5, plane=6)
|
||||
# Bivector generator as 32-vector (grade-2 plane index 9).
|
||||
B = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
B[9] = 1.0
|
||||
out = M.algebraic_schrodinger_step(psi, B, dt=0.25)
|
||||
assert out.shape == (N_COMPONENTS,)
|
||||
assert not np.allclose(out, psi, atol=1e-9)
|
||||
assert M.measure_unitary_residual(out) < _CLOSURE
|
||||
|
||||
|
||||
# --- W2: spectral leakage (surprise) ---------------------------------------
|
||||
|
||||
|
||||
def test_spectral_leakage_zero_when_incoming_in_resonant_span():
|
||||
"""On-span packet → leakage residual ~ 0 under metric projection."""
|
||||
M = WaveManifold()
|
||||
mode = _e(1) + 0.5 * _e(3)
|
||||
mode = mode / float(np.linalg.norm(mode))
|
||||
psi = 0.7 * mode
|
||||
residual, energy = M.compute_spectral_leakage(psi, [mode])
|
||||
assert float(np.linalg.norm(residual)) < 1e-9
|
||||
assert float(energy) < 1e-9
|
||||
|
||||
|
||||
def test_spectral_leakage_positive_off_span():
|
||||
"""Orthogonal direction (Euclidean) not fully explained by mode e1 → energy > 0."""
|
||||
M = WaveManifold()
|
||||
mode = _e(1)
|
||||
psi = _e(2)
|
||||
residual, energy = M.compute_spectral_leakage(psi, [mode])
|
||||
assert float(energy) > 0.1
|
||||
assert float(np.linalg.norm(residual)) > 0.1
|
||||
|
||||
|
||||
def test_spectral_leakage_is_metric_exact_not_euclidean():
|
||||
"""Projection uses CGA metric, not Euclidean Gram-Schmidt.
|
||||
|
||||
Same load-bearing pin as surprise metric projection: b = 2*e1 + e5,
|
||||
x = e1 → metric coeff 2/3, Euclidean 2/5.
|
||||
"""
|
||||
from algebra.cga import cga_inner
|
||||
|
||||
M = WaveManifold()
|
||||
b = 2.0 * _e(1) + _e(5)
|
||||
x = _e(1)
|
||||
residual, _ = M.compute_spectral_leakage(x, [b])
|
||||
|
||||
c_metric = cga_inner(b, x) / cga_inner(b, b)
|
||||
assert np.allclose(residual, x - c_metric * b, atol=1e-10)
|
||||
|
||||
c_eucl = float(np.dot(b, x)) / float(np.dot(b, b))
|
||||
assert not np.allclose(residual, x - c_eucl * b, atol=1e-6)
|
||||
|
||||
|
||||
# --- W3: wave polar analogy ------------------------------------------------
|
||||
|
||||
|
||||
def test_wave_polar_recovers_known_sandwich_rotor():
|
||||
"""ψ_B = R ψ_A ~R ⇒ polar extract recovers R (up to global sign)."""
|
||||
M = WaveManifold()
|
||||
psi_A = _unit_rotor(0.15, plane=6)
|
||||
R_true = _unit_rotor(0.55, plane=10)
|
||||
psi_B = versor_apply(R_true, psi_A)
|
||||
|
||||
R_hat = M.wave_analogical_polar(psi_A, psi_B)
|
||||
assert R_hat.shape == (N_COMPONENTS,)
|
||||
assert versor_condition(R_hat) < _CLOSURE
|
||||
|
||||
# Recovered map should send A → B under sandwich
|
||||
mapped = versor_apply(R_hat, psi_A)
|
||||
err = float(np.linalg.norm(mapped - psi_B))
|
||||
# Global sign ambiguity of rotors: also try -R
|
||||
err_neg = float(np.linalg.norm(versor_apply(-R_hat, psi_A) - psi_B))
|
||||
assert min(err, err_neg) < 1e-5
|
||||
|
||||
|
||||
# --- W4: chiral spinor charge ----------------------------------------------
|
||||
|
||||
|
||||
def test_chiral_charge_conserved_under_left_spinor_step():
|
||||
"""Q = ⟨ψ I ~ψ⟩_0 conserved under unitary left multiply (odd-capable ψ)."""
|
||||
M = WaveManifold()
|
||||
psi = _e(1) + 0.3 * _e(3) + 0.1 * _unit_rotor(0.2, plane=6)
|
||||
R = _unit_rotor(0.4, plane=7)
|
||||
|
||||
q0 = M.chiral_charge(psi)
|
||||
psi_next = M.left_spinor_step(psi, R)
|
||||
q1 = M.chiral_charge(psi_next)
|
||||
assert abs(q0 - q1) < 1e-9
|
||||
|
||||
|
||||
def test_chiral_charge_honest_on_even_unit_versor():
|
||||
"""Even unit versor: chiral readout is structural ~0 (does not revive #19 gate)."""
|
||||
M = WaveManifold()
|
||||
psi = _unit_rotor(0.9, plane=11)
|
||||
q = M.chiral_charge(psi)
|
||||
assert abs(float(q)) < 1e-9
|
||||
|
||||
|
||||
# --- Containment / determinism ---------------------------------------------
|
||||
|
||||
|
||||
def test_wave_manifold_determinism():
|
||||
M = WaveManifold()
|
||||
psi = _unit_rotor(0.2, plane=6)
|
||||
R = _unit_rotor(0.1, plane=7)
|
||||
a = M.sandwich_step(psi, R)
|
||||
b = M.sandwich_step(psi, R)
|
||||
assert np.array_equal(a, b)
|
||||
|
||||
|
||||
def test_wave_manifold_module_does_not_import_teaching():
|
||||
"""Physics boundary: wave_manifold must not import teaching (discovery is out)."""
|
||||
import ast
|
||||
from pathlib import Path
|
||||
|
||||
path = Path(wave_manifold.__file__)
|
||||
tree = ast.parse(path.read_text())
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
for alias in node.names:
|
||||
assert not alias.name.startswith("teaching")
|
||||
if isinstance(node, ast.ImportFrom) and node.module:
|
||||
assert not node.module.startswith("teaching")
|
||||
|
||||
|
||||
# --- Slice 2: operator subsumption (no parallel path) ----------------------
|
||||
|
||||
|
||||
def test_surprise_residual_delegates_to_wave_spectral_leakage():
|
||||
"""32-vec surprise residual matches WaveManifold.compute_spectral_leakage."""
|
||||
from core.physics.surprise import surprise_residual
|
||||
|
||||
M = WaveManifold()
|
||||
mode = _e(1) + 0.5 * _e(3)
|
||||
mode = mode / float(np.linalg.norm(mode))
|
||||
x = 0.7 * mode + 0.4 * _e(2)
|
||||
B = mode.reshape(N_COMPONENTS, 1)
|
||||
sur_vec, sur_n = surprise_residual(x, B)
|
||||
leak_vec, leak_n = M.compute_spectral_leakage(x, [mode])
|
||||
assert np.allclose(sur_vec, leak_vec, atol=1e-12)
|
||||
assert abs(sur_n - leak_n) < 1e-12
|
||||
|
||||
|
||||
def test_coherence_residual_delegates_to_wave_unitary():
|
||||
"""GoldTether coherence_residual is WaveManifold.measure_unitary_residual."""
|
||||
from core.physics.goldtether import coherence_residual
|
||||
|
||||
M = WaveManifold()
|
||||
psi = _unit_rotor(0.42, plane=8)
|
||||
assert abs(coherence_residual(psi) - M.measure_unitary_residual(psi)) < 1e-15
|
||||
|
||||
|
||||
def test_conformal_procrustes_single_field_uses_wave_polar():
|
||||
"""Single non-null field Procrustes recovers the same conjugator as wave polar."""
|
||||
from core.physics.dynamic_manifold import conformal_procrustes
|
||||
|
||||
M = WaveManifold()
|
||||
psi_A = _unit_rotor(0.15, plane=6)
|
||||
R_true = _unit_rotor(0.55, plane=10)
|
||||
psi_B = versor_apply(R_true, psi_A)
|
||||
V_proc, res = conformal_procrustes(psi_A, psi_B)
|
||||
V_wave = M.wave_analogical_polar(psi_A, psi_B)
|
||||
# Both must sandwich A → B; residual small.
|
||||
assert res < 1e-5
|
||||
err_p = min(
|
||||
float(np.linalg.norm(versor_apply(V_proc, psi_A) - psi_B)),
|
||||
float(np.linalg.norm(versor_apply(-V_proc, psi_A) - psi_B)),
|
||||
)
|
||||
err_w = min(
|
||||
float(np.linalg.norm(versor_apply(V_wave, psi_A) - psi_B)),
|
||||
float(np.linalg.norm(versor_apply(-V_wave, psi_A) - psi_B)),
|
||||
)
|
||||
assert err_p < 1e-5
|
||||
assert err_w < 1e-5
|
||||
|
||||
|
||||
def test_wave_field_conjugacy_multi_pair_thin_wrap():
|
||||
"""Multi-pair field conjugacy is available on WaveManifold (Slice 3 thin wrap)."""
|
||||
from core.physics.dynamic_manifold import conformal_procrustes
|
||||
|
||||
M = WaveManifold()
|
||||
R = _unit_rotor(0.4, plane=9)
|
||||
sources = [_unit_rotor(0.1 * (i + 1), plane=6) for i in range(3)]
|
||||
targets = [versor_apply(R, s) for s in sources]
|
||||
V, engine_r = M.wave_field_conjugacy(sources, targets)
|
||||
assert V.shape == (N_COMPONENTS,)
|
||||
assert versor_condition(V) < _CLOSURE
|
||||
assert engine_r < 1e-4
|
||||
# Sequence Procrustes uses the same wave conjugacy path.
|
||||
V2, res2 = conformal_procrustes(sources, targets)
|
||||
assert res2 < 1e-4
|
||||
for s, t in zip(sources, targets):
|
||||
err = min(
|
||||
float(np.linalg.norm(versor_apply(V2, s) - t)),
|
||||
float(np.linalg.norm(versor_apply(-V2, s) - t)),
|
||||
)
|
||||
assert err < 1e-4
|
||||
|
||||
|
||||
def test_resonant_recall_picks_registered_mode():
|
||||
"""Standing-wave registry: query locks onto the matching registered mode."""
|
||||
M = WaveManifold()
|
||||
a = _unit_rotor(0.2, plane=6)
|
||||
b = _unit_rotor(0.9, plane=7)
|
||||
M.register_resonant_mode(a)
|
||||
M.register_resonant_mode(b)
|
||||
mode, energy, idx = M.resonant_recall(b)
|
||||
assert idx == 1
|
||||
assert energy > 0.5
|
||||
assert np.allclose(mode, b, atol=1e-12)
|
||||
|
||||
|
||||
def test_resonant_recall_empty_refused():
|
||||
"""No confabulated recall from an empty mode set."""
|
||||
M = WaveManifold()
|
||||
with pytest.raises(ValueError, match="empty mode set"):
|
||||
M.resonant_recall(_unit_rotor(0.3, plane=6))
|
||||
|
||||
|
||||
def test_core_ha_package_absent():
|
||||
"""core_ha deprecation: no live package tree in this repo (W6 hygiene)."""
|
||||
import importlib.util
|
||||
|
||||
assert importlib.util.find_spec("core_ha") is None
|
||||
Loading…
Reference in a new issue