“It adapts” is two architectures and only one of them is safe
An adaptive parameter retunes the transform, so the output domain moves. A fixed function never changes and its output adapts because the input did. Same phrase in a design doc, opposite consequences — plus the parser that grew rows nobody could ever satisfy.
I had two requirements that looked contradictory for about a week.
The first: voice templates have to be compared in the same domain they were created in. If you build a reference from audio processed one way and match against audio processed another way, the comparison is meaningless — and it does not fail loudly, it just gets worse.
The second: noise handling has to work in a car, on a street, and at a desk. Which sounds like it must adapt. Which sounds like it must change the processing per environment. Which is the thing the first requirement forbids.
The contradiction dissolved once I noticed that “it adapts” describes two completely different things.
An adaptive parameter, versus a fixed function
An adaptive parameter retunes the transform itself for each environment. Spectral subtraction calibrated against a measured noise floor is this: the floor changes, so the subtraction changes, so the transform changes. The output domain moves with the room.
A fixed function never changes. The same operation, byte for byte, everywhere. Its output adapts because its input did — the function is doing the same thing to different audio, not a different thing. A trained denoiser like RNNoise is this.
Both are honestly described as “adaptive noise handling.” Only the second one preserves a stable domain, and the first one silently destroys the property the whole matching step depends on. Same sentence in a design doc. Opposite consequences.
The same shape, one layer up
Later the same week I hit the sibling of this and didn’t recognise it at first.
I appended some provenance notes to a tracking file as HTML comments. The parser that reads that file only understands lines beginning with #. It did not know what an HTML comment was.
It did not error. It did not warn. It read four comment lines as four entries, and my status board grew four new rows — each one requiring work to satisfy, each one permanently unsatisfiable, because there was nothing there.
A parser that trusts its input does not produce a crash. It produces a status display that is confidently wrong, which is strictly worse, because a crash gets fixed in ten minutes and a wrong status board gets believed.
The common root
In both cases a component quietly changed what it was producing, with no signal at the boundary.
The adaptive transform changed the domain of its output while everything downstream went on assuming a fixed one. The parser changed the meaning of its input — from “lines I understand” to “every line” — while everything downstream went on assuming it had been filtered.
Neither boundary was ever stated. That is the actual defect in both. Once you write down “this function has a fixed output domain” or “this parser accepts exactly these lines and rejects the rest,” both bugs become impossible to write by accident, because you would be visibly contradicting a sentence.
The question I now ask of anything sitting between two components: what does it promise about its output, and what does it do with input it doesn’t recognise? If the second answer is “passes it through,” that isn’t leniency. It’s a decision to be wrong quietly.