feat(adr-0242): macro-phase V2–V5 + sensorium feed (Drive gap close)
Parallel implementation of remaining Drive ADR-0242 vectors on PR #38: D3 V2 — multi_scale_energy: E_n(t)=E0·exp(-age/(F_n·τ0)), dyadic baseline, comparative helpers; not production FieldEnergyOperator default. D5 V4 — fibonacci_word_schedule: W0=B,W1=A,W_{n+1}=W_n W_{n-1}; telemetry only. D6 V5 — algebra/topological_reasoning quarantine + production AST pin. D7 — sensorium_wave_feed: packet→ψ, superpose, ρ via WaveManifold only. Serve quarantine extended for all new modules. Fidelity + ADR-0242 + runtime_contracts honesty pass. Suite: 118 related tests green. Single macro-phase commit per plan policy (no micro-PRs).
This commit is contained in:
parent
bbd3b6678f
commit
db6430ed4e
14 changed files with 1221 additions and 17 deletions
82
algebra/topological_reasoning/README.md
Normal file
82
algebra/topological_reasoning/README.md
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# Topological Reasoning — ADR-0242 Vector 5 (D6) Research Quarantine
|
||||
|
||||
**Status**: 🔴 RESEARCH ONLY — blocked from production
|
||||
**Authority**: ADR-0242 Vector 5 (topological anyon / braid holonomy)
|
||||
**Related**: `docs/adr/ADR-0242-atlas-packing-and-fibonacci.md`,
|
||||
`docs/analysis/fibonacci_applications_in_core_substrate.md` §2.2
|
||||
|
||||
---
|
||||
|
||||
## Purpose
|
||||
|
||||
Isolated study surface for Fibonacci anyon fusion and braid holonomy as a
|
||||
**topological composition research program**. The canonical fusion rule under
|
||||
study is:
|
||||
|
||||
\[
|
||||
\tau \otimes \tau = \mathbf{1} \oplus \tau
|
||||
\]
|
||||
|
||||
This package exists so research stubs, notes, and future proof-carrying
|
||||
algebra can land **without** contaminating the live cognitive path:
|
||||
|
||||
```text
|
||||
listen → comprehend → recall → think → articulate → learn → replay
|
||||
```
|
||||
|
||||
## Hard quarantine (do not violate)
|
||||
|
||||
Until algebraic **and** numerical proofs exist, and until an explicit ADR
|
||||
promotion gate is Accepted by human review, this package is **BLOCKED** from:
|
||||
|
||||
| Surface | Rule |
|
||||
|---------|------|
|
||||
| Production runtime | No imports from serve / hot path |
|
||||
| `chat/` | Not for import by chat or `chat/runtime.py` |
|
||||
| Serve / FFI | Must not enter serve or FFI bindings |
|
||||
| `core/physics/` | Not a production physics operator |
|
||||
| `generate/` | Not for articulation / planner / cognitive turns |
|
||||
| `vault/` | Not for vault standing, seal, or COHERENT promotion |
|
||||
| `teaching/` | Not for reviewed teaching or pack mutation |
|
||||
| GoldTether / κ paths | Not for production residual / κ optimization |
|
||||
| `algebra` public surface | Not re-exported from `algebra/__init__.py` |
|
||||
|
||||
Architectural pin: `tests/test_adr_0242_topological_quarantine.py` scans
|
||||
production packages for any import of `topological_reasoning` and must find
|
||||
none.
|
||||
|
||||
## Sovereignty (ADR-0242)
|
||||
|
||||
Fibonacci / topological operators may **never** dictate proposition truth,
|
||||
safety policy, identity, or authorize autonomous COHERENT promotion. Active
|
||||
reasoning remains governed by versor closure, exact CRDT recall, and
|
||||
human-gated review.
|
||||
|
||||
## What is allowed here
|
||||
|
||||
- Research constants and docstring contracts (e.g. fusion rule labels)
|
||||
- Future proof sketches, numerical experiments under tests/evals only when
|
||||
explicitly gated
|
||||
- Documentation of open questions and proof obligations
|
||||
|
||||
## What is not allowed here
|
||||
|
||||
- Production logic wired into cognition, serve, or vault truth
|
||||
- Stochastic / approximate substitutes for exact CGA recall
|
||||
- Hidden normalization or drift repair outside owned algebra boundaries
|
||||
- Silent promotion of research results into COHERENT standing
|
||||
|
||||
## API note
|
||||
|
||||
The package may expose minimal docstring / constant stubs (e.g. `FUSION_RULE`).
|
||||
No production operators, no side effects, no I/O.
|
||||
|
||||
## Promotion path
|
||||
|
||||
1. Algebraic + numerical proofs land and are reviewable.
|
||||
2. ADR update records evidence and remaining risks.
|
||||
3. Human Accept of a production promotion gate.
|
||||
4. Only then may a **separate**, reviewed integration surface be designed —
|
||||
still subject to serve quarantine and sovereignty invariant.
|
||||
|
||||
Until then: this directory is a quarantine box, not a feature.
|
||||
21
algebra/topological_reasoning/__init__.py
Normal file
21
algebra/topological_reasoning/__init__.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
"""ADR-0242 V5 (D6) — topological anyon / braid holonomy research quarantine.
|
||||
|
||||
Fibonacci anyon fusion research surface. BLOCKED from production, serve, FFI,
|
||||
chat/runtime, vault COHERENT, teaching mutation, and GoldTether production
|
||||
paths until algebraic and numerical proofs exist (see package README).
|
||||
|
||||
This module intentionally re-exports nothing into ``algebra``'s public API
|
||||
and must not be imported by production packages.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
# Canonical Fibonacci anyon fusion rule under study (research label only).
|
||||
# τ ⊗ τ = 1 ⊕ τ — not a production operator; no evaluation semantics.
|
||||
FUSION_RULE: str = "tau_otimes_tau_eq_1_oplus_tau"
|
||||
"""Research label for the Fibonacci anyon fusion rule τ⊗τ = 1⊕τ.
|
||||
|
||||
Docstring / constant only. Does not implement fusion, braiding, or holonomy.
|
||||
"""
|
||||
|
||||
__all__ = ["FUSION_RULE"]
|
||||
|
|
@ -101,6 +101,13 @@ from core.physics.fibonacci_search import (
|
|||
fibonacci_section_search,
|
||||
propose_kappa_from_search,
|
||||
)
|
||||
from core.physics.multi_scale_energy import (
|
||||
comparative_residual_separation,
|
||||
dyadic_tau_schedule,
|
||||
multi_scale_energy_for_schedule,
|
||||
multi_scale_energy_vector,
|
||||
schedule_mid_span_fraction,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"SalienceOperator", "SalienceMap", "FieldRegion",
|
||||
|
|
@ -150,4 +157,9 @@ __all__ = [
|
|||
"fibonacci_section_search",
|
||||
"propose_kappa_from_search",
|
||||
"propose_kappa_line_search",
|
||||
"comparative_residual_separation",
|
||||
"dyadic_tau_schedule",
|
||||
"multi_scale_energy_for_schedule",
|
||||
"multi_scale_energy_vector",
|
||||
"schedule_mid_span_fraction",
|
||||
]
|
||||
|
|
|
|||
106
core/physics/fibonacci_word_schedule.py
Normal file
106
core/physics/fibonacci_word_schedule.py
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
"""core.physics.fibonacci_word_schedule — ADR-0242 V4 (D5) observability choreography.
|
||||
|
||||
Fibonacci-word scheduler for telemetry / sealed-holdout sampling only.
|
||||
|
||||
Drive recurrence
|
||||
----------------
|
||||
W_0 = B
|
||||
W_1 = A
|
||||
W_{n+1} = W_n W_{n-1} (string concatenation)
|
||||
|
||||
where:
|
||||
* A — low-cost local measurement
|
||||
* B — high-cost cross-band check
|
||||
|
||||
Length formula
|
||||
--------------
|
||||
With the standard Fibonacci sequence F_0 = 0, F_1 = 1, F_2 = 1, F_3 = 2, …:
|
||||
|
||||
|W_n| = F_{n+1} for n >= 0
|
||||
(equivalently |W_0|=1, |W_1|=1, |W_2|=2, |W_3|=3, |W_4|=5, …)
|
||||
|
||||
Sovereignty (ADR-0242 absolute invariant)
|
||||
----------------------------------------
|
||||
This module is **outside the cognitive truth path**. It schedules
|
||||
observability / telemetry actions only. It MUST NOT:
|
||||
|
||||
* mutate vault standing or call VaultStore.store
|
||||
* mutate field state or authorize COHERENT promotion
|
||||
* dictate proposition truth, safety policy, or identity
|
||||
* be imported from the serve hot path (A-04 quarantine)
|
||||
|
||||
Pure and deterministic: no I/O, no randomness, no field/vault side effects.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
from typing import Iterator
|
||||
|
||||
|
||||
class Action(str, Enum):
|
||||
"""Observability action labels (telemetry only; not cognitive truth)."""
|
||||
|
||||
A = "A" # low-cost local measurement
|
||||
B = "B" # high-cost cross-band check
|
||||
|
||||
|
||||
def _require_nonneg_int(n: int, *, name: str = "n") -> int:
|
||||
if not isinstance(n, int) or isinstance(n, bool):
|
||||
raise TypeError(f"{name} must be an int, got {type(n).__name__}")
|
||||
if n < 0:
|
||||
raise ValueError(f"{name} must be non-negative, got {n}")
|
||||
return n
|
||||
|
||||
|
||||
def fibonacci_word(n: int) -> str:
|
||||
"""Return the Fibonacci word W_n as a string of 'A'/'B' characters.
|
||||
|
||||
W_0 = \"B\", W_1 = \"A\", W_{k+1} = W_k + W_{k-1}.
|
||||
Length |W_n| = F_{n+1} with F_0=0, F_1=1.
|
||||
"""
|
||||
n = _require_nonneg_int(n)
|
||||
if n == 0:
|
||||
return Action.B.value
|
||||
if n == 1:
|
||||
return Action.A.value
|
||||
# Iterative doubling: O(n) concatenations, O(F_{n+1}) total chars.
|
||||
prev = Action.B.value # W_0
|
||||
curr = Action.A.value # W_1
|
||||
for _ in range(2, n + 1):
|
||||
prev, curr = curr, curr + prev
|
||||
return curr
|
||||
|
||||
|
||||
def schedule_actions(n: int) -> tuple[str, ...]:
|
||||
"""Return the action sequence for W_n as an immutable tuple of \"A\"/\"B\".
|
||||
|
||||
Same recurrence and length as :func:`fibonacci_word`; form convenient for
|
||||
iteration without splitting a string.
|
||||
"""
|
||||
word = fibonacci_word(n)
|
||||
return tuple(word)
|
||||
|
||||
|
||||
def iter_schedule_actions(n: int) -> Iterator[str]:
|
||||
"""Iterate actions of W_n without building an intermediate tuple."""
|
||||
yield from fibonacci_word(n)
|
||||
|
||||
|
||||
def word_length(n: int) -> int:
|
||||
"""Return |W_n| = F_{n+1} (F_0=0, F_1=1) without building the word."""
|
||||
n = _require_nonneg_int(n)
|
||||
# F_{n+1}: a,b walk F_0=0, F_1=1 for (n+1) steps → a = F_{n+1}
|
||||
a, b = 0, 1
|
||||
for _ in range(n + 1):
|
||||
a, b = b, a + b
|
||||
return a
|
||||
|
||||
|
||||
__all__ = [
|
||||
"Action",
|
||||
"fibonacci_word",
|
||||
"schedule_actions",
|
||||
"iter_schedule_actions",
|
||||
"word_length",
|
||||
]
|
||||
178
core/physics/multi_scale_energy.py
Normal file
178
core/physics/multi_scale_energy.py
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
"""ADR-0242 V2 — multi-scale temporal energy basis (research prototype).
|
||||
|
||||
Drive formula:
|
||||
|
||||
E_n(t) = E_n(t_0) * exp(-(t - t_0) / (F_n * τ_0))
|
||||
|
||||
with Fibonacci scale factors F_n (n ≥ 1) and base time constant τ_0.
|
||||
|
||||
This module is **research-only**:
|
||||
- pure helpers for comparative study vs a dyadic (2^{n-1} τ_0) baseline
|
||||
- **not** a production default inside ``FieldEnergyOperator.compute``
|
||||
- serve-quarantined (A-04): must not be imported from ``chat/runtime.py``
|
||||
|
||||
Reuses ``fibonacci_number`` / ``fibonacci_tau_schedule`` — no parallel Fibonacci.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from math import exp, isfinite
|
||||
from typing import Sequence
|
||||
|
||||
from core.physics.fibonacci_search import fibonacci_number
|
||||
from core.physics.wave_energy_boundary import fibonacci_tau_schedule
|
||||
|
||||
_DEFAULT_TAU0 = 1.0
|
||||
|
||||
|
||||
def _validate_tau0(tau0: float) -> float:
|
||||
t0 = float(tau0)
|
||||
if not (t0 > 0.0) or not isfinite(t0):
|
||||
raise ValueError("tau0 must be a positive finite scalar")
|
||||
return t0
|
||||
|
||||
|
||||
def _validate_levels(levels: int) -> int:
|
||||
n = int(levels)
|
||||
if n < 1:
|
||||
raise ValueError("levels must be >= 1")
|
||||
return n
|
||||
|
||||
|
||||
def _validate_age(age: float) -> float:
|
||||
a = float(age)
|
||||
if a < 0.0 or not isfinite(a):
|
||||
raise ValueError("age must be a non-negative finite scalar")
|
||||
return a
|
||||
|
||||
|
||||
def _validate_e0(e0: float) -> float:
|
||||
e = float(e0)
|
||||
if not isfinite(e):
|
||||
raise ValueError("e0 must be a finite scalar")
|
||||
return e
|
||||
|
||||
|
||||
def dyadic_tau_schedule(
|
||||
tau0: float = _DEFAULT_TAU0,
|
||||
*,
|
||||
levels: int = 8,
|
||||
) -> tuple[float, ...]:
|
||||
"""Dyadic comparison baseline τ_n = 2^{n-1} · τ_0 for n = 1..levels.
|
||||
|
||||
ADR-0242 Phase 2 comparative hypothesis baseline (not a production default).
|
||||
"""
|
||||
t0 = _validate_tau0(tau0)
|
||||
n = _validate_levels(levels)
|
||||
return tuple(float(t0 * (2 ** (i - 1))) for i in range(1, n + 1))
|
||||
|
||||
|
||||
def multi_scale_energy_for_schedule(
|
||||
e0: float,
|
||||
age: float,
|
||||
taus: Sequence[float],
|
||||
) -> tuple[float, ...]:
|
||||
"""Apply E = e0 · exp(-age / τ) for each positive finite τ in ``taus``.
|
||||
|
||||
``age`` is (t − t_0). ``e0`` is the shared E_n(t_0) research default.
|
||||
"""
|
||||
e = _validate_e0(e0)
|
||||
a = _validate_age(age)
|
||||
if not taus:
|
||||
raise ValueError("taus must be non-empty")
|
||||
out: list[float] = []
|
||||
for raw in taus:
|
||||
tau = float(raw)
|
||||
if not (tau > 0.0) or not isfinite(tau):
|
||||
raise ValueError("each tau must be a positive finite scalar")
|
||||
out.append(float(e * exp(-a / tau)))
|
||||
return tuple(out)
|
||||
|
||||
|
||||
def multi_scale_energy_vector(
|
||||
e0: float,
|
||||
age: float,
|
||||
*,
|
||||
tau0: float = _DEFAULT_TAU0,
|
||||
levels: int = 8,
|
||||
) -> tuple[float, ...]:
|
||||
"""Fibonacci multi-scale energies E_n for n = 1..levels.
|
||||
|
||||
Drive form with shared E_n(t_0) = e0:
|
||||
|
||||
E_n = e0 * exp(-age / (F_n * tau0))
|
||||
|
||||
Equivalent to ``multi_scale_energy_for_schedule`` over
|
||||
``fibonacci_tau_schedule(tau0, levels=levels)``.
|
||||
"""
|
||||
t0 = _validate_tau0(tau0)
|
||||
n = _validate_levels(levels)
|
||||
# Explicit F_n path keeps the Drive formula visible at the callsite layer.
|
||||
e = _validate_e0(e0)
|
||||
a = _validate_age(age)
|
||||
return tuple(
|
||||
float(e * exp(-a / float(fibonacci_number(i) * t0)))
|
||||
for i in range(1, n + 1)
|
||||
)
|
||||
|
||||
|
||||
def comparative_residual_separation(
|
||||
e0: float,
|
||||
age: float,
|
||||
*,
|
||||
tau0: float = _DEFAULT_TAU0,
|
||||
levels: int = 8,
|
||||
) -> dict[str, object]:
|
||||
"""Deterministic Fibonacci vs dyadic multi-scale energy comparison.
|
||||
|
||||
Pure research helper — no I/O. Returns both schedules, both energy
|
||||
vectors, and per-index energy gaps (fib − dyadic). Promotion of
|
||||
Fibonacci multi-band energy into production requires evidence from
|
||||
this (or richer) comparative surface.
|
||||
"""
|
||||
t0 = _validate_tau0(tau0)
|
||||
n = _validate_levels(levels)
|
||||
fib_taus = fibonacci_tau_schedule(t0, levels=n)
|
||||
dyad_taus = dyadic_tau_schedule(t0, levels=n)
|
||||
fib_e = multi_scale_energy_for_schedule(e0, age, fib_taus)
|
||||
dyad_e = multi_scale_energy_for_schedule(e0, age, dyad_taus)
|
||||
gaps = tuple(float(f - d) for f, d in zip(fib_e, dyad_e, strict=True))
|
||||
return {
|
||||
"tau0": t0,
|
||||
"levels": n,
|
||||
"age": float(age),
|
||||
"e0": float(e0),
|
||||
"fibonacci_taus": fib_taus,
|
||||
"dyadic_taus": dyad_taus,
|
||||
"fibonacci_energies": fib_e,
|
||||
"dyadic_energies": dyad_e,
|
||||
"energy_gap_fib_minus_dyadic": gaps,
|
||||
}
|
||||
|
||||
|
||||
def schedule_mid_span_fraction(taus: Sequence[float], *, index: int | None = None) -> float:
|
||||
"""Fraction of max(τ) occupied by τ at mid (or given) index.
|
||||
|
||||
Used by comparative pins: Fibonacci mid-scale bands sit further along
|
||||
the normalized span than pure dyadic 2^{n-1} (slower φ-growth).
|
||||
"""
|
||||
if not taus:
|
||||
raise ValueError("taus must be non-empty")
|
||||
vals = tuple(float(t) for t in taus)
|
||||
for t in vals:
|
||||
if not (t > 0.0) or not isfinite(t):
|
||||
raise ValueError("each tau must be a positive finite scalar")
|
||||
peak = max(vals)
|
||||
i = len(vals) // 2 if index is None else int(index)
|
||||
if i < 0 or i >= len(vals):
|
||||
raise ValueError("index out of range for taus")
|
||||
return float(vals[i] / peak)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"comparative_residual_separation",
|
||||
"dyadic_tau_schedule",
|
||||
"multi_scale_energy_for_schedule",
|
||||
"multi_scale_energy_vector",
|
||||
"schedule_mid_span_fraction",
|
||||
]
|
||||
141
core/physics/sensorium_wave_feed.py
Normal file
141
core/physics/sensorium_wave_feed.py
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
"""D7 sensorium → ψ feed (I-04 boundary).
|
||||
|
||||
Thin construction-boundary adapter: modality surface packets become Cl(4,1)
|
||||
wave fields for algebraic multimodal resonance.
|
||||
|
||||
Real modality compilers remain in ``sensorium/*``. This module only standardizes
|
||||
the feed into the wave substrate:
|
||||
|
||||
* :class:`ModalityPacket` (or dict) — modality id + 32-float coefficients
|
||||
* :func:`compile_packet_to_psi` — validate / lift to shape ``(32,)``
|
||||
* :func:`superpose_packets` — ``ψ_total = Σ ψ_i``
|
||||
* :func:`phase_correlate` — delegates **only** to
|
||||
:meth:`WaveManifold.phase_correlation` (metric-exact ρ; no cosine / ANN)
|
||||
|
||||
Honest test fixtures via :func:`fake_deterministic_packet` use closed rotors
|
||||
from :func:`algebra.rotor.make_rotor_from_angle` when live compilers are not
|
||||
under test. That is a fixture, not a claim that audio/vision compilers ran.
|
||||
|
||||
Off-serve: must not be imported by ``chat/runtime.py`` (A-04 quarantine).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Mapping, Sequence, Union
|
||||
|
||||
import numpy as np
|
||||
|
||||
from algebra.cl41 import N_COMPONENTS
|
||||
from algebra.rotor import make_rotor_from_angle
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
|
||||
PacketLike = Union["ModalityPacket", Mapping[str, Any]]
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class ModalityPacket:
|
||||
"""Construction-boundary packet: modality tag + 32 Cl(4,1) coefficients.
|
||||
|
||||
After compile, the field has no modality concept (Logos recovery).
|
||||
``modality_id`` is provenance only.
|
||||
"""
|
||||
|
||||
modality_id: str
|
||||
coefficients: np.ndarray # shape (N_COMPONENTS,)
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
mid = str(self.modality_id).strip()
|
||||
if not mid:
|
||||
raise ValueError("modality_id must be non-empty")
|
||||
arr = np.asarray(self.coefficients, dtype=np.float64).reshape(-1)
|
||||
if arr.shape != (N_COMPONENTS,):
|
||||
raise ValueError(
|
||||
f"coefficients must have shape ({N_COMPONENTS},); got {arr.shape}"
|
||||
)
|
||||
object.__setattr__(self, "modality_id", mid)
|
||||
object.__setattr__(self, "coefficients", arr.copy())
|
||||
|
||||
|
||||
def _coerce_packet(packet: PacketLike) -> ModalityPacket:
|
||||
if isinstance(packet, ModalityPacket):
|
||||
return packet
|
||||
if isinstance(packet, Mapping):
|
||||
mid = packet.get("modality_id", packet.get("modality"))
|
||||
coeffs = packet.get("coefficients")
|
||||
if coeffs is None:
|
||||
coeffs = packet.get("coeffs")
|
||||
if coeffs is None:
|
||||
coeffs = packet.get("psi")
|
||||
if mid is None or coeffs is None:
|
||||
raise ValueError(
|
||||
"packet mapping requires modality_id (or modality) and "
|
||||
"coefficients (or coeffs / psi)"
|
||||
)
|
||||
return ModalityPacket(modality_id=str(mid), coefficients=np.asarray(coeffs))
|
||||
raise TypeError(
|
||||
f"packet must be ModalityPacket or mapping; got {type(packet).__name__}"
|
||||
)
|
||||
|
||||
|
||||
def compile_packet_to_psi(packet: PacketLike) -> np.ndarray:
|
||||
"""Lift a modality packet to a wave field ψ of shape ``(32,)``.
|
||||
|
||||
Construction-boundary only: validates shape/dtype and returns a fresh
|
||||
float64 copy. Does not repair non-unit packets (no hidden unitize).
|
||||
"""
|
||||
p = _coerce_packet(packet)
|
||||
return p.coefficients.astype(np.float64, copy=True)
|
||||
|
||||
|
||||
def superpose_packets(packets: Sequence[PacketLike]) -> np.ndarray:
|
||||
"""Linear superposition ``ψ_total = Σ_i compile_packet_to_psi(packet_i)``.
|
||||
|
||||
Empty input refuses (no confabulated zero field as resonance truth).
|
||||
"""
|
||||
if not packets:
|
||||
raise ValueError("superpose_packets: empty packet list")
|
||||
total = np.zeros(N_COMPONENTS, dtype=np.float64)
|
||||
for packet in packets:
|
||||
total = total + compile_packet_to_psi(packet)
|
||||
return total
|
||||
|
||||
|
||||
def phase_correlate(
|
||||
psi_a: np.ndarray,
|
||||
psi_b: np.ndarray,
|
||||
*,
|
||||
manifold: WaveManifold | None = None,
|
||||
) -> float:
|
||||
"""Algebraic multimodal resonance ρ(A,B) for I-04.
|
||||
|
||||
Delegates solely to :meth:`WaveManifold.phase_correlation`.
|
||||
Forbidden: cosine similarity, ANN, sklearn neighbors, embedding ranking.
|
||||
"""
|
||||
m = manifold if manifold is not None else WaveManifold()
|
||||
return float(m.phase_correlation(psi_a, psi_b))
|
||||
|
||||
|
||||
def fake_deterministic_packet(
|
||||
modality_id: str,
|
||||
*,
|
||||
angle: float = 0.3,
|
||||
plane: int = 6,
|
||||
) -> ModalityPacket:
|
||||
"""Honest deterministic fixture when real modality compilers are absent.
|
||||
|
||||
Builds a closed unit rotor via :func:`make_rotor_from_angle`. This is a
|
||||
test/construction fixture — not a live audio/vision compile path.
|
||||
"""
|
||||
coeffs = make_rotor_from_angle(float(angle), bivector_idx=int(plane))
|
||||
return ModalityPacket(modality_id=modality_id, coefficients=coeffs)
|
||||
|
||||
|
||||
__all__ = [
|
||||
"ModalityPacket",
|
||||
"PacketLike",
|
||||
"compile_packet_to_psi",
|
||||
"superpose_packets",
|
||||
"phase_correlate",
|
||||
"fake_deterministic_packet",
|
||||
]
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# ADR-0242: Deterministic Fibonacci Operators and Evidence-Gated Optimization
|
||||
|
||||
**Status**: Proposed — V1 cert discipline + V3 packing landed; V2/V4/V5 staged; **not** self-Accepted (Joshua review).
|
||||
**Status**: Proposed — V1 cert + V3 packing + V2 research helpers + V4 word schedule + V5 quarantine + sensorium feed landed; ready for Joshua review (do not self-accept).
|
||||
**Date**: 2026-07-13 (Drive authority); in-repo expansion 2026-07-15
|
||||
**Deciders**: Joshua Shay + multi-model R&D
|
||||
**Traceability**: Drive ADR-0242 (`15_NECCPy-tEWGfYi_BNqawm8GytUTMkz1DsOqGVMXhI`), PR #37/#38, cohesion plan
|
||||
|
|
@ -41,7 +41,7 @@ Module: `core/physics/fibonacci_search.py`
|
|||
- success → proposed κ = minimizer (telemetry; no auto state mutation)
|
||||
- failure → **baseline κ = 1.0**
|
||||
|
||||
### Vector 2 — Multi-scale temporal basis (research) 🟡
|
||||
### Vector 2 — Multi-scale temporal basis (research helpers) 🟢 research / 🟡 production
|
||||
|
||||
Drive:
|
||||
|
||||
|
|
@ -49,8 +49,9 @@ Drive:
|
|||
E_n(t) = E_n(t_0)\,\exp\bigl(-(t-t_0)/(F_n\tau_0)\bigr)
|
||||
\]
|
||||
|
||||
Landed progressive form: `fibonacci_tau_schedule` / `recency_band_index` in `wave_energy_boundary.py` (constants table).
|
||||
**Not** yet production default inside `FieldEnergyOperator`. Promotion requires comparative benchmark vs dyadic \(2^n\tau_0\) (Drive comparative hypothesis).
|
||||
- `wave_energy_boundary.fibonacci_tau_schedule` / `recency_band_index` (constants table)
|
||||
- `multi_scale_energy.py`: `multi_scale_energy_vector`, `dyadic_tau_schedule`, `comparative_residual_separation`
|
||||
**Not** production default inside `FieldEnergyOperator`. Flip requires comparative benchmark + Joshua gate.
|
||||
|
||||
### Vector 3 — Golden-Angle mode allocator 🟢
|
||||
|
||||
|
|
@ -62,15 +63,18 @@ Module: `core/physics/atlas_packing.py`
|
|||
- Reconstruction-over-storage: `ALLOCATOR_VERSION = golden_angle_v1` + `allocator_layout_descriptor`
|
||||
- Not holographic seals (null points ≠ closed unit versors)
|
||||
|
||||
### Vector 4 — Fibonacci-word observability choreography 🔴 staged
|
||||
### Vector 4 — Fibonacci-word observability choreography 🟢
|
||||
|
||||
Module: `core/physics/fibonacci_word_schedule.py`
|
||||
|
||||
Drive: \(W_0=B, W_1=A, W_{n+1}=W_n W_{n-1}\) for telemetry / sealed-holdout sampling.
|
||||
**Outside cognitive truth path.** Not yet implemented (plan D5).
|
||||
**Outside cognitive truth path** — pure schedule only; no vault/field mutation.
|
||||
|
||||
### Vector 5 — Topological anyon / braid holonomy 🔴 research quarantine
|
||||
### Vector 5 — Topological anyon / braid holonomy 🟢 quarantine box
|
||||
|
||||
Drive: isolated `algebra/topological_reasoning/` study; blocked from production.
|
||||
Not implemented (plan D6). Must not enter serve/FFI until proofs exist.
|
||||
Package: `algebra/topological_reasoning/` (README + `FUSION_RULE` stub).
|
||||
Production AST pin: `chat/`, `core/physics/`, `generate/`, `vault/`, `teaching/` must not import it.
|
||||
No fusion/braid logic until proofs + human Accept.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -79,10 +83,10 @@ Not implemented (plan D6). Must not enter serve/FFI until proofs exist.
|
|||
| Phase | Vector | Status |
|
||||
|-------|--------|--------|
|
||||
| 1 | V1 search + κ cert gate | 🟢 |
|
||||
| 2 | V2 multi-scale energy study | 🟡 table only |
|
||||
| 2 | V2 multi-scale energy study | 🟢 helpers; 🟡 not production default |
|
||||
| 3 | V3 packing | 🟢 |
|
||||
| 4 | V4 word scheduler | 🔴 |
|
||||
| 5 | V5 anyons | 🔴 quarantine |
|
||||
| 4 | V4 word scheduler | 🟢 |
|
||||
| 5 | V5 anyons | 🟢 quarantine only (no logic) |
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -302,9 +302,10 @@ PY
|
|||
| Golden-Angle atlas packing \(d_{\min}=0.12\) (V3) | 🟢 ADR-0242 (`atlas_packing`; CGA null-point \(d\); `golden_angle_v1`) |
|
||||
| Fibonacci section search cert/failure (V1) | 🟢 ADR-0242 (`FibonacciSearchCertificate` \| `OptimizationFailure`; dual-run digest) |
|
||||
| κ cert gate fail → baseline 1.0 (V1b) | 🟢 `propose_kappa_from_search` / `goldtether.propose_kappa_line_search` |
|
||||
| Multi-scale \(\tau_n=F_n\tau_0\) (V2) | 🟡 table only; production multi-band \(E_n(t)\) not default |
|
||||
| Fibonacci-word scheduler (V4) | 🔴 staged |
|
||||
| Fibonacci anyons (V5) | 🔴 research quarantine |
|
||||
| Multi-scale \(\tau_n=F_n\tau_0\) + \(E_n(t)\) helpers (V2) | 🟢 research API (`multi_scale_energy`); production energy default unchanged |
|
||||
| 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\)) |
|
||||
| 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; E0–E1 crystallization) |
|
||||
|
||||
|
|
|
|||
|
|
@ -866,10 +866,14 @@ wrong=0 serve entry path (AST-pinned in `tests/test_third_door_cohesion.py`):
|
|||
|--------|------|
|
||||
| `core.physics.wave_manifold` | Cl(4,1) wave field \(\psi\), leakage, polar conjugacy, chiral, \(\rho\) |
|
||||
| `core.physics.holographic_vault` | Durable standing-wave spectrum via `VaultStore` |
|
||||
| `core.physics.atlas_packing` | Golden-Angle mode packing (ADR-0242) |
|
||||
| `core.physics.fibonacci_search` | Fixed-budget unimodal section search (ADR-0242) |
|
||||
| `core.physics.atlas_packing` | Golden-Angle mode packing (ADR-0242 V3) |
|
||||
| `core.physics.fibonacci_search` | Cert-gated Fibonacci section search (ADR-0242 V1) |
|
||||
| `core.physics.fibonacci_word_schedule` | Fibonacci-word observability choreography (ADR-0242 V4; telemetry only) |
|
||||
| `core.physics.multi_scale_energy` | Multi-band \(E_n(t)\) research helpers (ADR-0242 V2; not serve) |
|
||||
| `core.physics.sensorium_wave_feed` | Sensorium → \(\psi\) construction feed (I-04) |
|
||||
| `core.contemplation.wave_seam` | P9 Trace A SPECULATIVE seal + hypothesis/evidence reconstruct |
|
||||
| `core.physics.wave_energy_boundary` | P10 Trace B residual→energy / \(\tau_n\) / crystallization |
|
||||
| `algebra.topological_reasoning` | ADR-0242 V5 research quarantine only — never serve/production |
|
||||
|
||||
Wiring any of these into serve requires an explicit ADR amendment and a
|
||||
failing-to-green containment test change in the same PR.
|
||||
|
|
|
|||
222
tests/test_adr_0241_sensorium_wave_feed.py
Normal file
222
tests/test_adr_0241_sensorium_wave_feed.py
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
"""D7 sensorium → ψ feed (I-04 boundary) pins.
|
||||
|
||||
ADR-0241 cohesion: modality packets compile to Cl(4,1) wave fields;
|
||||
multimodal resonance uses WaveManifold.phase_correlation only.
|
||||
|
||||
Honest fake packets when real compilers are not under test.
|
||||
No cosine / ANN / sklearn neighbors.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from algebra.cl41 import N_COMPONENTS
|
||||
from algebra.rotor import make_rotor_from_angle
|
||||
from algebra.versor import versor_condition
|
||||
from core.physics.sensorium_wave_feed import (
|
||||
ModalityPacket,
|
||||
compile_packet_to_psi,
|
||||
fake_deterministic_packet,
|
||||
phase_correlate,
|
||||
superpose_packets,
|
||||
)
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
|
||||
_ROOT = Path(__file__).resolve().parents[1]
|
||||
_MODULE = _ROOT / "core/physics/sensorium_wave_feed.py"
|
||||
_CLOSURE = 1e-6
|
||||
|
||||
|
||||
def _closed(angle: float = 0.3, plane: int = 6) -> np.ndarray:
|
||||
return make_rotor_from_angle(angle, bivector_idx=plane)
|
||||
|
||||
|
||||
# --- compile / packet --------------------------------------------------------
|
||||
|
||||
|
||||
def test_compile_packet_to_psi_from_modality_packet():
|
||||
coeffs = _closed(0.41, plane=7)
|
||||
packet = ModalityPacket(modality_id="vision", coefficients=coeffs)
|
||||
psi = compile_packet_to_psi(packet)
|
||||
assert psi.shape == (N_COMPONENTS,)
|
||||
assert psi.dtype == np.float64
|
||||
assert float(np.linalg.norm(psi - coeffs)) < 1e-15
|
||||
# Fresh copy — not the same buffer
|
||||
assert psi is not packet.coefficients
|
||||
|
||||
|
||||
def test_compile_packet_to_psi_from_dict():
|
||||
coeffs = _closed(0.22, plane=8)
|
||||
psi = compile_packet_to_psi(
|
||||
{"modality_id": "audio", "coefficients": coeffs.tolist()}
|
||||
)
|
||||
assert psi.shape == (32,)
|
||||
assert float(np.linalg.norm(psi - coeffs)) < 1e-12
|
||||
|
||||
|
||||
def test_compile_packet_accepts_modality_and_psi_keys():
|
||||
coeffs = _closed(0.15, plane=6)
|
||||
psi = compile_packet_to_psi({"modality": "text", "psi": coeffs})
|
||||
assert float(np.linalg.norm(psi - coeffs)) < 1e-15
|
||||
|
||||
|
||||
def test_compile_packet_rejects_wrong_shape():
|
||||
with pytest.raises(ValueError, match="shape"):
|
||||
ModalityPacket(modality_id="x", coefficients=np.zeros(16))
|
||||
|
||||
|
||||
def test_compile_packet_rejects_empty_modality_id():
|
||||
with pytest.raises(ValueError, match="modality_id"):
|
||||
ModalityPacket(modality_id=" ", coefficients=_closed())
|
||||
|
||||
|
||||
def test_compile_packet_rejects_incomplete_dict():
|
||||
with pytest.raises(ValueError, match="modality_id"):
|
||||
compile_packet_to_psi({"coefficients": _closed()})
|
||||
|
||||
|
||||
# --- superpose ---------------------------------------------------------------
|
||||
|
||||
|
||||
def test_superpose_packets_is_sum_of_compiled():
|
||||
a = fake_deterministic_packet("audio", angle=0.2, plane=6)
|
||||
b = fake_deterministic_packet("vision", angle=0.55, plane=8)
|
||||
total = superpose_packets([a, b])
|
||||
expected = compile_packet_to_psi(a) + compile_packet_to_psi(b)
|
||||
assert float(np.linalg.norm(total - expected)) < 1e-15
|
||||
|
||||
|
||||
def test_superpose_packets_empty_refused():
|
||||
with pytest.raises(ValueError, match="empty"):
|
||||
superpose_packets([])
|
||||
|
||||
|
||||
# --- phase correlate (I-04) --------------------------------------------------
|
||||
|
||||
|
||||
def test_phase_correlate_delegates_to_wave_manifold():
|
||||
a = _closed(0.2, plane=6)
|
||||
b = _closed(0.55, plane=8)
|
||||
M = WaveManifold()
|
||||
rho_direct = M.phase_correlation(a, b)
|
||||
rho_feed = phase_correlate(a, b, manifold=M)
|
||||
assert abs(rho_feed - rho_direct) < 1e-15
|
||||
|
||||
|
||||
def test_phase_correlate_symmetric():
|
||||
a = compile_packet_to_psi(fake_deterministic_packet("text", angle=0.3, plane=6))
|
||||
b = compile_packet_to_psi(fake_deterministic_packet("audio", angle=0.7, plane=9))
|
||||
assert abs(phase_correlate(a, b) - phase_correlate(b, a)) < 1e-12
|
||||
assert phase_correlate(a, a) > 0.5
|
||||
|
||||
|
||||
def test_cross_modal_fake_packets_phase_correlate():
|
||||
"""I-04 feed path: two modalities → ψ → algebraic ρ (not cosine)."""
|
||||
audio = fake_deterministic_packet("audio", angle=0.25, plane=6)
|
||||
vision = fake_deterministic_packet("vision", angle=0.25, plane=6)
|
||||
# Same closed rotor → strong self-like correlation across modality tags
|
||||
rho_same = phase_correlate(
|
||||
compile_packet_to_psi(audio),
|
||||
compile_packet_to_psi(vision),
|
||||
)
|
||||
assert rho_same > 0.5
|
||||
|
||||
other = fake_deterministic_packet("vision", angle=1.1, plane=10)
|
||||
rho_diff = phase_correlate(
|
||||
compile_packet_to_psi(audio),
|
||||
compile_packet_to_psi(other),
|
||||
)
|
||||
# Distinct planes/angles are not required to be lower, but path must run.
|
||||
assert isinstance(rho_diff, float)
|
||||
|
||||
|
||||
# --- fake deterministic fixtures ---------------------------------------------
|
||||
|
||||
|
||||
def test_fake_deterministic_packet_closed_and_stable():
|
||||
p1 = fake_deterministic_packet("sensorimotor", angle=0.4, plane=7)
|
||||
p2 = fake_deterministic_packet("sensorimotor", angle=0.4, plane=7)
|
||||
assert p1.modality_id == "sensorimotor"
|
||||
assert float(np.linalg.norm(p1.coefficients - p2.coefficients)) == 0.0
|
||||
assert versor_condition(p1.coefficients) < _CLOSURE
|
||||
|
||||
|
||||
def test_fake_deterministic_matches_make_rotor():
|
||||
angle, plane = 0.37, 11
|
||||
packet = fake_deterministic_packet("motor", angle=angle, plane=plane)
|
||||
expected = make_rotor_from_angle(angle, bivector_idx=plane)
|
||||
assert float(np.linalg.norm(packet.coefficients - expected)) < 1e-15
|
||||
|
||||
|
||||
# --- hygiene: no approx neighbors / cosine -----------------------------------
|
||||
|
||||
|
||||
def test_module_forbids_approx_neighbor_and_cosine_imports():
|
||||
"""I-04: no faiss / hnsw / annoy / sklearn / cosine_similarity stack."""
|
||||
src = _MODULE.read_text(encoding="utf-8")
|
||||
tree = ast.parse(src)
|
||||
banned_roots = {
|
||||
"faiss",
|
||||
"hnswlib",
|
||||
"annoy",
|
||||
"sklearn",
|
||||
"scipy",
|
||||
"sklearn.neighbors",
|
||||
}
|
||||
banned_names = {
|
||||
"cosine_similarity",
|
||||
"NearestNeighbors",
|
||||
"cosine",
|
||||
"cdist",
|
||||
}
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
for alias in node.names:
|
||||
root = alias.name.split(".")[0]
|
||||
assert root not in banned_roots, f"banned import {alias.name}"
|
||||
assert alias.name not in banned_roots
|
||||
if isinstance(node, ast.ImportFrom) and node.module:
|
||||
root = node.module.split(".")[0]
|
||||
assert root not in banned_roots, f"banned from {node.module}"
|
||||
assert node.module not in banned_roots
|
||||
for alias in node.names:
|
||||
assert alias.name not in banned_names
|
||||
if isinstance(node, ast.Attribute):
|
||||
assert node.attr not in banned_names
|
||||
if isinstance(node, ast.Name):
|
||||
assert node.id not in banned_names
|
||||
# Source-level ban on cosine similarity wording as implementation path
|
||||
assert "cosine_similarity" not in src
|
||||
assert "NearestNeighbors" not in src
|
||||
|
||||
|
||||
def test_phase_correlate_source_only_calls_phase_correlation():
|
||||
"""phase_correlate body must call WaveManifold.phase_correlation only."""
|
||||
src = _MODULE.read_text(encoding="utf-8")
|
||||
tree = ast.parse(src)
|
||||
func = None
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.FunctionDef) and node.name == "phase_correlate":
|
||||
func = node
|
||||
break
|
||||
assert func is not None, "phase_correlate not found"
|
||||
call_attrs: list[str] = []
|
||||
for node in ast.walk(func):
|
||||
if isinstance(node, ast.Call) and isinstance(node.func, ast.Attribute):
|
||||
call_attrs.append(node.func.attr)
|
||||
assert "phase_correlation" in call_attrs
|
||||
# No alternate resonance / similarity calls inside the function
|
||||
forbidden = {
|
||||
"cosine_similarity",
|
||||
"resonant_recall",
|
||||
"resonant_reconstruct",
|
||||
"dot",
|
||||
"norm",
|
||||
}
|
||||
for attr in call_attrs:
|
||||
assert attr not in forbidden, f"phase_correlate must not call .{attr}"
|
||||
136
tests/test_adr_0242_fibonacci_word.py
Normal file
136
tests/test_adr_0242_fibonacci_word.py
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
"""ADR-0242 V4 (D5) — Fibonacci-word observability scheduler.
|
||||
|
||||
Telemetry-only; dual-run deterministic; cannot mutate cognitive truth.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from core.physics.fibonacci_word_schedule import (
|
||||
Action,
|
||||
fibonacci_word,
|
||||
iter_schedule_actions,
|
||||
schedule_actions,
|
||||
word_length,
|
||||
)
|
||||
|
||||
|
||||
# Expected words from Drive: W0=B, W1=A, W_{n+1}=W_n W_{n-1}
|
||||
_EXPECTED = {
|
||||
0: "B",
|
||||
1: "A",
|
||||
2: "AB",
|
||||
3: "ABA",
|
||||
4: "ABAAB",
|
||||
5: "ABAABABA",
|
||||
6: "ABAABABAABAAB",
|
||||
}
|
||||
|
||||
|
||||
def test_w0_is_b():
|
||||
assert fibonacci_word(0) == "B"
|
||||
assert schedule_actions(0) == ("B",)
|
||||
|
||||
|
||||
def test_w1_is_a():
|
||||
assert fibonacci_word(1) == "A"
|
||||
assert schedule_actions(1) == ("A",)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("n,expected", sorted(_EXPECTED.items()))
|
||||
def test_fibonacci_word_table(n: int, expected: str):
|
||||
assert fibonacci_word(n) == expected
|
||||
|
||||
|
||||
@pytest.mark.parametrize("n,expected", sorted(_EXPECTED.items()))
|
||||
def test_schedule_actions_matches_word(n: int, expected: str):
|
||||
actions = schedule_actions(n)
|
||||
assert actions == tuple(expected)
|
||||
assert all(a in (Action.A.value, Action.B.value) for a in actions)
|
||||
|
||||
|
||||
def test_w2_ab_w3_aba_w4_abaab():
|
||||
assert fibonacci_word(2) == "AB"
|
||||
assert fibonacci_word(3) == "ABA"
|
||||
assert fibonacci_word(4) == "ABAAB"
|
||||
|
||||
|
||||
def test_recurrence_w_n_concat():
|
||||
"""W_{n+1} == W_n + W_{n-1} for several n."""
|
||||
for n in range(1, 10):
|
||||
assert fibonacci_word(n + 1) == fibonacci_word(n) + fibonacci_word(n - 1)
|
||||
|
||||
|
||||
def test_length_equals_fib_n_plus_1():
|
||||
"""|W_n| = F_{n+1} with F_0=0, F_1=1, F_2=1, F_3=2, F_4=3, F_5=5, …"""
|
||||
# F_{n+1} table for n=0..8 → 1,1,2,3,5,8,13,21,34
|
||||
fib_np1 = [1, 1, 2, 3, 5, 8, 13, 21, 34]
|
||||
for n, expected_len in enumerate(fib_np1):
|
||||
word = fibonacci_word(n)
|
||||
assert len(word) == expected_len
|
||||
assert word_length(n) == expected_len
|
||||
assert len(schedule_actions(n)) == expected_len
|
||||
|
||||
|
||||
def test_dual_run_identical():
|
||||
"""Deterministic: two independent evaluations produce byte-identical results."""
|
||||
for n in range(0, 12):
|
||||
a = fibonacci_word(n)
|
||||
b = fibonacci_word(n)
|
||||
assert a == b
|
||||
assert schedule_actions(n) == schedule_actions(n)
|
||||
assert tuple(iter_schedule_actions(n)) == schedule_actions(n)
|
||||
|
||||
|
||||
def test_action_enum_values():
|
||||
assert Action.A.value == "A"
|
||||
assert Action.B.value == "B"
|
||||
assert Action.A == "A"
|
||||
assert Action.B == "B"
|
||||
|
||||
|
||||
def test_rejects_negative_n():
|
||||
with pytest.raises(ValueError, match="non-negative"):
|
||||
fibonacci_word(-1)
|
||||
with pytest.raises(ValueError, match="non-negative"):
|
||||
schedule_actions(-1)
|
||||
with pytest.raises(ValueError, match="non-negative"):
|
||||
word_length(-1)
|
||||
|
||||
|
||||
def test_rejects_non_int_n():
|
||||
with pytest.raises(TypeError):
|
||||
fibonacci_word(1.5) # type: ignore[arg-type]
|
||||
with pytest.raises(TypeError):
|
||||
fibonacci_word(True) # type: ignore[arg-type]
|
||||
|
||||
|
||||
def test_only_ab_alphabet():
|
||||
for n in range(0, 14):
|
||||
word = fibonacci_word(n)
|
||||
assert set(word) <= {"A", "B"}
|
||||
if n == 0:
|
||||
assert set(word) == {"B"}
|
||||
elif n == 1:
|
||||
assert set(word) == {"A"}
|
||||
else:
|
||||
assert set(word) == {"A", "B"}
|
||||
|
||||
|
||||
def test_module_is_pure_no_side_effect_imports():
|
||||
"""Sovereignty pin: module must not pull vault/field mutation surfaces."""
|
||||
import ast
|
||||
from pathlib import Path
|
||||
|
||||
src = Path("core/physics/fibonacci_word_schedule.py").read_text()
|
||||
tree = ast.parse(src)
|
||||
forbidden = {"vault", "field", "store", "VaultStore", "generate", "chat"}
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
for alias in node.names:
|
||||
root = alias.name.split(".")[0]
|
||||
assert root not in forbidden, alias.name
|
||||
if isinstance(node, ast.ImportFrom) and node.module:
|
||||
root = node.module.split(".")[0]
|
||||
assert root not in forbidden, node.module
|
||||
167
tests/test_adr_0242_multi_scale_energy.py
Normal file
167
tests/test_adr_0242_multi_scale_energy.py
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
"""ADR-0242 V2 — multi-scale temporal energy basis (research prototype).
|
||||
|
||||
Pins Drive form E_n = E0 · exp(-age / (F_n · τ_0)), dyadic baseline comparison,
|
||||
determinism, and serve quarantine. Does **not** change FieldEnergyOperator defaults.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
from math import exp
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from core.physics.fibonacci_search import fibonacci_number
|
||||
from core.physics.multi_scale_energy import (
|
||||
comparative_residual_separation,
|
||||
dyadic_tau_schedule,
|
||||
multi_scale_energy_for_schedule,
|
||||
multi_scale_energy_vector,
|
||||
schedule_mid_span_fraction,
|
||||
)
|
||||
from core.physics.wave_energy_boundary import fibonacci_tau_schedule
|
||||
|
||||
_ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
# --- Schedules --------------------------------------------------------------
|
||||
|
||||
|
||||
def test_dyadic_tau_schedule_powers_of_two():
|
||||
# τ_n = 2^{n-1} · τ_0 for n = 1..5 → 1, 2, 4, 8, 16 when τ_0=1
|
||||
assert dyadic_tau_schedule(tau0=1.0, levels=5) == (1.0, 2.0, 4.0, 8.0, 16.0)
|
||||
assert dyadic_tau_schedule(tau0=0.5, levels=4) == (0.5, 1.0, 2.0, 4.0)
|
||||
|
||||
|
||||
def test_dyadic_tau_schedule_rejects_bad_inputs():
|
||||
with pytest.raises(ValueError):
|
||||
dyadic_tau_schedule(tau0=0.0, levels=3)
|
||||
with pytest.raises(ValueError):
|
||||
dyadic_tau_schedule(tau0=1.0, levels=0)
|
||||
|
||||
|
||||
def test_fibonacci_tau_matches_fibonacci_number():
|
||||
taus = fibonacci_tau_schedule(tau0=1.0, levels=6)
|
||||
expected = tuple(float(fibonacci_number(i)) for i in range(1, 7))
|
||||
assert taus == expected
|
||||
|
||||
|
||||
# --- Drive energy formula ---------------------------------------------------
|
||||
|
||||
|
||||
def test_multi_scale_energy_vector_matches_drive_formula():
|
||||
e0, age, tau0, levels = 2.0, 3.0, 1.0, 5
|
||||
got = multi_scale_energy_vector(e0, age, tau0=tau0, levels=levels)
|
||||
expected = tuple(
|
||||
e0 * exp(-age / (fibonacci_number(i) * tau0)) for i in range(1, levels + 1)
|
||||
)
|
||||
assert len(got) == levels
|
||||
for a, b in zip(got, expected, strict=True):
|
||||
assert a == pytest.approx(b, rel=0.0, abs=1e-15)
|
||||
|
||||
|
||||
def test_multi_scale_energy_matches_schedule_helper():
|
||||
e0, age, tau0, levels = 1.0, 2.5, 0.5, 6
|
||||
via_vector = multi_scale_energy_vector(e0, age, tau0=tau0, levels=levels)
|
||||
via_schedule = multi_scale_energy_for_schedule(
|
||||
e0, age, fibonacci_tau_schedule(tau0=tau0, levels=levels)
|
||||
)
|
||||
assert via_vector == via_schedule
|
||||
|
||||
|
||||
def test_decay_larger_age_yields_smaller_energy():
|
||||
young = multi_scale_energy_vector(1.0, age=1.0, tau0=1.0, levels=5)
|
||||
old = multi_scale_energy_vector(1.0, age=10.0, tau0=1.0, levels=5)
|
||||
assert all(o < y for o, y in zip(old, young, strict=True))
|
||||
# age=0 → full e0 at every scale
|
||||
zero = multi_scale_energy_vector(1.25, age=0.0, tau0=1.0, levels=4)
|
||||
assert zero == (1.25, 1.25, 1.25, 1.25)
|
||||
|
||||
|
||||
def test_larger_tau_scale_retains_more_energy():
|
||||
# Within a Fibonacci vector, coarser scales (larger F_n) decay slower.
|
||||
vec = multi_scale_energy_vector(1.0, age=5.0, tau0=1.0, levels=8)
|
||||
# F_1=1, F_8=21 → last component strictly larger residual energy
|
||||
assert vec[-1] > vec[0]
|
||||
|
||||
|
||||
def test_multi_scale_energy_rejects_bad_inputs():
|
||||
with pytest.raises(ValueError):
|
||||
multi_scale_energy_vector(1.0, age=-1.0)
|
||||
with pytest.raises(ValueError):
|
||||
multi_scale_energy_vector(float("nan"), age=1.0)
|
||||
with pytest.raises(ValueError):
|
||||
multi_scale_energy_for_schedule(1.0, 1.0, ())
|
||||
with pytest.raises(ValueError):
|
||||
multi_scale_energy_for_schedule(1.0, 1.0, (1.0, 0.0))
|
||||
|
||||
|
||||
# --- Determinism + comparative surface --------------------------------------
|
||||
|
||||
|
||||
def test_deterministic_dual_run():
|
||||
kwargs = dict(e0=1.0, age=4.0, tau0=1.0, levels=8)
|
||||
a = multi_scale_energy_vector(**kwargs)
|
||||
b = multi_scale_energy_vector(**kwargs)
|
||||
assert a == b
|
||||
ca = comparative_residual_separation(**kwargs)
|
||||
cb = comparative_residual_separation(**kwargs)
|
||||
assert ca == cb
|
||||
|
||||
|
||||
def test_fibonacci_bands_longer_than_dyadic_mid_scale():
|
||||
"""Mid-scale Fibonacci bands occupy a larger fraction of total span.
|
||||
|
||||
Absolute τ: F_n grows as ~φ^n while dyadic is 2^{n-1}, so dyadic absolute
|
||||
τ is larger late. Comparatively, φ-growth places the mid-index band further
|
||||
along the *normalized* hierarchy (span fraction) than pure dyadic — the
|
||||
structural property the V2 research pin checks.
|
||||
"""
|
||||
levels = 8
|
||||
tau0 = 1.0
|
||||
fib = fibonacci_tau_schedule(tau0=tau0, levels=levels)
|
||||
dyad = dyadic_tau_schedule(tau0=tau0, levels=levels)
|
||||
mid = levels // 2
|
||||
fib_frac = schedule_mid_span_fraction(fib, index=mid)
|
||||
dyad_frac = schedule_mid_span_fraction(dyad, index=mid)
|
||||
assert fib_frac > dyad_frac
|
||||
# Absolute mid τ still follows F_5=5 vs 2^4=16
|
||||
assert fib[mid] == 5.0
|
||||
assert dyad[mid] == 16.0
|
||||
|
||||
|
||||
def test_comparative_residual_separation_shape():
|
||||
report = comparative_residual_separation(1.0, age=3.0, tau0=1.0, levels=5)
|
||||
assert report["levels"] == 5
|
||||
assert len(report["fibonacci_taus"]) == 5
|
||||
assert len(report["dyadic_taus"]) == 5
|
||||
assert len(report["fibonacci_energies"]) == 5
|
||||
assert len(report["dyadic_energies"]) == 5
|
||||
assert len(report["energy_gap_fib_minus_dyadic"]) == 5
|
||||
# age=0 → identical unit energies regardless of schedule
|
||||
zero = comparative_residual_separation(1.0, age=0.0, tau0=1.0, levels=4)
|
||||
assert zero["fibonacci_energies"] == (1.0, 1.0, 1.0, 1.0)
|
||||
assert zero["dyadic_energies"] == (1.0, 1.0, 1.0, 1.0)
|
||||
assert zero["energy_gap_fib_minus_dyadic"] == (0.0, 0.0, 0.0, 0.0)
|
||||
|
||||
|
||||
# --- Serve quarantine (A-04) ------------------------------------------------
|
||||
|
||||
|
||||
def test_serve_runtime_does_not_import_multi_scale_energy():
|
||||
tree = ast.parse((_ROOT / "chat/runtime.py").read_text(encoding="utf-8"))
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.ImportFrom) and node.module:
|
||||
assert "multi_scale_energy" not in node.module
|
||||
assert "wave_energy_boundary" not in node.module
|
||||
if isinstance(node, ast.Import):
|
||||
for alias in node.names:
|
||||
assert "multi_scale_energy" not in alias.name
|
||||
|
||||
|
||||
def test_field_energy_operator_untouched_by_multi_scale_module():
|
||||
"""Production energy operator must not import the research multi-scale path."""
|
||||
energy_src = (_ROOT / "core/physics/energy.py").read_text(encoding="utf-8")
|
||||
assert "multi_scale_energy" not in energy_src
|
||||
assert "fibonacci_tau_schedule" not in energy_src
|
||||
124
tests/test_adr_0242_topological_quarantine.py
Normal file
124
tests/test_adr_0242_topological_quarantine.py
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
"""ADR-0242 V5 (D6) — topological_reasoning research quarantine pins.
|
||||
|
||||
Authority: docs/adr/ADR-0242-atlas-packing-and-fibonacci.md Vector 5.
|
||||
Package may exist under algebra/topological_reasoning/ for isolated study.
|
||||
Production packages must not import it.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import ast
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
_ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
# Production surfaces that must never import the research quarantine package.
|
||||
_PRODUCTION_PACKAGES = (
|
||||
"chat",
|
||||
"core/physics",
|
||||
"generate",
|
||||
"vault",
|
||||
"teaching",
|
||||
)
|
||||
|
||||
_BANNED_MARKERS = (
|
||||
"topological_reasoning",
|
||||
"algebra.topological_reasoning",
|
||||
)
|
||||
|
||||
|
||||
def _iter_python_files(package_rel: str) -> list[Path]:
|
||||
base = _ROOT / package_rel
|
||||
if not base.is_dir():
|
||||
return []
|
||||
return sorted(p for p in base.rglob("*.py") if p.is_file())
|
||||
|
||||
|
||||
def _import_mentions_topological(tree: ast.AST) -> list[str]:
|
||||
"""Return import module strings that reference topological_reasoning."""
|
||||
hits: list[str] = []
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
for alias in node.names:
|
||||
name = alias.name
|
||||
if any(m in name for m in _BANNED_MARKERS):
|
||||
hits.append(name)
|
||||
elif isinstance(node, ast.ImportFrom):
|
||||
mod = node.module or ""
|
||||
if any(m in mod for m in _BANNED_MARKERS):
|
||||
hits.append(mod)
|
||||
# from algebra import topological_reasoning
|
||||
if mod == "algebra" or mod.endswith(".algebra"):
|
||||
for alias in node.names:
|
||||
if alias.name == "topological_reasoning" or (
|
||||
alias.name and "topological_reasoning" in alias.name
|
||||
):
|
||||
hits.append(f"{mod}.{alias.name}")
|
||||
return hits
|
||||
|
||||
|
||||
def test_topological_reasoning_package_imports_in_isolation() -> None:
|
||||
"""Package is importable on its own without production wiring."""
|
||||
import algebra.topological_reasoning as tr
|
||||
|
||||
assert hasattr(tr, "FUSION_RULE")
|
||||
assert isinstance(tr.FUSION_RULE, str)
|
||||
assert tr.FUSION_RULE == "tau_otimes_tau_eq_1_oplus_tau"
|
||||
# Research label only — no callable production fusion API required.
|
||||
assert "FUSION_RULE" in tr.__all__
|
||||
|
||||
|
||||
def test_algebra_public_import_still_works() -> None:
|
||||
"""Quarantine package must not break the algebra package surface."""
|
||||
import algebra
|
||||
from algebra import versor_condition, word_transition_rotor
|
||||
|
||||
assert callable(versor_condition)
|
||||
assert callable(word_transition_rotor)
|
||||
# Research package is not re-exported on algebra's public surface.
|
||||
assert not hasattr(algebra, "topological_reasoning") or "topological_reasoning" not in getattr(
|
||||
algebra, "__all__", ()
|
||||
)
|
||||
|
||||
|
||||
def test_topological_reasoning_package_directory_may_exist() -> None:
|
||||
"""Algebraic research quarantine box is allowed to exist on disk."""
|
||||
pkg = _ROOT / "algebra" / "topological_reasoning"
|
||||
assert pkg.is_dir()
|
||||
assert (pkg / "__init__.py").is_file()
|
||||
assert (pkg / "README.md").is_file()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("package_rel", _PRODUCTION_PACKAGES)
|
||||
def test_production_packages_do_not_import_topological_reasoning(
|
||||
package_rel: str,
|
||||
) -> None:
|
||||
"""Architectural: production trees must not import topological_reasoning."""
|
||||
files = _iter_python_files(package_rel)
|
||||
assert files, f"expected python sources under {package_rel}"
|
||||
|
||||
violations: list[str] = []
|
||||
for path in files:
|
||||
# Never scan the quarantine package itself (it lives under algebra/).
|
||||
rel = path.relative_to(_ROOT).as_posix()
|
||||
if "topological_reasoning" in rel.split("/"):
|
||||
continue
|
||||
try:
|
||||
src = path.read_text(encoding="utf-8")
|
||||
except OSError as exc:
|
||||
violations.append(f"{rel}: unreadable ({exc})")
|
||||
continue
|
||||
try:
|
||||
tree = ast.parse(src, filename=rel)
|
||||
except SyntaxError as exc:
|
||||
violations.append(f"{rel}: syntax error ({exc})")
|
||||
continue
|
||||
for hit in _import_mentions_topological(tree):
|
||||
violations.append(f"{rel}: imports {hit}")
|
||||
|
||||
assert not violations, (
|
||||
"ADR-0242 V5 quarantine violated — production import(s) of "
|
||||
"topological_reasoning:\n" + "\n".join(violations)
|
||||
)
|
||||
|
|
@ -60,17 +60,23 @@ def test_phase0_a04_serve_path_quarantines_wave_and_fibonacci():
|
|||
"wave_manifold",
|
||||
"holographic_vault",
|
||||
"fibonacci_search",
|
||||
"fibonacci_word_schedule",
|
||||
"atlas_packing",
|
||||
"wave_seam", # P9 Trace A — contemplation only, never serve
|
||||
"wave_energy_boundary", # P10 Trace B — energy/τ gate, never serve
|
||||
"multi_scale_energy", # ADR-0242 V2 research multi-band E_n(t), never serve
|
||||
"sensorium_wave_feed", # D7 I-04 sensorium→ψ feed, never serve
|
||||
}
|
||||
banned_substrings = (
|
||||
"wave_manifold",
|
||||
"holographic_vault",
|
||||
"fibonacci_search",
|
||||
"fibonacci_word_schedule",
|
||||
"atlas_packing",
|
||||
"wave_seam",
|
||||
"wave_energy_boundary",
|
||||
"multi_scale_energy",
|
||||
"sensorium_wave_feed",
|
||||
)
|
||||
for node in ast.walk(tree):
|
||||
if isinstance(node, ast.Import):
|
||||
|
|
|
|||
Loading…
Reference in a new issue