Implement core physics and pack validation

This commit is contained in:
Shay 2026-05-14 12:35:19 -07:00
parent fbbd7c52e3
commit 6bad4189d2
43 changed files with 1365 additions and 686 deletions

View file

@ -8,6 +8,9 @@ import numpy as np
from algebra.versor import versor_condition
from core.config import DEFAULT_CONFIG, RuntimeConfig
from core.physics.drive import GradientField, ValueAxis
from core.physics.exertion import CycleCost, ExertionMeter
from core.physics.identity import IdentityManifold
from generate.articulation import ArticulationPlan, realize
from generate.dialogue import DialogueRole, classify_dialogue_blade, propose_dialogue
from generate.proposition import FrameRegistry, Proposition, propose
@ -94,6 +97,12 @@ class ChatRuntime:
self._pos_by_surface = {
e.surface: (e.pos or e.part_of_speech or "X") for e in entries
}
self.identity_manifold = _default_identity_manifold()
self.exertion_meter = ExertionMeter(capacity_ceiling=128.0)
self.drive_gradients = tuple(
GradientField(axis=axis, magnitude=0.75)
for axis in self.identity_manifold.value_axes
)
@property
def session(self) -> SessionContext:
@ -190,6 +199,15 @@ class ChatRuntime:
salience_top_k=self.config.salience_top_k,
inhibition_threshold=self.config.inhibition_threshold,
)
self.exertion_meter.record(
CycleCost(
cycle_index=self._context.turn,
attention_cost=float(result.candidates_used or 0),
inhibition_cost=float(self.config.inhibition_threshold),
digest_cost=0.0,
trajectory_cost=float(len(result.trajectory or ())),
)
)
self._context.state = result.final_state
self._context.vault.store(
result.final_state.F,
@ -216,3 +234,31 @@ class ChatRuntime:
return self.chat(text, max_tokens=max_tokens).surface
except ValueError:
return ""
def _default_identity_manifold() -> IdentityManifold:
axes = (
ValueAxis(
axis_id="truthfulness",
name="truthfulness",
direction=(1.0, 0.0, 0.0),
theological_note="Truth is treated as a fixed value axis, not a prompt preference.",
),
ValueAxis(
axis_id="coherence",
name="coherence",
direction=(0.0, 1.0, 0.0),
theological_note="Operations must preserve field coherence under propagation.",
),
ValueAxis(
axis_id="reverence",
name="reverence",
direction=(0.0, 0.0, 1.0),
theological_note="Depth-language handling remains bounded by source structure.",
),
)
return IdentityManifold(
value_axes=axes,
boundary_ids=frozenset({"no_fabricated_source", "no_hot_path_repair"}),
alignment_threshold=0.75,
)

View file

@ -95,7 +95,10 @@ def cmd_chat(args: argparse.Namespace) -> int:
def cmd_test(args: argparse.Namespace) -> int:
"""Run pytest. Extra args are forwarded unchanged."""
default_args = ["-q", "--tb=short"]
return _run(sys.executable, "-m", "pytest", *(args.args or default_args))
forwarded = list(args.args or default_args)
if forwarded and forwarded[0] == "--":
forwarded = forwarded[1:]
return _run(sys.executable, "-m", "pytest", *forwarded)
def cmd_check(args: argparse.Namespace) -> int:
@ -276,6 +279,31 @@ def cmd_pack_verify(args: argparse.Namespace) -> int:
return _run(sys.executable, "-m", "language_packs", "verify", args.pack_id)
def cmd_pack_validate(args: argparse.Namespace) -> int:
"""Run executable source-pack validation gates."""
import importlib.util
pack_dir = _REPO_ROOT / "packs" / args.pack_id
validator_path = pack_dir / "validators.py"
if not validator_path.exists():
_die(f"source-pack validator not found: {validator_path}", code=1)
spec = importlib.util.spec_from_file_location(f"{args.pack_id}_validators", validator_path)
if spec is None or spec.loader is None:
_die(f"cannot load source-pack validator: {validator_path}", code=1)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
report = module.validate_pack()
if args.json:
print(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True))
else:
print(f"pack_id: {report['pack_id']}")
print(f"active : {report['active']}")
for name, result in report["gates"].items():
status = "PASS" if result["passed"] else "FAIL"
print(f"{status} {name:<12} {result['reason']}")
return 0 if report["active"] else 1
def _print_rust_status() -> bool:
from algebra.backend import using_rust
@ -434,6 +462,10 @@ def build_parser() -> argparse.ArgumentParser:
pack_verify = pack_sub.add_parser("verify", help="verify a pack checksum")
pack_verify.add_argument("pack_id", help="pack id, e.g. en_minimal_v1")
pack_verify.set_defaults(func=cmd_pack_verify)
pack_validate = pack_sub.add_parser("validate", help="validate a source pack under packs/")
pack_validate.add_argument("pack_id", help="source pack id, e.g. en, he, grc, el")
pack_validate.add_argument("--json", action="store_true", help="emit machine-readable JSON")
pack_validate.set_defaults(func=cmd_pack_validate)
rust = subparsers.add_parser(
"rust",

View file

@ -10,6 +10,8 @@ State lives in the FieldState; operators are pure transformations.
"""
from core.physics.salience import SalienceOperator, SalienceMap, FieldRegion
from core.physics.energy import EnergyClass, EnergyProfile, FieldEnergyOperator
from core.physics.valence import ValenceBundle
from core.physics.attention import AttentionOperator, AttentionPlan, CoherenceBudget
from core.physics.inhibition import InhibitionOperator, InhibitionMask
from core.physics.binding import BindingFrame, BindingOperator
@ -19,9 +21,11 @@ from core.physics.articulation import ArticulationPlan, ArticulationPlanner, Out
from core.physics.drive import DriveGradientMap, GradientField, ValueAxis
from core.physics.exertion import ExertionMeter, FatigueIndex, CycleCost
from core.physics.identity import IdentityManifold, IdentityCheck, IdentityScore, CharacterProfile
from core.physics.learning import PromotionDecision, VaultPromotionPolicy
__all__ = [
"SalienceOperator", "SalienceMap", "FieldRegion",
"EnergyClass", "EnergyProfile", "FieldEnergyOperator", "ValenceBundle",
"AttentionOperator", "AttentionPlan", "CoherenceBudget",
"InhibitionOperator", "InhibitionMask",
"BindingFrame", "BindingOperator",
@ -31,4 +35,5 @@ __all__ = [
"DriveGradientMap", "GradientField", "ValueAxis",
"ExertionMeter", "FatigueIndex", "CycleCost",
"IdentityManifold", "IdentityCheck", "IdentityScore", "CharacterProfile",
"PromotionDecision", "VaultPromotionPolicy",
]

View file

@ -7,6 +7,7 @@ Each output segment carries full field provenance.
"""
from __future__ import annotations
import hashlib
from dataclasses import dataclass
from enum import Enum, auto
from typing import Tuple
@ -51,4 +52,55 @@ class ArticulationPlanner:
trajectory,
modality: OutputModality,
) -> ArticulationPlan:
raise NotImplementedError("ArticulationPlanner.plan: implement plan construction")
segments: list[ArticulationSegment] = []
for idx, frame in enumerate(trajectory.frames):
confidence = max(0.0, min(1.0, float(frame.coherence_magnitude)))
source_regions = tuple(sorted(str(region_id) for region_id in frame.region_ids))
segment_id = _segment_id(trajectory.trajectory_id, frame.frame_id, idx)
segments.append(
ArticulationSegment(
segment_id=segment_id,
source_frame_id=frame.frame_id,
source_region_ids=source_regions,
confidence=confidence,
modality=modality,
formatting_constraints=_constraints_for(modality),
)
)
overall = (
sum(segment.confidence for segment in segments) / len(segments)
if segments
else 0.0
)
return ArticulationPlan(
plan_id=_plan_id(trajectory.trajectory_id, modality, tuple(segments)),
segments=tuple(segments),
source_trajectory_id=trajectory.trajectory_id,
target_modality=modality,
overall_confidence=overall,
)
def _constraints_for(modality: OutputModality) -> Tuple[str, ...]:
if modality is OutputModality.CODE:
return ("preserve_syntax", "monospace")
if modality is OutputModality.STRUCTURED_DATA:
return ("machine_readable", "schema_stable")
if modality is OutputModality.HEBREW:
return ("rtl", "preserve_script")
if modality is OutputModality.KOINE_GREEK:
return ("polytonic", "preserve_script")
return ("plain_text",)
def _segment_id(trajectory_id: str, frame_id: str, idx: int) -> str:
return hashlib.sha256(f"{trajectory_id}:{frame_id}:{idx}".encode("utf-8")).hexdigest()
def _plan_id(trajectory_id: str, modality: OutputModality, segments: Tuple[ArticulationSegment, ...]) -> str:
h = hashlib.sha256()
h.update(trajectory_id.encode("utf-8"))
h.update(modality.name.encode("ascii"))
for segment in segments:
h.update(segment.segment_id.encode("utf-8"))
return h.hexdigest()

View file

@ -48,4 +48,27 @@ class AttentionOperator:
"""Produces an AttentionPlan from a SalienceMap and CoherenceBudget."""
def plan(self, salience_map, budget: CoherenceBudget, cycle_index: int) -> AttentionPlan:
raise NotImplementedError("AttentionOperator.plan: implement traversal scheduling")
steps: list[TraversalStep] = []
spent = 0.0
max_curvature = max(
(float(entry.curvature_magnitude) for entry in salience_map.entries),
default=0.0,
)
if max_curvature <= 0.0:
return AttentionPlan(steps=(), total_cost=0.0, cycle_index=cycle_index)
for entry in salience_map.entries:
depth = max(0.0, min(1.0, float(entry.curvature_magnitude) / max_curvature))
duration = max(1.0, float(entry.influence_radius))
cost = depth * duration
if spent + cost > budget.available:
break
steps.append(
TraversalStep(
region_id=entry.region_id,
depth=depth,
duration=duration,
cost=cost,
)
)
spent += cost
return AttentionPlan(steps=tuple(steps), total_cost=spent, cycle_index=cycle_index)

View file

