core/tests/test_realize_oov.py
Shay be2d4b487e feat(realize): R1c + OOV — binding_graph substrate and OOV subjects
Generalizes what REALIZE accepts, on the structural-key foundation from #592.

R1c — binding_graph / arithmetic realize:
- `realize_quantitative(QuantComprehension | Refusal, ctx)` realizes a comprehended
  arithmetic structure (its admissibility-checked binding_graph) as a SPECULATIVE
  record with `structure_kind="binding_graph"` and a span-free `structure_key` over
  symbols/facts/equations. The only wrong=0 guard needed is the `Refusal` check —
  factless input is already a Refusal upstream (the fact-count gate would be vacuous).
- Extracts the shared `_realize_structured` write path so meaning_graph and
  binding_graph share ONE wrong=0 dedup/store point (the `.store` call stays in the
  INV-21-allowlisted realize.py).

OOV — lift the in-vocab subject gate:
- R0 declined OOV subjects on the mistaken belief that OOV grounding is
  non-deterministic. It is deterministic and reboot-stable, and #591 makes it
  injective. Correctness rests on the structural key, not the versor, so OOV subjects
  now realize normally. The "side-effect-free" comment is corrected: probe_ingest of
  an OOV token mutates the shared vocab via a session-scoped `insert_transient` that
  is NOT serialized into the snapshot, so reboot-stability rests on the vault record.

Honesty: the binding_graph entities (alice, the synthesized `total`) are symbolic/OOV
so the placement versor is deterministic-GIVEN-session-state, NOT subject-determined;
reboot-stability is carried by the Shape B+ snapshot of the exact bytes, and
distinctness by structural recall — never the (possibly colliding) metric. SPECULATIVE
always; versor_condition<1e-6 + exact CGA recall preserved; no parallel learning path.

Tests: test_realize_r1c_binding_graph.py (8) + test_realize_oov.py (6, incl. a
fresh-vocab reboot proving stability rests on the vault record not the transient) +
test_realize_r0.py oov test flipped to realize. Green: 35 realize + smoke locally.
2026-06-06 06:16:21 -07:00

119 lines
5.1 KiB
Python

"""REALIZE — OOV subjects are realizable (the in-vocab gate is lifted).
R0 declined OOV subjects on the (mistaken) belief that OOV grounding is
non-deterministic. It is in fact deterministic and reboot-stable, and #591 makes it
injective. These tests pin the consumer half: an OOV subject realizes a normal
SPECULATIVE record, distinct OOV facts stay distinct, and the fact survives reboot —
crucially via the VAULT RECORD, not the (session-scoped, snapshot-excluded) vocab
transient. They assert STRUCTURAL distinctness / stability (names + content_hash +
restored bytes), which holds regardless of whether the versor collides — versor
injectivity itself is #591's own test.
"""
from __future__ import annotations
import pytest
from algebra.versor import versor_condition
from chat.runtime import ChatRuntime
from generate.meaning_graph.reader import comprehend
from generate.realize import NotRealized, Realized, realize_comprehension, recall_realized
from session.context import SessionContext
_HIGH_INTERVAL = 10**9
@pytest.fixture(scope="module")
def vocab_persona():
rt = ChatRuntime(no_load_state=True)
return rt._context.vocab, rt._context.persona
def _ctx(vocab_persona) -> SessionContext:
vocab, persona = vocab_persona
return SessionContext(vocab=vocab, persona=persona, vault_reproject_interval=_HIGH_INTERVAL)
def _realize(text: str, ctx: SessionContext):
return realize_comprehension(comprehend(text), ctx)
def test_oov_subject_realizes(vocab_persona) -> None:
ctx = _ctx(vocab_persona)
res = _realize("Rhea is a raven.", ctx) # "rhea"/"raven" are OOV
assert isinstance(res, Realized) and res.created is True
assert res.record.relation_arguments == ("rhea", "raven")
assert res.record.epistemic_status == "speculative"
got = recall_realized(ctx, subject="rhea")
assert len(got) == 1 and got[0].content_hash == res.record.content_hash
def test_distinct_oov_subjects_stay_distinct(vocab_persona) -> None:
# Even if the field versor were to collide (pre-#591 substrate), the structural
# key keeps distinct OOV facts distinct — correctness never rests on the versor.
ctx = _ctx(vocab_persona)
_realize("Rhea is a raven.", ctx)
_realize("Zorg is a planet.", ctx)
assert len(ctx.vault._metadata) == 2
assert len({m["structure_key"] for m in ctx.vault._metadata}) == 2
assert recall_realized(ctx, subject="rhea")[0].relation_arguments == ("rhea", "raven")
assert recall_realized(ctx, subject="zorg")[0].relation_arguments == ("zorg", "planet")
def test_oov_fact_is_idempotent(vocab_persona) -> None:
ctx = _ctx(vocab_persona)
first = _realize("Rhea is a raven.", ctx)
second = _realize("Rhea is a raven.", ctx)
assert isinstance(first, Realized) and first.created is True
assert isinstance(second, Realized) and second.created is False
assert len(ctx.vault._metadata) == 1
def test_oov_placement_deterministic_across_fresh_contexts(vocab_persona) -> None:
# OOV grounding is deterministic: the same OOV fact realized in two independent
# fresh contexts (same shared vocab) yields identical content_hash AND identical
# stored versor bytes.
a = _ctx(vocab_persona)
b = _ctx(vocab_persona)
ra = _realize("Rhea is a raven.", a)
rb = _realize("Rhea is a raven.", b)
assert isinstance(ra, Realized) and isinstance(rb, Realized)
assert ra.record.content_hash == rb.record.content_hash
va = a.vault._versors[ra.record.vault_index].tobytes()
vb = b.vault._versors[rb.record.vault_index].tobytes()
assert va == vb
def test_oov_fact_survives_reboot_into_a_FRESH_vocab(vocab_persona) -> None:
# The strongest reboot claim: restore into a context built on a DIFFERENT vocab
# instance (no "rhea" transient present) — the realized fact is still recalled
# structurally and its versor bytes are restored exactly. Proves reboot-stability
# rests on the VAULT RECORD, not on the session-scoped vocab transient.
ctx = _ctx(vocab_persona)
res = _realize("Rhea is a raven.", ctx)
assert isinstance(res, Realized)
pre_versor_bytes = ctx.vault._versors[res.record.vault_index].tobytes()
snap = ctx.snapshot()
fresh = ChatRuntime(no_load_state=True) # a brand-new vocab/persona surface
rebooted = SessionContext(
vocab=fresh._context.vocab,
persona=fresh._context.persona,
vault_reproject_interval=_HIGH_INTERVAL,
)
rebooted.restore(snap)
got = recall_realized(rebooted, subject="rhea")
assert len(got) == 1
assert got[0].content_hash == res.record.content_hash
post_versor = rebooted.vault._versors[got[0].vault_index]
assert post_versor.tobytes() == pre_versor_bytes # exact restore, no reprojection
assert versor_condition(post_versor) < 1e-6
def test_ineligible_oov_input_still_realizes_nothing(vocab_persona) -> None:
# Lifting the in-vocab gate does NOT loosen the other wrong=0 floors.
ctx = _ctx(vocab_persona)
assert isinstance(_realize("Is rhea a raven?", ctx), NotRealized) # query
assert isinstance(_realize("Rhea is a raven. Zorg is a planet.", ctx), NotRealized) # multi
assert len(ctx.vault._metadata) == 0