Truth and provenance
A claim only lands in the graph if its evidence is a literal substring of the source, disagreeing claims surface through a query instead of a scroll-back, and a correction you make outranks the model structurally, not by convention.
Verified 2026-07-08 @ 3ee3d0fe
What this is
Truth on Ouroboros is not a confidence score an agent reports about itself. It is two mechanical checks that run whether or not anyone asks for them: a mined claim only lands in the knowledge graph if its evidence quote is a literal substring of the source document, and once you’ve corrected a claim, that correction structurally outranks the model’s version on every later read — not as a ranking preference an agent could ignore, but as a check that runs before a conflicting write is even allowed to land.
Why it exists
An early pass at relationship extraction in this codebase once produced
Example Person employee_of Example Labs, role: CEO from a document that
actually said Benjamin Smith, CEO; reports_to: Director (Example Brian Person) — the model connected the wrong two names with total confidence and
no visible seam. Verbatim-quote grounding exists specifically to catch that
failure: if the claim can’t point at a real sentence, it doesn’t get
written. Contradiction surfacing exists for the sibling failure — two mining
passes asserting different things about the same fact with neither one ever
noticing, because a chat transcript has no WHERE clause to catch it.
And a correction has to actually stick. Telling an agent “no, that’s wrong” inside one conversation doesn’t help if next week’s mining pass or a different agent’s session quietly reasserts the old value. The user-outranks- LLM covenant is the guarantee that a correction is durable state, not a one-turn courtesy.
How it works
Grounding happens at write time, in proxy/src/extraction/claimGraph.ts.
Every claim the extraction model emits carries an evidence string capped
at 300 characters; verifyOne() normalizes both the evidence and the source
text (smart quotes, dashes, markdown bold, unicode arrows all collapse to a
plain form) and runs a literal .includes() check. No match, no write — the
module’s own header comment calls it “a for-loop, not a model, not
negotiable.” The same primitive is exposed as three separate tools for
different moments: sophia.verify_evidence batch-checks a list of quotes
against source text before a mining sub-agent submits anything,
sophia.preflight_not_in_source checks one quote against one document by
id, and sophia.verify_citation re-runs the check against a wiki page’s
current source — catching drift when a document gets edited or re-mined
after the citation was written.
The correction side runs at read time. Every query against the knowledge
table orders corrected_by_user='1' rows first, and the write path checks
for an existing correction before it dedupes or inserts — so a later
extraction pass that would touch the same content is skipped outright, not
merely outranked. Knowledge Graph covers that
row shape in full; this page is about what an agent does once the row is
there.
Two more primitives close the loop. sophia.find_contradictions groups
active claims by (subject, predicate) and flags the ones with disagreeing
objects within the same date bucket, with severity high whenever one side
is a user correction. sophia.evidence_for walks the other direction from a
single fact — its source document, its supersession chain, and any
correction that touched it — in one call instead of three round trips.
flowchart TB
subgraph write["Write-time grounding"]
M["Model emits claim + evidence"] --> V{"normalize + .includes()<br/>against source text"}
V -- match --> ROW[("claim row<br/>in the graph")]
V -- no match --> DROP["dropped — never written"]
end
subgraph read["Read-time covenant"]
ROW --> Q["sophia.query_knowledge"]
U["You correct a claim"] -->|"corrected_by_user='1'<br/>skips future overwrite"| ROW
ROW -->|"ORDER BY corrected_by_user DESC"| Q
end
style U fill:#1a4d2e,stroke:#22c55e,color:#fff
style DROP fill:#3a1a1a,stroke:#ef4444,color:#fff What your agent does with it
// Real responses from this daemon, captured 2026-07-08:
const check = await sophia.verify_evidence({
source_text: 'The daemon journals every write with full before/after JSON...',
quotes: [
{ id: 'real', text: 'journals every write with full before/after JSON' },
{ id: 'fabricated', text: 'encrypts every write with a per-user key' },
],
});
// → { ok: false, found_count: 1, results: [
// { id: 'real', found: true, match_span: [11, 59] },
// { id: 'fabricated', found: false } ] }
const conflicts = await sophia.find_contradictions({ entity_id: 'bb3ad5a2-...' });
// → { contradiction_count: 3, by_severity: { high: 0, medium: 2, low: 1 },
// contradictions: [ { subject: 'ouroboros repo', predicate: 'has_tooling_recommendation',
// objects: [ /* two near-duplicate claims from the same document */ ], severity: 'medium' } ] }
const trail = await sophia.evidence_for({ fact_id: '7bb78a47-...' });
// → { fact: { predicate: 'has_tooling_recommendation', is_active: true },
// bitemporal: { chain_parents: [], chain_children: [] },
// correction: { corrected_by_user: false } } The first call is the grounding primitive itself — one real quote, one fabricated one, run through the same check the extraction pipeline runs on every claim before it writes anything. The second is contradiction surfacing on a live entity: two near-identical tooling recommendations mined from the same document, medium severity because neither side is a user correction. The third is per-fact provenance — on an uncorrected, un- superseded fact the chain comes back empty, which is itself the honest answer: nothing has challenged this claim yet.
Boundaries
Grounding applies to claim-typed rows with a populated evidence field —
the majority of what mining produces day to day (entity_mention and
summary rows carry no evidence to check, and free-text notes written via
sophia.remember_fact never had a source quote in the first place; those
get a force-capped confidence instead, covered on
Knowledge Graph). It categorically does not
cover what an agent says out loud in a response — an agent can still
summarize, extrapolate, or reason past what’s grounded. The check runs once,
at the moment a claim is written to the graph; a fluent paragraph built on
top of three grounded facts and one inference is not itself re-verified
word by word.
What every past version of a corrected or superseded row looked like, and how to revert one, is Time Machine, not this page. The daemon and its storage layers are The State Layer; the full tool catalog these calls are drawn from is MCP Surface; the five enforced rules this page’s mechanics support are laid out end to end at Trust Covenant.