From 4e7c29b84ab1a5d709f790141baab8a0ea2eb0c1 Mon Sep 17 00:00:00 2001 From: Shay Date: Wed, 13 May 2026 14:24:29 -0700 Subject: [PATCH] Fix field state introspection and pack manifold geometry --- field/state.py | 5 ++--- language_packs/compiler.py | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/field/state.py b/field/state.py index 31afc061..a0a7c1f2 100644 --- a/field/state.py +++ b/field/state.py @@ -4,7 +4,7 @@ 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(). -FieldState is immutable by design (frozen=True, slots=True). +FieldState is immutable by design (frozen=True). The np.ndarray F is copied and validated at construction — the copy() call is the explicit contract boundary. Callers must not retain a mutable reference to the array passed in and expect coherence. @@ -17,7 +17,7 @@ import numpy as np _EXPECTED_COMPONENTS = 32 -@dataclass(frozen=True, slots=True) +@dataclass(frozen=True) class FieldState: F: np.ndarray # shape (32,) float32 — Cl(4,1) multivector on the versor manifold node: int = 0 # current node index in the vocabulary manifold @@ -28,7 +28,6 @@ class FieldState: # Enforce copy + dtype + shape at the construction boundary. # frozen=True prevents reassignment, but ndarray contents are still # mutable via the array object; copy() here is the defence. - # slots=True closes __dict__ so no incidental attributes can be added. F = np.array(self.F, dtype=np.float32).copy() if F.shape != (_EXPECTED_COMPONENTS,): raise ValueError( diff --git a/language_packs/compiler.py b/language_packs/compiler.py index 321986dc..cfbc5517 100644 --- a/language_packs/compiler.py +++ b/language_packs/compiler.py @@ -36,13 +36,30 @@ def _feature_rotor(name: str, salt: str, weight: float) -> np.ndarray: return rotor +def _domain_features(domain: str) -> list[tuple[str, float]]: + """ + Lift hierarchical semantic domains into a small feature chain. + + A domain like ``logos.illumination.photon`` contributes the trunk + (``logos``), then the branch (``logos.illumination``), then the leaf. + This reduces accidental hash collisions where unrelated surfaces land + close together despite having disjoint semantic structure. + """ + parts = domain.lower().split(".") + return [ + (".".join(parts[: depth + 1]), 0.45 / (depth + 1)) + for depth in range(len(parts)) + ] + + def _entry_to_coordinate(entry: LexicalEntry) -> np.ndarray: vec = np.zeros(N_COMPONENTS, dtype=np.float32) vec[0] = 1.0 pos = (entry.pos or entry.part_of_speech or "").lower() for domain in entry.semantic_domains: - vec = geometric_product(vec, _feature_rotor(domain.lower(), "domain", 0.7)) + for feature, weight in _domain_features(domain): + vec = geometric_product(vec, _feature_rotor(feature, "domain", weight)) if pos: vec = geometric_product(vec, _feature_rotor(pos, "pos", 0.35))