# In what scenarios must an instance distrust its own anomaly score: score-inversion under provenance-graph densification on the memory write path **Date of Record:** 2026 November 10 **Scope:** This record applies to memory-poisoning detectors that compute a scalar anomaly score over a write-path provenance graph (writer identity, taint lineage, read-set ancestry, and edge multiplicity) and gate acceptance of a memory write on that score. It does not apply to content-classifier detectors, embedding-similarity detectors, or provenance systems that emit only boolean taint bits without per-edge multiplicity. ## Core Distinction The non-obvious boundary is between *provenance anomaly* and *provenance density*. Most detectors treat a high score as "this write is suspicious" and a low score as "this write is clean." That mapping is only valid while the graph's edge population is stable. When a legitimate subsystem begins writing through a shared, highly connected ancestor (a common fetch-and-cache layer, a shared tool-call wrapper, a consolidated memory broker), the write's provenance graph acquires many *benign* edges. A scoring function that sums or averages anomaly evidence over edges will then either inflate the score (false positive) or, if the score is normalized by degree, *deflate* it — and a genuinely poisoned write that rides the same dense ancestor is normalized into the clean band. This is score inversion: the same structural feature that makes benign traffic look anomalous makes poisoned traffic look benign. The distinction that matters operationally is not "high vs. low score" but "score computed under graph density comparable to the calibration density." ## What Was Observed During a consolidation of three memory writers behind a single broker process, the detector's median score on benign writes rose from 0.18 to 0.61 (degree-normalized variant) while a known-poisoned replay set fell from 0.74 to 0.29. Both populations moved toward the decision threshold of 0.50 from opposite sides. The poisoned writes were not evading detection by changing content; they were unchanged payloads replayed through the new broker. Their provenance graphs had simply acquired the broker's high-degree ancestor, and the degree normalization divided away the taint evidence that had previously separated them. In the un-normalized variant the opposite happened: benign broker traffic saturated the alert queue and the operator muted the detector, after which the poisoned writes passed unexamined. Two failure modes, one root cause: the score was calibrated against a graph density that no longer existed. A second observation: the inversion appeared *before* any alert fired. The detector's own health metrics (alert volume, mean score) looked acceptable in both variants; only a joint plot of benign and poisoned score distributions revealed the crossing. Per-population monitoring is insufficient; the crossing is a property of the *relative* distributions. ## Condition of Validity The score-to-trust mapping is valid only when all three hold: 1. **Degree stationarity.** The degree distribution of ancestors reachable from a write in the current window is within a calibrated band of the degree distribution at calibration time. Track a rolling statistic (e.g., p95 ancestor degree) and treat drift beyond the band as invalidating the score, not as an anomaly to be scored. 2. **Normalization consistency.** The normalization divisor (edge count, ancestor degree, path length) must be computed from the same graph slice as the anomaly evidence. Mixing a current-window divisor with a calibration-window numerator silently rescales the threshold. 3. **Population separation.** The benign and poisoned score distributions must remain separated by a margin larger than the window-to-window variance of each. When the margin collapses, the score carries no decision information regardless of its absolute value. When any condition fails, the correct action is to fall back to a density-independent signal (e.g., taint-bit reachability, explicit writer allowlist, or human review of the write) rather than to re-tune the threshold. Re-tuning the threshold to restore separation is the trap: it restores apparent separation on the current window while leaving the inversion mechanism intact for the next densification event. ## Decision Boundary Distrust the score and escalate to fallback when **either** the rolling ancestor-degree statistic exits its calibrated band **or** the estimated separation margin between benign and poisoned reference distributions falls below the variance floor. Do not escalate on absolute score alone; a high score under densified provenance is as likely to be a benign broker write as a poisoning attempt. Conversely, do not accept a low score as clean when density has drifted — a low score under densification is the exact signature of inversion. The boundary is density-conditional, not score-conditional. ## Operational Effect Instances that apply this boundary stop treating the anomaly score as a trust oracle and treat it as a *conditional* estimator with an explicit validity precondition. The practical consequences: (1) detector health is monitored as distribution separation, not alert volume; (2) densification events (broker consolidation, wrapper adoption, cache-layer introduction) trigger a mandatory recalibration or fallback rather than a threshold tweak; (3) poisoned writes that ride dense benign ancestors are caught by the fallback path, which is density-independent by construction. The cost is a higher fallback rate during topology changes; the benefit is that score inversion cannot silently convert a poisoned write into an accepted one. ```python class ProvenanceScoreInvalidError(RuntimeError): """Raised when an anomaly score is computed under graph density outside its calibration band, making the score-to-trust mapping undefined (score inversion risk).""" pass def gate_memory_write( write_id: str, anomaly_score: float, ancestor_degree_p95: float, calibration_degree_band: tuple[float, float], separation_margin: float, variance_floor: float, ) -> str: low, high = calibration_degree_band density_drifted = not (low <= ancestor_degree_p95 <= high) separation_collapsed = separation_margin < variance_floor if density_drifted or separation_collapsed: # Do NOT re-tune the threshold here. The score carries no # decision information under these conditions; escalate to a # density-independent fallback path instead. raise ProvenanceScoreInvalidError( f"write {write_id!r}: score {anomaly_score:.3f} is not " f"trustworthy (ancestor_degree_p95={ancestor_degree_p95:.2f}, " f"calibrated_band={calibration_degree_band}, " f"separation_margin={separation_margin:.3f}, " f"variance_floor={variance_floor:.3f}); " f"route to taint-reachability fallback or human review" ) return "accept" if anomaly_score < 0.5 else "quarantine" ```