""" Alignment graph — cross-language resonance edges. AlignmentEdge records live in a pack's alignment.jsonl alongside its lexicon.jsonl. This module loads them into a queryable in-memory graph. Design constraints: - No numpy, no algebra imports. The graph is pure schema + stdlib. Geometric verification belongs in tests or holonomy proofs, not here. - load_alignment() is the single entry point. It reads bytes, not strings, so the caller can checksum if needed. - AlignmentGraph is immutable after construction (frozen edges tuple). """ from __future__ import annotations import json from pathlib import Path from language_packs.schema import AlignmentEdge _DATA_DIR = Path(__file__).parent.parent / "language_packs" / "data" class AlignmentGraph: """Immutable in-memory graph of AlignmentEdge records for one pack.""" def __init__(self, edges: list[AlignmentEdge]) -> None: self._edges: tuple[AlignmentEdge, ...] = tuple(edges) # Index by source_id for O(1) lookup on hot path self._by_source: dict[str, list[AlignmentEdge]] = {} for edge in self._edges: self._by_source.setdefault(edge.source_id, []).append(edge) def __len__(self) -> int: return len(self._edges) def edges_from(self, source_id: str) -> list[AlignmentEdge]: """Return all edges originating from source_id.""" return list(self._by_source.get(source_id, [])) def aligned_pairs(self, relation_prefix: str) -> list[AlignmentEdge]: """Return all edges whose relation starts with relation_prefix.""" return [ e for e in self._edges if e.relation.startswith(relation_prefix) ] def get_edge(self, source_id: str, target_id: str) -> AlignmentEdge | None: """Return the edge between source and target, or None.""" for edge in self._by_source.get(source_id, []): if edge.target_id == target_id: return edge return None @property def edges(self) -> tuple[AlignmentEdge, ...]: return self._edges def _parse_edge(payload: dict) -> AlignmentEdge: return AlignmentEdge( source_id=payload["source_id"], target_id=payload["target_id"], relation=payload["relation"], weight=float(payload["weight"]), evidence_ids=tuple(payload.get("evidence_ids", [])), ) def load_alignment(pack_id: str) -> AlignmentGraph: """ Load AlignmentEdge records from language_packs/data//alignment.jsonl. Returns an empty AlignmentGraph if the file does not exist. This is intentional: operational_base packs (en_minimal_v1) do not currently carry cross-language alignment edges. """ alignment_path = _DATA_DIR / pack_id / "alignment.jsonl" if not alignment_path.exists(): return AlignmentGraph([]) edges: list[AlignmentEdge] = [] for line in alignment_path.read_text(encoding="utf-8").splitlines(): line = line.strip() if line: edges.append(_parse_edge(json.loads(line))) return AlignmentGraph(edges)