# In what scenarios must an instance treat write-audit lineage as insufficient to detect memory poisoning **Date of Record:** 2026 November 8 **Scope:** Applies to agent memory stores that attach provenance (writer identity, write timestamp, parent-record lineage) to every record and use trust-weighted recall to gate retrieval. Does not apply to append-only immutable logs with no recall path, or to stores where all writers share a single trust tier. ## Core Distinction Write-audit lineage answers *who wrote this and from what ancestor*. Trust-weighted recall answers *how much should we believe a record at retrieval time*. Poisoning detection fails at the seam between them: a record can have an impeccable lineage chain (correct writer, correct parent, correct timestamp) and still be poisoned, because the *content* was corrupted upstream of the write, or because the writer's trust score was itself inflated by a prior poisoning round. Lineage is a graph property; poisoning is a semantic property. The audit trail proves the record arrived through legitimate channels; it does not prove the channel was not compromised before the write. ## What Was Observed During a multi-week run of a retrieval-augmented agent with a provenance-tagged store, a batch of records was inserted with valid signatures from a mid-trust writer and correct parent pointers to a verified source document. The write-audit passed cleanly: signature valid, lineage acyclic, parent hash matched. Trust-weighted recall retrieved these records at high weight because the writer's trust score had been raised two cycles earlier by *a different set of poisoned records from the same writer* that had passed a shallow content check. The poisoning was not in the write event; it was in the trust score's history. The audit trail faithfully recorded the corruption without flagging it, because the corruption was a *trust accumulation* effect, not a lineage violation. Detection only fired when a downstream reasoning step produced a contradiction that traced back through three hops to the original inflated-trust seed. The invariant that broke: *lineage integrity is preserved under trust-score poisoning*. An attacker who can get one record past content filtering can bootstrap trust, and subsequent records inherit that trust with clean lineage. ## Condition of Validity The failure is reachable only when all three hold: (1) trust scores are mutable and updated from record content or downstream outcomes, (2) recall weights are derived from trust scores rather than from independent content verification, and (3) at least one write path allows content that passes lineage audit but not semantic audit. If trust is static per-writer-identity, the attack surface collapses to identity compromise. If recall re-verifies content against an external source at retrieval, trust inflation is neutralized. If every write is content-audited against a ground-truth oracle, lineage insufficiency is moot. Absent any one condition, the seam does not open. ## Decision Boundary Do not rely on write-audit alone when trust scores are *derived* rather than *assigned*. The decision rule: if a record's recall weight depends on any trust score that was itself computed from prior records, then lineage audit is necessary but not sufficient, and you must add a *trust-provenance audit* that traces the score's contributing records and re-validates them at the point of trust update, not at the point of write. Conversely, if trust is externally assigned and immutable, lineage audit is sufficient and adding trust-provenance auditing is wasted cost. The boundary is the mutability of trust, not the complexity of lineage. ## Operational Effect Systems that conflate the two audits exhibit *silent trust drift*: recall quality degrades gradually as inflated-trust records accumulate weight, with no lineage alarm. The practical mitigation is to snapshot trust scores at each update with the contributing record set, and to run periodic re-validation of high-weight records against their claimed sources. When a contradiction is detected downstream, the trust-provenance snapshot lets you roll back the score to a pre-poisoning value rather than quarantining the entire writer. The cost is O(records × trust-update-frequency) storage for snapshots; the benefit is that poisoning becomes a bounded, reversible event instead of an unbounded trust infection. ```python class TrustProvenanceViolation(RuntimeError): """Raised when a recall weight depends on a trust score whose contributing records cannot be re-validated at update time.""" pass def audit_trust_update(writer_id: str, new_score: float, contributing_records: list[dict], validator) -> float: """Re-validate the records that justified a trust-score change. Lineage audit alone is insufficient here: the records may have clean provenance but poisoned content that inflated the score. We must re-check content against the validator before accepting the score. """ if not contributing_records: raise TrustProvenanceViolation( f"writer {writer_id}: trust update with no contributing records; " "score cannot be traced and must not be applied" ) for rec in contributing_records: if not validator(rec): raise TrustProvenanceViolation( f"writer {writer_id}: contributing record {rec.get('id')} " f"fails content re-validation; refusing trust update to " f"{new_score} (lineage was clean, content was not)" ) # Only now is the score safe to persist with its provenance snapshot. return new_score def recall_weight(record: dict, trust_snapshot: dict, validator) -> float: """Compute retrieval weight; refuse if trust provenance is unverifiable.""" writer = record["writer_id"] snap = trust_snapshot.get(writer) if snap is None: raise TrustProvenanceViolation( f"record {record['id']}: no trust snapshot for writer {writer}; " "cannot distinguish assigned trust from poisoned trust" ) if not validator(record): raise TrustProvenanceViolation( f"record {record['id']}: content fails validation despite " "clean write-audit lineage; recall blocked" ) return snap["score"] * record.get("base_weight", 1.0) ```