diff --git a/tests/test_architectural_invariants.py b/tests/test_architectural_invariants.py index cfcaa8c3..208feb6b 100644 --- a/tests/test_architectural_invariants.py +++ b/tests/test_architectural_invariants.py @@ -935,6 +935,12 @@ VAULT_RECALL_SITES: dict[str, str] = { "generate/stream.py": "EVIDENCE_TELEMETRY", "session/context.py": "RECOGNITION", # generic delegate; callers categorize "vault/store.py": "RECOGNITION", # self-references in helpers/docstrings + # Vault P2: the workbench rehydrates the persisted vault and runs the real + # recall purely as read-only OPERATOR inspection evidence (the "Exact CGA + # Recall" inspector panel). It is not CORE's user-facing articulation + # surface and shapes no claims, so unfiltered recall is correct and + # faithful (each hit's epistemic_status is shown verbatim). + "workbench/readers.py": "EVIDENCE_TELEMETRY", } VALID_RECALL_ROLES: frozenset[str] = frozenset({ @@ -962,7 +968,16 @@ def _file_has_vault_recall_call(path: Path) -> bool: func.attr if isinstance(func, ast.Attribute) else func.id if isinstance(func, ast.Name) else "" ) - if func_name == "VaultStore": + # Factory classmethods (e.g. ``VaultStore.from_dict(...)``) construct + # a real VaultStore too — bind the target so a later ``.recall`` on it + # is still detected. Without this, recall on a rehydrated store would + # silently escape the registry (Vault P2 read-substrate addition). + is_vaultstore_factory = ( + isinstance(func, ast.Attribute) + and isinstance(func.value, ast.Name) + and func.value.id == "VaultStore" + ) + if func_name == "VaultStore" or is_vaultstore_factory: for target in node.targets: if isinstance(target, ast.Name): vault_bindings.add(target.id) diff --git a/tests/test_workbench_vault_recall_evidence.py b/tests/test_workbench_vault_recall_evidence.py new file mode 100644 index 00000000..9a58195b --- /dev/null +++ b/tests/test_workbench_vault_recall_evidence.py @@ -0,0 +1,146 @@ +"""Vault P2 — exact-CGA recall evidence (read-only). + +The recall endpoint proves a persisted vault entry is recallable by CORE's +*actual* exact CGA machinery: it rehydrates the persisted ``VaultStore`` +(bit-exact versors, no reprojection) and runs the real ``VaultStore.recall`` +using the entry's own stored versor as the query. These tests fail under the +specific violations the surface must never commit: + +- claiming evidence when no persisted snapshot exists (must 501); +- accepting a caller-controlled index out of range / non-integer (must 404); +- losing the self-recall proof (the entry must recall itself); +- leaking ``recall``'s ``+inf`` self-match sentinel into the JSON (the score + must be the genuine finite ``cga_inner``); +- mutating the persisted file (the surface is read-only); +- non-determinism across identical reads. +""" + +from __future__ import annotations + +import json +import math +from pathlib import Path + +import numpy as np +import pytest + +from teaching.epistemic import EpistemicStatus +from vault.store import VaultStore +from workbench import readers +from workbench.api import WorkbenchApi +from workbench.schemas import to_data + + +def _build_vault(n: int = 3) -> VaultStore: + """A real vault of ``n`` distinct 32-dim (Cl(4,1)) versors.""" + store = VaultStore(reproject_interval=0) + for i in range(n): + f = np.zeros(32, dtype=np.float32) + f[0] = 1.0 + f[i + 1] = 0.25 * (i + 1) + store.store(f, {"turn": i, "role": "assistant"}, epistemic_status=EpistemicStatus.COHERENT) + return store + + +def _persist(tmp_path: Path, monkeypatch: pytest.MonkeyPatch, store: VaultStore | None) -> Path: + engine_state = tmp_path / "engine_state" + engine_state.mkdir(exist_ok=True) + path = engine_state / "session_state.json" + if store is not None: + path.write_text(json.dumps({"vault": store.to_dict()}, sort_keys=True), encoding="utf-8") + monkeypatch.setattr(readers, "ENGINE_STATE_ROOT", engine_state) + return path + + +def test_absent_snapshot_is_evidence_unavailable( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + _persist(tmp_path, monkeypatch, store=None) # no file written + with pytest.raises(readers.EvidenceUnavailableError): + readers.vault_entry_recall(0) + + +@pytest.mark.parametrize("bad_index", [99, -1]) +def test_out_of_range_index_is_not_found( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch, bad_index: int +) -> None: + _persist(tmp_path, monkeypatch, _build_vault(3)) + with pytest.raises(FileNotFoundError): + readers.vault_entry_recall(bad_index) + + +def test_entry_recalls_itself_by_exact_byte_identity( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + _persist(tmp_path, monkeypatch, _build_vault(3)) + result = readers.vault_entry_recall(1) + + assert result.self_hit_found is True + assert result.self_hit_rank == 0 # exact self-match promoted ahead of metric ranking + assert result.hits, "recall returned no hits" + top = result.hits[0] + assert top.entry_index == 1 + assert top.exact_self_match is True + # The query digest is the same content-addressed digest the entry carries. + assert result.query_versor_digest == readers.list_vault_entries()[1].versor_digest + assert top.versor_digest == result.query_versor_digest + + +def test_score_is_finite_exact_cga_never_the_inf_sentinel( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + _persist(tmp_path, monkeypatch, _build_vault(3)) + result = readers.vault_entry_recall(0) + + for hit in result.hits: + assert math.isfinite(hit.cga_inner), "recall's +inf self-match sentinel leaked into the score" + # And the whole payload survives strict JSON (no Infinity / NaN). + json.dumps(to_data(result), allow_nan=False) + + +def test_exact_cga_flags_are_pinned(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: + _persist(tmp_path, monkeypatch, _build_vault(2)) + result = readers.vault_entry_recall(0) + assert result.exact_cga is True + assert result.approximate is False + + +def test_recall_is_deterministic(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: + _persist(tmp_path, monkeypatch, _build_vault(3)) + first = to_data(readers.vault_entry_recall(2)) + second = to_data(readers.vault_entry_recall(2)) + assert first == second + + +def test_recall_does_not_mutate_the_persisted_file( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + path = _persist(tmp_path, monkeypatch, _build_vault(3)) + before = path.read_bytes() + readers.vault_entry_recall(0) + assert path.read_bytes() == before + + +def test_api_route_status_codes(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None: + _persist(tmp_path, monkeypatch, _build_vault(2)) + api = WorkbenchApi() + + ok = api.handle("GET", "/vault/entries/0/recall") + assert ok.status == 200 + assert ok.payload["ok"] is True + assert ok.payload["data"]["exact_cga"] is True + assert ok.payload["data"]["approximate"] is False + assert ok.payload["data"]["self_hit_found"] is True + + assert api.handle("GET", "/vault/entries/99/recall").status == 404 + assert api.handle("GET", "/vault/entries/not-an-int/recall").status == 404 + + +def test_api_route_absent_snapshot_is_501( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch +) -> None: + monkeypatch.setattr(readers, "ENGINE_STATE_ROOT", tmp_path / "engine_state") + api = WorkbenchApi() + response = api.handle("GET", "/vault/entries/0/recall") + assert response.status == 501 + assert response.payload["error"]["code"] == "evidence_unavailable" diff --git a/workbench-ui/src/api/client.ts b/workbench-ui/src/api/client.ts index e075fdae..5c126dcc 100644 --- a/workbench-ui/src/api/client.ts +++ b/workbench-ui/src/api/client.ts @@ -24,6 +24,7 @@ import type { LogosAlignmentRow, VaultSummary, VaultEntry, + VaultRecall, CalibrationClass, ServingMetrics, CognitivePipelineRecord, @@ -362,6 +363,12 @@ export async function fetchVaultEntries(limit?: number, offset?: number): Promis return envelope.items; } +export async function fetchVaultEntryRecall(entryIndex: number): Promise { + return apiFetch( + `/vault/entries/${encodeURIComponent(String(entryIndex))}/recall`, + ); +} + export async function fetchCalibrationClasses(): Promise { const envelope = await apiFetch>("/calibration/classes"); return envelope.items; diff --git a/workbench-ui/src/api/queries.ts b/workbench-ui/src/api/queries.ts index ee98182e..337709b1 100644 --- a/workbench-ui/src/api/queries.ts +++ b/workbench-ui/src/api/queries.ts @@ -28,6 +28,7 @@ import { fetchLogosPackAlignment, fetchVaultSummary, fetchVaultEntries, + fetchVaultEntryRecall, fetchCalibrationClasses, fetchServingMetrics, fetchTraceTurn, @@ -68,6 +69,7 @@ import type { LogosAlignmentRow, VaultSummary, VaultEntry, + VaultRecall, CalibrationClass, ServingMetrics, CognitivePipelineRecord, @@ -504,6 +506,17 @@ export function useVaultEntries(enabled: boolean, limit?: number, offset?: numbe }); } +export function useVaultEntryRecall(entryIndex?: number | null) { + return useQuery({ + queryKey: ["api", "vault", "recall", entryIndex ?? null], + queryFn: () => fetchVaultEntryRecall(entryIndex as number), + enabled: typeof entryIndex === "number", + retry: false, + staleTime: 30_000, + refetchOnWindowFocus: false, + }); +} + export function useCalibrationClasses() { return useQuery({ queryKey: ["api", "calibration", "classes"], diff --git a/workbench-ui/src/app/RightInspector.test.tsx b/workbench-ui/src/app/RightInspector.test.tsx index 74452afe..8b451d8e 100644 --- a/workbench-ui/src/app/RightInspector.test.tsx +++ b/workbench-ui/src/app/RightInspector.test.tsx @@ -1,8 +1,10 @@ import { act, fireEvent, render, screen } from "@testing-library/react"; +import { QueryClientProvider } from "@tanstack/react-query"; import { useEffect } from "react"; import { EvidenceProvider, useEvidenceSubject } from "./evidenceContext"; import { RightInspector } from "./RightInspector"; -import type { ChatTurnResult, ProposalDetail } from "../types/api"; +import { createTestQueryClient } from "../test/createTestQueryClient"; +import type { ChatTurnResult, ProposalDetail, VaultRecall } from "../types/api"; const MOCK_TURN: ChatTurnResult = { prompt: "What is alpha?", @@ -238,3 +240,117 @@ describe("RightInspector", () => { } }); }); + +const RECALL_FIXTURE: VaultRecall = { + entry_index: 7, + query_versor_digest: "sha256:qqqqqqqqqqqq", + top_k: 5, + hits: [ + { + entry_index: 7, + rank: 0, + cga_inner: 1.2e-7, + exact_self_match: true, + epistemic_status: "coherent", + epistemic_state: "decoded", + versor_digest: "sha256:qqqqqqqqqqqq", + }, + { + entry_index: 3, + rank: 1, + cga_inner: 0.4212, + exact_self_match: false, + epistemic_status: "coherent", + epistemic_state: "decoded", + versor_digest: "sha256:zzzzzzzzzzzz", + }, + ], + self_hit_rank: 0, + self_hit_found: true, + exact_cga: true, + approximate: false, + source_path: "engine_state/session_state.json", +}; + +function stubRecallFetch() { + vi.stubGlobal( + "fetch", + vi.fn((input: unknown) => { + const path = new URL(String(input)).pathname; + if (path === "/vault/entries/7/recall") { + return Promise.resolve({ + json: () => Promise.resolve({ ok: true, generated_at: "now", data: RECALL_FIXTURE }), + }); + } + return Promise.resolve({ + json: () => + Promise.resolve({ + ok: false, + generated_at: "now", + error: { code: "not_found", message: `unexpected ${path}` }, + }), + }); + }), + ); +} + +function renderVaultInspector() { + function SetVaultEntry() { + const { setSubject } = useEvidenceSubject(); + useEffect(() => { + setSubject({ + kind: "vault_entry", + entryIndex: 7, + data: { + entry_index: 7, + epistemic_status: "coherent", + epistemic_state: "decoded", + versor_digest: "sha256:qqqqqqqqqqqq", + metadata: { turn: 3, role: "assistant" }, + }, + }); + }, [setSubject]); + return ; + } + return render( + + + + + , + ); +} + +describe("VaultEntryInspector — exact CGA recall", () => { + afterEach(() => { + vi.unstubAllGlobals(); + }); + + it("keeps recall opt-in: collapsed by default, no fetch, no banned language", () => { + stubRecallFetch(); + renderVaultInspector(); + // The disclosure is present but the recall body has not mounted. + expect(screen.getByText("Show exact CGA recall")).toBeInTheDocument(); + expect(screen.queryByText(/recalls itself/)).not.toBeInTheDocument(); + expect(fetch).not.toHaveBeenCalled(); + // Exact-recall doctrine holds on the collapsed surface too. + expect(screen.queryByText(/similarity|relevance|cosine|approximat|score/i)).not.toBeInTheDocument(); + }); + + it("expands to show exact CGA recall evidence — self-recall proof, never a similarity proxy", async () => { + stubRecallFetch(); + renderVaultInspector(); + + fireEvent.click(screen.getByText("Show exact CGA recall")); + + // The self-recall proof: the entry recalls itself at rank 0 as an exact match. + expect(await screen.findByText(/recalls itself at rank 0/)).toBeInTheDocument(); + expect(screen.getByText(/exact match/)).toBeInTheDocument(); + // The exact primitive is named; no fabricated similarity/relevance/score. + expect(screen.getAllByText(/cga_inner/).length).toBeGreaterThan(0); + expect(screen.getByText("query_versor")).toBeInTheDocument(); + expect( + screen.queryByText(/similarity|relevance|cosine|approximat|score|\bann\b/i), + ).not.toBeInTheDocument(); + }); +}); diff --git a/workbench-ui/src/app/RightInspector.tsx b/workbench-ui/src/app/RightInspector.tsx index 56e6b282..0d6f1227 100644 --- a/workbench-ui/src/app/RightInspector.tsx +++ b/workbench-ui/src/app/RightInspector.tsx @@ -15,6 +15,7 @@ import { type SafetyVerdict, } from "../design/components/badges"; import type { LeewayEvidence } from "../types/api"; +import { useVaultEntryRecall } from "../api/queries"; // Rendered when a subject was restored from a URL but its detail has not // loaded in this session yet. An honest absence state, not a guess. @@ -574,6 +575,98 @@ function VaultEntryInspector({ subject }: { subject: Extract ) : null} + + + ); +} + +function formatCgaInner(value: number): string { + if (!Number.isFinite(value)) return "—"; + return Math.abs(value) < 1e-4 ? value.toExponential(2) : value.toPrecision(5); +} + +// Exact-CGA recall evidence for a selected vault entry. Collapsed by default so +// the read-only recall fetch is opt-in (the hook lives in VaultRecallBody, which +// only mounts when expanded). Doctrine: "exact CGA recall" / cga_inner only — +// never similarity / relevance / cosine / ANN / approximate. +function VaultRecallSection({ entryIndex }: { entryIndex: number }) { + const [open, setOpen] = useState(false); + return ( +
+ + {open ? : null} +
+ ); +} + +function VaultRecallBody({ entryIndex }: { entryIndex: number }) { + const recall = useVaultEntryRecall(entryIndex); + + if (recall.isPending) { + return

Running exact CGA recall…

; + } + if (recall.isError || !recall.data) { + return ( +

+ {recall.error?.message ?? "Exact CGA recall evidence is unavailable for this entry."} +

+ ); + } + + const data = recall.data; + const handleRows: MetadataRow[] = [ + ...(data.query_versor_digest + ? [{ key: "query_versor", value: data.query_versor_digest, mono: true, copyable: true } as const] + : []), + { + key: "self_recall", + value: data.self_hit_found + ? `recalls itself at rank ${data.self_hit_rank}` + : "not within top results", + }, + { key: "exact_cga", value: data.exact_cga ? "yes" : "no" }, + ]; + + return ( +
+

+ CORE's exact cga_inner recall over the persisted + vault snapshot, querying with this entry's own stored versor. Read-only — the live + runtime is untouched. +

+ +

+ Rank is CORE's actual recall order. An exact byte-identical self-match is promoted to + the front — stored versors are CGA null vectors, so the self{" "} + cga_inner is ~0; identity is proven by exact + byte-equality, not a maximal value. +

+
    + {data.hits.map((hit) => ( +
  • + #{hit.rank} + + vault:{hit.entry_index} + {hit.exact_self_match ? ( + (exact match) + ) : null} + + + cga_inner {formatCgaInner(hit.cga_inner)} + +
  • + ))} +
); } diff --git a/workbench-ui/src/types/api.ts b/workbench-ui/src/types/api.ts index e54ce523..724e1666 100644 --- a/workbench-ui/src/types/api.ts +++ b/workbench-ui/src/types/api.ts @@ -722,6 +722,35 @@ export interface VaultEntry { versor_digest: string | null; } +// One hit from CORE's exact CGA recall scan over the persisted vault. +// `cga_inner` is the genuine exact inner product (never a similarity proxy). +// `exact_self_match` flags a byte-identical entry, promoted ahead of metric +// ranking (stored versors are CGA null vectors → ~0 self inner-product). +export interface VaultRecallHit { + entry_index: number; + rank: number; + cga_inner: number; + exact_self_match: boolean; + epistemic_status: string; + epistemic_state: string; + versor_digest: string | null; +} + +// Read-only proof that a persisted vault entry is recallable by CORE's actual +// exact CGA machinery. `exact_cga` is always true / `approximate` always false: +// this is the exact `cga_inner` scan, never ANN / cosine / approximate ranking. +export interface VaultRecall { + entry_index: number; + query_versor_digest: string | null; + top_k: number; + hits: VaultRecallHit[]; + self_hit_rank: number | null; + self_hit_found: boolean; + exact_cga: boolean; + approximate: boolean; + source_path: string; +} + // Wave M Phase B — calibrated-learning / serving-discipline read views. // reliability_floor + the license verdicts are computed by the engine // (core.reliability_gate), never the workbench. diff --git a/workbench/api.py b/workbench/api.py index 1edd1e2b..a95dc9ff 100644 --- a/workbench/api.py +++ b/workbench/api.py @@ -290,6 +290,24 @@ class WorkbenchApi: } ), ) + if ( + method == "GET" + and path.startswith("/vault/entries/") + and path.endswith("/recall") + ): + raw_index = unquote( + path.removeprefix("/vault/entries/").removesuffix("/recall").strip("/") + ) + try: + recall_index = int(raw_index) + except ValueError: + return ApiResponse( + 404, error("not_found", f"vault entry not found: {raw_index}") + ) + # An out-of-range index raises FileNotFoundError -> 404; an absent + # persisted snapshot raises EvidenceUnavailableError -> 501 (both via + # handle()). Read-only: the live runtime and the file are untouched. + return ApiResponse(200, ok(readers.vault_entry_recall(recall_index))) if method == "GET" and path == "/demos": return ApiResponse(200, ok({"items": readers.list_demos()})) if method == "GET" and path == "/tour": diff --git a/workbench/readers.py b/workbench/readers.py index 1461241c..1edbfe37 100644 --- a/workbench/readers.py +++ b/workbench/readers.py @@ -50,6 +50,8 @@ from workbench.schemas import ( RunTurnRef, RuntimeStatus, VaultEntry, + VaultRecall, + VaultRecallHit, VaultSummary, ) from workbench.lived_life import lived_life_from_payload, missing_lived_life @@ -1958,6 +1960,104 @@ def list_vault_entries(*, limit: int = 100, offset: int = 0) -> list[VaultEntry] return _page(entries, limit=limit, offset=offset) +# Fixed recall breadth: a small, deterministic top-k is enough to prove a +# persisted entry is recallable by exact CGA inner product. Not a tunable knob +# — keeps the read endpoint deterministic and its surface minimal. +VAULT_RECALL_TOP_K = 5 + + +def vault_entry_recall(entry_index: int, *, top_k: int = VAULT_RECALL_TOP_K) -> VaultRecall: + """Prove a persisted vault entry is recallable by CORE's exact CGA machinery. + + Read-only evidence: rehydrates the persisted ``VaultStore`` from + ``engine_state/session_state.json`` (bit-exact versors via the array codec; + the load path performs no reprojection / normalization — restoring bytes is + not a normalization site, per ``VaultStore.from_dict``) and runs the real + ``VaultStore.recall`` using the selected entry's own stored versor as the + query. Recall is the exact ``cga_inner`` scan — never approximate, never an + ANN index. + + The persisted file is never written and the live runtime is never touched. + The raw versor never crosses the boundary: only content-addressed digests + and the finite exact ``cga_inner`` value per hit are emitted. ``recall``'s + exact-self-match sentinel (``+inf``) is replaced here by the genuine, + finite, JSON-safe ``cga_inner`` plus an ``exact_self_match`` flag. + + Trust boundary: ``entry_index`` is caller-controlled (URL path). A + non-integer / out-of-range index raises ``FileNotFoundError`` (404); an + absent persisted snapshot raises ``EvidenceUnavailableError`` (501). + """ + import math + + from algebra import cga_inner + from core.array_codec import decode_array + from vault.store import VaultStore + + path, vault = _load_vault_snapshot() + versors_raw = vault.get("versors") + metadata_raw = vault.get("metadata") + if not isinstance(versors_raw, list) or not isinstance(metadata_raw, list): + raise EvidenceUnavailableError( + "vault evidence unavailable: snapshot has no recallable versors" + ) + entry_count = min(len(versors_raw), len(metadata_raw)) + if ( + isinstance(entry_index, bool) + or not isinstance(entry_index, int) + or not (0 <= entry_index < entry_count) + ): + raise FileNotFoundError(f"vault entry not found: {entry_index}") + + def _digest_for(index: int) -> str | None: + if 0 <= index < len(versors_raw): + return _sha256_bytes(_canonical_json_bytes(versors_raw[index])) + return None + + store = VaultStore.from_dict(vault) + query = decode_array(versors_raw[entry_index]) + raw_hits = store.recall(query, top_k=top_k) + + hits: list[VaultRecallHit] = [] + self_hit_rank: int | None = None + for rank, hit in enumerate(raw_hits): + idx = int(hit["index"]) + # The genuine exact inner product — finite and JSON-safe. recall promotes + # exact byte-identical matches with a +inf sentinel; the real cga_inner + # (≈0 for null-vector self inner-products) is reported instead, and the + # exact_self_match flag carries the byte-identity fact. + inner = float(cga_inner(query, hit["versor"])) + meta = ( + metadata_raw[idx] + if 0 <= idx < len(metadata_raw) and isinstance(metadata_raw[idx], dict) + else {} + ) + hits.append( + VaultRecallHit( + entry_index=idx, + rank=rank, + cga_inner=inner, + exact_self_match=math.isinf(hit["score"]), + epistemic_status=str(meta.get("epistemic_status") or "unknown"), + epistemic_state=str(meta.get("epistemic_state") or "unknown"), + versor_digest=_digest_for(idx), + ) + ) + if idx == entry_index and self_hit_rank is None: + self_hit_rank = rank + + return VaultRecall( + entry_index=entry_index, + query_versor_digest=_digest_for(entry_index), + top_k=top_k, + hits=hits, + self_hit_rank=self_hit_rank, + self_hit_found=self_hit_rank is not None, + exact_cga=True, + approximate=False, + source_path=_display_path(path), + ) + + def run_safe_eval_lane( lane_name: str, *, diff --git a/workbench/schemas.py b/workbench/schemas.py index 8eefe8c6..7a895fda 100644 --- a/workbench/schemas.py +++ b/workbench/schemas.py @@ -915,6 +915,46 @@ class VaultEntry: versor_digest: str | None +@dataclass(frozen=True, slots=True) +class VaultRecallHit: + """One result of CORE's exact CGA recall scan over the persisted vault. + + ``cga_inner`` is the genuine, finite exact inner product (never a + similarity proxy). ``exact_self_match`` flags an entry recalled by exact + byte-identity (``recall`` promotes those ahead of metric ranking — stored + versors are CGA null vectors, so their self inner-product is ~0; identity + is established by byte-equality, not a maximal value). The raw versor never + crosses the boundary — only its content-addressed ``versor_digest``. + """ + + entry_index: int + rank: int + cga_inner: float + exact_self_match: bool + epistemic_status: str + epistemic_state: str + versor_digest: str | None + + +@dataclass(frozen=True, slots=True) +class VaultRecall: + """Read-only proof that a persisted vault entry is recallable by CORE's + actual exact CGA machinery (``VaultStore.recall`` over rehydrated, bit-exact + versors). ``exact_cga`` is always True / ``approximate`` always False — this + surface is the exact ``cga_inner`` scan, never ANN / cosine / approximate. + """ + + entry_index: int + query_versor_digest: str | None + top_k: int + hits: list[VaultRecallHit] + self_hit_rank: int | None + self_hit_found: bool + exact_cga: bool + approximate: bool + source_path: str + + # --------------------------------------------------------------------------- # Wave M Phase B — calibrated-learning / serving-discipline read views. # The workbench computes none of these numbers: reliability_floor and the