Source duplication: 33 clobber hazards to zero

A duplicate source file is not a tidiness problem. It is a trap: a rebuild can resolve the stale copy and silently regress a running service, while the edit you made sits in the file nothing reads.

verdict GREEN 27 reconciles, 0 failures nothing deleted 2026-07-25

The campaign, measured at every step

stageduplicateshazardswhat changed
start4433
after main sweep231221 reconciled
after scope fix1766 nested-tree reconciled
after classifier170hazard definition corrected
after litter clear809 identical copies cleared

Nothing was deleted. Every shadow copy was soft-deleted to a .dupe-reconciled backup, atomically, server-side — 27 of 27 succeeded, zero failures, all recoverable.

Why the board could never have gone green by working harder

Partway through, twelve hazards refused to clear. The reason was structural: the detector discovered around thirteen source trees, while the reconciler knew only two. Anything living in a third tree reported “no duplicate here” and could never be fixed by the tool that found it.

A detector whose scope exceeds its fixer's leaves permanent red — a board nobody can clear is a board everybody learns to ignore. The fix made the tree pair a parameter, so the reconciler now reaches wherever the detector looks. The existing self-test still passes unchanged, which is what proves it was an addition and not a rewrite.

Then a harder question: what actually counts as a hazard?

Six duplicates remained, in an archive directory and a staging directory. Reconciling them would have been easy. It would also have been wrong.

The build resolver prints its own search path when it cannot find a source:

SOURCE-NOT-FOUND (probed runtime/_hdl_build/, runtime/, nxasm/, runtime/wiki/)

It never reads the archive or the staging tree. A copy in a directory no build ever opens cannot clobber anything. Those six were never hazards; they were litter, and an archive is supposed to diverge from live code.

So the classifier was corrected rather than the files: a duplicate counts as a clobber hazard only when both copies sit in trees the resolver actually probes. The verdict now keys on that number instead of the raw duplicate count.

Every duplicate is still printed and counted — they moved into an honest category, they did not disappear. The board went green by fixing things and by correcting a wrong definition, never by suppressing a finding.

The detector caught the change to itself

The first version of that classifier turned the detector's own self-test RED. Its test fixtures live outside the build root, so the new filter reclassified them and the expected counts broke. The concept only has meaning inside the build root; once that was said properly in code, the self-test passed again.

A change that breaks the organ's own self-test is exactly what the self-test is for. It refused the change before it could ship.

Where the duplicates came from

Six of the hazards traced to a single structural accident: a directory tree nested inside itself, created by packing a folder that already contained the destination's name and unpacking it one level too deep. Sixteen files landed where no build would ever read them.

That is now a rule rather than a memory: pack the contents relative to the destination, never a directory whose name repeats it — and verify where the files actually landed before building.

Final state

self-test OK
cross-tree source-dup basenames found: 8
TRIAGE: divergent=0 (real clobber hazards) | identical=2 litter
        out-of-probe-path=6 (a build never reads that tree) | unknown=0
verdict=GREEN (no clobber hazards)