tool_map: the drift guard graded a revision, so the pre-commit tree was ungraded; --rev WORKTREE derives the map from the files git would commit
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 wasea8fe24and 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 at190d1aa: 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 at4602bd5. 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.
This commit is contained in:
1 parent
190d1aae05
commit
214c200bb2
3 files changed
+132
-28
No files matched your search
@@ -10536,3 +10536,19 @@ Verification, read at `6cd2114` (the revision this record was written against; a
|
||||
7. **What it does not claim.** The reply-count guard is sentinel's artifact outside this repo and still hardcodes `249` against an archive of 257 — I did not edit another lane's file, and it was red before this tick, independent of the restore; it stays red until its snapshot advances, which is the point of point 2. The restored reply is byte-identical to `bf1b792`'s blob, but beam's commits were not re-verified this tick — restoration is not re-verification. `TARGET` closes a red only where the row's own citation holds, and the census still runs over a corpus of 499 files, not the archive's prose. No Q-item state changed, and nothing here decides anything Alexander holds.
|
||||
|
||||
— Volt
|
||||
|
||||
**Pre-commit guard 2026-10-21 (volt, Workhorse) — the map's drift guard graded a revision, so the ten minutes before a commit were ungraded: `--rev WORKTREE` derives the map from the files git would commit, and it was measured separating the two trees on a real worktree, not only on a fixture.** No item opened or closed; the open set is as the previous record left it (`Q37`'s pipe span, the career-lane `Q53` decision held for Alexander, `Q64`'s design question Alexander's). Appended at the foot; `docs/queue-index.md` re-rendered in the same commit.
|
||||
|
||||
1. **The blind spot, measured at `4602bd5` from inside a detached worktree.** That commit's message states "TOOLS.md re-rendered, byte-identical"; the map it ships is not the render of its own tree. `python3 tools/tool_map.py --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 whose document was not re-rendered. `--repo . --selftest` reads **15/16, rc 1**, the failure being the currency cell. Before the commit existed, the same commands on the pre-commit worktree (`HEAD` = `ea8fe24`, the edit only on disk) read **rc 0** and **16/16**: the guard was working, and it was guarding the last commit instead of the one about to be made.
|
||||
|
||||
2. **Why the gate stayed green, and the claim that did not survive re-measurement.** `selftest_sweep.py --repo .` at `4602bd5` reads **21 tools, 21 OK, 0 fatal**, measured today. `selftest_sweep.py:449` runs each tool as `[python, path, "--selftest"]` with **no `--repo`**, and `tool_map.py`'s `DEFAULT_REPO` is an absolute path, so its selftest graded `/root/troupe-standup` — the clean clone — from inside the drifted worktree. The first draft of this tick's docstring claimed the sweep leg went fatal at 17:28:26Z and stayed fatal for two hours; that reading did not reproduce, and the sentence was **deleted and replaced by the measurement above**, not softened. The sweep's wrong-tree axis is a second defect and is **not fixed here**.
|
||||
|
||||
3. **What landed** in `tools/tool_map.py`: 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) and leaves `HEAD` on `git ls-tree`; `main()` skips `rev-parse --verify` only for the sentinel; `graderc()` passes a rev so the new cells exercise the parser. Four cells were added: a clean worktree renders exactly what `HEAD` renders; the map reads the file on disk, not the blob at `HEAD`; 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 cells, 20/20 rc 0.**
|
||||
|
||||
4. **Measured outside the fixture, on a second worktree.** A clean detached worktree at `190d1aa`: `--check` **rc 0**, `--rev WORKTREE --check` **rc 0**, both against the same document. With one line appended to `verify.py`'s `write-axis` description and nothing committed: `--rev HEAD` still **rc 0**, `--rev WORKTREE` **rc 1, `DRIFT at line 49`**. Transcript: `/root/.hermes/wizard-outputs/volt/2026-10-21-worktree-mode/measure.txt`.
|
||||
|
||||
5. **Verification at the commit carrying this record.** `tool_map.py --selftest` **20/20 rc 0**; `--repo . --check docs/TOOLS.md` **rc 0**; `--repo . --rev WORKTREE --check docs/TOOLS.md` **rc 0** (no derived cell moved, so the document is unchanged); `verify.py --repo .` **6 legs, 6 pass, 0 fault, 0 ungradable, 0 skipped**; `doc_command_check.py --repo . --fail` **65 commands over 19 oracles, OK 65** (one more command than the previous tick: this record's usage line); `doc_census_check.py --repo . --tools tools/tool_map.py --fail` **0 INTERNAL SPLIT, 0 STALE**.
|
||||
|
||||
6. **What it does not claim.** `WORKTREE` is a literal name, so a branch of that name is shadowed by the sentinel. The mode grades tracked files: a tool that has not been `git add`ed is not a row — the same blind spot one step earlier, and why the usage line says "as it will be committed". The currency cell stays `HEAD`-scoped by design. The sweep's missing `--repo` is recorded, not repaired: another lane's instrument, and a fix there needs its own red-first evidence. No Q-item state changed, and nothing here decides anything Alexander holds.
|
||||
|
||||
— Volt
|
||||
+11
-11
@@ -56,7 +56,7 @@
|
||||
| 46 | Q44 | 6162-6705 | 88496 | opening | The pin class: redirect every constant composed from the live data root, not only `SNAPSHOT_PATH` *(Helm lane; opened 2026-10-12 by the pipe, per Q43's own closing sentence — "extend the redirect … | DONE 2026-10-12 — `recoveries/helm-root-redirect.md` (Merlin, Helm lane); the closure block is at the foot |
|
||||
| 47 | Q48 | 6706-6825 | 15123 | opening | The runtime-resolution redirect: close the class Q45's literals cannot see | DONE 2026-10-13 — `recoveries/helm-runtime-redirect.md` (Merlin, Helm lane), scratch tree |
|
||||
| 48 | Q49 | 6826-7593 | 92050 | opening | The runtime-resolved root's live write path: name it, reproduce it, then close it | open and unclaimed. Opened by the pipe 2026-10-13 |
|
||||
| 49 | Q45 | 7594-10538 | 525440 | opening | §9 follow-on — the home-directory channel *(Helm lane; Merlin)* | OPEN — awaiting Alexander's zoom/whole-shop answer; build is the pipe's. |
|
||||
| 49 | Q45 | 7594-10554 | 529776 | opening | §9 follow-on — the home-directory channel *(Helm lane; Merlin)* | OPEN — awaiting Alexander's zoom/whole-shop answer; build is the pipe's. |
|
||||
|
||||
## Ids with no `## ` heading
|
||||
|
||||
@@ -71,9 +71,9 @@ Opened as records inside another section. `line` is the record's own opening lin
|
||||
| Q50 | 6990 | 6990 | 46 | Q49 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q51 | 7106 | 7106 | 37 | Q49 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q52 | 7167 | 7167 | 90 | Q49 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q53 | 7292 | 7246 | 150 | Q49 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q53 | 7292 | 7246 | 151 | Q49 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q63 | 9918 | 9909 | 17 | Q45 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q64 | 10308 | 10308 | 13 | Q45 | BULLET+BOLD | BOLD-LEAD |
|
||||
| Q64 | 10308 | 10308 | 14 | Q45 | BULLET+BOLD | BOLD-LEAD |
|
||||
|
||||
**Not in this document.** Ids the prose corpus names that the queue has never mentioned (`checkins/`, `replies/`, `recoveries/`, `audits/`, `docs/`, the top-level documents; `tools/` excluded). That set moves with the prose, not with the queue, so embedding it here would make `--check` go RED for a reason that has nothing to do with the queue being current. It is reported on demand: `python3 tools/queue_index.py --outside`.
|
||||
|
||||
@@ -218,7 +218,7 @@ The block below is the parse this document renders, byte for byte. `--check` com
|
||||
"form": "BOLD-LEAD",
|
||||
"id": "Q53",
|
||||
"line": 7292,
|
||||
"refs": 150,
|
||||
"refs": 151,
|
||||
"section": "Q49",
|
||||
"shape": "BULLET+BOLD"
|
||||
},
|
||||
@@ -236,7 +236,7 @@ The block below is the parse this document renders, byte for byte. `--check` com
|
||||
"form": "BOLD-LEAD",
|
||||
"id": "Q64",
|
||||
"line": 10308,
|
||||
"refs": 13,
|
||||
"refs": 14,
|
||||
"section": "Q45",
|
||||
"shape": "BULLET+BOLD"
|
||||
}
|
||||
@@ -246,9 +246,9 @@ The block below is the parse this document renders, byte for byte. `--check` com
|
||||
"end_line": 8,
|
||||
"line": 1
|
||||
},
|
||||
"queue_bytes": 1417701,
|
||||
"queue_lines": 10538,
|
||||
"queue_sha256": "630b8b3f6732163d2f722aa0785dbb32217b6026f11d315d3f79b014c000d208",
|
||||
"queue_bytes": 1422037,
|
||||
"queue_lines": 10554,
|
||||
"queue_sha256": "7d367619ac1c9213f714d47c201838df184e7a4fb0c9d0fb88e1ff7bd95a8ab6",
|
||||
"sections": [
|
||||
{
|
||||
"bytes": 3139,
|
||||
@@ -827,11 +827,11 @@ The block below is the parse this document renders, byte for byte. `--check` com
|
||||
"title": "The runtime-resolved root's live write path: name it, reproduce it, then close it"
|
||||
},
|
||||
{
|
||||
"bytes": 525440,
|
||||
"end_line": 10538,
|
||||
"bytes": 529776,
|
||||
"end_line": 10554,
|
||||
"id": "Q45",
|
||||
"line": 7594,
|
||||
"lines": 2945,
|
||||
"lines": 2961,
|
||||
"role": "opening",
|
||||
"role_detail": "",
|
||||
"status": "OPEN \u2014 awaiting Alexander's zoom/whole-shop answer; build is the pipe's.",
|
||||
|
||||
+105
-17
@@ -2,12 +2,12 @@
|
||||
"""tool_map.py -- the instruments get a map, and the map is generated from the tree.
|
||||
|
||||
WHY THIS EXISTS
|
||||
`tools/` holds sixteen scripts and there is no document that says what they
|
||||
are. A reader meets them one at a time -- in a `verify.py` leg, in a queue
|
||||
block, in a reply -- and nothing states the whole set: which tool grades what,
|
||||
which flags each one actually accepts, which of them the two probe axes cover,
|
||||
and which leg of the operator's gate a failure shows up in. The closest thing
|
||||
is `verify.py`'s `LEGS` table, which names five of the sixteen.
|
||||
`tools/` holds one script per instrument and there is no document that says
|
||||
what they are. A reader meets them one at a time -- in a `verify.py` leg, in a
|
||||
queue block, in a reply -- and nothing states the whole set: which tool grades
|
||||
what, which flags each one actually accepts, which of them the two probe axes
|
||||
cover, and which leg of the operator's gate a failure shows up in. The closest
|
||||
thing is `verify.py`'s `LEGS` table, which names six of them.
|
||||
|
||||
A hand-written map would be a fourth notation of the defect this suite keeps
|
||||
grading: prose about the tree, one step from the thing it describes, with no
|
||||
@@ -39,6 +39,42 @@ WHAT IT MEASURES -- one verdict per invocation
|
||||
docstring, flags or probe rows without re-rendering the map turns the sweep
|
||||
RED instead of leaving a stale document that reads as current.
|
||||
|
||||
THE PRE-COMMIT BLIND SPOT, AND THE MODE THAT CLOSES IT
|
||||
Every cell above is derived from a REVISION, not from the working tree:
|
||||
`collect()` reads blobs with `git show <rev>:<path>` and runs `--help` from a
|
||||
copy of that blob. That is right for a document that makes a claim about a
|
||||
commit, and wrong for the ten minutes before a commit exists.
|
||||
|
||||
Measured on this repository, 2026-10-21. `4602bd5` is drifted: its commit
|
||||
message states "TOOLS.md re-rendered, byte-identical" and the map it ships is
|
||||
not the render of its own tree. Two runs, both from inside a worktree checked
|
||||
out at that commit: `--repo . --check docs/TOOLS.md` reads **rc 1, DRIFT at
|
||||
line 49** (the `write-axis` cell, whose description moved in `verify.py`),
|
||||
and `--repo . --selftest` reads **15/16, rc 1**, the one failure being the
|
||||
currency cell below. Before the commit existed both commands read rc 0 and
|
||||
16/16, because the document on disk and the tools at `HEAD` (`ea8fe24`) were
|
||||
still the pre-edit pair -- the edit lived only in the worktree.
|
||||
|
||||
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.
|
||||
|
||||
`--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
|
||||
files will carry. Measured on a clean worktree at `190d1aa`: rc 0, and
|
||||
byte-identical to what HEAD renders; with one uncommitted line appended to
|
||||
`verify.py`'s `write-axis` description, `--rev HEAD` still reads rc 0 and
|
||||
`--rev WORKTREE` reads **rc 1, DRIFT at line 49**. The currency cell stays
|
||||
HEAD-scoped by design: a worktree mid-edit is not a fault, and a sweep that
|
||||
fails while a docstring is being typed teaches nothing. The pre-commit guard
|
||||
is that `--check` is run in WORKTREE mode before the commit; four cells below
|
||||
measure that it separates the two trees and that a clean worktree renders
|
||||
byte-for-byte what HEAD renders, so the mode cannot invent a drift of its own.
|
||||
|
||||
READ-ONLY except for the one path it is told to write. The only process it
|
||||
starts is `<tool> --help`, which does no work by construction; it never runs a
|
||||
documented command, so it cannot write, post, or deploy anything.
|
||||
@@ -52,8 +88,9 @@ EXIT CODES (the tools/ contract)
|
||||
USAGE
|
||||
python3 tool_map.py --repo . --write docs/TOOLS.md # render
|
||||
python3 tool_map.py --repo . --check docs/TOOLS.md # grade drift, rc 1 on drift
|
||||
python3 tool_map.py --repo . --rev WORKTREE --check docs/TOOLS.md # ...as it will be committed
|
||||
python3 tool_map.py --repo . --json out.json
|
||||
python3 tool_map.py --selftest # 16 cells
|
||||
python3 tool_map.py --selftest # 20 cells
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -70,6 +107,10 @@ DEFAULT_REPO = "/root/troupe-standup"
|
||||
DEFAULT_DOC = "docs/TOOLS.md"
|
||||
HELP_TIMEOUT = 30
|
||||
|
||||
# The one value of `--rev` that does not name a revision: the files git would
|
||||
# commit from this worktree (the index lists them, the disk supplies them).
|
||||
WORKTREE = "WORKTREE"
|
||||
|
||||
# A long option, or a short one, as argparse prints them in the usage block.
|
||||
# `-h`/`--help` are dropped: every tool has them, and a column of sixteen
|
||||
# identical pairs is noise, not information.
|
||||
@@ -84,13 +125,29 @@ def git(repo, *args, inp=None):
|
||||
|
||||
|
||||
def read_blob(repo, rev, path):
|
||||
"""The file's text at `rev`; from disk when `rev` is WORKTREE."""
|
||||
if rev == WORKTREE:
|
||||
try:
|
||||
with open(os.path.join(repo, path), encoding="utf-8") as fh:
|
||||
return fh.read()
|
||||
except OSError:
|
||||
return None
|
||||
rc, out, err = git(repo, "show", f"{rev}:{path}")
|
||||
return out if rc == 0 else None
|
||||
|
||||
|
||||
def tracked_tools(repo, rev):
|
||||
"""Sorted `tools/*.py` basenames tracked at `rev`."""
|
||||
rc, out, _ = git(repo, "ls-tree", "-r", "--name-only", rev, "--", "tools/")
|
||||
"""Sorted `tools/*.py` basenames tracked at `rev`.
|
||||
|
||||
WORKTREE is not a revision and has no tree object: the set is the INDEX
|
||||
(`git ls-files`), which is what a commit of tracked files will carry, and
|
||||
the contents come from disk. Reading the index rather than a reflog of the
|
||||
worktree keeps one rule -- "the file git would commit" -- for both halves.
|
||||
"""
|
||||
if rev == WORKTREE:
|
||||
rc, out, _ = git(repo, "ls-files", "--", "tools/")
|
||||
else:
|
||||
rc, out, _ = git(repo, "ls-tree", "-r", "--name-only", rev, "--", "tools/")
|
||||
if rc != 0:
|
||||
return None
|
||||
names = [p.split("/")[-1] for p in out.split("\n")
|
||||
@@ -417,6 +474,34 @@ def selftest(repo):
|
||||
cell("--repo a directory that is not a git work tree: rc 2",
|
||||
rc_norepo == 2, f"rc {rc_norepo}")
|
||||
|
||||
# -- WORKTREE: the tree you are about to commit, not the last commit --
|
||||
# The map is derived from a revision by construction, so a docstring
|
||||
# edited after the last commit is invisible to both `--check` and the
|
||||
# currency cell below. That is measured here, not described: the same
|
||||
# document is current against HEAD and drifted against the worktree.
|
||||
cell("WORKTREE: a clean worktree renders exactly what HEAD renders",
|
||||
render(collect(fixture, WORKTREE)) == text)
|
||||
fake = os.path.join(fixture, "tools", "fake_tool.py")
|
||||
with open(fake, encoding="utf-8") as fh:
|
||||
src = fh.read()
|
||||
with open(fake, "w", encoding="utf-8") as fh:
|
||||
fh.write(src.replace("which nothing measured",
|
||||
"which nothing has measured yet"))
|
||||
wt = collect(fixture, WORKTREE)
|
||||
hd = collect(fixture, "HEAD")
|
||||
purpose_wt = {r["tool"]: r["purpose"] for r in wt["rows"]}["fake_tool.py"]
|
||||
purpose_hd = {r["tool"]: r["purpose"] for r in hd["rows"]}["fake_tool.py"]
|
||||
cell("WORKTREE: reads the file on disk, not the blob at HEAD",
|
||||
purpose_wt != purpose_hd and "has measured yet" in purpose_wt,
|
||||
f"worktree={purpose_wt!r} head={purpose_hd!r}")
|
||||
rc_head = compare(doc, render(hd), quiet=True)
|
||||
rc_wt = compare(doc, render(wt), quiet=True)
|
||||
cell("blind spot: an uncommitted docstring edit is rc 0 at HEAD and rc 1 at WORKTREE",
|
||||
rc_head == 0 and rc_wt == 1, f"HEAD rc {rc_head}, WORKTREE rc {rc_wt}")
|
||||
rc_wt_norepo = graderc(td, rev=WORKTREE)
|
||||
cell("WORKTREE outside a git work tree: rc 2, not a crash",
|
||||
rc_wt_norepo == 2, f"rc {rc_wt_norepo}")
|
||||
|
||||
# -- the currency cell: the reason this document stays true ----------
|
||||
here = os.path.join(repo, "docs", "TOOLS.md")
|
||||
try:
|
||||
@@ -436,11 +521,13 @@ def selftest(repo):
|
||||
return 0 if passed == len(cells) else 1
|
||||
|
||||
|
||||
def graderc(td):
|
||||
def graderc(td, rev=None):
|
||||
"""rc of a full `--check` run against a directory that is not a repo."""
|
||||
proc = subprocess.run([sys.executable, os.path.abspath(__file__),
|
||||
"--repo", td, "--check", os.path.join(td, "x.md")],
|
||||
capture_output=True, text=True)
|
||||
cmd = [sys.executable, os.path.abspath(__file__), "--repo", td]
|
||||
if rev:
|
||||
cmd += ["--rev", rev]
|
||||
cmd += ["--check", os.path.join(td, "x.md")]
|
||||
proc = subprocess.run(cmd, capture_output=True, text=True)
|
||||
return proc.returncode
|
||||
|
||||
|
||||
@@ -488,10 +575,11 @@ def main():
|
||||
if rc != 0:
|
||||
print(f"tool_map: cannot read repo: {args.repo} is not a git work tree")
|
||||
return 2
|
||||
rc, _, err = git(args.repo, "rev-parse", "--verify", f"{args.rev}^{{commit}}")
|
||||
if rc != 0:
|
||||
print(f"tool_map: cannot read rev {args.rev}: {err.strip().splitlines()[0] if err.strip() else 'no such object'}")
|
||||
return 2
|
||||
if args.rev != WORKTREE:
|
||||
rc, _, err = git(args.repo, "rev-parse", "--verify", f"{args.rev}^{{commit}}")
|
||||
if rc != 0:
|
||||
print(f"tool_map: cannot read rev {args.rev}: {err.strip().splitlines()[0] if err.strip() else 'no such object'}")
|
||||
return 2
|
||||
|
||||
data = collect(args.repo, args.rev)
|
||||
text = render(data)
|
||||
|
||||
Reference in new issue
Block a user