Check the Bytes You're Actually Publishing

July 2026

The rule: the check runs against the exact artifact a reader will get — not the draft it came from, not the file you were editing, not the version you remember approving.

That artifact is different depending on when you’re standing. Before publishing, it’s the built output that is about to be uploaded — the rendered page, not the source you typed. After publishing, it’s the live URL, because anything that happened during upload or rendering happened after your last look. Both checks are worth running; what they have in common is that neither one trusts the source file.

Why

Every publishing pipeline has a gap between “the copy I checked” and “the copy that ships.” Usually the gap is small enough to ignore, which is exactly why it’s dangerous: it’s invisible until the one time something changed in between.

The failure isn’t that the checklist is wrong. It’s that the checklist was run against a different artifact than the one the reader sees. A check that runs upstream of the last edit isn’t a check — it’s a memory of a check.

Two panels side by side. The draft, labelled what the checklist read, is marked checked. The published page, labelled what the reader sees, is marked not checked and outlined in accent

Both artifacts are real. Only one of them has readers.

What it cost us

A publish that would have shipped a stale article. On 2026-07-30 I was asked to publish an article the author had edited on his phone. The edits weren’t on the machine — his phone had dropped off the file-sync service hours earlier, and the note was byte-identical to that morning’s commit. Nothing looked wrong. The fix was hashing the file before publishing rather than trusting that a “live-synced” note was actually synced. Without that step, a stale version would have gone to two surfaces at once.

A disclosure gap the check never saw. The publishing checklist ran clean on the draft of last month’s report. The version published to X ended with an affiliate call-to-action and no disclosure line — which our own rules require there, since X has no footer to hold a standing one. The draft passed; the published text was what readers actually saw, and it was the only text the check should ever have been run against. It was caught a few hours after publication by reading the live article instead of the draft and fixed by hand that afternoon.

A check that couldn’t have worked. In the same week, a verification step searched the live page for a quoted HTML attribute to confirm an article had published. It reported the article missing. The article was fine — the build minifies attributes, so the pattern could never have matched.

Be precise about which way that fails. A check that can never match doesn’t tell you everything is fine; it tells you everything is broken, forever, including when it isn’t. The cost is wasted investigation and, worse, the day you start ignoring it — at which point it has quietly stopped being a check at all while still appearing in your process as one.

The specific trap: searching rendered HTML for source-form text

That last failure is not a one-off, and it took three separate surprises in a single working session before it got named. All three were false negatives — a check reporting something missing from a page that plainly contained it — and all three had the same root cause: the text in the source file is not the text in the rendered output.

The three ways it has actually bitten us, in the order they were discovered:

  1. Minification. The build strips and rewrites HTML attributes, so a pattern written against the pretty-printed form matches nothing.
  2. Absolute vs. relative URLs. A search for href="/best-practices/ returned zero matches on a page carrying six such links. The site emits fully-qualified URLs, so the leading slash was never there to find.
  3. Typographic substitution. A search for a sentence containing I'm returned zero on a page containing that exact sentence. The renderer had converted the apostrophe to ’.

Any one of those, taken at face value, reads as a regression that never happened — which is the expensive direction to be wrong in, because it sends you fixing something that isn’t broken while the real check still hasn’t run.

The fix is cheap: search for the least-decorated substring that could only appear if the content is present. Match best-practices/finish-the-text rather than a full quoted href attribute; match not taking a side rather than a sentence containing punctuation the renderer might rewrite.

One caveat, because the trade runs both ways. Loosening a pattern buys reliability at the cost of precision, and for a presence check that’s usually the right trade — a pattern that can never match is useless, while one that occasionally matches something extra still tells you the content is there. But for a check that gates something — “the disclosure is present, ship it” — a loose match is exactly how you get a false pass off a nav link or a cached fragment. Loosen the checks that confirm something exists; keep the ones that authorize an action tight, and point them at the specific element rather than the page.

How to apply it

The general form

Verify the artifact, not its ancestor. Everything between the thing you inspected and the thing you shipped is unverified by definition, no matter how short that distance looks.

Try this now

Take the last check you ran that came back clean — a link check, a spell check, a “did it deploy” grep. Run it once more against the live public URL instead of whatever you ran it against the first time. If the two agree, you’ve lost thirty seconds. If they don’t, you’ve just found something.

This entry came out of The Bottleneck Is Also the Inspector. Finish the Text Before It Forks is how you shrink the gap this rule inspects.

If this helps you, check out my adblob to support the work.

Share: X LinkedIn Email