init: ingest, field, vocab, vault, persona, generate, session layers

This commit is contained in:
Shay 2026-05-12 19:14:22 -07:00
parent b80dd57a9b
commit b5989f35ec
15 changed files with 384 additions and 0 deletions

2
field/__init__.py Normal file
View file

@ -0,0 +1,2 @@
from .state import FieldState
from .propagate import propagate_step

21
field/propagate.py Normal file
View file

@ -0,0 +1,21 @@
"""
Field propagation the generation heartbeat.
Each step: F <- versor_apply(V, F)
V is the rotor for the current node's outgoing edge in the vocab manifold.
No correction. No normalization. No conditional branching. The loop is tight.
"""
from algebra.versor import versor_apply
from field.state import FieldState
def propagate_step(state: FieldState, V) -> FieldState:
"""
Apply one versor transition.
V is the edge rotor from the current node.
Returns a new FieldState one step forward on the manifold.
"""
new_F = versor_apply(V, state.F)
return FieldState(F=new_F, node=state.node, step=state.step + 1)

20
field/state.py Normal file
View file

@ -0,0 +1,20 @@
"""
FieldState the complete cognitive field at one moment.
Invariant: versor_condition(F) < 1e-6 always.
This is checked at injection and maintained structurally by versor_apply().
"""
from dataclasses import dataclass
import numpy as np
@dataclass
class FieldState:
F: np.ndarray # shape (32,) — Cl(4,1) multivector on the versor manifold
node: int = 0 # current node index in the vocabulary manifold
step: int = 0 # number of propagation steps taken
def advance(self, new_F: np.ndarray, new_node: int) -> "FieldState":
"""Return a new FieldState after one propagation step."""
return FieldState(F=new_F, node=new_node, step=self.step + 1)

1
generate/__init__.py Normal file
View file

@ -0,0 +1 @@
from .stream import generate, agenerate

51
generate/stream.py Normal file
View file

@ -0,0 +1,51 @@
"""
Generation loop token streaming from the versor manifold.
Every token: nearest word to current F via CGA inner product.
Every step: F <- versor_apply(V, F) where V is the edge rotor.
No confidence gates. No IDK fallback. No attractor clamping.
F is always on the manifold. nearest() is always exact.
"""
import numpy as np
from field.state import FieldState
from field.propagate import propagate_step
def generate(state: FieldState, vocab, persona, max_tokens: int = 128) -> list:
"""
Generate a token sequence from an initial FieldState.
Loop:
1. Apply persona motor to current field
2. Find nearest vocab node via CGA inner product
3. Emit token
4. Get edge rotor from current node to nearest node
5. Propagate: F <- versor_apply(V, F)
6. Advance node pointer
"""
tokens = []
current = state
for _ in range(max_tokens):
F_voiced = persona.apply(current.F)
word, word_idx = vocab.nearest(F_voiced)
tokens.append(word)
V = vocab.edge_rotor(current.node, word_idx)
current = propagate_step(current, V)
current = FieldState(F=current.F, node=word_idx, step=current.step)
return tokens
async def agenerate(state: FieldState, vocab, persona, max_tokens: int = 128):
"""Async streaming version — yields one token at a time."""
current = state
for _ in range(max_tokens):
F_voiced = persona.apply(current.F)
word, word_idx = vocab.nearest(F_voiced)
yield word
V = vocab.edge_rotor(current.node, word_idx)
current = propagate_step(current, V)
current = FieldState(F=current.F, node=word_idx, step=current.step)

1
ingest/__init__.py Normal file
View file

@ -0,0 +1 @@
from .gate import inject

38
ingest/gate.py Normal file
View file

@ -0,0 +1,38 @@
"""
The single injection gate.
The ONLY point where raw data enters the versor manifold.
normalize_to_versor() is called here and nowhere else in production code.
Contract:
Input: raw token sequence + VocabManifold
Output: FieldState with F satisfying versor_condition(F) < 1e-6
"""
from algebra.versor import normalize_to_versor, versor_condition
from algebra.holonomy import holonomy_encode
from field.state import FieldState
def inject(tokens: list, vocab) -> FieldState:
"""
Encode a token sequence and inject into the versor manifold.
Steps:
1. Look up each token's versor in the vocab manifold
2. Encode via holonomy walk
3. Normalize to versor (the single allowed normalization call)
4. Assert versor condition before returning
"""
word_versors = [vocab.get_versor(t) for t in tokens]
H = holonomy_encode(word_versors)
F = normalize_to_versor(H)
cond = versor_condition(F)
if cond > 1e-5:
raise RuntimeError(
f"Injection produced non-versor field: condition={cond:.2e}. "
"Check holonomy_encode() and normalize_to_versor()."
)
return FieldState(F=F, node=0, step=0)

