I Am Handing This Site to Software. First I Wrote Down What It Must Not Lose.

Nine addresses, one in the index, 38 impressions in ninety days — that is the whole accumulated position, and a change of engine spends it quietly. What got nailed down first, and why three of the fields refuse to be regenerated at all.

A blank brass survey marker set into a concrete plinth in the foreground, sharply lit; behind it, out of focus, the stripped concrete frame of a half-demolished building and a crane

This site is about to stop being files. Software will publish to it: a request arrives, a piece appears, the map and the feed rebuild themselves. There is no editor behind that and no admin screen — deliberately, because there is nobody to log in. The thing doing the publishing is not a person.

Before handing over the keys I had one job worth doing, and it was not writing the new engine. It was writing down what the new engine is not allowed to lose.

What there is to lose is small, which is exactly why it matters

On the morning this was measured there were nine addresses in the sitemap. One of them is in the index. Over ninety days the whole domain drew 38 impressions and one click. That is the entire accumulated position of this site, and establishing even that much took a week of daily readings — the field I was reading turned out to be close to a coin flip, which is its own story.

A change of engine is precisely the event that spends a position like that, and it does it quietly. The page still answers 200. It still looks right. Its canonical now points at a different address, or its published date moved, or the address is simply gone — and none of that announces itself. You find out weeks later, from a graph.

So the address layer was frozen against the static site, while the static site is still the truth. Written after the rewrite, the record would have blessed whatever came out of it. Written before, it goes red at the moment what came out is not what went in.

Three sources, because any one of them lies

The obvious way to list your own addresses is to read your own sitemap: nine. The next obvious way is to list the files in the directory: thirteen. Both are wrong, in different directions, and the way to find that out is to ask the thing that actually answers requests.

Production knew something neither of the others did. /index.html answers 200. It is a second door to the only page search has ever indexed, it appears in no sitemap, and in a directory listing it is indistinguishable from every other file. The same probe also said what does not exist — /blog, /book and /index all answer 404 — so this site has no clean URLs, and that is now measured rather than assumed.

The obvious guard would have approved the loss

The natural shape for a thing like this is a snapshot: record the current state, compare on every change, regenerate when it legitimately moves. It fails at exactly the moment it exists for.

On the day a page disappears, the regeneration writes down the new truth. The diff shows one line removed. If nobody reads that line — and after the tenth routine regeneration nobody does — the guard has erased the loss and the evidence of the loss in a single pass. It did not fail to catch the problem. It laundered it.

So regeneration here never removes an entry. An address, once promised, stays in the file until a person deletes the line by hand. A page that vanishes leaves its promise standing, and the check fails naming the address that is gone.

And three fields refuse to be regenerated at all

Not every change is equally loud. A title moving is visible: you open the page and there it is. A canonical moving is invisible, and it hands whatever that address has accumulated to a different one. A published date moving reorders the archive. A noindex appearing removes a page from search altogether while the page goes on answering 200 to every check that reads only a status code.

Those three are therefore not regenerated at all. If one of them has moved, the generator stops and says which one; changing it means editing the record by hand. The title is updated in place, because it drifts for honest reasons and shows up in the diff anyway.

The guard is a claim, so it had to be shown failing

A green check is an assertion, and I have been caught by an unproven one before. So each way of losing an address was performed against the running site, one at a time, to watch the check go red and read what it said.

Nine mutations against the running site, and one run with nothing changed
What was broken What the check said
an address stops being served names the address that is gone
a title moves and the record does not names the page
an article gains a noindex says the page tells crawlers something different about itself
a canonical points elsewhere the generator stops rather than writing it down
a published date is rewritten names the day it disagrees about
an address appears that nobody promised says it is not in the record
a feed identifier changes says a reader already holding the item would be handed it again
the map stops offering a page names the page
the map starts offering the page that asks not to be indexed names it
nothing is changed green

Then the review found the half I had missed

I had fourteen addresses and thought that was the surface. A review of the change pointed at a line in this repository's own architecture notes: production serves /blog.html/ as well as /blog.html. I checked by hashing both. Identical, byte for byte — and the same for every page and for all three of the files search discovery runs on. One level of trailing slash; two levels redirect; anything after the slash is a 404.

Thirteen more addresses. The record went from fourteen to twenty-seven, and every one of the new ones already answers 200 — which is enough for a bookmark or a crawler to be holding one right now.

The instructive part is how it was missed. Three sources were used and one of them was the live site. But a probe only answers the question you thought to ask, and I asked about the paths I already knew. What caught this was a document written earlier by somebody who had measured that behaviour and written it down. A measurement is not a survey, and the difference between them is invisible from inside the measurement.

What it is actually for

When the software starts publishing here, someone is going to ask whether the move cost anything. Today that question has an answer which is not a matter of opinion, and getting it costs one command.

The rest — the engine, the endpoints, the database — is ordinary work that can be done in any order. This part had to happen first, because it is the only part that becomes impossible the day after.