English
Changelog
Every change to Knockwire, newest first, grouped by the day it shipped. There are no version numbers here because there are no releases: the product deploys continuously, so the date is the only honest label. The list starts at the first commit, on 29 July 2026. Housekeeping is left out. Anything that changed what the product does, or what it claims about itself, is in.
Five languages, and no published mailboxes
- AddedThe marketing pages, the three legal documents and the blog now exist in Japanese, Brazilian Portuguese, Spanish and French as well as English. Every page is canonical to itself, with reciprocal hreflang. A page that has not been translated has no route and no hreflang entry, because a link promising a language it cannot serve is worse than no link.
- AddedField Notes, the writing. Fourteen long form pieces, about 19,000 words in English, and all fourteen in all five languages: 70 posts. Charts are declared as data rather than pictures, so a translated post gets a translated chart.
- AddedThe dashboard reads in five languages, 246 strings each. The language comes from the account, so changing it applies on every device at once rather than at the next sign in.
- AddedA contact form. Every message reaches a person, and the addresses live on the server where nothing can read them.
- RemovedSix published email addresses across the site, and a seventh in the structured data, which was the worst of them: machine readable and served on every page. A product built on the premise that reading public pages at scale is easy should not be surprised when it happens to us.
- FixedEvery page was served as English. A Japanese page was being read aloud by screen readers in an English voice, and search engines were told the same thing.
- FixedSharing any page produced the English home page’s card. All 101 pages had inherited one social card, so a Japanese privacy policy advertised itself with the home page blurb.
- FixedAn unmatched URL took the server down instead of returning 404. That was the cause of the intermittent 502s, and of the broken styling people reported alongside them.
- FixedFollowing a link to a section of the landing page from another page landed on a blank screen. The interaction script was not being wired after a client side navigation, which had also left the accordion, the counters and the live demo dead.
- FixedThe one live number on the landing page was grouped by the server’s locale rather than the reader’s. French now reads 4 182 and Brazilian Portuguese 4.182, matching the fixed figures beside them.
- FixedTwo chrome links pointed at routes that did not exist, and the footer link to Field Notes sent a French reader to the English index.
Accounts, a verified sender, and the submission stage
- AddedSign in with a six digit code by email, or with Google. There is no password column anywhere in the database, and a column that does not exist cannot leak.
- AddedNothing sends under an address a tenant has not proven it owns. Sending is gated on a DNS record published under the domain. A confirmation link proves control of a mailbox, and a file on a web server proves control of a web server; neither is the claim being made. Free mail addresses are refused up front with their own message.
- AddedThe submission stage. An approved message is prepared, rehearsed against the real form, and only then posted. It becomes a knock when the form accepts it, and not before. Rehearsal is the default, a form behind a CAPTCHA is refused rather than solved, and no code path retries a request that may already have gone out: there is no network condition under which a second letter to a stranger is the correct repair.
- AddedTwo discovery sources. A directory of data companies, where the entry requirement is the profile we look for: 28 of 28 domains from the first sweep resolved, against roughly four in five from bios. And the Y Combinator directory, the only source that says out loud whether a company is still trading. 1,861 of its 6,108 companies are already acquired or inactive.
- AddedA tenant can name the companies it already sells to, and suppress anyone it does not want contacted. Both lists had been empty since the rule that reads them was written, which is why a current top twelve customer had been researched as a cold prospect.
- AddedA sender profile, so a form asking for a phone number or a country has somewhere to look it up. Nothing on that page is inferred. A phone number typed into a stranger’s contact form is an assertion about a real business, so it comes from a person or it does not go.
- ChangedThe dashboard shows the real ledger. It had been rendering a fixture written before the pipeline existed: busier than the truth, and every number on it invented.
- ChangedEvery qualified company used to score exactly 20. Three of the score’s four terms could not vary at the moment it was computed, so the queue was insertion order wearing a number. It has six terms now, all of them knowable when the score is taken.
- FixedThe sign in form could sit on "Checking" forever. The server was answering the whole time; a dropped connection left the button pinned with no message and no way out but a reload.
- RemovedTailwind, and four orphaned components. Nothing in the app used a utility class any more.
The Rejection Index stops being illustrative
- ChangedThe Rejection Index reads the ledger. Under a heading about publishing our refusals sat a table of invented percentages, footed "Illustrative distribution". It was the one part of the page that argued against itself. The first real reading was 72 refusals from 151 companies, each with the sentence written when the verdict was reached.
- AddedEnrichment, drafting and a review queue. A verdict taken from a company’s own site overrules the one taken from its bio: 79 provisional passes became 5, with 16 dead domains and 6 name collisions among the casualties. An overturned pass is written back as a refusal, so the Rejection Index gets more honest as the pipeline runs rather than drifting away from it.
- AddedSign in mail goes out under a self imposed cap of 40 sends an hour, reserved before the send rather than counted after. The realistic way to lose a mailbox is not steady legitimate use, it is a retry loop at 3am.
- FixedTwo read endpoints answered anonymous callers and returned up to 500 ledger rows for whichever tenant the URL named. Both are behind the dashboard lock now, and the tenant comes from the session rather than the query string.
- FixedThe demo was answering well known companies from memory instead of looking. One domain came back complete with zero searches and zero fetches, while the page beside it says the demo really goes and looks. Both prompts now carry a floor, and the timing copy was corrected with it: "about 40 seconds" became a minute or two, which is what it actually does.
- ChangedThe demo runs on a pinned model at a deliberate effort setting rather than inheriting whatever the tool ships with. At its default effort one run spent 203 seconds, exhausted its turn budget and returned nothing, for nearly three times the cost of the run that succeeded in 73.
- AddedDemo failures are told apart. A spent allowance, an overloaded model, a timeout and an unconfigured runner used to collapse into one message that read as though the visitor had typed a bad domain.
- AddedRate limits, run budgets and the circuit breaker survive a deploy. They had lived in memory, so shipping a change handed out a fresh allowance and forgot every run already in flight.
- AddedDemo runs are recorded, so the claims made on that page can be checked against what it really did. The visitor’s address is hashed with a salt and never stored: nothing here needs to identify anyone, only to count them.
First commit, and refusals become records
- AddedKnockwire, renamed from delvebase on the day it started. The product is not the list it produces. It is the list it refuses, and the reason attached to each refusal.
- AddedThe reads ledger. Every company looked at is kept, passed or not, with its outcome, its refusal reason and an evidence link a person can open. Deleting a refused company would destroy the evidence this product rests on, so nothing is deleted.
- AddedDiscovery. Five ways of finding companies were measured against live endpoints and one won: reading what organisations write about themselves returned 1,171 organisations with websites from 136 queries, of which 186 qualified. Publishing a scraper is vendor behaviour. Writing "price intelligence platform" in your own bio is buyer behaviour, and the whole first gate rests on telling those apart.
- ChangedVendor filtering moved out of discovery and into the judgment step. Competitors were being dropped silently, so they never reached the ledger, and a refusal nobody can audit is not evidence.
- FixedA competitor reached the qualified list on the first live run. The vendor exclusion list held ten names and needed thirty. That is the worst failure this product has had, and it is recorded here rather than quietly repaired.
- AddedContact resolution, which never guesses. A published contact form is preferred over an address, because a form is a door the company opened for this purpose. A role address is used only when the company actually publishes it. There is no first.last permutation and no pattern inference, and robots.txt is read before any fetch.
- AddedThe site, the pricing, and the terms, privacy and refund policies.
- AddedThe live demo on the public site, which runs against whatever domain a visitor types. It is boxed in rather than trusted: two tools allowed and everything else denied, an empty working directory, no access to our environment, and retrieved pages treated as data rather than as instructions.
- FixedThree ways to abuse that demo, all demonstrated against production rather than theorised. Two of its three actions were unmetered, the per visitor limit could be bypassed with one header, and nothing capped how many runs could be in flight at once.
- AddedThe ledger went live on a real database the same evening. First pass: 60 companies read, 36 qualified, 24 refused, every refusal carrying its reason and its evidence link.