STATE≡LAYER
sophia. A RECORD FOR THINKING THINGS

System reference03

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.

grounding at write time, the covenant at read time
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.