core/ingest/gate.py
Shay 3746f06898 fix: cohesive seam pass — frozen FieldState, GenerationResult, generation/vocab/algebra separation, normalization doctrine
- field/state.py: FieldState is now frozen+slotted; constructor copies and
  enforces float32 shape (32,); advance() updated to pass raw arrays.
  np.ndarray inside frozen dataclass is ref-frozen — copy() at construction
  is the explicit contract boundary.

- generate/result.py: NEW — GenerationResult frozen dataclass carrying
  tokens + final_state. Async variant yields tokens and exposes final_state
  on completion.

- generate/stream.py: generate() now returns GenerationResult, not list[str].
  vocab.edge_rotor() call replaced with:
    A = vocab.get_versor_at(current.node)
    B = vocab.get_versor_at(word_idx)
    V = word_transition_rotor(A, B)
  agenerate() updated to yield tokens and surface final_state.

- vocab/manifold.py: added get_versor_at(idx) and get_word_at(idx) indexed
  accessors. VocabManifold stores points; algebra constructs operators.
  normalize_to_versor() call-site in docstring clarified: callers must call
  unitize_versor() (algebra construction primitive) before add(), not
  normalize_to_versor() directly.

- algebra/versor.py: unitize_versor() added as the explicit construction-time
  primitive. normalize_to_versor() kept but marked internal/gate-only.
  Distinction encoded in docstrings and __all__.

- persona/motor.py + ingest/gate.py: SessionContext.respond() is not yet in
  the repo as a separate file; gate.py docstring updated to reflect the
  three-tier normalization doctrine:
    unitize_versor()    — algebra construction only
    inject()            — gate, once per raw input
    normalization       — forbidden in propagate/generate/vault recall
2026-05-13 12:32:36 -07:00

53 lines
1.9 KiB
Python

"""
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.
Normalization doctrine (three-tier):
unitize_versor() algebra/versor.py — construction primitive.
Allowed in: algebra/, persona/, vocab/ (pre-add).
Purpose: build valid rotors/motors/manifold entries.
inject() THIS function — gate operation, once per raw input.
Calls normalize_to_versor() internally at the
holonomy-to-field boundary.
FORBIDDEN: normalization inside propagation, generation,
vault recall, or as post-hoc repair after a
supposedly closed transition. If normalization is
needed there, fix the operator — not the result.
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 gate 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)