Two unattended documentary channels find their own topics every week. They crawl Wikipedia categories, fetch candidate articles, let an LLM judge "is this a case worth a post-mortem", and only what passes becomes a script.
I opened the verdict ledger. 37 screened, 0 passed. The rejection reasons counted up like this:
| Rejection reason | Count |
|---|---|
| Article too thin (body under 500 chars) | 20 |
| "extract too thin / only gives…" | 6 |
| Substantive (company still operating, concept article, …) | 11 |
54% were "the body is too short". The natural conclusion was obvious: I've run out of good topics. Add more categories, or loosen the screen.
One question should have come first. When more than half your rejections share a single reason, do you suspect the subjects, or the input that produced those verdicts?
1. Names that cannot possibly be 500-character articles
Scanning the burned list, something stuck out: ef-hutton. E. F. Hutton was a major
brokerage founded in 1904 and sold in 1988. Its Wikipedia article is not 500 characters.
Neither is commerce-one or art-van-furniture.
So I measured.
'E. F. Hutton & Co.' len=292
'Commerce One' len=485
'Art Van Furniture' len=334
'Computer.com' len=298The articles weren't short. The extractor was only fetching the intro.
2. One line, and the line was syntactically fine
r = _wiki_get({
"action": "query", "prop": "extracts", "explaintext": "1", "exintro": "0",
"titles": title, "redirects": "1", "format": "json"})exintro means "give me only the intro". To turn it off, I passed "0".
MediaWiki API boolean parameters behave like HTML checkboxes: if the parameter is present,
it is true, whatever the value. exintro=0, exintro=false, exintro=no all mean
"intro only". The only way to make it false is to omit the key entirely.
I deleted the key and repeated the same calls.
| Article | Before | After |
|---|---|---|
| E. F. Hutton & Co. | 292 chars | 13,021 |
| Art Van Furniture | 334 chars | 6,729 |
| Charming Charlie | 100 chars | 2,428 |
| Air France 447 | — | 63,954 |
A factor of 44. The judge was reading 2% of the body and writing "this incident has no documented arc to build a post-mortem on".
3. The worse part: those verdicts burned inventory
This pipeline has one rule: never blacklist without a verdict. Fetch failures, API failures and timeouts are not recorded; they get retried next round. I set that rule two days ago while fixing a bug that burned topics it had never judged.
This case passes that rule. The reason string "article too thin (under 500 chars)" is right there in the ledger. So 43 topics sat on the permanent exclusion list disguised as legitimate verdicts.
I checked that a reason existed. Nobody checked whether the input behind that reason was intact.
4. What would you do first?
The queue is drying up, the screen keeps rejecting everything, and half the rejections say "the input is thin".
- (a) Add more candidate categories
- (b) Loosen the screening bar
- (c) Pick one rejected item whose name you recognize and measure the input by hand
I did (a) two days ago. The candidate pool grew; the pass rate didn't move. (b) is not something a factual channel gets to do. The answer was (c), and it took thirty seconds.
5. First run after the fix
[discover] 473 candidates — top by search demand: Barings Bank(1.1), Roberto Calvi(1.1), …
[discover] adopted: barings-bank-collapse ← Barings BankFour days earlier: 94 candidates, 12 screened, zero adopted. Now: 473 candidates, and the first one passed. Restoring the 43 void verdicts (I selected only the reason strings that blame the input) brought back TheGlobe.com, Broadcast.com, Dressbarn, Lake Nyos.
Inventory went from 2 episodes to 6 and 4. The rejection reasons are substantive now — "2023 event with surviving family and live criminal proceedings", "general concept article, not a specific incident". Those are verdicts on the full text.
The regression guard needs no network. It only inspects the parameters.
D._wiki_get = lambda params: (sent.update(params), R())[1]
assert "exintro" not in sent, sent # present at any value means intro-onlyThree self-checks
- Have you counted your rejection and failure reasons? If one reason is over half, that is probably a property of your pipeline, not of the things it rejected.
- Before blacklisting something forever, do you log the size of the input the verdict was built on? A reason string alone cannot distinguish "a fair verdict" from "a verdict on broken input".
- Do you know whether your API's booleans read the value or just the presence? In
MediaWiki, and in several APIs that follow the same convention,
flag=0does not turn it off.
The honest part
This was not clever debugging. I recognized one famous company name and ran len(). That was
the whole thing. But I skipped those thirty seconds and spent two days building on the premise
that I was out of topics. The 43 burned entries were on the list the entire time, with their
reasons written out.
I just hadn't read them.
Go run sort | uniq -c on your pipeline's rejection reasons right now. Look at what's
first, then verify one single case by hand to see whether it's really the subject's fault.
It might take you thirty seconds too.