feat(reasoning): field-wedge foundation — f64 embedding, lineage firewall, INV-27

Phase 0 of the field-reasoner wedge — net hardening regardless of the
experiment's outcome.

- algebra/cga.py: embed_point gains a dtype kwarg (f32 default byte-unchanged;
  cl41.geometric_product already preserves f64) + read_scalar_e1 projective
  dehomogenization read-back (weight-invariant; correct for dilations, where a
  raw distance-from-origin is wrong) + EMBED_EXACT_MAX pinned magnitude ceiling.
  f32 silently collapsed integer coordinates past ~1e4.
- core/reasoning/evidence.py: verify_tier2_agreement now keys independence on a
  reader_lineage pathway token (refuses SAME_READER_LINEAGE), replacing the
  label-only len(set(signatures))<2 check a single reader could satisfy by
  relabeling. reader_lineage is excluded from canonical serialization, so the
  entailment trace_hash is unchanged.
- tests INV-27: transitive reader-disjointness over TIER2_READER_PATHWAYS makes
  the lineage check load-bearing (distinct lineage => proven import-disjoint
  pathway). The two seeded readers share zero transitive first-party modules.

Green: smoke 87, algebra 82, cognition 121, 53 architectural invariants,
reasoning/deductive/r1 50; 16 new f64-exactness tests; zero regressions.
This commit is contained in:
Shay 2026-06-04 19:22:16 -07:00
parent 991be784fa
commit 568face63e
8 changed files with 429 additions and 11 deletions

View file

@ -1,5 +1,13 @@
from .cl41 import geometric_product, reverse, grade_project, scalar_part, norm_squared, basis_vector
from .versor import versor_apply, normalize_to_versor, versor_condition
from .cga import cga_inner, outer_product, is_null, null_project, embed_point
from .cga import (
EMBED_EXACT_MAX,
cga_inner,
outer_product,
is_null,
null_project,
embed_point,
read_scalar_e1,
)
from .holonomy import holonomy_encode, holonomy_similarity
from .rotor import word_transition_rotor

View file

