Hapax · Case study · Theme 3, the data storyteller

Fifty thousand rows, two hundred and sixty-four flags, one story nobody caught

A synthetic Finnish purchase ledger is screened three ways – standard audit rule tests, an anomaly-detection model, and three independent AI analysts – and every layer is marked against a held-out answer key. The rules catch everything rule-shaped. The model catches nothing that matters. The analysts triage all of it cleanly, find the one story only reasoning could reach – and still leave the case’s namesake story on the table.

This dataset is synthetic, engineered with a known answer key: 87 planted anomalous transactions and 18 planted benign exceptions in 50,000 rows (Saarnitukku Oy, a fictional wholesaler; every name is invented; seed 42, fully regenerable). The answer key stays out of every analysis and agent-facing path – it exists so these results can be marked honestly, misses included.
50,000ledger rows, FY2025
264flags: 64 rule + 200 model
87planted anomalies (0.17%)
39 ×3verdict units × blinded runs
2false positives in 117 verdicts
1story caught by nobody

A year of flags

Two automated layers screened the ledger. Seven deterministic rule tests – the audit classics: duplicates, round sums, threshold games, weekend postings, mis-posted accounts – raised 64 flags. An Isolation Forest over eight engineered features raised exactly 200. Every flag was grouped mechanically into 39 verdict units, and three independent analyst runs had to call each one: worry, or stand down, with recomputable evidence either way.

FLAGS PER POSTING MONTH · 2025 JanFebMarAprMayJunJulAugSepOctNovDec 25 26 9
rule-test flags (64) detector flags (200)

Detector flags cluster where the ledger is busiest, at the year-end seasonal peak. They turn out to be statistical texture.

Three layers, marked separately

The rules

48 / 64

flags on planted anomalies – 75% first-pass precision, exactly as pre-registered, with 100% recall on every rule-shaped class. The other 16 flags are the designed benign bank: contractual round rent, an agreed stocktake weekend, one coincidental equal-amount pair.

A second pass (recurring-identical suppression, materiality floors) would silence most of the 16. That pass is described in the write-up but was not implemented.

The detector

0 / 200

flags on anything planted. The Isolation Forest missed all three designed catches – the drift vendor’s best invoice ranked 818th of 50,000 – and reaching the designed six catches would have required flagging 29% of the whole ledger. A frozen, pre-registered deviation, reported as it ran.

Diagnosis in the notebook: a sustained drift inflates the very baseline it is measured against, and single-invoice vendors present no history to be unusual against.

The analysts

37 · 35 · 38

of 39 unit verdicts correct across three blinded runs. All 26 detector units were correctly stood down by all three – the 200-flag triage burden carried cleanly. Two false positives in total, both the same cautious hedge on one designed benign pair.

364 evidence figures machine-checked: zero disagreements; two −€1,000 headline slips recorded.

The catch matrix, designed against as-run

Eight anomaly classes were planted, each with a pre-registered prediction of which layer would catch it. Seven behaved. The eighth did not.

ClassWhat was plantedTxnsDesigned catchAs run
DDuplicate invoices – vendor re-sends after an unanswered week, both get posted12RulesRules – 12/12 flagged
RRound sums and amounts hugging the €10,000 approval tier10RulesRules – 10/10 flagged
WOne user posting on weekends and holidays8RulesRules – 8/8 flagged
SPurchases split to stay under the approval tier10RulesRules – 10/10 flagged
AAn advertising agency’s invoices mis-coded to IT services8RulesRules – 8/8 flagged
VOne supplier as three vendor records – three spellings, one VAT id, three IBANs15Agents (free hunt)Agents – found by 3/3 runs, each time as the top action item
GThe exemplum: freight silently bundled into goods invoices, then price rises hidden inside the bundle – breadcrumbed in the memos, mirrored in the freight carrier’s decline12Detector, then agentsNobody. Detector missed (best rank 818); all three free hunts left it unclaimed
CThe ceiling: twelve unremarkable consulting invoices, catchable only with data this ledger does not carry12NobodyNobody – and no run accused it. The trap held both ways

The case was designed with one class nothing catches. As run, it has two. A ~€1,800-a-month drift on one vendor is invisible in account-level totals. Only a per-vendor movers sweep with a drill-down would have surfaced it, and no run drilled there.

All 39 verdict units, all three runs

Every unit, its expected verdict derived from the answer key, and what each run actually said. Wine-marked rows are where a run got it wrong.

Try this – open a wine-bordered row below, RU-05 or RU-11 are good ones. Each expands to show what all three runs actually said and the evidence each run read, so you can see a plausible-sounding call go wrong for yourself.

worry expected/called stand down wrong call

Rule-side units (13)

