- aborist/qa/verify.py: three strategies tried in sequence. quote uses
sequential pairing (1st & 2nd `"`, 3rd & 4th, ...) which eliminates
the phantom inter-pair captures regex pairing produced on adjacent
quote pairs like `"title" prose "quote"`. span checks bullet/sentence
lines verbatim. entity matches multi-word proper nouns; gated by
policy ∈ {strict, hybrid, drop, proximity}. Default proximity
promotes to STRICT only when N=3 verified entities cluster within
W=300 chars in source — separates structural grounding (cast list,
infobox) from incidental mention (scattered plot summary).
- aborist/store.py: schema CHECK now `('STRICT','HYBRID','UNGROUNDED')`.
Migration helper rebuilds legacy `('STRICT','HYBRID','VISUAL')`
tables via temp-table copy, translating VISUAL → UNGROUNDED in the
SELECT. Idempotent — DDL inspection skips the rebuild on already-
migrated DBs.
- aborist/cli.py: new `aborist reclassify` re-runs the verifier
against existing live records under the current entity policy; no
LLM calls. --compare runs all four policies side-by-side, --dry-run
reports transitions without writing. Cold-source records skipped.
One providence_reclassify audit event per changed row.
- AuditMode.UNGROUNDED replaces VISUAL across search backend, FTS5,
test fixtures, CLAUDE.md. The substrate (Merkle-AGI) name was
about FOR-style visualization; in the RAG layer the semantic is
"no recoverable grounding," so the label now says that.
DEFAULT_QUERY_POLICY gains entity_policy + entity_proximity_n +
entity_proximity_window so any tuning folds into governance_policy_hash
and invalidates cache cleanly.
52 lines
1.6 KiB
Python
52 lines
1.6 KiB
Python
"""Search backend ABC + Hit dataclass with explicit audit mode.
|
|
|
|
Every search hit carries an `audit_mode` so callers never overclaim. Aborist
|
|
adapts the Merkle-AGI v7 audit-mode trichotomy to the RAG layer:
|
|
- STRICT — Merkle-verified evidence: every claim cited verbatim against
|
|
the source-content tree.
|
|
- HYBRID — partial / mixed evidence: some claims source-grounded, others
|
|
emerged from training. Cache or search hit is partially trusted.
|
|
- UNGROUNDED — no recoverable proof of grounding. Keyword (FTS5) hits land
|
|
here by default; LLM answers fall here when no double-quoted
|
|
span, sentence, or proper-noun phrase verifies against context.
|
|
Substrate name was VISUAL (no formal guarantees attached); we
|
|
renamed to UNGROUNDED so the RAG semantic is explicit.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import enum
|
|
import sqlite3
|
|
from abc import ABC, abstractmethod
|
|
from dataclasses import dataclass
|
|
|
|
|
|
class AuditMode(str, enum.Enum):
|
|
STRICT = "STRICT"
|
|
HYBRID = "HYBRID"
|
|
UNGROUNDED = "UNGROUNDED"
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class Hit:
|
|
document_root: str
|
|
document_uri: str
|
|
chunk_idx: int
|
|
snippet: str
|
|
score: float
|
|
audit_mode: AuditMode
|
|
title: str | None = None
|
|
|
|
|
|
class SearchBackend(ABC):
|
|
"""A search hook over the chunk store."""
|
|
|
|
name: str
|
|
audit_mode: AuditMode # default mode this backend reports
|
|
|
|
def __init__(self, conn: sqlite3.Connection):
|
|
self.conn = conn
|
|
|
|
@abstractmethod
|
|
def search(self, query: str, limit: int = 20) -> list[Hit]:
|
|
...
|