From 43fcd08ce88e88a24fba24eb6d7a9cf13835c872 Mon Sep 17 00:00:00 2001 From: Shay Date: Sat, 6 Jun 2026 02:33:48 -0700 Subject: [PATCH] =?UTF-8?q?feat(realize):=20R0=20=E2=80=94=20one=20told=20?= =?UTF-8?q?fact=20becomes=20a=20SPECULATIVE,=20reboot-stable=20vault=20ent?= =?UTF-8?q?ry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit REALIZE roadmap Step 3, slice R0: the boundary that turns comprehension from an EVAL ARTIFACT into accumulating living knowledge. A comprehended declarative fact is integrated into the held self as a structured vault entry (versor, metadata) — NOT a new store — so it inherits exact cga_inner recall, EpistemicStatus stamping, and bit-exact Shape B+ persistence for free. Scope: docs/analysis/REALIZE-scope-2026-06-06.md. generate/realize/realize.py — realize_comprehension(Comprehension|Refusal, ctx) -> Realized(record, created) | NotRealized(reason): - eligibility: a Comprehension (not Refusal) with NO queries and EXACTLY ONE non-negated relation whose subject grounds IN-VOCABULARY. Everything else is a typed NotRealized with zero vault writes (wrong=0). - in-vocab-subject only: OOV grounding is non-deterministic across reboots (an empirically-confirmed substrate gap), so OOV subjects are declined in R0. - SPECULATIVE always (COHERENT is never a default — ADR-0021); provenance via MeaningSpan source_span + structure_canonical; content_hash + replay_hash via canonical-JSON SHA-256 (floats forbidden). - idempotency: dedup by content_hash within the session (exact-canonical, span-inclusive — safe direction only, never drops a distinct fact). - durable schema admits a 2nd substrate later via structure_kind/structure_canonical. - stores via the existing VaultStore.store path: no new embedder, no normalization (closure stays algebra/versor.py), no parallel learning path. Explicitly OUT of R0: COHERENT promotion, teaching-loop proposals, trace-folding, relation-space recall, the arithmetic/binding_graph path. tests/test_realize_r0.py (10) — eligibility (refusal/query/multi-relation/OOV all write nothing); record fields; idempotency (re-told fact doesn't grow the vault); SPECULATIVE status firewall (recall(min_status=COHERENT) excludes it); the falsifiable exit gate (told -> realize -> snapshot -> reboot -> recall: byte-exact content_hash + score + versor bytes, speculative, versor_condition<1e-6); and replay_hash re-derivable after reboot. Gate verified to BITE (COHERENT default, refusal-writes, reprojection-on-load all fail it). INV-21: generate/realize/realize.py added to ALLOWED_VAULT_WRITERS — a sanctioned writer (same VaultStore.store path, SPECULATIVE default, nothing on Refusal). Adversarially reviewed (3 lenses: invariants/wrong0/honesty, determinism/boundary, scope/adjustments) — no critical/high/medium findings; low/nit honesty wrinkles folded (state-dependent-placement wording, span-inclusive-dedup note, direct versor-bytes gate assert, replay_hash re-derivation test). 10 R0 + 90 smoke green; lane SHAs 8/9 (sole miss = public_demo env flake; deductive_logic + math_teaching unchanged -> no GSM8K coupling). --- generate/realize/__init__.py | 15 ++ generate/realize/realize.py | 189 ++++++++++++++++++++++++ tests/test_architectural_invariants.py | 5 + tests/test_realize_r0.py | 196 +++++++++++++++++++++++++ 4 files changed, 405 insertions(+) create mode 100644 generate/realize/__init__.py create mode 100644 generate/realize/realize.py create mode 100644 tests/test_realize_r0.py diff --git a/generate/realize/__init__.py b/generate/realize/__init__.py new file mode 100644 index 00000000..ce173ac6 --- /dev/null +++ b/generate/realize/__init__.py @@ -0,0 +1,15 @@ +"""REALIZE — integrate comprehended structure into the held self (roadmap Step 3).""" + +from generate.realize.realize import ( + NotRealized, + Realized, + RealizedRecord, + realize_comprehension, +) + +__all__ = [ + "NotRealized", + "Realized", + "RealizedRecord", + "realize_comprehension", +] diff --git a/generate/realize/realize.py b/generate/realize/realize.py new file mode 100644 index 00000000..832db312 --- /dev/null +++ b/generate/realize/realize.py @@ -0,0 +1,189 @@ +"""REALIZE slice R0 — one told fact becomes a realized vault entry. + +The boundary that turns comprehension from an EVAL ARTIFACT into accumulating living +knowledge: a comprehended declarative fact is integrated into the held self as a +SPECULATIVE, provenance-rich vault entry that survives reboot and recalls exactly. + +A realized record is NOT a new store — it is a structured vault entry +``(versor, metadata)`` so it inherits exact ``cga_inner`` recall, ``EpistemicStatus`` +stamping, and bit-exact Shape B+ persistence for free (see +``docs/analysis/REALIZE-scope-2026-06-06.md``). + +Slice R0 deliberately boring (everything else grows from this without corrupting the +field): one told fact, SPECULATIVE only, in-vocab subject only, single non-negated +declarative relation, dedup by content hash. Explicitly OUT of R0: COHERENT +promotion, teaching-loop proposals, the quantitative ``binding_graph`` path, +trace-folding, and relation-space recall. + +wrong=0 at this layer: a ``Refusal`` (or any ineligible / ungrounded input) realizes +NOTHING — it is returned as ``NotRealized(reason)``, never coerced into a vault entry. +""" + +from __future__ import annotations + +from dataclasses import dataclass + +import numpy as np + +from formation.hashing import sha256_of +from generate.meaning_graph.reader import Comprehension, Refusal +from session.context import SessionContext +from teaching.epistemic import EpistemicStatus + +# The known failure modes of the session embedding path (probe_ingest): +# RuntimeError on cross-turn versor-condition violation; Key/Index/ValueError on a +# degenerate grounding. Any of them is a clean no-op, never a crashed turn. +_GROUNDING_FAILURES = (RuntimeError, KeyError, IndexError, ValueError) + +#: R0 realizes only the neutral MeaningGraph substrate. The record shape already +#: admits a second substrate (the quantitative binding-graph) via ``structure_kind``. +_STRUCTURE_KIND_MEANING_GRAPH = "meaning_graph" + + +@dataclass(frozen=True, slots=True) +class RealizedRecord: + """The realized-knowledge record (mirrors the stored vault metadata).""" + + structure_kind: str + structure_canonical: str + relation_predicate: str + entity_names: tuple[str, ...] + source_span: str + content_hash: str + replay_hash: str + epistemic_status: str + tier: str + vault_index: int + + +@dataclass(frozen=True, slots=True) +class Realized: + """The fact is realized. ``created`` is False on an idempotent dedup hit + (the fact was already realized this session — no new vault entry written).""" + + record: RealizedRecord + created: bool + + +@dataclass(frozen=True, slots=True) +class NotRealized: + """Nothing was realized (no vault write). ``reason`` is for audit, not control.""" + + reason: str + + +def realize_comprehension( + comprehension: Comprehension | Refusal, ctx: SessionContext +) -> Realized | NotRealized: + """Realize a comprehended declarative fact into ``ctx``'s vault, or decline. + + Eligibility (R0): a ``Comprehension`` (not a ``Refusal``) with NO queries and + EXACTLY ONE non-negated relation whose subject argument grounds in-vocabulary. + Everything else is a typed ``NotRealized`` — no vault write (wrong=0). + """ + if isinstance(comprehension, Refusal): + return NotRealized("refusal") + if not isinstance(comprehension, Comprehension): + return NotRealized("not_a_comprehension") + if comprehension.queries: + return NotRealized("query_bearing") # a question is recall, not intake + + graph = comprehension.meaning_graph + if len(graph.relations) != 1: + return NotRealized("not_single_relation") # multi-relation intake is ambiguous in R0 + rel = graph.relations[0] + if rel.negated: + return NotRealized("negated_relation") + if not rel.arguments: + return NotRealized("empty_relation") # defensive — arity>=1 by construction + + subject_id = rel.arguments[0] + entity = next((e for e in graph.entities if e.entity_id == subject_id), None) + if entity is None: + return NotRealized("ungrounded_subject") # defensive — graph invariant + + subject_token = entity.name + # In-vocab gate: OOV grounding is NOT reproducible across reboots, so an OOV + # subject cannot be realized deterministically yet (R0 scope; a substrate gap). + try: + ctx.vocab.index_of(subject_token) + except (KeyError, IndexError): + return NotRealized("oov_subject") + + # Side-effect-free embedding (no state/vault/referent mutation). Closure stays + # algebra/versor.py's job — REALIZE adds no normalization. NOTE: the field point + # composes with the CURRENT session state, so placement is deterministic for a + # GIVEN session state (the fact is realized at the held self's current field + # position), not purely subject-determined. + try: + field_state = ctx.probe_ingest([subject_token]) + except _GROUNDING_FAILURES: + return NotRealized("grounding_failed") + versor = np.asarray(field_state.F, dtype=np.float32) + + structure_canonical = graph.to_canonical_string() + source_span = rel.span.to_canonical_string() + content_hash = sha256_of(structure_canonical) + status = EpistemicStatus.SPECULATIVE # COHERENT is never a default (ADR-0021) + replay_hash = sha256_of( + { + "content_hash": content_hash, + "source_span": source_span, + "epistemic_status": status.value, + } + ) + entity_names = tuple(sorted(e.name for e in graph.entities)) + + # Idempotency: a re-told fact (same content_hash) does not grow the vault. Dedup + # is exact-canonical (the content_hash is span-INCLUSIVE), so the SAFE direction + # only — it never drops a genuinely distinct fact; it may fail to collapse the + # same fact re-stated at a different offset (a span-free key is a later R1 option). + # ``vault._metadata`` is read directly here (no public iterator exists yet); + # this is the established project pattern and an intentional boundary for R0. + for idx, meta in enumerate(ctx.vault._metadata): + if meta.get("kind") == "realized" and meta.get("content_hash") == content_hash: + return Realized(record=_record_from_metadata(meta, idx), created=False) + + metadata = { + "kind": "realized", + "structure_kind": _STRUCTURE_KIND_MEANING_GRAPH, + "structure_canonical": structure_canonical, + "relation_predicate": rel.predicate, + "entity_names": list(entity_names), + "source_span": source_span, + "content_hash": content_hash, + "replay_hash": replay_hash, + "tier": "session", + } + vault_index = ctx.vault.store(versor, metadata, epistemic_status=status) + return Realized( + record=RealizedRecord( + structure_kind=_STRUCTURE_KIND_MEANING_GRAPH, + structure_canonical=structure_canonical, + relation_predicate=rel.predicate, + entity_names=entity_names, + source_span=source_span, + content_hash=content_hash, + replay_hash=replay_hash, + epistemic_status=status.value, + tier="session", + vault_index=vault_index, + ), + created=True, + ) + + +def _record_from_metadata(meta: dict, idx: int) -> RealizedRecord: + """Reconstruct a RealizedRecord from a stored vault metadata dict.""" + return RealizedRecord( + structure_kind=meta.get("structure_kind", _STRUCTURE_KIND_MEANING_GRAPH), + structure_canonical=meta.get("structure_canonical", ""), + relation_predicate=meta.get("relation_predicate", ""), + entity_names=tuple(meta.get("entity_names", [])), + source_span=meta.get("source_span", ""), + content_hash=meta.get("content_hash", ""), + replay_hash=meta.get("replay_hash", ""), + epistemic_status=meta.get("epistemic_status", "speculative"), + tier=meta.get("tier", "session"), + vault_index=idx, + ) diff --git a/tests/test_architectural_invariants.py b/tests/test_architectural_invariants.py index c89cff9e..c4b845b1 100644 --- a/tests/test_architectural_invariants.py +++ b/tests/test_architectural_invariants.py @@ -643,6 +643,11 @@ ALLOWED_VAULT_WRITERS: frozenset[str] = frozenset({ "session/context.py", "vault/store.py", "generate/proposition.py", + # REALIZE (roadmap Step 3): integrates a comprehended declarative fact into the + # held self as a SPECULATIVE, provenance-rich vault entry. A sanctioned writer — + # it stores via the same VaultStore.store path (no parallel memory), defaults to + # SPECULATIVE (never COHERENT), and writes nothing on a Refusal (wrong=0). + "generate/realize/realize.py", }) PROJECT_ROOT_FOR_INV21 = Path(__file__).resolve().parent.parent diff --git a/tests/test_realize_r0.py b/tests/test_realize_r0.py new file mode 100644 index 00000000..82102099 --- /dev/null +++ b/tests/test_realize_r0.py @@ -0,0 +1,196 @@ +"""REALIZE slice R0 — one told fact survives reboot and recalls exactly, SPECULATIVE. + +The load-bearing exit gate (test_r0_exit_gate_*) is falsifiable: it FAILS if REALIZE +is decoration (a Refusal that silently writes, a COHERENT default, a missing +provenance span, a reprojection mutating the versor on load, or a non-deterministic +placement). The other tests pin eligibility, idempotency, and the SPECULATIVE +status firewall (remembered != evidence). +""" + +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 +from session.context import SessionContext +from teaching.epistemic import EpistemicStatus + +_HIGH_INTERVAL = 10**9 # never auto-reproject in R0 tests (adjustment: reproject boundary) + + +@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) + + +# --------------------------------------------------------------------------- # +# Eligibility — wrong=0: ineligible input realizes NOTHING (no vault write) +# --------------------------------------------------------------------------- # + + +def test_refusal_realizes_nothing(vocab_persona) -> None: + ctx = _ctx(vocab_persona) + res = _realize("The weather is nice today.", ctx) # comprehend -> Refusal + assert isinstance(res, NotRealized) and res.reason == "refusal" + assert len(ctx.vault._metadata) == 0 # no vault write + + +def test_query_bearing_realizes_nothing(vocab_persona) -> None: + ctx = _ctx(vocab_persona) + res = _realize("Is truth a concept?", ctx) # a question is recall, not intake + assert isinstance(res, NotRealized) and res.reason == "query_bearing" + assert len(ctx.vault._metadata) == 0 + + +def test_multi_relation_realizes_nothing(vocab_persona) -> None: + ctx = _ctx(vocab_persona) + res = _realize("Truth is a concept. Knowledge is a thought.", ctx) + assert isinstance(res, NotRealized) and res.reason == "not_single_relation" + assert len(ctx.vault._metadata) == 0 + + +def test_oov_subject_realizes_nothing(vocab_persona) -> None: + # "rhea" is out-of-vocabulary; OOV grounding is not reproducible across reboots, + # so R0 declines rather than realize a non-deterministic point. + ctx = _ctx(vocab_persona) + res = _realize("Rhea is a raven.", ctx) + assert isinstance(res, NotRealized) and res.reason == "oov_subject" + assert len(ctx.vault._metadata) == 0 + + +def test_single_in_vocab_declarative_is_realized(vocab_persona) -> None: + ctx = _ctx(vocab_persona) + res = _realize("Truth is a concept.", ctx) + assert isinstance(res, Realized) and res.created is True + r = res.record + assert r.structure_kind == "meaning_graph" + assert r.relation_predicate == "member" + assert r.epistemic_status == "speculative" # never COHERENT by default + assert r.tier == "session" + assert r.source_span # provenance present + assert r.content_hash and r.replay_hash + assert "truth" in r.entity_names and "concept" in r.entity_names + assert len(ctx.vault._metadata) == 1 + + +# --------------------------------------------------------------------------- # +# Idempotency — a re-told fact does not grow the vault (dedup by content_hash) +# --------------------------------------------------------------------------- # + + +def test_retold_fact_is_idempotent(vocab_persona) -> None: + ctx = _ctx(vocab_persona) + first = _realize("Truth is a concept.", ctx) + second = _realize("Truth is a concept.", ctx) + assert isinstance(first, Realized) and first.created is True + assert isinstance(second, Realized) and second.created is False # dedup hit + assert second.record.content_hash == first.record.content_hash + assert len(ctx.vault._metadata) == 1 # NOT grown + + +# --------------------------------------------------------------------------- # +# Status firewall — SPECULATIVE is candidate memory, NOT evidence +# --------------------------------------------------------------------------- # + + +def test_speculative_record_is_not_admitted_as_evidence(vocab_persona) -> None: + ctx = _ctx(vocab_persona) + res = _realize("Truth is a concept.", ctx) + assert isinstance(res, Realized) + query = ctx.probe_ingest(["truth"]).F + # default recall surfaces it as a CANDIDATE... + default_hits = ctx.vault.recall(query, top_k=5) + assert any(h["metadata"].get("kind") == "realized" for h in default_hits) + # ...but min_status=COHERENT must NOT return it (remembered != evidence). + coherent_hits = ctx.vault.recall(query, top_k=5, min_status=EpistemicStatus.COHERENT) + assert not any(h["metadata"].get("kind") == "realized" for h in coherent_hits) + + +# --------------------------------------------------------------------------- # +# Exit gate — told -> realize -> snapshot -> reboot -> recall, byte-exact +# --------------------------------------------------------------------------- # + + +def test_r0_exit_gate_survives_reboot_and_recalls_exactly(vocab_persona) -> None: + vocab, persona = vocab_persona + ctx = _ctx(vocab_persona) + + res = _realize("Truth is a concept.", ctx) + assert isinstance(res, Realized) and res.created + pre_query = ctx.probe_ingest(["truth"]).F + pre_hits = ctx.vault.recall(pre_query, top_k=5) + pre = next(h for h in pre_hits if h["metadata"].get("kind") == "realized") + pre_score = pre["score"] + pre_content_hash = pre["metadata"]["content_hash"] + pre_versor_bytes = pre["versor"].tobytes() + + # reboot: snapshot -> NEW context -> restore (no reprojection on load) + snap = ctx.snapshot() + rebooted = SessionContext(vocab=vocab, persona=persona, vault_reproject_interval=_HIGH_INTERVAL) + rebooted.restore(snap) + + post_query = rebooted.probe_ingest(["truth"]).F + post_hits = rebooted.vault.recall(post_query, top_k=5) + post = next(h for h in post_hits if h["metadata"].get("kind") == "realized") + + # content_hash byte-identical, recall score byte-identical (exact f32 restore) + assert post["metadata"]["content_hash"] == pre_content_hash + assert post["score"] == pre_score + assert post["metadata"]["epistemic_status"] == "speculative" + # the restored versor is byte-identical (DIRECT catch of any reprojection/ + # normalization on load) and still a valid versor. + assert post["versor"].tobytes() == pre_versor_bytes + assert versor_condition(post["versor"]) < 1e-6 + # provenance survived the reboot + assert post["metadata"]["source_span"] + + +def test_r0_replay_hash_is_rederivable_after_reboot(vocab_persona) -> None: + # The replay_hash is the determinism anchor: re-deriving it from the RESTORED + # metadata must reproduce the stored value byte-for-byte (closes the obligation + # that replay_hash is a real replay proof, not just asserted structure). + from formation.hashing import sha256_of + + vocab, persona = vocab_persona + ctx = _ctx(vocab_persona) + assert isinstance(_realize("Truth is a concept.", ctx), Realized) + + rebooted = SessionContext(vocab=vocab, persona=persona, vault_reproject_interval=_HIGH_INTERVAL) + rebooted.restore(ctx.snapshot()) + meta = next(m for m in rebooted.vault._metadata if m.get("kind") == "realized") + rederived = sha256_of( + { + "content_hash": meta["content_hash"], + "source_span": meta["source_span"], + "epistemic_status": meta["epistemic_status"], + } + ) + assert rederived == meta["replay_hash"] + + +def test_r0_placement_is_deterministic_across_fresh_contexts(vocab_persona) -> None: + # Realizing the SAME fact in two independent fresh contexts (same vocab) yields + # the identical content_hash AND identical stored versor bytes — guards + # idempotency + placement determinism (in-vocab subject). + a = _ctx(vocab_persona) + b = _ctx(vocab_persona) + ra = _realize("Truth is a concept.", a) + rb = _realize("Truth is a concept.", b) + assert isinstance(ra, Realized) and isinstance(rb, Realized) + assert ra.record.content_hash == rb.record.content_hash + va = a.vault.recall(a.probe_ingest(["truth"]).F, top_k=1)[0]["versor"] + vb = b.vault.recall(b.probe_ingest(["truth"]).F, top_k=1)[0]["versor"] + assert va.tobytes() == vb.tobytes()