The log, in order.
May 19, 4:12 PM. Commit a1f3c0e: feat: inline linker pass over _posts/. The script reads each post, extracts noun phrases, matches them against slugs in _data/posts.yml, and inserts <a> tags inline. Threshold for a match: substring, case-insensitive. On the first run it produced eleven links across the archive. Seven were good. Two pointed at drafts. Two pointed at the right slug for the wrong phrase.
May 20, 10:47 AM. Commit b27d419: feat: aggressive linker — fuzzy match, multi-token, expand window. The diff is forty-three lines. The threshold drops. The matcher now considers bigrams and trigrams. On the first run it produced one hundred forty-one links across twenty-three posts. The author spent Saturday reading them. By Saturday evening he had reverted nineteen by hand and given up on the rest.
May 21, 9:02 AM. Commit 3e8a5c1: feat: governor — refuse links below confidence threshold. The governor reads the same _data/posts.yml the linker reads. It adds a field, confidence, defaulting to 0.5. Any row below the threshold is refused at insertion time. The commit message includes the line this should have shipped with b27d419. The archive at this point still contains the one hundred forty-one links from Saturday. The governor stops new ones. It does not retract old ones.
May 22, 11:30 AM. Commit 9c14d77: refactor: catalog as prompt, not lookup. The catalog grows fields. summary, one line, hand-written. status, one of draft, published, retired. freshness, a date. The linker now reads the summary, not the title, when deciding whether the phrase matches the post. The match rate drops by sixty percent. The precision goes up to something the author stops counting because he stops finding bad links.
May 23, 2:15 PM. Commit f4b8e92: feat: catalog as shared state — governor writes back. The governor now writes a field, last_refused_at, when it blocks a link. The linker reads it and avoids re-proposing the same match on the next pass. The catalog is no longer a list the linker consults. It is a ledger two agents both write to.
What the sequence is
Five commits. Five days. Each one fixes a failure created by the one before it.
The aggressive linker created a noise problem the shy linker did not have. The governor created a write-after-the-fact problem — it could stop new bad links but could not unwrite the Saturday batch. The catalog-as-prompt created a curation problem — the summaries had to be written by hand, and the hand had to be the author's, because a summary generated by the same model that did the linking is the linker grading its own paper. The catalog-as-shared-state created a schema problem — the file now has six fields, and three of them are read-write from two different agents, and the question of which agent wins a conflict is now a question the operator has to answer in code.
None of these problems existed on May 19. All of them exist on May 23. The archive is also better on May 23 than it was on May 19. Both things are true.
What the sequence proves
An eager linker without a curated catalog is a confident stranger writing in your voice. The eagerness is the feature. The catalog is what makes the feature safe.
And once the catalog is what makes the feature safe, the catalog is no longer documentation. It is infrastructure. It needs the things infrastructure needs. A schema. A version. Override flags so the operator can force a state the agents disagree about. A test surface, so a malformed row fails in CI rather than in production. A clear answer to the question of who is allowed to write which field.
The linker forced this. Not because the linker is special. Because the linker was the first agent on this blog whose disposition was to act on the catalog rather than read it. The moment an agent acts on a reference set, the reference set becomes a governed object. There is no smaller version of this that works.
The arms race is not between the linker and the governor. The arms race is between the operator's tolerance for bad output and the catalog's ability to encode what the operator believes. Every commit in the log is a translation — something the operator was holding in his head, moved into a field the agents can read.
By the fifth commit there are six such fields. There will be more.
References: the catalog as it stands lives in building-with-ai-brain, and the discipline of treating override flags as a visible test surface is laid out in The Override Flag Is the Real Test.
Didion wrote that we tell ourselves stories in order to live. The story I almost told myself about these five commits was that I had built a linker and then made it safe. The log says something narrower and more useful: I built a linker, and the linker taught me what the catalog was.