@ -26,6 +26,14 @@ from .cl41 import geometric_product, scalar_part, basis_vector, N_COMPONENTS
_E4_IDX = 4
_E5_IDX = 5
# Pinned magnitude ceiling for f64-exact embedding + read-back (Phase 0A).
# Below this bound, ``embed_point(..., dtype=np.float64)`` round-trips integer
# coordinates exactly through ``read_scalar_e1`` and the conformal distance metric
# stays exact (proven in tests/test_cga_f64_exactness.py). The field-reasoner reader
# REFUSES any quantity whose magnitude exceeds this bound; the refusal lives in the
# reader — this module only states the bound. Generous vs GSM8K (quantities ~< 1e5).
EMBED_EXACT_MAX: int = 1_000_000
def cga_inner(X: np.ndarray, Y: np.ndarray) -> float:
"""
@ -62,18 +70,25 @@ def null_project(X: np.ndarray) -> np.ndarray:
return embed_point(euclidean)
def embed_point(x: np.ndarray) -> np.ndarray:
def embed_point(x: np.ndarray, *, dtype: "np.typing.DTypeLike" = np.float32) -> np.ndarray:
"""
Embed a Euclidean point x in R^3 into the CGA null cone.
X = x + n_o + 0.5|x|^2 n_inf,
where n_o = 0.5(e5-e4), n_inf = e4+e5.
``dtype`` defaults to ``float32`` so every existing caller is byte-unchanged.
The field-reasoner reader passes ``dtype=np.float64`` to get an exact embedding:
``geometric_product`` already preserves float64 (``np.result_type``), so the
only thing that forced f32 was this construction. f32 silently collapses the
``n_o`` weight past ~1e4 (the ``0.5|x|^2`` terms lose the ``±1``); f64 keeps it
exact up to :data:`EMBED_EXACT_MAX` (see tests/test_cga_f64_exactness.py).
"""
x = np.asarray(x, dtype=np.float32)
x = np.asarray(x, dtype=dtype)
assert len(x) == 3, "embed_point expects a 3D vector"
x_sq = float(np.dot(x, x))
result = np.zeros(N_COMPONENTS, dtype=np.float32)
result = np.zeros(N_COMPONENTS, dtype=dtype)
result[1:4] = x
# n_o + 0.5|x|^2 n_inf
@ -82,3 +97,26 @@ def embed_point(x: np.ndarray) -> np.ndarray:
result[_E4_IDX] = 0.5 * (x_sq - 1.0)
result[_E5_IDX] = 0.5 * (x_sq + 1.0)
return result
def read_scalar_e1(X: np.ndarray) -> float:
"""Projective dehomogenization on the e1 axis — the exact, weight-invariant
read-back of a scalar coordinate from a (possibly dilated) conformal point.
A point at coordinate ``v`` on the e1 number line embeds as
``X = v*e1 + n_o + 0.5 v^2 n_inf``; a uniform conformal dilation by ``k``
scales the whole null vector. The coordinate is recovered as
``e1_coefficient / n_o_weight`` where the n_o weight is ``X[e5] - X[e4]``
(== 1 for an un-dilated point), so any dilation weight divides out. This is
the correct read-back for weight-changing operators; a raw distance-from-origin
is wrong for them.
Raises ``ValueError`` on a degenerate (zero) n_o weight a point at infinity
or an f32 weight-collapse rather than returning a silently wrong value.
"""
no_weight = float(X[_E5_IDX] - X[_E4_IDX])
if no_weight == 0.0:
raise ValueError(
"read_scalar_e1: degenerate n_o weight (point at infinity or f32 collapse)"
)
return float(X[1]) / no_weight

View file

@ -7,6 +7,7 @@ from core.reasoning.evidence import (
DUPLICATE_STRUCTURAL_SIGNATURE,
INSUFFICIENT_EVIDENCE,
MISSING_COMMITMENT,
SAME_READER_LINEAGE,
TIER2_VERIFIED,
EvidenceBundle,
OperatorEvidence,
@ -23,6 +24,7 @@ __all__ = [
"DUPLICATE_STRUCTURAL_SIGNATURE",
"INSUFFICIENT_EVIDENCE",
"MISSING_COMMITMENT",
"SAME_READER_LINEAGE",
"TIER2_VERIFIED",
"EvidenceBundle",
"OperatorEvidence",

View file

@ -47,6 +47,7 @@ def evidence_from_entailment_trace(trace: EntailmentTrace) -> OperatorEvidence:
check_keys=check_keys,
commitment_key=commitment_key,
structural_signature=structural_signature,
reader_lineage="proof_chain.entail",
payload={"entailment_trace": trace.as_dict()},
)
@ -93,6 +94,7 @@ def evidence_from_math_solution(
check_keys=(trace_hash, trace.graph_canonical_hash),
commitment_key=commitment_key,
structural_signature=structural_signature,
reader_lineage="math_problem_graph.solve_verify",
payload={
"answer_entity": trace.answer_entity,
"answer_unit": trace.answer_unit,

View file

@ -20,6 +20,7 @@ INSUFFICIENT_EVIDENCE: Final[str] = "insufficient_evidence"
DUPLICATE_STRUCTURAL_SIGNATURE: Final[str] = "duplicate_structural_signature"
COMMITMENT_DISAGREEMENT: Final[str] = "commitment_disagreement"
MISSING_COMMITMENT: Final[str] = "missing_commitment"
SAME_READER_LINEAGE: Final[str] = "same_reader_lineage"
TIER2_REASONS: Final[frozenset[str]] = frozenset({
TIER2_VERIFIED,
@ -27,6 +28,7 @@ TIER2_REASONS: Final[frozenset[str]] = frozenset({
DUPLICATE_STRUCTURAL_SIGNATURE,
COMMITMENT_DISAGREEMENT,
MISSING_COMMITMENT,
SAME_READER_LINEAGE,
})
@ -74,6 +76,17 @@ class OperatorEvidence:
check_keys: tuple[str, ...]
commitment_key: str
structural_signature: str
# reader_lineage — the mechanistic identity of the decoding PATHWAY that
# produced this evidence (e.g. "proof_chain.entail"). The Tier-2 gate keys
# independence on this, not on the cosmetic structural_signature string, so a
# single reader cannot self-verify by relabeling. Deliberately EXCLUDED from
# ``as_dict``/``canonical_json`` (and therefore the evidence/trace hash): it is
# gate-routing provenance, not replayable evidence content, and including it
# would perturb the entailment trace_hash with no replay benefit. The
# static guarantee that distinct lineages are import-disjoint (cannot share a
# decoding pathway) is enforced by the architectural reader-disjointness
# invariant, not by this string alone.
reader_lineage: str = ""
payload: Mapping[str, Any] = field(default_factory=dict)
def __post_init__(self) -> None:
@ -83,6 +96,7 @@ class OperatorEvidence:
"outcome",
"reason",
"structural_signature",
"reader_lineage",
):
value = getattr(self, field_name)
if not isinstance(value, str) or not value.strip():
@ -146,6 +160,7 @@ class Tier2Verdict:
commitment_key: str = ""
evidence_hash: str = ""
structural_signatures: tuple[str, ...] = ()
reader_lineages: tuple[str, ...] = ()
def __post_init__(self) -> None:
if self.reason not in TIER2_REASONS:
@ -155,6 +170,11 @@ class Tier2Verdict:
"structural_signatures",
tuple(str(s) for s in self.structural_signatures),
)
object.__setattr__(
self,
"reader_lineages",
tuple(str(s) for s in self.reader_lineages),
)
def as_dict(self) -> dict[str, Any]:
return {
@ -163,13 +183,23 @@ class Tier2Verdict:
"commitment_key": self.commitment_key,
"evidence_hash": self.evidence_hash,
"structural_signatures": list(self.structural_signatures),
"reader_lineages": list(self.reader_lineages),
}
def verify_tier2_agreement(
evidences: tuple[OperatorEvidence, ...] | list[OperatorEvidence],
) -> Tier2Verdict:
"""Require two distinct structures converging on one non-empty commitment."""
"""Require two **independently-read** structures converging on one commitment.
Independence is keyed on ``reader_lineage`` the decoding PATHWAY not on the
cosmetic ``structural_signature``. The same reader cannot self-verify by emitting
two differently-labeled signatures for one case: that is refused with
``SAME_READER_LINEAGE``. The static guarantee that distinct lineages are
import-disjoint (so distinct lineage no shared decoding pathway) is enforced
by the architectural reader-disjointness invariant; this gate enforces the
runtime half (distinct producing pathways + distinct structure + one commitment).
"""
bundle = EvidenceBundle(tuple(evidences))
if len(bundle.evidences) < 2:
return Tier2Verdict(False, INSUFFICIENT_EVIDENCE)
@ -177,13 +207,26 @@ def verify_tier2_agreement(
if any(not ev.commitment_key for ev in bundle.evidences):
return Tier2Verdict(False, MISSING_COMMITMENT, evidence_hash=bundle.evidence_hash)
lineages = tuple(ev.reader_lineage for ev in bundle.evidences)
signatures = tuple(ev.structural_signature for ev in bundle.evidences)
# Mechanistic independence firewall: at least two DISTINCT decoding pathways.
if len(set(lineages)) < 2:
return Tier2Verdict(
False,
SAME_READER_LINEAGE,
evidence_hash=bundle.evidence_hash,
structural_signatures=tuple(sorted(set(signatures))),
reader_lineages=tuple(sorted(set(lineages))),
)
if len(set(signatures)) < 2:
return Tier2Verdict(
False,
DUPLICATE_STRUCTURAL_SIGNATURE,
evidence_hash=bundle.evidence_hash,
structural_signatures=tuple(sorted(set(signatures))),
reader_lineages=tuple(sorted(set(lineages))),
)
commitments = Counter(ev.commitment_key for ev in bundle.evidences)
@ -194,6 +237,7 @@ def verify_tier2_agreement(
COMMITMENT_DISAGREEMENT,
evidence_hash=bundle.evidence_hash,
structural_signatures=tuple(sorted(set(signatures))),
reader_lineages=tuple(sorted(set(lineages))),
)
return Tier2Verdict(
@ -202,4 +246,5 @@ def verify_tier2_agreement(
commitment_key=shared[0],
evidence_hash=bundle.evidence_hash,
structural_signatures=tuple(sorted(set(signatures))),
reader_lineages=tuple(sorted(set(lineages))),
)

View file

@ -1392,3 +1392,195 @@ class TestINV26InterlinguaNeutrality:
"INV-26b predicate failed to detect the adapter's domain-reader "
"import — the core-isolation check is vacuous."
)
# ===========================================================================
# INV-27 Tier-2 reader disjointness — the two readers whose AGREEMENT the
# Tier-2 gate trusts must share no decoding pathway
# ===========================================================================
#
# Claim (docs/analysis/field-reasoner-wedge-design-and-falsification-2026-06-04
# .md §3.1; the decoration firewall):
#
# ``verify_tier2_agreement`` keys independence on ``reader_lineage`` — the
# decoding PATHWAY — not on the cosmetic ``structural_signature``. That runtime
# check is only load-bearing if "distinct lineage" actually means "no shared
# decoding pathway." A string alone cannot prove that. This invariant supplies
# the static proof: every reader that EMITS a Tier-2 lineage is registered with
# its entry module, and any two registered readers' TRANSITIVE first-party
# import sets are disjoint (modulo an explicit pure-data neutral allowlist).
#
# The old gate admitted on ``len(set(signatures)) < 2`` — a label test that a
# single reader could satisfy by relabeling. The single-level INV-25 import
# check would also miss a helper that re-pulls a shared reader transitively;
# this check is TRANSITIVE.
#
# 27a Every ``reader_lineage="..."`` literal emitted in core/reasoning/adapters
# is registered in TIER2_READER_PATHWAYS (so its disjointness is proven).
# 27b Each registered reader module exists (drift guard).
# 27c Every pair of registered readers is transitively import-disjoint, except
# modules explicitly allowlisted as pure-data neutral meeting points.
# 27d Non-vacuity: the disjointness predicate flags a genuinely-shared pair and
# the neutral allowlist genuinely clears one — proving 27c can fail.
import dataclasses as _dataclasses
# Top-level first-party package roots. An imported module whose first dotted
# component is one of these is project code (a potential shared decoding pathway);
# stdlib and third-party (numpy, ...) are not.
_FIRST_PARTY_ROOTS: frozenset[str] = frozenset({
"generate", "core", "algebra", "field", "language_packs", "vault", "chat",
"teaching", "sensorium", "calibration", "evals", "ingest", "recognition",
"formation", "morphology", "vocab", "session", "contemplation", "persona",
"alignment", "probe", "core_ingest", "core_rs",
})
@_dataclasses.dataclass(frozen=True)
class Tier2Reader:
"""A reader whose evidence the Tier-2 gate may treat as an independent vote."""
lineage: str # must equal the ``reader_lineage`` this reader emits
module: str # repo-relative path to the reader's entry module
# Readers whose agreement the Tier-2 gate is allowed to trust. Adding one is the
# reviewable seam: it asserts (and INV-27c proves) the new reader shares no
# decoding pathway with the others.
TIER2_READER_PATHWAYS: tuple[Tier2Reader, ...] = (
Tier2Reader("proof_chain.entail", "generate/proof_chain/entail.py"),
Tier2Reader("math_problem_graph.solve_verify", "generate/math_solver.py"),
)
# Pure-data / contract modules that are a NEUTRAL meeting point, not a shared
# decoding pathway: two readers may both import these without their agreement
# becoming common-mode. Every entry must be parser/solver-free (frozen data or
# pure algebra). EMPTY today — the current readers share nothing; the field
# reader (Phase W) will add ``generate.binding_graph.model`` here, with review.
TIER2_NEUTRAL_MODULES: frozenset[str] = frozenset()
def _is_first_party(mod: str) -> bool:
return mod.split(".")[0] in _FIRST_PARTY_ROOTS
def _resolve_module(mod: str) -> Path | None:
base = _REPO_ROOT / mod.replace(".", "/")
if (f := base.with_suffix(".py")).is_file():
return f
if (pkg := base / "__init__.py").is_file():
return pkg
return None
def _transitive_first_party_imports(entry_module: str) -> set[str]:
"""Every first-party module reachable from ``entry_module`` via imports.
Follows ``import``/``from ... import`` edges through first-party modules only,
so a reader that pulls a shared comprehension helper three hops deep is still
caught unlike the single-level :func:`_module_imports`.
"""
seen: set[str] = set()
stack = [entry_module]
while stack:
mod = stack.pop()
if mod in seen:
continue
path = _resolve_module(mod)
if path is None:
continue
seen.add(mod)
for imported in _module_imports(path):
if _is_first_party(imported) and imported not in seen:
stack.append(imported)
return seen
def _shared_first_party(a: set[str], b: set[str], neutral: frozenset[str]) -> set[str]:
"""First-party modules both sets import, minus the neutral allowlist."""
return (a & b) - set(neutral)
def _module_name_of(rel_path: str) -> str:
stem = rel_path[:-3] if rel_path.endswith(".py") else rel_path
return stem.replace("/", ".")
class TestINV27Tier2ReaderDisjointness:
"""The two readers whose agreement the Tier-2 gate trusts share no decoding
pathway so ``verify_tier2_agreement``'s lineage check is load-bearing."""
def test_emitted_lineages_are_registered(self):
"""27a — every reader_lineage a producer emits is registered, so its
disjointness is actually proven below (not merely asserted by a string)."""
adapters = _REPO_ROOT / "core" / "reasoning" / "adapters.py"
tree = ast.parse(adapters.read_text())
emitted: set[str] = set()
for node in ast.walk(tree):
if isinstance(node, ast.Call):
for kw in node.keywords:
if kw.arg == "reader_lineage" and isinstance(kw.value, ast.Constant):
if isinstance(kw.value.value, str):
emitted.add(kw.value.value)
registered = {r.lineage for r in TIER2_READER_PATHWAYS}
unregistered = sorted(emitted - registered)
assert not unregistered, (
f"Reader(s) emit unregistered Tier-2 lineage(s): {unregistered}. "
"Register them in TIER2_READER_PATHWAYS so INV-27c proves they share "
"no decoding pathway, or the gate's independence check is unbacked."
)
def test_registered_reader_modules_exist(self):
"""27b — drift guard: a registered module that moved makes 27c vacuous."""
missing = [r.module for r in TIER2_READER_PATHWAYS
if not (_REPO_ROOT / r.module).is_file()]
assert not missing, (
f"Registered Tier-2 reader module(s) not found: {missing}. "
"Update TIER2_READER_PATHWAYS."
)
def test_registered_readers_are_pairwise_import_disjoint(self):
"""27c — the load-bearing static guarantee. Any two readers the gate may
treat as independent votes import no first-party module in common (except
explicit neutral pure-data modules). Distinct lineage disjoint pathway."""
transitive = {
r.lineage: _transitive_first_party_imports(_module_name_of(r.module))
for r in TIER2_READER_PATHWAYS
}
offenders: list[str] = []
readers = list(TIER2_READER_PATHWAYS)
for i in range(len(readers)):
for j in range(i + 1, len(readers)):
a, b = readers[i], readers[j]
shared = _shared_first_party(
transitive[a.lineage], transitive[b.lineage], TIER2_NEUTRAL_MODULES
)
if shared:
offenders.append(
f"{a.lineage}{b.lineage} share {sorted(shared)}"
)
assert not offenders, (
"Tier-2 readers the gate trusts as independent share a decoding "
"pathway:\n " + "\n ".join(offenders)
+ "\n\nTheir agreement would be common-mode, not independent (the "
"GSM8K blind spot). Re-implement one independently, or — if the shared "
"module is genuinely pure data — add it to TIER2_NEUTRAL_MODULES with "
"a justification that it is parser/solver-free."
)
def test_disjointness_predicate_is_non_vacuous(self):
"""27d — prove 27c can fail and that the neutral allowlist genuinely
clears a shared module (CLAUDE.md schema-defined proof obligation)."""
a = {"generate.reader_a", "generate.shared_parser", "algebra.versor"}
b = {"generate.reader_b", "generate.shared_parser"}
# A genuinely shared first-party module is flagged.
assert _shared_first_party(a, b, frozenset()) == {"generate.shared_parser"}
# Allowlisting that module as neutral clears it.
assert _shared_first_party(a, b, frozenset({"generate.shared_parser"})) == set()
# The transitive walker really follows edges: math_solver reaches the
# problem-graph module it is built on (a multi-hop first-party import).
ms = _transitive_first_party_imports("generate.math_solver")
assert "generate.math_problem_graph" in ms, (
"transitive walker did not follow math_solver -> math_problem_graph; "
"the disjointness proof would miss deep shared readers."
)

