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.
Every claim on this page checked against the product source at a pinned revision: 2026-07-16 @ f34b15ff.
What this is
Truth on Sophia 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 and 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.