TekmerDB doesn't ask an LLM how much to trust a claim. Every PFO's confidence is a number produced by fixed arithmetic over three inputs — the confidence you declared, what an NLI classifier finds when it's compared to related claims, and the track record of the source it came from. Same inputs, same score, every time.
Whatever you insert with — POST /pfo, the insert_pfo MCP tool, or tekmerdb-ingest --confidence (default 0.7) — is just the starting value. Everything from here on is what the engine does to that number mechanically, independent of what was originally asserted.
Before confidence math even applies, the claim's embedding has to belong. The engine builds a running domain centroid from the first cold_start_inserts claims (default 10). After that, every new claim's cosine similarity to the centroid is checked against domain_threshold (default 0.70) — fall short and the claim is rejected outright, with no confidence at all, because it was never stored. See Configure → Domain enforcement.
Once accepted, the engine pulls the hnsw_top_k nearest neighbours (default 20) by embedding similarity, but only considers ones from a different source — a source doesn't corroborate or conflict with itself. Any candidate below similarity_floor (default 0.85) is skipped entirely: below that threshold, two claims are treated as different topics, not evaluated for agreement or disagreement.
For every candidate that clears the similarity floor, a natural-language-inference model classifies the pair in both directions (claim A implies claim B, and claim B implies claim A), each producing contradiction / entailment / neutral probabilities. The two results combine into one of five outcomes:
| Outcome | When it fires |
|---|---|
| Contradiction | Either direction's contradiction probability > 0.5 |
| Corroboration | Both directions' entailment probability > 0.5 — or similarity > 0.95 with entailment > 0.3 both ways (a reworded restatement of the same fact) |
| Subsumption | One direction entails, the other is neutral — the claims are related but at different scope (one is more specific/general). Stored independently, confidence untouched. |
| Uncertain | A weak contradiction signal (probability between 0.3 and 0.5) that didn't clear the threshold either way |
| Unrelated | None of the above — ignored |
| Outcome | Effect on confidence |
|---|---|
| Contradiction | Both claims drop 25%: confidence × 0.75. Both are cross-referenced in each other's conflict_refs — the disagreement is recorded, not hidden or resolved in either direction's favour. |
| Corroboration | Both claims are set to 1 − (1 − confidence) × (1 − source_weight), where source_weight is the corroborating source's current effective_weight (step 6). The more reliable that source has been, the closer the result climbs to 1. |
| Uncertain | A small penalty on both: confidence × 0.95. |
| Subsumption / Unrelated | No change. |
Every source starts neutral, at effective_weight = 0.5. It moves mechanically as it corroborates or conflicts with others:
effective_weight = 1 − (1 − effective_weight) × 0.95 — each corroboration closes 5% of the remaining gap to 1.0, an asymptotic climb that never quite reaches it.effective_weight ×= 0.90 — a flat 10% cut, charged to the source that introduced the new, conflicting claim.This weight feeds straight back into step 5's corroboration formula — a source that keeps getting corroborated lifts the confidence of what it corroborates more over time; one that keeps triggering conflicts contributes less and less. Check any source's current standing with get_source (MCP) or GET /source?name=.
1. Insert "North Sea wind capacity reached 35 GW in 2024" confidence 0.80, source "IEA Energy Report" (new source, weight 0.500) → no related claims yet, stored as-is: confidence 0.800 2. Insert "North Sea offshore wind hit roughly 35 GW in 2024" confidence 0.75, source "Grid Report 2024" (new source, weight 0.500) → similarity 0.93, NLI: entails both ways → CORROBORATION → new confidence = 1 - (1 - 0.75) x (1 - 0.500) = 0.875 → both claims now: confidence 0.875 → source "Grid Report 2024" weight: 1 - (1 - 0.500) x 0.95 = 0.525 3. Insert "North Sea wind capacity fell to 20 GW in 2024" confidence 0.80, source "Lobby Group" (new source, weight 0.500) → similarity 0.91 vs claim #1, NLI: contradicts → CONTRADICTION → both drop 25%: claim #3 → 0.600, claim #1 → 0.656 → source "Lobby Group" weight: 0.500 x 0.90 = 0.450
Nothing here was guessed. Every number is reproducible from the claim text, the embeddings, and the two sources' prior history.
A human or agent can set a PFO's confidence directly — update_confidence (MCP) or PATCH /pfo/:id/confidence — but only with a documented reason. It's recorded as an explicit override, not folded silently into the mechanical trail, so the EU AI Act audit history shows exactly when and why a human stepped in.