fix(algebra): P11a physics hot paths via algebra.backend (Rust-ready)
Some checks failed
smoke / smoke (-m "not quarantine") (pull_request) Successful in 5m57s
lane-shas / verify pinned lane SHAs (pull_request) Failing after 1h43m22s

Stop wave/Third-Door physics from bypassing native dispatch:

- Route geometric_product / versor_apply / versor_condition / cga_inner
  through algebra.backend in wave_manifold, goldtether, trajectory,
  dynamic_manifold, surprise, holographic_vault, atlas_packing,
  biography, self_authorship.
- Backend: dtype-aware Rust use — f32 workloads use core_rs; f64 wave
  residual pins keep Python SOT until f64 GP parity exists. Coerce
  arrays for PyO3 bindings; fail soft to Python.
- AST hygiene pin: tests/test_physics_backend_dispatch_hygiene.py
- Docs: RUST.md, runtime_contracts, fidelity (ADR-0235 / UMA hygiene).

Verified: wave + cohesion suites green default and CORE_BACKEND=rust
(with core_rs built). MLX still exploratory off-serve.
This commit is contained in:
Shay 2026-07-14 20:23:08 -07:00
parent db6430ed4e
commit 44f7258b16
14 changed files with 208 additions and 25 deletions

View file

@ -48,9 +48,36 @@ def _build_cga_inner_metric() -> np.ndarray:
_CGA_INNER_METRIC: np.ndarray = _build_cga_inner_metric()
def _f32_1d32(x: np.ndarray) -> np.ndarray:
"""Contiguous f32 (32,) for core_rs PyReadonlyArray1 bindings."""
return np.ascontiguousarray(
np.asarray(x, dtype=np.float32).reshape(-1)[:32], dtype=np.float32
)
def _is_f32_workload(*arrays: np.ndarray) -> bool:
"""True when all arrays are float32 (Rust f32 kernel is parity-safe).
float64 wave residual pins require Python SOT (or future f64 Rust GP).
Forcing f64f32 would break 1e-9 chiral / leakage pins (ADR-0241).
"""
return all(np.asarray(a).dtype == np.float32 for a in arrays)
def geometric_product(A: np.ndarray, B: np.ndarray) -> np.ndarray:
if _RUST:
return np.asarray(_rs.geometric_product(A, B), dtype=np.float32)
"""Cl(4,1) geometric product via Rust f32 when enabled, else Python.
float64 inputs always use the pure-Python product (semantic SOT for
wave-field residual math). float32 field-graph workloads get Rust.
"""
if _RUST and _is_f32_workload(A, B):
try:
return np.asarray(
_rs.geometric_product(_f32_1d32(A), _f32_1d32(B)),
dtype=np.float32,
)
except (AttributeError, TypeError, ValueError, Exception):
pass
from algebra.cl41 import geometric_product as _gp
return _gp(A, B)
@ -67,25 +94,34 @@ def versor_apply(V: np.ndarray, F: np.ndarray) -> np.ndarray:
"""
if _RUST:
try:
Vc = np.ascontiguousarray(V, dtype=np.float64)
Fc = np.ascontiguousarray(F, dtype=np.float64)
return np.asarray(_rs.versor_apply_with_closure_f64(Vc, Fc), dtype=np.float64)
except (AttributeError, Exception):
Vc = np.ascontiguousarray(V, dtype=np.float64).reshape(-1)[:32]
Fc = np.ascontiguousarray(F, dtype=np.float64).reshape(-1)[:32]
return np.asarray(
_rs.versor_apply_with_closure_f64(Vc, Fc), dtype=np.float64
)
except (AttributeError, TypeError, ValueError, Exception):
pass
from algebra.versor import versor_apply as _va
return _va(V, F)
def versor_condition(F: np.ndarray) -> float:
if _RUST:
return float(_rs.versor_condition(F))
"""Versor residual. Rust f32 path only for float32 inputs (see GP note)."""
if _RUST and _is_f32_workload(F):
try:
return float(_rs.versor_condition(_f32_1d32(F)))
except (AttributeError, TypeError, ValueError, Exception):
pass
from algebra.versor import versor_condition as _vc
return _vc(F)
def cga_inner(X: np.ndarray, Y: np.ndarray) -> float:
if _RUST:
return float(_rs.cga_inner(X, Y))
if _RUST and _is_f32_workload(X, Y):
try:
return float(_rs.cga_inner(_f32_1d32(X), _f32_1d32(Y)))
except (AttributeError, TypeError, ValueError, Exception):
pass
from algebra.cga import cga_inner as _ci
return _ci(X, Y)

View file

@ -22,7 +22,8 @@ from typing import Sequence
import numpy as np
from algebra.cga import cga_inner, embed_point
from algebra.backend import cga_inner
from algebra.cga import embed_point
from core.physics.wave_manifold import WaveManifold
PHI = (1.0 + math.sqrt(5.0)) / 2.0

View file

@ -16,9 +16,10 @@ from typing import Any, Sequence
import numpy as np
from algebra.backend import versor_condition
from algebra.cl41 import N_COMPONENTS
from algebra.holonomy import holonomy_encode, holonomy_similarity
from algebra.versor import unitize_versor, versor_condition
from algebra.versor import unitize_versor
from core.physics.wave_manifold import WaveManifold
_CLOSURE_TOL = 1e-6

View file

@ -16,8 +16,9 @@ from typing import Optional, Sequence, Tuple, Union
import numpy as np
from algebra.backend import geometric_product, versor_condition
from algebra.cga import is_null
from algebra.cl41 import N_COMPONENTS, geometric_product, grade_project, reverse
from algebra.cl41 import N_COMPONENTS, grade_project, reverse
from algebra.null_point import (
NullPointRecoveryError,
dilator,
@ -26,7 +27,6 @@ from algebra.null_point import (
translator,
)
from algebra.rotor import rotor_power, word_transition_rotor
from algebra.versor import versor_condition
_CLOSURE_TOL = 1e-6
_NEAR_ZERO = 1e-12

View file

@ -28,9 +28,10 @@ from typing import Any, Literal, Optional, Tuple
import numpy as np
from algebra.cl41 import N_COMPONENTS, geometric_product, reverse
from algebra.backend import geometric_product, versor_condition
from algebra.cl41 import N_COMPONENTS, reverse
from algebra.rotor import rotor_power, word_transition_rotor
from algebra.versor import versor_condition, versor_unit_residual
from algebra.versor import versor_unit_residual
from core.physics.wave_manifold import WaveManifold
_CLOSURE_TOL = 1e-6

View file

@ -24,8 +24,8 @@ from typing import Any, Optional
import numpy as np
from algebra.backend import versor_condition
from algebra.cl41 import N_COMPONENTS
from algebra.versor import versor_condition
from core.physics.wave_manifold import WaveManifold
from teaching.epistemic import EpistemicStatus
from vault.store import VaultStore, _parse_entry_status, _status_admits

View file

@ -9,8 +9,8 @@ from typing import Any, Mapping, Sequence
import numpy as np
from algebra.backend import versor_condition
from algebra.cl41 import N_COMPONENTS
from algebra.versor import versor_condition
from core.physics.dynamic_manifold import conformal_procrustes
from core.physics.goldtether import GoldTetherMonitor, coherence_residual
from core.physics.surprise import dual_procrustes_surprise, surprise_residual

View file

@ -39,9 +39,8 @@ from typing import Optional, Sequence, Tuple, Union
import numpy as np
from algebra.cga import cga_inner
from algebra.backend import cga_inner, versor_condition
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

View file

@ -22,8 +22,9 @@ from typing import Sequence
import numpy as np
from algebra.cl41 import N_COMPONENTS, geometric_product, reverse
from algebra.versor import versor_condition, versor_unit_residual
from algebra.backend import geometric_product, versor_condition
from algebra.cl41 import N_COMPONENTS, reverse
from algebra.versor import versor_unit_residual
_CLOSURE_TOL = 1e-6
_DEFAULT_EPS_TRAJECTORY = 1e-5

View file

@ -12,6 +12,12 @@ Continuous multivector wave fields ψ ∈ ℝ³² under:
Algebra-native only (algebra/*). No scipy-as-truth. No teaching/vault imports.
Off-serving until explicit gates; dual-checked unitary residual.
**Backend dispatch (P11a / ADR-0235):** Cl(4,1) hot ops go through
``algebra.backend`` so ``CORE_BACKEND=rust`` can accelerate them when
``core_rs`` is built. Python remains semantic source of truth when Rust
is unset. Helpers without a Rust path (``reverse``, ``scalar_part``,
``versor_unit_residual``) stay on pure algebra modules.
"""
from __future__ import annotations
@ -20,9 +26,14 @@ 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
from algebra.backend import (
cga_inner,
geometric_product,
versor_apply,
versor_condition,
)
from algebra.cl41 import N_COMPONENTS, reverse, scalar_part
from algebra.versor import versor_unit_residual
_CLOSURE_TOL = 1e-6
_NEAR_ZERO = 1e-12

