core/docs/decisions/ADR-0004-rotor-as-operator-not-property.md
Shay 377201015f docs: add ADR log and session decision record for 2026-05-12
- Add docs/decisions/README.md: ADR format guide and index
- Add docs/decisions/ADR-0001-vocab-layer-invariants.md
- Add docs/decisions/ADR-0002-ingest-layer-design.md
- Add docs/decisions/ADR-0003-coordinate-system-dissolution.md
- Add docs/decisions/ADR-0004-rotor-as-operator-not-property.md
- Add docs/decisions/SESSION-2026-05-12.md: full timestamped session log
2026-05-12 20:56:21 -07:00

2.8 KiB
Raw Blame History

ADR-0004: Rotor as Operator, Not Vocabulary Property

Date: 2026-05-12
Status: Accepted
Commit: bd423e4
Implements: ADR-0003

Context

VocabManifold in the initial core implementation included an edge_rotor() method that computed the rotor between two stored word-versors:

def edge_rotor(self, from_idx: int, to_idx: int) -> np.ndarray:
    A = self._versors[from_idx]
    B = self._versors[to_idx]
    R = geometric_product(B, reverse(A))
    R[0] += 1.0
    return normalize_to_versor(R)

This method is mathematically correct but architecturally misplaced. Storing it on VocabManifold means the vocabulary is carrying operator construction logic — implying that the relationship between two words is a property of the vocabulary rather than a property of a transformation being applied in the field.

Decision

  1. Remove edge_rotor() from VocabManifold.
  2. Create algebra/rotor.py with word_transition_rotor(A, B) as a free function.
  3. Export word_transition_rotor from algebra/__init__.py.

VocabManifold contract is now strictly: store word-versor pairs, support relational lookup by CGA inner product. Nothing else.

Rationale

A rotor between two words is not a property of those words in isolation — it is a description of a transformation being applied at a moment in the field. Storing it on the vocabulary conflates the map (what words exist and where they are) with the territory (what operations are being performed on the field state during generation or propagation).

Serves Field-State: operators live in algebra/; relational structure lives in field/; the vocabulary is a lookup structure, not an operator store.

Serves Dual-Correction: the forward operator (field propagation) and its corrective counterpart (rotor application / coherence restoration) should both originate in algebra/, not be scattered across layers that dont own them.

Consequences

  • Cleaner dependency graph: vocab/ now imports from algebra/ for algebraic primitives only (grade-norm check). It never constructs operators.
  • Clear callsite semantics: algebra.word_transition_rotor(A, B) at a callsite in field/ or generate/ is self-documenting: an operator is being constructed here, by the layer that owns operators.
  • Forbidden: Any method on VocabManifold that constructs a rotor, versor product, or transformation. Vocabulary is read-only geometry.

Alternatives Considered

  • Keep edge_rotor() as a convenience method with a deprecation warning: Rejected. Convenience methods that violate layer contracts tend to be the ones that get used. Remove cleanly.
  • Move to a separate VocabOps class in vocab/: Rejected. The operators dont belong in vocab/ regardless of what class they live in. The layer boundary is the constraint, not the class boundary.