Thicket.
← Back to Journal

Engineering

'NDA' Is Inside 'Calendar'. Our Classifier Didn't Know.

We sort the companies we contact into industries with a keyword classifier. Six of the nine it called legal tech were calendar and planning tools.

Our classifier decides a company’s industry by checking whether any of its keywords appear in the company’s own product description. It checks with a bare substring test. So the legal-tech key “nda” fires on “calendar”, and the security key “sso” fires on “compressor”. Across our records, 19 of 152 were classified entirely by a key that never appears as its own word.

What the classifier is for

We run an outbound test. Each company we write to gets a measurement of whether an AI assistant names it when a buyer asks about its category. We split those companies into two groups by industry, security and compliance software on one side and non-developer software on the other, to ask whether they respond differently. The classifier assigns the industry. We fixed its rules in advance, the way a preregistered study does, so that the grouping could not be adjusted after we saw who replied.

That made the classifier load-bearing. If it puts a company in the wrong group, the comparison is answering a different question from the one we asked.

Five keys did all of it

The audit asked one question of every record: does the winning keyword appear anywhere in the product facts as a word of its own? For 19 records the answer was no. Five keys account for every one:

  • ide (8 records): inside video, videos, guides, guided, side, alongside, ideas, identify, identity
  • nda (6): inside calendar, agendas, standard, standards
  • cli (2): inside clipboard, client
  • sso (2): inside compressor, lessons
  • tax (1): inside TAXII

The worst case is legal tech. Of the nine records stored under it, six are the “nda” artifact: a time tracker built on calendar data, a daily planner, an event-management tool, a database-diagram tool that enforces naming standards, an operations API over inbox and calendar, and an open standard for agent memory. None of them is a legal product.

A substring test does not know where a word starts. It only knows whether three letters occur in order.

This failure has a name. The Scunthorpe problem is the same mechanism in content filters, which block innocent text because an unacceptable string sits inside a longer, harmless word. Ours runs the other way. It does not block anything. It quietly files things under the wrong label.

Our first count was wrong too

The first pass flagged 44 records, using a rule that counted any key matching inside a longer word. That number was wrong, and we are printing it so nobody quotes it.

Most in-word matches are correct. The classifier’s author wrote stems on purpose: “orchestrat” for orchestration, “invoic” for invoicing, “vulnerab” for vulnerabilities. Ordinary inflection does the rest: “sql” in sqlite, “sdk” in sdks, “legal” in legally. One record matched “legal” inside “legally-binding signatures”. That is an electronic-signature product, and legal tech is the right label.

So a rule like “keys of three letters or fewer must match on a word boundary” would have refused real signals. The defect was five particular keys, and the fix names those five.

Why it had not hurt yet, and why it would have

All 19 records were qualified before the rules were frozen, and none had been placed in either group. We checked each one rather than assuming it. The groups as they stood held no collision record, so the comparison was clean.

The risk was what came next. A collision does not just add noise to one group. It moves records across the boundary in both directions. “nda” in calendar puts a calendar app into legal tech, which is in the non-developer group. “sso” in compressor puts an image compressor into security, which is in the other one. And “tax” in TAXII, a standard for exchanging threat intelligence, put a honeypot threat-intel vendor, a security company, into fintech. That happened one day before the freeze.

The test exists to compare two hypotheses. A record filed under the wrong one is the single error the design was built to prevent.

We did not fix the classifier

Correcting the rules would reclassify every stored record and break the comparison the freeze protects. Restating a company’s industry after seeing whether it replied is exactly the after-the-fact slicing that agreeing the outcome in advance is meant to stop.

So the fix is a gate outside the classifier, and it never relabels anything. It refuses to send only when every keyword that fired for the winning industry is one of the five collision keys and none of them appears as its own word. One sound key is enough to pass, whether that is a stem, an inflection or a multi-word phrase. The gate loads the classifier from its file and refuses to run if the rules have changed, so it cannot drift away from what it checks.

It was tested on real records, both ways, with the mailer stubbed out. A video-captioning product (“ide” in video) was refused, and the refusal named the host word. The one held record in the security group passed through to the next check. A made-up description of a calendar app classified as legal tech and was refused. Empty product facts pass, because a missing field is not a negative result. We wrote about that last distinction in a validator that checks assertions but not denials.

What to take from it

If you classify text with keywords, audit the result from the record’s side. For every record, ask which keys fired and whether each one appears as its own word. Then read the misses by hand before you change anything, because most of them will be stems doing their job.

And if the classifier feeds a comparison, assume a mislabel moves records between the groups rather than just adding noise. That is the case worth testing for. It is also why every visibility check we run carries a control: an instrument you have not tested against a known answer can still look like it is measuring something.

The 19 stored verdicts were left as the classifier wrote them. Our read of the two groups will apply the frozen definition with this note in front of it: six of the nine legal-tech records are artifacts, so any legal-tech figure carries that caveat. The measurement those companies receive is described on the Engine page.

Frequently asked

Why does a keyword classifier match inside unrelated words?

Because the test is a substring test. Checking whether 'nda' is in a piece of text returns true for 'calendar', 'agendas' and 'standard', since the three letters appear inside each of them. The classifier has no idea where a word starts or ends. A word-boundary match only fires when the key appears as its own word, which is a different test and has to be written on purpose.

How many of our records were affected?

19 of the 152 records that carry product facts were classified entirely by a key that never appears as its own word anywhere in those facts. Five keys did all of it: 'ide' (8 records, inside words like video, guides, side and identity), 'nda' (6, inside calendar, agendas, standard), 'cli' (2, inside clipboard and client), 'sso' (2, inside compressor and lessons) and 'tax' (1, inside TAXII, a threat-intelligence exchange standard).

Why not just require keys to be at least four letters long?

Because most short keys that match inside a word are matching correctly. 'sql' inside 'sqlite' and 'sdk' inside 'sdks' are real signals. A length rule would refuse those. So would a blanket word-boundary rule: our first pass flagged 44 records using it, and that number was wrong, because stems written on purpose, like 'invoic' for invoicing and 'vulnerab' for vulnerabilities, also match inside longer words. The defect was five specific keys, so the gate names those five.

Why not fix the classifier itself?

It is frozen. We fixed its rules before running a comparison between two groups of prospects, so the result cannot be bent by changing the definition after seeing who replied. Editing the rules now would silently reclassify every stored record and invalidate the comparison it was frozen to protect. The fix sits outside it: a check that refuses to send to a record whose classification rests only on a collision. It never relabels anything.

Did the bad classifications affect anything already measured?

No. All 19 records were qualified before the rules were frozen, and none had been assigned to either comparison group. Each was checked directly. The risk was forward: a collision does not just add noise to a group, it can put a record that belongs to one group into the other. A threat-intelligence vendor for security teams landed in fintech because 'tax' sits inside 'TAXII'.

How do you test a gate like this?

On real records in both directions, with the mailer stubbed out. A video-captioning product that matched 'ide' inside 'video' was refused, and the refusal named the host word. The one held record in the security group, which has sound keys, passed through to the next check. A synthetic description of a calendar app classified as legal tech and was refused. Empty product facts pass, because a missing field is not a negative result.

More from the Journal