294
published papers found to be affected by leakage
across 17 disciplines — Kapoor & Narayanan, Patterns, 2023
Before the model ships
A bank builds a model to predict who will repay a loan. It scores almost perfectly in testing, so they ship it — and it fails.
The model was never good. One of the facts it was shown could only be known after the loan decision had already been made. It wasn’t predicting. It was reading the answer.
Hindsight catches that before the model reaches anyone.
It works by reading DataHub — following which column was built from which back from the model, then checking whether anything it found could only have been known after the decision.
Why this matters
294
published papers found to be affected by leakage
across 17 disciplines — Kapoor & Narayanan, Patterns, 2023
100k+
public notebooks where leakage was found to be pervasive
Yang, Brower-Sinning, Lewis & Kästner, ASE, 2022
0
false positives across 21 legitimate queries
our own benchmark, measured — see the evidence
Yang et al. analysed the code that trains the model. The leak Hindsight targets is usually made earlier, in a pipeline the person training the model never opens — so it survives checks that happen inside the notebook, and it survives testing, because in testing the answer really is there.
Built for decisions with a clock
Each has an instant after which nothing was knowable, and a wrong model costs money or causes harm.
Not built for
Usually no per-row decision moment to reason about, so the central question this asks does not apply.
| What you get | What it needs | Who that is |
|---|---|---|
| Find post-decision sources in your SQL | nothing — no DataHub, no config | Anyone with a dbt project or a folder of SQL |
| Rebuild a feature as of the decision and re-test it | A timestamp recording when each value became known | Teams with event history or dated snapshots |
| The full lineage trace and catalog write-back | DataHub with column-level lineage populated | Teams whose connectors emit fine-grained lineage |
The first row needs nothing at all. Point it at a folder of SQL and
it reports which models read a post-decision source with no availability guard.
Exit code 3 blocks a pull request.
uv run hindsight scan-sql path/to/dbt/models --post-outcome-table payments_after_decision
Files it cannot parse are reported as unchecked, never as clean. A file that was never examined has not passed.
How it works
It reads the company’s data catalog — a record of every table and column in the business, and crucially which column was built from which. That map is the only place the answer exists.
Why nothing else can catch this. The notebook that trained the model can’t see it — the problem was created far upstream, in the warehouse. The feature store sees the finished features, not where they came from. Monitoring only notices months later, once the losses show up. Only a map spanning all of them can answer “could this have been known at the time?” — and that map is DataHub.
Follow the map backwards from the model to find where each fact it used actually came from.
Ask when each fact became known, and compare that to the moment the decision had to be made.
Rebuild the model using only what was knowable at the time. Real skill survives. Cheating collapses.
Once a person approves, write it into DataHub so the next engineer inherits it instead of rediscovering it.
Built on DataHub
Hindsight does not guess which feature is suspicious and it does not read your warehouse. It asks DataHub one question, through the Agent Context Kit: is there a path from this column to that one, and which way does it run?
hindsight trace-lineage --source-column payment_recorded_at --target-column days_since_last_payment
payment_recorded_at
urn:li:query:d47c395f75a3ca4422cf5…
days_since_last_payment
Look at the middle. The middle element is a DataHub query entity. The catalog does not only say these two columns are connected - it identifies the transformation that connects them. The evidence chain can therefore cite the catalog's own record of the SQL rather than a file someone pointed us at.
available and found are separate. 'The catalog says there is no path' is evidence against leakage. 'We could not reach the catalog' is not evidence at all. Collapsing them would let an outage read as a clean bill of health.
Agent Context Kit
get_lineage_paths_between is the core primitive, not a bolt-on. Column-level and directional, which is exactly the question an audit needs.
MCP Server
Discovery, lineage reads, and governed mutations against a real instance.
Context graph
Column-level lineage, ML entities, schema and profiles — the map nothing else in the stack has.
DataHub Actions
Audits a model the moment it appears on the event stream, with nobody triggering it. It may raise an incident; it never publishes evidence itself.
DataHub Skills
datahub-ml-release-audit packages the verdict contract so any agent can run this workflow.
Written back, then re-read
A tag, a structured property, an audit document and an incident. Each one is read back afterwards — a write that cannot be re-read is treated as a failure.
We gave something back. Building this turned up a gap in DataHub's
own documentation: the incidents guide lists CUSTOM as a supported type
without mentioning that customType is required with it, so the guide as
written fails. The fix is
merged into
datahub-project/datahub.
A second pull request, adding the release-audit skill to datahub-skills, is open and awaiting review.
Try it
5 audits across three industries, including one that is expected to pass. Each is a real audit against generated data — pick whichever is closest to your world.
A bank wants to predict whether someone will repay a loan, so it can decide who to approve.
“Will this applicant repay the loan?”
LendingThe same bank, after applying the one-line repair Hindsight proposed. This is what a clean audit looks like.
“Will this applicant repay the loan?”
LendingThe same bank, but the defect is realistic: only about one application in seven has post-decision data attached, so the model barely looks suspicious.
“Will this applicant repay the loan?”
HealthcareA hospital wants to predict which patients will be readmitted within 30 days, so it can offer extra follow-up care at discharge.
“Will this patient be readmitted within 30 days?”
PaymentsA payments company wants to block fraudulent transactions in real time, before the money moves.
“Is this transaction fraudulent?”
Your activity
Most recent result
ALLOW
no violation found
Scenario
Credit Default Fixed
credit-default-prior-delinquencies-safe-control
Records re-tested
4,000
in 0.11 seconds
Audits run
5
every one kept as evidence