View file

@ -1,5 +1,31 @@
# Rust Extension (core-rs)
## Physics hot-path hygiene (P11a)
Third-Door / ADR-0241 physics modules must import Cl(4,1) multiplies and
closure residual helpers from **`algebra.backend`**, not directly from
`algebra.cl41` / `algebra.versor` / `algebra.cga` for:
- `geometric_product`
- `versor_apply`
- `versor_condition`
- `cga_inner`
Pinned by `tests/test_physics_backend_dispatch_hygiene.py`.
```bash
# Default: pure Python (semantic SOT)
uv run pytest tests/test_adr_0241_wave_manifold.py -q
# Apple Silicon / native acceleration (after maturin build)
export CORE_BACKEND=rust
uv run --with maturin maturin develop --release --manifest-path core-rs/Cargo.toml
uv run python -c "from algebra.backend import using_rust; assert using_rust()"
```
MLX remains an **exploratory** UMA lane (ADR-0235); not required for serving.
## Why Rust
The active Rust extension is an opt-in native substrate for parity-gated hot

View file

@ -306,6 +306,7 @@ PY
| Fibonacci-word scheduler (V4) | 🟢 `fibonacci_word_schedule` (telemetry only) |
| Fibonacci anyons (V5) | 🟢 quarantine package only; zero production imports |
| Sensorium → ψ feed (I-04) | 🟢 `sensorium_wave_feed` (fake packets + real \(\rho\)) |
| Physics Cl(4,1) via `algebra.backend` (P11a) | 🟢 wave/goldtether/trajectory/procrustes/surprise/vault/packing; AST pin; Rust when `CORE_BACKEND=rust` |
| Contemplation Trace A SPECULATIVE holographic seal (P9) | 🟢 `core/contemplation/wave_seam.py` (hypothesis vs COHERENT evidence) |
| Energy boundary + multi-scale τ (P10 Trace B) | 🟢 `wave_energy_boundary` (wave residual → energy/trajectory; τ_n=F_n·τ_0; E0E1 crystallization) |

