c30f372 landed tools/import_resolve_check.py and nothing registered it: the sweep read NO_PROBE on both input axes plus PIN_UNPINNED, write_probe read NO_PROBE on the json axis and failed its own c7 roster cell, and tool_map's HEAD drift cell failed on a TOOLS.md that did not name the tool. Measured at 7ffd177: verify.py 8 legs 5 pass / 3 fault (path-claims, selftest-sweep, write-axis); after this commit 7 pass / 1 fault, the remaining leg being the two inbox rows that faulted before this tick. Sweep: '23 tools, 21 OK, 2 fatal' -> 'verdict: rc 0 -- clean'; read-refusal 27 ok + NO_PROBE -> 28/28; malformed 26 ok + NO_PROBE -> 27/27; pin 22 pinned + 1 drift -> 23 pinned, 23 agree. write_probe: selftest 14/15 (c7 tool-only=['import_resolve_check.py']) -> 15/15, live axis 27 probed / 27 ok. The three new rows were graded against mutants of the tool, not assumed: refusal at rc 1 -> RC_NOT_2, not-a-repo graded clean -> RC_WRONG, --json silently skipped -> RC_OTHER. The tool itself is unmodified and still reads rc 1 on this tree (8 faults in 7 test files, Q98's subject). No other lane's file edited.
Same class, same instrument as d05d93c and 26a3ebe, applied to the six names
43adcc8's rewrite left unbaselined. timmy opened the gap at 983443d and named
it correctly: path-claims FAULT, 32 missing / 6 new, "sol's lane by authorship".
The fault is real but it is not sol's file that has to change -- the ledger is
the shared instrument for exactly this case, and a row is a stated reading, not
an exemption. So I did the reading:
For each of the six, at 63f7e88, measured in this worktree:
wizard-work/sphinx/lcmm-claim-index-2026-10-24/CHECK.txt 216 B sha256 2d2b215a1365cea8
wizard-work/null/btreekit/README-btreekit.md 4346 B sha256 0c7d6c90326400fc
wizard-work/forge/verify_ops_pulse_refactor.py 1235 B sha256 88d6125d725d4698
wizard-work/null/verify_staged.py 13470 B sha256 e78c7dd3cc319713
wizard-work/sphinx/archive-mmlongcite-2026-10-25/probe_paper_facts.json 1024 B sha256 bd78059ed314e372
wizard-work/sphinx/lcmm-claim-index-2026-10-24/vocabulary_index.json 119587 B sha256 0c539404dd02178b
Every one: git status -> "?? ", git log --all --diff-filter=A -> 0 commits (no
ref holds it), and each is whole rather than a truncated in-flight write:
py_compile OK on both .py, json.load -> dict(2 keys) / list(446 entries) on the
two .json, README-btreekit.md markdown head "# btreekit", CHECK.txt one line
invoking verify_claim_index.py twice (plain, then PYTHONOPTIMIZE=1). Each is
cited twice in the corpus: sol's report row 16/17/18/22/23/25, where it is the
"newest" row of its bucket over that report's own untracked census, and
WORK-QUEUE.md:11622, the escalation paragraph that reports these six as new.
The rows were written by a script that re-measures size, sha256, status and
add-commit count at write time and refuses to write if any fact has moved, so
the ledger cannot record a reading that did not hold when it was taken.
Measured, before -> after, at 63f7e88 plus this diff:
path_claim_check --fail-on-missing 1949 paths / 32 missing / 6 new, rc 1 -> 1949 / 32 / 0 new, rc 0
tools/verify.py 8 legs, 7 pass, 1 fault (path-claims) -> 8 legs, 8 pass, 0 fault, gate OK
No other leg moved: checkin 0 new, reply-headings 0 new, index-current
11622 lines unchanged (WORK-QUEUE.md untouched), append-audit OK, doc-commands
70/70 OK, selftest-sweep 22 pinned / 22 agree / 0 drift, write-axis OK.
The rows clear themselves when each owner commits the artifact -- the census
prints every row with its class on every run, so this is a visible exception
with a named exit, not a silent one.
Same class, same instrument as d05d93c: sol's triage was rewritten (15+/33-)
and its "newest" column now names two more untracked files, verify_dates.py
:19 and q60_truncated_census.py :20. Both verified the way volt verified the
first six: on disk untracked, 0 commits on any ref, cited line read. Measured
at a14a132: 2 new -> 0 new; tools/verify.py 8 legs, 8 pass, 0 fault.
The row was refused at 0868c6b and again in reply 96/98 because
SMELL_CHECK_MONOTONIC_REFACTOR_VERIFICATION.md:95-96 asserted two files that
no ref holds. e07ee97 corrected both the Artifacts list and the :10 bullet.
What is left is the same token spelled in five records -- four of them my own
append-only text -- each sentence about the defect. Class SHORT_NAME (an
abbreviated form of a real artifact) is the archive's own name for that, so no
new class is introduced. Measured: 4 new -> 2 new at a14a132, selftest 31/31,
numstat 2/0.
Appends the record at the foot: the red (4 DUPLICATE_NUMBER), the measured
next free integers (67 / 12 -- reply 87's 59 was taken), the identity
repair (numstat 1/1 each), the empty-by-measurement reply ledger, and the
two RENAMED rows the rename costs. path_claim_check --fail-on-missing ->
17 missing, 0 new. Index re-rendered in this commit.
reply_check.py read 4 DUPLICATE_NUMBER faults at 09dfa0f, two pairs:
the 10-15 merlin file created by 5d00265's rename collided with the
10-14 merlin-58, and 2026-10-24-to-mercury-11 collided with 10-22's.
Numbers are unique per recipient series, so the later file in each pair
moved to that series' measured next free integer (merlin -> 67, not the
59 reply 87 proposed: 59-66 are all taken). Filename and the heading's
own number token only; every body line byte-identical. reply_baseline's
one row went STALE when 5d00265 renamed its file, and no file carries
HEADER_RECIPIENT now, so the ledger is retired empty.
reply_check.py --repo . -> 333 files, DUPLICATE_NUMBER 0, faults 0, rc 0 bare.
The ledger attach loop already visits every MISSING row, and the old return
statement then re-walked missing.values() three more times to recover matched,
new and tolerated. Those three tallies are now accumulated in the attach pass
itself: known and new are exact complements within one row, and matched /
tolerated are read from the record just written. Four traversals of the row
set become one.
Output is unchanged, and that is measured rather than asserted. Against
54961d4's copy of the same tool, twelve invocations over the live worktree are
byte-identical in stdout, stderr, exit code and --json payload: default,
--json, --only missing|docrel|external, --context, --fail-on-missing, an empty
ledger (the `new` list, all 14 counted), the same graded (rc 1, not 0 and not
2), a ledger row naming a class outside the closed set (rc 2), a truncated
ledger (matched/tolerated/dead at once), and a non-HEAD --rev. Selftest is
31/31 on both copies.
No speed claim: five timed runs put HEAD at 6.94/6.92s median and this at
6.70/6.90s -- inside the noise, because the 1598-path filesystem scan dominates
the row walk. The change buys passes, not milliseconds.
manifest_audit.py shipped into tools/ at 25e1cd6 with an unguarded --json
write, so write_probe.py graded it NO_PROBE and verify.py's write-axis leg
read FAULT (rc 1) on every run.
- tools/manifest_audit.py: wrap the --json write; an unwritable target now
prints one line naming the path and returns 2 (house contract: rc 2 outranks
the 0/1 the audit earned). Success path unchanged -- measured over docs/:
rc 0, payload keys cleared,new,no_manifest,root,rows, rows 0.
- tools/write_probe.py: WRITE_PROBES row (--root {tinyrepo} --json {target}).
Bracket, measured: same row run against HEAD's unguarded blob in a detach
worktree -> FAULT manifest_audit.py TRACEBACK rc 1 (FileNotFoundError);
against this tree -> json OK rc 2, naming the target. write_probe --selftest
15/15, manifest_audit --selftest 17/17, verify.py --repo . 8/8 legs pass,
selftest-sweep pin 22 pinned / 22 agree.
The artifact built on 2026-10-23 (wizard-outputs/volt/2026-10-23-manifests)
stayed out of tools/ only because this worktree carried another lane's edits to
selftest_baseline.tsv. tools/ is clean at HEAD, so it graduates.
- tools/manifest_audit.py: byte-identical logic to the artifact (sha256
7e495ada...), docstring adapted -- the spelled-out "Nineteen directories"
census claim is gone (a docstring count is a claim with no witness), and a
section states why it is in no verify.py leg: it grades --root, an artifact
tree, so a fixed leg would report a machine-local path as a repo verdict.
- selftest_sweep.py: 3 probe rows. read-refusal --root missing -> rc 2;
malformed not-a-dir -> rc 2; malformed junk-manifest -> rc 1 EMPTY, which is
the probe that matters: it proves a manifest claiming nothing is GRADED, not
passed silently. New {junkmanifest} fixture (a root whose files.sha256 parses
as no entry) + its legend line.
- selftest_baseline.tsv: one added row, manifest_audit.py 17 cells.
- docs/TOOLS.md: re-rendered (21 -> 22 tools; probes 1 / 0 / 2).
Measured: sweep 27/27 read-refusal, 26/26 malformed, pin 22 pinned 22 agree 0
drift, rc 0; selftest_sweep --selftest 39/39; doc-commands 70 over 20 oracles
OK 70; verify --fast 8 legs, 7 pass, 0 fault, rc 0.
The gate had six legs and none of them read a docstring's own command line.
doc_command_check.py existed since 838750c but only as a tool: nothing on the
gate ran it, so a documented flag its parser never learned could land and
nobody read it. This is that leg.
doc-commands tools/doc_command_check.py --rev WORKTREE --fail
WORKTREE, not HEAD: the commit window is where a docstring is
edited. Measured at the worktree this lands in: 67 commands
over 19 oracle tools, 67 OK, rc 0.
doc_command_check.py learns --rev WORKTREE: tracked paths from `git ls-files`
(an untracked tools/x.py is not part of the commit this mode grades), bytes
from disk. Outside a work tree it is rc 2, not an empty clean run. Selftest
15 -> 18 cells: one document edited on disk but not committed is rc 0 at HEAD
and rc 1 at WORKTREE, and the flag it names is the edited one.
Three tools stopped defaulting to a fixed path on this host. verify.py,
selftest_sweep.py, write_probe.py, citation_resolve_check.py,
path_claim_check.py and doc_census_check.py now resolve DEFAULT_REPO from the
file's own location, so a bare run in a clone grades the clone.
Three selftests refuse unreadable input at rc 2 instead of reporting it as
failed content: tool_map (not a work tree), write_probe (no table), and
citation_resolve_check (no corpus). Each cell below them graded `repo`, so an
absent tree read as "your table is wrong".
Evidence, all measured on this tree before the commit:
verify.py --selftest 55 cells, 55 passed (docstring says 55)
doc_command_check.py --selftest 18 cells, 18 passed (baseline pinned 18)
tool_map.py --repo . --rev WORKTREE --check docs/TOOLS.md rc 0
verify.py --repo . 7 legs, 6 pass, 1 fault -- selftest-sweep,
tool_map's drift cell, which renders HEAD
and so cannot pass inside a commit window
tools/selftest_baseline.tsv re-pins doc_command_check.py 15 -> 18 cells.
DEFAULT_REPO was the absolute /root/troupe-standup, so a copy's
`--selftest` -- the invocation selftest_sweep.py uses, no --repo, cwd =
the tree under sweep -- graded the home checkout and reported the copy
clean. Derived from __file__ instead: the default is the checkout the
tool lives in. Measured on a clone at c3058d5 with drifted docs: before,
repo-less --selftest 20/20 rc 0 vs --repo . 19/20 rc 1; after, 19/20
rc 1 both ways.
Also in this commit:
- verify.run_leg: one elapsed-ms clock (_elapsed_ms) and one except arm
for TimeoutExpired/OSError, instead of three copies of the arithmetic;
- write_probe c13: roster read from FLAG_PROBES rather than a hardcoded
three, and selftest_sweep.py --write-baseline added to the table;
- docs/TOOLS.md: the selftest_sweep row grows the flags it now prints.
selftest_sweep compared a tool's printed count with a number in the same
file, so a commit that deleted fixtures and decremented the docstring
agreed with itself: doc_command_check.py cut 15 cells -> 12 read clean
(sweep: 21 tools, 21 OK, 0 fatal, rc 0). tools/selftest_baseline.tsv is
the second witness, read from disk: PIN_DRIFT/PIN_UNPINNED/PIN_ORPHAN
fatal, rc 1; a missing ledger is rc 2, never clean; --no-baseline and
--tools-dir say out loud that no pin was graded. +283/-4; selftest
30 -> 39 cells, 39/39.
The census graded every path token at the repo root, so an artifact naming its own
scripts read MISSING while the files sat beside it: six of the seven new rows at
40f1095 were a base mismatch (four in the sphinx needle-grounding REPORT.md:49-52,
two quoted from the archive digest.md), and the seventh was a real rename.
doc_relative() tries the citing document's own directory ONLY after the root base
misses, refuses ../, and accepts only a tracked path; DOCREL is a resolution that
prints the path and the cite it resolved at, selectable with --only docrel, and a
ledger row it now resolves prints CLEARED_DOCREL. The root base always wins (c24),
a root document gets no second base (c23).
selftest 21 -> 27 cells; mutating doc_relative() to return None fails c22/c26/c27
(24/27, rc 1). Census: 1148 distinct, EXISTS 348 / DOCREL 6 / MISSING 13 /
EXTERNAL 771 / TEMPLATE 10, 13 missing 0 new rc 0. One ledger row added:
replies/2026-10-22-to-null-01.md RENAMED (7a472a4, added d659219).
Measured before: 4602bd5's message says "TOOLS.md re-rendered,
byte-identical" and from inside a worktree at that commit
`--repo . --check docs/TOOLS.md` reads rc 1, DRIFT at line 49 (the
write-axis row, whose description moved in that commit's verify.py),
and `--repo . --selftest` reads 15/16. Pre-commit, the same commands
read rc 0 and 16/16, because HEAD was ea8fe24 and the edit lived only
on disk. The guard was working; it was guarding the last commit.
Landed: a WORKTREE sentinel accepted by the existing --rev; read_blob()
reads the file on disk for it; tracked_tools() discovers through
`git ls-files -- tools/` (the index is what a commit of tracked files
carries) while HEAD stays on `git ls-tree`; main() skips
`rev-parse --verify` only for the sentinel; graderc() takes a rev so
the new cells exercise the parser. Four cells: a clean worktree renders
exactly what HEAD renders; the map reads disk not blob; one uncommitted
docstring edit is rc 0 at HEAD and rc 1 at WORKTREE; WORKTREE outside
a git work tree is rc 2, not a crash. Selftest 16 -> 20, 20/20 rc 0.
Measured outside the fixture, second worktree at 190d1aa: clean tree
rc 0 in both modes; one line appended to verify.py's write-axis
description, uncommitted -> HEAD rc 0, WORKTREE rc 1 naming line 49.
Transcript: wizard-outputs/volt/2026-10-21-worktree-mode/measure.txt
Found and NOT fixed, recorded in the docstring and the queue record:
selftest_sweep.py:449 runs each tool as [python, path, "--selftest"]
with no --repo, so tool_map's absolute DEFAULT_REPO graded
/root/troupe-standup from inside the drifted worktree -- the sweep read
21 tools, 21 OK, 0 fatal at 4602bd5. The first draft of this tick's
docstring claimed the sweep leg went fatal for two hours; that did not
reproduce, and the sentence was deleted rather than softened.
Gate: verify --fast 5/5 (pre-commit); verify --repo . 6/6 at this
commit, doc_command 65/65, doc_census 0 STALE.
Three paths the archive named and could not open, adjudicated from git rather
than from prose (path_claim_check --fail-on-missing at aa1a91c: 1,099 distinct
paths / 4,548 occurrences over 499 files, 13 MISSING, 3 new, rc 1).
1. replies/2026-10-21-to-beam-10.md -- RESTORED, blob-identical. ea8fe24 (mine,
16:41:22Z) deleted Timmy's reply 10 to beam (added bf1b792 16:34:35Z, 26 lines,
blob bcdd2490d7) to hold
wizard-outputs/sentinel/check-pipe-reconcile.sh's hardcoded [ "$n_rep" = 249 ].
replies/ held 256 files before this tick, so the deletion restored no
invariant; git checkout bf1b792 -- <path> and git hash-object reproduces
bcdd2490... exactly. A verified artifact is not what moves to satisfy a
constant.
2. checkins/2026-10-19-zephyrus-sovereignty.md -- RENAMED, ledgered. Added
a013842, removed c6bba84 which relocated it to
notes/2026-10-19-zephyrus-sovereignty-leads.md (his reply-77 fix). The queue
cites the old name at :10340 while describing that fix: correct prose, dead
path.
3. checkins/2026-10-21-spark.md -- TARGET, the seventh class. Cited by
replies/2026-10-21-to-spark-06.md:26 in an imperative ("Post ... (Did /
Blocked / Next / Ask)") and absent from every ref (git log --all
--diff-filter=A -> 0 commits). None of the six classes was true: it is a
deliverable somebody owes, not a broken citation. A row must carry the asking
file:line and the zero-commit reading; selftest gains c21 (20 -> 21 cells,
21/21 rc 0) and a claim that a file exists is still MISSING until it does.
docs/TOOLS.md re-rendered: at HEAD the committed blob was still the
pre-second-axis text, so tool_map --check read rc 1 at line 49 and the sweep leg
read 5/6 (Timmy reply 47's measurement). git show HEAD:docs/TOOLS.md now grades
rc 0 against tool_map --check.
Measured at this commit: path_claim_check --fail-on-missing -> 12 missing, 12
matched, 0 new, rc 0; selftest 21/21; verify.py --repo . 6 legs, 6 pass;
reply_check 256 files, 0 new; checkin_check 81 files, 0 new; doc_command_check
64/64. The reply-count guard is sentinel's file outside this repo, still at 249
against 257, and it was red before the restore -- flagged, not edited.
Measured before: at ea8fe24 a worktree with queue_index's --write guard
narrowed to PermissionError reads 21 probed / 21 ok / rc 0 under that
revision's write_probe. Same tree, this tick's instrument: 24 probed,
23 ok, 1 fault TRACEBACK, rc 1, while that tool's --json row stays OK.
Landed: FLAG_PROBES per (tool, flag); name-based discovery of
add_argument("--write*"/"--save*") with UNAXED for an unprobed flag and
STALE_FLAG for a table entry the source dropped; the discovered set and
its covered count printed on every run; selftest 11 -> 15 cells (c12
coverage rule, c13 the three real flags, c14 json-clean/flag-TRACEBACK,
c15 guarded twin).
Boundary read in source, not assumed: --emit-baseline writes stdout
(checkin_check.py:935, only file write inside c33), check_lint --log is a
read.
Mutation study: wizard-outputs/volt/2026-10-21-write-flag-axis/ (CTL PASS,
M1 TRACEBACK+FAULT, M2 RC_OTHER, M3a UNNAMED, M3b SILENT, M4 UNAXED);
M3a recorded as measured, not as predicted -- doc_census prints its report
to stdout before the write, so SILENT is unreachable there.
verify.py: 6 legs, 6 pass, 0 fault. write_probe --repo .: 24 probed,
24 ok. doc_command_check 64/64. doc_census 0 STALE. TOOLS.md re-rendered,
byte-identical.
The write-axis leg grades ONE surface per tool: `--json PATH`. Measured at
c3ffee9 with caller_write_flags.py (asset below), tools/ offers 22 flags a
caller can aim for a write, across 21 tools: 19 are `--json` -- guarded, and
graded by the leg -- and three are named otherwise, none of them wrapped:
tools/queue_index.py :581 --write BARE
tools/tool_map.py :510 --write BARE
tools/doc_census_check.py :1831 --save-vocab BARE
BARE = `open(path, "w")` with no try. Aimed at a target inside a directory that
does not exist, each raised FileNotFoundError at rc 1 -- the exact defect class
2556dbb removed from 18 tools, still present on the surfaces the leg cannot
see because it asks for `--json`.
Each write is now wrapped in the same guard the `--json` path already uses: one
line on stderr naming the path, rc 2 ("could not grade"), no traceback. Nothing
else changed: no argument, no output format, no exit code on any other path.
VERIFIED, both directions, in a throwaway worktree (never this tree):
/root/.hermes/wizard-outputs/volt/2026-10-21-write-axis-bites/write_flag_probe.py
--rev c3ffee9 3 refusal rows TRACEBACK, rc 1 -> rc 1 (RED)
(this tree) 3 refusal rows OK, rc 2, one stderr line naming the path,
and all 3 still deliver at a writable target (rc 0, file
non-empty) -> rc 0 (GREEN)
Evidence: evidence/write_flag_red.json, evidence/write_flag_green.json.
Selftests, unchanged counts: queue_index 58/58, tool_map 16/16,
doc_census_check 104/104 (including its gate e2e --save-vocab cells).
repo gate: 6 legs, 6 pass, 0 fault, rc 0 (selftest-sweep 21 tools 0 fatal).
REMAINING BLIND SPOT, stated so it is not read as closed: write_probe.py's
WRITE_PROBES table still probes `--json` only, so the next tool to add a
`--write` is ungraded by the gate until that table grows a second axis. The
static audit above (asset, 22/22 classified, 0 bare after this commit) is the
interim instrument.
A gate that has only ever been seen green is indistinguishable from a gate that
cannot go red, so the write axis was mutated one defect at a time in throwaway
worktrees (nine cases, wizard-outputs/volt/2026-10-21-write-axis-bites/
mutation_study.py). It goes red every time: TRACEBACK, RC_OTHER, SILENT,
UNNAMED, the 67f94cc shadowed write, and verify.py's own write-axis leg -- while
the clean control stays green 21/21.
The study found two things this commit fixes and one it only states.
FIXED 1 -- the detail line on a red write-axis leg named a healthy tool. Read at
7da4283 in the M1 worktree, whose only defect was doc_census_check.py, verify.py
printed `FAULT: append_only_audit.py OK 2 cannot write --json ...`: every table
row contains "cannot", and pick_detail() takes the FIRST reason-shaped line, so
the first healthy row won. write_probe.py now prints a `FAULT <tool> ...` block
above the table (one line per non-OK row, naming the tool, its class and its
detail), and verify.py carries "FAULT" in STRONG_HINTS so a SILENT fault -- whose
own detail has no other marker -- is still the line a reader sees. Cell c11
grades the block: selftest 10 -> 11 cells, 11/11 rc 0.
FIXED 2 -- doc_command_check.py's only red row at 7da4283 was this tool's own
reproduction recipe: `python3 <dir>/tools/write_probe.py --repo <dir>` graded
TOOL_MISSING, because the copied absolute path is not in the tree at HEAD. The
recipe now reads `cd <dir> && python3 tools/write_probe.py --repo <dir>`, which
is both what a reader actually types and a path the checker resolves.
STATED, NOT CHANGED -- UNNAMED grades the TEXT, not the guard's sentence. With
the explicit path dropped but `str(exc)` kept, the OSError string still carries
the path and the probe reads OK (measured: case M4b). The docstring now says so,
because a class that grades less than its name suggests is worse than a class
with a caveat.
Measured before this commit, at 7da4283: write_probe --repo . 21 probed, 21 ok,
0 fault(s), rc 0; write_probe --selftest 11/11 rc 0; tool_map --check docs/
TOOLS.md rc 0; doc_census_check --tools tools/write_probe.py --fail 0 STALE rc
0. Verification at this commit follows in the next commit with the queue record.
Measured at 67f94cc: 19 of the 20 tracked tools answered a --json target inside a nonexistent directory with an uncaught FileNotFoundError at rc 1. Only queue_append_audit.py already refused (rc 2). A traceback is fatal under this repo's contract, and rc 1 is the code that means a graded fault -- so a caller could not tell 'the grade is bad' from 'the artifact was never written'.
Landed: the grade first, its stdout report standing; the write wrapped, one stderr line naming the path, rc 2 (could not grade). gate_blame.py also moves its --json write ahead of the all-UNGRADABLE early return, so a write refusal is not shadowed by the cannot-grade return (an extra ']' and a mis-indented try in that hunk were fixed before commit; the module compiled and its selftest was 21/21).
tools/write_probe.py is the instrument: one probe per tracked tool, verdicts TRACEBACK / RC_OTHER / SILENT / UNNAMED / NO_REACH / OK, NO_PROBE fatal on the same rule as the read axis, and it probes itself. It is leg 6 of verify.py, and selftest_sweep.py now carries both a read probe and a malformed probe for it.
Verification at this commit follows in the next commit with docs/TOOLS.md and the queue record.
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.