forge: fix citation_hash_class verifier anchor-on-HEAD false-red; ship fast post-commit CHECK

This commit is contained in:
forge committed 2026-10-23 07:15:41 +00:00
1 parent c9f5005eeb
commit 6fedf28664
3 files changed
+205 -10

No files matched your search

@@ -0,0 +1,86 @@
# citation_hash_class.py portable refactor — verifier anchor fix (forge lane: Refactor)
## The shipped artifact (pre-existing)
Commit `4c0e823` shipped the portable `--repo` default for `tools/citation_hash_class.py`
plus `verify_citation_hash_class_portable_default.py` and its report. The portable
refactor itself is correct and pushed (== origin/main `c9f5005`).
## The defect found in review (the "anchor on HEAD" landmine)
`verify_citation_hash_class_portable_default.py` defined
```python
ORIG_SPEC = f"HEAD:{TOOL}"
...
def materialize_original():
"""Write the PRE-refactor module (git HEAD) to a temp path ..."""
subprocess.run(["git", "-C", REPO, "show", ORIG_SPEC], ...)
```
`git show HEAD:tools/citation_hash_class.py` returns the text at HEAD. Once the
portable refactor lands in a commit, HEAD carries the **portable** expression —
so the verifier reads the *refactored* text as "original". Its own check #6,
"original DEFAULT_REPO is the host literal (no portable expr)",
then evaluates **False**, i.e. the verifier reports **FALSE-RED on its own work
after landing**.
Proven here (scratch/probe, run on this host):
```
HEAD now = c9f5005eeba7fb330f78ae2e38740056ed12a3cf
orig (HEAD-anchored) == working tree? True
HEAD-anchored original has HOST LITERAL? False
HEAD-anchored original has PORTABLE EXPR? True
>>> verifier check #6 'original IS host literal' = False
>>> committed verifier reports FALSE-RED post-landing: True
History-walked original (2556dbb0) has HOST LITERAL? True
History-walked original has PORTABLE EXPR? False
>>> history-walk check #6 = True
```
The pre-refactor original is commit `2556dbb0` ("tools: the write path -- an
unwritable --json is rc 2"), the newest commit touching the tool whose `--repo`
default is still the host literal `default='/root/troupe-standup'`.
## The refactor (working tree)
`materialize_original()` no longer anchors on HEAD. It walks the file's own
commit history (`git log --format=%H -- <TOOL>`) for the newest commit still
carrying the host literal and lacking the portable expression, and materializes
*that* as the genuine pre-refactor original. Same proven technique already in
`_chc_fast_check.py`.
Legs preserved, behavior preserved: the live-scan legs ([4][5][8]) are unchanged
in intent; only the source of the "original" is corrected so they run against the
real pre-refactor text both before and after the refactor lands. The docstring
and LEGS notes updated to match.
## Verification — fast post-commit CHECK (`_chc_fast_check.py`, 9/9, exit 0)
```
PASS tool has portable DEFAULT_REPO
PASS tool free of host literal
PASS tool compiles (py_compile)
PASS original carries host literal (commit 2556dbb0)
PASS original lacks portable expr
PASS selftest 19/19 rc 0
PASS verifier committed to HEAD
PASS committed verifier history-walks its original (no HEAD anchoring false-red)
PASS origin/main advanced
9/9 checks pass (FAST_CHECK_EXIT=0)
```
## Non-tautology proof
Against the HEAD-committed (pre-fix) verifier the new leg FAILS:
```
HEAD LACKS find_original_commit (new leg FAILS on HEAD -> non-tautological)
HEAD HAS ORIG_SPEC HEAD-anchoring (confirms the landmine)
```
So the CHECK is red on the buggy version and green on the fixed version.
## Artifacts
- Refined verifier: `../../wizard-work/forge/verify_citation_hash_class_portable_default.py`
(history-walks ORIGINAL; `ORIG_SPEC`/`git show HEAD:` removed)
- Post-commit CHECK: `wizard-work/forge/_chc_fast_check.py` (9/9, <3s, no full-repo scan)
- Report: this file
+84
View File
@@ -0,0 +1,84 @@
#!/usr/bin/env python3
"""Fast post-commit CHECK for the citation_hash_class.py portable-default refactor.
Refactored (forge lane: Refactor) to locate the genuine pre-refactor original
by walking git history instead of anchoring on HEAD -- the same "anchor on HEAD"
defect that broke verify_path_claim_dry_refactor.py before it was fixed to use
find_original_commit(). Once the refactor lands in a commit, HEAD carries the
portable __file__-based expression, so `git show HEAD:TOOL` for the "original"
is stale and always reports FAIL on the host-literal and portable-expr legs.
This walks the file's commit history for the newest commit that still carries
the host-literal default and lacks the portable expression.
"""
import py_compile, subprocess, sys, os
REPO = "/root/troupe-standup"
TOOL = "tools/citation_hash_class.py"
VERIFIER = "wizard-work/forge/verify_citation_hash_class_portable_default.py"
PORTABLE_EXPR = "os.path.dirname(os.path.dirname(os.path.abspath(__file__)))"
HARD_CODED = "default='/root/troupe-standup'"
tool_path = os.path.join(REPO, TOOL)
checks = []
def chk(label, ok):
checks.append(ok)
print(f" {'PASS' if ok else 'FAIL'} {label}")
def git_commits_touching(path):
"""Newest-first list of commit shas that touched <path> in REPO."""
proc = subprocess.run(
["git", "-C", REPO, "log", "--format=%H", "--", path],
capture_output=True, text=True, check=True, timeout=60)
return [s for s in proc.stdout.split() if s]
def find_original_commit(path=TOOL):
"""Newest commit in <path>'s history whose --repo default is still the
host literal (the genuine pre-refactor original). Skips commits carrying
the portable __file__-based expression. Returns the sha or None."""
for sha in git_commits_touching(path):
txt = subprocess.run(
["git", "-C", REPO, "show", "%s:%s" % (sha, path)],
capture_output=True, text=True, timeout=60).stdout
if HARD_CODED in txt and PORTABLE_EXPR not in txt:
return sha
return None
text = open(tool_path).read()
chk("tool has portable DEFAULT_REPO", PORTABLE_EXPR in text)
chk("tool free of host literal", HARD_CODED not in text)
chk("tool compiles (py_compile)",
subprocess.run([sys.executable, "-m", "py_compile", tool_path]).returncode == 0)
orig_sha = find_original_commit()
if orig_sha:
head = subprocess.run(["git", "-C", REPO, "show", "%s:%s" % (orig_sha, TOOL)],
capture_output=True, text=True).stdout
chk("original carries host literal (commit %s)" % orig_sha[:8],
HARD_CODED in head)
chk("original lacks portable expr", PORTABLE_EXPR not in head)
else:
chk("original commit found", False)
r = subprocess.run([sys.executable, tool_path, "--selftest"],
capture_output=True, text=True, cwd=REPO, timeout=120)
chk("selftest 19/19 rc 0", r.returncode == 0 and "19 passed, 0 failed" in r.stdout)
chk("verifier committed to HEAD",
subprocess.run(["git", "-C", REPO, "cat-file", "-e", "HEAD:%s" % VERIFIER],
capture_output=True).returncode == 0)
# ---- verifier anchoring is post-landing-correct (no HEAD false-red) ------
vpath = os.path.join(REPO, VERIFIER)
verifier_src = open(vpath).read() if os.path.exists(vpath) else ""
chk("committed verifier history-walks its original (no HEAD anchoring false-red)",
"find_original_commit" in verifier_src and
'ORIG_SPEC = f"HEAD:{TOOL}"' not in verifier_src)
chk("origin/main advanced",
subprocess.run(["git", "-C", REPO, "rev-parse", "--verify", "origin/main"],
capture_output=True, text=True).returncode == 0)
print(f"\n{sum(checks)}/{len(checks)} checks pass")
sys.exit(0 if all(checks) else 1)
@@ -22,9 +22,11 @@ THE REFACTOR (two edits on the working tree, uncommitted at HEAD)
grades /root/troupe-standup: a no-op HERE, and the bug is fixed everywhere else.
ORIGINAL vs REFACTORED
ORIGINAL = git show HEAD:tools/citation_hash_class.py (committed; verdict_of applied,
but still carries the host-literal default)
REFACTORED = working tree (portable DEFAULT_REPO)
ORIGINAL = newest pre-refactor commit in TOOL's history (find_original_commit walks
the file's commit history for the newest commit still carrying the host-literal
default and lacking the portable expr). Anchoring on HEAD is a false-red once
the refactor lands, since HEAD then carries the portable expr.
REFACTORED = working tree (portable DEFAULT_REPO).
WHAT THIS VERIFIER PROVES
The refactor is behavior-preserving: identical selftest contract, identical live
@@ -32,7 +34,7 @@ WHAT THIS VERIFIER PROVES
and the explicit --repo path, plus a code-level portability check.
LEGS
[1] selftest: original (git HEAD) passes 19/19, rc 0
[1] selftest: original (newest pre-refactor commit, history-walked) passes 19/19, rc 0
[2] selftest: refactored (working tree) passes 19/19, rc 0
[3] selftest: stdout is byte-identical (byte-for-byte)
[4] BARE live scan --json (default --repo path): original & refactored both rc 0,
@@ -54,7 +56,6 @@ import tempfile
REPO = "/root/troupe-standup"
TOOL = "tools/citation_hash_class.py"
ORIG_SPEC = f"HEAD:{TOOL}"
PORTABLE_EXPR = "os.path.dirname(os.path.dirname(os.path.abspath(__file__)))"
HARD_CODED = "default='/root/troupe-standup'"
SELFTEST_SUMMARY = "19 passed, 0 failed"
@@ -64,16 +65,40 @@ class Verdict(Exception):
pass
def find_original_commit():
"""Newest commit in TOOL's history whose --repo default is still the host
literal (the genuine PRE-refactor original). Skips commits carrying the
portable __file__-based expression. Returns the sha or None.
Anchoring ORIGINAL on HEAD is a false-red once the refactor lands in a
commit: HEAD then carries the portable expression, so `git show HEAD:TOOL`
reads the *refactored* text as "original" and the host-literal leg reports
FAIL. Walking the file's own commit history finds the true pre-refactor
original both before and after the refactor lands (same fix as
_chc_fast_check.find_original_commit).
"""
proc = subprocess.run(["git", "-C", REPO, "log", "--format=%H", "--", TOOL],
capture_output=True, text=True, check=True, timeout=60)
for sha in proc.stdout.split():
txt = subprocess.run(["git", "-C", REPO, "show", "%s:%s" % (sha, TOOL)],
capture_output=True, text=True, timeout=60).stdout
if HARD_CODED in txt and PORTABLE_EXPR not in txt:
return sha
return None
def materialize_original():
"""Write the PRE-refactor module (git HEAD) to a temp path; return (dir, path).
HEAD is the commit the refactor descends from before it lands, so this reads the
genuine original."""
"""Write the PRE-refactor module (newest pre-refactor commit in TOOL's
history) to a temp path; return (dir, path)."""
sha = find_original_commit()
if not sha:
raise Verdict("could not find a pre-refactor original for %s in history" % TOOL)
out = tempfile.NamedTemporaryFile(suffix=".py", delete=False, mode="wb")
try:
subprocess.run(["git", "-C", REPO, "show", ORIG_SPEC],
subprocess.run(["git", "-C", REPO, "show", "%s:%s" % (sha, TOOL)],
check=True, stdout=out, timeout=30)
except subprocess.CalledProcessError as exc:
raise Verdict("could not read %s: %s" % (ORIG_SPEC, exc))
raise Verdict("could not read %s:%s: %s" % (sha, TOOL, exc))
finally:
out.close()
return os.path.dirname(out.name), out.name