Produce the two files a crawler asks for, and refuse a sitemap that drifts [#69] - #161
Merged
Conversation
…rifts [#69] A crawler asks for the exclusion file before it asks for anything else and a sitemap is how it is told which addresses exist. The build wrote neither, so both requests were answered with the not-found page: a request the reader's host serves for nothing, and an answer carrying none of what was asked for. The build now writes robots.txt and sitemap.xml, last, after everything that can put a page into the output. The sitemap lists every produced page at the address it is served at, sorted, and leaves out the not-found page, which is served in answer to addresses that are not its own and would otherwise be offered for indexing under an address the site claims to have. Neither file carries a date, because a sitemap stating when each page last changed would produce different bytes from unchanged source on two days. The failure the new gate leg prevents is the day after. A generated file agrees with the output on the day it is written, so what reds here is a page written by something added below the writer and listed nowhere, or an address left in the list with no page behind it. The first is invisible to every other check: the page is valid, it is served, and nothing tells a crawler it exists. The second sends every client that reads the file to the not-found page. The leg walks the output directory rather than the list the build reported, so what it compares is the file on disk against the files on disk. Which pages a sitemap carries is one function, used by the writer and by the comparison, because a rule stated in both places would agree on the day the second statement was written and never be checked against it again. The suite cases that asserted how many files a build reports now ask whether it reported the file they are about. Counting was a statement about the whole set, which every new writer moves and none of those cases was about. The icon that issue also asks for is not here. What it shows is entry 7 of #7 and is not settled, so it waits rather than being answered by whatever this change would have drawn. Signed-off-by: Nils Lehnen <30603423+iderex@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #69, and short of its whole done condition. The last section says what
is left and why.
What was wrong
Two files get requested whether or not any page links them, and the build wrote
neither, so each request was answered with the not-found page:
Run 2026-08-13 at
269d93e. The reader's host serves a request for nothing, andthe client that asked gets none of what it asked for.
What the change does
The build writes
robots.txtandsitemap.xml, last, after everything that canput a page into the output:
Three decisions are in the change rather than under it, each with its reason at
the code.
The not-found page is the one produced page the sitemap leaves out. A sitemap is
a list of addresses a crawler is invited to fetch and index, and that page is
served in answer to addresses that are not its own, so listing it asks for an
index entry that sends a reader to an error page under an address this site
claims to have.
Neither file carries a date. A sitemap may state when each page last changed,
and a build writing today's date into one produces different bytes from
unchanged source on two days. That is checked rather than asserted:
The exclusion file names the sitemap only where one was written, because a
robots file pointing at an address the build did not produce sends the one
client that reads it to the not-found page.
Which pages a sitemap carries is one exported function, read by the writer and
by the leg that compares the two. Stating the rule in both places would state it
twice, and the second statement would agree with the first on the day it was
written and never be checked against it again.
The leg, and what it refuses
The file is generated, so on the day it is written the two agree by construction
and a comparison over them proves nothing. What it refuses is the day after, and
both directions are shown against this tree rather than against a fixture.
A page listed nowhere, produced by changing the writer to drop one address. This
is the failure every other check passes: the page is valid, it is served, and
nothing tells a crawler it is there.
An address with no page behind it, produced by appending one to the writer:
Both edits were made to the writer and taken out again; the branch carries
neither. The same two directions are decided cases in the suite, together with a
page listed twice, which both directions above pass over because each entry has
a page behind it.
The leg walks the output directory rather than reading the list of paths the
build reported. A walk that trusted the writer's own account of what it wrote
would agree with the writer about a page the writer never mentioned.
What this moves in the existing suite
Five cases asserted how many paths a build reported, which is a statement about
the whole set of files the build writes. Every new writer moves that number and
none of those cases is about it, so each now asks whether the build reported the
file the case is about. The one about an absolute output directory asks instead
that every reported path is under the directory it was given, which is what that
case was for.
One count is deliberately left as a count. The reproducibility neighbour states
three files, because the two new ones are the likeliest in this tree to become
unreproducible and that case is where it would be caught.
The gate
All commands run 2026-08-13 at
fe91b05.One verb reds on this branch and it reds identically on
main, for a reasonthis change does not touch:
Run 2026-08-13 on this branch and again with the branch stashed. It is not a leg
of the gate and it is about the release run, which #53 holds.
The means
Go, and the same shapes the tree already carries: a writer beside the other page
writers, a package with a pure decision the suite drives directly, and a leg in
the gate. It adds no language, no runtime and no dependency, and every claim
above is a command in a suite that already exists.
What is not covered
The icon. #69 asks for three files and this lands two. What the icon shows is
entry 7 of #7 and is not settled, so shipping one here would answer that entry
by drawing it. The clause about serving the produced files over a real host is
also untouched, and the byte budget clause reaches the icon rather than these
two.
Reader
This change carries no second reader. The evidence above is in its place: every
claim is a command run at
fe91b05, and the two directions the new leg refusesare shown reddening this tree and then passing with the same bytes restored.