View file

@ -0,0 +1,112 @@
"""Phase 0A — f64-exact conformal embedding + projective read-back + pinned ceiling.
The field-reasoner wedge encodes quantities as conformal points on the e1 number
line and reads the answer back by *projective dehomogenization* the only exact
read-back for weight-changing (dilation) operators. ``embed_point`` was f32-hardcoded
(``algebra/cga.py``), which silently destroys integers past ~1e4: at v=12345 the f32
``n_o`` weight collapses to 0 and the read-back is unusable.
These tests pin three contracts:
1. ``embed_point``'s f32 default is byte-unchanged (no existing caller regresses).
2. The new ``dtype=np.float64`` path + ``read_scalar_e1`` recover integer coordinates
**exactly** across the whole admissible band, where f32 already fails.
3. ``EMBED_EXACT_MAX`` is the pinned magnitude ceiling: exactness is asserted up to it;
the field reader refuses above it (the refusal lives in the reader, not here).
"""
from __future__ import annotations
import numpy as np
import pytest
from algebra.cga import (
EMBED_EXACT_MAX,
cga_inner,
embed_point,
read_scalar_e1,
)
def _e1(v: float, dtype: "np.typing.DTypeLike" = np.float64) -> np.ndarray:
"""Embed a scalar coordinate on the e1 axis."""
return embed_point(np.array([v, 0.0, 0.0]), dtype=dtype)
# --- contract 1: f32 default is byte-unchanged -----------------------------
def test_embed_point_f32_default_unchanged():
"""The default path stays float32 and byte-identical to the prior impl."""
x = np.array([1.0, 2.0, 3.0], dtype=np.float32)
X = embed_point(x)
assert X.dtype == np.float32
# Prior closed-form: result[1:4]=x, e4=0.5(|x|^2-1), e5=0.5(|x|^2+1).
x_sq = float(np.dot(x, x)) # 14.0
assert X[1] == np.float32(1.0)
assert X[2] == np.float32(2.0)
assert X[3] == np.float32(3.0)
assert X[4] == np.float32(0.5 * (x_sq - 1.0))
assert X[5] == np.float32(0.5 * (x_sq + 1.0))
# --- contract 2: f64 exact read-back where f32 fails -----------------------
@pytest.mark.parametrize("v", [0, 1, 7, 42, 103, 300, 9999, 12345, 100000, 1000000])
def test_read_scalar_e1_exact_f64(v):
"""Projective dehomogenization recovers the integer coordinate exactly in f64."""
X = _e1(float(v), dtype=np.float64)
assert read_scalar_e1(X) == float(v)
def test_f32_readback_fails_where_f64_succeeds():
"""The motivating hazard: f32 cannot round-trip a mid-size integer; f64 can.
A meaningfully-failing guard if this passes under f32 the f64 work is moot.
"""
v = 12345.0
f64 = read_scalar_e1(_e1(v, dtype=np.float64))
assert f64 == v
Xf32 = _e1(v, dtype=np.float32)
denom = float(Xf32[5] - Xf32[4]) # n_o weight collapses toward 0 in f32
assert denom != 1.0 # the f32 weight is already wrong at this scale
def test_dilation_weighted_point_readback():
"""Read-back is exact for a *weighted* (dilated) null vector, not just unit weight.
A dilation about the origin by factor k scales the whole null vector; the e1
coordinate must come back as k*v via the e1/n_o-weight ratio, never as a raw
distance-from-origin.
"""
v, k = 2.0, 4.0
X = _e1(v, dtype=np.float64)
Xw = (k * X).astype(np.float64) # uniform conformal weight k
assert read_scalar_e1(Xw) == v # projective: weight divides out
# --- contract 3: the pinned ceiling ----------------------------------------
def test_embed_exact_max_is_pinned_and_generous():
"""The ceiling is a concrete int, comfortably above any GSM8K quantity."""
assert isinstance(EMBED_EXACT_MAX, int)
assert EMBED_EXACT_MAX >= 1_000_000
def test_distance_exact_within_ceiling():
"""The conformal distance metric stays exact for integer pairs up to the ceiling.
cga_inner(embed(a), embed(b)) = -1/2 (a-b)^2, computed in f64.
"""
for a, b in [(0, 1), (3, 7), (100, 103), (0, EMBED_EXACT_MAX)]:
inner = cga_inner(_e1(float(a)), _e1(float(b)))
expected = -0.5 * (a - b) ** 2
assert inner == expected, f"a={a} b={b}: {inner} != {expected}"
def test_embedded_f64_point_is_null():
"""f64 embedding still lands on the null cone."""
X = _e1(123.0, dtype=np.float64)
assert abs(cga_inner(X, X)) < 1e-6

