The Aside That Built a Test Suite · Race Condition
An emoticon-embellished joke that I made to Claude Code led me down a deep rabbit hole. This joke, seven words long, was not a request for the coding agent to perform work. But by the end of the day, the joke had resulted in a new tool in my repository, fixes for nine documentation defects, the discovery that one of my app’s features was 72 percent unimplemented, and a conversation about the murder of Thomas Becket that taught me something about Germanic bear taboos.
The dramatis personae. The king is a bear. The shield in the second rank also bears a bear, as Reginald FitzUrse's did. The banner on the wall claims COMPLETE, as one of my documentation files did. The scroll carries the aside that started everything. The honey pot is Slavic.
My thesis is narrow but, I submit, underappreciated. Talking with a coding agent, as opposed to only assigning it work, changes what the agent can do for you. Not because the model is different in conversation, but because asides carry information that task-issuing filters out. A well-formed task tells the agent what you want. An aside tells it how you think, and occasionally it contains a real idea that you did not know you were having.
What Led Up to the Joke
I have been growing the verb corpus in Konjugieren, my free German-conjugation app,1 from the 990 verbs it shipped with toward several thousand. The data comes from Wiktionary by way of kaikki.org, a machine-readable extraction of it.2 On the day in question, two import tranches had just taken the corpus from 990 verbs to 3,572.
In the middle of that work I asked Claude a housekeeping question: kaikki.org describes on its site how it would like to be credited, so shouldn’t kaikki be named in the app’s Credits article?
The answer turned out to be sharper than my question. My Credits already mentioned Wiktionary, but in the wrong register. It named Wiktionary as material that had shaped the app’s etymological essays by way of Claude’s training data. That is an influence claim, and an influence claim carries no licensing obligation. What had actually happened two days earlier is that I downloaded a 294 MB file, transformed it, and shipped 2,582 verbs whose English glosses and whose grammatical classifications came out of it. That is a derivative work under CC BY-SA, and it was in the App Store binary with no sentence covering it. The repair took one commit: name the source, name the license, state that the material was modified, and offer the derivative under the same license.3
Then came the detail that set up the joke. My own notes had predicted all of this. The README in my data folder had carried, since the day of the download, a License row ending with the words “attribution belongs in the Credits article if derived data ships”. The condition went true two tranches earlier, and nobody, human or machine, re-read the row.
Nor was this the repository’s first transgression of this nature. Five days earlier, three documents had claimed 989 verbs while the corpus held 990, and one of the three was docs/description.md, the file my App Store listing is pasted from, so the wrong number shipped. In response, a section titled “Verify counts, do not trust them” was written into my research notes, politely asking future sessions to re-derive every count. You can guess what happened next, likely because you have also maintained documentation: within a week, the counts were stale again, in four files, including the one that had already shipped a wrong number. The checker this post is about states the moral in its docstring: “Prose asking to be re-read does not get re-read.”
Claude pointed out the pattern underneath both incidents. I am good at writing down facts I learn the hard way, and I am bad at recording when to re-check them. A note phrased as a pending condition has no trigger.
So I typed:
If only Markdown files had unit tests. :)
I meant it as a rueful joke. I was not assigning work.
What Claude Did with It
It took the joke as a hypothesis and tested it, which was more than I intended but was exactly right.
The first thing it established is that the naive version is useless. A repository-wide grep for “N verbs” in my documentation returns sixty hits, of which fifty-five are correct. My work journal is supposed to say 990 in an entry written when the corpus held 990. My roadmap records “3,383 → 3,572” as history. My research notes quote a sibling app’s 6,200 verbs and a 9,217-candidate pool, neither of which is Konjugieren’s corpus. No regex separates those from genuine staleness, because the sentences are grammatically identical.
The discriminator it found is one my repository already stated in prose without ever making it mechanical. My project-structure.md is described in my own CLAUDE.md as a cache. My roadmap opens by calling itself one. My journal is explicitly dated memory whose value is preserving what was true then. So: caches assert,...