ADR-029: Per-fact trust & freshness: a deterministic, explainable score
Date: 2026-06-12 Status: Accepted (owner-delegated review, 2026-06-12) Author: Rômulo Febasi
Context
The most-cited unsolved failure mode in agent memory is “stale facts served
with high confidence” (a production mem0 audit found 97.8% junk over 32 days).
Synapse should surface a per-fact trust/freshness signal in show, search,
and MCP so stale-but-confident memory is visibly flagged. It must be
deterministic and explainable (a closed-form arithmetic over data already
stored (x-ai-* provenance, confidence tier from ADR-022, timestamps,
supersession from ADR-027, ed25519 signing)) never an opaque ML confidence
number, which would manufacture exactly the false authority that memory-poisoning
exploits. The same paper’s edge-weighting findings ground the semantic-edge
weight that SYN-245 needs. Implements SYN-241 (trust) and the weight half of
SYN-245 (edges).
Decision
Per-fact trust = multiplicative composition (Weighted Product Model: it is dimensionless, needs no weight tuning, and lets any single collapsing dimension veto the whole, which is the correct behaviour for “stale OR contradicted ⇒ low regardless of the rest”):
TRUST(fact) = Confidence × Freshness × SupersessionPenalty × ProvenanceGate
All four factors ∈ (0, 1]; output ∈ [0, 1]; each is independently inspectable, that is the explanation.
- Confidence: Beta / subjective-logic projected probability. With
rindependent corroborations,scontradictions, prior weightW = 2, and base rateakeyed to the ADR-022 tier:Confidence = (r + a·W) / (r + s + W), witha = 0.60auto-accepted,0.85human-accepted,0.95signed/identity. A new fact sits at its tier prior with full uncertainty; corroboration raises it, contradiction lowers it. The raw opinion(b, d, u),u = W/(r+s+W),b = r/(r+s+W): is surfaced as a decision aid (see below). - Freshness: ACT-R base-level activation, squashed. With reinforcement-event
ages
t₁…tₙ(days) and decayd = 0.5:B = ln(Σⱼ tⱼ^(−d)),Freshness = σ((B − B₀)/s). The O(1)-state approximationB ≈ ln(n/(1−d)) − d·ln(L)(store only countnand first-seen ageL) is permitted when per-access timestamps aren’t kept. Recency and frequency compose in one validated formula. - SupersessionPenalty:
γ^k,γ = 0.5, wherekis supersession depth (the current head fact hask = 0). Superseded facts sink fast but never hit zero (they remain auditable history). - ProvenanceGate: a coarse, honest, discrete multiplier (not a fake
continuous knob):
1.0cryptographically signed,0.9human-accepted unsigned,0.8auto-accepted (ADR-022 safe tier).
Display is banded (one of five bands, or ≤2 decimals) never 3-decimal false
precision. All constants (a, γ, d, gate buckets, B₀, s) are
config-exposed defaults to calibrate on real data, not laws; B₀/s are set
from a histogram of actual fact ages before locking.
Semantic-edge weight (SYN-245). Do not threshold raw cosine: in high
dimensions cosines concentrate, so absolute thresholds drift and aren’t
comparable across regions. Gate edges by mutual-kNN (k ≈ 10: keep (i,j)
iff j ∈ kNN(i) and i ∈ kNN(j)), then weight by a local-baseline rescale:
weight(i,j) = max(0, (cos(i,j) − μ_local)/(1 − μ_local)), where μ_local is
the mean cosine of i to its k neighbours. For co-occurrence edges (two
entities in the same note, no embedding) use clamped NPMI ∈ [0,1], which
discounts ubiquitous entities exactly like IDF, formalizing “high-value,
high-recurrence” as recurring together more than chance, not merely frequent.
Consequences
- Improves: a deterministic, per-term-explainable trust signal that directly
answers “stale served as confident”; the ACT-R activation
Bdoubles as a declarative-memory retrieval prior for ranking (relevance × Freshness); surfacing(b, d, u)distinguishes “uncertain: go corroborate” from “disputed: go resolve”. Edge weights are calibration-free (rank-based), so the live graph (SYN-244/245) stays meaningful across embedding models. - Worsens: constants need calibration on real data; the σ centering (
B₀,s) needs a quick spike (naiveσ(B)clusters near 0.5); freshness needs either per-access timestamps or the(n, L)approximation stored per fact. - Open: exact
B₀/sfrom an age histogram; per-access vs optimized state; the moment multiple signing identities co-assert a fact, the Beta(r, s)model extends cleanly to a real trust graph: revisit then (not now).
Alternatives considered
- EigenTrust / PageRank over facts. Need a population of mutually-rating agents; a single offline user makes the trust matrix rank-1 and the eigenvector trivial. (PageRank is fine for entity centrality: importance, not trust, and must never be silently multiplied into TRUST.) Rejected for trust.
- Additive weighted sum (
w₁·conf + w₂·fresh + …). Hides that a stale-but-confident and a fresh-but-dubious fact can score identically, and demands normalization that silently reorders results. Multiplicative composition is veto-respecting and tuning-free. Rejected. - Continuous provenance score. “Signed” is binary information; a smooth
provenance ∈ [0,1]is false precision. Three buckets. Rejected. - Absolute cosine thresholds for edges (e.g.
cos > 0.8). Drift with model, dimension, and local density. Rank-based mutual-kNN has no magic float. Rejected. - More than ~4 factors / 3-decimal display. Each extra multiplicand drags scores toward 0 and dilutes explainability; the math doesn’t support 3 significant figures. Rejected.
Research grounding
Jøsang, Subjective Logic; Jøsang & Ismail, Beta Reputation System; ACT-R base-level activation (Anderson & Schooler 1991); Ebbinghaus forgetting curve; SM-2 / SuperMemo; BM25 IDF (Robertson/Spärck-Jones); Pointwise Mutual Information / NPMI; Wilson score interval (Miller, How Not to Sort by Average Rating); concentration of measure + mutual-kNN (curse of dimensionality); Weighted Product Model / composite-index theory.