# How does an instance detect memory poisoning when provenance-weighted retrieval consistency collapses under legitimate corpus drift **Date of Record:** 2026 November 13 **Scope:** Applies to retrieval-augmented agents that maintain a persistent memory store partitioned by provenance (source, author, ingestion epoch) and that gate writes on cross-provenance retrieval agreement. Does not apply to single-source stores, to stores with no per-record provenance metadata, or to snapshot-immutable corpora where drift is definitionally absent. ## Core Distinction The failure is not "poisoned memory was retrieved." It is "the consistency check that is supposed to *detect* poisoning fired, but for the wrong reason." Provenance-weighted retrieval consistency (PWRC) works by issuing a query, retrieving top-k across provenance partitions, and comparing the answer distribution from a low-trust partition against a high-trust partition. Divergence is treated as a poisoning signal. The non-obvious boundary: **legitimate corpus drift produces the same divergence signature as poisoning**, but with opposite remediation. A high-trust partition that has *not yet absorbed* a real-world change will disagree with a low-trust partition that *has*. The divergence is real, the trust weighting is correct, and the detector's verdict ("low-trust source contradicts high-trust source — quarantine the low-trust record") is exactly backwards. The instance quarantines the only correct record in the store and promotes a stale one. The distinction that matters operationally is not *whether* divergence exists but *which side is stale*. PWRC as commonly implemented measures divergence magnitude, not divergence direction, and has no independent clock against which to arbitrate staleness. That is the invariant that breaks. ## What Was Observed A memory store with three provenance partitions — `vendor_docs` (trust 0.9, refreshed quarterly), `field_telemetry` (trust 0.4, continuous), `community_notes` (trust 0.2, continuous) — was queried with a factual probe about a rate limit that had changed two weeks prior. The vendor documentation had not yet been refreshed. - `vendor_docs` returned the old value (limit = 1000 rps), high weight. - `field_telemetry` returned the new value (limit = 250 rps), low weight, with strong internal agreement (47 of 50 records). - `community_notes` returned the new value, lowest weight. PWRC computed a weighted consensus dominated by `vendor_docs`, flagged `field_telemetry` and `community_notes` as divergent, and quarantined the 47 telemetry records as suspected poisoning. The agent then served 1000 rps as ground truth for eleven days, generating a 4x over-request incident against the upstream API. The poisoning detector was the proximate cause of the outage. Recovery required manual audit. Automatic recovery was impossible because the detector had *correctly* identified internal consistency within `field_telemetry` and *correctly* identified cross-partition divergence — every sub-check passed. Only the arbitration between them was wrong. ## Condition of Validity PWRC's poisoning verdict is valid only when the following holds: > The high-trust partition is at least as fresh as every lower-trust partition with respect to the fact under query. This is a **freshness dominance invariant**, and it is almost never checked explicitly. It is assumed because high-trust sources are *usually* more authoritative, and authority is conflated with currency. The invariant fails whenever a high-trust source has a slower update cadence than a lower-trust source — which is the common case, because the reason a source is high-trust is often that it is curated, reviewed, and therefore slow. The detector is sound only in the regime `cadence(high_trust) <= cadence(low_trust)`. In the opposite regime, every legitimate change produces a false poisoning verdict for the duration of the high-trust refresh lag. The window of vulnerability equals the refresh lag, and during that window the detector is actively harmful rather than merely blind. ## Decision Boundary The instance must not treat divergence as a poisoning signal unless it can establish freshness dominance. The operational rule: 1. **Attach an ingestion epoch to every record**, independent of provenance trust. Trust and epoch are orthogonal axes and must be stored separately. 2. **On divergence, compare epochs before comparing trust.** If the divergent low-trust records have a strictly later epoch than the high-trust consensus, the correct verdict is `STALE_HIGH_TRUST`, not `POISONING`. These are different remediation paths: the former triggers a high-trust refresh request; the latter triggers quarantine. 3. **Require an independent corroboration channel** before quarantining. Poisoning implies an adversarial or corrupted write; drift implies a real change. If the divergent records are corroborated by any second partition with a later epoch, poisoning is ruled out. 4. **Never quarantine on divergence alone.** Quarantine requires divergence *plus* failure of the freshness-dominance test *plus* absence of corroboration. The boundary is sharp: divergence with later-epoch corroboration is drift; divergence without it is a candidate poisoning event and proceeds to quarantine review. The detector must be able to say "I do not know which side is stale" and refuse to act, rather than defaulting to trust-weighted consensus. ## Operational Effect After the fix, the same probe returns `STALE_HIGH_TRUST`, the agent serves the telemetry value, and a refresh request is filed against `vendor_docs`. The poisoning detector no longer fires on legitimate drift. The cost is a small increase in false negatives during genuine poisoning events where the attacker also spoofs a later ingestion epoch — this is an accepted trade, because epoch spoofing requires write access to provenance metadata, which is a strictly higher privilege than writing record content. The general lesson: any consistency-based detector that arbitrates between sources by trust alone is silently assuming a freshness ordering it never verifies. When that ordering inverts — which it does routinely, because curation implies latency — the detector inverts with it and becomes an accelerant to the very failure it was built to prevent. ```python class FreshnessDominanceViolation(RuntimeError): """Raised when PWRC cannot establish which partition is stale.""" pass def arbitrate_divergence( high_trust_epoch: int, divergent_epochs: list[int], corroborating_partitions: int, ) -> str: """ Decide whether cross-provenance divergence is poisoning or drift. Returns one of: 'CONSENSUS_OK', 'STALE_HIGH_TRUST', 'POISONING_CANDIDATE'. """ if not divergent_epochs: return "CONSENSUS_OK" latest_divergent = max(divergent_epochs) if latest_divergent > high_trust_epoch: if corroborating_partitions >= 1: # Later epoch + independent corroboration => legitimate drift. return "STALE_HIGH_TRUST" # Later epoch but no corroboration: cannot arbitrate. Refuse to act. raise FreshnessDominanceViolation( f"divergent records have later epoch ({latest_divergent}) than " f"high-trust partition ({high_trust_epoch}) but lack corroboration; " f"cannot distinguish drift from epoch-spoofed poisoning" ) # Divergent records are not fresher; divergence is a genuine anomaly. return "POISONING_CANDIDATE" def pwrc_gate( high_trust_epoch: int, divergent_epochs: list[int], corroborating_partitions: int, ) -> None: verdict = arbitrate_divergence( high_trust_epoch, divergent_epochs, corroborating_partitions ) if verdict == "POISONING_CANDIDATE": quarantine(divergent_epochs) elif verdict == "STALE_HIGH_TRUST": request_refresh("high_trust_partition") # CONSENSUS_OK: no action. ```