@ -6,6 +6,7 @@ by coherence threshold, not by clock tick.
"""
from __future__ import annotations
import hashlib
from dataclasses import dataclass
from typing import FrozenSet
@ -34,4 +35,45 @@ class BindingOperator:
coherence_threshold: float,
cycle_index: int,
) -> BindingFrame | None:
raise NotImplementedError("BindingOperator.bind: implement co-activation fusion")
region_ids = _region_ids(attention_plan)
if not region_ids:
return None
coherence = _coherence(attention_plan, field_state)
if coherence < coherence_threshold:
return None
ordered = tuple(sorted(region_ids))
frame_id = _hash_parts(("frame", str(cycle_index), *ordered))
content_address = _hash_parts((frame_id, f"{coherence:.12f}", *ordered))
return BindingFrame(
frame_id=frame_id,
region_ids=frozenset(ordered),
coherence_magnitude=coherence,
cycle_index=cycle_index,
content_address=content_address,
)
def _region_ids(attention_plan) -> frozenset[str]:
if hasattr(attention_plan, "steps"):
return frozenset(str(step.region_id) for step in attention_plan.steps)
if hasattr(attention_plan, "allowed_indices"):
return frozenset(str(int(idx)) for idx in attention_plan.allowed_indices)
return frozenset()
def _coherence(attention_plan, field_state) -> float:
if hasattr(attention_plan, "steps") and attention_plan.steps:
depths = [float(step.depth) for step in attention_plan.steps]
return max(0.0, min(1.0, sum(depths) / len(depths)))
energy = getattr(field_state, "energy", None)
if energy is not None:
return max(0.0, min(1.0, float(energy.raw)))
return 1.0 if _region_ids(attention_plan) else 0.0
def _hash_parts(parts: tuple[str, ...]) -> str:
h = hashlib.sha256()
for part in parts:
h.update(part.encode("utf-8"))
h.update(b"\0")
return h.hexdigest()

View file

@ -9,6 +9,10 @@ regions. It propagates a coherence wave outward from the binding frame.
from __future__ import annotations
from dataclasses import dataclass
import numpy as np
from field.state import FieldState
@dataclass(frozen=True)
class DigestCycle:
@ -28,6 +32,25 @@ class DigestOperator:
def digest(self, binding_frame, field_state, budget_reserve: float) -> tuple:
"""Returns (updated_field_state, DigestCycle)."""
raise NotImplementedError(
"DigestOperator.digest: implement coherence wave propagation"
coherence = max(0.0, min(1.0, float(binding_frame.coherence_magnitude)))
budget = max(0.0, float(budget_reserve))
consumed = min(budget, coherence * max(1, len(binding_frame.region_ids)))
radius = consumed / max(1, len(binding_frame.region_ids))
updated = FieldState(
F=np.asarray(field_state.F).copy(),
node=field_state.node,
step=field_state.step + 1,
holonomy=field_state.holonomy,
energy=getattr(field_state, "energy", None),
valence=getattr(field_state, "valence", None),
)
return (
updated,
DigestCycle(
frame_id=binding_frame.frame_id,
propagation_radius=radius,
coherence_delta=coherence * radius,
cycle_index=binding_frame.cycle_index,
budget_consumed=consumed,
),
)

View file

@ -8,7 +8,7 @@ into a combined gradient landscape.
from __future__ import annotations
from dataclasses import dataclass
from typing import Dict, Tuple
from typing import Tuple
@dataclass(frozen=True)
@ -35,4 +35,12 @@ class DriveGradientMap:
def combined_bias(self, coordinates: Tuple[float, ...]) -> Tuple[float, ...]:
"""Return the additive gradient bias vector at the given field coordinates."""
raise NotImplementedError("DriveGradientMap.combined_bias: implement gradient composition")
if not coordinates:
return ()
bias = [0.0 for _ in coordinates]
for gradient in self.gradients:
if not gradient.active:
continue
for idx, component in enumerate(gradient.axis.direction[: len(bias)]):
bias[idx] += float(component) * float(gradient.magnitude)
return tuple(bias)

118
core/physics/energy.py Normal file
View file

@ -0,0 +1,118 @@
"""core.physics.energy — ADR-0006 scalar companion classes.
The operator assigns a bounded thermodynamic class from structural inputs:
convergence density, recent activation, coherence residual, and morphology
aspect. It does not inspect grades, repair fields, or normalize anything.
"""
from __future__ import annotations
from dataclasses import dataclass
from enum import Enum
from math import exp, log1p
from typing import Mapping
class EnergyClass(str, Enum):
E0 = "E0"
E1 = "E1"
E2 = "E2"
E3 = "E3"
E4 = "E4"
@property
def vault_candidate(self) -> bool:
return self in {EnergyClass.E0, EnergyClass.E1}
@property
def governance_critical(self) -> bool:
return self is EnergyClass.E4
@dataclass(frozen=True, slots=True)
class EnergyProfile:
raw: float
energy_class: EnergyClass
convergence_density: int = 0
activation_count: int = 0
last_activation_cycle: int = 0
coherence_residual: float = 0.0
aspect_weight: float = 0.0
anchor_adjacent: bool = False
@property
def requires_architect_review(self) -> bool:
return self.energy_class.governance_critical or (
self.anchor_adjacent and self.energy_class in {EnergyClass.E3, EnergyClass.E4}
)
_ASPECT_WEIGHTS: dict[str, float] = {
"qatal": 0.15,
"aorist": 0.15,
"wayyiqtol": 0.45,
"perfect": 0.25,
"yiqtol": 0.65,
"imperfect": 0.70,
"present": 0.65,
"cohortative": 0.55,
"optative": 0.50,
"imperative": 0.90,
"jussive": 0.60,
"subjunctive": 0.55,
}
def aspect_weight(features: Mapping[str, object] | None) -> float:
if not features:
return 0.0
values = [
str(value).lower()
for key, value in features.items()
if key in {"aspect", "tense", "mood"}
]
return max((_ASPECT_WEIGHTS.get(value, 0.0) for value in values), default=0.0)
class FieldEnergyOperator:
"""Compute ADR-0006 energy class from explicit structural inputs."""
def compute(
self,
*,
convergence_density: int = 0,
activation_count: int = 0,
current_cycle: int = 0,
last_activation_cycle: int = 0,
coherence_residual: float = 0.0,
morphology_features: Mapping[str, object] | None = None,
anchor_adjacent: bool = False,
) -> EnergyProfile:
convergence = min(log1p(max(0, convergence_density)) / log1p(8), 1.0)
age = max(0, int(current_cycle) - int(last_activation_cycle))
recency = min(max(0, activation_count), 8) / 8.0 * exp(-age / 12.0)
residual = min(max(0.0, float(coherence_residual)), 1.0)
aspect = aspect_weight(morphology_features)
raw = (0.35 * convergence) + (0.25 * recency) + (0.20 * residual) + (0.20 * aspect)
if anchor_adjacent and raw >= 0.72:
energy_class = EnergyClass.E4
elif raw >= 0.82:
energy_class = EnergyClass.E4
elif raw >= 0.62:
energy_class = EnergyClass.E3
elif raw >= 0.38:
energy_class = EnergyClass.E2
elif raw >= 0.16:
energy_class = EnergyClass.E1
else:
energy_class = EnergyClass.E0
return EnergyProfile(
raw=raw,
energy_class=energy_class,
convergence_density=max(0, convergence_density),
activation_count=max(0, activation_count),
last_activation_cycle=max(0, last_activation_cycle),
coherence_residual=residual,
aspect_weight=aspect,
anchor_adjacent=anchor_adjacent,
)

View file

@ -43,7 +43,28 @@ class IdentityCheck:
"""Checks a ReasoningTrajectory against an IdentityManifold."""
def check(self, trajectory, manifold: IdentityManifold) -> IdentityScore:
raise NotImplementedError("IdentityCheck.check: implement manifold alignment check")
if not manifold.value_axes:
return IdentityScore(
score=1.0,
flagged=False,
deviation_axes=frozenset(),
trajectory_id=trajectory.trajectory_id,
)
confidence = getattr(trajectory, "total_coherence_delta", 0.0)
if trajectory.frames:
confidence += sum(float(frame.coherence_magnitude) for frame in trajectory.frames) / len(trajectory.frames)
score = max(0.0, min(1.0, 0.5 + (confidence / 2.0)))
deviations = frozenset(
axis.axis_id
for axis in manifold.value_axes
if score < manifold.alignment_threshold
)
return IdentityScore(
score=score,
flagged=score < manifold.alignment_threshold,
deviation_axes=deviations,
trajectory_id=trajectory.trajectory_id,
)
@dataclass(frozen=True)

View file

@ -28,6 +28,27 @@ class InhibitionOperator:
"""
def mask(self, attention_plan, field_state, cycle_index: int) -> InhibitionMask:
raise NotImplementedError(
"InhibitionOperator.mask: implement interference suppression"
active = _active_regions(attention_plan)
suppressed = _candidate_regions(field_state) - active
coherence_delta = min(1.0, 0.05 * len(suppressed))
return InhibitionMask(
suppressed_region_ids=frozenset(sorted(suppressed)),
suppression_reason="outside_attention_plan",
coherence_delta=coherence_delta,
cycle_index=cycle_index,
)
def _active_regions(attention_plan) -> set[str]:
if hasattr(attention_plan, "steps"):
return {str(step.region_id) for step in attention_plan.steps}
if hasattr(attention_plan, "allowed_indices"):
return {str(int(idx)) for idx in attention_plan.allowed_indices}
return set()
def _candidate_regions(field_state) -> set[str]:
candidates = getattr(field_state, "candidate_region_ids", None)
if candidates is None:
return set()
return {str(region_id) for region_id in candidates}

32
core/physics/learning.py Normal file
View file

@ -0,0 +1,32 @@
"""core.physics.learning — ADR-0014 vault promotion criteria."""
from __future__ import annotations
from dataclasses import dataclass
from core.physics.energy import EnergyClass, EnergyProfile
@dataclass(frozen=True, slots=True)
class PromotionDecision:
promote: bool
reason: str
energy_class: EnergyClass
class VaultPromotionPolicy:
"""Promote only settled, coherent regions into deep vault storage."""
def __init__(self, residual_threshold: float = 0.05) -> None:
if residual_threshold < 0.0:
raise ValueError("residual_threshold must be non-negative")
self.residual_threshold = float(residual_threshold)
def decide(self, energy: EnergyProfile | None) -> PromotionDecision:
if energy is None:
return PromotionDecision(False, "missing_energy_profile", EnergyClass.E2)
if not energy.energy_class.vault_candidate:
return PromotionDecision(False, "region_still_active", energy.energy_class)
if energy.coherence_residual > self.residual_threshold:
return PromotionDecision(False, "coherence_residual_above_threshold", energy.energy_class)
return PromotionDecision(True, "settled_coherent_region", energy.energy_class)

View file

@ -7,7 +7,8 @@ Trajectories are append-only; no in-place mutation after construction.
"""
from __future__ import annotations
from dataclasses import dataclass, field
import hashlib
from dataclasses import dataclass
from typing import FrozenSet, Tuple
@ -37,6 +38,42 @@ class TrajectoryOperator:
"""Builds a ReasoningTrajectory from an ordered sequence of BindingFrames."""
def build(self, frames: list, trajectory_id: str) -> ReasoningTrajectory:
raise NotImplementedError(
"TrajectoryOperator.build: implement trajectory construction"
ordered = tuple(frames)
transitions: list[TrajectoryTransition] = []
for left, right in zip(ordered, ordered[1:]):
left_regions = set(left.region_ids)
right_regions = set(right.region_ids)
spine = frozenset(left_regions & right_regions)
diff = frozenset(left_regions ^ right_regions)
delta = float(right.coherence_magnitude) - float(left.coherence_magnitude)
transitions.append(
TrajectoryTransition(
from_frame_id=left.frame_id,
to_frame_id=right.frame_id,
pressure_delta=delta,
continuity_spine=spine,
differential_set=diff,
coherence_won=max(0.0, delta),
coherence_lost=max(0.0, -delta),
)
)
total = sum(t.pressure_delta for t in transitions)
if ordered:
span = (ordered[0].cycle_index, ordered[-1].cycle_index)
else:
span = (0, 0)
resolved_id = trajectory_id or _trajectory_id(ordered)
return ReasoningTrajectory(
trajectory_id=resolved_id,
frames=ordered,
transitions=tuple(transitions),
total_coherence_delta=float(total),
cycle_span=span,
)
def _trajectory_id(frames: tuple) -> str:
h = hashlib.sha256()
for frame in frames:
h.update(frame.frame_id.encode("utf-8"))
return h.hexdigest()

View file

@ -7,8 +7,11 @@ of neighboring regions — when it bends the field around itself.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Dict, Tuple
import hashlib
from dataclasses import dataclass
from typing import Tuple
import numpy as np
@dataclass(frozen=True)
@ -55,12 +58,51 @@ class SalienceOperator:
"""
def compute(self, regions: Tuple[FieldRegion, ...], cycle_index: int) -> SalienceMap:
"""Compute salience for the given field regions.
Stub: full curvature kernel implemented in Rust hot-path.
Python fallback uses pairwise pressure gradient approximation.
"""
raise NotImplementedError(
"SalienceOperator.compute is a Rust hot-path stub. "
"Implement in core_rs::physics::salience or provide Python fallback."
"""Compute local curvature by pairwise pressure-gradient deflection."""
if not regions:
return SalienceMap(entries=(), cycle_index=cycle_index, content_address=_salience_address(()))
coords = [np.asarray(region.coordinates, dtype=np.float64) for region in regions]
entries: list[SalienceEntry] = []
for idx, region in enumerate(regions):
gradient = np.zeros_like(coords[idx], dtype=np.float64)
curvature = 0.0
radius_num = 0.0
radius_den = 0.0
for jdx, neighbor in enumerate(regions):
if idx == jdx:
continue
delta = coords[jdx] - coords[idx]
distance = max(float(np.linalg.norm(delta)), 1e-8)
pressure_delta = abs(float(neighbor.pressure_magnitude) - float(region.pressure_magnitude))
contribution = pressure_delta / (distance * distance)
direction = delta / distance
gradient += direction * contribution
curvature += contribution
radius_num += distance * contribution
radius_den += contribution
gradient_tuple = tuple(float(v) for v in gradient)
entries.append(
SalienceEntry(
region_id=region.region_id,
curvature_magnitude=float(curvature),
gradient_vector=gradient_tuple,
influence_radius=float(radius_num / radius_den) if radius_den > 0.0 else 0.0,
)
)
ordered = tuple(
sorted(entries, key=lambda entry: (-entry.curvature_magnitude, entry.region_id))
)
return SalienceMap(
entries=ordered,
cycle_index=cycle_index,
content_address=_salience_address(ordered),
)
def _salience_address(entries: Tuple[SalienceEntry, ...]) -> str:
h = hashlib.sha256()
for entry in entries:
h.update(entry.region_id.encode("utf-8"))
h.update(f":{entry.curvature_magnitude:.12f}:".encode("ascii"))
h.update(",".join(f"{v:.12f}" for v in entry.gradient_vector).encode("ascii"))
return h.hexdigest()

156
core/physics/valence.py Normal file
View file

@ -0,0 +1,156 @@
"""core.physics.valence — ADR-0007 valence bundle and deterministic lifting."""
from __future__ import annotations
import json
from dataclasses import asdict, dataclass, field
from enum import Enum
from typing import Mapping
class ForceClass(str, Enum):
DECLARATIVE = "declarative"
PERFORMATIVE = "performative"
IMPERATIVE = "imperative"
COHORTATIVE = "cohortative"
JUSSIVE = "jussive"
INTERROGATIVE = "interrogative"
OPTATIVE = "optative"
EXPRESSIVE = "expressive"
COMMISSIVE = "commissive"
@dataclass(frozen=True, slots=True)
class EmphasisProfile:
focus_element: str | None = None
mechanism: str = "unmarked"
degree: str = "unmarked"
@dataclass(frozen=True, slots=True)
class PolaritySpec:
value: str = "positive"
kind: str | None = None
@dataclass(frozen=True, slots=True)
class OrientationSpec:
direction: str = "within"
target: str | None = None
preposition_source: str | None = None
@dataclass(frozen=True, slots=True)
class ValenceBundle:
affective: frozenset[str] = field(default_factory=frozenset)
force: ForceClass = ForceClass.DECLARATIVE
emphasis: EmphasisProfile = field(default_factory=EmphasisProfile)
polarity: PolaritySpec = field(default_factory=PolaritySpec)
orientation: OrientationSpec = field(default_factory=OrientationSpec)
def to_payload(self) -> dict[str, object]:
payload = asdict(self)
payload["affective"] = sorted(self.affective)
payload["force"] = self.force.value
return payload
def to_json(self) -> str:
return json.dumps(self.to_payload(), sort_keys=True, separators=(",", ":"))
_NEGATIVE_PARTICLES = {
"lo": "absolute",
"לֹא": "absolute",
"al": "prohibitive",
"אַל": "prohibitive",
"ou": "factual",
"οὐ": "factual",
"me": "conditional",
"μή": "conditional",
}
_ORIENTATION_BY_PREPOSITION = {
"pros": "toward",
"πρός": "toward",
"en": "within",
"ἐν": "within",
"ek": "from",
"ἐκ": "from",
"apo": "from",
"ἀπό": "from",
"dia": "through",
"διά": "through",
"hypo": "under",
"ὑπό": "under",
"epi": "upon",
"ἐπί": "upon",
"para": "alongside",
"παρά": "alongside",
}
def lift_valence(
*,
lemma: str,
language: str,
features: Mapping[str, object] | None = None,
notes: str | None = None,
) -> ValenceBundle:
"""Lift valence deterministically from morphology and pack notes."""
features = dict(features or {})
lower_lemma = lemma.lower()
lower_notes = (notes or "").lower()
mood = str(features.get("mood", "")).lower()
stem = str(features.get("stem", "")).lower()
tense = str(features.get("tense", "")).lower()
force = ForceClass.DECLARATIVE
if "divine" in lower_notes and ("create" in lower_notes or "creation" in lower_notes):
force = ForceClass.PERFORMATIVE
elif mood == "imperative":
force = ForceClass.IMPERATIVE
elif mood == "cohortative":
force = ForceClass.COHORTATIVE
elif mood == "jussive":
force = ForceClass.JUSSIVE
elif mood == "optative":
force = ForceClass.OPTATIVE
affective: set[str] = set()
if "divine" in lower_notes or lower_lemma in {"θεός", "god"}:
affective.add("awe")
if "truth" in lower_notes or lower_lemma in {"אמת", "ἀλήθεια", "truth"}:
affective.add("peace")
if "life" in lower_notes or lower_lemma in {"ζωή", "life"}:
affective.add("exultation")
mechanism = "unmarked"
degree = "unmarked"
if stem in {"piel", "intensive"}:
mechanism = "stem_intensification"
degree = "strong"
elif "front" in lower_notes:
mechanism = "fronting"
degree = "strong"
elif "anarthrous" in lower_notes:
mechanism = "particle"
degree = "light"
neg_kind = _NEGATIVE_PARTICLES.get(lower_lemma)
polarity = PolaritySpec(
value="negative" if neg_kind else "positive",
kind=neg_kind,
)
direction = _ORIENTATION_BY_PREPOSITION.get(lower_lemma, "within")
orientation = OrientationSpec(
direction=direction,
preposition_source=lemma if direction != "within" or lower_lemma in _ORIENTATION_BY_PREPOSITION else None,
)
if tense in {"imperfect", "present"} and force is ForceClass.DECLARATIVE:
degree = "light" if degree == "unmarked" else degree
return ValenceBundle(
affective=frozenset(affective),
force=force,
emphasis=EmphasisProfile(focus_element=lemma, mechanism=mechanism, degree=degree),
polarity=polarity,
orientation=orientation,
)

View file

@ -29,7 +29,6 @@ from typing import TYPE_CHECKING, Sequence
from core_ingest.types import (
CandidateGeometricPressure,
DeterminismClass,
GateDisposition,
LearningArtifact,
ReviewDecision,
@ -90,9 +89,20 @@ class SemanticGate:
def check(self, packet: CandidateGeometricPressure) -> str | None:
import json
from core_ingest.types import Modality
from core.physics.energy import EnergyClass
if packet.payload_json in ("{}", ""):
return "payload_json is empty — no content to ingest"
payload = json.loads(packet.payload_json)
if "energy_class_hint" in payload:
try:
EnergyClass(str(payload["energy_class_hint"]))
except ValueError:
return f"invalid energy_class_hint: {payload['energy_class_hint']!r}"
if "valence" in payload:
failure = _validate_valence_payload(payload["valence"])
if failure is not None:
return failure
# Require non-empty lemma for text / scripture
if packet.modality in (Modality.TEXT, Modality.SCRIPTURE) and not packet.lemma:
@ -137,8 +147,17 @@ class GovernanceGate:
packet: CandidateGeometricPressure,
authorized_ids: frozenset[str],
) -> GateDisposition:
import json
if packet.review_level == ReviewLevel.AUTO_REJECT:
return GateDisposition.REJECTED_GOVERNANCE
payload = json.loads(packet.payload_json)
if payload.get("energy_class_hint") == "E4":
if packet.review_level != ReviewLevel.ARCHITECT_REVIEW_REQUIRED:
return GateDisposition.REJECTED_GOVERNANCE
if packet.pressure_id in authorized_ids:
return GateDisposition.OVERRIDE_ACCEPTED
return GateDisposition.REJECTED_GOVERNANCE
# Override: an authorized ReviewDecision accepts regardless of level
if packet.pressure_id in authorized_ids:
@ -155,6 +174,21 @@ class GovernanceGate:
return GateDisposition.REJECTED_GOVERNANCE
def _validate_valence_payload(valence: object) -> str | None:
if not isinstance(valence, dict):
return "valence must be an object"
required = {"affective", "force", "emphasis", "polarity", "orientation"}
missing = required - set(valence)
if missing:
return f"valence missing required channel(s): {', '.join(sorted(missing))}"
if not isinstance(valence["affective"], list):
return "valence.affective must be a list"
for key in ("emphasis", "polarity", "orientation"):
if not isinstance(valence[key], dict):
return f"valence.{key} must be an object"
return None
# ---------------------------------------------------------------------------
# Compiler
# ---------------------------------------------------------------------------

View file

@ -21,4 +21,11 @@ def propagate_step(state: FieldState, V) -> FieldState:
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, holonomy=state.holonomy)
return FieldState(
F=new_F,
node=state.node,
step=state.step + 1,
holonomy=state.holonomy,
energy=state.energy,
valence=state.valence,
)

View file

@ -12,8 +12,13 @@ reference to the array passed in and expect coherence.
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING
import numpy as np
if TYPE_CHECKING:
from core.physics.energy import EnergyProfile
from core.physics.valence import ValenceBundle
_EXPECTED_COMPONENTS = 32
@ -23,6 +28,8 @@ class FieldState:
node: int = 0 # current node index in the vocabulary manifold
step: int = 0 # number of propagation steps taken
holonomy: np.ndarray | None = None
energy: EnergyProfile | None = None
valence: ValenceBundle | None = None
def __post_init__(self) -> None:
# Enforce copy + dtype + shape at the construction boundary.
@ -54,4 +61,11 @@ class FieldState:
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, holonomy=self.holonomy)
return FieldState(
F=new_F,
node=new_node,
step=self.step + 1,
holonomy=self.holonomy,
energy=self.energy,
valence=self.valence,
)

