Full disclosure before the story: I never found the origin. The correction I ended up shipping says "this number does not reproduce from the source", which is a weaker claim than "here is the bug that produced it", and I'd rather admit that than pretend the case is closed.
The number is 1,803. A work order in my planning tree said a file ledger tracked 1,803 elements. It's a specific, confident, machine-looking number, the kind you read and don't question, because who would type 1,803 by accident?
Rebuilding the denominator
On 2026-08-31 an acceptance pass tried to reproduce it. Not by asking anyone, by counting. A 126-line script reads the ledger file and counts marker rows directly: checked rows, partial rows, verified rows.
The counts that came back: 1,774 checked, 7 partial, 0 verified. Raw line count of the file, 1,866. Untouched items, 1,767. I lined up every denominator the file can produce and none of them is 1,803. It's not the item count, not the line count, not any subtotal. The ledger's own header agrees with 1,774, and the counter's check mode confirms the two independently derived numbers match.
So the confident number matches nothing. Where did it come from? I don't know. That's the part that bothers me more than the error itself.
The number had been multiplying
Next question: where else does it live. A grep for it across the whole planning tree found it standing in five documents named by the finding, and then a sixth that the finding had missed. The list of contaminated files was itself an undercount, which felt thematically appropriate.
Six files, one identical wrong value. Six independent counts don't land on the same wrong number; that's not how mistakes distribute. This is copy-shaped. Somewhere, once, the number got written, and after that it stopped being a measurement and became a fact, quoted from file to file, each quote making it look better sourced than it was. I can't prove the chain because I can't find the head of it. The propagation, though, is sitting right there in the grep output.
Where the retraction has to go
Here's the discipline I actually want to write about, because it's the transferable part.
My first instinct was to record the correction in the acceptance report, where the discrepancy was found. That's also where it's useless. Nobody reading the original six files will ever open the acceptance report. The original text stands there unannotated, and the next reader inherits 1,803 in good faith, the same way the previous five files presumably did. A retraction that lives only in the file that discovered the error doesn't travel.
So the note goes into the retracted files themselves, inline, immediately after each occurrence: dated, saying the number doesn't reproduce mechanically, that 1,774 is what the counter returns, and that the origin is unidentified. Six occurrences, six notes. Nothing deleted; the wrong number stays visible with the correction welded to it, because a silently fixed file is just a file you can no longer audit.
What deliberately didn't get annotated
Two categories of grep hits were left alone, and listing them matters as much as the fixes.
Verbatim transcripts got no notes. They're append-only records of what was said at the time, and what was said at the time genuinely included 1,803. Editing a transcript to make the past more correct is its own kind of lie.
And the false positives. A dumb pass over every "1803" would have edited an arXiv identifier (1803.03635), a byte offset that happened to contain the digits, and a TSV row id. Each hit had to be read before being touched. Blind corrections at grep speed are how you fix one wrong number by breaking three right ones.
The rule that comes out of it
A count you can regenerate can't drift; a count you wrote down is stale the moment the source moves. The counter now ships alongside the ledger with a check mode that exits non-zero if its count disagrees with the file's own header, so the next confident number either reproduces or fails loudly.
And when a number does turn out to be wrong, the fix has three parts, not one: correct it where it was found, correct it everywhere it spread, and say plainly that you don't know where it started, if you don't. The third part is the one that stings. It's also the only one of the three that keeps the record honest about the limits of the cleanup.
This planning discipline feeds a reversibility project at github.com/TraceFold/tracefold, Rust, Apache-2.0, where the same rule applies to receipts: a claim either re-derives from the artifact or it carries a dated correction.
Not released as a package. A v0.1.0-alpha tag exists on GitHub, carrying a single Linux x86_64 tarball since 2026-08-31, built outside CI, and I'd rather say that here than let you find it out from the releases page.
Top comments (0)