What we got wrong
Every defect we have found in our own work, dated, as a causal chain: what the signals said, what was true, the fix that did not work, the fix that did, and whether the guard was proved. Nobody else publishes this; that is the point.
Never publish a number we cannot defend, and say plainly where the evidence runs out. Everything on this site follows from that, and this page is where it is hardest to keep: a list of the times our own work was wrong, written so that the reusable part survives. The reusable part is almost never the fix. It is what made the defect invisible.
We publish this because BvLogic has no customers, no logos and no case studies, so the only thing that separates our published claims from anyone else's is that they survive being checked. A weaker true number beats a stronger invented one. Every entry below is one of ours.
The pattern across all of them
Success signals lie. A clean exit, a passing gate, a rising page count and a green test suite each prove that something completed. None of them prove that the right thing happened. Four of the defects below passed every automated signal we had and were found by reading the result.
The defects, as causal chains
Each is written the same way: what the signals said, what was actually true, why the obvious fix was wrong, what fixed it, and whether the guard that now prevents it was itself proved by deliberately breaking it.
1. Our deploy gate was bypassed by the convenience of reading its output
Signals said: the build printed FAILED and the deploy proceeded anyway. What was true: the gate was perfect. It caught an orphan page and exited with an error. The deploy command piped the build through a text filter to show the verdict, and a pipeline reports the status of its last command. The filter found the word FAILED, the filter succeeded, and the next step ran. Every component behaved correctly. The failure was in composition. Fix: a deploy script that tests exit codes, never log text, holds a page-count floor that aborts before the swap, and checks ten live addresses after. It earned its place on its first dry run, catching a specification that still published a benchmark figure the harness had already moved past. Lesson: a gate that can be bypassed by reading its output is not a gate.
2. A live page was silently replaced, and we deployed it
Signals said: nothing. Build clean, page count up by one, verify gate passed, deploy succeeded. What was true: a new article declared itself a pillar inside a section where a pillar resolves to the category address. It won the lookup, took over the published category page and pushed the original down to a different address. Found only by opening the page by hand afterwards. Fix: its own category, and a build guard that fails when two articles declare pillar in one category, naming both. The guard was wrong first: its first version counted articles whose type merely defaulted to pillar and fired on two entirely healthy categories. Production was checked before the alarm was believed, both were fine, and the guard was corrected to count only a declared pillar. Lesson: verify your own alarm before acting on it. A new guard's first firing is at least as likely to be a false positive as a find.
3. Our own summaries outranked the sources they quoted
Signals said: top-one retrieval on our published benchmark fell with no change to the engine. We measured 66.7% before and 58.3% after. What was true: three synthesis pages restate figures that have a proper home elsewhere, and length normalisation prefers the shorter copy, so a summary outranked the guide it was quoting. The fix that did not work: stripping quoted blocks from the index. The summary's own prose was still legitimately about the subject, so it still ranked first, now without the number, which is worse. Reverted, and the lower figure was published in the meantime rather than hidden. The fix that worked: weight synthesis pages down in the index, which the same table had already done for an identical failure five weeks earlier. Recovered to the earlier figure, measured live. Lesson: any new summary page goes into that weight list before it ships, not after it is measured cannibalising its sources.
4. A stemming rule fired where the suffix was not one
Signals said: a question about when a regulation applies returned a page containing nothing about it, while the page stating the date outright had the highest term coverage and still lost. What was true: a rule that strips a common ending fired on words where those letters are not an ending, so two unrelated word families collapsed into the same token. On a site whose largest guide is about compliance, that is not a rounding error. It was also inconsistent: one form of the word hit a different rule first, so one word family produced two unrelated tokens depending on what the visitor typed. Fix: an explicit table of irregular words in both tokenisers, index rebuilt. The second-order defect: the parity test between the two tokenisers hand-listed which constants to compare, so adding the table broke it in a way that looked like a parity failure rather than a missing extraction. And the first mutation test did not catch a deliberately broken stemmer, because its word list lacked the new family. List grown; mutation now caught.
5. The word proving we had not covered the subject was invisible
Signals said: a question naming a company we have never written about was answered confidently from an unrelated guide. What was true: the pivot, the word carrying the question's meaning, was chosen only among words in our corpus. The company name was unknown, so it was skipped, and the pivot fell through to a common word we cover well. The one word that proved the subject was unpublished was invisible precisely because we knew nothing about it. Fix: unknown terms compete for pivot at the maximum weight already used to cost them; if the winner is unknown, the subject is unpublished and the engine declines. Why it was safe: every genuine question in the reference set has zero unknown terms, so the change cost nothing on questions we can answer.
6. A function ignored what it did not recognise and reported success
Signals said: exit clean. What was true: a page builder was passed an option it did not support, attached nothing, emitted no warning, and produced a page whose interactive half did nothing. Fix: it now throws on anything unrecognised. Same class as a dead mail function, a step that deleted itself, and an alarm that lived in a printing routine no test could reach: everything reports fine and the work did not happen.
7. An internal document was published to the public web root
Signals said: the document built. What was true: the document tool wrote into the folder that is publicly served, so building an internal ledger published a file stating that BvLogic has no customers. Caught before deploy, verified absent. Fix: moving the file would fix nothing for the next one, so the tool now takes an explicit output location and its default is documented as published.
8. A rate limit was tested against a fresh visitor every time
Signals said: three successful requests in a row, so the limiter must be broken. What was true: the visitor identity hashes the network address, the browser agent and the date. The proof used a command-line client against a quota built up by a different agent, so each request was a new visitor and the three successes meant nothing. Fix: test a rate limit on one fixed agent, and prove it in both directions: the permitted requests through, the next two refused, a probe without the secret refused, a bogus secret refused, the real secret through.
The refusals
Not defects, but decisions that look like under-delivery until you know what they protect. Each declined part of what was asked for.
- The benchmark scores only us. Asked to compare against four named competitors. We cannot run their systems, so any number against their name would be invented, and comparative claims about named competitors are actionable in the markets we sell into. We published the method in full, our own scores including the failures, and the harness for anyone to run themselves.
- No target number. The brief named a headline accuracy figure to reach. A benchmark built to reach a number is a number, not a benchmark. Whatever the harness measures is the headline, and it has been published going down.
- Unmeasurable rows are absent, not estimated. Capabilities we do not have are not scored. In the specification they appear as not implemented rather than being dropped, because silently omitting a metric you would score zero on is how a vendor specification lies.
- No peer median. Asked for a your-score-against-peers column. We have no respondents. A median derived from nothing would sit in the position of maximum influence on the page.
- No certification, no certificate. We hold none, and a credential issued by a supplier to its own prospects is marketing with a border around it.
- The specification is version 0.1, draft. One organisation publishing a specification is a proposal. It becomes a standard when somebody who does not work here runs it and disagrees.
Where this list runs out
It holds only what we have found. A defect we have not found is not on it, and the ratio that matters is the one we can state: nine things built across five roadmap phases, nine defects found in our own work. That ratio is why maintenance, not addition, is where the value now is.
Every guard named above was deliberately broken to confirm it fails. A guard nobody has watched fail is a guard nobody knows works.