1
persona/__init__.py Normal file
View file

@ -0,0 +1 @@
from .motor import PersonaMotor

79
persona/motor.py Normal file
View file

@ -0,0 +1,79 @@
"""
Persona as a CGA motor a rigid screw motion on the generation manifold.
M = T * R where:
T = translator versor (persona's position in concept space)
R = rotor (persona's characteristic rotation)
Applying persona: F_voiced = M * F * reverse(M)
This is a versor product. Persona application is algebraically closed.
No weight overlay. No post-hoc bias. No separate correction pass.
"""
import numpy as np
from algebra.versor import versor_apply, normalize_to_versor
from algebra.cl41 import geometric_product, reverse, basis_vector, N_COMPONENTS
class PersonaMotor:
def __init__(self, translator: np.ndarray, rotor: np.ndarray):
"""
translator: a versor encoding translational bias in CGA
rotor: a versor encoding rotational character
Both must satisfy versor_condition < 1e-6.
"""
self.M = normalize_to_versor(
geometric_product(
np.asarray(translator, dtype=np.float32),
np.asarray(rotor, dtype=np.float32),
)
)
def apply(self, F: np.ndarray) -> np.ndarray:
"""Apply persona to field F. Returns M * F * reverse(M)."""
return versor_apply(self.M, F)
def compose(self, other: "PersonaMotor") -> "PersonaMotor":
"""
Compose two persona motors: M_combined = self.M * other.M
Used to blend persona layers (base persona + session persona).
"""
result = PersonaMotor.__new__(PersonaMotor)
result.M = normalize_to_versor(geometric_product(self.M, other.M))
return result
@classmethod
def identity(cls) -> "PersonaMotor":
"""The identity motor — applies no transformation."""
inst = cls.__new__(cls)
inst.M = np.zeros(N_COMPONENTS, dtype=np.float32)
inst.M[0] = 1.0
return inst
@classmethod
def from_concept_vector(cls, concept: np.ndarray) -> "PersonaMotor":
"""
Build a persona motor from a 3D concept vector in R^3.
Embeds as a CGA translator: T = 1 + (1/2) * t * e_inf
where e_inf = e+ + e- (the point at infinity in CGA).
"""
concept = np.asarray(concept, dtype=np.float32)
assert len(concept) == 3
e_inf = basis_vector(3) + basis_vector(4) # e+ + e-
t_blade = np.zeros(N_COMPONENTS, dtype=np.float32)
for i in range(3):
t_blade += concept[i] * geometric_product(basis_vector(i), e_inf)
translator = np.zeros(N_COMPONENTS, dtype=np.float32)
translator[0] = 1.0
translator += 0.5 * t_blade
rotor = np.zeros(N_COMPONENTS, dtype=np.float32)
rotor[0] = 1.0
return cls(
normalize_to_versor(translator),
normalize_to_versor(rotor),
)

1
session/__init__.py Normal file
View file

@ -0,0 +1 @@
from .context import SessionContext

49
session/context.py Normal file
View file

@ -0,0 +1,49 @@
"""
SessionContext binds field, vault, vocab, and persona for one session.
One session = one field trajectory on the manifold.
The vault accumulates versors across turns.
The persona motor is fixed per session (or composable across sessions).
"""
from field.state import FieldState
from vault.store import VaultStore
from persona.motor import PersonaMotor
from ingest.gate import inject
from generate.stream import generate, agenerate
class SessionContext:
def __init__(self, vocab, persona=None, vault=None):
self.vocab = vocab
self.persona = persona or PersonaMotor.identity()
self.vault = vault or VaultStore()
self.state: FieldState = None
self.turn: int = 0
def ingest(self, tokens: list) -> FieldState:
"""Inject a prompt. Sets self.state. Stores field in vault."""
self.state = inject(tokens, self.vocab)
self.vault.store(self.state.F, {"turn": self.turn, "role": "user"})
return self.state
def respond(self, max_tokens: int = 128) -> list:
"""Generate a response from current state. Stores result in vault."""
assert self.state is not None, "Call ingest() before respond()."
tokens = generate(self.state, self.vocab, self.persona, max_tokens)
self.vault.store(self.state.F, {"turn": self.turn, "role": "assistant"})
self.turn += 1
return tokens
async def arespond(self, max_tokens: int = 128):
"""Async streaming response."""
assert self.state is not None, "Call ingest() before arespond()."
async for token in agenerate(self.state, self.vocab, self.persona, max_tokens):
yield token
self.vault.store(self.state.F, {"turn": self.turn, "role": "assistant"})
self.turn += 1
def recall(self, query_tokens: list, top_k: int = 5) -> list:
"""Recall relevant past versors for a query."""
query_state = inject(query_tokens, self.vocab)
return self.vault.recall(query_state.F, top_k=top_k)

