R-CMD-check License: MIT R >= 4.1.0

DecisionDrift

Detecting, Decomposing, and Stress-Testing Temporal Change in Repeated Decision Systems


Overview

DecisionDrift is an R package for auditing temporal drift in repeated binary decision systems — such as algorithmic screening tools, institutional review boards, or any AI system that issues repeated yes/no decisions over time.

It complements the decisionpaths package by shifting focus from path construction to system-level change:

Package Core question
decisionpaths What happened? Path construction, DRI, entropy, equity
DecisionDrift Did the system change? Drift detection, decomposition, stress-testing

Installation

# install.packages("remotes")
remotes::install_github("causalfragility-lab/DecisionDrift")

From CRAN (once accepted)

install.packages("DecisionDrift")

Quick start

library(DecisionDrift)

# --- 1. Build a drift panel object -----------------------------------------
dat <- data.frame(
  id       = rep(1:100, each = 8),
  time     = rep(1:8, times = 100),
  decision = rbinom(800, 1, rep(seq(0.25, 0.55, length.out = 8), 100)),
  group    = rep(c("A", "B"), 50, each = 1)
)

dp <- dd_build(dat, id, time, decision,
               group      = group,
               event_time = 5L)   # known policy change at wave 5

# --- 2. Run the full audit in one call --------------------------------------
aud <- dd_audit(dp)
print(aud)
plot(aud)

# --- 3. Or call individual modules ------------------------------------------
dd_prevalence(dp)      # Was the overall decision rate stable?
dd_transition(dp)      # Did switching/persistence dynamics change?
dd_entropy_trend(dp)   # Did path complexity evolve?
dd_group_drift(dp)     # Did drift differ across groups?
dd_changepoint(dp)     # Where did the system break?

# --- 4. Summary drift indices -----------------------------------------------
dd_indices(dp)
# DDI = Decision Drift Index
# TDI = Transition Drift Index
# GDD = Group Differential Drift
# CDB = Cumulative Drift Burden

# --- 5. Stress-test conclusions ---------------------------------------------
dd_robustness(dp)      # Are conclusions stable across analytic choices?
dd_sensitivity(dp)     # How vulnerable are conclusions to data problems?

## Package architecture

DecisionDrift ├── dd_build() Core: build drift_panel object │ ├── Module 1: dd_prevalence() Drift in decision rate → DDI ├── Module 2: dd_transition() Drift in transition structure → TDI ├── Module 3: dd_entropy_trend() Drift in path complexity / stability ├── Module 4: dd_group_drift() Group-differential drift → GDD ├── Module 5: dd_changepoint() Change-point & regime detection │ ├── dd_indices() All four indices in one call (DDI, TDI, GDD, CDB) │ ├── dd_robustness() Stability across: balanced panel, LOPO, │ LOGO, min_waves grid, bootstrap CIs │ ├── dd_sensitivity() Vulnerability to: miscoding, missingness, │ threshold shifts, composition shifts │ └── dd_audit() Flagship: 3-layer audit → verdict ## The four drift indices

Index Symbol Meaning
Decision Drift Index DDI Standardised linear trend in decision rate. Positive = more permissive over time.
Transition Drift Index TDI Mean absolute change in transition probabilities. Higher = more volatile dynamics.
Group Differential Drift GDD Difference in trend slopes between groups. Non-zero = unequal drift.
Cumulative Drift Burden CDB Total accumulated wave-to-wave rate change (direction-agnostic).

The three-layer audit

dd_audit() follows a deliberate three-layer logic:

  1. Detection — Did the process drift? dd_prevalence(), dd_transition()

  2. Decomposition — Was drift due to prevalence change, transition instability, subgroup divergence, or a regime shift? dd_entropy_trend(), dd_group_drift(), dd_changepoint()

  3. Stress-testing — Are conclusions robust to noise, coding choices, and missing waves? dd_robustness(), dd_sensitivity()

The audit closes with a single verdict: "no drift detected", "marginal drift", "moderate drift", or "strong drift".


Relationship to decisionpaths

decisionpaths answers: What paths occurred, how stable, how entropic, how equitable?

DecisionDrift answers: Did the system itself change, when, how much, for whom, and is that conclusion robust?

They are designed to be used together: build paths with decisionpaths::dp_build(), audit drift with DecisionDrift::dd_audit().

A third package in the ecosystem, AIBias, will ask: Did inequality accumulate or amplify over repeated decisions?


Dependencies

Imports: cli, rlang, stats, tibble

Suggests (for plotting): ggplot2, patchwork


Citation

Hait, S. (2026). DecisionDrift: Detecting, decomposing, and stress-testing temporal change in repeated decision systems. R package version 0.1.0. https://github.com/causalfragility-lab/DecisionDrift


License

MIT © Subir Hait