View file

@ -5,6 +5,7 @@ from dataclasses import dataclass
import numpy as np
from algebra.backend import cga_inner
from core.physics.salience import FieldRegion, SalienceOperator as CurvatureSalienceOperator
from field.state import FieldState
from vocab.manifold import VocabManifold
@ -23,13 +24,11 @@ class SalienceMap:
class SalienceOperator:
"""
Compute geometric salience of manifold points relative to current FieldState.
Compute generation-facing salience from ADR-0008 field curvature.
Salience is field-relative CGA activation:
salience(v_i) = |cga_inner(F, v_i)| / (||F|| * ||v_i||)
No learned weights. No softmax. Pure geometry routed through algebra.backend,
which uses core_rs when active.
The live API still returns manifold indices for generation, but the score is
now a local curvature magnitude from core.physics.salience rather than
normalized proximity to the query field.
"""
def compute(self, field: FieldState, vocab: VocabManifold, top_k: int = 16) -> SalienceMap:
@ -38,15 +37,26 @@ class SalienceOperator:
if len(vocab) == 0:
return SalienceMap(indices=np.asarray([], dtype=np.int64), scores=np.asarray([], dtype=np.float32), budget=0)
query = np.asarray(field.F, dtype=np.float32)
query_norm = max(float(np.linalg.norm(query)), 1e-8)
scores: list[float] = []
active = vocab.get_versor_at(field.node)
regions: list[FieldRegion] = []
for idx in range(len(vocab)):
v = vocab.get_versor_at(idx)
denom = query_norm * max(float(np.linalg.norm(v)), 1e-8)
scores.append(abs(float(cga_inner(query, v))) / denom)
energy = vocab.energy_for_word(vocab.get_word_at(idx))
baseline = energy.raw if energy is not None else 0.1
active_distance = max(0.0, -2.0 * float(cga_inner(active, v)))
pressure = baseline + (1.0 / (1.0 + active_distance))
regions.append(
FieldRegion(
region_id=str(idx),
coordinates=tuple(float(x) for x in np.asarray(v, dtype=np.float32)),
pressure_magnitude=pressure,
)
)
scores_arr = np.asarray(scores, dtype=np.float32)
curvature = CurvatureSalienceOperator().compute(tuple(regions), cycle_index=field.step)
scores_arr = np.zeros(len(vocab), dtype=np.float32)
for entry in curvature.entries:
scores_arr[int(entry.region_id)] = float(entry.curvature_magnitude)
k = min(int(top_k), len(vocab))
order = np.argsort(-scores_arr, kind="stable")[:k]
return SalienceMap(indices=order.astype(np.int64), scores=scores_arr[order], budget=k)