View file

@ -12,6 +12,7 @@ from core.reasoning import (
COMMITMENT_DISAGREEMENT,
DUPLICATE_STRUCTURAL_SIGNATURE,
MISSING_COMMITMENT,
SAME_READER_LINEAGE,
TIER2_VERIFIED,
EvidenceBundle,
OperatorEvidence,
@ -24,6 +25,7 @@ def _ev(
signature: str = "shape-a",
commitment: str = "answer:42",
outcome: str = "verified",
lineage: str = "reader-a",
) -> OperatorEvidence:
return OperatorEvidence(
domain="mathematics_logic",
@ -34,6 +36,7 @@ def _ev(
check_keys=("check-a",),
commitment_key=commitment,
structural_signature=signature,
reader_lineage=lineage,
payload={"nested": {"values": [1, 2, "x"]}},
)
@ -64,19 +67,35 @@ def test_evidence_bundle_hash_is_ordered_and_stable() -> None:
def test_tier2_verifies_two_distinct_structures_same_commitment() -> None:
verdict = verify_tier2_agreement((
_ev(signature="shape-a"),
_ev(signature="shape-b"),
_ev(signature="shape-a", lineage="reader-a"),
_ev(signature="shape-b", lineage="reader-b"),
))
assert verdict.verified is True
assert verdict.reason == TIER2_VERIFIED
assert verdict.commitment_key == "answer:42"
assert verdict.structural_signatures == ("shape-a", "shape-b")
assert verdict.reader_lineages == ("reader-a", "reader-b")
def test_tier2_refuses_same_reader_lineage() -> None:
"""The decoration firewall: one reader cannot self-verify by relabeling its
structural signature. Two evidences from the SAME decoding pathway are refused
even when their structural_signatures differ and the commitment agrees.
Meaningfully-failing guard: under the old label-only check this admitted.
"""
verdict = verify_tier2_agreement((
_ev(signature="shape-a", lineage="one-reader"),
_ev(signature="shape-b", lineage="one-reader"),
))
assert verdict.verified is False
assert verdict.reason == SAME_READER_LINEAGE
def test_tier2_refuses_duplicate_signature() -> None:
verdict = verify_tier2_agreement((
_ev(signature="same"),
_ev(signature="same"),
_ev(signature="same", lineage="reader-a"),
_ev(signature="same", lineage="reader-b"),
))
assert verdict.verified is False
assert verdict.reason == DUPLICATE_STRUCTURAL_SIGNATURE
@ -84,8 +103,8 @@ def test_tier2_refuses_duplicate_signature() -> None:
def test_tier2_refuses_disagreeing_commitments() -> None:
verdict = verify_tier2_agreement((
_ev(signature="shape-a", commitment="answer:42"),
_ev(signature="shape-b", commitment="answer:41"),
_ev(signature="shape-a", commitment="answer:42", lineage="reader-a"),
_ev(signature="shape-b", commitment="answer:41", lineage="reader-b"),
))
assert verdict.verified is False
assert verdict.reason == COMMITMENT_DISAGREEMENT