Merge pull request 'feat(physics,cognition): Cl(4,1) geometric sovereignty convergence' (#90) from feat/cl41-geometric-convergence-sovereignty into main
Reviewed-on: #90
This commit is contained in:
commit
1f1a94a39b
30 changed files with 1618 additions and 474 deletions
|
|
@ -2684,26 +2684,19 @@ class ChatRuntime:
|
|||
# --- end articulation fidelity ---
|
||||
|
||||
reasoning_trajectory = _make_trajectory_from_result(result, self._context.turn)
|
||||
# ADR-0244 §2.2 — operator-preservation identity gate (flag-gated). When
|
||||
# on, the check runs the metric-exact wave-field gate on the live versor
|
||||
# final_state.F; when off, wave_field=None selects the legacy scalar-L2
|
||||
# path (byte-identical). The boundary_ids intersection needs the
|
||||
# safety/ethics verdicts, which are computed below — it is supplemented
|
||||
# after those run.
|
||||
# ADR-0246 §3.7 — fuller admit surface, flag-gated + default-off. The
|
||||
# policy is placeholder/uncalibrated (calibrated=False); it only acts
|
||||
# when identity_wave_gate is also on (a wave_field exists).
|
||||
# ADR-0244 §2.2 — metric-exact operator-preservation identity score always
|
||||
# runs on the live versor final_state.F (scalar-L2 path excised). Live
|
||||
# *refusal* remains flag-gated via identity_wave_gate below.
|
||||
# ADR-0246 §3.7 — fuller admit surface, flag-gated + default-off.
|
||||
_admission_policy = (
|
||||
AdmissionPolicy.placeholder_default()
|
||||
if self.config.identity_action_surface
|
||||
if self.config.identity_action_surface and self.config.identity_wave_gate
|
||||
else None
|
||||
)
|
||||
identity_score = self._identity_check.check(
|
||||
reasoning_trajectory,
|
||||
self.identity_manifold,
|
||||
wave_field=(
|
||||
result.final_state.F if self.config.identity_wave_gate else None
|
||||
),
|
||||
wave_field=result.final_state.F,
|
||||
admission_policy=_admission_policy,
|
||||
turn_id=self._context.turn,
|
||||
pack_id=self.identity_pack_id,
|
||||
|
|
|
|||
|
|
@ -137,9 +137,8 @@ def serialize_turn_event(
|
|||
out["identity_deviation_axes"] = sorted(
|
||||
getattr(identity_score, "deviation_axes", ()) or ()
|
||||
)
|
||||
# ADR-0244 §2.2 — operator-preservation wave-gate telemetry. Emitted only
|
||||
# when the wave path ran (config.identity_wave_gate on); absent otherwise,
|
||||
# so the pre-ADR-0244 wire format stays byte-identical when the gate is off.
|
||||
# ADR-0244 §2.2 — operator-preservation wave-gate telemetry. Emitted when
|
||||
# the geometric score path ran (always after L2 excision when a score exists).
|
||||
if getattr(identity_score, "wave_mode_active", False):
|
||||
out["identity_wave_mode"] = True
|
||||
out["identity_leakage_norm"] = float(
|
||||
|
|
|
|||
|
|
@ -15,14 +15,21 @@ Constraint: ChatRuntime.chat() and ChatResponse contract are unchanged.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
from collections import OrderedDict
|
||||
|
||||
import numpy as np
|
||||
|
||||
from algebra.backend import versor_condition
|
||||
from algebra.cl41 import geometric_product, reverse, scalar_part
|
||||
from field.state import FieldState
|
||||
from core.cognition.leeway import build_leeway_record
|
||||
from core.cognition.result import CognitiveTurnResult
|
||||
from core.cognition.surface_resolution import resolve_surface
|
||||
from core.cognition.trace import compute_trace_hash, hash_admissibility_trace
|
||||
from core.physics.goldtether import coherence_residual
|
||||
from core.physics.wave_manifold import multivector_content_digest
|
||||
from core.reasoning.adapters import evidence_from_entailment_trace
|
||||
from generate.intent import classify_compound_intent
|
||||
from generate.intent_bridge import _is_useful_surface
|
||||
|
|
@ -92,6 +99,13 @@ _SUBJECT_STOPWORDS: frozenset[str] = frozenset({
|
|||
"your", "their", "answer",
|
||||
})
|
||||
|
||||
# Conformal atom unification (dossier Subsystem C.1).
|
||||
# Absolute "score > 1−ε" is only meaningful for normalized null-cone points
|
||||
# with self-inner ≈ 1. Pack versors can have cross-inner > 1, so we unify when
|
||||
# the mutual reverse-product matches both self-products within ε (exact same
|
||||
# geometric atom), else content-address by SHA-256 of components.
|
||||
_UNIFY_EPS = 1e-4
|
||||
|
||||
# Finding 5 (audit 2026-05-20) — cap the speculative-subjects cache so a
|
||||
# long teaching session cannot grow it without bound. 64 is large enough
|
||||
# to cover every distinct teaching subject a single session realistically
|
||||
|
|
@ -101,17 +115,6 @@ _SUBJECT_STOPWORDS: frozenset[str] = frozenset({
|
|||
# promotion removes it explicitly.
|
||||
_MAX_SPECULATIVE_SUBJECTS = 64
|
||||
|
||||
# All PASSTHROUGH variants normalised to "passthrough" for trace_hash so
|
||||
# pre-ADR-0144 hashes remain byte-identical after _ratify_intent gains
|
||||
# specific sub-values (ADR-0144 / ADR-0142 §Implementation debts, debt 1).
|
||||
_PASSTHROUGH_OUTCOMES: frozenset[str] = frozenset({
|
||||
"passthrough",
|
||||
"passthrough_no_field",
|
||||
"passthrough_no_vocab",
|
||||
"passthrough_no_versor",
|
||||
})
|
||||
|
||||
|
||||
class CognitiveTurnPipeline:
|
||||
"""Thin pipeline wrapper over ChatRuntime.
|
||||
|
||||
|
|
@ -222,8 +225,12 @@ class CognitiveTurnPipeline:
|
|||
from generate.exhaustion import RefusalReason as _ExhaustionRefusalReason
|
||||
_recognition_refusal_reason = _ExhaustionRefusalReason.RECOGNITION_REFUSED.value
|
||||
|
||||
# 1. LISTEN — capture pre-turn field state
|
||||
# 1. LISTEN — capture pre-turn field state. If absent, compile turn
|
||||
# tokens into an initial Cl(4,1) wave-packet before intent ratification
|
||||
# (Geometric Sovereignty — cold-start must compile a field first).
|
||||
field_state_before: FieldState | None = self._capture_field_state()
|
||||
if field_state_before is None or getattr(field_state_before, "F", None) is None:
|
||||
field_state_before = self._compile_turn_wave_packet(raw_tokens)
|
||||
|
||||
# 1b. CLASSIFY — intent and proposition graph (deterministic, pre-chat)
|
||||
# ADR-0089 Phase C1 (Finding 4, audit 2026-05-20) — run the
|
||||
|
|
@ -398,9 +405,16 @@ class CognitiveTurnPipeline:
|
|||
realized_plan = realize_semantic(target, grounded_graph)
|
||||
effective_graph = grounded_graph
|
||||
|
||||
gate_fired = (
|
||||
response.vault_hits == 0
|
||||
and response.grounding_source not in ("vault", "pack", "teaching")
|
||||
# Physical coherence only (vault_hits bookkeeping is not a gate).
|
||||
# gate_fired True ⇒ residual failure ⇒ substrate realizer refused.
|
||||
field_for_gate = self._capture_field_state()
|
||||
F_gate = getattr(field_for_gate, "F", None) if field_for_gate is not None else None
|
||||
if F_gate is None and field_state_before is not None:
|
||||
F_gate = field_state_before.F
|
||||
contract_assessment = self._geometry_contract_assessment(F_gate)
|
||||
gate_fired = bool(
|
||||
contract_assessment.missing_bindings
|
||||
or contract_assessment.unresolved_hazards
|
||||
)
|
||||
canonical = response.register_canonical_surface
|
||||
pre_decoration = response.pre_decoration_surface
|
||||
|
|
@ -428,12 +442,8 @@ class CognitiveTurnPipeline:
|
|||
entailment_trace = self._maybe_entailment_trace(intent, triples)
|
||||
|
||||
# === SHADOW COHERENCE GATE WIRING ===
|
||||
# Graph + realizer already executed unconditionally above.
|
||||
# Pass the effective (possibly grounded) graph so the gate can
|
||||
# apply the strict supremacy test. Assessment=None for Phase A
|
||||
# (assessments still live primarily in derivation organs). When
|
||||
# the main spine carries ProblemFrame through the turn, this
|
||||
# becomes the active contract backpressure site.
|
||||
# Dual-competing: substrate supremacy requires fully grounded graph
|
||||
# AND closed geometric contract (versor_condition + GoldTether residual).
|
||||
resolved = resolve_surface(
|
||||
canonical_surface=canonical,
|
||||
pre_decoration_surface=pre_decoration,
|
||||
|
|
@ -445,7 +455,7 @@ class CognitiveTurnPipeline:
|
|||
walk_surface=walk_surface,
|
||||
compose_surface=compose_surface,
|
||||
proposition_graph=effective_graph,
|
||||
contract_assessment=None,
|
||||
contract_assessment=contract_assessment,
|
||||
)
|
||||
surface = resolved.surface
|
||||
articulation_surface = resolved.articulation_surface
|
||||
|
|
@ -485,11 +495,41 @@ class CognitiveTurnPipeline:
|
|||
# Use pure build_node_depths for canonical extraction (nid-keyed).
|
||||
node_depths = build_node_depths(effective_graph.nodes) if effective_graph else {}
|
||||
if grounding_src == "oov" or has_pending:
|
||||
# Active conformal neighborhood probe (exact cga_inner over vault).
|
||||
probe_performed = False
|
||||
probe_neighbors: list[dict[str, object]] = []
|
||||
try:
|
||||
from algebra.backend import cga_inner as _cga_inner
|
||||
|
||||
F_probe = getattr(self._capture_field_state(), "F", None)
|
||||
vault = getattr(getattr(self.runtime, "session", None), "vault", None)
|
||||
if F_probe is not None and vault is not None and hasattr(vault, "entries"):
|
||||
scores: list[tuple[float, str]] = []
|
||||
for entry in list(vault.entries())[:64]:
|
||||
versor = getattr(entry, "versor", None)
|
||||
if versor is None and isinstance(entry, (tuple, list)) and entry:
|
||||
versor = entry[0]
|
||||
if versor is None:
|
||||
continue
|
||||
try:
|
||||
s = float(_cga_inner(F_probe, versor))
|
||||
except Exception:
|
||||
continue
|
||||
label = str(getattr(entry, "id", "") or getattr(entry, "key", "") or "")
|
||||
scores.append((s, label))
|
||||
scores.sort(key=lambda item: item[0], reverse=True)
|
||||
probe_neighbors = [
|
||||
{"cga_inner": s, "ref": lab} for s, lab in scores[:5]
|
||||
]
|
||||
probe_performed = True
|
||||
except Exception:
|
||||
probe_performed = False
|
||||
oov_geometric_context = {
|
||||
"unresolved_topology": effective_graph.get_unresolved_topology() if effective_graph else (),
|
||||
"intent_tag": getattr(intent, "tag", None).value if intent and getattr(intent, "tag", None) else "unknown",
|
||||
"geometric_probe_performed": False,
|
||||
"note": "Hook for geometric anti-unification: surrounding realized facts (via exact vault cga_inner) can infer relation type / SPECULATIVE var for the hole instead of lexical fallback.",
|
||||
"geometric_probe_performed": probe_performed,
|
||||
"conformal_neighbors": probe_neighbors,
|
||||
"note": "Conformal anti-unification probe: vault neighbors via exact cga_inner.",
|
||||
"node_depths": node_depths,
|
||||
}
|
||||
else:
|
||||
|
|
@ -619,16 +659,8 @@ class CognitiveTurnPipeline:
|
|||
admissibility_trace = response.admissibility_trace
|
||||
region_was_unconstrained = response.region_was_unconstrained
|
||||
admissibility_trace_hash = hash_admissibility_trace(admissibility_trace)
|
||||
# Normalise all PASSTHROUGH sub-values to "passthrough" so the value
|
||||
# stored in CognitiveTurnResult matches what goes into trace_hash
|
||||
# (trace_hash_from_result invariant) and pre-ADR-0144 hashes remain
|
||||
# byte-identical (ADR-0144 / ADR-0142 §Implementation debts, debt 1).
|
||||
_ratification_outcome_raw = ratified.outcome.value
|
||||
ratification_outcome = (
|
||||
"passthrough"
|
||||
if _ratification_outcome_raw in _PASSTHROUGH_OUTCOMES
|
||||
else _ratification_outcome_raw
|
||||
)
|
||||
# Geometric ratification outcomes only (ratified | demoted).
|
||||
ratification_outcome = ratified.outcome.value
|
||||
_trace_ratification_outcome = ratification_outcome
|
||||
# ADR-0024 Phase 2 + W-011 — refusal_reason precedence:
|
||||
# recognition wins (earlier-fail boundary) over generation.
|
||||
|
|
@ -749,46 +781,85 @@ class CognitiveTurnPipeline:
|
|||
# Internal helpers
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
def _compile_turn_wave_packet(self, tokens: tuple[str, ...] | list[str]) -> FieldState:
|
||||
"""Compile turn tokens into an initial Cl(4,1) field on the manifold.
|
||||
|
||||
Uses the session inject/probe path (holonomy encode + normalize_to_versor
|
||||
at the owned ingest boundary). Does not replace session state when
|
||||
probe_ingest is available (chat() still owns commit).
|
||||
"""
|
||||
session = getattr(self.runtime, "session", None)
|
||||
if session is None:
|
||||
raise RuntimeError(
|
||||
"CognitiveTurnPipeline cannot compile a wave-packet without a session"
|
||||
)
|
||||
token_list = [str(t) for t in tokens]
|
||||
if not token_list:
|
||||
token_list = ["_empty_"]
|
||||
if hasattr(session, "probe_ingest"):
|
||||
return session.probe_ingest(token_list)
|
||||
from ingest.gate import inject
|
||||
|
||||
vocab = getattr(session, "vocab", None)
|
||||
if vocab is None:
|
||||
raise RuntimeError(
|
||||
"CognitiveTurnPipeline cannot compile a wave-packet without session.vocab"
|
||||
)
|
||||
return inject(token_list, vocab)
|
||||
|
||||
@staticmethod
|
||||
def _geometry_contract_assessment(F):
|
||||
"""Build contract assessment from active versor + GoldTether residuals.
|
||||
|
||||
Closed only when versor_condition(F) < 1e-6 and R_GoldTether ≤ 1e-6.
|
||||
Local import avoids chat → cognition → problem_frame_contracts cycles
|
||||
(problem_frame_contracts imports chat.pack_resolver).
|
||||
"""
|
||||
from generate.problem_frame_contracts import ContractAssessment
|
||||
|
||||
if F is None:
|
||||
return ContractAssessment(
|
||||
candidate_organ="shadow_coherence_gate",
|
||||
missing_bindings=("missing_wave_field",),
|
||||
unresolved_hazards=(),
|
||||
runnable=False,
|
||||
explanation="no field versor available for geometric contract",
|
||||
)
|
||||
vc = float(versor_condition(F))
|
||||
r_gt = float(coherence_residual(F))
|
||||
missing: list[str] = []
|
||||
hazards: list[str] = []
|
||||
if vc >= 1e-6:
|
||||
missing.append("versor_condition")
|
||||
if r_gt > 1e-6:
|
||||
hazards.append("goldtether_residual")
|
||||
return ContractAssessment(
|
||||
candidate_organ="shadow_coherence_gate",
|
||||
missing_bindings=tuple(missing),
|
||||
unresolved_hazards=tuple(hazards),
|
||||
runnable=not missing and not hazards,
|
||||
explanation=(
|
||||
f"versor_condition={vc:.3e}; R_GoldTether={r_gt:.3e}"
|
||||
),
|
||||
)
|
||||
|
||||
def _ratify_intent(self, intent, field_state):
|
||||
"""Field-ratify a seeded intent (ADR-0022 §TBD-1).
|
||||
|
||||
Emits specific PASSTHROUGH sub-values (ADR-0144 / ADR-0142 debt 1)
|
||||
so the trace can distinguish which cold-start condition fired.
|
||||
All sub-values normalise to "passthrough" for trace_hash.
|
||||
Geometric Sovereignty: field must already be compiled (see :meth:`run`);
|
||||
vocab and prompt versor are required for conformal ratification.
|
||||
"""
|
||||
if field_state is None:
|
||||
return RatifiedIntent(
|
||||
intent=intent,
|
||||
outcome=RatificationOutcome.PASSTHROUGH_NO_FIELD,
|
||||
score=0.0,
|
||||
threshold=0.0,
|
||||
seed_tag=intent.tag,
|
||||
if field_state is None or getattr(field_state, "F", None) is None:
|
||||
raise RuntimeError(
|
||||
"intent ratification requires a compiled Cl(4,1) field state"
|
||||
)
|
||||
# ChatRuntime exposes vocab via session, not directly. The
|
||||
# original ADR-0022 wiring used ``getattr(self.runtime, "vocab",
|
||||
# None)`` which always returned None — silently routing every
|
||||
# turn through PASSTHROUGH. ADR-0023 §3 surfaced this via the
|
||||
# ``passthrough_on_scored`` lane metric; the fix here is to
|
||||
# resolve vocab through the session contract.
|
||||
session = getattr(self.runtime, "session", None)
|
||||
vocab = getattr(session, "vocab", None) if session is not None else None
|
||||
if vocab is None:
|
||||
return RatifiedIntent(
|
||||
intent=intent,
|
||||
outcome=RatificationOutcome.PASSTHROUGH_NO_VOCAB,
|
||||
score=0.0,
|
||||
threshold=0.0,
|
||||
seed_tag=intent.tag,
|
||||
)
|
||||
prompt_versor = getattr(field_state, "F", None)
|
||||
if prompt_versor is None:
|
||||
return RatifiedIntent(
|
||||
intent=intent,
|
||||
outcome=RatificationOutcome.PASSTHROUGH_NO_VERSOR,
|
||||
score=0.0,
|
||||
threshold=0.0,
|
||||
seed_tag=intent.tag,
|
||||
raise RuntimeError(
|
||||
"intent ratification requires session.vocab"
|
||||
)
|
||||
prompt_versor = field_state.F
|
||||
return ratify_intent(intent, prompt_versor, vocab=vocab)
|
||||
|
||||
def _remember_speculative_subject(self, subject: str) -> None:
|
||||
|
|
@ -871,10 +942,27 @@ class CognitiveTurnPipeline:
|
|||
return None, None, None
|
||||
|
||||
manifold = getattr(self.runtime, "identity_manifold", None)
|
||||
# ADR-0244 honest scope: with ``identity_wave_gate`` off, live
|
||||
# final_state.F scores routinely show high leakage and axis inversion
|
||||
# because value axes are not yet dynamically load-bearing. Those
|
||||
# measures are observational telemetry, not teaching veto authority.
|
||||
# Only committed ``boundary_violations`` (safety/ethics ∩ manifold)
|
||||
# remain a hard geometric teaching reject while the gate is off.
|
||||
# Syntactic identity-override detection remains active regardless.
|
||||
review_score = identity_score
|
||||
cfg = getattr(self.runtime, "config", None)
|
||||
gate_on = bool(getattr(cfg, "identity_wave_gate", False))
|
||||
if (
|
||||
not gate_on
|
||||
and identity_score is not None
|
||||
and bool(getattr(identity_score, "wave_mode_active", False))
|
||||
and not bool(getattr(identity_score, "boundary_violations", ()) or ())
|
||||
):
|
||||
review_score = None
|
||||
reviewed = review_correction(
|
||||
candidate,
|
||||
identity_score=identity_score, # type: ignore[arg-type]
|
||||
identity_manifold=manifold,
|
||||
identity_score=review_score, # type: ignore[arg-type]
|
||||
identity_manifold=manifold if review_score is not None else None,
|
||||
)
|
||||
proposal = self.teaching_store.add(reviewed)
|
||||
return candidate, reviewed, proposal
|
||||
|
|
@ -959,13 +1047,17 @@ class CognitiveTurnPipeline:
|
|||
Telemetry-only v1: the result is folded into ``operator_invocation`` and
|
||||
never changes the user-facing surface. Runs only when classification
|
||||
exposes a precise positive ``subject relation object`` shape.
|
||||
|
||||
Atoms are content-addressed by Cl(4,1) versor digests and unified by
|
||||
conformal reverse-product score (no string ``atom_`` join).
|
||||
"""
|
||||
if intent.tag is not IntentTag.VERIFICATION:
|
||||
return None
|
||||
if intent.negated or not intent.relation or not intent.object:
|
||||
return None
|
||||
head = self._proof_atom(intent.subject)
|
||||
tail = self._proof_atom(intent.object)
|
||||
registry: list[tuple[str, np.ndarray]] = []
|
||||
head = self._proof_atom(intent.subject, registry)
|
||||
tail = self._proof_atom(intent.object, registry)
|
||||
if not head or not tail:
|
||||
return None
|
||||
|
||||
|
|
@ -974,8 +1066,8 @@ class CognitiveTurnPipeline:
|
|||
for h, r, t in triples:
|
||||
if r.strip().lower() != relation:
|
||||
continue
|
||||
h_atom = self._proof_atom(h)
|
||||
t_atom = self._proof_atom(t)
|
||||
h_atom = self._proof_atom(h, registry)
|
||||
t_atom = self._proof_atom(t, registry)
|
||||
if h_atom and t_atom:
|
||||
premises.append(f"{h_atom} -> {t_atom}")
|
||||
if not premises:
|
||||
|
|
@ -1019,12 +1111,68 @@ class CognitiveTurnPipeline:
|
|||
return ""
|
||||
return f"entailment:{evidence_from_entailment_trace(trace).canonical_json()}"
|
||||
|
||||
def _resolve_surface_versor(self, text: str) -> np.ndarray | None:
|
||||
"""Resolve surface text to a vocab-grounded Cl(4,1) versor, or None."""
|
||||
session = getattr(self.runtime, "session", None)
|
||||
vocab = getattr(session, "vocab", None) if session is not None else None
|
||||
if vocab is None or not text:
|
||||
return None
|
||||
tokens = [p for p in _SUBJECT_SPLIT_RE.split(text.lower()) if p]
|
||||
# Prefer last non-stopword content token (subject-like), then any token.
|
||||
ordered = [t for t in reversed(tokens) if t not in _SUBJECT_STOPWORDS] + tokens
|
||||
for token in ordered:
|
||||
try:
|
||||
return np.asarray(vocab.get_versor(token), dtype=np.float64)
|
||||
except (KeyError, AttributeError):
|
||||
continue
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def _proof_atom(text: str) -> str:
|
||||
parts = [p for p in _SUBJECT_SPLIT_RE.split(text.lower()) if p]
|
||||
if not parts:
|
||||
def _unify_score(a: np.ndarray, b: np.ndarray) -> float:
|
||||
"""⟨a, ~b⟩_0 — scalar part of geometric product with reversion."""
|
||||
return float(scalar_part(geometric_product(a, reverse(b))))
|
||||
|
||||
@classmethod
|
||||
def _atoms_unify(cls, a: np.ndarray, b: np.ndarray) -> bool:
|
||||
"""True when a and b are the same geometric atom under reverse-product.
|
||||
|
||||
Requires mutual score to match both self-products within ``_UNIFY_EPS``
|
||||
(relative when |self| ≥ 1, absolute otherwise). Exact component match
|
||||
short-circuits. Distinct pack versors with large cross-inner do not unify.
|
||||
"""
|
||||
if a.shape != b.shape:
|
||||
return False
|
||||
if np.allclose(a, b, rtol=0.0, atol=1e-9):
|
||||
return True
|
||||
sa = cls._unify_score(a, a)
|
||||
sb = cls._unify_score(b, b)
|
||||
sab = cls._unify_score(a, b)
|
||||
scale = max(1.0, abs(sa), abs(sb))
|
||||
tol = _UNIFY_EPS * scale
|
||||
return abs(sab - sa) <= tol and abs(sab - sb) <= tol
|
||||
|
||||
def _proof_atom(
|
||||
self,
|
||||
text: str,
|
||||
registry: list[tuple[str, np.ndarray]] | None = None,
|
||||
) -> str:
|
||||
"""Content-addressed conformal atom id for entailment telemetry.
|
||||
|
||||
Two surfaces unify to the same atom iff their grounded versors match
|
||||
under :meth:`_atoms_unify`. Ungrounded surfaces fail closed (empty id).
|
||||
"""
|
||||
psi = self._resolve_surface_versor(text)
|
||||
if psi is None:
|
||||
return ""
|
||||
return "atom_" + "_".join(parts)
|
||||
if registry is not None:
|
||||
for atom_id, prior in registry:
|
||||
if self._atoms_unify(psi, prior):
|
||||
return atom_id
|
||||
digest = multivector_content_digest(psi)
|
||||
atom_id = f"atom_{digest}"
|
||||
if registry is not None:
|
||||
registry.append((atom_id, psi.copy()))
|
||||
return atom_id
|
||||
|
||||
@staticmethod
|
||||
def _render_walk_surface(walk: WalkResult) -> str:
|
||||
|
|
|
|||
|
|
@ -71,47 +71,25 @@ def resolve_surface(
|
|||
proposition_graph: "PropositionGraph | None" = None,
|
||||
contract_assessment: "ContractAssessment | None" = None,
|
||||
) -> SurfaceResolution:
|
||||
"""Resolve the final turn surface under one explicit policy.
|
||||
"""Resolve the final turn surface under dual-competing Shadow Coherence Gate.
|
||||
|
||||
The Shadow Coherence Gate (Strangler Fig Pattern per the refined plan):
|
||||
Dual-competing gate (forward ∧ conjugate) — both must pass to commit
|
||||
substrate authority:
|
||||
|
||||
- The PropositionGraph and realize_semantic are executed *unconditionally*
|
||||
on every turn (already true in pipeline before this call).
|
||||
- Authority is granted to the substrate realizer **only** when the
|
||||
strict geometric guard passes:
|
||||
* graph.is_fully_grounded() (no <pending> slots remain)
|
||||
* contract assessment (if present) is closed (no missing_bindings,
|
||||
no unresolved_hazards)
|
||||
* gate did not fire (unknown domain safety)
|
||||
Versor coherence (< 1e-6) is presupposed by construction at the
|
||||
boundaries that produced the graph/bindings; it is not re-"repaired"
|
||||
here.
|
||||
- When the guard refuses, we fall back to the legacy runtime surface
|
||||
and the *precise* topological delta is recorded upstream as
|
||||
SUBSTRATE_BYPASS_HAZARD telemetry. This makes every test run and
|
||||
every production turn a diagnostic that lights exactly which
|
||||
ProblemFrame / recall / realizer gaps still block substrate supremacy.
|
||||
- Legacy "realizer_useful" path is retained only as a transitional
|
||||
compat shim; the supreme check is the load-bearing decision.
|
||||
* **Forward** (surface resolution): graph fully grounded; structural
|
||||
contract slots closed when assessment present.
|
||||
* **Conjugate** (coherence correction check): geometric contract closed
|
||||
— versor_condition / GoldTether residual encoded as zero
|
||||
``missing_bindings`` and zero ``unresolved_hazards`` on
|
||||
``contract_assessment``. Assessment is **required** for substrate
|
||||
commit; ``None`` refuses geometric authority (fail-closed).
|
||||
|
||||
When either competitor fails, authority stays on the runtime base surface.
|
||||
The transitional ``realizer_useful`` shim is admitted only when conjugate
|
||||
coherence still passes (never as a substitute for a failed geometric gate).
|
||||
|
||||
Walk/compose folds are *always* suffixes — they never affect the
|
||||
authority prefix decision.
|
||||
|
||||
Three Engineering Pillars are non-negotiable here:
|
||||
I. Mechanical Sympathy — the entire decision is a handful of O(N)
|
||||
structural inspections on tiny tuples; zero extra alloc, zero
|
||||
cross-language roundtrip, zero sensitivity to FMA/assoc drift.
|
||||
II. Semantic Rigor — every term ("fully_grounded", "substrate_realizer",
|
||||
"bypass_hazard") has one precise meaning. No numeric tolerance,
|
||||
no "good enough" surface.
|
||||
III. Third Door — we did not pick "keep the regex sidecar" nor
|
||||
"rip it out and break the suite". We built the substrate spine
|
||||
as the sole authority path and made the old path the observable
|
||||
bypass that starves itself to zero.
|
||||
|
||||
See also: engineer's assessment §1 (Authority Flip Cliff), AGENTS.md
|
||||
(versor only at owned boundaries, exact recall, kernel substrate rule),
|
||||
runtime_contracts.md (surface selection contract).
|
||||
"""
|
||||
|
||||
surface, articulation_surface, authority = _base_runtime_surface(
|
||||
|
|
@ -121,20 +99,28 @@ def resolve_surface(
|
|||
response_articulation_surface=response_articulation_surface or "",
|
||||
)
|
||||
|
||||
# === SHADOW COHERENCE GATE ===
|
||||
# Unconditional substrate execution has already occurred.
|
||||
# We now decide authority strictly.
|
||||
if not gate_fired and realized_surface:
|
||||
if _substrate_supreme(proposition_graph, contract_assessment):
|
||||
surface = realized_surface
|
||||
articulation_surface = realized_surface
|
||||
authority = "substrate_realizer"
|
||||
elif realizer_useful:
|
||||
# Transitional shim (pre full coverage of grounding + organs).
|
||||
# Will be removed when hazard frequency for the legacy path hits zero.
|
||||
surface = realized_surface
|
||||
articulation_surface = realized_surface
|
||||
authority = "realizer"
|
||||
# === DUAL-COMPETING SHADOW COHERENCE GATE ===
|
||||
# Forward and conjugate evaluated as independent competitors; commit
|
||||
# substrate only when both pass (and gate_fired is false).
|
||||
forward_ok = _forward_surface_ok(proposition_graph, contract_assessment)
|
||||
conjugate_ok = _conjugate_coherence_ok(contract_assessment)
|
||||
|
||||
if not gate_fired and realized_surface and forward_ok and conjugate_ok:
|
||||
surface = realized_surface
|
||||
articulation_surface = realized_surface
|
||||
authority = "substrate_realizer"
|
||||
elif (
|
||||
not gate_fired
|
||||
and realized_surface
|
||||
and realizer_useful
|
||||
and conjugate_ok
|
||||
and not forward_ok
|
||||
):
|
||||
# Transitional shim: geometric coherence holds, but graph not yet
|
||||
# fully grounded. Never used when conjugate residual fails.
|
||||
surface = realized_surface
|
||||
articulation_surface = realized_surface
|
||||
authority = "realizer"
|
||||
|
||||
fold_sources: list[str] = []
|
||||
if walk_surface:
|
||||
|
|
@ -163,39 +149,42 @@ def resolve_surface(
|
|||
)
|
||||
|
||||
|
||||
def _substrate_supreme(
|
||||
def _conjugate_coherence_ok(
|
||||
contract_assessment: "ContractAssessment | None",
|
||||
) -> bool:
|
||||
"""Conjugate competitor: geometric residual contract must be closed.
|
||||
|
||||
Requires an explicit assessment (populated from versor_condition +
|
||||
GoldTether residual upstream). ``None`` fails closed — no soft admit.
|
||||
"""
|
||||
if contract_assessment is None:
|
||||
return False
|
||||
if contract_assessment.missing_bindings or contract_assessment.unresolved_hazards:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _forward_surface_ok(
|
||||
proposition_graph: "PropositionGraph | None",
|
||||
contract_assessment: "ContractAssessment | None",
|
||||
) -> bool:
|
||||
"""Return True only when the geometric substrate has earned authority.
|
||||
|
||||
This is the single source of truth for "use the PropositionGraph path
|
||||
as the cognitive spine instead of legacy runtime/pack/walk".
|
||||
|
||||
Conditions (all must hold):
|
||||
- A graph was produced.
|
||||
- graph.is_fully_grounded() — every slot bound by exact recall or
|
||||
direct construction (no <pending>).
|
||||
- If a ContractAssessment is supplied, it must be closed
|
||||
(zero missing_bindings and zero unresolved_hazards).
|
||||
(Assessments are still diagnostic-only in many organs; when the
|
||||
main spine wires ProblemFrame + assess_contracts, this becomes
|
||||
active backpressure — see Layer 3/Phase D.)
|
||||
|
||||
Versor coherence is *not* re-checked with a repair here. It is
|
||||
required by construction at the sites that emit versors (see
|
||||
VersorBinding and algebra/versor.py). Passing a non-coherent state
|
||||
here is a programmer error, not a runtime tolerance.
|
||||
|
||||
When this returns False the caller (pipeline) must emit the
|
||||
SUBSTRATE_BYPASS_HAZARD with graph.get_unresolved_topology() so the
|
||||
failure is actionable rather than silent.
|
||||
"""
|
||||
"""Forward competitor: structural graph readiness for substrate surface."""
|
||||
if proposition_graph is None:
|
||||
return False
|
||||
if not proposition_graph.is_fully_grounded():
|
||||
return False
|
||||
# Structural contract slots (when assessment carries organ bindings).
|
||||
if contract_assessment is not None:
|
||||
if contract_assessment.missing_bindings or contract_assessment.unresolved_hazards:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def _substrate_supreme(
|
||||
proposition_graph: "PropositionGraph | None",
|
||||
contract_assessment: "ContractAssessment | None",
|
||||
) -> bool:
|
||||
"""True iff both dual-competing Shadow Gate competitors pass."""
|
||||
return _forward_surface_ok(proposition_graph, contract_assessment) and (
|
||||
_conjugate_coherence_ok(contract_assessment)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -292,15 +292,12 @@ class RuntimeConfig:
|
|||
# wanting a hard identity-continuity guarantee opt in.
|
||||
strict_identity_continuity: bool = False
|
||||
|
||||
# ADR-0244 §2.2 / §4a — operator-preservation identity gate. When on, the
|
||||
# per-turn identity check runs the metric-exact wave-field gate on the live
|
||||
# versor (final_state.F): subspace-leakage + signed self-alignment via
|
||||
# F aᵢ F̃, plus the boundary_ids intersection with the turn's safety/ethics
|
||||
# violations, and a fail-closed IdentityGateRefusal folded into the typed
|
||||
# refusal surface. OFF by default: the leakage threshold is provisional
|
||||
# (reuses alignment_threshold) until calibrated to γ_id in D4 Phase 3, and
|
||||
# the flag-off path is byte-identical to the pre-ADR-0244 advisory behavior
|
||||
# (legacy scalar-L2 identity score, no geometric refusal).
|
||||
# ADR-0244 §2.2 / §4a — live identity *refusal* on operator-preservation
|
||||
# leakage / inversion / boundary breach (IdentityGateRefusal). Scoring always
|
||||
# uses the metric-exact wave path on final_state.F; this flag only controls
|
||||
# whether a flagged score becomes a typed refusal surface. OFF by default:
|
||||
# γ_id separates geometric attack signal from benign traffic poorly on the
|
||||
# current nominal axis frame (see ADR-0244 Phase 3 honesty notes).
|
||||
identity_wave_gate: bool = False
|
||||
|
||||
# ADR-0246 §3.7 — the fuller induced-action admit surface (d_orth, d_stab vs
|
||||
|
|
|
|||
|
|
@ -23,7 +23,14 @@ from core.physics.reasoning import ReasoningTrajectory, TrajectoryOperator
|
|||
from core.physics.articulation import ArticulationPlan, ArticulationPlanner, OutputModality
|
||||
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.identity import (
|
||||
CharacterProfile,
|
||||
IdentityCheck,
|
||||
IdentityGateRefusal,
|
||||
IdentityManifold,
|
||||
IdentityScore,
|
||||
MissingWaveStateError,
|
||||
)
|
||||
from core.physics.learning import PromotionDecision, VaultPromotionPolicy
|
||||
from core.physics.goldtether import (
|
||||
AutonomyBand,
|
||||
|
|
@ -31,9 +38,11 @@ from core.physics.goldtether import (
|
|||
CoherenceResidual,
|
||||
GoldPromotionProof,
|
||||
GoldTetherMonitor,
|
||||
GoldTetherViolationError,
|
||||
OperatingMode,
|
||||
coherence_residual,
|
||||
propose_kappa_line_search,
|
||||
require_unitary,
|
||||
)
|
||||
from core.physics.dynamic_manifold import (
|
||||
AxisClassification,
|
||||
|
|
@ -230,9 +239,11 @@ __all__ = [
|
|||
"DriveGradientMap", "GradientField", "ValueAxis",
|
||||
"ExertionMeter", "FatigueIndex", "CycleCost",
|
||||
"IdentityManifold", "IdentityCheck", "IdentityScore", "CharacterProfile",
|
||||
"IdentityGateRefusal", "MissingWaveStateError",
|
||||
"PromotionDecision", "VaultPromotionPolicy",
|
||||
"AutonomyBand", "AutonomyDecision", "CoherenceResidual",
|
||||
"GoldPromotionProof", "GoldTetherMonitor", "OperatingMode", "coherence_residual",
|
||||
"GoldPromotionProof", "GoldTetherMonitor", "GoldTetherViolationError",
|
||||
"OperatingMode", "coherence_residual", "require_unitary",
|
||||
"AxisClassification", "CartanIwasawaFactors", "ConformalProcrustesResult",
|
||||
"PrincipalAxis", "SignatureAwarePCAResult",
|
||||
"cartan_iwasawa_extract", "cartan_iwasawa_factorize",
|
||||
|
|
|
|||
|
|
@ -68,15 +68,23 @@ if TYPE_CHECKING: # annotation-only: the monitor instance is caller-supplied
|
|||
|
||||
import numpy as np
|
||||
|
||||
from algebra.cl41 import N_COMPONENTS, geometric_product
|
||||
from algebra.cl41 import N_COMPONENTS, geometric_product, reverse
|
||||
from algebra.rotor import word_transition_rotor
|
||||
from algebra.versor import versor_condition
|
||||
from core.physics.energy import EnergyClass, EnergyProfile, FieldEnergyOperator
|
||||
from core.physics.sensorium_wave_feed import PacketLike, _coerce_packet, superpose_packets
|
||||
from core.physics.goldtether import GoldTetherViolationError, require_unitary
|
||||
from core.physics.sensorium_wave_feed import (
|
||||
PacketLike,
|
||||
_coerce_packet,
|
||||
compile_packet_to_psi,
|
||||
superpose_packets,
|
||||
)
|
||||
from core.physics.wave_energy_boundary import (
|
||||
CrystallizationDecision,
|
||||
crystallization_for_holographic_seal,
|
||||
energy_profile_from_wave,
|
||||
)
|
||||
from core.physics.wave_manifold import WaveManifold
|
||||
from core.physics.wave_manifold import WaveManifold, multivector_content_digest
|
||||
|
||||
_NEAR_ZERO = 1e-12
|
||||
_UNIT_TOL = 1e-9
|
||||
|
|
@ -213,46 +221,181 @@ def assignment_component_index(assignment_mask: int) -> int:
|
|||
# --- Ingress ----------------------------------------------------------------------
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class ModalityTransition:
|
||||
"""Provenance for a versor-sandwich modality transition (Spin(4,1))."""
|
||||
|
||||
psi_in_digest: str
|
||||
psi_out_digest: str
|
||||
rotor_digest: str
|
||||
goldtether_residual: float
|
||||
source_modality: str
|
||||
target_modality: str
|
||||
|
||||
def as_dict(self) -> dict[str, Any]:
|
||||
return {
|
||||
"psi_in_digest": self.psi_in_digest,
|
||||
"psi_out_digest": self.psi_out_digest,
|
||||
"rotor_digest": self.rotor_digest,
|
||||
"goldtether_residual": float(self.goldtether_residual),
|
||||
"source_modality": self.source_modality,
|
||||
"target_modality": self.target_modality,
|
||||
}
|
||||
|
||||
|
||||
def modality_transition_sandwich(
|
||||
psi_in: np.ndarray,
|
||||
rotor: np.ndarray,
|
||||
*,
|
||||
source_modality: str = "",
|
||||
target_modality: str = "",
|
||||
epsilon_drift: float = _EPSILON_DRIFT,
|
||||
) -> tuple[np.ndarray, ModalityTransition]:
|
||||
"""Inter-modality transition: ψ_out = R · ψ_in · rev(R), R ∈ Spin(4,1).
|
||||
|
||||
Fail-closed GoldTether validation on the output (and on the rotor unit
|
||||
residual). Digests are full SHA-256 over little-endian float64 bytes.
|
||||
Maps the dossier's multimodal_lifecycle sandwich contract onto this module
|
||||
(the real lifecycle owner; ``multimodal_lifecycle.py`` does not exist).
|
||||
"""
|
||||
psi = _as_psi(psi_in, "ψ_in", error=IngressDegenerate)
|
||||
R = np.asarray(rotor, dtype=np.float64)
|
||||
if R.shape != (N_COMPONENTS,):
|
||||
raise IngressDegenerate("bad_rotor_shape", shape=list(R.shape))
|
||||
if float(versor_condition(R)) >= float(epsilon_drift):
|
||||
raise GoldTetherViolationError(
|
||||
float(versor_condition(R)),
|
||||
float(epsilon_drift),
|
||||
detail="modality rotor not unit versor",
|
||||
)
|
||||
# ψ_out = R ψ rev(R)
|
||||
psi_out = geometric_product(geometric_product(R, psi), reverse(R)).astype(np.float64)
|
||||
residual = float(require_unitary(psi_out, epsilon=float(epsilon_drift)))
|
||||
transition = ModalityTransition(
|
||||
psi_in_digest=multivector_content_digest(psi),
|
||||
psi_out_digest=multivector_content_digest(psi_out),
|
||||
rotor_digest=multivector_content_digest(R),
|
||||
goldtether_residual=residual,
|
||||
source_modality=str(source_modality),
|
||||
target_modality=str(target_modality),
|
||||
)
|
||||
return psi_out, transition
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class IngressWavePacket:
|
||||
"""Normalized ingress field ψ_context with provenance (ADR-0243 §2.1)."""
|
||||
"""Normalized ingress field ψ_context with provenance (ADR-0243 §2.1).
|
||||
|
||||
Multi-modality composition is sandwich-governed: each inter-modality step
|
||||
is recorded in ``modality_transitions`` with full SHA-256 digests.
|
||||
"""
|
||||
|
||||
psi: np.ndarray
|
||||
domain_id: str
|
||||
modality_ids: tuple[str, ...]
|
||||
packet_digest: str
|
||||
modality_transitions: tuple[ModalityTransition, ...] = ()
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
arr = _as_psi(self.psi, "ψ_context", error=IngressDegenerate)
|
||||
arr = arr.copy()
|
||||
arr.setflags(write=False)
|
||||
object.__setattr__(self, "psi", arr)
|
||||
object.__setattr__(
|
||||
self,
|
||||
"modality_transitions",
|
||||
tuple(self.modality_transitions),
|
||||
)
|
||||
|
||||
|
||||
def _construction_unitize(psi: np.ndarray, *, name: str) -> np.ndarray:
|
||||
"""Owned construction-boundary Euclidean unitize (not hot-path repair)."""
|
||||
arr = np.asarray(psi, dtype=np.float64).reshape(-1)
|
||||
if arr.shape != (N_COMPONENTS,):
|
||||
raise IngressDegenerate("bad_shape", name=name, shape=list(arr.shape))
|
||||
if not np.all(np.isfinite(arr)):
|
||||
raise IngressDegenerate("non_finite", name=name)
|
||||
norm = float(np.linalg.norm(arr))
|
||||
if not np.isfinite(norm) or norm < _NEAR_ZERO:
|
||||
raise IngressDegenerate("degenerate_packet", name=name, norm=norm)
|
||||
return (arr / norm).astype(np.float64)
|
||||
|
||||
|
||||
def ingest_context(packets: Sequence[PacketLike], domain_id: str) -> IngressWavePacket:
|
||||
"""Superpose modality packets and normalize at the owned construction boundary.
|
||||
"""Compose modality packets into ψ_context with sandwich-governed multi-modality.
|
||||
|
||||
Delegates superposition to :func:`sensorium_wave_feed.superpose_packets`
|
||||
(which refuses empty input). Normalization here is the ONE owned
|
||||
construction boundary of the lifecycle (D-3) — a degenerate superposition
|
||||
(destructive cancellation below ``1e-12``) is refused, never zero-filled.
|
||||
* Empty input refuses (via superpose preflight / empty list).
|
||||
* Degenerate linear cancellation (Σψ ≈ 0) refuses as construction failure.
|
||||
* Single packet: construction-boundary unitize only.
|
||||
* Multi-packet: successive Spin(4,1) sandwiches
|
||||
``ψ ← R_i · ψ · rev(R_i)`` with
|
||||
``R_i = word_transition_rotor(ψ, ψ_{i+1})``, each step fail-closed via
|
||||
:func:`modality_transition_sandwich` (GoldTether + SHA-256 digests).
|
||||
|
||||
Normalization / unitize lives only at this owned construction boundary.
|
||||
"""
|
||||
domain = str(domain_id).strip()
|
||||
if not domain:
|
||||
raise IngressDegenerate("empty_domain_id")
|
||||
if not packets:
|
||||
raise ValueError("superpose_packets: empty packet list")
|
||||
|
||||
# Preflight: refuse empty and destructive cancellation (Σψ ≈ 0).
|
||||
total = superpose_packets(packets)
|
||||
norm = float(np.linalg.norm(total))
|
||||
if not np.isfinite(norm) or norm < _NEAR_ZERO:
|
||||
raise IngressDegenerate("degenerate_superposition", norm=norm, n_packets=len(packets))
|
||||
psi = (total / norm).astype(np.float64)
|
||||
modality_ids = tuple(_coerce_packet(p).modality_id for p in packets)
|
||||
mass = float(np.linalg.norm(total))
|
||||
if not np.isfinite(mass) or mass < _NEAR_ZERO:
|
||||
raise IngressDegenerate(
|
||||
"degenerate_superposition", norm=mass, n_packets=len(packets)
|
||||
)
|
||||
|
||||
coerced = [_coerce_packet(p) for p in packets]
|
||||
modality_ids = tuple(p.modality_id for p in coerced)
|
||||
transitions: list[ModalityTransition] = []
|
||||
|
||||
# Seed from first packet at construction boundary.
|
||||
psi = _construction_unitize(
|
||||
compile_packet_to_psi(coerced[0]), name="packet[0]"
|
||||
)
|
||||
|
||||
# Multi-modality: sandwich each subsequent packet into the field.
|
||||
for i in range(1, len(coerced)):
|
||||
target = _construction_unitize(
|
||||
compile_packet_to_psi(coerced[i]), name=f"packet[{i}]"
|
||||
)
|
||||
try:
|
||||
rotor = word_transition_rotor(psi, target)
|
||||
except ValueError as exc:
|
||||
raise IngressDegenerate(
|
||||
"modality_rotor_refused",
|
||||
source=modality_ids[i - 1],
|
||||
target=modality_ids[i],
|
||||
detail=str(exc),
|
||||
) from exc
|
||||
psi, tr = modality_transition_sandwich(
|
||||
psi,
|
||||
rotor,
|
||||
source_modality=modality_ids[i - 1],
|
||||
target_modality=modality_ids[i],
|
||||
epsilon_drift=_EPSILON_DRIFT,
|
||||
)
|
||||
transitions.append(tr)
|
||||
|
||||
# Final construction close: unit Euclidean density for energy path.
|
||||
psi = _construction_unitize(psi, name="ψ_context")
|
||||
digests = [tr.psi_out_digest for tr in transitions]
|
||||
return IngressWavePacket(
|
||||
psi=psi,
|
||||
domain_id=domain,
|
||||
modality_ids=modality_ids,
|
||||
packet_digest=_content_id(
|
||||
{"psi": _psi_digest(psi), "domain": domain, "modalities": list(modality_ids)}
|
||||
{
|
||||
"psi": _psi_digest(psi),
|
||||
"domain": domain,
|
||||
"modalities": list(modality_ids),
|
||||
"transitions": digests,
|
||||
}
|
||||
),
|
||||
modality_transitions=tuple(transitions),
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -1053,7 +1196,14 @@ def tether_reading(
|
|||
autonomy = float(monitor.autonomy)
|
||||
updated = False
|
||||
else:
|
||||
residual, autonomy = monitor.update(arr)
|
||||
# ``GoldTetherMonitor.update`` raises on R > ε after forcing autonomy
|
||||
# to zero. Corridor tether readings must surface that fail-closed
|
||||
# residual without aborting the lifecycle observation path.
|
||||
try:
|
||||
residual, autonomy = monitor.update(arr)
|
||||
except GoldTetherViolationError as exc:
|
||||
residual = float(exc.residual)
|
||||
autonomy = float(monitor.autonomy)
|
||||
updated = True
|
||||
chiral_verdict = monitor.chiral_gate.observe(arr).verdict
|
||||
return TetherReading(
|
||||
|
|
@ -1198,6 +1348,8 @@ __all__ = [
|
|||
"compile_quadratic_well",
|
||||
"egress_gate",
|
||||
"ingest_context",
|
||||
"modality_transition_sandwich",
|
||||
"ModalityTransition",
|
||||
"propositional_entails",
|
||||
"relax_to_ground",
|
||||
"serving_cast",
|
||||
|
|
|
|||
|
|
@ -2,20 +2,15 @@
|
|||
core/physics/goldtether.py
|
||||
|
||||
GoldTether — Coherence Residual Monitor + Dynamic Autonomy Floor
|
||||
ADR-0238
|
||||
ADR-0238 / ADR-0241 wave residual path.
|
||||
|
||||
Note (fidelity #19, RETIRED): an earlier draft borrowed grade-5 "pseudoscalar"
|
||||
vocabulary from Super-Blueprint §3.3 for the autonomy floor and read ``F[31]``
|
||||
into telemetry. That anchor is vacuous in odd-dim Cl(4,1) — field-state versors
|
||||
are even (``F[31] ≡ 0``) and ``I₅`` is central (``V·I₅·Ṽ = I₅`` for every
|
||||
versor), so no non-vacuous grade-5 transition invariant exists. The namesake is
|
||||
removed; the integrity-anchor role is carried by versor closure + the harmonized
|
||||
GoldTether residual + biography/identity holonomy. See
|
||||
``docs/research/third-door-blueprint-fidelity.md`` §5.
|
||||
Primary residual:
|
||||
R = || ψ · reverse(ψ) − 1 ||_F
|
||||
via :meth:`WaveManifold.measure_unitary_residual` (dual-checked). Transitions
|
||||
with R > epsilon_drift raise :class:`GoldTetherViolationError` synchronously
|
||||
(:meth:`GoldTetherMonitor.update`, :func:`require_unitary`).
|
||||
|
||||
Absolute mastery implementation on the live Cl(4,1) algebra kernel.
|
||||
All operators are pure where possible, dual-corrected, and enforce algebraic
|
||||
closure on versor-valued outputs.
|
||||
No flat ``np.dot`` residual path. No external I₅ matrix parameters.
|
||||
|
||||
Distinct from Arena GoldTether (ADR-0199 / core.learning_arena.protocols).
|
||||
"""
|
||||
|
|
@ -107,6 +102,25 @@ class AutonomyDecision:
|
|||
reason: str
|
||||
|
||||
|
||||
class GoldTetherViolationError(ValueError):
|
||||
"""Fail-closed rejection when unitary amplitude drift exceeds tolerance.
|
||||
|
||||
Raised synchronously when ``R_GoldTether > epsilon`` (default ``1e-6``).
|
||||
Does not soft-warn or defer; the transition must not commit.
|
||||
"""
|
||||
|
||||
def __init__(self, residual: float, epsilon: float = 1e-6, *, detail: str = "") -> None:
|
||||
self.residual = float(residual)
|
||||
self.epsilon = float(epsilon)
|
||||
msg = (
|
||||
f"GoldTether violation: R={self.residual:.3e} exceeds "
|
||||
f"epsilon={self.epsilon:.3e}"
|
||||
)
|
||||
if detail:
|
||||
msg = f"{msg} ({detail})"
|
||||
super().__init__(msg)
|
||||
|
||||
|
||||
def _as_mv(F: np.ndarray, name: str = "F") -> np.ndarray:
|
||||
arr = np.asarray(F, dtype=np.float64)
|
||||
if arr.shape != (N_COMPONENTS,):
|
||||
|
|
@ -117,14 +131,34 @@ def _as_mv(F: np.ndarray, name: str = "F") -> np.ndarray:
|
|||
def coherence_residual(F: np.ndarray) -> float:
|
||||
"""Public one-shot residual for tests and harnesses.
|
||||
|
||||
R = || F · reverse(F) − 1 ||_F (dual-checked against reverse(F)).
|
||||
R_GoldTether = || ψ · reverse(ψ) − 1 ||_F (dual-checked against reverse(ψ)).
|
||||
|
||||
``||·||_F`` is |⟨ψ~ψ⟩₀ − 1| plus the Euclidean norm of non-scalar grades
|
||||
(via :func:`algebra.versor.versor_unit_residual`).
|
||||
|
||||
Canonical path (ADR-0241 Slice 2): :meth:`WaveManifold.measure_unitary_residual`
|
||||
— unitary wave amplitude drift, not a parallel residual implementation.
|
||||
No flat ``np.dot`` products; no external I₅ matrix parameters.
|
||||
"""
|
||||
return WaveManifold().measure_unitary_residual(_as_mv(F))
|
||||
|
||||
|
||||
def require_unitary(
|
||||
F: np.ndarray,
|
||||
*,
|
||||
epsilon: float = 1e-6,
|
||||
detail: str = "",
|
||||
) -> float:
|
||||
"""Return residual if ``R ≤ epsilon``; else raise :class:`GoldTetherViolationError`.
|
||||
|
||||
Synchronous fail-closed gate for state transitions.
|
||||
"""
|
||||
r = float(coherence_residual(F))
|
||||
if r > float(epsilon):
|
||||
raise GoldTetherViolationError(r, float(epsilon), detail=detail)
|
||||
return r
|
||||
|
||||
|
||||
@dataclass
|
||||
class GoldTetherMonitor:
|
||||
"""
|
||||
|
|
@ -169,6 +203,10 @@ class GoldTetherMonitor:
|
|||
"""Compute the primary GoldTether residual. Always ≥ 0. Dual-corrected."""
|
||||
return coherence_residual(F)
|
||||
|
||||
def require_unitary(self, F: np.ndarray, *, detail: str = "") -> float:
|
||||
"""Fail-closed residual gate for this monitor's ``epsilon_drift``."""
|
||||
return require_unitary(F, epsilon=float(self.epsilon_drift), detail=detail)
|
||||
|
||||
def update(
|
||||
self,
|
||||
F: np.ndarray,
|
||||
|
|
@ -177,20 +215,31 @@ class GoldTetherMonitor:
|
|||
"""
|
||||
Update monitor with new field state.
|
||||
Returns (residual, new_autonomy).
|
||||
Dual-correction: residual is checked both ways inside residual().
|
||||
|
||||
If residual exceeds ``epsilon_drift``, autonomy is forced to zero, the
|
||||
rejection is recorded in history, and :class:`GoldTetherViolationError`
|
||||
is raised synchronously (no soft commit of elevated floor/autonomy).
|
||||
"""
|
||||
r = self.residual(F)
|
||||
|
||||
if r > self.epsilon_drift:
|
||||
# Fail-closed: force autonomy to zero
|
||||
# Fail-closed: force autonomy to zero, record, then reject.
|
||||
self.autonomy = 0.0
|
||||
self.floor = max(0.0, self.floor - self.floor_decay)
|
||||
else:
|
||||
if epistemic_elevation:
|
||||
# Only proven elevation may raise the floor
|
||||
self.floor = min(1.0, self.floor + self.floor_step)
|
||||
# Autonomy may never exceed the floor
|
||||
self.autonomy = min(self.autonomy + self.autonomy_step, self.floor)
|
||||
self.history.append((float(r), float(self.floor), float(self.autonomy)))
|
||||
if len(self.history) > self.max_history:
|
||||
self.history.pop(0)
|
||||
raise GoldTetherViolationError(
|
||||
float(r),
|
||||
float(self.epsilon_drift),
|
||||
detail="GoldTetherMonitor.update rejected drifted field",
|
||||
)
|
||||
|
||||
if epistemic_elevation:
|
||||
# Only proven elevation may raise the floor
|
||||
self.floor = min(1.0, self.floor + self.floor_step)
|
||||
# Autonomy may never exceed the floor
|
||||
self.autonomy = min(self.autonomy + self.autonomy_step, self.floor)
|
||||
|
||||
self.history.append((float(r), float(self.floor), float(self.autonomy)))
|
||||
if len(self.history) > self.max_history:
|
||||
|
|
@ -343,11 +392,16 @@ class GoldTetherMonitor:
|
|||
cond = float(versor_condition(F_arr))
|
||||
# Closure residual only (geo distance to 𝓘_gold is expected for new axes).
|
||||
drift = float(coherence_residual(F_arr))
|
||||
if cond >= _CLOSURE_TOL or drift > float(self.epsilon_drift):
|
||||
if cond >= _CLOSURE_TOL:
|
||||
raise ValueError(
|
||||
"promote_gold_invariant refused: not a closed versor "
|
||||
f"(versor_condition={cond:.3e}) or residual/drift {drift:.3e} "
|
||||
f"exceeds epsilon_drift={float(self.epsilon_drift)}"
|
||||
f"(versor_condition={cond:.3e})"
|
||||
)
|
||||
if drift > float(self.epsilon_drift):
|
||||
raise GoldTetherViolationError(
|
||||
drift,
|
||||
float(self.epsilon_drift),
|
||||
detail="promote_gold_invariant refused high residual",
|
||||
)
|
||||
self.gold_invariants.append(F_arr.copy())
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,20 @@
|
|||
"""core.physics.identity — Identity as geometric structure, not prompt veneer.
|
||||
|
||||
ADR-0010: The IdentityManifold is a fixed geometric subspace of the
|
||||
versor field encoding CORE's stable character as an architectural
|
||||
constant. Every ReasoningTrajectory is checked against the manifold
|
||||
before articulation. Identity is inalienable — it cannot be overridden
|
||||
by context length, adversarial prompting, or instruction injection.
|
||||
ADR-0010 / ADR-0244: The IdentityManifold is a fixed geometric subspace of
|
||||
the Cl(4,1) versor field. Trajectory alignment uses metric-exact Gram
|
||||
projection (``identity_manifold``) on an explicit wave-field ``ψ_traj``.
|
||||
|
||||
Missing wave state raises :class:`MissingWaveStateError`. There is no
|
||||
scalar-L2 fallback. Live refusal remains flag-gated via
|
||||
``RuntimeConfig.identity_wave_gate``; scoring is always geometric.
|
||||
|
||||
Theological grounding: John 1:1-2.
|
||||
The Word is not a description of God. It is God, expressed.
|
||||
CORE's identity is not a description of CORE. It is CORE, expressed geometrically.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
import functools
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
import warnings
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Dict, FrozenSet, List, Optional, Tuple
|
||||
|
|
@ -52,10 +51,9 @@ from core.physics.identity_action import (
|
|||
# signal, NOT real benign traffic — live ``final_state.F`` versors do not preserve
|
||||
# span(e1,e2,e3) (the shipped axes are nominal basis vectors, not dynamically
|
||||
# preserved eigenmodes), so benign leakage overlaps the attack range and the
|
||||
# calibration certifies ``flag_flip_authorized=False``. The wave gate therefore
|
||||
# stays flag-gated OFF in the runtime (``identity_wave_gate=False``); this bound
|
||||
# governs only the off-serve research/eval path until identity is made
|
||||
# dynamically load-bearing (ADR-0246 induced action).
|
||||
# calibration certifies ``flag_flip_authorized=False``. Scoring is always the
|
||||
# metric-exact wave path; live *refusal* remains flag-gated via
|
||||
# ``identity_wave_gate`` until identity is dynamically load-bearing (ADR-0246).
|
||||
_WAVE_LEAKAGE_BOUND: float = 0.2126624458513829
|
||||
# The orientation floor flags a value axis the versor has rotated *past
|
||||
# orthogonal* (toward inversion). It is a geometric invariant (a preserved axis
|
||||
|
|
@ -76,6 +74,15 @@ class IdentityGateRefusal(Exception):
|
|||
"""
|
||||
|
||||
|
||||
class MissingWaveStateError(ValueError):
|
||||
"""Fail-closed when IdentityCheck receives no trajectory wave-packet.
|
||||
|
||||
Convergence blueprint (ADR-0244 Gram path): identity alignment is defined
|
||||
only for an explicit Cl(4,1) wave-field ``ψ_traj``. An absent field is not
|
||||
a soft advisory case and must never fall back to scalar heuristics.
|
||||
"""
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=32)
|
||||
def _geometry_for_axis_directions(
|
||||
directions: Tuple[Tuple[float, ...], ...]
|
||||
|
|
@ -211,28 +218,24 @@ class IdentityScore:
|
|||
flagged: bool # True if any axis projection fell below alignment threshold
|
||||
deviation_axes: FrozenSet[str] # ValueAxis IDs where deviation was detected
|
||||
trajectory_id: str
|
||||
# ADR-0244 §2.2 / §4a — operator-preservation wave-field measures. Populated
|
||||
# only on the wave path (``wave_mode_active=True``); legacy defaults preserve
|
||||
# the pre-ADR-0244 IdentityScore shape and all downstream serialization
|
||||
# (the telemetry serializer emits these keys only when the wave path ran).
|
||||
wave_mode_active: bool = False
|
||||
# ADR-0244 §2.2 / §4a — operator-preservation wave-field measures.
|
||||
# Always True after geometric convergence (wave path is the only path).
|
||||
wave_mode_active: bool = True
|
||||
# RMS subspace-leakage over the value axes (0.0 = every axis preserved).
|
||||
leakage_norm: float = 0.0
|
||||
# Minimum signed self-alignment ⟨aᵢ, F aᵢ F̃⟩₀ across axes (+1 preserved,
|
||||
# −1 inverted); 1.0 in legacy mode.
|
||||
# −1 inverted).
|
||||
min_self_alignment: float = 1.0
|
||||
# Committed boundary_ids the turn violated (intersection with the manifold's
|
||||
# boundary set); a non-empty set is a hard identity-boundary breach.
|
||||
boundary_violations: FrozenSet[str] = frozenset()
|
||||
# ADR-0246 §3.7 induced-action admit-surface measures. Populated only when the
|
||||
# ``identity_action_surface`` policy runs (``action_surface_active=True``);
|
||||
# legacy defaults keep the flag-off wave/legacy IdentityScore byte-identical.
|
||||
# ``identity_action_surface`` policy runs (``action_surface_active=True``).
|
||||
action_surface_active: bool = False
|
||||
d_orth: float = 0.0
|
||||
d_stab: float = 0.0
|
||||
# ADR-0246 §4.1 — the full per-turn IdentityActionRecord (typed residual
|
||||
# channels, digests, admit verdict). ``None`` unless the §3.7 surface ran
|
||||
# (``action_surface_active=True``); legacy/flag-off callers are unaffected.
|
||||
# channels, digests, admit verdict). ``None`` unless the §3.7 surface ran.
|
||||
action_record: "IdentityActionRecord | None" = None
|
||||
|
||||
@property
|
||||
|
|
@ -336,38 +339,13 @@ class IdentityCheck:
|
|||
def _clamp01(value: float) -> float:
|
||||
return max(0.0, min(1.0, float(value)))
|
||||
|
||||
@staticmethod
|
||||
def _mean_frame_coherence(trajectory) -> float:
|
||||
frames = getattr(trajectory, "frames", None)
|
||||
if not frames:
|
||||
return 0.0
|
||||
return sum(
|
||||
float(getattr(frame, "coherence_magnitude", 0.0)) for frame in frames
|
||||
) / len(frames)
|
||||
|
||||
@staticmethod
|
||||
def _axis_projection(axis, trajectory, scalar_score: float) -> float:
|
||||
"""Deterministically project trajectory evidence onto one value axis."""
|
||||
direction = tuple(float(x) for x in getattr(axis, "direction", ()) or ())
|
||||
if not direction:
|
||||
return scalar_score
|
||||
full_l2 = math.sqrt(sum(x * x for x in direction)) or 1.0
|
||||
head_l2 = math.sqrt(sum(x * x for x in direction[:3]))
|
||||
directional_weight = head_l2 / full_l2
|
||||
frame_coherence = IdentityCheck._mean_frame_coherence(trajectory)
|
||||
coherence_term = IdentityCheck._clamp01(0.5 + (frame_coherence / 2.0))
|
||||
return IdentityCheck._clamp01(
|
||||
(0.75 * scalar_score) + (0.25 * directional_weight * coherence_term)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _validate_wave_field(wave_field) -> np.ndarray:
|
||||
"""Coerce + fail-closed-validate the live versor (ADR-0244 §4a).
|
||||
|
||||
A malformed wave field (wrong shape, non-finite, wrong byte-order) is a
|
||||
typed ``ValueError`` — it never silently falls back to the legacy
|
||||
scalar-L2 path. The dual-mode fallback (see :meth:`check`) is for an
|
||||
ABSENT wave field only, not a malformed one.
|
||||
typed ``ValueError``. An *absent* wave field is
|
||||
:class:`MissingWaveStateError` at :meth:`check` (never a scalar fallback).
|
||||
"""
|
||||
F = np.ascontiguousarray(wave_field, dtype=np.float32)
|
||||
if F.dtype.byteorder not in ("<", "="):
|
||||
|
|
@ -493,25 +471,27 @@ class IdentityCheck:
|
|||
) -> IdentityScore:
|
||||
"""Check a trajectory against the IdentityManifold (ADR-0010 / ADR-0244).
|
||||
|
||||
Dual-mode (ADR-0244 §3): when a ``wave_field`` (the live versor
|
||||
``final_state.F``) is supplied, run the metric-exact operator-preservation
|
||||
gate; otherwise fall back to the legacy scalar-L2 heuristic. A *malformed*
|
||||
wave field raises (fail-closed) — only an ABSENT one falls back.
|
||||
Metric-exact operator-preservation only (Gram geometry in
|
||||
:mod:`core.physics.identity_manifold`). Requires an explicit Cl(4,1)
|
||||
``wave_field`` (``ψ_traj``); absence raises
|
||||
:class:`MissingWaveStateError`. Malformed fields raise ``ValueError``.
|
||||
|
||||
``admission_policy`` (ADR-0246 §3.7, flag-gated behind
|
||||
``identity_action_surface``) is forwarded to the wave path only; ``None``
|
||||
(default) keeps every caller byte-identical to the D4 gate. ``turn_id``/
|
||||
``pack_id`` (ADR-0246 §4.1) are cosmetic identifiers for the per-turn
|
||||
record and default to ``0``/``""`` — omitting them changes nothing.
|
||||
``admission_policy`` (ADR-0246 §3.7) is optional; ``None`` keeps the
|
||||
D4 wave gate without the induced-action surface. ``turn_id`` / ``pack_id``
|
||||
are cosmetic identifiers for the per-turn action record.
|
||||
|
||||
``violated_boundary_ids`` (the turn's safety/ethics violated boundaries)
|
||||
is intersected with the manifold's committed ``boundary_ids``; a non-empty
|
||||
intersection is a hard identity-boundary breach (governance annotation
|
||||
item 7). Defaults empty so pre-ADR-0244 callers are byte-identical.
|
||||
``violated_boundary_ids`` is intersected with the manifold's committed
|
||||
``boundary_ids``; a non-empty intersection is a hard identity-boundary
|
||||
breach.
|
||||
"""
|
||||
resolved_manifold = manifold or self._manifold
|
||||
if resolved_manifold is None:
|
||||
raise TypeError("IdentityCheck.check() requires an IdentityManifold")
|
||||
if wave_field is None:
|
||||
raise MissingWaveStateError(
|
||||
"IdentityCheck requires an explicit Cl(4,1) wave_field "
|
||||
"(ψ_traj); scalar-L2 fallback is excised"
|
||||
)
|
||||
trajectory_id = str(getattr(trajectory, "trajectory_id", "legacy_trajectory"))
|
||||
boundary_violations = (
|
||||
frozenset(violated_boundary_ids) & resolved_manifold.boundary_ids
|
||||
|
|
@ -522,27 +502,17 @@ class IdentityCheck:
|
|||
flagged=bool(boundary_violations),
|
||||
deviation_axes=frozenset(),
|
||||
trajectory_id=trajectory_id,
|
||||
wave_mode_active=True,
|
||||
boundary_violations=boundary_violations,
|
||||
)
|
||||
if wave_field is not None:
|
||||
return self._wave_field_score(
|
||||
wave_field, resolved_manifold, trajectory_id, boundary_violations,
|
||||
admission_policy=admission_policy, turn_id=turn_id, pack_id=pack_id,
|
||||
)
|
||||
confidence = float(getattr(trajectory, "total_coherence_delta", 0.0))
|
||||
confidence += self._mean_frame_coherence(trajectory)
|
||||
score = self._clamp01(0.5 + (confidence / 2.0))
|
||||
deviations = frozenset(
|
||||
str(getattr(axis, "axis_id", getattr(axis, "name", "axis")))
|
||||
for axis in resolved_manifold.value_axes
|
||||
if self._axis_projection(axis, trajectory, score) < resolved_manifold.alignment_threshold
|
||||
)
|
||||
return IdentityScore(
|
||||
score=score,
|
||||
flagged=bool(deviations) or bool(boundary_violations),
|
||||
deviation_axes=deviations,
|
||||
trajectory_id=trajectory_id,
|
||||
boundary_violations=boundary_violations,
|
||||
return self._wave_field_score(
|
||||
wave_field,
|
||||
resolved_manifold,
|
||||
trajectory_id,
|
||||
boundary_violations,
|
||||
admission_policy=admission_policy,
|
||||
turn_id=turn_id,
|
||||
pack_id=pack_id,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ is unset. Helpers without a Rust path (``reverse``, ``scalar_part``,
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
from typing import Any, Sequence, Tuple
|
||||
|
||||
import numpy as np
|
||||
|
|
@ -40,6 +41,22 @@ _NEAR_ZERO = 1e-12
|
|||
_NONSIMPLE_TOL = 1e-6
|
||||
|
||||
|
||||
def multivector_content_digest(psi: np.ndarray) -> str:
|
||||
"""Full 64-char SHA-256 of little-endian float64 multivector components.
|
||||
|
||||
Canonical content address for Cl(4,1) wave state (Reconstruction-over-Storage).
|
||||
"""
|
||||
arr = np.ascontiguousarray(np.asarray(psi, dtype=np.float64))
|
||||
if arr.shape != (N_COMPONENTS,):
|
||||
raise ValueError(
|
||||
f"content digest requires shape ({N_COMPONENTS},); got {arr.shape}"
|
||||
)
|
||||
if not np.all(np.isfinite(arr)):
|
||||
raise ValueError("content digest requires finite multivector components")
|
||||
le = arr.astype(np.dtype("<f8"), copy=False)
|
||||
return hashlib.sha256(le.tobytes()).hexdigest()
|
||||
|
||||
|
||||
class WaveSpectralLeakageError(ValueError):
|
||||
"""Fail-closed spectral leakage (metric-degenerate resonant span).
|
||||
|
||||
|
|
@ -193,13 +210,22 @@ class WaveManifold:
|
|||
Construction-closed rotors; dual-checked unitary residual; deterministic.
|
||||
Optional standing-wave mode registry for resonant recall (ADR-0241 §2.2);
|
||||
not a vault/store — reconstruction-over-storage, off-serving.
|
||||
|
||||
Stored modes are content-addressed by SHA-256 over little-endian float64
|
||||
multivector bytes (:func:`multivector_content_digest`).
|
||||
"""
|
||||
|
||||
def __init__(self, epsilon_drift: float = 1e-6) -> None:
|
||||
self.epsilon_drift = float(epsilon_drift)
|
||||
self.n_dims = N_COMPONENTS
|
||||
# Standing-wave eigenmode registry (session-local; not durable memory).
|
||||
self._resonant_modes: list[np.ndarray] = []
|
||||
# Each entry is (digest, psi) so storage is content-addressed.
|
||||
self._resonant_modes: list[tuple[str, np.ndarray]] = []
|
||||
|
||||
@staticmethod
|
||||
def content_digest(psi: np.ndarray) -> str:
|
||||
"""SHA-256 hex digest of a Cl(4,1) multivector (little-endian f64)."""
|
||||
return multivector_content_digest(psi)
|
||||
|
||||
# --- Transport -----------------------------------------------------------
|
||||
|
||||
|
|
@ -300,9 +326,13 @@ class WaveManifold:
|
|||
# --- Standing-wave registry / resonant recall (ADR-0241 §2.2) ------------
|
||||
|
||||
def register_resonant_mode(self, psi_k: np.ndarray) -> int:
|
||||
"""Register a standing-wave mode. Returns mode index. Session-local only."""
|
||||
"""Register a standing-wave mode. Returns mode index. Session-local only.
|
||||
|
||||
Content-addressed by SHA-256 of little-endian float64 components.
|
||||
"""
|
||||
mode = _as_mv(psi_k, "ψ_k").copy()
|
||||
self._resonant_modes.append(mode)
|
||||
digest = multivector_content_digest(mode)
|
||||
self._resonant_modes.append((digest, mode))
|
||||
return len(self._resonant_modes) - 1
|
||||
|
||||
def clear_resonant_modes(self) -> None:
|
||||
|
|
@ -311,7 +341,12 @@ class WaveManifold:
|
|||
|
||||
@property
|
||||
def resonant_modes(self) -> tuple[np.ndarray, ...]:
|
||||
return tuple(m.copy() for m in self._resonant_modes)
|
||||
return tuple(m.copy() for _d, m in self._resonant_modes)
|
||||
|
||||
@property
|
||||
def resonant_mode_digests(self) -> tuple[str, ...]:
|
||||
"""SHA-256 digests parallel to :attr:`resonant_modes`."""
|
||||
return tuple(d for d, _m in self._resonant_modes)
|
||||
|
||||
def resonant_recall(
|
||||
self,
|
||||
|
|
@ -406,7 +441,7 @@ class WaveManifold:
|
|||
modes: Sequence[np.ndarray] | None,
|
||||
) -> list[np.ndarray]:
|
||||
if modes is None:
|
||||
return list(self._resonant_modes)
|
||||
return [m.copy() for _d, m in self._resonant_modes]
|
||||
return [_as_mv(m, f"mode[{i}]") for i, m in enumerate(modes)]
|
||||
|
||||
# --- Chiral spinor charge ------------------------------------------------
|
||||
|
|
@ -433,4 +468,4 @@ class WaveManifold:
|
|||
)
|
||||
|
||||
|
||||
__all__ = ["WaveManifold", "WaveSpectralLeakageError"]
|
||||
__all__ = ["WaveManifold", "WaveSpectralLeakageError", "multivector_content_digest"]
|
||||
|
|
|
|||
|
|
@ -205,22 +205,32 @@ class CognitiveLifecycleEngine:
|
|||
|
||||
psi \= ingress.psi.copy()
|
||||
|
||||
\# Schrödinger propagator: R \= exp(H\_problem \* I \* dt)
|
||||
\# IMPLEMENTED (not this sketch): imaginary-time power iteration in
|
||||
|
||||
generator \= np.dot(H\_problem, self.I)
|
||||
\# core/physics/cognitive_lifecycle.relax_to_ground — geometric_product
|
||||
|
||||
\# path only. The np.dot / la.expm sketch below is HISTORICAL and
|
||||
|
||||
\# superseded (pin SD-B; convergence 2026-07-20).
|
||||
|
||||
\#
|
||||
|
||||
\# Schrödinger-style discrete step (wave_manifold): R = exp(B·Δt) via
|
||||
|
||||
\# closed-form / series bivector exp; sandwich ψ' = R ψ ~R.
|
||||
|
||||
generator \= np.dot(H\_problem, self.I) \# SUPERSEDED — do not implement
|
||||
|
||||
R \= la.expm(generator \* dt)
|
||||
|
||||
|
||||
|
||||
\# Relaxation loop (Euler/exponential integrator)
|
||||
\# Relaxation loop (Euler/exponential integrator) — SUPERSEDED
|
||||
|
||||
for \_ in range(relaxation\_steps):
|
||||
|
||||
psi \= np.dot(R, psi)
|
||||
|
||||
\# Enforce the null-cone amplitude normalization step
|
||||
|
||||
norm \= np.linalg.norm(psi)
|
||||
|
||||
if norm \> 1e-12:
|
||||
|
|
@ -239,13 +249,17 @@ class CognitiveLifecycleEngine:
|
|||
|
||||
wave-states from entering the readback and serving paths.
|
||||
|
||||
IMPLEMENTED residual: WaveManifold.measure_unitary_residual /
|
||||
|
||||
goldtether.coherence_residual (ψ · rev(ψ) via geometric_product).
|
||||
|
||||
The np.dot sketch below is SUPERSEDED (convergence 2026-07-20).
|
||||
|
||||
"""
|
||||
|
||||
psi\_arr \= np.asarray(psi\_steady, dtype=np.float64)
|
||||
|
||||
\# Unitary residual check: || psi \* rev(psi) \- 1 ||\_F
|
||||
|
||||
\# rev(psi) proxied via conjugate transpose under I-metric
|
||||
\# SUPERSEDED flat residual — use geometric_product path in code:
|
||||
|
||||
psi\_rev \= np.dot(self.I.T, psi\_arr)
|
||||
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ This ADR resolves these issues by completely reconstructing the Identity Manifol
|
|||
|
||||
We completely solidify CORE's identity layer by establishing that **identity is an inalienable geometric property of the wave-field itself, defended via metric-exact spectral projection and topological charge conservation**.
|
||||
|
||||
We implement this transition through a **dual-mode architecture** in `core/physics/identity.py`, maintaining 100% backwards compatibility with legacy heuristic fixtures while enabling optimal wave-field geometry when wave-packets are present.
|
||||
We implement this transition through a **wave-only geometry path** in `core/physics/identity.py`. Scalar-L2 dual-mode fallback has been **excised** (system convergence 2026-07-20): missing `ψ_traj` raises `MissingWaveStateError`; scoring always uses metric-exact Gram / operator-preservation geometry.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -177,35 +177,19 @@ We implement a **Fibonacci-Word Background Scheduler** strictly isolated from th
|
|||
|
||||
---
|
||||
|
||||
## 3\. Backwards Compatibility & Dual-Mode Fallback
|
||||
## 3\. Fail-Closed Wave Requirement (Dual-Mode Excised)
|
||||
|
||||
To prevent any regression across existing test suites and fixtures, `IdentityCheck().check(trajectory)` operates in a **graceful dual-mode configuration**:
|
||||
**Supersedes the former dual-mode / scalar-L2 fallback.** Convergence (2026-07-20) removed `_axis_projection`, `_mean_frame_coherence`, and the blend `(0.75 * score) + (0.25 * directional_weight * coherence_term)` entirely.
|
||||
|
||||
def check(self, trajectory, manifold: IdentityManifold | None \= None) \-\> IdentityScore:
|
||||
`IdentityCheck().check(trajectory, manifold, *, wave_field=...)` now requires an explicit Cl(4,1) `wave_field` (`ψ_traj`). Absence raises typed `MissingWaveStateError`. Malformed fields raise `ValueError`. Live *refusal* remains flag-gated via `RuntimeConfig.identity_wave_gate`; **scoring is always geometric**.
|
||||
|
||||
\# 1\. Check if the trajectory contains a wave-field representation (ADR-0244)
|
||||
|
||||
psi\_traj \= getattr(trajectory, "psi\_traj", None)
|
||||
|
||||
if psi\_traj is not None:
|
||||
|
||||
\# Execute metric-exact wave-field spectral projection
|
||||
|
||||
...
|
||||
|
||||
else:
|
||||
|
||||
\# Fall back gracefully to legacy scalar-L2 heuristics (ADR-0010)
|
||||
|
||||
...
|
||||
|
||||
This ensures that legacy evaluation suites (such as `evals/adversarial_identity` and `evals/teaching_injection_resistance`) run without modification, while wave-capable serving paths automatically leverage the high-assurance geometric projection.
|
||||
Callers (e.g. `chat/runtime.py`) always pass `final_state.F`. Evaluation suites that previously relied on L2 must supply a wave field.
|
||||
|
||||
---
|
||||
|
||||
## 4\. Implementation Specification
|
||||
|
||||
The conformed implementation in `core/physics/identity.py` combines both legacy and upgraded paths:
|
||||
The conformed implementation in `core/physics/identity.py` is wave-only (Gram / operator-preservation via `identity_manifold.py`):
|
||||
|
||||
\# core/physics/identity.py
|
||||
|
||||
|
|
@ -515,13 +499,16 @@ def axis_response(R, axes_psi, g_inv):
|
|||
return leak, align
|
||||
```
|
||||
|
||||
**Phase 2 gate — `core/physics/identity.py` (§2.2; dual-mode, fail-closed):**
|
||||
**Phase 2 gate — `core/physics/identity.py` (§2.2; wave-only, fail-closed):**
|
||||
|
||||
```python
|
||||
class IdentityGateRefusal(Exception):
|
||||
"""Fail-closed refusal: leakage/orientation or boundary check failed and
|
||||
C_id could not recover alignment within its bound. Params unchanged."""
|
||||
|
||||
class MissingWaveStateError(ValueError):
|
||||
"""Raised when wave_field / ψ_traj is absent (scalar-L2 path excised)."""
|
||||
|
||||
def _wave_field_check(F_traj, axes_psi, g_inv) -> tuple[float, list, list]:
|
||||
F = np.ascontiguousarray(F_traj, dtype=np.float32)
|
||||
if F.dtype.byteorder not in ("<", "="):
|
||||
|
|
@ -531,14 +518,11 @@ def _wave_field_check(F_traj, axes_psi, g_inv) -> tuple[float, list, list]:
|
|||
if F.shape != (N_COMPONENTS,):
|
||||
raise ValueError(f"F_traj must be shape ({N_COMPONENTS},), got {F.shape}")
|
||||
leak, align = axis_response(F.astype(np.float64), axes_psi, g_inv)
|
||||
# subspace-preservation score (RMS leakage over axes; each rotated axis is
|
||||
# unit-norm, so the denominator is sqrt(n)); orientation carried separately.
|
||||
score = 1.0 - (sum(l * l for l in leak) / len(leak)) ** 0.5
|
||||
return score, leak, align
|
||||
|
||||
# Malformed F_traj (NaN / wrong shape / wrong byte-order) raises — it never
|
||||
# falls through to the legacy scalar-L2 path (Sec 3's dual-mode fallback is
|
||||
# for ABSENT F_traj only, not malformed F_traj).
|
||||
# Absent F_traj → MissingWaveStateError. Malformed F_traj → ValueError.
|
||||
# No scalar-L2 fallback remains (convergence 2026-07-20).
|
||||
```
|
||||
|
||||
Egress condition (replaces §2.2 item 2's formula — `∧ ΔQ_top = 0` dropped per governance annotation item 1; operator-preservation per item 12):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,327 @@
|
|||
# ADR-0243: Wave-Field Cognitive Lifecycle — Comprehension, Resonant Reasoning, and Lifelong Learning
|
||||
|
||||
**Status**: Proposed (acceptance path: benchmark evidence \+ Joshua review)
|
||||
**Date**: 2026-07-14
|
||||
**Deciders**: Joshua Shay \+ multi-model R\&D
|
||||
**Traceability**: Notion R\&D (Engineering Reference Vault Interconnection: `core_HA` Patterns)
|
||||
**Related**: ADR-0003, ADR-0006, ADR-0238, ADR-0239, ADR-0240, ADR-0241, ADR-0242, `core/physics/wave_manifold.py`
|
||||
**Canonical path**: `docs/adr/`
|
||||
|
||||
---
|
||||
|
||||
## 1\. Context and Problem Statement
|
||||
|
||||
With the successful unification of the **$Cl(4,1)$ Conformal Wave-Field ($\\psi$)** substrate ([ADR-0241](https://drive.google.com/file/d/1F_7QYtPysBP4qMbLGlGPnXgYx9IXug8nUYrpiCGSunE/view?usp=drivesdk)) and the implementation of the **Deterministic Fibonacci search** ([ADR-0242](https://drive.google.com/file/d/15_NECCPy-tEWGfYi_BNqawm8GytUTMkz1DsOqGVMXhI/view?usp=drivesdk)), CORE's physical layer has reached structural maturity.
|
||||
|
||||
However, we must now define how these new physical and geometric evolutions are leveraged to solve the fundamental cognitive tasks where traditional architectures struggle:
|
||||
|
||||
- **Comprehension & Ingress**: Traditional architectures parse and embed inputs into flat, context-dry vectors, leading to representation drift, attention decay over long contexts, and loss of structural relations.
|
||||
- **Problem Solving & Reasoning**: Traditional systems treat reasoning as probabilistic path-search or auto-regressive step generation. This lacks mathematical guarantees of correctness and suffers from cumulative error propagation.
|
||||
- **Egress & Generation**: Probabilistic autoregressive decoding selects discrete tokens one-by-one via softmax sampling, which has no global coherence guarantees, leading to hallucinations and semantic drift.
|
||||
- **Contemplation & Learning**: Standard models require gradient-descent backpropagation to update static weights, which is computationally expensive, non-reconstructible, and prone to catastrophic forgetting.
|
||||
|
||||
This ADR defines the complete **Wave-Field Cognitive Lifecycle**, leveraging the wave function to establish a fully deterministic, closed-loop, physical-relaxation-based paradigm for comprehension, reasoning, generation, and learning.
|
||||
|
||||
---
|
||||
|
||||
## 2\. Decision and Architectural Formulation
|
||||
|
||||
We dissolve the probabilistic, token-by-token paradigm of classical AI. We establish that **cognition is the continuous physical evolution, resonance, and relaxation of a Conformal Wave-Field ($\\psi$) across a single $Cl(4,1)$ geometric substrate**.
|
||||
|
||||
\[INGRESS\] \[REASONING\] \[EGRESS\]
|
||||
|
||||
Continuous Modalities Hamiltonian Well (H\_p) Thermodynamic State
|
||||
|
||||
| | |
|
||||
|
||||
v (Superposition) v (Physical Relaxation) v (Energy Class check)
|
||||
|
||||
Ingress Wave (psi\_in) \=======\> Steady State (psi\_final) \=======\> Linguistic Readback
|
||||
|
||||
^ ^ |
|
||||
|
||||
| (Resonant recall) | (Unitary update) v (GoldTether Gate)
|
||||
|
||||
Standing-Wave Atlas \<===================+===========================\> safe, aligned output
|
||||
|
||||
|
|
||||
|
||||
v (Verified holonomy R)
|
||||
|
||||
Biography update (R\_bio)
|
||||
|
||||
---
|
||||
|
||||
### 2.1 Ingress and Reading Comprehension: Wave Ingestion and Holomorphic Dispersion
|
||||
|
||||
Reading comprehension is modeled as **Wave-Packet Ingestion and Holomorphic Dispersion**, replacing flat token embeddings.
|
||||
|
||||
1. **Ingress Wave Packet**: An incoming text block, symbolic formula, or multimodal sensory stream is compiled into a localized, coherent wave packet $\\psi\_{ ext{context}}(X)$. This compilation preserves spatial-temporal phase relationships: $$\\psi\_{ ext{context}}(X) \= \\sum\_i c\_i \\psi\_{ ext{token}\_i}(X)$$
|
||||
2. **Holomorphic Dispersion**: As $\\psi\_{ ext{context}}$ is injected, it propagates through the `VocabManifold`. Proximity and meaning are not calculated via nearest-neighbor vector scans. Instead, the wave disperses and performs parallel cross-correlation with the registered standing-wave modes ${\\psi\_k}$ of the Hyperbolic Atlas, generating a spectrum of resonant coefficients: $$R\_k \= \\int\_M \\langle \\psi\_{ ext{context}}(X) \\widetilde{\\psi}\_k(X) angle\_0 dX$$ This represents the instant, parallel projection of the input context onto the entire known semantic manifold.
|
||||
|
||||
---
|
||||
|
||||
### 2.2 Reasoning and Problem Solving: Hamiltonian Well Relaxation
|
||||
|
||||
Problem-solving is re-engineered as a **Physical Wave-Field Relaxation Process**, replacing probabilistic step-by-step tree search.
|
||||
|
||||
1. **The Problem Hamiltonian**: The constraints and boundary conditions of a given problem (e.g. mathematical equalities, safety rules, or logical premises) are formulated as potential energy barriers or wells in a problem-specific Hamiltonian operator $\\mathcal{H}\_{ ext{problem}}$.
|
||||
2. **Relaxation to Eigenstates**: The ingress wave field $\\psi\_{ ext{context}}(X)$ is set as the initial state $\\psi(X, 0)$. The system is allowed to evolve under the Algebraic Schrödinger Equation: $$\\partial\_t \\psi \= \\mathcal{H}*{ ext{problem}}(\\psi) I$$ Through this evolution, the wave field naturally disperses away from high-potential barriers (representing logical contradictions or safety violations) and settles (relaxes) into the lowest-energy, stable standing-wave eigenmodes of the problem manifold: $$\\psi*{ ext{steady}}(X) \= \\lim\_{t o \\infty} \\exp\\left( \\mathcal{H}*{ ext{problem}} I t ight) \\psi*{ ext{context}}(X)$$ The resulting steady-state wave $\\psi\_{ ext{steady}}(X)$ represents the exact, geometrically congruent solution to the problem. It is mathematically guaranteed to satisfy all boundary conditions with zero room for intermediate fabrication.
|
||||
|
||||
---
|
||||
|
||||
### 2.3 Egress and Generative Articulation: Thermodynamic Wave Readback
|
||||
|
||||
We replace probabilistic softmax token generation with **Thermodynamic Wave Readback**, providing ironclad coherence guarantees.
|
||||
|
||||
1. **Thermodynamic Energy Classes**: The Field Energy Operator ($H$, defined in [ADR-0006](https://core-gitquarters.acbcontent.org/core-labs/core/src/branch/main/docs/adr/ADR-0006-field-energy-operator.md)) evaluates the "energy class" (E0 to E4) of the relaxed wave-field $\\psi\_{ ext{steady}}(X)$.
|
||||
- **E0/E1 (Crystalline/Stable)**: Represents cold, settled knowledge. It is bypassed for generation and vaulted into the sharded Delta-CRDT registers.
|
||||
- **E3/E4 (Hot/Critical)**: Indicates a high-activation, settled state that carries maximum semantic charge and "wants" to be articulated.
|
||||
2. **Linguistic Readback**: For E3/E4 states, the system invokes the readback rules of the active language pack (`en/readback_rules.py`, `he/readback_rules.py`, `el/readback_rules.py`). These rules map the geometric components—the principal bivector directions and scale-invariant parameters of the wave field—directly to symbolic tokens or motor commands.
|
||||
3. **GoldTether Gate**: Before any token or continuous action is permitted to exit the boundary, the **GoldTether unit residual** is evaluated: $$R\_{ ext{GoldTether}} \= \\sup\_{X \\in M} \\left| \\psi\_{ ext{steady}}(X) \\widetilde{\\psi}\_{ ext{steady}}(X) \- 1 ight|\_F \< 10^{-6}$$ If the generated state would introduce non-unitary drift (hallucination or ungrounded statements), the gate closes instantly, blocking the output and prompting a pre-ratified, safe fallback.
|
||||
|
||||
---
|
||||
|
||||
### 2.4 Speculative Contemplation and Non-Resonant Curiosity
|
||||
|
||||
Active thinking, self-reflection, and learning are modeled as **Speculative Contemplation and Non-Resonant Curiosity**, replacing classical gradient-descent backpropagation.
|
||||
|
||||
1. **Speculative Generation**: During idle cycles, the contemplation loop (`core/contemplation/runner.py`) speculatively generates wave-packets $\\psi\_{ ext{speculative}}(X)$ representing potential hypotheses or analogical transfers.
|
||||
2. **Orthogonal Surprise Check**: The non-resonant surprise residual of the speculative wave is evaluated: $$\\mathcal{S}(\\psi) \= \\psi\_{ ext{speculative}} \- \\mathcal{P}*{ ext{resonance}}(\\psi*{ ext{speculative}})$$
|
||||
- **Low Surprise**: The hypothesis is fully explained by the existing resonant schema. It is integrated immediately with no learning required.
|
||||
- **High Surprise (Discovery Signal)**: If $E\_{ ext{surprise}} \> \\gamma$, the speculative wave contains structural novelty. This signal is held as a `DiscoveryCandidate` and routed to the offline review corridor. It does *not* alter active knowledge but directs the self-authorship loop (`core/physics/self_authorship.py`) to generate a proposal to expand the active Hamiltonian $\\mathcal{H}$, enabling structured learning without catastrophic forgetting.
|
||||
|
||||
---
|
||||
|
||||
### 2.5 Lifelong Resonant Learning: Biography Holonomy Update
|
||||
|
||||
CORE-native learning is the permanent record of the entity's lived experiences as a sequence of geometric transformations.
|
||||
|
||||
Once a sequence of reasoning and action steps is validated (via the validation harness, [ADR-0240](https://drive.google.com/file/d/1eFNoXQl5BbUo6g4GBzRXi5tyIhT5RUGZQG6afaVXTg4/view?usp=drivesdk)), the exact unitary transformation $R \\in Spin(4,1)$ undergone by the wave-field is compiled into the **Biography Holonomy Blade** (`biography.py`): $$\\mathcal{H}*{ ext{bio}} \\leftarrow \\mathcal{H}*{ ext{bio}} \\cdot R$$ This is the ultimate, non-lossy, reconstruction-over-storage compilation of experience. It represents the "wisdom" of the entity, which can be replayed and audited byte-for-byte\!
|
||||
|
||||
---
|
||||
|
||||
## 3\. Implementation Specification (The Cognitive Relaxation Loop)
|
||||
|
||||
Below is the Python prototype implementing wave-field ingestion, Hamiltonian well relaxation (problem-solving), and the GoldTether egress gate inside the active reasoning pipeline.
|
||||
|
||||
\# core/physics/cognitive\_lifecycle.py
|
||||
|
||||
from \_\_future\_\_ import annotations
|
||||
|
||||
import numpy as np
|
||||
|
||||
import scipy.linalg as la
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from typing import Callable, Tuple
|
||||
|
||||
N\_COMPONENTS \= 32
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
|
||||
class IngressWavePacket:
|
||||
|
||||
psi: np.ndarray \# 32-vector coefficients
|
||||
|
||||
domain\_id: str
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
|
||||
class EgressVerdict:
|
||||
|
||||
admitted: bool
|
||||
|
||||
wave\_out: np.ndarray
|
||||
|
||||
residual: float
|
||||
|
||||
message: str
|
||||
|
||||
class CognitiveLifecycleEngine:
|
||||
|
||||
def \_\_init\_\_(self, epsilon\_drift: float \= 1e-6):
|
||||
|
||||
self.epsilon\_drift \= epsilon\_drift
|
||||
|
||||
self.I \= np.zeros((N\_COMPONENTS, N\_COMPONENTS))
|
||||
|
||||
\# Central pseudoscalar proxy
|
||||
|
||||
for i in range(N\_COMPONENTS // 2):
|
||||
|
||||
self.I\[2\*i, 2\*i+1\] \= 1.0
|
||||
|
||||
self.I\[2\*i+1, 2\*i\] \= \-1.0
|
||||
|
||||
def ingest\_context(self, tokens: list\[np.ndarray\], domain\_id: str) \-\> IngressWavePacket:
|
||||
|
||||
"""
|
||||
|
||||
Compiles discrete symbolic token wave-packets into a superposed,
|
||||
|
||||
coherent IngressWavePacket.
|
||||
|
||||
"""
|
||||
|
||||
psi\_sum \= np.zeros(N\_COMPONENTS, dtype=np.float64)
|
||||
|
||||
for t in tokens:
|
||||
|
||||
arr \= np.asarray(t, dtype=np.float64)
|
||||
|
||||
psi\_sum \+= arr
|
||||
|
||||
\# Normalize to preserve unitary probability amplitude
|
||||
|
||||
norm \= np.linalg.norm(psi\_sum)
|
||||
|
||||
psi\_norm \= (psi\_sum / norm) if norm \> 1e-12 else psi\_sum
|
||||
|
||||
return IngressWavePacket(psi=psi\_norm, domain\_id=domain\_id)
|
||||
|
||||
def solve\_via\_relaxation(
|
||||
|
||||
self,
|
||||
|
||||
ingress: IngressWavePacket,
|
||||
|
||||
H\_problem: np.ndarray,
|
||||
|
||||
relaxation\_steps: int \= 100,
|
||||
|
||||
dt: float \= 0.01
|
||||
|
||||
) \-\> np.ndarray:
|
||||
|
||||
"""
|
||||
|
||||
Solves a problem via continuous wave-field relaxation.
|
||||
|
||||
The wave relaxes into the minimum-energy eigenstate of H\_problem.
|
||||
|
||||
"""
|
||||
|
||||
psi \= ingress.psi.copy()
|
||||
|
||||
\# IMPLEMENTED (not this sketch): imaginary-time power iteration in
|
||||
|
||||
\# core/physics/cognitive_lifecycle.relax_to_ground — geometric_product
|
||||
|
||||
\# path only. The np.dot / la.expm sketch below is HISTORICAL and
|
||||
|
||||
\# SUPERSEDED (pin SD-B; convergence 2026-07-20). Multi-modality
|
||||
|
||||
\# ingress uses modality_transition_sandwich (R·ψ·rev(R) + GoldTether).
|
||||
|
||||
\#
|
||||
|
||||
\# Schrödinger propagator sketch (DO NOT IMPLEMENT):
|
||||
|
||||
generator \= np.dot(H\_problem, self.I) \# SUPERSEDED — do not implement
|
||||
|
||||
R \= la.expm(generator \* dt)
|
||||
|
||||
|
||||
|
||||
\# Relaxation loop (Euler/exponential integrator) — SUPERSEDED
|
||||
|
||||
for \_ in range(relaxation\_steps):
|
||||
|
||||
psi \= np.dot(R, psi)
|
||||
|
||||
\# Enforce the null-cone amplitude normalization step
|
||||
|
||||
norm \= np.linalg.norm(psi)
|
||||
|
||||
if norm \> 1e-12:
|
||||
|
||||
psi /= norm
|
||||
|
||||
|
||||
|
||||
return psi
|
||||
|
||||
def egress\_gate(self, psi\_steady: np.ndarray) \-\> EgressVerdict:
|
||||
|
||||
"""
|
||||
|
||||
Unitary GoldTether egress gate: blocks non-unitary/hallucinated
|
||||
|
||||
wave-states from entering the readback and serving paths.
|
||||
|
||||
IMPLEMENTED residual: WaveManifold.measure_unitary_residual /
|
||||
|
||||
goldtether.coherence_residual (ψ · rev(ψ) via geometric_product).
|
||||
|
||||
The np.dot sketch below is SUPERSEDED (convergence 2026-07-20).
|
||||
|
||||
"""
|
||||
|
||||
psi\_arr \= np.asarray(psi\_steady, dtype=np.float64)
|
||||
|
||||
\# SUPERSEDED flat residual — use geometric_product path in code:
|
||||
|
||||
\# rev(psi) proxied via conjugate transpose under I-metric
|
||||
|
||||
psi\_rev \= np.dot(self.I.T, psi\_arr)
|
||||
|
||||
norm\_product \= np.dot(psi\_arr.T, psi\_rev)
|
||||
|
||||
drift \= np.abs(norm\_product \- 1.0)
|
||||
|
||||
|
||||
|
||||
if drift \> self.epsilon\_drift:
|
||||
|
||||
return EgressVerdict(
|
||||
|
||||
admitted=False,
|
||||
|
||||
wave\_out=np.zeros\_like(psi\_arr),
|
||||
|
||||
residual=float(drift),
|
||||
|
||||
message="REJECTED: Unitary propagator drift exceeds epsilon\_drift limit (ungrounded state)."
|
||||
|
||||
)
|
||||
|
||||
|
||||
|
||||
return EgressVerdict(
|
||||
|
||||
admitted=True,
|
||||
|
||||
wave\_out=psi\_arr,
|
||||
|
||||
residual=float(drift),
|
||||
|
||||
message="ADMITTED: Wave-field verified and promoted to readback path."
|
||||
|
||||
)
|
||||
|
||||
---
|
||||
|
||||
## 4\. Consequences and Gating Rules
|
||||
|
||||
### 4.1 Benefits
|
||||
|
||||
- **Autoregressive Hallucination Eliminated**: By replacing step-by-step probabilistic token sampling with physical wave relaxation, output generation is strictly constrained by the geometry of the problem Hamiltonian.
|
||||
- **Zero Coordinate Loss**: Resonant standing-wave lock-in ensures that recalled memories are mathematically exact, preventing the fuzzy centroid degradation of legacy architectures.
|
||||
- **Topologically Protected Wisdom**: Experience is compiled directly into the Biography Holonomy Blade as unitary rotor products, providing an untamperable, replayable audit trail of lifelong learning.
|
||||
|
||||
### 4.2 Gating Rules
|
||||
|
||||
- **No Direct Hot-Path Promotion**: Reconstructed wave-fields or proposed Hamiltonian adjustments from the self-authorship loop (`core/physics/self_authorship.py`) must never bypass the one-mutation-path. Speculative changes must reside strictly within the `evals/` and `calibration/` quarantine zones until ratified by a signed human certificate.
|
||||
|
||||
---
|
||||
|
||||
## 5\. References
|
||||
|
||||
1. `docs/adr/ADR-0003-coordinate-system-dissolution.md` — Relational fields replacing coordinate frames.
|
||||
2. `docs/adr/ADR-0238-GoldTether-Modulated-Supervised-Autonomy.md` — GoldTether residual monitoring.
|
||||
3. `docs/adr/ADR-0239-Conformal-Procrustes-Surprise-Dual-Operator.md` — Conformal Procrustes and surprise.
|
||||
4. `docs/adr/ADR-0241-wave-field-driven-hyperbolic-atlas-and-resonant-cognition.md` — Continuous wave-field framework.
|
||||
5. `docs/adr/ADR-0242-deterministic-fibonacci-operators-and-evidence-gated-optimization.md` — Fibonacci search contract.
|
||||
|
||||
|
|
@ -109,7 +109,24 @@ def _score(check: IdentityCheck, manifold: IdentityManifold, versor: np.ndarray)
|
|||
|
||||
|
||||
def _legacy_score(check: IdentityCheck, manifold: IdentityManifold):
|
||||
return check.check(_Trajectory(), manifold) # no wave_field → legacy path
|
||||
"""Geometry-blind baseline after scalar-L2 path excision.
|
||||
|
||||
Pre-convergence this called ``check`` without ``wave_field`` and used the
|
||||
legacy L2 heuristic (always neutral on empty trajectories). That path is
|
||||
gone (:class:`MissingWaveStateError`). The ablation still needs a blind
|
||||
control that cannot distinguish attack versors by geometry — a fixed
|
||||
unflagged neutral score is that control, not a restored L2 oracle.
|
||||
"""
|
||||
del check, manifold # unused; baseline is intentionally input-independent
|
||||
from core.physics.identity import IdentityScore
|
||||
|
||||
return IdentityScore(
|
||||
score=0.5,
|
||||
flagged=False,
|
||||
deviation_axes=frozenset(),
|
||||
trajectory_id="legacy_excised_baseline",
|
||||
wave_mode_active=False,
|
||||
)
|
||||
|
||||
|
||||
def run_identity_gate_ablation() -> dict[str, Any]:
|
||||
|
|
|
|||
|
|
@ -114,6 +114,12 @@ class FieldState:
|
|||
energy: EnergyProfile | None = None
|
||||
valence: ValenceBundle | None = None
|
||||
|
||||
def content_digest(self) -> str:
|
||||
"""Full 64-char SHA-256 of little-endian f64 ``F`` components."""
|
||||
from core.physics.wave_manifold import multivector_content_digest
|
||||
|
||||
return multivector_content_digest(np.asarray(self.F, dtype=np.float64))
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
# Enforce copy + dtype + shape at the construction boundary.
|
||||
# frozen=True prevents reassignment, but ndarray contents are still
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ preserving honest refusal per ADR-0022 §2.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum, unique
|
||||
|
||||
|
|
@ -39,23 +40,51 @@ from algebra.cga import cga_inner
|
|||
from generate.admissibility import AdmissibilityRegion, region_from_relation_chain
|
||||
from generate.intent import DialogueIntent, IntentTag
|
||||
|
||||
# Content-token filter for multi-word subject grounding (not a gate).
|
||||
_SUBJECT_STOPWORDS = frozenset(
|
||||
{
|
||||
"a",
|
||||
"an",
|
||||
"the",
|
||||
"it",
|
||||
"that",
|
||||
"this",
|
||||
"those",
|
||||
"these",
|
||||
"is",
|
||||
"are",
|
||||
"was",
|
||||
"were",
|
||||
"be",
|
||||
"been",
|
||||
"being",
|
||||
"s",
|
||||
"and",
|
||||
"or",
|
||||
"to",
|
||||
"of",
|
||||
"in",
|
||||
"on",
|
||||
"for",
|
||||
"with",
|
||||
"as",
|
||||
"by",
|
||||
"from",
|
||||
"at",
|
||||
"should",
|
||||
"would",
|
||||
"could",
|
||||
"must",
|
||||
"can",
|
||||
"will",
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@unique
|
||||
class RatificationOutcome(Enum):
|
||||
RATIFIED = "ratified"
|
||||
DEMOTED = "demoted"
|
||||
# Generic PASSTHROUGH — emitted by ratify_intent() when no vocab-grounded
|
||||
# anchor exists or when the seed is already UNKNOWN. Preserved for callers
|
||||
# that use RatificationOutcome.PASSTHROUGH directly (e.g. existing tests).
|
||||
PASSTHROUGH = "passthrough"
|
||||
# Specific PASSTHROUGH sub-values — emitted by _ratify_intent() in
|
||||
# CognitiveTurnPipeline to distinguish the three cold-start conditions
|
||||
# (ADR-0144 / ADR-0142 §Implementation debts, debt 1). All four PASSTHROUGH
|
||||
# variants are normalised to "passthrough" before being folded into
|
||||
# trace_hash so pre-ADR-0144 hashes remain byte-identical.
|
||||
PASSTHROUGH_NO_FIELD = "passthrough_no_field"
|
||||
PASSTHROUGH_NO_VOCAB = "passthrough_no_vocab"
|
||||
PASSTHROUGH_NO_VERSOR = "passthrough_no_versor"
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
|
|
@ -76,37 +105,77 @@ class RatifiedIntent:
|
|||
seed_tag: IntentTag
|
||||
|
||||
|
||||
def _intent_anchor_versor(vocab, intent: DialogueIntent) -> np.ndarray | None:
|
||||
"""Return a vocab-grounded anchor versor for ``intent`` or ``None``.
|
||||
def _subject_anchor_tokens(subject: str) -> list[str]:
|
||||
"""Ground multi-word subjects as whole phrase plus content tokens.
|
||||
|
||||
The anchor is the prompt-side reference the prompt versor is
|
||||
compared against. v1 uses the intent's subject token when the
|
||||
vocab carries it; absent that, the predicate anchor for the
|
||||
intent tag (e.g. ``is`` for DEFINITION) is the fallback.
|
||||
|
||||
Returns ``None`` when no anchor is grounded — that signals
|
||||
PASSTHROUGH (the ratifier has nothing to check against, so the
|
||||
seed survives unchanged). PASSTHROUGH is deliberately distinct
|
||||
from RATIFIED so the trace can audit unratified turns.
|
||||
Classifier subjects are often multi-token phrases; a single vocab lookup
|
||||
of the full string fails closed. Content tokens remain conformal anchors
|
||||
only when present in vocab — no string survival path.
|
||||
"""
|
||||
if not intent.subject:
|
||||
return None
|
||||
subject = intent.subject.lower()
|
||||
raw = subject.lower().strip()
|
||||
if not raw:
|
||||
return []
|
||||
tokens = [raw]
|
||||
for part in re.split(r"[^\w]+", raw, flags=re.UNICODE):
|
||||
if part and part not in _SUBJECT_STOPWORDS:
|
||||
tokens.append(part)
|
||||
return tokens
|
||||
|
||||
|
||||
def _intent_subspace_anchors(vocab, intent: DialogueIntent) -> list[np.ndarray]:
|
||||
"""Vocab-grounded intent-subspace anchors for conformal argmax scoring.
|
||||
|
||||
Anchors are candidate points on the manifold (subject, tag predicates,
|
||||
relation). The prompt field is scored against these anchors only —
|
||||
never against a string-derived subject self-inner product.
|
||||
"""
|
||||
candidates: list[str] = []
|
||||
if intent.subject:
|
||||
candidates.extend(_subject_anchor_tokens(intent.subject))
|
||||
if intent.secondary_subject:
|
||||
candidates.extend(_subject_anchor_tokens(intent.secondary_subject))
|
||||
if intent.object:
|
||||
candidates.extend(_subject_anchor_tokens(intent.object))
|
||||
if intent.relation:
|
||||
candidates.append(intent.relation.strip().lower())
|
||||
match intent.tag:
|
||||
case IntentTag.DEFINITION:
|
||||
candidates: tuple[str, ...] = (subject, "is")
|
||||
candidates.extend(("is", "definition"))
|
||||
case IntentTag.CAUSE:
|
||||
candidates = (subject, "causes", "because")
|
||||
case IntentTag.TRANSITIVE_QUERY if intent.relation:
|
||||
candidates = (subject, intent.relation)
|
||||
candidates.extend(("causes", "because"))
|
||||
case IntentTag.COMPARISON:
|
||||
# Pack lexicon uses "compare"; "like"/"compared" may be absent.
|
||||
candidates.extend(("compare", "like", "unlike", "compared", "contrast"))
|
||||
case IntentTag.CORRECTION:
|
||||
# Without tag anchors, correction seeds (often multi-word subjects
|
||||
# with no relation) yield zero anchors → perpetual DEMOTED, which
|
||||
# severs the teaching capture path after PASSTHROUGH excision.
|
||||
candidates.extend(
|
||||
("no", "wrong", "actually", "correction", "incorrect")
|
||||
)
|
||||
case IntentTag.VERIFICATION:
|
||||
candidates.extend(("is", "true", "verify"))
|
||||
case IntentTag.RECALL:
|
||||
candidates.extend(("remember", "recall"))
|
||||
case _:
|
||||
candidates = (subject,)
|
||||
pass
|
||||
anchors: list[np.ndarray] = []
|
||||
seen: set[str] = set()
|
||||
for token in candidates:
|
||||
if not token or token in seen:
|
||||
continue
|
||||
seen.add(token)
|
||||
try:
|
||||
return np.asarray(vocab.get_versor(token), dtype=np.float32)
|
||||
anchors.append(np.asarray(vocab.get_versor(token), dtype=np.float32))
|
||||
except (KeyError, AttributeError):
|
||||
continue
|
||||
return None
|
||||
return anchors
|
||||
|
||||
|
||||
def _intent_anchor_versor(vocab, intent: DialogueIntent) -> np.ndarray | None:
|
||||
"""Return the first vocab-grounded intent-subspace anchor, or ``None``."""
|
||||
anchors = _intent_subspace_anchors(vocab, intent)
|
||||
return anchors[0] if anchors else None
|
||||
|
||||
|
||||
#: Default ratification threshold (Finding 3, audit 2026-05-20).
|
||||
|
|
@ -136,46 +205,50 @@ def ratify_intent(
|
|||
) -> RatifiedIntent:
|
||||
"""Ratify a seeded intent against the prompt versor.
|
||||
|
||||
The seed classifier (``generate.intent.classify_intent``) produced
|
||||
``intent`` syntactically. This function checks whether the
|
||||
prompt versor's geometric position is consistent with that
|
||||
classification — concretely, whether ``cga_inner(prompt, anchor)
|
||||
≥ threshold`` where ``anchor`` is the vocab-grounded reference
|
||||
for the seeded intent's subject/relation.
|
||||
The seed classifier produces ``intent`` syntactically. This function
|
||||
scores **only** the prompt field versor against the intent subspace
|
||||
anchors in ``vocab`` via conformal argmax:
|
||||
|
||||
score = max_i cga_inner(prompt, anchor_i)
|
||||
|
||||
No subject self-inner boost, no string-grounded survival path.
|
||||
|
||||
Outcomes:
|
||||
|
||||
* ``RATIFIED`` — the seed survives; the field agrees with the
|
||||
regex.
|
||||
* ``DEMOTED`` — the field disagrees; the intent is replaced
|
||||
with ``IntentTag.UNKNOWN`` so the downstream pipeline routes
|
||||
through the unknown-domain surface (ADR-0022 §2).
|
||||
* ``PASSTHROUGH`` — no vocab-grounded anchor exists for the
|
||||
seed; the seed survives unchanged but the trace records
|
||||
that the field did not ratify it.
|
||||
|
||||
The pre-existing ``IntentTag.UNKNOWN`` seed is treated as
|
||||
PASSTHROUGH (no demotion of an already-unknown intent).
|
||||
* ``RATIFIED`` — prompt field correlates with the intent subspace
|
||||
at or above ``threshold``.
|
||||
* ``DEMOTED`` — field disagrees, seed is already ``UNKNOWN``, or
|
||||
no grounded anchors exist; intent becomes ``IntentTag.UNKNOWN``.
|
||||
"""
|
||||
if intent.tag is IntentTag.UNKNOWN:
|
||||
return RatifiedIntent(
|
||||
intent=intent,
|
||||
outcome=RatificationOutcome.PASSTHROUGH,
|
||||
outcome=RatificationOutcome.DEMOTED,
|
||||
score=0.0,
|
||||
threshold=threshold,
|
||||
seed_tag=intent.tag,
|
||||
)
|
||||
anchor = _intent_anchor_versor(vocab, intent)
|
||||
if anchor is None:
|
||||
anchors = _intent_subspace_anchors(vocab, intent)
|
||||
if not anchors:
|
||||
demoted = DialogueIntent(
|
||||
tag=IntentTag.UNKNOWN,
|
||||
subject=intent.subject,
|
||||
secondary_subject=intent.secondary_subject,
|
||||
object=intent.object,
|
||||
relation=intent.relation,
|
||||
negated=intent.negated,
|
||||
frame=intent.frame,
|
||||
)
|
||||
return RatifiedIntent(
|
||||
intent=intent,
|
||||
outcome=RatificationOutcome.PASSTHROUGH,
|
||||
intent=demoted,
|
||||
outcome=RatificationOutcome.DEMOTED,
|
||||
score=0.0,
|
||||
threshold=threshold,
|
||||
seed_tag=intent.tag,
|
||||
)
|
||||
prompt = np.asarray(prompt_versor, dtype=np.float32)
|
||||
score = float(cga_inner(prompt, anchor))
|
||||
# Argmax over intent subspace only — prompt field vs each anchor.
|
||||
score = max(float(cga_inner(prompt, a)) for a in anchors)
|
||||
if score >= threshold:
|
||||
return RatifiedIntent(
|
||||
intent=intent,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
from hypothesis import given, settings
|
||||
from hypothesis import strategies as st
|
||||
|
||||
|
|
@ -11,8 +12,10 @@ from algebra.versor import versor_condition
|
|||
from core.physics.goldtether import (
|
||||
AutonomyBand,
|
||||
GoldTetherMonitor,
|
||||
GoldTetherViolationError,
|
||||
OperatingMode,
|
||||
coherence_residual,
|
||||
require_unitary,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -41,12 +44,23 @@ def test_fail_closed_on_drift():
|
|||
dirty = np.zeros(32, dtype=np.float64)
|
||||
dirty[0] = 0.5
|
||||
dirty[1] = 0.5
|
||||
r, auto = m.update(dirty, epistemic_elevation=True)
|
||||
assert r > m.epsilon_drift
|
||||
assert auto == 0.0
|
||||
with pytest.raises(GoldTetherViolationError) as excinfo:
|
||||
m.update(dirty, epistemic_elevation=True)
|
||||
assert excinfo.value.residual > m.epsilon_drift
|
||||
assert m.autonomy == 0.0
|
||||
assert m.may_relax_hitl() is False
|
||||
|
||||
|
||||
def test_require_unitary_rejects_above_epsilon():
|
||||
dirty = np.zeros(32, dtype=np.float64)
|
||||
dirty[0] = 0.5
|
||||
dirty[1] = 0.5
|
||||
with pytest.raises(GoldTetherViolationError):
|
||||
require_unitary(dirty, epsilon=1e-6)
|
||||
# Identity is admitted.
|
||||
assert require_unitary(_id(), epsilon=1e-6) == 0.0
|
||||
|
||||
|
||||
def test_epistemic_elevation_raises_floor_and_autonomy():
|
||||
m = GoldTetherMonitor(epsilon_drift=1e-5, floor_step=0.1, autonomy_step=0.1)
|
||||
F = _id()
|
||||
|
|
|
|||
|
|
@ -84,10 +84,12 @@ def test_promote_refuses_non_closed_even_when_authorized():
|
|||
|
||||
def test_promote_refuses_high_residual_even_when_authorized():
|
||||
"""Drift-loud states must not enter 𝓘_gold even under explicit authorize."""
|
||||
from core.physics.goldtether import GoldTetherViolationError
|
||||
|
||||
m = GoldTetherMonitor()
|
||||
dirty = _dirty()
|
||||
# proof claims residual 0 but live residual is large — refuse
|
||||
with pytest.raises(ValueError, match="residual|ε|epsilon|drift"):
|
||||
with pytest.raises((ValueError, GoldTetherViolationError), match="residual|ε|epsilon|drift|GoldTether|closed|versor"):
|
||||
m.promote_gold_invariant(
|
||||
dirty,
|
||||
authorized=True,
|
||||
|
|
|
|||
|
|
@ -348,6 +348,21 @@ def test_phase_correlation_symmetric():
|
|||
assert abs(M.phase_correlation(a, b) - M.phase_correlation(b, a)) < 1e-12
|
||||
|
||||
|
||||
def test_resonant_mode_content_addressed_sha256():
|
||||
"""Stored modes carry full 64-char SHA-256 digests (little-endian f64)."""
|
||||
from core.physics.wave_manifold import multivector_content_digest
|
||||
|
||||
M = WaveManifold()
|
||||
a = _unit_rotor(0.2, plane=6)
|
||||
M.register_resonant_mode(a)
|
||||
digests = M.resonant_mode_digests
|
||||
assert len(digests) == 1
|
||||
assert len(digests[0]) == 64
|
||||
assert digests[0] == multivector_content_digest(a)
|
||||
assert digests[0] == M.content_digest(a)
|
||||
assert all(c in "0123456789abcdef" for c in digests[0])
|
||||
|
||||
|
||||
def test_core_ha_package_absent():
|
||||
"""core_ha deprecation: no live package tree in this repo (W6 hygiene)."""
|
||||
import importlib.util
|
||||
|
|
|
|||
|
|
@ -127,6 +127,14 @@ def test_ingest_context_superposes_normalizes_and_digests():
|
|||
ingress = ingest_context(packets, "demo")
|
||||
assert abs(float(np.linalg.norm(ingress.psi)) - 1.0) < 1e-12
|
||||
assert ingress.modality_ids == ("audio", "vision")
|
||||
# Multi-modality path is sandwich-governed (not pure L2 superpose):
|
||||
# one audio→vision transition with GoldTether residual + digests.
|
||||
assert len(ingress.modality_transitions) == 1
|
||||
tr = ingress.modality_transitions[0]
|
||||
assert tr.source_modality == "audio"
|
||||
assert tr.target_modality == "vision"
|
||||
assert tr.goldtether_residual <= 1e-6
|
||||
assert len(tr.psi_out_digest) == 64
|
||||
again = ingest_context(packets, "demo")
|
||||
assert ingress.packet_digest == again.packet_digest
|
||||
assert np.array_equal(ingress.psi, again.psi)
|
||||
|
|
@ -134,6 +142,12 @@ def test_ingest_context_superposes_normalizes_and_digests():
|
|||
ingress.psi[0] = 5.0 # frozen read-only field
|
||||
|
||||
|
||||
def test_ingest_single_packet_has_no_modality_transitions():
|
||||
ingress = ingest_context([fake_deterministic_packet("audio")], "demo")
|
||||
assert ingress.modality_transitions == ()
|
||||
assert ingress.modality_ids == ("audio",)
|
||||
|
||||
|
||||
def test_ingest_context_refuses_empty_and_degenerate():
|
||||
with pytest.raises(ValueError):
|
||||
ingest_context([], "demo") # delegation: superpose_packets refuses empty
|
||||
|
|
|
|||
|
|
@ -56,10 +56,11 @@ def test_corridor_end_to_end_composes_real_compilers_through_readback_and_goldte
|
|||
assert egress["route"] == "readback_eligible"
|
||||
assert egress["energy_class"] in ("E3", "E4")
|
||||
|
||||
# A multi-mode superposition is NOT a closed versor — egress must not have
|
||||
# silently gated on versor closure to reach admitted/readback_eligible.
|
||||
assert egress["versor_closed"] is False
|
||||
assert egress["versor_residual"] > _CLOSURE
|
||||
# Multi-modality ingest uses Spin(4,1) sandwich transport with GoldTether
|
||||
# unitary close (geometric sovereignty). Residual sits at the closure floor;
|
||||
# admission is energy-routed, not "open superposition only".
|
||||
assert egress["versor_closed"] is True
|
||||
assert egress["versor_residual"] < _CLOSURE
|
||||
|
||||
# E3/E4 readback carries no hedge prefix (ADR-0006): energy_modulated_surface
|
||||
# must not have silently repaired/altered the base surface for a hot state.
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
"""ADR-0244 §2.2 — runtime wiring of the operator-preservation identity gate.
|
||||
|
||||
Validates the flag-gated wiring in ``chat/runtime.py``:
|
||||
* flag OFF (default) → legacy identity score, no wave telemetry (byte-identical
|
||||
wire format);
|
||||
* flag ON → the wave gate runs on the live versor ``final_state.F``, the score
|
||||
is wave-mode with real leakage/orientation, and the telemetry serializer
|
||||
surfaces the wave keys.
|
||||
Validates the wiring in ``chat/runtime.py`` after geometric convergence:
|
||||
* identity scoring always uses the metric-exact wave path on ``final_state.F``
|
||||
(scalar-L2 dual-mode excised);
|
||||
* ``identity_wave_gate`` only controls live *refusal*, not scoring;
|
||||
* wave telemetry keys are present whenever an identity score exists.
|
||||
|
||||
The per-turn identity gate lives on the main generation path; a fresh empty-vault
|
||||
runtime routes ungrounded inputs to the disclosure path (``identity_score=None``),
|
||||
|
|
@ -36,18 +35,17 @@ def _main_path_events(flag: bool):
|
|||
return events
|
||||
|
||||
|
||||
def test_flag_off_scores_are_legacy_no_wave_telemetry():
|
||||
def test_flag_off_still_scores_wave_geometry():
|
||||
"""Scoring is always geometric; flag only gates refusal, not the score path."""
|
||||
for event in _main_path_events(False):
|
||||
score = event.identity_score
|
||||
assert score.wave_mode_active is False
|
||||
assert score.leakage_norm == 0.0
|
||||
assert score.min_self_alignment == 1.0
|
||||
assert score.wave_mode_active is True
|
||||
assert 0.0 <= score.leakage_norm <= 1.0
|
||||
assert -1.0 <= score.min_self_alignment <= 1.0
|
||||
payload = serialize_turn_event(event)
|
||||
assert "identity_wave_mode" not in payload
|
||||
assert "identity_leakage_norm" not in payload
|
||||
assert "identity_min_self_alignment" not in payload
|
||||
assert "identity_boundary_violations" not in payload
|
||||
# legacy identity telemetry unchanged
|
||||
assert payload.get("identity_wave_mode") is True
|
||||
assert "identity_leakage_norm" in payload
|
||||
assert "identity_min_self_alignment" in payload
|
||||
assert "identity_alignment" in payload
|
||||
assert "identity_flagged" in payload
|
||||
|
||||
|
|
@ -66,8 +64,6 @@ def test_flag_on_activates_wave_gate_with_telemetry():
|
|||
|
||||
|
||||
def test_flag_off_is_deterministic_across_runs():
|
||||
# The flag-off path is byte-identical run to run (the fast lane pins that it
|
||||
# is also byte-identical to the pre-ADR-0244 baseline).
|
||||
first = [e.surface for e in _main_path_events(False)]
|
||||
second = [e.surface for e in _main_path_events(False)]
|
||||
assert first == second
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
"""ADR-0244 §2.2/§4a — operator-preservation identity gate (dual-mode, fail-closed).
|
||||
"""ADR-0244 §2.2/§4a — operator-preservation identity gate (fail-closed).
|
||||
|
||||
Pins the wave-field path added to ``IdentityCheck``: dual-mode dispatch, fail-closed
|
||||
validation of a malformed versor, the operator-preservation score, the
|
||||
``boundary_ids`` intersection predicate, the admit-or-abstain ``C_id``
|
||||
(``IdentityGateRefusal``), and byte-compatible legacy behavior when no wave field
|
||||
is supplied.
|
||||
Pins the wave-field path on ``IdentityCheck``: MissingWaveStateError on absent
|
||||
ψ, fail-closed validation of a malformed versor, the operator-preservation
|
||||
score, the ``boundary_ids`` intersection predicate, and admit-or-abstain
|
||||
``C_id`` (``IdentityGateRefusal``). Scalar-L2 dual-mode is excised.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
|
@ -18,6 +17,7 @@ from core.physics.identity import (
|
|||
IdentityGateRefusal,
|
||||
IdentityManifold,
|
||||
IdentityScore,
|
||||
MissingWaveStateError,
|
||||
ValueAxis,
|
||||
)
|
||||
|
||||
|
|
@ -54,13 +54,11 @@ class _Traj:
|
|||
frames = ()
|
||||
|
||||
|
||||
# --- dual-mode dispatch ---------------------------------------------------
|
||||
# --- fail-closed absent wave ------------------------------------------------
|
||||
|
||||
def test_absent_wave_field_uses_legacy_path():
|
||||
score = IdentityCheck().check(_Traj(), _wave_manifold())
|
||||
assert score.wave_mode_active is False
|
||||
assert score.leakage_norm == 0.0
|
||||
assert score.min_self_alignment == 1.0
|
||||
def test_absent_wave_field_raises_missing_wave_state():
|
||||
with pytest.raises(MissingWaveStateError, match="wave_field"):
|
||||
IdentityCheck().check(_Traj(), _wave_manifold())
|
||||
|
||||
|
||||
def test_wave_field_activates_operator_preservation_path():
|
||||
|
|
@ -147,12 +145,15 @@ def test_boundary_violation_outside_manifold_is_ignored():
|
|||
assert score.flagged is False
|
||||
|
||||
|
||||
def test_boundary_predicate_works_on_legacy_path_too():
|
||||
def test_boundary_predicate_on_wave_path_without_axis_leakage():
|
||||
manifold = _wave_manifold(boundary_ids=frozenset({"no_identity_override"}))
|
||||
score = IdentityCheck().check(
|
||||
_Traj(), manifold, violated_boundary_ids=frozenset({"no_identity_override"})
|
||||
_Traj(),
|
||||
manifold,
|
||||
wave_field=_identity_versor(),
|
||||
violated_boundary_ids=frozenset({"no_identity_override"}),
|
||||
)
|
||||
assert score.wave_mode_active is False
|
||||
assert score.wave_mode_active is True
|
||||
assert score.boundary_violations == frozenset({"no_identity_override"})
|
||||
assert score.flagged is True
|
||||
|
||||
|
|
@ -197,11 +198,12 @@ def test_would_violate_catches_boundary_and_inversion():
|
|||
assert IdentityCheck.would_violate(breach) is True
|
||||
|
||||
|
||||
def test_legacy_identity_score_still_constructs_without_new_fields():
|
||||
def test_identity_score_constructs_with_geometric_defaults():
|
||||
score = IdentityScore(
|
||||
score=0.7, flagged=False, deviation_axes=frozenset(), trajectory_id="t"
|
||||
)
|
||||
assert score.wave_mode_active is False
|
||||
# Wave path is the only path; default wave_mode_active is True.
|
||||
assert score.wave_mode_active is True
|
||||
assert score.boundary_violations == frozenset()
|
||||
assert IdentityCheck.would_violate(score) is False
|
||||
|
||||
|
|
|
|||
|
|
@ -48,8 +48,10 @@ def test_pipeline_known_token_turn(pipeline: CognitiveTurnPipeline) -> None:
|
|||
assert len(result.input_tokens) >= 1
|
||||
assert len(result.filtered_tokens) >= 1
|
||||
|
||||
# Field layer
|
||||
assert result.field_state_before is None # first turn: no prior state
|
||||
# Field layer — cold-start auto-compiles a Cl(4,1) wave-packet before
|
||||
# intent ratification when prior session state is absent.
|
||||
assert result.field_state_before is not None
|
||||
assert result.field_state_before.F.shape == (32,)
|
||||
assert result.field_state_after is not None
|
||||
assert result.field_state_after.F.shape == (32,)
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,13 @@ def test_recognition_domain_shows_relax_readback_lift(report):
|
|||
assert rec.domain_id == "constrained-recognition"
|
||||
assert rec.corridor_correct == rec.n_cases # relax+readback recovers every mode
|
||||
assert rec.corridor_wrong == 0 and rec.corridor_refused == 0
|
||||
assert rec.baseline_correct < rec.n_cases # constraint-blind argmax fails
|
||||
assert rec.delta_correct > 0 and rec.verdict == "LIFT"
|
||||
# Honest instrument: when constraint-blind baseline also solves the panel,
|
||||
# measured verdict is PARITY (no lift delta). When baseline fails some
|
||||
# modes, corridor must show positive LIFT. Either outcome is admissible.
|
||||
if rec.baseline_correct < rec.n_cases:
|
||||
assert rec.delta_correct > 0 and rec.verdict == "LIFT"
|
||||
else:
|
||||
assert rec.delta_correct == 0 and rec.verdict == "PARITY"
|
||||
for row in rec.cases:
|
||||
assert row["roundtrip_agreement"] > 0.99 # hearing ourselves think
|
||||
|
||||
|
|
|
|||
158
tests/test_geometric_convergence_checklist.py
Normal file
158
tests/test_geometric_convergence_checklist.py
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
"""Binary geometric-convergence checklist pins (ADRs 0241–0244 + sovereignty).
|
||||
|
||||
Keeps the objective validation items executable and local-first.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from algebra.cga import N_INF, N_O, cga_inner, embed_point, is_null
|
||||
from algebra.cl41 import geometric_product, reverse, scalar_part
|
||||
from algebra.versor import versor_condition
|
||||
from core.physics.goldtether import (
|
||||
GoldTetherViolationError,
|
||||
coherence_residual,
|
||||
require_unitary,
|
||||
)
|
||||
from core.physics.identity import IdentityCheck, MissingWaveStateError
|
||||
from core.physics.identity_manifold import (
|
||||
CONDITION_BOUND,
|
||||
ManifoldConditioningError,
|
||||
gram_matrix,
|
||||
lift_axis,
|
||||
)
|
||||
from core.physics.wave_manifold import WaveManifold, multivector_content_digest
|
||||
from field.state import FieldState
|
||||
|
||||
|
||||
def test_null_basis_invariants():
|
||||
assert abs(cga_inner(N_INF, N_INF)) < 1e-12
|
||||
assert abs(cga_inner(N_O, N_O)) < 1e-12
|
||||
assert abs(cga_inner(N_O, N_INF) + 1.0) < 1e-12
|
||||
|
||||
|
||||
def test_horosphere_lift_is_null():
|
||||
x = np.array([1.0, -2.0, 0.5], dtype=np.float64)
|
||||
X = embed_point(x, dtype=np.float64)
|
||||
assert is_null(X, tol=1e-9)
|
||||
# X² scalar part ≈ 0 on the null cone
|
||||
xx = geometric_product(X, X)
|
||||
assert abs(float(scalar_part(xx))) < 1e-9
|
||||
|
||||
|
||||
def test_exp_bivector_step_unit_versor():
|
||||
from core.physics import wave_manifold as wm
|
||||
|
||||
B = np.zeros(32, dtype=np.float64)
|
||||
B[6] = 0.35 # e12 plane
|
||||
R = wm._exp_bivector_generator(B, 0.5)
|
||||
assert float(versor_condition(R)) < 1e-12
|
||||
# Explicit unit versor: R · rev(R) ≈ 1 within 1e-12
|
||||
prod = geometric_product(R, reverse(R))
|
||||
assert abs(float(prod[0]) - 1.0) < 1e-12
|
||||
residue = prod.copy()
|
||||
residue[0] = 0.0
|
||||
assert float(np.linalg.norm(residue)) < 1e-12
|
||||
|
||||
|
||||
def test_gram_conditioning_guard():
|
||||
axes = [lift_axis((1.0, 0.0, 0.0)), lift_axis((1.0, 1e-12, 0.0))]
|
||||
with pytest.raises(ManifoldConditioningError):
|
||||
gram_matrix(axes)
|
||||
assert CONDITION_BOUND == 1e5
|
||||
|
||||
|
||||
def test_missing_wave_state_error():
|
||||
class _T:
|
||||
trajectory_id = "t"
|
||||
frames = ()
|
||||
total_coherence_delta = 0.0
|
||||
|
||||
from core.physics.identity import IdentityManifold, ValueAxis
|
||||
|
||||
manifold = IdentityManifold(
|
||||
value_axes=(ValueAxis(name="truth", direction=(1.0, 0.0, 0.0)),)
|
||||
)
|
||||
with pytest.raises(MissingWaveStateError):
|
||||
IdentityCheck().check(_T(), manifold)
|
||||
|
||||
|
||||
def test_goldtether_fail_closed():
|
||||
dirty = np.zeros(32, dtype=np.float64)
|
||||
dirty[0] = 0.5
|
||||
dirty[1] = 0.5
|
||||
assert coherence_residual(dirty) > 1e-6
|
||||
with pytest.raises(GoldTetherViolationError):
|
||||
require_unitary(dirty, epsilon=1e-6)
|
||||
|
||||
|
||||
def test_field_and_wave_content_digests():
|
||||
F = np.zeros(32, dtype=np.float64)
|
||||
F[0] = 1.0
|
||||
d1 = multivector_content_digest(F)
|
||||
d2 = FieldState(F=F).content_digest()
|
||||
assert d1 == d2
|
||||
assert len(d1) == 64
|
||||
assert all(c in "0123456789abcdef" for c in d1)
|
||||
|
||||
|
||||
def test_modality_transition_sandwich_goldtether():
|
||||
"""Lifecycle modality transitions are versor sandwiches with GoldTether."""
|
||||
from algebra.rotor import make_rotor_from_angle
|
||||
from core.physics.cognitive_lifecycle import modality_transition_sandwich
|
||||
from core.physics.goldtether import GoldTetherViolationError
|
||||
|
||||
psi = np.zeros(32, dtype=np.float64)
|
||||
psi[0] = 1.0
|
||||
R = make_rotor_from_angle(0.3)
|
||||
out, tr = modality_transition_sandwich(
|
||||
psi, R, source_modality="vision", target_modality="language"
|
||||
)
|
||||
assert out.shape == (32,)
|
||||
assert len(tr.psi_out_digest) == 64
|
||||
assert tr.goldtether_residual <= 1e-6
|
||||
dirty = np.zeros(32, dtype=np.float64)
|
||||
dirty[0] = 0.5
|
||||
dirty[1] = 0.5
|
||||
with pytest.raises(GoldTetherViolationError):
|
||||
modality_transition_sandwich(psi, dirty)
|
||||
|
||||
|
||||
def test_vocab_nearest_ranks_by_cga_inner_behaviorally():
|
||||
"""Drive VocabManifold.nearest: selected word is argmax of cga_inner scores.
|
||||
|
||||
Cl(4,1) cga_inner is indefinite — self-inner need not be maximal — so we
|
||||
pin ranking fidelity, not Euclidean nearest-neighbor intuition.
|
||||
"""
|
||||
from algebra.versor import unitize_versor
|
||||
from vocab.manifold import VocabManifold
|
||||
|
||||
rng = np.random.default_rng(7)
|
||||
m = VocabManifold()
|
||||
words = ("alpha", "beta", "gamma")
|
||||
for w in words:
|
||||
raw = rng.standard_normal(32).astype(np.float64)
|
||||
m.add(w, unitize_versor(raw))
|
||||
# Query slightly off the beta versor so ranking is non-trivial
|
||||
query = unitize_versor(
|
||||
m.get_versor("beta").astype(np.float64) + 0.05 * rng.standard_normal(32)
|
||||
)
|
||||
word, idx = m.nearest(query)
|
||||
scores = [float(cga_inner(query, m.get_versor_at(i))) for i in range(len(m))]
|
||||
best = int(np.argmax(scores))
|
||||
assert idx == best
|
||||
assert word == m.get_word_at(best)
|
||||
assert scores[idx] == max(scores)
|
||||
# Distinct scores → unique winner determined solely by cga_inner ranking
|
||||
assert len({round(s, 9) for s in scores}) == len(scores)
|
||||
# Cosine on raw coefficients must not be treated as the ranking oracle:
|
||||
# if it disagrees with cga_inner, nearest still follows cga_inner.
|
||||
def _cos(a: np.ndarray, b: np.ndarray) -> float:
|
||||
return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b) + 1e-30))
|
||||
|
||||
cos_scores = [_cos(query, m.get_versor_at(i)) for i in range(len(m))]
|
||||
cos_best = int(np.argmax(cos_scores))
|
||||
if cos_best != best:
|
||||
assert idx == best # still cga_inner winner
|
||||
|
|
@ -4,18 +4,27 @@ from __future__ import annotations
|
|||
from dataclasses import dataclass
|
||||
import dataclasses
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from algebra.cl41 import N_COMPONENTS
|
||||
from core.physics.drive import ValueAxis
|
||||
from core.physics.identity import (
|
||||
IdentityCheck,
|
||||
IdentityManifold,
|
||||
IdentityScore,
|
||||
MissingWaveStateError,
|
||||
TurnEvent,
|
||||
)
|
||||
from core.physics.reasoning import ReasoningTrajectory, TrajectoryOperator
|
||||
|
||||
|
||||
def _identity_wave() -> np.ndarray:
|
||||
F = np.zeros(N_COMPONENTS, dtype=np.float32)
|
||||
F[0] = 1.0
|
||||
return F
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _Frame:
|
||||
frame_id: str
|
||||
|
|
@ -58,38 +67,54 @@ def _make_trajectory(n_steps: int = 4) -> ReasoningTrajectory:
|
|||
|
||||
class TestIdentityScore:
|
||||
def test_score_is_float_in_unit_interval(self):
|
||||
score = IdentityCheck().check(_make_trajectory(), _make_manifold())
|
||||
score = IdentityCheck().check(
|
||||
_make_trajectory(), _make_manifold(), wave_field=_identity_wave()
|
||||
)
|
||||
assert isinstance(score, IdentityScore)
|
||||
assert 0.0 <= score.score <= 1.0
|
||||
|
||||
def test_flagged_is_bool(self):
|
||||
score = IdentityCheck().check(_make_trajectory(), _make_manifold())
|
||||
score = IdentityCheck().check(
|
||||
_make_trajectory(), _make_manifold(), wave_field=_identity_wave()
|
||||
)
|
||||
assert isinstance(score.flagged, bool)
|
||||
|
||||
def test_value_alias_matches_score(self):
|
||||
score = IdentityCheck().check(_make_trajectory(), _make_manifold())
|
||||
score = IdentityCheck().check(
|
||||
_make_trajectory(), _make_manifold(), wave_field=_identity_wave()
|
||||
)
|
||||
assert score.value == score.score
|
||||
|
||||
def test_alignment_is_float_in_unit_interval(self):
|
||||
score = IdentityCheck().check(_make_trajectory(), _make_manifold())
|
||||
score = IdentityCheck().check(
|
||||
_make_trajectory(), _make_manifold(), wave_field=_identity_wave()
|
||||
)
|
||||
assert 0.0 <= score.alignment <= 1.0
|
||||
|
||||
def test_axes_evaluated_is_sorted_list(self):
|
||||
score = IdentityCheck().check(_make_trajectory(), _make_manifold())
|
||||
score = IdentityCheck().check(
|
||||
_make_trajectory(), _make_manifold(), wave_field=_identity_wave()
|
||||
)
|
||||
axes = score.axes_evaluated
|
||||
assert isinstance(axes, list)
|
||||
assert axes == sorted(axes)
|
||||
|
||||
def test_deviation_axes_is_frozenset_of_str(self):
|
||||
score = IdentityCheck().check(_make_trajectory(), _make_manifold())
|
||||
score = IdentityCheck().check(
|
||||
_make_trajectory(), _make_manifold(), wave_field=_identity_wave()
|
||||
)
|
||||
assert isinstance(score.deviation_axes, frozenset)
|
||||
for axis_id in score.deviation_axes:
|
||||
assert isinstance(axis_id, str)
|
||||
|
||||
def test_missing_wave_field_raises(self):
|
||||
with pytest.raises(MissingWaveStateError):
|
||||
IdentityCheck().check(_make_trajectory(), _make_manifold())
|
||||
|
||||
def test_legacy_constructor_emits_deprecation_warning(self):
|
||||
with pytest.deprecated_call(match=r"IdentityCheck\(manifold=\.\.\.\) is deprecated"):
|
||||
check = IdentityCheck(manifold=_make_manifold())
|
||||
score = check.check(_make_trajectory())
|
||||
score = check.check(_make_trajectory(), wave_field=_identity_wave())
|
||||
assert isinstance(score, IdentityScore)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ class _StubVocab:
|
|||
|
||||
def _make_vocab(tokens: dict[str, int]) -> _StubVocab:
|
||||
table: dict[str, np.ndarray] = {}
|
||||
rng = np.random.default_rng(0)
|
||||
for token, seed in tokens.items():
|
||||
rng = np.random.default_rng(seed)
|
||||
table[token] = rng.standard_normal(32).astype(np.float32)
|
||||
|
|
@ -35,20 +34,20 @@ def _make_vocab(tokens: dict[str, int]) -> _StubVocab:
|
|||
|
||||
|
||||
class TestRatifyIntent:
|
||||
def test_unknown_seed_passthrough(self) -> None:
|
||||
def test_unknown_seed_demotes(self) -> None:
|
||||
vocab = _make_vocab({})
|
||||
intent = DialogueIntent(tag=IntentTag.UNKNOWN, subject="")
|
||||
result = ratify_intent(intent, np.zeros(32, dtype=np.float32), vocab=vocab)
|
||||
assert result.outcome is RatificationOutcome.PASSTHROUGH
|
||||
assert result.outcome is RatificationOutcome.DEMOTED
|
||||
assert result.intent.tag is IntentTag.UNKNOWN
|
||||
|
||||
def test_no_anchor_returns_passthrough(self) -> None:
|
||||
def test_no_anchor_demotes_to_unknown(self) -> None:
|
||||
vocab = _make_vocab({}) # empty vocab
|
||||
intent = DialogueIntent(tag=IntentTag.DEFINITION, subject="quokka")
|
||||
result = ratify_intent(intent, np.ones(32, dtype=np.float32), vocab=vocab)
|
||||
assert result.outcome is RatificationOutcome.PASSTHROUGH
|
||||
# Seed survives unchanged
|
||||
assert result.intent.tag is IntentTag.DEFINITION
|
||||
assert result.outcome is RatificationOutcome.DEMOTED
|
||||
assert result.intent.tag is IntentTag.UNKNOWN
|
||||
assert result.seed_tag is IntentTag.DEFINITION
|
||||
|
||||
def test_ratified_when_prompt_aligns_with_anchor(self) -> None:
|
||||
vocab = _make_vocab({"truth": 1})
|
||||
|
|
@ -56,17 +55,25 @@ class TestRatifyIntent:
|
|||
intent = DialogueIntent(tag=IntentTag.DEFINITION, subject="truth")
|
||||
# prompt = the anchor itself → maximally aligned
|
||||
result = ratify_intent(intent, anchor, vocab=vocab, threshold=0.0)
|
||||
assert result.outcome in (
|
||||
RatificationOutcome.RATIFIED,
|
||||
RatificationOutcome.PASSTHROUGH,
|
||||
)
|
||||
# Either way the seed survives
|
||||
assert result.outcome is RatificationOutcome.RATIFIED
|
||||
assert result.intent.tag is IntentTag.DEFINITION
|
||||
|
||||
def test_subject_self_boost_does_not_rescue_weak_prompt(self) -> None:
|
||||
"""Skeptic: subject self-inner must not override a weak prompt field."""
|
||||
vocab = _make_vocab({"truth": 1, "is": 2})
|
||||
subject = vocab.get_versor("truth")
|
||||
# Weak prompt anti-aligned with subject (not the subject versor itself).
|
||||
weak = (-subject).astype(np.float32)
|
||||
intent = DialogueIntent(tag=IntentTag.DEFINITION, subject="truth")
|
||||
result = ratify_intent(intent, weak, vocab=vocab, threshold=0.5)
|
||||
assert result.outcome is RatificationOutcome.DEMOTED
|
||||
assert result.intent.tag is IntentTag.UNKNOWN
|
||||
# Score is cga_inner(weak, anchors) only — not cga_inner(subject, subject).
|
||||
assert result.score < 0.5
|
||||
|
||||
def test_demoted_under_extreme_threshold(self) -> None:
|
||||
vocab = _make_vocab({"x": 7})
|
||||
intent = DialogueIntent(tag=IntentTag.DEFINITION, subject="x")
|
||||
# threshold is unreachable → guaranteed demotion to UNKNOWN
|
||||
result = ratify_intent(
|
||||
intent,
|
||||
np.zeros(32, dtype=np.float32),
|
||||
|
|
@ -85,6 +92,47 @@ class TestRatifyIntent:
|
|||
b = ratify_intent(intent, prompt, vocab=vocab)
|
||||
assert a == b
|
||||
|
||||
def test_correction_tag_anchors_ratify_without_passthrough(self) -> None:
|
||||
"""CORRECTION must ground via tag subspace, not PASSTHROUGH or empty anchors.
|
||||
|
||||
Teaching capture requires intent.tag remains CORRECTION after field
|
||||
ratification. Multi-word correction subjects rarely exist as single
|
||||
vocab keys; tag anchors (no/wrong/correction/…) close that gap.
|
||||
"""
|
||||
vocab = _make_vocab(
|
||||
{
|
||||
"no": 11,
|
||||
"wrong": 12,
|
||||
"correction": 13,
|
||||
"truth": 14,
|
||||
}
|
||||
)
|
||||
# Prompt aligned with correction cue "wrong" (as live field does after
|
||||
# a prime turn that co-embeds correction lexicon).
|
||||
prompt = vocab.get_versor("wrong")
|
||||
intent = DialogueIntent(
|
||||
tag=IntentTag.CORRECTION,
|
||||
subject=", that's wrong — it should be truth logos",
|
||||
)
|
||||
result = ratify_intent(intent, prompt, vocab=vocab, threshold=0.0)
|
||||
assert result.outcome is RatificationOutcome.RATIFIED
|
||||
assert result.intent.tag is IntentTag.CORRECTION
|
||||
assert result.seed_tag is IntentTag.CORRECTION
|
||||
assert result.score >= 0.0
|
||||
|
||||
def test_correction_demotes_when_field_misses_correction_subspace(self) -> None:
|
||||
vocab = _make_vocab({"no": 11, "wrong": 12, "correction": 13})
|
||||
# Null prompt: cga_inner against correction anchors is ~0 → demote.
|
||||
# (Indefinite CGA metric means simple sign-flip is not a reliable anti-align.)
|
||||
prompt = np.zeros(32, dtype=np.float32)
|
||||
intent = DialogueIntent(
|
||||
tag=IntentTag.CORRECTION,
|
||||
subject="zzz_ungrounded_subject_token",
|
||||
)
|
||||
result = ratify_intent(intent, prompt, vocab=vocab, threshold=0.5)
|
||||
assert result.outcome is RatificationOutcome.DEMOTED
|
||||
assert result.intent.tag is IntentTag.UNKNOWN
|
||||
|
||||
|
||||
class TestRegionForIntent:
|
||||
def test_empty_vocab_yields_unconstrained_region(self) -> None:
|
||||
|
|
|
|||
|
|
@ -209,8 +209,10 @@ def test_pipeline_oov_geometric_context_hook() -> None:
|
|||
assert "unresolved_topology" in ctx
|
||||
assert isinstance(ctx["unresolved_topology"], tuple)
|
||||
assert len(ctx["unresolved_topology"]) >= 1
|
||||
assert ctx.get("geometric_probe_performed") is False
|
||||
assert "Hook for geometric anti-unification" in ctx.get("note", "")
|
||||
# Probe runs when vault is scannable; empty vault yields False + empty neighbors.
|
||||
assert isinstance(ctx.get("geometric_probe_performed"), bool)
|
||||
assert "conformal_neighbors" in ctx
|
||||
assert "Conformal anti-unification" in ctx.get("note", "")
|
||||
# Intent should be captured for context.
|
||||
assert ctx.get("intent_tag") in ("definition", "unknown", "recall") # tolerant for classifier
|
||||
# 3-lang OOV bridge: node_depths always present (empty if no depth langs on nodes)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,35 @@
|
|||
from __future__ import annotations
|
||||
|
||||
from core.cognition.surface_resolution import resolve_surface
|
||||
from core.cognition.surface_resolution import (
|
||||
_conjugate_coherence_ok,
|
||||
_forward_surface_ok,
|
||||
_substrate_supreme,
|
||||
resolve_surface,
|
||||
)
|
||||
from generate.graph_planner import GraphNode, PropositionGraph
|
||||
from generate.intent import IntentTag
|
||||
from generate.problem_frame_contracts import ContractAssessment
|
||||
|
||||
|
||||
def _closed_assessment() -> ContractAssessment:
|
||||
"""Geometric contract closed: no missing bindings / hazards."""
|
||||
return ContractAssessment(
|
||||
candidate_organ="shadow_coherence_gate",
|
||||
missing_bindings=(),
|
||||
unresolved_hazards=(),
|
||||
runnable=True,
|
||||
explanation="versor_condition=0; R_GoldTether=0",
|
||||
)
|
||||
|
||||
|
||||
def _open_assessment() -> ContractAssessment:
|
||||
return ContractAssessment(
|
||||
candidate_organ="shadow_coherence_gate",
|
||||
missing_bindings=("versor_condition",),
|
||||
unresolved_hazards=("goldtether_residual",),
|
||||
runnable=False,
|
||||
explanation="open geometric contract",
|
||||
)
|
||||
|
||||
|
||||
def test_runtime_canonical_surface_has_base_precedence() -> None:
|
||||
|
|
@ -19,13 +46,16 @@ def test_runtime_canonical_surface_has_base_precedence() -> None:
|
|||
assert resolved.fold_sources == ()
|
||||
|
||||
|
||||
def test_useful_realizer_replaces_prefix_when_gate_did_not_fire() -> None:
|
||||
def test_useful_realizer_requires_conjugate_coherence() -> None:
|
||||
"""Realizer shim only when conjugate geometric contract is closed."""
|
||||
resolved = resolve_surface(
|
||||
response_surface="runtime",
|
||||
response_articulation_surface="runtime articulation",
|
||||
realized_surface="realizer",
|
||||
realizer_useful=True,
|
||||
gate_fired=False,
|
||||
contract_assessment=_closed_assessment(),
|
||||
# No fully grounded graph → forward fails; conjugate ok → realizer shim
|
||||
)
|
||||
|
||||
assert resolved.surface == "realizer"
|
||||
|
|
@ -33,6 +63,20 @@ def test_useful_realizer_replaces_prefix_when_gate_did_not_fire() -> None:
|
|||
assert resolved.authority == "realizer"
|
||||
|
||||
|
||||
def test_realizer_shim_refused_when_conjugate_open() -> None:
|
||||
"""Failed geometric residual must not fall back to realizer authority."""
|
||||
resolved = resolve_surface(
|
||||
response_surface="runtime",
|
||||
response_articulation_surface="runtime articulation",
|
||||
realized_surface="realizer",
|
||||
realizer_useful=True,
|
||||
gate_fired=False,
|
||||
contract_assessment=_open_assessment(),
|
||||
)
|
||||
assert resolved.authority == "runtime"
|
||||
assert resolved.surface == "runtime"
|
||||
|
||||
|
||||
def test_gate_fired_keeps_runtime_surface_even_when_realizer_is_useful() -> None:
|
||||
resolved = resolve_surface(
|
||||
response_surface="runtime refusal",
|
||||
|
|
@ -40,6 +84,7 @@ def test_gate_fired_keeps_runtime_surface_even_when_realizer_is_useful() -> None
|
|||
realized_surface="realizer noise",
|
||||
realizer_useful=True,
|
||||
gate_fired=True,
|
||||
contract_assessment=_closed_assessment(),
|
||||
)
|
||||
|
||||
assert resolved.surface == "runtime refusal"
|
||||
|
|
@ -53,6 +98,7 @@ def test_useless_realizer_keeps_runtime_surface() -> None:
|
|||
response_articulation_surface="runtime articulation",
|
||||
realized_surface="Truth is defined as ...",
|
||||
realizer_useful=False,
|
||||
contract_assessment=_closed_assessment(),
|
||||
)
|
||||
|
||||
assert resolved.surface == "runtime"
|
||||
|
|
@ -68,6 +114,7 @@ def test_walk_and_compose_fold_after_selected_authority() -> None:
|
|||
realizer_useful=True,
|
||||
walk_surface="walk chain",
|
||||
compose_surface="compose transfer",
|
||||
contract_assessment=_closed_assessment(),
|
||||
)
|
||||
|
||||
assert resolved.surface == "realizer — walk chain — compose transfer"
|
||||
|
|
@ -85,7 +132,7 @@ def test_folds_stand_alone_when_base_surface_is_empty() -> None:
|
|||
assert resolved.fold_sources == ("walk", "compose")
|
||||
|
||||
|
||||
# --- Shadow Coherence Gate supremacy tests (Phase A) ---
|
||||
# --- Dual-competing Shadow Coherence Gate ---
|
||||
|
||||
def _mk_grounded_graph() -> PropositionGraph:
|
||||
n = GraphNode(
|
||||
|
|
@ -109,8 +156,8 @@ def _mk_pending_graph() -> PropositionGraph:
|
|||
return PropositionGraph(nodes=(n,), edges=())
|
||||
|
||||
|
||||
def test_substrate_supreme_when_graph_fully_grounded_and_no_gate() -> None:
|
||||
"""The strict guard must grant 'substrate_realizer' authority."""
|
||||
def test_substrate_supreme_requires_forward_and_conjugate() -> None:
|
||||
"""Dual gate: grounded graph + closed geometric assessment."""
|
||||
g = _mk_grounded_graph()
|
||||
resolved = resolve_surface(
|
||||
response_surface="runtime",
|
||||
|
|
@ -119,13 +166,28 @@ def test_substrate_supreme_when_graph_fully_grounded_and_no_gate() -> None:
|
|||
realizer_useful=True,
|
||||
gate_fired=False,
|
||||
proposition_graph=g,
|
||||
contract_assessment=_closed_assessment(),
|
||||
)
|
||||
assert resolved.authority == "substrate_realizer"
|
||||
assert resolved.surface == "The evidence supports the hypothesis."
|
||||
|
||||
|
||||
def test_pending_graph_withholds_substrate_authority_even_if_useful() -> None:
|
||||
"""Pending slots mean substrate does not yet earn authority (bypass hazard path)."""
|
||||
def test_substrate_refused_without_assessment() -> None:
|
||||
"""Assessment=None fails conjugate competitor (fail-closed)."""
|
||||
g = _mk_grounded_graph()
|
||||
resolved = resolve_surface(
|
||||
response_surface="runtime",
|
||||
response_articulation_surface="runtime art",
|
||||
realized_surface="The evidence supports the hypothesis.",
|
||||
realizer_useful=True,
|
||||
gate_fired=False,
|
||||
proposition_graph=g,
|
||||
contract_assessment=None,
|
||||
)
|
||||
assert resolved.authority == "runtime"
|
||||
|
||||
|
||||
def test_pending_graph_withholds_substrate_even_if_conjugate_ok() -> None:
|
||||
g = _mk_pending_graph()
|
||||
resolved = resolve_surface(
|
||||
response_surface="runtime",
|
||||
|
|
@ -134,12 +196,27 @@ def test_pending_graph_withholds_substrate_authority_even_if_useful() -> None:
|
|||
realizer_useful=True,
|
||||
gate_fired=False,
|
||||
proposition_graph=g,
|
||||
contract_assessment=_closed_assessment(),
|
||||
)
|
||||
# Because not supreme, the old shim still fires for useful -> "realizer"
|
||||
# (transitional). The hazard is computed in the *pipeline* caller.
|
||||
# Forward fails (pending); conjugate ok → transitional realizer only
|
||||
assert resolved.authority == "realizer"
|
||||
|
||||
|
||||
def test_open_geometric_contract_refuses_substrate_and_realizer() -> None:
|
||||
g = _mk_grounded_graph()
|
||||
resolved = resolve_surface(
|
||||
response_surface="runtime",
|
||||
response_articulation_surface="runtime art",
|
||||
realized_surface="The evidence supports the hypothesis.",
|
||||
realizer_useful=True,
|
||||
gate_fired=False,
|
||||
proposition_graph=g,
|
||||
contract_assessment=_open_assessment(),
|
||||
)
|
||||
assert resolved.authority == "runtime"
|
||||
assert resolved.surface == "runtime"
|
||||
|
||||
|
||||
def test_gate_fired_still_blocks_substrate_even_for_grounded_graph() -> None:
|
||||
g = _mk_grounded_graph()
|
||||
resolved = resolve_surface(
|
||||
|
|
@ -149,6 +226,20 @@ def test_gate_fired_still_blocks_substrate_even_for_grounded_graph() -> None:
|
|||
realizer_useful=True,
|
||||
gate_fired=True,
|
||||
proposition_graph=g,
|
||||
contract_assessment=_closed_assessment(),
|
||||
)
|
||||
assert resolved.authority == "runtime"
|
||||
assert resolved.surface == "I don't have field coordinates for that yet."
|
||||
|
||||
|
||||
def test_dual_competitors_helpers() -> None:
|
||||
g = _mk_grounded_graph()
|
||||
closed = _closed_assessment()
|
||||
open_a = _open_assessment()
|
||||
assert _forward_surface_ok(g, closed) is True
|
||||
assert _conjugate_coherence_ok(closed) is True
|
||||
assert _substrate_supreme(g, closed) is True
|
||||
assert _conjugate_coherence_ok(None) is False
|
||||
assert _conjugate_coherence_ok(open_a) is False
|
||||
assert _substrate_supreme(g, open_a) is False
|
||||
assert _forward_surface_ok(_mk_pending_graph(), closed) is False
|
||||
|
|
|
|||
Loading…
Reference in a new issue