Home/Concepts/Reproducibility and the replication crisis in software engineering teams
Reproducibility and the replication crisis in software engineering teams
Every claim drawn from published science has a half-life. Retraction Watch lists over 50,000 retractions; papers are often cited hundreds of times after withdrawal. Any system…
Where the demand for reproducibility came from
Reproducibility, as a formal demand, is younger than most people assume. The phrase "replication crisis" hardened around 2011, and the decade that followed did the diagnostic work. Daryl Bem published a paper in the Journal of Personality and Social Psychology claiming evidence for precognition, and it survived peer review using entirely ordinary statistical practice. Diederik Stapel's fabrications in social psychology surfaced the same year. John Ioannidis had already argued, in 2005, that most published research findings were false, on structural grounds rather than accusations of fraud. Simmons, Nelson and Simonsohn then showed in 2011 that undisclosed analytic flexibility — trying several exclusion criteria, several covariates, stopping data collection when the result looked good — could manufacture statistical significance more or less on demand.
The Reproducibility Project: Psychology re-ran 100 published studies and reproduced the original significant effect in 36 of them. Amgen's oncology group tried to confirm 53 landmark preclinical cancer papers and could confirm six. The diagnosis, once people stopped treating this as a scandal about individual cheats, was structural: publication rewards novelty, not verification; small samples generate noisy effects; incentives favour the surprising result over the checked one. The fix that emerged — preregistration, registered reports, mandatory data deposit — was not a fraud filter. It was an attempt to make the evidence trail continuously inspectable, rather than trusting a single confident report filed once and never revisited.
That is the core structural fact worth carrying forward: a body of published findings is not a store of settled facts. It is a ledger, provisional, unevenly corrected, and corrected on a timescale much slower than the timescale on which the findings get cited, taught and built upon.
The same shape, in a dependency tree
Software engineering teams run a smaller, faster version of exactly this crisis, and most engineers have lived through an instance of it without naming it.
A team pulls in a transitive dependency — not the library they chose, but a library three levels down that their chosen library depends on. At the moment of import, the dependency is clean: no known CVEs, a green build, a passing security scan. Six weeks later a researcher discloses a deserialisation flaw in that package. An advisory is filed. The advisory is accurate, dated, and complete. It also arrives long after the vulnerable version has been built, tested, released and deployed across a dozen services, each pinned to a slightly different lockfile, some of which nobody has audited since the original import.
This is the software equivalent of a retracted paper still being cited. The finding — "this package version is safe to use" — was true when it was recorded and became false later, quietly, without anyone re-checking the belief that was actually still load-bearing in production. The CI pipeline that gave a green light on day one has no way of noticing that the ground it certified has since moved. Nothing about the original build was wrong. What was wrong is that the team treated a point-in-time check as a permanent property.
The person who ends up accountable for this is usually a staff engineer — not because they wrote the vulnerable line, but because they are the one expected to know the shape of the dependency graph across services, and to have some answer when the audit finds a package that shipped for weeks with a known-exploitable flaw already public. Their honest answer is structural, not personal: the org's intake of security information stopped the moment the build passed. Everything after that was silence, not confirmation.
What a frozen snapshot actually contains
Consider what a model of "the state of our dependencies" looks like if it is built once, at onboarding or at a major audit, and then treated as reference. It contains every commit up to that date, every CI result, every advisory published before the cutoff. It does not contain the advisory filed the following Tuesday. Worse: like a citation graph that keeps citing a paper after its retraction, the org's own internal documentation, runbooks and architecture diagrams keep referring to a dependency as "vetted" long after the vetting has expired, because the artefact that recorded the vetting — a ticket, a wiki page, a passed scan — never carried an expiry condition. The confident claim persists. The correction, when it exists, is a short entry in an advisory feed nobody is watching, buried under noise from packages nobody uses.
A frozen model of the system does not merely fail to help here. It actively misleads, because it presents the original clean result with the same confidence months after the ground has shifted, exactly as a citation of a withdrawn clinical trial paper still reads as a peer-reviewed finding to anyone who does not separately check Retraction Watch.
Why "watch the room" doesn't fix it either
The natural next move is to argue that continuous observation of the current system — dashboards, live topology, present-state scanning — solves this. It does not, for the same reason that sensing a present scene tells you nothing about whether a 2014 result held up. Knowing the current shape of the service graph, in real time, does not tell you which of the beliefs embedded in that graph were verified when and against what evidence. A live dependency graph shows you what is running. It does not show you that the "safe" tag on a given version was assigned before an advisory that postdates it, and it has no mechanism for demoting that tag when the advisory lands.
What the failure mode actually requires is intake that never closes — commit streams, CI results, incident feeds and dependency advisories, running continuously — paired with a record of why each belief about the system's safety was held, and a live channel for demoting that belief when new evidence arrives. That triad — open streams, provenance, demotion — is the only construction in which "this dependency is currently believed safe" is a claim that can actually go stale on schedule rather than silently.
Retraction — or its advisory equivalent — is a solved engineering problem. Dependabot and equivalent tooling already flag known-CVE packages against a public database. You don't need continuous belief-tracking; you need a lookup table someone else maintains.
This is true and worth conceding for the narrow case: formally disclosed CVEs against named versions are cheap to flag, and the tooling for this has improved a great deal. But most dependency decay is not a clean CVE. It is a maintainer going quiet, a package silently changing its transitive dependencies in a minor version bump, a license changing, a build tool deprecating a flag your CI still relies on. None of that trips an advisory. It shows up only if something is watching the ongoing stream of commits and releases upstream, continuously, which is the architecture the objection claims to avoid and in fact just outsources.
Continuous ingestion of every commit, advisory and incident feed multiplies the problem. You've traded a stable, auditable snapshot for a flood of half-verified signals — a preprint-grade advisory is not evidence, it's noise with a timestamp.
This is the stronger objection, and it is correct against a naive version of the argument. A new advisory, freshly filed, unconfirmed and unpatched, is weak evidence, not strong evidence, and treating every incoming signal as equally actionable will drown a team in false positives — the software equivalent of updating a scientific belief on the strength of a single unreplicated finding. The answer is not less intake. It is intake with provenance: an advisory should raise a belief tagged "unconfirmed, sev-unknown," not an immediate hard block, and that tag should update as confirmation, a patch, or a retraction of the advisory itself arrives. What a frozen build manifest offers instead is stability of a different kind — a stable, permanent absence of any update at all. That stability is not a virtue when the underlying claim is wrong.
Why this sits at the top of the intake axis
The three generations differ in exactly this dimension, nowhere else. A model trained on a frozen corpus of code, tickets and advisories inherits the audit's error rate at the moment of the cutoff — high-prominence green builds, low-prominence advisories filed after. A model that senses only the present state of the running system adds live topology, which resolves nothing about whether last month's "vetted" tag on a transitive dependency was true when assigned or is true now. Neither position can make "this dependency is currently believed safe" behave as a provisional claim, because provisionality is a relationship to a later stream of evidence, and a relationship cannot be represented by either a fixed snapshot or a live sensor with no memory of its own certifications.
What remains, once intake stays open across commit streams, CI results, incident feeds and advisories, with provenance on every belief and a working channel for demotion, is not a further class of evidence to add. It is coverage — which streams you actually watch — and latency — how fast a demotion propagates from advisory to build gate — and trust, in the ordinary sense of whether the staff engineer signing off on an audit believes the tooling is telling them the truth. Those are matters of degree. The architectural question — open streams, tagged provenance, live demotion — has no further rung above it on this axis.