View file

@ -919,3 +919,17 @@ Acceptance inventory: `docs/audit/adr_0241_cohesion_acceptance_checklist.md`.
Every wave transition still obeys `versor_condition(F) < 1e-6`. Residual breach
is **fail-closed** — no hot-path nearest-versor drift repair.
### Algebra backend / Apple Silicon (P11a hygiene)
Cl(4,1) hot ops in physics (`geometric_product`, `versor_apply`,
`versor_condition`, `cga_inner`) must import from **`algebra.backend`**, not
direct pure-algebra modules. Pin: `tests/test_physics_backend_dispatch_hygiene.py`.
| Mode | How |
|------|-----|
| Default | Pure Python (semantic source of truth) |
| Native accel | `CORE_BACKEND=rust` + `core_rs` built (`maturin develop --release -m core-rs/Cargo.toml`) |
| float64 wave residual pins | Stay on Python product when inputs are f64 (Rust f32 GP not parity-safe for 1e-9 pins yet) |
| float32 field graphs | Rust f32 GP / residual when enabled |
| MLX / UMA | Exploratory (ADR-0235); not serving until parity gates |

View file

@ -0,0 +1,92 @@
"""P11a — physics hot paths must dispatch Cl(4,1) ops via algebra.backend.
Prevents silent drift back to pure-Python-only imports for geometric_product /
versor_apply / cga_inner / versor_condition in wave-field and related modules.
Python remains default when CORE_BACKEND is unset; Rust accelerates when
CORE_BACKEND=rust and core_rs is built (ADR-0235).
"""
from __future__ import annotations
import ast
from pathlib import Path
_ROOT = Path(__file__).resolve().parents[1]
_PHYSICS = _ROOT / "core" / "physics"
# Modules that perform Cl(4,1) multiplies / residuals in the cognitive physics
# layer — must take the load-bearing ops from algebra.backend.
_BACKEND_HOT_MODULES = (
"wave_manifold.py",
"goldtether.py",
"trajectory_invariants.py",
"dynamic_manifold.py",
"surprise.py",
"holographic_vault.py",
"atlas_packing.py",
"biography.py",
"self_authorship.py",
)
# Names that must not be imported from algebra.cl41 / algebra.versor / algebra.cga
# in those modules (use backend instead).
_BANNED_FROM_PURE = frozenset(
{
"geometric_product",
"versor_apply",
"versor_condition",
"cga_inner",
}
)
def _imports_from(module: str, path: Path) -> set[str]:
tree = ast.parse(path.read_text(encoding="utf-8"))
names: set[str] = set()
for node in ast.walk(tree):
if isinstance(node, ast.ImportFrom) and node.module == module:
for alias in node.names:
names.add(alias.name)
return names
def test_hot_modules_import_backend_for_algebra_ops():
for name in _BACKEND_HOT_MODULES:
path = _PHYSICS / name
assert path.is_file(), f"missing {path}"
backend_names = _imports_from("algebra.backend", path)
# Each file should pull at least one of the dispatch ops.
assert backend_names & _BANNED_FROM_PURE, (
f"{name} must import Cl(4,1) hot ops from algebra.backend; "
f"got backend imports {sorted(backend_names)}"
)
def test_hot_modules_do_not_import_hot_ops_from_pure_algebra():
pure_modules = ("algebra.cl41", "algebra.versor", "algebra.cga")
for name in _BACKEND_HOT_MODULES:
path = _PHYSICS / name
for mod in pure_modules:
pure_names = _imports_from(mod, path)
offenders = pure_names & _BANNED_FROM_PURE
assert not offenders, (
f"{name} imports {sorted(offenders)} from {mod}; "
"route through algebra.backend for CORE_BACKEND=rust"
)
def test_wave_manifold_uses_backend_geometric_product_and_versor_apply():
path = _PHYSICS / "wave_manifold.py"
backend = _imports_from("algebra.backend", path)
assert "geometric_product" in backend
assert "versor_apply" in backend
assert "versor_condition" in backend
assert "cga_inner" in backend
def test_backend_using_rust_api_exists():
from algebra.backend import using_rust
# Default env: Python path (no silent force of Rust).
assert using_rust() is False or using_rust() is True # bool only
assert isinstance(using_rust(), bool)