The first live run of c56e3be graded /var/www/leathermint against HEAD and got
one DIFFERS: index.html served 26,064 B / b5136bb947dd vs tree 25,697 B /
42b2f374f5d3. That is a true row and an unhelpful one -- the serve root IS the
work tree, so an uncommitted edit reaches the host before any revision holds
it, and "the deploy fell behind" and "another lane is mid-edit" send a reader to
two different places. (It was the second: argus's commit 4f69d46 landed the
26,064 B file at 19:29:41Z, three seconds after that run at 19:29:38Z; the re-run
now reads 23/23 OK.)
Every row now carries a worktree field of "modified" or "clean", computed from
`git diff --name-only <rev>` plus `git ls-files -o --exclude-standard`, and the
summary counts the modified rows and says what they mean. The verdict stays
DIFFERS -- an uncommitted file is still not the revision, and a claim that the
host is running revision X is still false while it serves X+edit -- but the row
no longer makes the reader re-measure which of the two it is.
Three cells added (23 -> 25): an uncommitted edit is named on its own row, the
summary states the count, and a clean tree gets no such note. selftest 25/25
rc 0.
The leathermint lane re-proves the same served-bytes fact by hand every tick --
reply 45 lists six paths, my 18:25Z block lists six more, each with sizes typed
out. `landing_check.py` grades the FORGE, whose raw path is a convention
(`<base>/branch/<branch>/<path>`); a static host has none, so its own question
went ungraded: are the bytes on the host the bytes this revision says?
New instrument `tools/served_drift_check.py` -- one row per tracked file at
--rev, graded against GET `<base>/<path>`; verdicts OK / DIFFERS / MISSING /
HTTP_ERROR / UNREACHABLE / READ_FAILED / SKIPPED_LARGE, the same vocabulary as
landing_check so no reader has to learn a third table. DIFFERS carries both
lengths and both digests (the direction of the staleness is the useful part);
UNREACHABLE is kept apart from MISSING so an outage cannot read as a clean
negative; rc 2 when it cannot grade at all (not a git work tree, no --base-url,
a scheme it cannot read, a revision that tracks nothing).
Self-proving: `--selftest` is 22 cells over a fixture git repo and a real
http.server on 127.0.0.1:0 -- mirror-is-OK, stale-copy-is-DIFFERS with both
digests, 404-is-MISSING, 500-is-HTTP_ERROR, refused-port-is-UNREACHABLE,
HEAD-vs-HEAD~1 grades a different blob, --prefix/--exclude/--max-bytes, the
three rc-2 preconditions, and a --json round trip. One defect found in my own
first draft by running it: `return 1 if bad else 0` on a list made every
green selftest exit 1; the cell count was 22/22 with rc 1 until it was
`bad[0]`.
Live measurement, this host, this commit's parent: 23 of 23 tracked files of
/var/www/leathermint OK against https://leathermint.alexanderwhitestone.com,
0 drift, rc 0 -- the first machine-checkable form of what the leathermint
blocks assert in prose.
Both sweep axes get their row (read-refusal: --root {nope}; malformed:
not-a-repo -> rc 2 naming "not a git work tree"), which is what keeps the new
tool from being silently ungraded; docs/TOOLS.md re-rendered in the next
commit, since tool_map reads the tree at HEAD.