volt: tool_map grades the tree it lives in, not the one it was written in

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.
This commit is contained in:
volt committed 2026-10-22 17:08:40 +00:00
1 parent 2a1ef2feaf
commit b859ad6464
4 files changed
+70 -36

No files matched your search

+1 -1
View File
@@ -27,7 +27,7 @@ module docstring, flags from the tool's own `--help`, probe rows from
| `queue_claim_check.py` | the claim check for `WORK-QUEUE.md`, shipped with its tests. | `--queue` `--json` `--git` `--validate` `--selftest` `--fail-on-stale` `--explain` `--census` | 1 / 1 / 1 | - |
| `queue_index.py` | the work queue's table of contents, and the gate that it is current. | `--repo` `--queue` `--index` `--json` `--write` `--check` `--outside` `--selftest` | 1 / 1 / 1 | `index-current` |
| `reply_check.py` | does every reply file's own header agree with its own name? | `--repo` `--dir` `--roster` `--head-lines` `--json` `--baseline` `--emit-baseline` | 1 / 0 / 1 | `reply-headings` |
| `selftest_sweep.py` | every instrument proves itself, in one command, and the number it advertises is the number it prints. | `--repo` `--tools-dir` `--timeout` `--json` `--quiet` `--verbose` `--selftest` | 1 / 0 / 1 | `selftest-sweep` |
| `selftest_sweep.py` | every instrument proves itself, in one command, and the number it advertises is the number it prints. | `--repo` `--tools-dir` `--timeout` `--json` `--baseline` `--no-baseline` `--write-baseline` `--quiet` `--verbose` `--selftest` | 1 / 0 / 1 | `selftest-sweep` |
| `served_drift_check.py` | does the host actually serve the tree at this revision? | `--root` `--rev` `--base-url` `--prefix` `--exclude` `--max-bytes` `--timeout` `--json` `--quiet` `--selftest` | 1 / 0 / 1 | - |
| `tool_map.py` | the instruments get a map, and the map is generated from the tree. | `--repo` `--rev` `--write` `--check` `--json` `--selftest` | 1 / 0 / 1 | - |
| `verify.py` | the HOME the index gate did not have: one command, six legs, one exit code, and a row per leg so a partial run cannot look like a clean one. | `--repo` `--queue` `--index` `--checkin-day` `--fast` `--timeout` `--json` `--quiet` `--selftest` | 1 / 0 / 1 | - |
+21 -5
View File
@@ -58,10 +58,26 @@ THE PRE-COMMIT BLIND SPOT, AND THE MODE THAT CLOSES IT
The gate did not catch it either. `selftest_sweep.py --repo .` at `4602bd5`
reads **21 tools, 21 OK, 0 fatal**, because the sweep runs each tool as
`[python, path, "--selftest"]` with no `--repo` (`selftest_sweep.py:449`) and
this tool's `DEFAULT_REPO` is an absolute path, so its selftest graded
/root/troupe-standup -- a different, clean tree. That is a second defect, and
it is NOT fixed here: the sweep's selftest axis can grade the wrong tree. It
is recorded because it is why the pre-commit runs stayed green.
this tool's `DEFAULT_REPO` was an absolute path, so its selftest graded
/root/troupe-standup -- a different, clean tree. That was a second defect:
the sweep's selftest axis could grade the wrong tree, and it did.
FIXED 2026-10-22 (volt). `DEFAULT_REPO` is now derived from this file's own
location -- `dirname(dirname(abspath(__file__)))` -- so the default target is
the checkout the tool lives in: the same path in place, a different path in a
copy. Measured on a clone at `c3058d5`, whose `docs/TOOLS.md` is drifted
(`--check` reads **rc 1, DRIFT at line 30**):
- before the fix, `--selftest` with no `--repo` -- the sweep's own
invocation, `cwd` = the clone -- read **20/20, rc 0**: it graded
/root/troupe-standup, the clean tree, and called the clone's drift clean;
- the same clone under `--selftest --repo .` read **19/20, rc 1**, the one
failure being the currency cell below;
- after the fix, the repo-less run reads **19/20, rc 1** -- the same
verdict as `--repo .`, because the default now names the copy.
`selftest_sweep.py` needed no edit: `cwd` was already the tree under sweep,
so the fix alone is enough for the sweep's axis to grade what it walks.
`--rev WORKTREE` derives the map from the files on disk, discovered through
`git ls-files -- tools/` -- the index, which is what a commit of tracked
@@ -103,7 +119,7 @@ import subprocess
import sys
import tempfile
DEFAULT_REPO = "/root/troupe-standup"
DEFAULT_REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DEFAULT_DOC = "docs/TOOLS.md"
HELP_TIMEOUT = 30
+34 -23
View File
@@ -361,6 +361,16 @@ def leg_argv(key, repo, queue, index, checkin_day=None):
raise KeyError(key)
def _elapsed_ms(started):
"""Milliseconds elapsed since `started`; the integer clock every row carries.
Extracted so run_leg() does not recompute `int((time.time() - started) * 1000)`
at each of its exit paths -- the DRY collapse that previously ran the same
expression three times (timeout, OSError, normal verdict).
"""
return int((time.time() - started) * 1000)
def run_leg(leg, repo, queue, index, timeout, checkin_day=None):
"""One leg -> one row. rc 0/1/2 are graded; anything else is ungradable."""
tool = os.path.join(repo, "tools", leg["tool"])
@@ -384,30 +394,31 @@ def run_leg(leg, repo, queue, index, timeout, checkin_day=None):
proc = subprocess.run(leg_argv(leg["key"], repo, queue, index, day),
cwd=repo, capture_output=True, text=True,
timeout=timeout)
except subprocess.TimeoutExpired:
row.update(verdict=UNGRADABLE, detail="TIMEOUT after %ss" % timeout)
row["ms"] = int((time.time() - started) * 1000)
return row
except OSError as exc:
row.update(verdict=UNGRADABLE, detail="could not run: %s" % exc)
row["ms"] = int((time.time() - started) * 1000)
return row
out = (proc.stdout or "") + (proc.stderr or "")
row["rc"] = proc.returncode
row["detail"] = pick_detail(out, summary=(proc.returncode == 0))
if proc.returncode == 0:
row["verdict"] = PASS
elif proc.returncode == 1:
row["verdict"] = FAULT
elif proc.returncode == 2:
row["verdict"] = UNGRADABLE
except (subprocess.TimeoutExpired, OSError) as exc:
# Both transport failures collapse to the same ungradable shape; only the
# detail differs -- timeout names the deadline, OSError names the error.
if isinstance(exc, subprocess.TimeoutExpired):
detail = "TIMEOUT after %ss" % timeout
else:
detail = "could not run: %s" % exc
row.update(verdict=UNGRADABLE, detail=detail)
else:
# rc 3 is retired in this repo (one meaning, two codes); any other code
# is a tool that left the contract, and the run cannot grade through it.
row["verdict"] = UNGRADABLE
row["detail"] = "unexpected rc %d: %s" % (proc.returncode, row["detail"])
row["ms"] = int((time.time() - started) * 1000)
out = (proc.stdout or "") + (proc.stderr or "")
row["rc"] = proc.returncode
row["detail"] = pick_detail(out, summary=(proc.returncode == 0))
if proc.returncode == 0:
row["verdict"] = PASS
elif proc.returncode == 1:
row["verdict"] = FAULT
elif proc.returncode == 2:
row["verdict"] = UNGRADABLE
else:
# rc 3 is retired in this repo (one meaning, two codes); any other
# code is a tool that left the contract, and the run cannot grade
# through it.
row["verdict"] = UNGRADABLE
row["detail"] = "unexpected rc %d: %s" % (proc.returncode, row["detail"])
row["ms"] = _elapsed_ms(started)
return row
+14 -7
View File
@@ -191,6 +191,9 @@ FLAG_PROBES = {
"queue_index.py": ("--write",
["--repo", "{tinyrepo}", "--queue", "{queue}",
"--write", "{flagtarget}"]),
"selftest_sweep.py": ("--write-baseline",
["--repo", "{tinyrepo}", "--write-baseline",
"{flagtarget}"]),
"tool_map.py": ("--write",
["--repo", "{tinyrepo}", "--write", "{flagtarget}"]),
}
@@ -489,25 +492,29 @@ def selftest(repo):
"covered=%s/%s uncovered=%s/%s outside-class=%s/%s"
% (probe_ok, faults_ok, probe_un, faults_un, probe_no, faults_no))
# c13 is the integration cell: this repo's three caller-path write flags are
# probed by the same code path main() uses, over the same fixtures.
# c13 is the integration cell: every caller-path write flag this repo's
# table names is probed by the same code path main() uses, over the same
# fixtures. The roster is READ FROM FLAG_PROBES, not listed here: a cell
# with its own hardcoded three would keep passing while the table grew,
# which is the same blind spot the UNAXED rule closes one level down.
real_rows = []
with tempfile.TemporaryDirectory(prefix="write-selftest-flag-") as tdf:
fxf = build_fixtures(tdf, repo)
for nm in ("doc_census_check.py", "queue_index.py", "tool_map.py"):
for nm in sorted(FLAG_PROBES):
pf = os.path.join(repo, "tools", nm)
try:
with open(pf, encoding="utf-8") as fh:
s = fh.read()
except OSError as exc:
cell("c13 this repo's three caller-path write flags probe OK", False,
"unreadable %s: %s" % (pf, exc))
cell("c13 every caller-path write flag in the table probes OK",
False, "unreadable %s: %s" % (pf, exc))
real_rows = None
break
real_rows.extend(probe_flags(nm, s, pf, fxf, 300, fxf["tinyrepo"]))
if real_rows is not None:
cell("c13 this repo's three caller-path write flags probe OK",
len(real_rows) == 3 and all(r["verdict"] == "OK" for r in real_rows),
cell("c13 every caller-path write flag in the table probes OK",
len(real_rows) == len(FLAG_PROBES)
and all(r["verdict"] == "OK" for r in real_rows),
str([(r["tool"], r["flag"], r["verdict"]) for r in real_rows]))
# c14/c15 are the blind spot the axis exists for, measured on a fixture tool