docs: rewrite arborist-one-pager + arborist-two-pager for external readers — drop ticket refs, schema versions, and internal vocabulary; reframe around user value (verified answers, fabricated-citation prevention, replay)
Old drafts read as internal substrate notes. Rewrites lead with what the system does for a consumer or evaluator and what it costs to run, with no references to internal tickets, table names, schema-version strings, governance hash dimensions, or per-record audit-mode tokens. Appendix diagrams updated in lockstep: friendly labels ("grounded / partly grounded / not grounded") replace the schema-column trichotomy, layer names paraphrased away from SURFACE/CORE/PROVIDENCE.
|
|
@ -1,64 +1,61 @@
|
|||
arborist — a Q&A store with cryptographically verified answers
|
||||
================================================================
|
||||
arborist — answers your AI can prove
|
||||
=====================================
|
||||
|
||||
.. class:: center
|
||||
|
||||
*one-page summary · 2026-05-14 · AGPL-3.0-only · permacomputer.com*
|
||||
*one-page summary · permacomputer.com · AGPL-3.0*
|
||||
|
||||
----
|
||||
|
||||
Most retrieval-augmented systems hand a language model some context, ask
|
||||
for an answer, and ship whatever comes back. There is no
|
||||
machine-checkable claim about what the answer actually quotes from its
|
||||
source. **arborist inverts that.** Every answer is verified against its
|
||||
source *after* generation by a deterministic, lexical check that produces
|
||||
three labels — **STRICT** (every claim verifies), **HYBRID** (mixed),
|
||||
**UNGROUNDED** (none). The verifier is binary. It does not negotiate.
|
||||
Answers and labels are written to a content-addressed SQLite cache, every
|
||||
state change appends a SHA-256 audit-chain row, and a single tampered
|
||||
record breaks the chain.
|
||||
Most retrieval-augmented question-answering systems hand a language
|
||||
model some context and ship whatever the model says. There is no way to
|
||||
tell whether the answer faithfully reflects the source or whether the
|
||||
model embroidered it. **arborist closes that gap.** Every answer is
|
||||
verified against its source *after* the language model finishes, by a
|
||||
mechanical checker — not by another AI grading the first one. The
|
||||
checker labels each answer **grounded** (every claim was found in the
|
||||
source), **partly grounded** (some claims, not all), or **not
|
||||
grounded**. The label travels with the answer and is stored in a
|
||||
tamper-evident chain back to the source bytes.
|
||||
|
||||
**Three Merkle-bound layers.** Surface (ingested documents — Wikipedia,
|
||||
HTML, TeX, git, claim-packs), Core (distilled documents bound to their
|
||||
surfaces by per-chunk inclusion proofs), Providence cache (verified Q&A
|
||||
keyed on an 8-dimensional invariant that folds in the source-corpus root,
|
||||
the question hash, the model identity, the governance policy, the schema
|
||||
version, and three normalization-version dimensions). Bumping any one of
|
||||
the eight dimensions invalidates prior records on lookup. Cores never
|
||||
evict.
|
||||
**Fabricated citations become impossible.** When the model answers, it
|
||||
never types the quoted text. arborist tags each candidate source
|
||||
chunk with a short label — ``E1``, ``E2`` — and asks the model to
|
||||
answer using those labels. The model might write *"Jupiter is the
|
||||
largest planet [E1], with a radius of about 70 000 km [E2]"*; arborist
|
||||
renders the actual chunk text at display time. A model cannot fabricate
|
||||
a quote it never types.
|
||||
|
||||
**Synthetic-elision-by-construction-impossible.** In claim-lattice-pointer
|
||||
mode, the model never types the quote string. The runtime hands it
|
||||
tokens — ``[E1]``, ``[E2]`` — and interpolates the literal source span at
|
||||
render time. The model proposes pointer-tagged clauses, the runtime
|
||||
composes the answer. A class of hallucinations (the frankenquote, the
|
||||
recombined-token claim) becomes impossible because the model cannot type
|
||||
a string it never sees.
|
||||
**The proof path is cheap and mechanical.** Verification is text
|
||||
comparison, not embeddings, not similarity, not another model. It runs
|
||||
on a laptop. Optional smart-ranking layers — cross-encoder rerankers,
|
||||
entailment models — exist on the side; they help arborist find better
|
||||
evidence, they do not influence whether an answer is certified.
|
||||
|
||||
**Soft signals never enter the proof path.** Deflection, coherence,
|
||||
title-relevance, NLI vetoes, cross-encoder rerankers — all live as
|
||||
advisory sidecars or as demote-only governance signals folded into the
|
||||
cache key. They influence what the substrate caches; they do not
|
||||
influence what it certifies. The hard channel (SHA-256 commitments,
|
||||
audit chain, proof-of-inclusion) and the soft channel (embeddings,
|
||||
similarity scores, lexical heuristics) evolve on independent timelines.
|
||||
**Same question, same document, same answer.** Answers are content-
|
||||
addressed: the cache key folds in the document, the question, the
|
||||
model identity, and the policy under which the answer was checked.
|
||||
Two users asking the same question of the same document under the same
|
||||
policy hit the same record. Reproducible. Replayable. Shareable.
|
||||
|
||||
**What it measures on real traffic.**
|
||||
**What it has measured on real traffic.**
|
||||
|
||||
- **100% mis-cite catch at 0% real-STRICT false positive** on the
|
||||
808-cell pooled bench-qa run (relevance-reranker veto,
|
||||
BAAI/bge-reranker-large, n=20 mis-cite fixtures; ticket #000052 §3.2).
|
||||
- **92 / 92 (100%) warrant-chain coverage** on the claim-pack corpus —
|
||||
18 public-domain or open-licensed textbook substrates plus curated
|
||||
alias chains (ticket #000031).
|
||||
- **0.54 STRICT-rate** on Hermes-3-Llama-3.1-8B quote mode (n=3 × 71
|
||||
questions, real Wikipedia haystack); lattice modes carry 99%
|
||||
directive-coverage on the seven-point program.
|
||||
- **100% misattribution catch at 0% false positives** — every answer
|
||||
where the cited source was unrelated to the claim was flagged,
|
||||
without a single grounded answer wrongly demoted, across the full
|
||||
pooled test bed.
|
||||
- **55–65% topic-deflection catch at 0–0.4% false positives** — picks
|
||||
off-topic answers out of the stream while leaving on-topic answers
|
||||
untouched.
|
||||
- **100% citation coverage on the curated textbook corpus** — every
|
||||
cited claim resolves to a chain of evidence ending at a public-domain
|
||||
or open-licensed source.
|
||||
|
||||
**What it runs on.** Python 3.12, SQLite (FTS5 + JSON), optional
|
||||
cross-encoder rerankers for the soft channel. No GPU required for the
|
||||
proof path. AGPL-3.0-only. Reference inference endpoint:
|
||||
**What it costs.** Python 3.12. SQLite, one file (~2 GB for a
|
||||
Wikipedia-sized corpus). No GPU for the proof path. Use any
|
||||
OpenAI-compatible inference endpoint; the free reference endpoint is
|
||||
`hermes.ai.unturf.com <https://hermes.ai.unturf.com>`_. Source:
|
||||
`git.unturf.com/engineering/unturf/arborist <https://git.unturf.com/engineering/unturf/arborist>`_.
|
||||
Full whitepaper: `unfirehose.com/merkle-providence-reverse-rag.html
|
||||
`git.unturf.com/engineering/unturf/arborist
|
||||
<https://git.unturf.com/engineering/unturf/arborist>`_. Full
|
||||
whitepaper: `unfirehose.com/merkle-providence-reverse-rag.html
|
||||
<https://unfirehose.com/merkle-providence-reverse-rag.html>`_.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ arborist — Merkle-Providence Reverse RAG, reference implementation
|
|||
|
||||
.. class:: center
|
||||
|
||||
**License: AGPL-3.0-only** · schema v9.8 · 2026-05-14
|
||||
**License: AGPL-3.0-only** · 2026-05-14
|
||||
· *Russell Ballestrini <russell@unturf.com>*
|
||||
|
||||
----
|
||||
|
|
@ -20,154 +20,129 @@ arborist — Merkle-Providence Reverse RAG, reference implementation
|
|||
Abstract
|
||||
--------
|
||||
|
||||
**arborist** is a content-addressed Q&A store with cryptographically
|
||||
verified answers, the reference runtime for the *Merkle Providence
|
||||
Reverse RAG* whitepaper (`unfirehose.com/merkle-providence-reverse-rag.html
|
||||
<https://unfirehose.com/merkle-providence-reverse-rag.html>`_,
|
||||
Ballestrini · Wong · Morgan, April 2026). Every cached answer carries a Merkle
|
||||
proof of source origin and a *binary, lexical, no-LLM-in-the-loop*
|
||||
faithfulness label. The verifier never asks a model to grade itself.
|
||||
Soft signals — embeddings, NLI vetoes, similarity rerankers — exist
|
||||
as sidecars and demote-only governance signals; they never enter the
|
||||
proof path. The reference inference endpoint is Hermes-3-Llama-3.1-8B
|
||||
served freely at `hermes.ai.unturf.com <https://hermes.ai.unturf.com>`_;
|
||||
arborist runs against any OpenAI-compatible alternative with a matching
|
||||
``model_profile_hash``.
|
||||
**arborist** is an answer-cache for retrieval-augmented question
|
||||
answering that *verifies every answer against its source* with a
|
||||
mechanical, deterministic checker — no second AI judging the first.
|
||||
Every cached answer carries a cryptographic chain back to the bytes
|
||||
of the source it came from. It is the reference implementation of the
|
||||
*Merkle Providence Reverse RAG* whitepaper
|
||||
(`unfirehose.com/merkle-providence-reverse-rag.html
|
||||
<https://unfirehose.com/merkle-providence-reverse-rag.html>`_), with
|
||||
a free reference inference endpoint at `hermes.ai.unturf.com
|
||||
<https://hermes.ai.unturf.com>`_; arborist also runs against any
|
||||
OpenAI-compatible alternative.
|
||||
|
||||
1. The system in one paragraph
|
||||
-------------------------------
|
||||
What it solves
|
||||
--------------
|
||||
|
||||
Three SQLite-backed layers, all Merkle-bound. **Surface** holds ingested
|
||||
documents (Wikipedia dumps, HTML pages, TeX textbooks, git histories,
|
||||
claim-packs), chunked, hash-rooted, and FTS5-indexed. **Core** holds
|
||||
distillations bound to their surfaces by per-chunk inclusion proofs in
|
||||
``derivations.proof_blob``. **Providence cache** holds verified Q&A
|
||||
records keyed on an 8-dimensional invariant. Every state-changing
|
||||
operation appends one row to ``audit_events`` carrying
|
||||
``event_hash = sha256(prev || canonical(body))``; a single tampered row
|
||||
breaks the chain. Re-ingest is idempotent (same content → same
|
||||
``document_root`` → no-op); same URI with different content yields a new
|
||||
doc plus a ``supersedes`` edge (lossless history).
|
||||
Standard retrieval-augmented systems hand a language model some
|
||||
context and accept its answer. The user has no way to tell whether the
|
||||
answer faithfully reflects the source or whether the model improvised.
|
||||
arborist replaces that trust gap with a check: **every answer is
|
||||
verified, every answer is labelled, every answer carries a proof chain
|
||||
back to the bytes of the source it cites.**
|
||||
|
||||
2. What makes arborist different
|
||||
---------------------------------
|
||||
How it works
|
||||
------------
|
||||
|
||||
Eleven design rules govern the substrate. The four that matter most for
|
||||
a reviewer:
|
||||
arborist keeps three layers in a single SQLite file. **Ingested
|
||||
documents** are split into chunks, hashed, and indexed for full-text
|
||||
search. **Derived layers** — summaries, indices, distillations — are
|
||||
hash-bound to the documents they came from. **An answer cache** stores
|
||||
every verified answer, keyed by the document, the question, the model
|
||||
that produced it, and the policy under which it was checked. Every
|
||||
write appends a hash-chained audit row; a single tampered record
|
||||
breaks the chain.
|
||||
|
||||
**The verifier stays binary.** Each evidence unit verifies or does not.
|
||||
No per-unit confidence scores, no fuzzy-match indicators, no soft
|
||||
labels. Once a soft signal contaminates the chain, every prior
|
||||
cryptographic claim becomes negotiable.
|
||||
When you ask a question, arborist retrieves candidate source chunks,
|
||||
tags each one with a short label (``E1``, ``E2``, …), and passes them
|
||||
to the language model. The model emits prose with those labels — for
|
||||
example, *"Jupiter is the largest planet [E1], with a radius of about
|
||||
70 000 km [E2]"*. **The model never types the quoted text.** arborist
|
||||
composes the answer at display time, interpolating the actual chunk
|
||||
text at each label. A class of fabrication — the synthetic quote that
|
||||
looks like a verbatim citation but came out of the model's prior —
|
||||
becomes impossible by construction.
|
||||
|
||||
**The runtime owns quote text.** In ``claim_lattice_pointer`` mode the
|
||||
model emits prose with bracketed pointer tags (``[E1]``, ``[E2]``); the
|
||||
runtime interpolates the literal source span at render time. The model
|
||||
never types the quote string. *Synthetic-elision-by-construction-impossible*
|
||||
— a model cannot produce a frankenquote it cannot type.
|
||||
After generation, the verifier runs. Four mechanical strategies
|
||||
(exact-quote match, line-span match, named-entity proximity,
|
||||
paraphrase coverage) try in sequence to confirm each claim against
|
||||
the cited chunks. The output is a single label per answer: **grounded**
|
||||
(every claim verifies), **partly grounded**, or **not grounded**.
|
||||
There is no "high confidence" middle ground — confidence labels are
|
||||
soft signals in disguise. The verifier names what it can prove and
|
||||
what it cannot.
|
||||
|
||||
**Soft hash never enters the proof path.** Embeddings, TF-IDF scores,
|
||||
cross-encoder rerankers, NLI judgments shape ranking and retrieval and
|
||||
inform demote-only governance. They never feed ``cache_key`` ,
|
||||
``document_root``, or ``audit_event_hash``. The hard channel and the
|
||||
soft channel evolve on independent timelines.
|
||||
What makes it different
|
||||
-----------------------
|
||||
|
||||
**Labels name properties, not vibes.** ``POINTER-LINKED``,
|
||||
``ANCHOR-WARRANTED``, ``EVIDENCE-WARRANTED``, ``UNGROUNDED`` each name a
|
||||
property the verifier could lexically confirm or could not. There are
|
||||
no "high confidence" labels. A reviewer reads the label and immediately
|
||||
knows what was checked.
|
||||
**The verifier is mechanical, not neural.** Faithfulness is a textual
|
||||
property of (answer, evidence, source) and is computed deterministically.
|
||||
No language model in the proof path means no model drift in the proof
|
||||
path.
|
||||
|
||||
3. The 8-dimensional cache key
|
||||
-------------------------------
|
||||
**The model cannot fabricate citations.** arborist sits between the
|
||||
model's output and the rendered answer; the model proposes references,
|
||||
arborist renders the content of those references from the actual
|
||||
source bytes.
|
||||
|
||||
A cache hit returns a previously computed answer with a Merkle proof of
|
||||
origin; a cache miss triggers fresh inference. The key folds together:
|
||||
**Soft signals stay outside the proof.** Embedding similarity,
|
||||
cross-encoder rerankers, natural-language-inference judgments — all
|
||||
useful, all used to find and rank evidence; none of them allowed to
|
||||
influence the verification label or the audit chain. The cheap,
|
||||
provable path ships by default; the expensive, semantic path is
|
||||
opt-in and additive.
|
||||
|
||||
================================ ===================================================
|
||||
``source_root`` Merkle root of the corpus the answer is about
|
||||
``question_hash`` dedup-mode-aware hash of the question (strict | equivalence_class)
|
||||
``model_profile_hash`` model identity (name + sampling profile)
|
||||
``conversation_hash`` prior-turn dependency, if any
|
||||
``governance_policy_hash`` every policy field that alters generation
|
||||
``schema_version`` ``v9.8.0``
|
||||
``canonicalization_version`` ``norm-v1``
|
||||
``chunking_version`` ``tok-512-v1``
|
||||
================================ ===================================================
|
||||
**Replay is free and exact.** Answers are content-addressed. The same
|
||||
question on the same document under the same policy returns the same
|
||||
record, with the same proof chain. Different document, different
|
||||
model, or different policy yields a different cache entry. The cache
|
||||
partitions cleanly; the corpus stays untouched.
|
||||
|
||||
Bumping any one dimension invalidates prior records on lookup —
|
||||
governance evolves, the corpus does not get rewritten when governance
|
||||
evolves. Every preflight policy decision is *bound twice*: once into
|
||||
``governance_policy_hash`` (cache identity) and once into ``run_dag_root``
|
||||
via the preflight stage (audit replay).
|
||||
|
||||
4. The layered verifier
|
||||
------------------------
|
||||
|
||||
Four strategies are tried in order; first to find evidence classifies.
|
||||
**quote** (sequential pair-matching, never regex — prevents phantom
|
||||
inter-pair captures), **span** (verbatim line match), **entity**
|
||||
(proximity-clustered proper nouns), **paraphrase** (token-coverage,
|
||||
prose-shaped only). Trichotomy on the schema column: STRICT = every unit
|
||||
verifies, HYBRID = mixed, UNGROUNDED = none. The renderer maps that
|
||||
column to a four-rung claim-lattice ladder
|
||||
(POINTER-LINKED → ANCHOR-WARRANTED → EVIDENCE-WARRANTED;
|
||||
ENTAILMENT-VERIFIED reserved); programmatic callers see the trichotomy,
|
||||
human-facing surfaces see the ladder. The ENTAILMENT-VERIFIED rung is
|
||||
deliberately empty — committing NLI to the proof path would re-introduce
|
||||
the soft/hard boundary leak the architecture is built to prevent.
|
||||
Honesty about the ceiling is a feature.
|
||||
|
||||
----
|
||||
|
||||
5. What we measure on real traffic
|
||||
-----------------------------------
|
||||
|
||||
The bench is the scoreboard; the live fixtures are the gates. Numbers
|
||||
that survive the 5pp signal floor on real-shard, real-LLM runs:
|
||||
|
||||
- **Mis-cite catch (claim about X cited to source about Y).** The
|
||||
``BAAI/bge-reranker-large`` veto at threshold ``θ ≤ -2.42`` catches
|
||||
20/20 (100%) of mis-cite fixtures at strictly 0/808 (0%) real-STRICT
|
||||
false positive on the pooled bench-qa, with a 1.4-point margin
|
||||
between the worst mis-cite and the best STRICT (#000052 §3.2).
|
||||
- **Deflection catch (off-topic answer to an on-topic question).** Same
|
||||
reranker catches 11/20 (55%) of real-haystack deflection fixtures at
|
||||
the same 0/808 FP threshold. The cost-pick alternate
|
||||
(``ms-marco-MiniLM-L-6-v2``, 5× smaller) catches 13/20 (65%) at 0.4% FP.
|
||||
- **Recombination catch (right tokens, wrong subject).** The NLI veto
|
||||
(``facebook/bart-large-mnli``, top-k=12, θc=0.999) catches ~48% of
|
||||
hand-crafted real-haystack recombination fixtures at 0/808 FP; the
|
||||
ceiling is selector-bound, not entailment-bound (#000049 §7 #27).
|
||||
- **Warrant-chain coverage.** 92/92 (100%) of the claim-pack corpus
|
||||
resolves to a warrant chain (18 public-domain or open-licensed
|
||||
textbook substrates + curated citation aliases + term aliases;
|
||||
ticket #000031).
|
||||
- **STRICT-rate, quote mode, real Wikipedia haystack.** 0.54 on
|
||||
Hermes-3-Llama-3.1-8B (n=3 × 71 questions, sample-shuffled @ c=4;
|
||||
see ``docs/qa-modes-bench.md``).
|
||||
|
||||
Sample sizes are stated. Synthetic shortcuts are not. The five-point
|
||||
sweep-wide/sweep-deep discipline ("real-traffic-sized samples or it
|
||||
didn't happen") lives in ``docs/bench-maxing.md``.
|
||||
|
||||
6. Closed substrate work
|
||||
What you would run it for
|
||||
-------------------------
|
||||
|
||||
Recent substrate work that is *landed and pinned*: ticket #000005
|
||||
(four-rung ladder display layer), #000008 (broad-quantifier preflight
|
||||
guard with six-level disable hierarchy), #000010 (metacognition
|
||||
preflight — false-premise, contradiction, stale-risk, out-of-corpus),
|
||||
#000015 (π* canonical projections — arithmetic, logic-kernel,
|
||||
algebra-symbolic), #000027 (canonical-projection persistence in
|
||||
providence cache), #000031 (claim-pack warrant resolver, 100%
|
||||
coverage), #000049 §3 (NLI veto, partial closure), #000052 §3.1
|
||||
(coherence sidecar — circular, vacuous, phrase-component-reuse) and
|
||||
§3.2 (relevance reranker, viable runtime soft-veto). The synthesis
|
||||
brief for the independent review thread is
|
||||
``docs/relevance-and-veto-synthesis-for-dav1d.md``.
|
||||
You hold a corpus — internal documents, public scientific literature,
|
||||
a legal archive, a textbook collection — and you want reliable Q&A
|
||||
over it without paying a closed-source vendor or wiring up a vector
|
||||
database. You care that the answers track your sources. You want users
|
||||
to be able to verify, replay, and share the proof. You want it to keep
|
||||
working when the model changes, when the policy changes, when the
|
||||
corpus version-bumps.
|
||||
|
||||
----
|
||||
What it costs
|
||||
-------------
|
||||
|
||||
================== ============================================================
|
||||
Language Python 3.12
|
||||
Storage SQLite — one file, ~2 GB for a Wikipedia-sized corpus
|
||||
Compute No GPU required for the proof path. Inference runs wherever
|
||||
you want — locally, or via an OpenAI-compatible endpoint.
|
||||
Optional Cross-encoder rerankers (80–560 MB) for harder relevance
|
||||
ranking. They never enter the proof.
|
||||
License AGPL-3.0-only
|
||||
================== ============================================================
|
||||
|
||||
What it has measured on real traffic
|
||||
-------------------------------------
|
||||
|
||||
- **Misattribution detection.** Catches 100% of answers where the cited
|
||||
source is unrelated to the claim — at strictly zero false positives
|
||||
across the full pooled test bed (cross-encoder reranker, hard
|
||||
threshold, real Wikipedia-haystack questions).
|
||||
|
||||
- **Topic-deflection detection.** Catches 55–65% of off-topic answers
|
||||
at 0–0.4% false positives, depending on the reranker model chosen
|
||||
(a small 80 MB model and a larger 560 MB model both clear the bar).
|
||||
|
||||
- **Citation coverage.** On the curated textbook corpus, 100% of cited
|
||||
claims resolve to a chain of evidence ending at a public-domain or
|
||||
open-licensed source — eighteen textbooks plus curated cross-citation
|
||||
aliases.
|
||||
|
||||
Sample sizes are stated, sample sources are real, and the gates are
|
||||
reported against the same numbers an external reviewer can reproduce
|
||||
from the repository.
|
||||
|
||||
License — Permacomputer Preamble
|
||||
---------------------------------
|
||||
|
|
@ -188,24 +163,25 @@ License — Permacomputer Preamble
|
|||
|
||||
----
|
||||
|
||||
Appendix A — Three-layer architecture
|
||||
--------------------------------------
|
||||
Appendix A — The three layers
|
||||
------------------------------
|
||||
|
||||
.. figure:: diagrams/pager-arch-stack.png
|
||||
:width: 5.5in
|
||||
:align: center
|
||||
|
||||
Surface, Core, Providence cache — each layer hash-binds to the next;
|
||||
every state change appends a row to the audit chain.
|
||||
Ingested documents, derived layers, and the answer cache — each
|
||||
layer hash-binds to the next. Every state change appends one row
|
||||
to the audit chain; a single tampered record breaks the chain.
|
||||
|
||||
Appendix B — Verifier flow
|
||||
---------------------------
|
||||
Appendix B — How an answer is verified
|
||||
---------------------------------------
|
||||
|
||||
.. figure:: diagrams/pager-verifier-flow.png
|
||||
:width: 6.5in
|
||||
:align: center
|
||||
|
||||
Question → retrieval → pointer-tagged context → LLM → binary
|
||||
verifier → trichotomy label → audit chain & providence cache. The
|
||||
LLM never types the quote string.
|
||||
|
||||
The model sees labelled source chunks and emits prose tagged with
|
||||
those labels — it never types the quote text. A mechanical
|
||||
verifier then checks every cited claim against the actual source
|
||||
and assigns the answer one of three labels.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
// Compact 3-layer architecture for the 2-pager appendix.
|
||||
// External-facing labels — no schema-column or table-name vocabulary.
|
||||
// Render: dot -Tsvg pager-arch-stack.dot -o pager-arch-stack.svg
|
||||
|
||||
digraph arch_stack {
|
||||
|
|
@ -9,11 +10,11 @@ digraph arch_stack {
|
|||
edge [fontname="Helvetica", fontsize=9]
|
||||
bgcolor="white"
|
||||
|
||||
surface [label="SURFACE — ingested documents\nWikipedia · HTML · TeX · git · claim-packs\nchunked → Merkle-rooted → FTS5-indexed", fillcolor="#e9f3ff"]
|
||||
core [label="CORE — distilled documents\nMerkle-bound to surfaces by per-chunk\ninclusion proofs (derivations.proof_blob)", fillcolor="#dff5e7"]
|
||||
cache [label="PROVIDENCE CACHE — verified Q&A\n8-dim cache_key · audit_mode label ∈\n{STRICT, HYBRID, UNGROUNDED}", fillcolor="#fff3d6"]
|
||||
surface [label="Ingested documents\n(Wikipedia · HTML · TeX · git · claim-packs)\nchunked → hashed → full-text-indexed", fillcolor="#e9f3ff"]
|
||||
core [label="Derived layers\n(summaries, indices, distillations)\nhash-bound back to source chunks", fillcolor="#dff5e7"]
|
||||
cache [label="Answer cache\nverified Q&A · grounded / partly / not grounded\ncryptographic chain back to source bytes", fillcolor="#fff3d6"]
|
||||
|
||||
audit [label="AUDIT CHAIN — every state change\nappends sha256(prev || canonical(body))\nto audit_events (single SQLite file)", fillcolor="#fde7e9", shape=note]
|
||||
audit [label="Audit chain\nevery write appends a hash-linked row;\na single tampered record breaks the chain", fillcolor="#fde7e9", shape=note]
|
||||
|
||||
surface -> core [label="distill", fontsize=9]
|
||||
core -> cache [label="verify → cache", fontsize=9]
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 38 KiB |
|
|
@ -4,77 +4,77 @@
|
|||
<!-- Generated by graphviz version 2.43.0 (0)
|
||||
-->
|
||||
<!-- Title: arch_stack Pages: 1 -->
|
||||
<svg width="379pt" height="268pt"
|
||||
viewBox="0.00 0.00 379.00 268.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="434pt" height="268pt"
|
||||
viewBox="0.00 0.00 433.50 268.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 264)">
|
||||
<title>arch_stack</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-264 375,-264 375,4 -4,4"/>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-264 429.5,-264 429.5,4 -4,4"/>
|
||||
<!-- surface -->
|
||||
<g id="node1" class="node">
|
||||
<title>surface</title>
|
||||
<path fill="#e9f3ff" stroke="black" d="M319,-44C319,-44 98,-44 98,-44 92,-44 86,-38 86,-32 86,-32 86,-12 86,-12 86,-6 92,0 98,0 98,0 319,0 319,0 325,0 331,-6 331,-12 331,-12 331,-32 331,-32 331,-38 325,-44 319,-44"/>
|
||||
<text text-anchor="middle" x="208.5" y="-31.2" font-family="Helvetica,sans-Serif" font-size="11.00">SURFACE — ingested documents</text>
|
||||
<text text-anchor="middle" x="208.5" y="-19.2" font-family="Helvetica,sans-Serif" font-size="11.00">Wikipedia · HTML · TeX · git · claim-packs</text>
|
||||
<text text-anchor="middle" x="208.5" y="-7.2" font-family="Helvetica,sans-Serif" font-size="11.00">chunked → Merkle-rooted → FTS5-indexed</text>
|
||||
<path fill="#e9f3ff" stroke="black" d="M380.5,-44C380.5,-44 153.5,-44 153.5,-44 147.5,-44 141.5,-38 141.5,-32 141.5,-32 141.5,-12 141.5,-12 141.5,-6 147.5,0 153.5,0 153.5,0 380.5,0 380.5,0 386.5,0 392.5,-6 392.5,-12 392.5,-12 392.5,-32 392.5,-32 392.5,-38 386.5,-44 380.5,-44"/>
|
||||
<text text-anchor="middle" x="267" y="-31.2" font-family="Helvetica,sans-Serif" font-size="11.00">Ingested documents</text>
|
||||
<text text-anchor="middle" x="267" y="-19.2" font-family="Helvetica,sans-Serif" font-size="11.00">(Wikipedia · HTML · TeX · git · claim-packs)</text>
|
||||
<text text-anchor="middle" x="267" y="-7.2" font-family="Helvetica,sans-Serif" font-size="11.00">chunked → hashed → full-text-indexed</text>
|
||||
</g>
|
||||
<!-- core -->
|
||||
<g id="node2" class="node">
|
||||
<title>core</title>
|
||||
<path fill="#dff5e7" stroke="black" d="M245.5,-116C245.5,-116 31.5,-116 31.5,-116 25.5,-116 19.5,-110 19.5,-104 19.5,-104 19.5,-84 19.5,-84 19.5,-78 25.5,-72 31.5,-72 31.5,-72 245.5,-72 245.5,-72 251.5,-72 257.5,-78 257.5,-84 257.5,-84 257.5,-104 257.5,-104 257.5,-110 251.5,-116 245.5,-116"/>
|
||||
<text text-anchor="middle" x="138.5" y="-103.2" font-family="Helvetica,sans-Serif" font-size="11.00">CORE — distilled documents</text>
|
||||
<text text-anchor="middle" x="138.5" y="-91.2" font-family="Helvetica,sans-Serif" font-size="11.00">Merkle-bound to surfaces by per-chunk</text>
|
||||
<text text-anchor="middle" x="138.5" y="-79.2" font-family="Helvetica,sans-Serif" font-size="11.00">inclusion proofs (derivations.proof_blob)</text>
|
||||
<path fill="#dff5e7" stroke="black" d="M295.5,-116C295.5,-116 112.5,-116 112.5,-116 106.5,-116 100.5,-110 100.5,-104 100.5,-104 100.5,-84 100.5,-84 100.5,-78 106.5,-72 112.5,-72 112.5,-72 295.5,-72 295.5,-72 301.5,-72 307.5,-78 307.5,-84 307.5,-84 307.5,-104 307.5,-104 307.5,-110 301.5,-116 295.5,-116"/>
|
||||
<text text-anchor="middle" x="204" y="-103.2" font-family="Helvetica,sans-Serif" font-size="11.00">Derived layers</text>
|
||||
<text text-anchor="middle" x="204" y="-91.2" font-family="Helvetica,sans-Serif" font-size="11.00">(summaries, indices, distillations)</text>
|
||||
<text text-anchor="middle" x="204" y="-79.2" font-family="Helvetica,sans-Serif" font-size="11.00">hash-bound back to source chunks</text>
|
||||
</g>
|
||||
<!-- surface->core -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>surface->core</title>
|
||||
<path fill="none" stroke="black" d="M187.5,-44C181.11,-50.39 173.98,-57.52 167.17,-64.33"/>
|
||||
<polygon fill="black" stroke="black" points="164.57,-61.98 159.97,-71.53 169.52,-66.93 164.57,-61.98"/>
|
||||
<text text-anchor="middle" x="190.5" y="-55.8" font-family="Helvetica,sans-Serif" font-size="9.00">distill</text>
|
||||
<path fill="none" stroke="black" d="M248.1,-44C242.47,-50.25 236.2,-57.22 230.2,-63.89"/>
|
||||
<polygon fill="black" stroke="black" points="227.41,-61.75 223.32,-71.53 232.62,-66.44 227.41,-61.75"/>
|
||||
<text text-anchor="middle" x="252" y="-55.8" font-family="Helvetica,sans-Serif" font-size="9.00">distill</text>
|
||||
</g>
|
||||
<!-- audit -->
|
||||
<g id="node4" class="node">
|
||||
<title>audit</title>
|
||||
<polygon fill="#fde7e9" stroke="black" points="365,-260 128,-260 128,-216 371,-216 371,-254 365,-260"/>
|
||||
<polyline fill="none" stroke="black" points="365,-260 365,-254 "/>
|
||||
<polyline fill="none" stroke="black" points="371,-254 365,-254 "/>
|
||||
<text text-anchor="middle" x="249.5" y="-247.2" font-family="Helvetica,sans-Serif" font-size="11.00">AUDIT CHAIN — every state change</text>
|
||||
<text text-anchor="middle" x="249.5" y="-235.2" font-family="Helvetica,sans-Serif" font-size="11.00">appends sha256(prev || canonical(body))</text>
|
||||
<text text-anchor="middle" x="249.5" y="-223.2" font-family="Helvetica,sans-Serif" font-size="11.00">to audit_events (single SQLite file)</text>
|
||||
<polygon fill="#fde7e9" stroke="black" points="419.5,-260 174.5,-260 174.5,-216 425.5,-216 425.5,-254 419.5,-260"/>
|
||||
<polyline fill="none" stroke="black" points="419.5,-260 419.5,-254 "/>
|
||||
<polyline fill="none" stroke="black" points="425.5,-254 419.5,-254 "/>
|
||||
<text text-anchor="middle" x="300" y="-247.2" font-family="Helvetica,sans-Serif" font-size="11.00">Audit chain</text>
|
||||
<text text-anchor="middle" x="300" y="-235.2" font-family="Helvetica,sans-Serif" font-size="11.00">every write appends a hash-linked row;</text>
|
||||
<text text-anchor="middle" x="300" y="-223.2" font-family="Helvetica,sans-Serif" font-size="11.00">a single tampered record breaks the chain</text>
|
||||
</g>
|
||||
<!-- surface->audit -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>surface->audit</title>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M241.95,-44.24C250.98,-51.8 259.59,-61.18 264.5,-72 270.08,-84.3 269.38,-158.79 260.95,-206.05"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="257.49,-205.49 258.96,-215.98 264.35,-206.86 257.49,-205.49"/>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M294.75,-44.09C302.85,-51.88 310.68,-61.42 315,-72 320.38,-85.18 319.5,-160.34 311.42,-206.13"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="307.98,-205.49 309.46,-215.98 314.84,-206.85 307.98,-205.49"/>
|
||||
</g>
|
||||
<!-- cache -->
|
||||
<g id="node3" class="node">
|
||||
<title>cache</title>
|
||||
<path fill="#fff3d6" stroke="black" d="M215,-188C215,-188 12,-188 12,-188 6,-188 0,-182 0,-176 0,-176 0,-156 0,-156 0,-150 6,-144 12,-144 12,-144 215,-144 215,-144 221,-144 227,-150 227,-156 227,-156 227,-176 227,-176 227,-182 221,-188 215,-188"/>
|
||||
<text text-anchor="middle" x="113.5" y="-175.2" font-family="Helvetica,sans-Serif" font-size="11.00">PROVIDENCE CACHE — verified Q&A</text>
|
||||
<text text-anchor="middle" x="113.5" y="-163.2" font-family="Helvetica,sans-Serif" font-size="11.00">8-dim cache_key · audit_mode label ∈</text>
|
||||
<text text-anchor="middle" x="113.5" y="-151.2" font-family="Helvetica,sans-Serif" font-size="11.00">{STRICT, HYBRID, UNGROUNDED}</text>
|
||||
<path fill="#fff3d6" stroke="black" d="M266,-188C266,-188 12,-188 12,-188 6,-188 0,-182 0,-176 0,-176 0,-156 0,-156 0,-150 6,-144 12,-144 12,-144 266,-144 266,-144 272,-144 278,-150 278,-156 278,-156 278,-176 278,-176 278,-182 272,-188 266,-188"/>
|
||||
<text text-anchor="middle" x="139" y="-175.2" font-family="Helvetica,sans-Serif" font-size="11.00">Answer cache</text>
|
||||
<text text-anchor="middle" x="139" y="-163.2" font-family="Helvetica,sans-Serif" font-size="11.00">verified Q&A · grounded / partly / not grounded</text>
|
||||
<text text-anchor="middle" x="139" y="-151.2" font-family="Helvetica,sans-Serif" font-size="11.00">cryptographic chain back to source bytes</text>
|
||||
</g>
|
||||
<!-- core->cache -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>core->cache</title>
|
||||
<path fill="none" stroke="black" d="M131,-116C129.01,-121.57 126.82,-127.71 124.68,-133.71"/>
|
||||
<polygon fill="black" stroke="black" points="121.24,-132.93 121.17,-143.53 127.83,-135.29 121.24,-132.93"/>
|
||||
<text text-anchor="middle" x="160.5" y="-127.8" font-family="Helvetica,sans-Serif" font-size="9.00">verify → cache</text>
|
||||
<path fill="none" stroke="black" d="M184.5,-116C178.69,-122.25 172.22,-129.22 166.03,-135.89"/>
|
||||
<polygon fill="black" stroke="black" points="163.18,-133.82 158.94,-143.53 168.31,-138.58 163.18,-133.82"/>
|
||||
<text text-anchor="middle" x="209" y="-127.8" font-family="Helvetica,sans-Serif" font-size="9.00">verify → cache</text>
|
||||
</g>
|
||||
<!-- core->audit -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>core->audit</title>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M200.73,-116.01C213.64,-123.04 225.91,-132.2 234.5,-144 247.33,-161.63 250.87,-186.11 251.31,-205.54"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="247.81,-205.72 251.28,-215.73 254.81,-205.74 247.81,-205.72"/>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M254.11,-116.13C265.91,-123.34 277.28,-132.55 285,-144 297.19,-162.08 300.75,-186.55 301.37,-205.85"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="297.87,-205.99 301.44,-215.97 304.87,-205.94 297.87,-205.99"/>
|
||||
</g>
|
||||
<!-- cache->audit -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>cache->audit</title>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M151.73,-188.09C163.18,-194.29 175.8,-201.01 187.5,-207 190.37,-208.47 193.33,-209.97 196.32,-211.46"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="194.83,-214.63 205.35,-215.94 197.94,-208.36 194.83,-214.63"/>
|
||||
<text text-anchor="middle" x="213" y="-199.8" font-family="Helvetica,sans-Serif" font-size="9.00">every write</text>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M187.31,-188C204.58,-195.51 224.22,-204.05 242.21,-211.88"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="240.88,-215.11 251.45,-215.89 243.68,-208.69 240.88,-215.11"/>
|
||||
<text text-anchor="middle" x="255.5" y="-199.8" font-family="Helvetica,sans-Serif" font-size="9.00">every write</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.5 KiB |
|
|
@ -1,5 +1,5 @@
|
|||
// Compact verifier flow for the 2-pager appendix.
|
||||
// (Question, source-chunks) → model → (text, pointers) → verifier → label.
|
||||
// External-facing labels — no internal vocabulary.
|
||||
// Render: dot -Tsvg pager-verifier-flow.dot -o pager-verifier-flow.svg
|
||||
|
||||
digraph verifier_flow {
|
||||
|
|
@ -10,27 +10,27 @@ digraph verifier_flow {
|
|||
edge [fontname="Helvetica", fontsize=11]
|
||||
bgcolor="white"
|
||||
|
||||
question [label="QUESTION", fillcolor="#fff7e6", shape=note]
|
||||
retrieval [label="retrieval\n(FTS5 + phrase route\n+ rivalry exclusion)", fillcolor="#e9f3ff"]
|
||||
pointers [label="POINTER MAP\nE1 → span\nE2 → span\n…", fillcolor="#dff5e7", shape=note]
|
||||
model [label="LLM\nsees: question +\npointer-tagged chunks\nemits: prose with [E1] [E2] tags\n(never types the quote string)", fillcolor="#f0e6ff"]
|
||||
verifier [label="verifier\n(quote · span · entity\n· paraphrase — binary,\nno LLM call)", fillcolor="#fff3d6"]
|
||||
question [label="Question", fillcolor="#fff7e6", shape=note]
|
||||
retrieval [label="Retrieve\ncandidate source chunks", fillcolor="#e9f3ff"]
|
||||
pointers [label="Labelled chunks\nE1 → text\nE2 → text\n…", fillcolor="#dff5e7", shape=note]
|
||||
model [label="Language model\nsees: question + labelled chunks\nemits: prose tagged [E1] [E2]\n(never types the quote text)", fillcolor="#f0e6ff"]
|
||||
verifier [label="Verifier\nfour mechanical strategies,\nno model in the loop", fillcolor="#fff3d6"]
|
||||
|
||||
label_strict [label="STRICT\nevery claim verifies", fillcolor="#28a745", fontcolor="white"]
|
||||
label_hybrid [label="HYBRID\nsome verify, some don't", fillcolor="#ffc107"]
|
||||
label_ungrounded [label="UNGROUNDED\nnone verify", fillcolor="#dc3545", fontcolor="white"]
|
||||
label_grounded [label="grounded\nevery claim verifies", fillcolor="#28a745", fontcolor="white"]
|
||||
label_partial [label="partly grounded\nsome verify, some don't", fillcolor="#ffc107"]
|
||||
label_ungrounded [label="not grounded\nnone verify", fillcolor="#dc3545", fontcolor="white"]
|
||||
|
||||
audit [label="audit chain\n+ providence cache\n(8-dim key, governance-aware)", fillcolor="#fde7e9", shape=note]
|
||||
audit [label="Audit chain\n+ answer cache\n(reproducible, replayable)", fillcolor="#fde7e9", shape=note]
|
||||
|
||||
question -> retrieval -> pointers
|
||||
pointers -> model
|
||||
model -> verifier [label="answer\n+ pointer IDs"]
|
||||
verifier -> label_strict
|
||||
verifier -> label_hybrid
|
||||
model -> verifier [label="answer with [E1] [E2] tags"]
|
||||
verifier -> label_grounded
|
||||
verifier -> label_partial
|
||||
verifier -> label_ungrounded
|
||||
label_strict -> audit [style=dashed, color="#888888"]
|
||||
label_hybrid -> audit [style=dashed, color="#888888"]
|
||||
label_grounded -> audit [style=dashed, color="#888888"]
|
||||
label_partial -> audit [style=dashed, color="#888888"]
|
||||
label_ungrounded -> audit [style=dashed, color="#888888"]
|
||||
|
||||
{rank=same; label_strict; label_hybrid; label_ungrounded}
|
||||
{rank=same; label_grounded; label_partial; label_ungrounded}
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 62 KiB |
|
|
@ -4,149 +4,145 @@
|
|||
<!-- Generated by graphviz version 2.43.0 (0)
|
||||
-->
|
||||
<!-- Title: verifier_flow Pages: 1 -->
|
||||
<svg width="1288pt" height="152pt"
|
||||
viewBox="0.00 0.00 1288.00 152.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<svg width="1389pt" height="152pt"
|
||||
viewBox="0.00 0.00 1389.00 152.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 148)">
|
||||
<title>verifier_flow</title>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-148 1284,-148 1284,4 -4,4"/>
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-148 1385,-148 1385,4 -4,4"/>
|
||||
<!-- question -->
|
||||
<g id="node1" class="node">
|
||||
<title>question</title>
|
||||
<polygon fill="#fff7e6" stroke="black" points="74,-90 0,-90 0,-54 80,-54 80,-84 74,-90"/>
|
||||
<polyline fill="none" stroke="black" points="74,-90 74,-84 "/>
|
||||
<polyline fill="none" stroke="black" points="80,-84 74,-84 "/>
|
||||
<text text-anchor="middle" x="40" y="-68.9" font-family="Helvetica,sans-Serif" font-size="12.00">QUESTION</text>
|
||||
<polygon fill="#fff7e6" stroke="black" points="64,-90 0,-90 0,-54 70,-54 70,-84 64,-90"/>
|
||||
<polyline fill="none" stroke="black" points="64,-90 64,-84 "/>
|
||||
<polyline fill="none" stroke="black" points="70,-84 64,-84 "/>
|
||||
<text text-anchor="middle" x="35" y="-68.9" font-family="Helvetica,sans-Serif" font-size="12.00">Question</text>
|
||||
</g>
|
||||
<!-- retrieval -->
|
||||
<g id="node2" class="node">
|
||||
<title>retrieval</title>
|
||||
<path fill="#e9f3ff" stroke="black" d="M239,-95.5C239,-95.5 119,-95.5 119,-95.5 113,-95.5 107,-89.5 107,-83.5 107,-83.5 107,-60.5 107,-60.5 107,-54.5 113,-48.5 119,-48.5 119,-48.5 239,-48.5 239,-48.5 245,-48.5 251,-54.5 251,-60.5 251,-60.5 251,-83.5 251,-83.5 251,-89.5 245,-95.5 239,-95.5"/>
|
||||
<text text-anchor="middle" x="179" y="-81.9" font-family="Helvetica,sans-Serif" font-size="12.00">retrieval</text>
|
||||
<text text-anchor="middle" x="179" y="-68.9" font-family="Helvetica,sans-Serif" font-size="12.00">(FTS5 + phrase route</text>
|
||||
<text text-anchor="middle" x="179" y="-55.9" font-family="Helvetica,sans-Serif" font-size="12.00">+ rivalry exclusion)</text>
|
||||
<path fill="#e9f3ff" stroke="black" d="M250,-90C250,-90 109,-90 109,-90 103,-90 97,-84 97,-78 97,-78 97,-66 97,-66 97,-60 103,-54 109,-54 109,-54 250,-54 250,-54 256,-54 262,-60 262,-66 262,-66 262,-78 262,-78 262,-84 256,-90 250,-90"/>
|
||||
<text text-anchor="middle" x="179.5" y="-75.4" font-family="Helvetica,sans-Serif" font-size="12.00">Retrieve</text>
|
||||
<text text-anchor="middle" x="179.5" y="-62.4" font-family="Helvetica,sans-Serif" font-size="12.00">candidate source chunks</text>
|
||||
</g>
|
||||
<!-- question->retrieval -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>question->retrieval</title>
|
||||
<path fill="none" stroke="black" d="M80.26,-72C85.5,-72 91.02,-72 96.66,-72"/>
|
||||
<polygon fill="black" stroke="black" points="96.9,-75.5 106.9,-72 96.9,-68.5 96.9,-75.5"/>
|
||||
<path fill="none" stroke="black" d="M70.13,-72C75.41,-72 81.06,-72 86.91,-72"/>
|
||||
<polygon fill="black" stroke="black" points="86.91,-75.5 96.91,-72 86.91,-68.5 86.91,-75.5"/>
|
||||
</g>
|
||||
<!-- pointers -->
|
||||
<g id="node3" class="node">
|
||||
<title>pointers</title>
|
||||
<polygon fill="#dff5e7" stroke="black" points="372,-102 278,-102 278,-42 378,-42 378,-96 372,-102"/>
|
||||
<polyline fill="none" stroke="black" points="372,-102 372,-96 "/>
|
||||
<polyline fill="none" stroke="black" points="378,-96 372,-96 "/>
|
||||
<text text-anchor="middle" x="328" y="-88.4" font-family="Helvetica,sans-Serif" font-size="12.00">POINTER MAP</text>
|
||||
<text text-anchor="middle" x="328" y="-75.4" font-family="Helvetica,sans-Serif" font-size="12.00">E1 → span</text>
|
||||
<text text-anchor="middle" x="328" y="-62.4" font-family="Helvetica,sans-Serif" font-size="12.00">E2 → span</text>
|
||||
<text text-anchor="middle" x="328" y="-49.4" font-family="Helvetica,sans-Serif" font-size="12.00">…</text>
|
||||
<polygon fill="#dff5e7" stroke="black" points="396,-102 289,-102 289,-42 402,-42 402,-96 396,-102"/>
|
||||
<polyline fill="none" stroke="black" points="396,-102 396,-96 "/>
|
||||
<polyline fill="none" stroke="black" points="402,-96 396,-96 "/>
|
||||
<text text-anchor="middle" x="345.5" y="-88.4" font-family="Helvetica,sans-Serif" font-size="12.00">Labelled chunks</text>
|
||||
<text text-anchor="middle" x="345.5" y="-75.4" font-family="Helvetica,sans-Serif" font-size="12.00">E1 → text</text>
|
||||
<text text-anchor="middle" x="345.5" y="-62.4" font-family="Helvetica,sans-Serif" font-size="12.00">E2 → text</text>
|
||||
<text text-anchor="middle" x="345.5" y="-49.4" font-family="Helvetica,sans-Serif" font-size="12.00">…</text>
|
||||
</g>
|
||||
<!-- retrieval->pointers -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>retrieval->pointers</title>
|
||||
<path fill="none" stroke="black" d="M251.35,-72C256.79,-72 262.24,-72 267.59,-72"/>
|
||||
<polygon fill="black" stroke="black" points="267.72,-75.5 277.72,-72 267.72,-68.5 267.72,-75.5"/>
|
||||
<path fill="none" stroke="black" d="M262.02,-72C267.51,-72 273,-72 278.39,-72"/>
|
||||
<polygon fill="black" stroke="black" points="278.62,-75.5 288.62,-72 278.62,-68.5 278.62,-75.5"/>
|
||||
</g>
|
||||
<!-- model -->
|
||||
<g id="node4" class="node">
|
||||
<title>model</title>
|
||||
<path fill="#f0e6ff" stroke="black" d="M596,-108.5C596,-108.5 417,-108.5 417,-108.5 411,-108.5 405,-102.5 405,-96.5 405,-96.5 405,-47.5 405,-47.5 405,-41.5 411,-35.5 417,-35.5 417,-35.5 596,-35.5 596,-35.5 602,-35.5 608,-41.5 608,-47.5 608,-47.5 608,-96.5 608,-96.5 608,-102.5 602,-108.5 596,-108.5"/>
|
||||
<text text-anchor="middle" x="506.5" y="-94.9" font-family="Helvetica,sans-Serif" font-size="12.00">LLM</text>
|
||||
<text text-anchor="middle" x="506.5" y="-81.9" font-family="Helvetica,sans-Serif" font-size="12.00">sees: question +</text>
|
||||
<text text-anchor="middle" x="506.5" y="-68.9" font-family="Helvetica,sans-Serif" font-size="12.00">pointer-tagged chunks</text>
|
||||
<text text-anchor="middle" x="506.5" y="-55.9" font-family="Helvetica,sans-Serif" font-size="12.00">emits: prose with [E1] [E2] tags</text>
|
||||
<text text-anchor="middle" x="506.5" y="-42.9" font-family="Helvetica,sans-Serif" font-size="12.00">(never types the quote string)</text>
|
||||
<path fill="#f0e6ff" stroke="black" d="M629,-102C629,-102 441,-102 441,-102 435,-102 429,-96 429,-90 429,-90 429,-54 429,-54 429,-48 435,-42 441,-42 441,-42 629,-42 629,-42 635,-42 641,-48 641,-54 641,-54 641,-90 641,-90 641,-96 635,-102 629,-102"/>
|
||||
<text text-anchor="middle" x="535" y="-88.4" font-family="Helvetica,sans-Serif" font-size="12.00">Language model</text>
|
||||
<text text-anchor="middle" x="535" y="-75.4" font-family="Helvetica,sans-Serif" font-size="12.00">sees: question + labelled chunks</text>
|
||||
<text text-anchor="middle" x="535" y="-62.4" font-family="Helvetica,sans-Serif" font-size="12.00">emits: prose tagged [E1] [E2]</text>
|
||||
<text text-anchor="middle" x="535" y="-49.4" font-family="Helvetica,sans-Serif" font-size="12.00">(never types the quote text)</text>
|
||||
</g>
|
||||
<!-- pointers->model -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>pointers->model</title>
|
||||
<path fill="none" stroke="black" d="M378.17,-72C383.46,-72 388.98,-72 394.64,-72"/>
|
||||
<polygon fill="black" stroke="black" points="394.95,-75.5 404.95,-72 394.95,-68.5 394.95,-75.5"/>
|
||||
<path fill="none" stroke="black" d="M402.25,-72C407.58,-72 413.11,-72 418.74,-72"/>
|
||||
<polygon fill="black" stroke="black" points="418.99,-75.5 428.99,-72 418.99,-68.5 418.99,-75.5"/>
|
||||
</g>
|
||||
<!-- verifier -->
|
||||
<g id="node5" class="node">
|
||||
<title>verifier</title>
|
||||
<path fill="#fff3d6" stroke="black" d="M849,-102C849,-102 719,-102 719,-102 713,-102 707,-96 707,-90 707,-90 707,-54 707,-54 707,-48 713,-42 719,-42 719,-42 849,-42 849,-42 855,-42 861,-48 861,-54 861,-54 861,-90 861,-90 861,-96 855,-102 849,-102"/>
|
||||
<text text-anchor="middle" x="784" y="-88.4" font-family="Helvetica,sans-Serif" font-size="12.00">verifier</text>
|
||||
<text text-anchor="middle" x="784" y="-75.4" font-family="Helvetica,sans-Serif" font-size="12.00">(quote · span · entity</text>
|
||||
<text text-anchor="middle" x="784" y="-62.4" font-family="Helvetica,sans-Serif" font-size="12.00">· paraphrase — binary,</text>
|
||||
<text text-anchor="middle" x="784" y="-49.4" font-family="Helvetica,sans-Serif" font-size="12.00">no LLM call)</text>
|
||||
<path fill="#fff3d6" stroke="black" d="M984,-95.5C984,-95.5 827,-95.5 827,-95.5 821,-95.5 815,-89.5 815,-83.5 815,-83.5 815,-60.5 815,-60.5 815,-54.5 821,-48.5 827,-48.5 827,-48.5 984,-48.5 984,-48.5 990,-48.5 996,-54.5 996,-60.5 996,-60.5 996,-83.5 996,-83.5 996,-89.5 990,-95.5 984,-95.5"/>
|
||||
<text text-anchor="middle" x="905.5" y="-81.9" font-family="Helvetica,sans-Serif" font-size="12.00">Verifier</text>
|
||||
<text text-anchor="middle" x="905.5" y="-68.9" font-family="Helvetica,sans-Serif" font-size="12.00">four mechanical strategies,</text>
|
||||
<text text-anchor="middle" x="905.5" y="-55.9" font-family="Helvetica,sans-Serif" font-size="12.00">no model in the loop</text>
|
||||
</g>
|
||||
<!-- model->verifier -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>model->verifier</title>
|
||||
<path fill="none" stroke="black" d="M608.13,-72C637.15,-72 668.55,-72 696.63,-72"/>
|
||||
<polygon fill="black" stroke="black" points="696.81,-75.5 706.81,-72 696.81,-68.5 696.81,-75.5"/>
|
||||
<text text-anchor="middle" x="657.5" y="-87.2" font-family="Helvetica,sans-Serif" font-size="11.00">answer</text>
|
||||
<text text-anchor="middle" x="657.5" y="-75.2" font-family="Helvetica,sans-Serif" font-size="11.00">+ pointer IDs</text>
|
||||
<path fill="none" stroke="black" d="M641.1,-72C692.45,-72 753.92,-72 804.56,-72"/>
|
||||
<polygon fill="black" stroke="black" points="804.87,-75.5 814.87,-72 804.87,-68.5 804.87,-75.5"/>
|
||||
<text text-anchor="middle" x="728" y="-75.2" font-family="Helvetica,sans-Serif" font-size="11.00">answer with [E1] [E2] tags</text>
|
||||
</g>
|
||||
<!-- label_strict -->
|
||||
<!-- label_grounded -->
|
||||
<g id="node6" class="node">
|
||||
<title>label_strict</title>
|
||||
<path fill="#28a745" stroke="black" d="M1023.5,-144C1023.5,-144 913.5,-144 913.5,-144 907.5,-144 901.5,-138 901.5,-132 901.5,-132 901.5,-120 901.5,-120 901.5,-114 907.5,-108 913.5,-108 913.5,-108 1023.5,-108 1023.5,-108 1029.5,-108 1035.5,-114 1035.5,-120 1035.5,-120 1035.5,-132 1035.5,-132 1035.5,-138 1029.5,-144 1023.5,-144"/>
|
||||
<text text-anchor="middle" x="968.5" y="-129.4" font-family="Helvetica,sans-Serif" font-size="12.00" fill="white">STRICT</text>
|
||||
<text text-anchor="middle" x="968.5" y="-116.4" font-family="Helvetica,sans-Serif" font-size="12.00" fill="white">every claim verifies</text>
|
||||
<title>label_grounded</title>
|
||||
<path fill="#28a745" stroke="black" d="M1158.5,-144C1158.5,-144 1048.5,-144 1048.5,-144 1042.5,-144 1036.5,-138 1036.5,-132 1036.5,-132 1036.5,-120 1036.5,-120 1036.5,-114 1042.5,-108 1048.5,-108 1048.5,-108 1158.5,-108 1158.5,-108 1164.5,-108 1170.5,-114 1170.5,-120 1170.5,-120 1170.5,-132 1170.5,-132 1170.5,-138 1164.5,-144 1158.5,-144"/>
|
||||
<text text-anchor="middle" x="1103.5" y="-129.4" font-family="Helvetica,sans-Serif" font-size="12.00" fill="white">grounded</text>
|
||||
<text text-anchor="middle" x="1103.5" y="-116.4" font-family="Helvetica,sans-Serif" font-size="12.00" fill="white">every claim verifies</text>
|
||||
</g>
|
||||
<!-- verifier->label_strict -->
|
||||
<!-- verifier->label_grounded -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>verifier->label_strict</title>
|
||||
<path fill="none" stroke="black" d="M861.07,-94.51C872.92,-98.01 885.11,-101.62 896.83,-105.09"/>
|
||||
<polygon fill="black" stroke="black" points="895.96,-108.48 906.54,-107.96 897.95,-101.77 895.96,-108.48"/>
|
||||
<title>verifier->label_grounded</title>
|
||||
<path fill="none" stroke="black" d="M991.9,-95.53C1003.75,-98.79 1015.84,-102.13 1027.48,-105.33"/>
|
||||
<polygon fill="black" stroke="black" points="1026.56,-108.71 1037.13,-107.99 1028.42,-101.96 1026.56,-108.71"/>
|
||||
</g>
|
||||
<!-- label_hybrid -->
|
||||
<!-- label_partial -->
|
||||
<g id="node7" class="node">
|
||||
<title>label_hybrid</title>
|
||||
<path fill="#ffc107" stroke="black" d="M1037,-90C1037,-90 900,-90 900,-90 894,-90 888,-84 888,-78 888,-78 888,-66 888,-66 888,-60 894,-54 900,-54 900,-54 1037,-54 1037,-54 1043,-54 1049,-60 1049,-66 1049,-66 1049,-78 1049,-78 1049,-84 1043,-90 1037,-90"/>
|
||||
<text text-anchor="middle" x="968.5" y="-75.4" font-family="Helvetica,sans-Serif" font-size="12.00">HYBRID</text>
|
||||
<text text-anchor="middle" x="968.5" y="-62.4" font-family="Helvetica,sans-Serif" font-size="12.00">some verify, some don't</text>
|
||||
<title>label_partial</title>
|
||||
<path fill="#ffc107" stroke="black" d="M1172,-90C1172,-90 1035,-90 1035,-90 1029,-90 1023,-84 1023,-78 1023,-78 1023,-66 1023,-66 1023,-60 1029,-54 1035,-54 1035,-54 1172,-54 1172,-54 1178,-54 1184,-60 1184,-66 1184,-66 1184,-78 1184,-78 1184,-84 1178,-90 1172,-90"/>
|
||||
<text text-anchor="middle" x="1103.5" y="-75.4" font-family="Helvetica,sans-Serif" font-size="12.00">partly grounded</text>
|
||||
<text text-anchor="middle" x="1103.5" y="-62.4" font-family="Helvetica,sans-Serif" font-size="12.00">some verify, some don't</text>
|
||||
</g>
|
||||
<!-- verifier->label_hybrid -->
|
||||
<!-- verifier->label_partial -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>verifier->label_hybrid</title>
|
||||
<path fill="none" stroke="black" d="M861.07,-72C866.44,-72 871.87,-72 877.31,-72"/>
|
||||
<polygon fill="black" stroke="black" points="877.72,-75.5 887.72,-72 877.72,-68.5 877.72,-75.5"/>
|
||||
<title>verifier->label_partial</title>
|
||||
<path fill="none" stroke="black" d="M996.18,-72C1001.59,-72 1007.03,-72 1012.43,-72"/>
|
||||
<polygon fill="black" stroke="black" points="1012.77,-75.5 1022.77,-72 1012.77,-68.5 1012.77,-75.5"/>
|
||||
</g>
|
||||
<!-- label_ungrounded -->
|
||||
<g id="node8" class="node">
|
||||
<title>label_ungrounded</title>
|
||||
<path fill="#dc3545" stroke="black" d="M1009,-36C1009,-36 928,-36 928,-36 922,-36 916,-30 916,-24 916,-24 916,-12 916,-12 916,-6 922,0 928,0 928,0 1009,0 1009,0 1015,0 1021,-6 1021,-12 1021,-12 1021,-24 1021,-24 1021,-30 1015,-36 1009,-36"/>
|
||||
<text text-anchor="middle" x="968.5" y="-21.4" font-family="Helvetica,sans-Serif" font-size="12.00" fill="white">UNGROUNDED</text>
|
||||
<text text-anchor="middle" x="968.5" y="-8.4" font-family="Helvetica,sans-Serif" font-size="12.00" fill="white">none verify</text>
|
||||
<path fill="#dc3545" stroke="black" d="M1140,-36C1140,-36 1067,-36 1067,-36 1061,-36 1055,-30 1055,-24 1055,-24 1055,-12 1055,-12 1055,-6 1061,0 1067,0 1067,0 1140,0 1140,0 1146,0 1152,-6 1152,-12 1152,-12 1152,-24 1152,-24 1152,-30 1146,-36 1140,-36"/>
|
||||
<text text-anchor="middle" x="1103.5" y="-21.4" font-family="Helvetica,sans-Serif" font-size="12.00" fill="white">not grounded</text>
|
||||
<text text-anchor="middle" x="1103.5" y="-8.4" font-family="Helvetica,sans-Serif" font-size="12.00" fill="white">none verify</text>
|
||||
</g>
|
||||
<!-- verifier->label_ungrounded -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>verifier->label_ungrounded</title>
|
||||
<path fill="none" stroke="black" d="M861.07,-49.49C876.09,-45.05 891.68,-40.44 906.14,-36.16"/>
|
||||
<polygon fill="black" stroke="black" points="907.35,-39.45 915.94,-33.25 905.36,-32.74 907.35,-39.45"/>
|
||||
<path fill="none" stroke="black" d="M991.9,-48.47C1009.75,-43.55 1028.18,-38.48 1044.74,-33.91"/>
|
||||
<polygon fill="black" stroke="black" points="1046.08,-37.17 1054.79,-31.14 1044.22,-30.43 1046.08,-37.17"/>
|
||||
</g>
|
||||
<!-- audit -->
|
||||
<g id="node9" class="node">
|
||||
<title>audit</title>
|
||||
<polygon fill="#fde7e9" stroke="black" points="1274,-95.5 1076,-95.5 1076,-48.5 1280,-48.5 1280,-89.5 1274,-95.5"/>
|
||||
<polyline fill="none" stroke="black" points="1274,-95.5 1274,-89.5 "/>
|
||||
<polyline fill="none" stroke="black" points="1280,-89.5 1274,-89.5 "/>
|
||||
<text text-anchor="middle" x="1178" y="-81.9" font-family="Helvetica,sans-Serif" font-size="12.00">audit chain</text>
|
||||
<text text-anchor="middle" x="1178" y="-68.9" font-family="Helvetica,sans-Serif" font-size="12.00">+ providence cache</text>
|
||||
<text text-anchor="middle" x="1178" y="-55.9" font-family="Helvetica,sans-Serif" font-size="12.00">(8-dim key, governance-aware)</text>
|
||||
<polygon fill="#fde7e9" stroke="black" points="1375,-95.5 1211,-95.5 1211,-48.5 1381,-48.5 1381,-89.5 1375,-95.5"/>
|
||||
<polyline fill="none" stroke="black" points="1375,-95.5 1375,-89.5 "/>
|
||||
<polyline fill="none" stroke="black" points="1381,-89.5 1375,-89.5 "/>
|
||||
<text text-anchor="middle" x="1296" y="-81.9" font-family="Helvetica,sans-Serif" font-size="12.00">Audit chain</text>
|
||||
<text text-anchor="middle" x="1296" y="-68.9" font-family="Helvetica,sans-Serif" font-size="12.00">+ answer cache</text>
|
||||
<text text-anchor="middle" x="1296" y="-55.9" font-family="Helvetica,sans-Serif" font-size="12.00">(reproducible, replayable)</text>
|
||||
</g>
|
||||
<!-- label_strict->audit -->
|
||||
<!-- label_grounded->audit -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>label_strict->audit</title>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M1035.72,-108.77C1048.7,-105.39 1062.59,-101.77 1076.4,-98.18"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="1077.63,-101.48 1086.43,-95.57 1075.87,-94.7 1077.63,-101.48"/>
|
||||
<title>label_grounded->audit</title>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M1168.2,-107.94C1179.18,-104.83 1190.8,-101.54 1202.37,-98.26"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="1203.39,-101.61 1212.05,-95.51 1201.48,-94.87 1203.39,-101.61"/>
|
||||
</g>
|
||||
<!-- label_hybrid->audit -->
|
||||
<!-- label_partial->audit -->
|
||||
<g id="edge9" class="edge">
|
||||
<title>label_hybrid->audit</title>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M1049.13,-72C1054.63,-72 1060.23,-72 1065.85,-72"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="1065.99,-75.5 1075.99,-72 1065.99,-68.5 1065.99,-75.5"/>
|
||||
<title>label_partial->audit</title>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M1184.19,-72C1189.53,-72 1194.94,-72 1200.35,-72"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="1200.72,-75.5 1210.72,-72 1200.72,-68.5 1200.72,-75.5"/>
|
||||
</g>
|
||||
<!-- label_ungrounded->audit -->
|
||||
<g id="edge10" class="edge">
|
||||
<title>label_ungrounded->audit</title>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M1021.06,-31.42C1038,-35.83 1057.45,-40.89 1076.75,-45.91"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="1075.94,-49.32 1086.5,-48.45 1077.7,-42.54 1075.94,-49.32"/>
|
||||
<path fill="none" stroke="#888888" stroke-dasharray="5,2" d="M1152.08,-31.49C1167.19,-35.77 1184.45,-40.66 1201.63,-45.53"/>
|
||||
<polygon fill="#888888" stroke="#888888" points="1201.15,-49.03 1211.73,-48.39 1203.06,-42.3 1201.15,-49.03"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 9.6 KiB |