FINGERPRINT · per-entity MDL

When an entity stops looking like itself

Every cashier, pump, terminal or account gets its own order-k Markov compression model, fit on its ownhistory. Score = the surprise of its recent window in the entity’s ownbits-per-event units. A legitimately refund-heavy lane is never flagged for being refund-heavy — only one that changes. Extends observe from one whole-stream model to one model per entity.

per-entity
each entity is watched against ITSELF, not a global average
2 nulls
a label-shuffle and a no-injection control-world null, every run
calibrated
threshold set at the Nth pct of clean-world noise, not z≥3
refuse-on-null
signal fails its own null → zero alerts emitted

Baseline the entities, then scan

at1 fingerprint baseline pos.csv --entity cashier -o lanes.at1fp
#   40 entities, calibrated threshold z>=3.79 @ far 0.01

at1 fingerprint scan pos.csv --entity cashier --baseline lanes.at1fp
#   RANKED REVIEW QUEUE (a rank is a review, NOT a verdict)
#     #1 cashier_16  z=11.5  <ALERT     #2 cashier_08  z=11.0  <ALERT
#   NULL 2 control world: naive z>=3 fires on 3% of clean windows (the trap)
#     -> CALIBRATED threshold z>=3.79, base false-alarm rate 0.011
#   NULL 1 label-shuffle: AUC 1.00, 3.7 sd above null, p=0.001
#   SIGNAL PASSES ITS NULL -> 3 calibrated alerts. Every alert needs a human.

Self-relative, by design

A returns desk does lots of refunds; a fuel lane almost none. One global model buries the returns desk in false alarms. A per-entity model only reacts to an entity deviating from its own norm.

Two nulls, every run

A per-entity model alwaysfinds “some change” in a recent window. So we run a label-shuffle null (is the ranking real?) and a no-injection control-world null (what does pure noise cost?) on everyscan — and print both. This is a feature, not fine print.

Calibrated, not magic

The threshold is set at the Nth percentile of the control world’s own out-of-sample noise, so the false-alarm rate is chosen and measured, never a hard-coded z≥3 (which fires on noise alone).

A behaviour change is not a crime

  • • The output is a ranked review queueand a calibrated alert set — never a “fraud” label. Every alert needs a human.
  • • New POS software, a trainee, a promotion, a reassigned role, or just a bad day all shift an entity’s pattern. This is a top-of-queue triage aid measured in investigator-hours saved, not in “fraud caught.”
  • • If the signal does not clearly beat its own null, the engine emits zero alerts (kill-criterion) and says so. No accusation, no automated adverse action against any person.
  • • Real fraud is rare, so precision at the operating point on live data will sit below any clean-simulation number. We ship the calibration, honestly, alongside the signal.

Extends AT-1 Observe from one whole-stream baseline to one baseline per entity. Runs local, stdlib-only. “Detected” means statistically surprised versus its own history and its own null, not proven wrongdoing.