I spent a session this week repositioning the copy on this site, and at the end of it I ran a typographic sweep across every file that holds text: strip the em dashes, replace them with the punctuation a person would actually type. Mechanical work, dozens of files, exactly the kind of thing you hand to a script.
The script was written the sensible way. For each file: read the current committed version from git, apply the rules, write the result back. Reading from HEAD rather than from disk is a real design choice with a real justification. It makes the pass idempotent. Run it twice and you get the same output, because the second run starts from the same clean baseline as the first. No double-applied rules, no compounding damage if something goes wrong halfway.
It also means the pass treats anything you have not committed as if it does not exist.
What that cost
An hour before the sweep, I had hand-edited the meta description on the about page. New positioning, one sentence, typed directly into app/about-me/page.tsx. Not committed. Sitting in the working tree, where uncommitted work sits.
That file was in the sweep's file set. The sweep read it from HEAD, which still had the old sentence, applied its dash rules, and wrote it back. My edit was gone. Then, afterwards, I re-applied the new positioning to the visible page body, which lives in a different file, about-content.tsx, and that one stuck.
So the page shipped in a state that is almost funny to describe. The body told visitors the new thing. The <meta name="description"> in the same route still advertised the old thing, which is what Google would have indexed and what a link preview would have rendered.
The part that actually bothers me
I did review the sweep. I looked at the diff before committing it, the way you are supposed to.
Here is the problem, and it took me a minute to see it clearly. The sweep produced rules(HEAD). The diff I reviewed was rules(HEAD) against HEAD. That diff contains exactly the dash substitutions, nothing else. It is clean. It is correct. It is precisely what I expected to see.
My lost edit could not appear in it, because my edit was never in HEAD. It existed only in the working tree, and the working tree was the thing the sweep overwrote and the thing the diff never consulted. The review artifact I would naturally use to catch the mistake is the one artifact structurally guaranteed not to show it.
That is the same shape as a bug I wrote about a few weeks ago, where a shell fallback turned "the check could not run" into a confident "found nothing." Different mechanism, same failure class: something reports success in a way that is locally, internally, technically true, and the truth it reports is not the truth you needed.
Why it landed in a meta tag
There is a second reason this survived. Of everything on that page, the sweep happened to revert the one field that renders nowhere a human looks.
I opened the page after the sweep. It looked right, because the body was right. I clicked through the site. Fine. Nothing in a browser window, a screenshot, or a manual pass over the rendered page shows you a meta description. You have to go looking at the document head, or at a link preview, or at what a crawler stored.
That is not a coincidence, it is a selection effect. Sweeps that break something visible get caught in the next five seconds. The ones that survive are the ones that land in the invisible layer: meta tags, alt text, JSON-LD, Open Graph fields, canonical URLs, sitemap entries, robots directives. That layer is large, it is entirely machine-facing, and on a site whose whole purpose is to be found and to be forwarded, it is not decorative.
What I changed
Three rules, in increasing order of how much I trust them.
-
Commit before a sweep. Obvious, weak, depends on me remembering. A rule that relies on discipline at exactly the moment I am moving fast is not a control.
-
Never re-derive a file from a committed baseline after hand-editing it, without re-applying and re-verifying every hand edit in that file. This is the rule I wrote into the commit that fixed it. Better, because it is specific about the dangerous operation rather than about my habits.
-
Read the working tree, or diff against it. The strongest version. If the pass reads from disk instead of from
HEAD, the problem cannot occur at all. If there is a genuine reason it must read fromHEAD, then the thing to inspect afterwards is not the diff againstHEAD, it is a comparison against the working tree as it was before the pass ran. That comparison shows the reverts. The other one cannot.
The general form, which I suspect applies well outside codemods: when a tool rebuilds its input from a snapshot, everything not in the snapshot is invisible to it, and invisible to every check that shares the same snapshot. Two things silently agreeing is not verification. It is one assumption, counted twice.