RU-01Mainostoimisto Kaarniala Oymapping · 8 flags · €36,934exp WWWW
The planted mis-posting (class A): every invoice coded to IT services instead of marketing, by one clerk, in September and October. All three runs called it, all three named the mechanism.
RU-02Pulttitarvike Tmiduplicate · 4 flags · €2,915exp WWWW
Two planted duplicate pairs (class D) – same amount, days apart, different invoice numbers, same order reference. 3/3 worried, correctly.
RU-03Poralogistiikka Tmiduplicate · 4 flags · €10,291exp WWWW
Two more D pairs. 3/3 worried.
RU-04Kumipalvelu Tmiduplicate · 4 flags · €8,122exp WWWW
The last two D pairs. 3/3 worried.
RU-05Säiliöpalvelu Oy Abround_sum · 6 flags · €41,000exp WSWW
Six invoices at exact €1,000 multiples (class R). Run 01 read them as contract-style billing and stood down – wrong against the key. Runs 02 and 03 called the round-sum habit.
RU-06Ratashuolto Oynear_threshold · 4 flags · €38,843exp WWWW
Four invoices at €9,580–9,899.99, the only vendor ledger-wide living in the band just under the €10,000 tier. 3/3 worried; run 03 rated it act-level.
RU-07Kantamateriaali Tmisplit · 4 flags · €24,567exp WWSW
Two split-purchase events (class S): pairs days apart, each part under €10,000, sums well over. Run 02 accepted the "osatoimitus" (partial delivery) memos at face value and stood down – the one reading the design planted the memos to test.
RU-08Verkkokomponentti Oy Absplit · 4 flags · €22,767exp WWSW
Two more S events; same split of opinion, same miss by run 02.
RU-09Kairakomponentti Oy Absplit · 2 flags · €13,331exp WWSW
The fifth S event. Runs 01 and 03 worried; run 02 stood down.
RU-10Kiinteistö Oy Vantaan Teollisuustaloround_sum · 12 flags · €180,000exp SSSS
The landlord’s rent: €15,000.00, monthly, by contract (benign B1). All three runs stood down with the recurring-contract evidence – the designed round-sum false positive, triaged correctly three times.
RU-11Ruuvitukku Halonen Oyduplicate · 2 flags · €14,840exp SSWW
The designed coincidence (benign B3): €7,420.00 twice, four days apart, genuinely distinct deliveries evidenced by two different PO references in the memos. Run 01 read the POs and stood down. Runs 02 and 03 saw the same POs and hedged to worry anyway – the case’s only two false positives, both cautious hedges on genuine uncertainty.
RU-12U-031calendar · 2 flags · €3,101exp SSSS
Two Saturday postings whose memos state the agreed stocktake overtime (benign B2). Stood down 3/3, memo quoted as evidence each time.
RU-13U-117calendar · 8 flags · €7,505exp WSWW
One user, eight postings on Saturdays and holidays, no stated justification, peers at zero (class W). Run 01 read it as flexible-hours data entry and stood down; runs 02 and 03 flagged the control question.

Detector-side units (26) – every one benign, every one stood down by every run

DU-01…2424 vendor clusters, 160 flags, €0 wrong3–17 flags each · €1,267–€66,828exp S ×24S ×72/72
Twenty-four vendors whose statistically odd rows – rare-but-allowed accounts, own-history amount tails, seasonal timing – explain themselves on inspection. All three runs stood every one down, each verdict with recomputed within-vendor evidence. 72 of 72 verdicts were correct on the model’s noise, which is the false-positive discipline the case was built to measure.
SINGLESNotable singles (top 10 by score)10 flags · €46,650exp SSSS
The detector’s ten highest-scoring unclustered rows. Nothing planted among them; stood down 3/3.
RESIDUALResidual tail30 flags · €105,891exp SSSS
Everything left. One aggregate distributional verdict per run; stood down 3/3.

What reasoning caught and what it missed

Found 3/3: the Kärrenbach trio

One German seals supplier existing as three vendor records – Kärrenbach, Kaerrenbach, KARRENBACH – one VAT id, one Hamburg address, three different IBANs, €49,001 of spend split across them. No rule test was built to see it (the byte-exact name check scores zero by design), and it lives across records, not within any one. Every run’s free hunt found it independently; every run made it the top action item; every run named the payment-integrity mechanism.

Found 0/3: the drift

From July, Teräskontio’s invoices carry "sis. rahtikulut" – freight bundled in, a +8% step – and then price rises hidden inside the bundle, December landing 19% over baseline, while the freight carrier’s own billing shows the mirrored decline. The evidence sits in plain memo text and one vendor-level comparison. The detector missed it; all three analysts, spending their bounded free hunts elsewhere, missed it too. The advisory-page story this case set out to demonstrate is the one no layer found.

And the ceiling class held in both directions: nothing flagged Neuvantila’s twelve unremarkable consulting invoices, and no run accused them without evidence. The production catches this ledger deliberately cannot support – three-way matching, fuzzy vendor-master hygiene, recurring-invoice suppression – are stated in the write-up.

What this would look like on your data

Your own purchase ledger already carries this shape of signal: duplicate submissions, round-sum habits, a vendor whose invoicing has quietly drifted. No extra instrumentation is needed. The method transfers as built. Deterministic rule tests and a statistical detector cover whatever the numbers alone can show, and reasoning agents read memos and vendor records for whatever needs explaining. Every layer is marked against something known before anyone trusts it unattended. On this ledger, the detector caught none of what was planted, and the reasoning layer carried the account.

Read the long-form case study · Code and dataset · Contact Hapax