1
vault/__init__.py Normal file
View file

@ -0,0 +1 @@
from .store import VaultStore

56
vault/store.py Normal file
View file

@ -0,0 +1,56 @@
"""
VaultStore exact memory via CGA inner product scan.
No HNSW. No approximate nearest neighbor. No index rebuild.
Recall is exact: argmax_i { cga_inner(query, X_i) } over stored versors.
Periodic null_project() prevents floating-point null-cone drift in long sessions.
"""
import numpy as np
from algebra.cga import cga_inner, null_project
class VaultStore:
def __init__(self, reproject_interval: int = 100):
self._versors: list = []
self._metadata: list = []
self._store_count: int = 0
self._reproject_interval = reproject_interval
def store(self, F: np.ndarray, metadata: dict = None) -> int:
"""Store a versor. Returns its index. Auto-reprojects every N stores."""
self._versors.append(np.asarray(F, dtype=np.float32).copy())
self._metadata.append(metadata or {})
self._store_count += 1
if self._store_count % self._reproject_interval == 0:
self.reproject()
return len(self._versors) - 1
def recall(self, query: np.ndarray, top_k: int = 5) -> list:
"""
Return top_k closest stored versors by CGA inner product.
Each result: {versor, score, metadata, index}
"""
if not self._versors:
return []
scores = [cga_inner(query, v) for v in self._versors]
top_indices = sorted(range(len(scores)), key=lambda i: -scores[i])[:top_k]
return [
{
"versor": self._versors[i],
"score": scores[i],
"metadata": self._metadata[i],
"index": i,
}
for i in top_indices
]
def reproject(self) -> None:
"""
Re-project all stored versors onto the null cone.
Corrects floating-point drift. Run between turns or asynchronously.
"""
self._versors = [null_project(v) for v in self._versors]
def __len__(self) -> int:
return len(self._versors)

1
vocab/__init__.py Normal file
View file

@ -0,0 +1 @@
from .manifold import VocabManifold

62
vocab/manifold.py Normal file
View file

@ -0,0 +1,62 @@
"""
VocabManifold the geometric vocabulary.
Each word is a versor in Cl(4,1). nearest(F) finds the closest word
by CGA inner product no cosine similarity, no ANN index.
"""
import numpy as np
from algebra.cga import cga_inner
from algebra.versor import normalize_to_versor
from algebra.cl41 import geometric_product, reverse
class VocabManifold:
def __init__(self):
self._words: list = []
self._versors: list = [] # each shape (32,)
def add(self, word: str, versor: np.ndarray) -> None:
"""Register a word-versor pair."""
self._words.append(word)
self._versors.append(np.asarray(versor, dtype=np.float32).copy())
def get_versor(self, word: str) -> np.ndarray:
"""Look up a word's versor. Raises KeyError if not found."""
try:
idx = self._words.index(word)
return self._versors[idx].copy()
except ValueError:
raise KeyError(f"Word '{word}' not in vocabulary.")
def nearest(self, F: np.ndarray, exclude_idx: int = -1) -> tuple:
"""
Find the word whose versor is closest to F by CGA inner product.
Returns (word, index). O(|vocab|), exact, no approximation.
cga_inner(X, Y) = -d^2 / 2 for null vectors: maximizing = minimizing distance.
"""
best_score = -np.inf
best_idx = 0
for i, v in enumerate(self._versors):
if i == exclude_idx:
continue
score = cga_inner(F, v)
if score > best_score:
best_score = score
best_idx = i
return self._words[best_idx], best_idx
def edge_rotor(self, from_idx: int, to_idx: int) -> np.ndarray:
"""
Compute the rotor that rotates from_versor toward to_versor.
R = normalize(1 + B * reverse(A))
"""
A = self._versors[from_idx]
B = self._versors[to_idx]
R = geometric_product(B, reverse(A))
R = R.copy()
R[0] += 1.0
return normalize_to_versor(R)
def __len__(self) -> int:
return len(self._words)