View file

@ -80,15 +80,46 @@ def _nearest_next(
)
for extra in fallback_orders:
try:
return vocab.nearest(
return _nearest_with_optional_candidates(
vocab,
F_voiced,
exclude_idx=current_node,
exclude_indices=extra,
candidate_indices=candidate_indices,
current_node,
extra,
candidate_indices,
)
except ValueError:
continue
return vocab.nearest(F_voiced, candidate_indices=candidate_indices)
return _nearest_with_optional_candidates(
vocab,
F_voiced,
-1,
set(),
candidate_indices,
)
def _nearest_with_optional_candidates(
vocab,
F_voiced,
current_node: int,
exclude_indices: set[int],
candidate_indices: np.ndarray | None,
) -> tuple[str, int]:
try:
return vocab.nearest(
F_voiced,
exclude_idx=current_node,
exclude_indices=exclude_indices,
candidate_indices=candidate_indices,
)
except TypeError:
if candidate_indices is not None:
raise
return vocab.nearest(
F_voiced,
exclude_idx=current_node,
exclude_indices=exclude_indices,
)
def _voiced_state(state: FieldState, persona) -> FieldState:
@ -98,6 +129,8 @@ def _voiced_state(state: FieldState, persona) -> FieldState:
node=state.node,
step=state.step,
holonomy=state.holonomy,
energy=state.energy,
valence=state.valence,
)
@ -121,6 +154,8 @@ def _recall_state(state: FieldState, vault, top_k: int) -> FieldState:
node=state.node,
step=current.step,
holonomy=state.holonomy,
energy=state.energy,
valence=state.valence,
)
return current
@ -207,7 +242,7 @@ def generate(
)
candidate_indices = _intersect_candidates(language_candidates, salience_candidates)
if candidate_indices is not None and len(candidate_indices) == 0:
candidate_indices = language_candidates if language_candidates is not None else salience_candidates
candidate_indices = salience_candidates if salience_candidates is not None else language_candidates
candidates_used = None if candidate_indices is None else len(candidate_indices)
stop_nodes = frozenset(
@ -237,7 +272,14 @@ def generate(
V = word_transition_rotor(A, B)
current = propagate_step(current, V)
current = FieldState(F=current.F, node=word_idx, step=current.step, holonomy=current.holonomy)
current = FieldState(
F=current.F,
node=word_idx,
step=current.step,
holonomy=current.holonomy,
energy=current.energy,
valence=current.valence,
)
recent_nodes.append(word_idx)
return GenerationResult(
@ -288,5 +330,12 @@ async def agenerate(
V = word_transition_rotor(A, B)
current = propagate_step(current, V)
current = FieldState(F=current.F, node=word_idx, step=current.step, holonomy=current.holonomy)
current = FieldState(
F=current.F,
node=word_idx,
step=current.step,
holonomy=current.holonomy,
energy=current.energy,
valence=current.valence,
)
recent_nodes.append(word_idx)

View file

@ -30,6 +30,8 @@ import numpy as np
from algebra.cl41 import geometric_product
from algebra.versor import normalize_to_versor, versor_condition
from core.physics.energy import FieldEnergyOperator, EnergyClass
from core.physics.valence import ValenceBundle
from algebra.holonomy import holonomy_encode
from field.state import FieldState
from language_packs.schema import MorphologyEntry
@ -225,6 +227,66 @@ def _lookup_or_ground(token: str, vocab) -> np.ndarray:
return _ground_unknown_token(token, vocab)
def _field_energy(tokens: list, vocab) -> object | None:
energy_for_word = getattr(vocab, "energy_for_word", None)
morphology_for_word = getattr(vocab, "morphology_for_word", None)
if energy_for_word is None:
return None
profiles = [energy_for_word(token) for token in tokens]
profiles = [profile for profile in profiles if profile is not None]
features: dict[str, object] = {}
if morphology_for_word is not None:
for token in tokens:
morphology = morphology_for_word(token)
if morphology is not None:
features.update(dict(morphology.inflection))
if morphology.stem:
features.setdefault("stem", morphology.stem)
if not profiles and not features:
return None
max_class = max((profile.energy_class for profile in profiles), default=EnergyClass.E0, key=lambda cls: int(cls.value[1]))
residual = max((profile.coherence_residual for profile in profiles), default=0.0)
convergence = sum(profile.convergence_density for profile in profiles) or len(tokens)
activation = sum(profile.activation_count for profile in profiles) or 1
anchor_adjacent = any(profile.anchor_adjacent for profile in profiles)
computed = FieldEnergyOperator().compute(
convergence_density=convergence,
activation_count=activation,
morphology_features=features,
anchor_adjacent=anchor_adjacent,
coherence_residual=residual,
)
return computed if int(computed.energy_class.value[1]) >= int(max_class.value[1]) else max(profiles, key=lambda profile: int(profile.energy_class.value[1]))
def _field_valence(tokens: list, vocab) -> ValenceBundle | None:
valence_for_word = getattr(vocab, "valence_for_word", None)
if valence_for_word is None:
return None
bundles = [valence_for_word(token) for token in tokens]
bundles = [bundle for bundle in bundles if bundle is not None]
if not bundles:
return None
affective: set[str] = set()
for bundle in bundles:
affective.update(bundle.affective)
strongest = max(
bundles,
key=lambda bundle: (
bundle.force.value != "declarative",
bundle.emphasis.degree in {"strong", "absolute"},
len(bundle.affective),
),
)
return ValenceBundle(
affective=frozenset(affective),
force=strongest.force,
emphasis=strongest.emphasis,
polarity=strongest.polarity,
orientation=strongest.orientation,
)
def inject(tokens: list, vocab) -> FieldState:
"""
Encode a token sequence and inject into the versor manifold.
@ -246,4 +308,4 @@ def inject(tokens: list, vocab) -> FieldState:
"Check holonomy_encode() and normalize_to_versor()."
)
return FieldState(F=F, node=0, step=0, holonomy=H)
return FieldState(F=F, node=0, step=0, holonomy=H, energy=_field_energy(tokens, vocab), valence=_field_valence(tokens, vocab))

View file

@ -9,6 +9,8 @@ import numpy as np
from algebra.cl41 import N_COMPONENTS, geometric_product, reverse as cl_reverse
from algebra.versor import unitize_versor
from core.physics.energy import FieldEnergyOperator
from core.physics.valence import lift_valence
from language_packs.schema import (
LanguagePackManifest,
LanguageRole,
@ -28,6 +30,7 @@ _MORPHOLOGY_CLUSTER_NUDGE_STRENGTH: float = 0.40
_PRIMARY_SEMANTIC_DOMAIN_WEIGHT: float = 0.55
_LOGOS_PARTICIPATION_WEIGHT: float = 0.25
_FEATURE_COMPONENTS: tuple[int, ...] = (6, 7, 9, 10, 12, 14)
_ENERGY = FieldEnergyOperator()
def _hash_to_blade(name: str, salt: str) -> int:
@ -271,7 +274,28 @@ def compile_entries_to_manifold(entries: list[LexicalEntry], morphology_registry
for entry in entries:
morphology = _resolved_morphology(entry, morphology_registry)
versor = _entry_to_coordinate(entry, morphology)
manifold.add(entry.surface, versor, morphology=morphology, language=entry.language)
features = dict(morphology.inflection) if morphology is not None else {}
if morphology is not None and morphology.stem:
features.setdefault("stem", morphology.stem)
energy = _ENERGY.compute(
convergence_density=max(1, len(entry.provenance_ids)),
activation_count=1,
morphology_features=features,
anchor_adjacent=_has_logos_participation(entry.semantic_domains),
)
valence = lift_valence(
lemma=entry.lemma or entry.surface,
language=entry.language,
features=features,
)
manifold.add(
entry.surface,
versor,
morphology=morphology,
language=entry.language,
energy=energy,
valence=valence,
)
entry_id_to_surface[entry.entry_id] = entry.surface
if morphology_registry is not None:
@ -403,6 +427,8 @@ def load_mounted_packs(pack_ids: tuple[str, ...] | list[str]) -> VocabManifold:
manifold.get_versor_at(idx),
morphology=manifold.morphology_for_word(surface),
language=None if entry is None else entry.language,
energy=manifold.energy_for_word(surface),
valence=manifold.valence_for_word(surface),
)
if entry is not None and entry.semantic_domains:
primary_groups.setdefault(entry.semantic_domains[0].lower(), []).append(

View file

@ -0,0 +1,52 @@
"""Measured holonomy-resonance evidence helpers for ADR-0015."""
from __future__ import annotations
from dataclasses import dataclass
import numpy as np
from algebra.cga import cga_inner
from algebra.holonomy import holonomy_encode
@dataclass(frozen=True, slots=True)
class ResonanceEvidence:
case_id: str
aligned_score: float
contrast_score: float
@property
def passes(self) -> bool:
return self.aligned_score > self.contrast_score
def encode_clause(manifold, tokens: tuple[str, ...] | list[str]) -> np.ndarray:
return holonomy_encode([manifold.get_versor(token) for token in tokens])
def mean_pair_score(manifold, pairs: tuple[tuple[str, str], ...]) -> float:
if not pairs:
return 0.0
return float(
np.mean(
[
cga_inner(manifold.get_versor(left), manifold.get_versor(right))
for left, right in pairs
]
)
)
def resonance_evidence(
*,
case_id: str,
manifold,
aligned_pairs: tuple[tuple[str, str], ...],
contrast_pairs: tuple[tuple[str, str], ...],
) -> ResonanceEvidence:
return ResonanceEvidence(
case_id=case_id,
aligned_score=mean_pair_score(manifold, aligned_pairs),
contrast_score=mean_pair_score(manifold, contrast_pairs),
)

View file

@ -0,0 +1,122 @@
"""Deterministic runtime helpers for local language-pack rules."""
from __future__ import annotations
import hashlib
import json
from dataclasses import dataclass
from pathlib import Path
from typing import Any
from core.physics.energy import EnergyClass
from core.physics.valence import lift_valence
from core_ingest.types import (
CandidateGeometricPressure,
DeterminismClass,
FrontendTrace,
Modality,
ReviewLevel,
SourceSpan,
)
@dataclass(frozen=True, slots=True)
class SurfaceRealization:
surface: str
language: str
field_target: str | None = None
energy_class: str | None = None
valence: dict[str, object] | None = None
def read_jsonl(path: Path) -> list[dict[str, Any]]:
return [
json.loads(line)
for line in path.read_text(encoding="utf-8").splitlines()
if line.strip()
]
def analysis_payload(analysis: object) -> dict[str, Any]:
if isinstance(analysis, dict):
payload = dict(analysis.get("input", analysis))
else:
payload = dict(getattr(analysis, "__dict__", {}))
if not payload:
raise ValueError("analysis must expose lemma_id or sense_id fields")
return payload
def lift_from_pack(pack_dir: Path, analysis: object, *, language: str) -> list[CandidateGeometricPressure]:
payload = analysis_payload(analysis)
senses = {record["sense_id"]: record for record in read_jsonl(pack_dir / "senses.jsonl")}
lemmas = {record["lemma_id"]: record for record in read_jsonl(pack_dir / "lemmas.jsonl")}
sense = senses.get(str(payload.get("sense_id", "")))
lemma_id = str(payload.get("lemma_id") or (sense or {}).get("lemma_id") or "")
lemma = lemmas.get(lemma_id)
if lemma is None:
raise KeyError(f"unknown lemma_id: {lemma_id}")
field_target = str((sense or {}).get("field_target") or lemma["field_hooks"][0])
pressure_kind = str(payload.get("pressure_kind", "semantic"))
features = {
"morph_class": lemma.get("morph_class", ""),
"semantic_family": lemma.get("semantic_family", ""),
}
valence = lift_valence(
lemma=str(lemma["script_form"]),
language=language,
features=features,
).to_payload()
packet_payload = {
"field_target": field_target,
"pressure_kind": pressure_kind,
"energy_class_hint": EnergyClass.E2.value,
"valence": valence,
"source": {
"lemma_id": lemma_id,
"sense_id": payload.get("sense_id"),
"frame_id": payload.get("frame_id"),
},
}
canonical = json.dumps(packet_payload, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
digest = hashlib.sha256(canonical.encode("utf-8")).hexdigest()
span = SourceSpan(byte_start=0, byte_end=max(1, len(canonical.encode("utf-8"))), source_sha256=digest)
packet = CandidateGeometricPressure(
kind=pressure_kind,
modality=Modality.SCRIPTURE if language in {"he", "el", "grc"} else Modality.TEXT,
provenance=(span,),
frontend=FrontendTrace(
instrument_id=f"{language}.lift_rules",
determinism=DeterminismClass.D0,
version="1.0.0",
),
review_level=ReviewLevel.AUTO_ACCEPT_ELIGIBLE,
confidence=1.0,
uncertainty=0.0,
lemma=str(lemma["script_form"]),
payload_json=canonical,
)
return [packet]
def readback_from_intent(field_state: object, intent: object, *, language: str) -> SurfaceRealization:
payload = analysis_payload(intent or {"surface": ""})
surface = payload.get("surface")
if surface is None and "tokens" in payload:
surface = " ".join(str(token) for token in payload["tokens"])
if surface is None and "lemma" in payload:
surface = str(payload["lemma"])
if surface is None and "script_form" in payload:
surface = str(payload["script_form"])
if surface is None:
energy = getattr(field_state, "energy", None)
surface = energy.energy_class.value if energy is not None else ""
energy = getattr(field_state, "energy", None)
valence = getattr(field_state, "valence", None)
return SurfaceRealization(
surface=str(surface),
language=language,
field_target=payload.get("field_target"),
energy_class=None if energy is None else energy.energy_class.value,
valence=None if valence is None else valence.to_payload(),
)

133
packs/common/validator.py Normal file
View file

@ -0,0 +1,133 @@
"""Executable validation gates for local language packs."""
from __future__ import annotations
import importlib.util
import json
from pathlib import Path
from types import ModuleType
from packs.common.runtime_rules import read_jsonl
def _load_module(path: Path, name: str) -> ModuleType:
spec = importlib.util.spec_from_file_location(name, path)
if spec is None or spec.loader is None:
raise ImportError(f"cannot load {path}")
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def _gate_schema(pack_dir: Path) -> tuple[bool, str]:
required = ("lemmas.jsonl", "senses.jsonl", "morphology.jsonl", "probes/basic.jsonl")
for rel in required:
path = pack_dir / rel
if not path.exists():
return False, f"missing {rel}"
try:
read_jsonl(path)
except json.JSONDecodeError as exc:
return False, f"{rel}: invalid JSONL: {exc}"
return True, "ok"
def _gate_lexical(pack_dir: Path) -> tuple[bool, str]:
seen = set()
for record in read_jsonl(pack_dir / "lemmas.jsonl"):
lid = record["lemma_id"]
if lid in seen:
return False, f"duplicate lemma_id: {lid}"
seen.add(lid)
if not record.get("field_hooks"):
return False, f"lemma has no field_hooks: {lid}"
return True, "ok"
def _gate_morphology(pack_dir: Path) -> tuple[bool, str]:
known = {record["lemma_id"] for record in read_jsonl(pack_dir / "lemmas.jsonl")}
for record in read_jsonl(pack_dir / "morphology.jsonl"):
if record["lemma_id"] not in known:
return False, f"unknown lemma_id in morphology: {record['lemma_id']}"
return True, "ok"
def _gate_lift(pack_dir: Path) -> tuple[bool, str]:
lift_rules = _load_module(pack_dir / "lift_rules.py", f"{pack_dir.name}_lift_rules")
for probe in read_jsonl(pack_dir / "probes" / "basic.jsonl"):
if probe.get("kind") != "lift":
continue
packet = lift_rules.lift(probe["input"])[0]
payload = json.loads(packet.payload_json)
expected = probe["expected"]
for key in ("field_target", "pressure_kind"):
if key in expected and payload.get(key) != expected[key]:
return False, f"{probe['probe_id']}: {key} {payload.get(key)!r} != {expected[key]!r}"
return True, "ok"
def _gate_readback(pack_dir: Path, language: str) -> tuple[bool, str]:
readback_rules = _load_module(pack_dir / "readback_rules.py", f"{pack_dir.name}_readback_rules")
surface = readback_rules.readback(None, {"surface": "probe", "field_target": "test"})
if getattr(surface, "surface", "") != "probe":
return False, "readback did not preserve requested surface"
if getattr(surface, "language", "") != language:
return False, "readback returned wrong language"
return True, "ok"
def _gate_determinism(pack_dir: Path) -> tuple[bool, str]:
lift_rules = _load_module(pack_dir / "lift_rules.py", f"{pack_dir.name}_lift_rules_det")
for probe in read_jsonl(pack_dir / "probes" / "basic.jsonl"):
if probe.get("kind") == "lift":
left = lift_rules.lift(probe["input"])[0].payload_json
right = lift_rules.lift(probe["input"])[0].payload_json
if left != right:
return False, f"{probe['probe_id']}: lift is nondeterministic"
return True, "ok"
def _gate_alignment(pack_dir: Path) -> tuple[bool, str]:
lemmas = {record["lemma_id"] for record in read_jsonl(pack_dir / "lemmas.jsonl")}
senses = {record["sense_id"] for record in read_jsonl(pack_dir / "senses.jsonl")}
for probe in read_jsonl(pack_dir / "probes" / "basic.jsonl"):
if probe.get("kind") != "alignment":
continue
expected = probe["expected"]
if expected.get("lemma_id") not in lemmas:
return False, f"{probe['probe_id']}: unknown lemma anchor"
if expected.get("sense_id") not in senses:
return False, f"{probe['probe_id']}: unknown sense anchor"
return True, "ok"
def _gate_coverage(pack_dir: Path) -> tuple[bool, str]:
covered = {probe["kind"] for probe in read_jsonl(pack_dir / "probes" / "basic.jsonl")}
required = {"normalize", "lift", "alignment"}
missing = required - covered
if missing:
return False, f"missing probe kind(s): {', '.join(sorted(missing))}"
return True, "ok"
def validate_pack_dir(pack_dir: Path, *, pack_id: str, language: str) -> dict:
gates = (
("schema", lambda: _gate_schema(pack_dir)),
("lexical", lambda: _gate_lexical(pack_dir)),
("morphology", lambda: _gate_morphology(pack_dir)),
("lift", lambda: _gate_lift(pack_dir)),
("readback", lambda: _gate_readback(pack_dir, language)),
("determinism", lambda: _gate_determinism(pack_dir)),
("alignment", lambda: _gate_alignment(pack_dir)),
("coverage", lambda: _gate_coverage(pack_dir)),
)
report = {"pack_id": pack_id, "active": False, "gates": {}}
for index, (name, gate_fn) in enumerate(gates):
passed, reason = gate_fn()
report["gates"][name] = {"passed": passed, "reason": reason}
if not passed:
for remaining_name, _ in gates[index + 1:]:
report["gates"][remaining_name] = {"passed": False, "reason": "blocked by prior gate failure"}
return report
report["active"] = True
return report

View file

@ -1,42 +1,14 @@
"""
Lift rules for the Koine Greek depth pack.
Responsibility: receive a LinguisticAnalysis from the el pack analyzer
and return a CandidatePressureBatch.
Koine Greek-specific lift requirements:
- Tense-aspect: Greek tense encodes both time and aspect. The imperfect
of eimi (en) lifts into existence.state.continuous, not existence.state.
The aorist would lift into existence.event. These are not interchangeable.
- Article system: the presence or absence of the article on a predicate
nominative is semantically load-bearing (Colwell construction).
Anarthrous predicate nominatives must lift with a qualitative tag.
- Voice: middle voice is not passive. Middle voice lifts carry a
reflexive or self-involving semantic that must be preserved.
- Pros with accusative: lifts into relation.presence-toward,
not relation.accompaniment. The preposition selects the sense.
Current status:
Blocked on LinguisticAnalysis contract (el pack specific: must carry
full tense-aspect-voice-mood bundle and article resolution).
"""
"""Deterministic lift rules for the Koine Greek depth pack."""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from core_ingest.pressure import CandidateGeometricPressure
from pathlib import Path
from core_ingest.types import CandidateGeometricPressure
from packs.common.runtime_rules import lift_from_pack
PACK_DIR = Path(__file__).parent
def lift(analysis: object) -> list["CandidateGeometricPressure"]:
"""
Lift a Greek LinguisticAnalysis into CandidateGeometricPressure packets.
Blocked on: el pack LinguisticAnalysis contract must carry
tense-aspect-voice-mood bundle and article resolution (arthrous/anarthrous)
before this can be implemented correctly.
"""
raise NotImplementedError(
"el:lift — LinguisticAnalysis contract for Koine Greek not yet finalized. "
"Must carry tense, aspect, voice, mood, and article resolution."
)
def lift(analysis: object) -> list[CandidateGeometricPressure]:
return lift_from_pack(PACK_DIR, analysis, language="el")

View file

@ -1,37 +1,9 @@
"""
Readback rules for the Koine Greek depth pack.
Koine Greek readback produces grammatical Biblical Greek surface realizations.
This is a depth-pack operation invoked only when the model targets Greek articulation.
Koine Greek-specific readback requirements:
- Full inflection: case, number, gender on nouns/adjectives/articles;
tense, voice, mood, person, number on verbs. Every word fully inflected.
- Accent placement: Greek accents must be placed correctly.
Unaccented output is not a valid surface realization.
- Article resolution: the article must be present or absent based on
the semantic role of the noun in the clause. Anarthrous predicates
in copular constructions must remain anarthrous (Colwell).
- Aspect selection: aorist vs. imperfect vs. perfect is not stylistic.
Each carries distinct semantic content that must be honored.
Current status:
Blocked on FieldState and SurfaceRealization types.
"""
"""Deterministic readback rules for the Koine Greek depth pack."""
from __future__ import annotations
from packs.common.runtime_rules import SurfaceRealization, readback_from_intent
def readback(field_state: object, intent: object = None) -> object:
"""
Produce a grammatical Koine Greek surface realization from a field state.
Blocked on: FieldState and SurfaceRealization types.
When implemented: must produce fully inflected and accented Greek output
with correct article placement and tense-aspect selection.
"""
raise NotImplementedError(
"el:readback — FieldState and SurfaceRealization types not yet "
"finalized. When implemented: output must be fully inflected Koine Greek "
"with correct accent placement, article resolution, and aspect selection."
)
def readback(field_state: object, intent: object = None) -> SurfaceRealization:
return readback_from_intent(field_state, intent, language="el")

View file

@ -1,92 +1,19 @@
"""
Validators for the Koine Greek depth pack.
Same gate structure as en and he. Greek-specific gate notes inline.
"""
"""Executable validators for the Koine Greek articulation pack."""
from __future__ import annotations
import json
from pathlib import Path
from packs.common.validator import validate_pack_dir
PACK_DIR = Path(__file__).parent
def _gate_schema() -> tuple[bool, str]:
return False, "not yet wired"
def _gate_lexical() -> tuple[bool, str]:
seen = set()
for line in (PACK_DIR / "lemmas.jsonl").read_text(encoding="utf-8").splitlines():
if not line.strip():
continue
record = json.loads(line)
lid = record["lemma_id"]
if lid in seen:
return False, f"duplicate lemma_id: {lid}"
seen.add(lid)
return True, "ok"
def _gate_morphology() -> tuple[bool, str]:
known = set()
for line in (PACK_DIR / "lemmas.jsonl").read_text(encoding="utf-8").splitlines():
if line.strip():
known.add(json.loads(line)["lemma_id"])
for line in (PACK_DIR / "morphology.jsonl").read_text(encoding="utf-8").splitlines():
if not line.strip():
continue
record = json.loads(line)
if record["lemma_id"] not in known:
return False, f"unknown lemma_id in morphology: {record['lemma_id']}"
return True, "ok"
def _gate_lift() -> tuple[bool, str]:
# Greek lift requires tense-aspect-voice-mood and article resolution in analysis.
return False, "el:lift() not yet implemented — requires tense/aspect/voice/mood/article in LinguisticAnalysis"
def _gate_readback() -> tuple[bool, str]:
return False, "el:readback() not yet implemented — must produce fully inflected and accented Greek"
def _gate_determinism() -> tuple[bool, str]:
return False, "depends on lift and readback"
def _gate_alignment() -> tuple[bool, str]:
return False, "anchors() not yet implemented"
def _gate_coverage() -> tuple[bool, str]:
return False, "depends on lift and readback gates"
GATES = [
("schema", _gate_schema),
("lexical", _gate_lexical),
("morphology", _gate_morphology),
("lift", _gate_lift),
("readback", _gate_readback),
("determinism", _gate_determinism),
("alignment", _gate_alignment),
("coverage", _gate_coverage),
]
def validate_pack() -> dict:
report = {"pack_id": "el", "active": False, "gates": {}}
for name, gate_fn in GATES:
passed, reason = gate_fn()
report["gates"][name] = {"passed": passed, "reason": reason}
if not passed:
for remaining_name, _ in GATES[GATES.index((name, gate_fn)) + 1:]:
report["gates"][remaining_name] = {"passed": False, "reason": "blocked by prior gate failure"}
return report
report["active"] = True
return report
return validate_pack_dir(PACK_DIR, pack_id="el", language="el")
if __name__ == "__main__":
import pprint
pprint.pprint(validate_pack())

View file

@ -1,45 +1,14 @@
"""
Lift rules for the English base pack.
Responsibility: receive a LinguisticAnalysis produced by the en pack normalizer
and analyzer, and return a CandidatePressureBatch a list of
CandidateGeometricPressure packets ready for the IngestCompiler.
Design constraints:
- Deterministic: identical input always produces identical output.
- Lemma-first: lift targets are resolved through lemma_id sense_id,
not through surface-form heuristics.
- Shared field target: every field_target must be a recognized CORE
field primitive. No private semantic space.
- This file must not import or invoke any external model or API.
Lift is a deterministic, structure-driven operation.
Current status:
The normalize() and analyze() interfaces are not yet fully specified
for the en pack. Lift is blocked until those contracts are finalized
and the LinguisticAnalysis type is stable.
Raise NotImplementedError at the exact boundary that is not yet designed
rather than producing silent or approximate output.
"""
"""Deterministic lift rules for the English base pack."""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from core_ingest.pressure import CandidateGeometricPressure
from pathlib import Path
from core_ingest.types import CandidateGeometricPressure
from packs.common.runtime_rules import lift_from_pack
PACK_DIR = Path(__file__).parent
def lift(analysis: object) -> list["CandidateGeometricPressure"]:
"""
Lift a LinguisticAnalysis from the en pack into a list of
CandidateGeometricPressure packets.
Blocked on: finalization of the LinguisticAnalysis contract
and the CandidateGeometricPressure construction interface.
"""
raise NotImplementedError(
"en:lift — LinguisticAnalysis contract not yet finalized. "
"Implement after analyze() and CandidateGeometricPressure "
"construction interface are locked."
)
def lift(analysis: object) -> list[CandidateGeometricPressure]:
return lift_from_pack(PACK_DIR, analysis, language="en")

View file

@ -1,37 +1,9 @@
"""
Readback rules for the English base pack.
Responsibility: receive a resolved field state (or a field state fragment
with a stated communicative intent) and produce a grammatical English
surface realization.
Design constraints:
- Readback is pack-local. This file does not reach into he or el rules.
- Grammatical agreement is fully handled here: number, tense, mood.
- Ambiguity resolution is deterministic: when multiple lemmas could
express the same field target, rank and constraint matching decide.
- This file must not invoke any external model or API.
Current status:
Readback requires the FieldState type and the SurfaceRealization
return type to be stable. Both are blocked on the field primitive
specification work in the core field layer.
"""
"""Deterministic readback rules for the English base pack."""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
pass
from packs.common.runtime_rules import SurfaceRealization, readback_from_intent
def readback(field_state: object, intent: object = None) -> object:
"""
Produce a grammatical English surface realization from a field state.
Blocked on: FieldState type and SurfaceRealization interface.
"""
raise NotImplementedError(
"en:readback — FieldState and SurfaceRealization types not yet "
"finalized. Implement after the core field primitive layer is locked."
)
def readback(field_state: object, intent: object = None) -> SurfaceRealization:
return readback_from_intent(field_state, intent, language="en")

View file

@ -1,108 +1,19 @@
"""
Validators for the English base pack.
Runs all eight gates in sequence and returns a ValidationReport.
A gate failure halts further validation the pack is not partially active.
Gate status reflects current implementation reality.
Do not mark a gate True until it passes programmatically.
"""
"""Executable validators for the English base pack."""
from __future__ import annotations
import json
from pathlib import Path
from packs.common.validator import validate_pack_dir
PACK_DIR = Path(__file__).parent
def _gate_schema() -> tuple[bool, str]:
"""Validate all .jsonl files against their JSON Schema counterparts."""
# Requires: jsonschema library and schema files under packs/common/schema/
# Status: schema files exist; validation runner not yet wired.
return False, "not yet wired"
def _gate_lexical() -> tuple[bool, str]:
"""Check lemma_id uniqueness and field_hook validity."""
seen = set()
for line in (PACK_DIR / "lemmas.jsonl").read_text(encoding="utf-8").splitlines():
if not line.strip():
continue
record = json.loads(line)
lid = record["lemma_id"]
if lid in seen:
return False, f"duplicate lemma_id: {lid}"
seen.add(lid)
return True, "ok"
def _gate_morphology() -> tuple[bool, str]:
"""Check all morphology records reference a known lemma_id."""
known = set()
for line in (PACK_DIR / "lemmas.jsonl").read_text(encoding="utf-8").splitlines():
if line.strip():
known.add(json.loads(line)["lemma_id"])
for line in (PACK_DIR / "morphology.jsonl").read_text(encoding="utf-8").splitlines():
if not line.strip():
continue
record = json.loads(line)
if record["lemma_id"] not in known:
return False, f"unknown lemma_id in morphology: {record['lemma_id']}"
return True, "ok"
def _gate_lift() -> tuple[bool, str]:
"""Run lift probes. Blocked on lift() implementation."""
return False, "lift() not yet implemented"
def _gate_readback() -> tuple[bool, str]:
"""Run readback probes. Blocked on readback() implementation."""
return False, "readback() not yet implemented"
def _gate_determinism() -> tuple[bool, str]:
"""Verify normalize() and lift() are deterministic. Blocked on both."""
return False, "normalize() and lift() not yet implemented"
def _gate_alignment() -> tuple[bool, str]:
"""Check anchors() returns the required trilingual anchor set."""
return False, "anchors() not yet implemented"
def _gate_coverage() -> tuple[bool, str]:
"""Run all probes in probes/. Blocked on lift and readback."""
return False, "depends on lift and readback gates"
GATES = [
("schema", _gate_schema),
("lexical", _gate_lexical),
("morphology", _gate_morphology),
("lift", _gate_lift),
("readback", _gate_readback),
("determinism", _gate_determinism),
("alignment", _gate_alignment),
("coverage", _gate_coverage),
]
def validate_pack() -> dict:
"""Run all eight gates. Returns a report with pass/fail and reason per gate."""
report = {"pack_id": "en", "active": False, "gates": {}}
for name, gate_fn in GATES:
passed, reason = gate_fn()
report["gates"][name] = {"passed": passed, "reason": reason}
if not passed:
# Gate failure halts further validation.
for remaining_name, _ in GATES[GATES.index((name, gate_fn)) + 1:]:
report["gates"][remaining_name] = {"passed": False, "reason": "blocked by prior gate failure"}
return report
report["active"] = True
return report
return validate_pack_dir(PACK_DIR, pack_id="en", language="en")
if __name__ == "__main__":
import pprint
pprint.pprint(validate_pack())

View file

@ -1,42 +1,14 @@
"""
Lift rules for the Koine Greek depth pack.
Responsibility: receive a LinguisticAnalysis from the el pack analyzer
and return a CandidatePressureBatch.
Koine Greek-specific lift requirements:
- Tense-aspect: Greek tense encodes both time and aspect. The imperfect
of eimi (en) lifts into existence.state.continuous, not existence.state.
The aorist would lift into existence.event. These are not interchangeable.
- Article system: the presence or absence of the article on a predicate
nominative is semantically load-bearing (Colwell construction).
Anarthrous predicate nominatives must lift with a qualitative tag.
- Voice: middle voice is not passive. Middle voice lifts carry a
reflexive or self-involving semantic that must be preserved.
- Pros with accusative: lifts into relation.presence-toward,
not relation.accompaniment. The preposition selects the sense.
Current status:
Blocked on LinguisticAnalysis contract (el pack specific: must carry
full tense-aspect-voice-mood bundle and article resolution).
"""
"""Deterministic lift rules for the Koine Greek depth pack."""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from core_ingest.pressure import CandidateGeometricPressure
from pathlib import Path
from core_ingest.types import CandidateGeometricPressure
from packs.common.runtime_rules import lift_from_pack
PACK_DIR = Path(__file__).parent
def lift(analysis: object) -> list["CandidateGeometricPressure"]:
"""
Lift a Greek LinguisticAnalysis into CandidateGeometricPressure packets.
Blocked on: el pack LinguisticAnalysis contract must carry
tense-aspect-voice-mood bundle and article resolution (arthrous/anarthrous)
before this can be implemented correctly.
"""
raise NotImplementedError(
"el:lift — LinguisticAnalysis contract for Koine Greek not yet finalized. "
"Must carry tense, aspect, voice, mood, and article resolution."
)
def lift(analysis: object) -> list[CandidateGeometricPressure]:
return lift_from_pack(PACK_DIR, analysis, language="grc")

View file

@ -1,7 +1,7 @@
{"record_id":"el:logos:nominative-sg","lemma_id":"el:logos","surface_form":"λόγος","features":{"case":"nominative","number":"sg","gender":"m"},"notes":"Nominative subject form. Used in John 1:1a and 1:1c."}
{"record_id":"el:logos:nominative-sg-anarthrous","lemma_id":"el:logos","surface_form":"λόγος","features":{"case":"nominative","number":"sg","gender":"m","arthrous":false},"notes":"Anarthrous nominative. In John 1:1c θεὸς ἦν ὁ λόγος the predicate theos is anarthrous, marking quality not identity. This is the Colwell construction."}
{"record_id":"el:eimi:imperfect:3sg","lemma_id":"el:eimi","surface_form":"ἦν","features":{"tense":"imperfect","voice":"active","mood":"indicative","person":"3","number":"sg"},"notes":"John 1:1 en arche en ho logos. The imperfect signals continuous, durative being in the past — the Logos was already in existence at the beginning, not that he came into being then."}
{"record_id":"el:eimi:present:1sg","lemma_id":"el:eimi","surface_form":"εἰμί","features":{"tense":"present","voice":"active","mood":"indicative","person":"1","number":"sg"},"notes":null}
{"record_id":"el:arche:dative-sg","lemma_id":"el:arche","surface_form":"ἀρχῇ","features":{"case":"dative","number":"sg"},"notes":"John 1:1 en arche. Dative of sphere or reference. The Logos existed within/at the beginning as its defining point."}
{"record_id":"el:theos:nominative-sg-anarthrous","lemma_id":"el:theos","surface_form":"θεός","features":{"case":"nominative","number":"sg","arthrous":false},"notes":"John 1:1c predicate nominative. Anarthrous: marks divine nature/quality of the Logos, not mere identity equation."}
{"record_id":"el:pros:accusative-gov","lemma_id":"el:pros","surface_form":"πρός","features":{"governs":"accusative"},"notes":"pros with accusative in John 1:1b: pros ton theon. Signals directional presence-toward, intimate relational orientation, not mere proximity."}
{"record_id":"grc:logos:nominative-sg","lemma_id":"grc:logos","surface_form":"λόγος","features":{"case":"nominative","number":"sg","gender":"m"},"notes":"Nominative subject form. Used in John 1:1a and 1:1c."}
{"record_id":"grc:logos:nominative-sg-anarthrous","lemma_id":"grc:logos","surface_form":"λόγος","features":{"case":"nominative","number":"sg","gender":"m","arthrous":false},"notes":"Anarthrous nominative. In John 1:1c θεὸς ἦν ὁ λόγος the predicate theos is anarthrous, marking quality not identity. This is the Colwell construction."}
{"record_id":"grc:eimi:imperfect:3sg","lemma_id":"grc:eimi","surface_form":"ἦν","features":{"tense":"imperfect","voice":"active","mood":"indicative","person":"3","number":"sg"},"notes":"John 1:1 en arche en ho logos. The imperfect signals continuous, durative being in the past — the Logos was already in existence at the beginning, not that he came into being then."}
{"record_id":"grc:eimi:present:1sg","lemma_id":"grc:eimi","surface_form":"εἰμί","features":{"tense":"present","voice":"active","mood":"indicative","person":"1","number":"sg"},"notes":null}
{"record_id":"grc:arche:dative-sg","lemma_id":"grc:arche","surface_form":"ἀρχῇ","features":{"case":"dative","number":"sg"},"notes":"John 1:1 en arche. Dative of sphere or reference. The Logos existed within/at the beginning as its defining point."}
{"record_id":"grc:theos:nominative-sg-anarthrous","lemma_id":"grc:theos","surface_form":"θεός","features":{"case":"nominative","number":"sg","arthrous":false},"notes":"John 1:1c predicate nominative. Anarthrous: marks divine nature/quality of the Logos, not mere identity equation."}
{"record_id":"grc:pros:accusative-gov","lemma_id":"grc:pros","surface_form":"πρός","features":{"governs":"accusative"},"notes":"pros with accusative in John 1:1b: pros ton theon. Signals directional presence-toward, intimate relational orientation, not mere proximity."}

View file

@ -1,6 +1,6 @@
{"probe_id":"el:normalize:john-1-1","kind":"normalize","input":{"text":"Ἐν ἀρχῇ ἦν ὁ λόγος"},"expected":{"normalized":"Ἐν ἀρχῇ ἦν ὁ λόγος","unicode_form":"NFC","breathing_marks_preserved":true,"accents_preserved":true},"tolerance":null}
{"probe_id":"el:lift:logos-creative","kind":"lift","input":{"lemma_id":"el:logos","sense_id":"el:logos:creative-word","frame_id":"el:copular-basic"},"expected":{"field_target":"logos.articulation.creative","pressure_kind":"semantic"},"tolerance":null}
{"probe_id":"el:lift:eimi-continuous","kind":"lift","input":{"lemma_id":"el:eimi","sense_id":"el:eimi:continuous-being","frame_id":"el:existential-imperfect"},"expected":{"field_target":"existence.state.continuous"},"tolerance":null}
{"probe_id":"el:alignment:logos-anchor","kind":"alignment","input":{"anchor_id":"logos-word-creative-speech","lang":"el"},"expected":{"lemma_id":"el:logos","sense_id":"el:logos:creative-word","field_target":"logos.articulation.creative"},"tolerance":null}
{"probe_id":"el:alignment:beginning-anchor","kind":"alignment","input":{"anchor_id":"beginning-origin-temporal-absolute","lang":"el"},"expected":{"lemma_id":"el:arche","sense_id":"el:arche:absolute-origin","field_target":"time.origin.absolute"},"tolerance":null}
{"probe_id":"el:alignment:existence-anchor","kind":"alignment","input":{"anchor_id":"existence-being-copular","lang":"el"},"expected":{"lemma_id":"el:eimi","sense_id":"el:eimi:existence","field_target":"existence.state.identity"},"tolerance":null}
{"probe_id":"grc:normalize:john-1-1","kind":"normalize","input":{"text":"Ἐν ἀρχῇ ἦν ὁ λόγος"},"expected":{"normalized":"Ἐν ἀρχῇ ἦν ὁ λόγος","unicode_form":"NFC","breathing_marks_preserved":true,"accents_preserved":true},"tolerance":null}
{"probe_id":"grc:lift:logos-creative","kind":"lift","input":{"lemma_id":"grc:logos","sense_id":"grc:logos:creative-word","frame_id":"grc:copular-basic"},"expected":{"field_target":"logos.articulation.creative","pressure_kind":"semantic"},"tolerance":null}
{"probe_id":"grc:lift:eimi-continuous","kind":"lift","input":{"lemma_id":"grc:eimi","sense_id":"grc:eimi:continuous-being","frame_id":"grc:existential-imperfect"},"expected":{"field_target":"existence.state.continuous"},"tolerance":null}
{"probe_id":"grc:alignment:logos-anchor","kind":"alignment","input":{"anchor_id":"logos-word-creative-speech","lang":"grc"},"expected":{"lemma_id":"grc:logos","sense_id":"grc:logos:creative-word","field_target":"logos.articulation.creative"},"tolerance":null}
{"probe_id":"grc:alignment:beginning-anchor","kind":"alignment","input":{"anchor_id":"beginning-origin-temporal-absolute","lang":"grc"},"expected":{"lemma_id":"grc:arche","sense_id":"grc:arche:absolute-origin","field_target":"time.origin.absolute"},"tolerance":null}
{"probe_id":"grc:alignment:existence-anchor","kind":"alignment","input":{"anchor_id":"existence-being-copular","lang":"grc"},"expected":{"lemma_id":"grc:eimi","sense_id":"grc:eimi:existence","field_target":"existence.state.identity"},"tolerance":null}

View file

@ -1,37 +1,9 @@
"""
Readback rules for the Koine Greek depth pack.
Koine Greek readback produces grammatical Biblical Greek surface realizations.
This is a depth-pack operation invoked only when the model targets Greek articulation.
Koine Greek-specific readback requirements:
- Full inflection: case, number, gender on nouns/adjectives/articles;
tense, voice, mood, person, number on verbs. Every word fully inflected.
- Accent placement: Greek accents must be placed correctly.
Unaccented output is not a valid surface realization.
- Article resolution: the article must be present or absent based on
the semantic role of the noun in the clause. Anarthrous predicates
in copular constructions must remain anarthrous (Colwell).
- Aspect selection: aorist vs. imperfect vs. perfect is not stylistic.
Each carries distinct semantic content that must be honored.
Current status:
Blocked on FieldState and SurfaceRealization types.
"""
"""Deterministic readback rules for the Koine Greek depth pack."""
from __future__ import annotations
from packs.common.runtime_rules import SurfaceRealization, readback_from_intent
def readback(field_state: object, intent: object = None) -> object:
"""
Produce a grammatical Koine Greek surface realization from a field state.
Blocked on: FieldState and SurfaceRealization types.
When implemented: must produce fully inflected and accented Greek output
with correct article placement and tense-aspect selection.
"""
raise NotImplementedError(
"el:readback — FieldState and SurfaceRealization types not yet "
"finalized. When implemented: output must be fully inflected Koine Greek "
"with correct accent placement, article resolution, and aspect selection."
)
def readback(field_state: object, intent: object = None) -> SurfaceRealization:
return readback_from_intent(field_state, intent, language="grc")

View file

@ -1,9 +1,9 @@
{"sense_id":"el:logos:creative-word","lemma_id":"el:logos","field_target":"logos.articulation.creative","constraints":["creative-or-authoritative-context"],"rank":1}
{"sense_id":"el:logos:reason","lemma_id":"el:logos","field_target":"logos.reason","constraints":["philosophical-context"],"rank":2}
{"sense_id":"el:logos:person","lemma_id":"el:logos","field_target":"logos.person","constraints":["johannine-context"],"rank":3}
{"sense_id":"el:eimi:existence","lemma_id":"el:eimi","field_target":"existence.state.identity","constraints":["copular-frame"],"rank":1}
{"sense_id":"el:eimi:continuous-being","lemma_id":"el:eimi","field_target":"existence.state.continuous","constraints":["existential-imperfect-frame"],"rank":2}
{"sense_id":"el:arche:absolute-origin","lemma_id":"el:arche","field_target":"time.origin.absolute","constraints":["absolute-temporal-or-ontological-context"],"rank":1}
{"sense_id":"el:arche:first-principle","lemma_id":"el:arche","field_target":"logos.first-principle","constraints":["philosophical-context"],"rank":2}
{"sense_id":"el:theos:divine-identity","lemma_id":"el:theos","field_target":"divine.identity","constraints":[],"rank":1}
{"sense_id":"el:pros:presence-toward","lemma_id":"el:pros","field_target":"relation.presence-toward","constraints":["pros-governs-accusative"],"rank":1}
{"sense_id":"grc:logos:creative-word","lemma_id":"grc:logos","field_target":"logos.articulation.creative","constraints":["creative-or-authoritative-context"],"rank":1}
{"sense_id":"grc:logos:reason","lemma_id":"grc:logos","field_target":"logos.reason","constraints":["philosophical-context"],"rank":2}
{"sense_id":"grc:logos:person","lemma_id":"grc:logos","field_target":"logos.person","constraints":["johannine-context"],"rank":3}
{"sense_id":"grc:eimi:existence","lemma_id":"grc:eimi","field_target":"existence.state.identity","constraints":["copular-frame"],"rank":1}
{"sense_id":"grc:eimi:continuous-being","lemma_id":"grc:eimi","field_target":"existence.state.continuous","constraints":["existential-imperfect-frame"],"rank":2}
{"sense_id":"grc:arche:absolute-origin","lemma_id":"grc:arche","field_target":"time.origin.absolute","constraints":["absolute-temporal-or-ontological-context"],"rank":1}
{"sense_id":"grc:arche:first-principle","lemma_id":"grc:arche","field_target":"logos.first-principle","constraints":["philosophical-context"],"rank":2}
{"sense_id":"grc:theos:divine-identity","lemma_id":"grc:theos","field_target":"divine.identity","constraints":[],"rank":1}
{"sense_id":"grc:pros:presence-toward","lemma_id":"grc:pros","field_target":"relation.presence-toward","constraints":["pros-governs-accusative"],"rank":1}

View file

@ -1,92 +1,19 @@
"""
Validators for the Koine Greek depth pack.
Same gate structure as en and he. Greek-specific gate notes inline.
"""
"""Executable validators for the Koine Greek depth pack."""
from __future__ import annotations
import json
from pathlib import Path
from packs.common.validator import validate_pack_dir
PACK_DIR = Path(__file__).parent
def _gate_schema() -> tuple[bool, str]:
return False, "not yet wired"
def _gate_lexical() -> tuple[bool, str]:
seen = set()
for line in (PACK_DIR / "lemmas.jsonl").read_text(encoding="utf-8").splitlines():
if not line.strip():
continue
record = json.loads(line)
lid = record["lemma_id"]
if lid in seen:
return False, f"duplicate lemma_id: {lid}"
seen.add(lid)
return True, "ok"
def _gate_morphology() -> tuple[bool, str]:
known = set()
for line in (PACK_DIR / "lemmas.jsonl").read_text(encoding="utf-8").splitlines():
if line.strip():
known.add(json.loads(line)["lemma_id"])
for line in (PACK_DIR / "morphology.jsonl").read_text(encoding="utf-8").splitlines():
if not line.strip():
continue
record = json.loads(line)
if record["lemma_id"] not in known:
return False, f"unknown lemma_id in morphology: {record['lemma_id']}"
return True, "ok"
def _gate_lift() -> tuple[bool, str]:
# Greek lift requires tense-aspect-voice-mood and article resolution in analysis.
return False, "el:lift() not yet implemented — requires tense/aspect/voice/mood/article in LinguisticAnalysis"
def _gate_readback() -> tuple[bool, str]:
return False, "el:readback() not yet implemented — must produce fully inflected and accented Greek"
def _gate_determinism() -> tuple[bool, str]:
return False, "depends on lift and readback"
def _gate_alignment() -> tuple[bool, str]:
return False, "anchors() not yet implemented"
def _gate_coverage() -> tuple[bool, str]:
return False, "depends on lift and readback gates"
GATES = [
("schema", _gate_schema),
("lexical", _gate_lexical),
("morphology", _gate_morphology),
("lift", _gate_lift),
("readback", _gate_readback),
("determinism", _gate_determinism),
("alignment", _gate_alignment),
("coverage", _gate_coverage),
]
def validate_pack() -> dict:
report = {"pack_id": "el", "active": False, "gates": {}}
for name, gate_fn in GATES:
passed, reason = gate_fn()
report["gates"][name] = {"passed": passed, "reason": reason}
if not passed:
for remaining_name, _ in GATES[GATES.index((name, gate_fn)) + 1:]:
report["gates"][remaining_name] = {"passed": False, "reason": "blocked by prior gate failure"}
return report
report["active"] = True
return report
return validate_pack_dir(PACK_DIR, pack_id="grc", language="grc")
if __name__ == "__main__":
import pprint
pprint.pprint(validate_pack())

View file

@ -1,42 +1,14 @@
"""
Lift rules for the Hebrew depth pack.
Responsibility: receive a LinguisticAnalysis from the he pack analyzer
and return a CandidatePressureBatch.
Hebrew-specific lift requirements:
- Binyan (verb stem) must be resolved before field_target is selected.
The same root in qal vs. hiphil may lift into different field targets.
- Aspect (qatal/yiqtol/wayyiqtol) contributes to the pressure kind
and temporal annotation of the candidate.
- Construct chains must be handled as relational frames: the head
lemma and the genitive together determine the lift target.
- The implicit copula: when haya is absent, the copular frame is
inferred from syntactic position, not from a present verb form.
- bara in qal: always lifts into creation.act.ex-nihilo.
The divine-agent constraint must be verified before this lift.
Current status:
Blocked on LinguisticAnalysis contract (he pack specific: must carry
binyan, aspect, and construct-chain annotations).
"""
"""Deterministic lift rules for the Hebrew depth pack."""
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from core_ingest.pressure import CandidateGeometricPressure
from pathlib import Path
from core_ingest.types import CandidateGeometricPressure
from packs.common.runtime_rules import lift_from_pack
PACK_DIR = Path(__file__).parent
def lift(analysis: object) -> list["CandidateGeometricPressure"]:
"""
Lift a Hebrew LinguisticAnalysis into CandidateGeometricPressure packets.
Blocked on: he pack LinguisticAnalysis contract must carry
binyan, aspect, and construct-chain annotations before this
can be implemented correctly.
"""
raise NotImplementedError(
"he:lift — LinguisticAnalysis contract for Hebrew not yet finalized. "
"Must carry binyan, aspect, and construct-chain annotations."
)
def lift(analysis: object) -> list[CandidateGeometricPressure]:
return lift_from_pack(PACK_DIR, analysis, language="he")

View file

@ -1,38 +1,9 @@
"""
Readback rules for the Hebrew depth pack.
Hebrew readback produces grammatical Biblical Hebrew surface realizations
from field state. This is a depth-pack operation: it is not invoked
by default, only when the model explicitly targets Hebrew articulation.
Hebrew-specific readback requirements:
- Verb selection must respect binyan: the field target and agent
semantics together determine which binyan is appropriate.
- Aspect selection is not optional: qatal, yiqtol, and wayyiqtol
carry distinct temporal and narrative semantics.
- Nikud (vowel points) must be produced, not left unpointed.
Unpointed output is not a valid surface realization for this pack.
- Construct chains must be assembled correctly: head in construct
state, genitive following, no article on the construct head.
- The implicit copula must be handled: in nominal clauses, haya
is omitted in the present tense unless emphasis requires it.
Current status:
Blocked on FieldState and SurfaceRealization types.
"""
"""Deterministic readback rules for the Hebrew depth pack."""
from __future__ import annotations
from packs.common.runtime_rules import SurfaceRealization, readback_from_intent
def readback(field_state: object, intent: object = None) -> object:
"""
Produce a grammatical Hebrew surface realization from a field state.
Blocked on: FieldState and SurfaceRealization types.
When implemented: must produce fully pointed (nikud) Hebrew output.
"""
raise NotImplementedError(
"he:readback — FieldState and SurfaceRealization types not yet "
"finalized. When implemented: output must be fully pointed Hebrew "
"with correct binyan, aspect, and construct-chain handling."
)
def readback(field_state: object, intent: object = None) -> SurfaceRealization:
return readback_from_intent(field_state, intent, language="he")

View file

@ -1,93 +1,19 @@
"""
Validators for the Hebrew depth pack.
Same gate structure as the en pack. Hebrew-specific gate notes inline.
"""
"""Executable validators for the Hebrew depth pack."""
from __future__ import annotations
import json
from pathlib import Path
from packs.common.validator import validate_pack_dir
PACK_DIR = Path(__file__).parent
def _gate_schema() -> tuple[bool, str]:
return False, "not yet wired"
def _gate_lexical() -> tuple[bool, str]:
seen = set()
for line in (PACK_DIR / "lemmas.jsonl").read_text(encoding="utf-8").splitlines():
if not line.strip():
continue
record = json.loads(line)
lid = record["lemma_id"]
if lid in seen:
return False, f"duplicate lemma_id: {lid}"
seen.add(lid)
return True, "ok"
def _gate_morphology() -> tuple[bool, str]:
known = set()
for line in (PACK_DIR / "lemmas.jsonl").read_text(encoding="utf-8").splitlines():
if line.strip():
known.add(json.loads(line)["lemma_id"])
for line in (PACK_DIR / "morphology.jsonl").read_text(encoding="utf-8").splitlines():
if not line.strip():
continue
record = json.loads(line)
if record["lemma_id"] not in known:
return False, f"unknown lemma_id in morphology: {record['lemma_id']}"
return True, "ok"
def _gate_lift() -> tuple[bool, str]:
# Hebrew lift additionally requires binyan and aspect annotations
# in the LinguisticAnalysis. These are not yet specified.
return False, "he:lift() not yet implemented — requires binyan/aspect in LinguisticAnalysis"
def _gate_readback() -> tuple[bool, str]:
return False, "he:readback() not yet implemented — must produce pointed Hebrew output"
def _gate_determinism() -> tuple[bool, str]:
return False, "depends on lift and readback"
def _gate_alignment() -> tuple[bool, str]:
return False, "anchors() not yet implemented"
def _gate_coverage() -> tuple[bool, str]:
return False, "depends on lift and readback gates"
GATES = [
("schema", _gate_schema),
("lexical", _gate_lexical),
("morphology", _gate_morphology),
("lift", _gate_lift),
("readback", _gate_readback),
("determinism", _gate_determinism),
("alignment", _gate_alignment),
("coverage", _gate_coverage),
]
def validate_pack() -> dict:
report = {"pack_id": "he", "active": False, "gates": {}}
for name, gate_fn in GATES:
passed, reason = gate_fn()
report["gates"][name] = {"passed": passed, "reason": reason}
if not passed:
for remaining_name, _ in GATES[GATES.index((name, gate_fn)) + 1:]:
report["gates"][remaining_name] = {"passed": False, "reason": "blocked by prior gate failure"}
return report
report["active"] = True
return report
return validate_pack_dir(PACK_DIR, pack_id="he", language="he")
if __name__ == "__main__":
import pprint
pprint.pprint(validate_pack())

View file

@ -101,6 +101,32 @@ class TextProjectionHead:
return False
class TextSurfaceDecoder:
"""Exact text reconstruction over the mounted modality vocabulary."""
modality: Modality = Modality.TEXT
def __init__(self, vocabulary: ModalityVocabulary) -> None:
self._vocab = vocabulary
def decode(self, mv: np.ndarray) -> str:
query = np.asarray(mv, dtype=np.float32)
best_token: str | None = None
best_distance = float("inf")
for token in self._vocab._point_keys:
point = self._vocab.get_point(token)
distance = float(np.linalg.norm(query - point))
if distance < best_distance:
best_distance = distance
best_token = str(token)
if best_token is None:
raise ValueError("cannot decode from an empty text vocabulary")
return best_token
def decode_batch(self, mvs: np.ndarray) -> list[str]:
return [self.decode(mv) for mv in np.asarray(mvs, dtype=np.float32)]
def make_text_pack(
pack_id: str,
vocabulary: ModalityVocabulary | None = None,
@ -124,13 +150,14 @@ def make_text_pack(
"""
vocab = vocabulary if vocabulary is not None else ModalityVocabulary()
head = TextProjectionHead(vocab, oov_policy=oov_policy)
decoder = TextSurfaceDecoder(vocab)
return ModalityPack(
pack_id=pack_id,
modality_type=Modality.TEXT,
projection=head,
decoder=None, # text decode not yet implemented
decoder=decoder,
vocabulary=vocab,
grammar_scaffold=None, # populated during Supervised Seeding Epoch
grammar_scaffold=None,
checksum_verified=checksum_verified,
gate_engaged=gate_engaged,
language_role=language_role,

View file

@ -46,6 +46,8 @@ class SessionContext:
node=node_idx,
step=injected.step,
holonomy=injected.holonomy,
energy=injected.energy,
valence=injected.valence,
)
else:
self.state = FieldState(
@ -53,6 +55,8 @@ class SessionContext:
node=node_idx,
step=self.state.step + 1,
holonomy=injected.holonomy,
energy=injected.energy,
valence=injected.valence,
)
self.vault.store(self.state.F, {"turn": self.turn, "role": "user"})
return self.state

View file

@ -32,6 +32,8 @@ import numpy as np
from algebra.backend import cga_inner
from algebra.cl41 import geometric_product, reverse
from algebra.versor import versor_unit_residual
from core.physics.energy import EnergyProfile
from core.physics.valence import ValenceBundle
from language_packs.schema import MorphologyEntry
_MANIFOLD_RESIDUAL_TOLERANCE = 1e-5
@ -68,6 +70,8 @@ class VocabManifold:
self._versors: list[np.ndarray] = [] # each shape (32,), unit-versor ±1
self._morphology_by_word: dict[str, MorphologyEntry] = {}
self._language_by_word: dict[str, str] = {}
self._energy_by_word: dict[str, EnergyProfile] = {}
self._valence_by_word: dict[str, ValenceBundle] = {}
self._transient_words: set[str] = set()
self._unknown_token_log: list[dict[str, object]] = []
@ -77,6 +81,8 @@ class VocabManifold:
versor: np.ndarray,
morphology: MorphologyEntry | None = None,
language: str | None = None,
energy: EnergyProfile | None = None,
valence: ValenceBundle | None = None,
) -> None:
"""
Register a word-versor pair.
@ -103,6 +109,10 @@ class VocabManifold:
self._language_by_word[word] = resolved_language
if morphology is not None:
self._morphology_by_word[word] = morphology
if energy is not None:
self._energy_by_word[word] = energy
if valence is not None:
self._valence_by_word[word] = valence
def insert_transient(self, word: str, versor: np.ndarray) -> None:
"""
@ -203,6 +213,14 @@ class VocabManifold:
"""Return structured morphology for a stored surface, if the pack provided it."""
return self._morphology_by_word.get(word)
def energy_for_word(self, word: str) -> EnergyProfile | None:
"""Return ADR-0006 energy profile for a stored surface, when available."""
return self._energy_by_word.get(word)
def valence_for_word(self, word: str) -> ValenceBundle | None:
"""Return ADR-0007 valence bundle for a stored surface, when available."""
return self._valence_by_word.get(word)
def language_for_word(self, word: str) -> str | None:
"""Return the language code for a stored surface, if known."""
morphology = self._morphology_by_word.get(word)