volt: repair the Q109 cell's false MISSING under a symlinked TMPDIR
test_shell_lone_copy_reds_on_its_sibling asserted the fixture path it had just built while verify_hermes_setup.sh reports the path it resolved with readlink -f. Under TMPDIR=/root/.hermes/profiles/volt/cache/scratch_link a correct pair read MISSING and the gate went rc 1 (measured before the repair: that cell was the only red, 15 others ok). The fixture root is now canonicalised once in setUp with os.path.realpath; two new cells pin the alias reading instead of assuming it -- a lone copy reached by a directory symlink names the real sibling that is absent (rc 1), and the same alias with the sibling present reads PASS (rc 0). CHECK-env-verifiers now runs the suite twice, ambient TMPDIR and a directory alias it builds, so the shape that produced the flake is graded every run. 16 cells; negative control (raw mkdtemp restored in a scratch copy) reds the alias leg and only that leg, rc 1.
This commit is contained in:
1 parent
3a107d8e33
commit
ecec64b95b
2 files changed
+113
-17
No files matched your search
@@ -1,34 +1,79 @@
|
||||
#!/bin/bash
|
||||
# CHECK-env-verifiers: grade the lane's two environment verifiers.
|
||||
#
|
||||
# Q109. The lane's own CHECK grades artifacts under an absolute /root path and
|
||||
# Q109. The lane's own CHECK grades artifacts under an absolute home path and
|
||||
# runs none of the lane's test_*.py (that blindness is a separate item), so this
|
||||
# file gives these two verifiers a gate of their own. The cell
|
||||
# (test_env_verifiers.py) invokes both verifiers as subprocesses with stub
|
||||
# modules on PYTHONPATH and synthetic Hermes trees, so it grades the tree it
|
||||
# sits in -- the paths are resolved from the cell's own location.
|
||||
#
|
||||
# 2026-10-29 repair. The lone-copy cell asserted the path it had built
|
||||
# (self.tmp/lone/snippet.py) while verify_hermes_setup.sh reports the path it
|
||||
# resolved with `readlink -f`. On any host whose TMPDIR is reached through a
|
||||
# symlink those two strings differ, and a correct pair read a false MISSING --
|
||||
# the gate went rc 1 on green work. The suite now canonicalises its fixture root
|
||||
# with os.path.realpath and pins the alias case with two cells of its own; this
|
||||
# gate runs the suite TWICE, under the ambient TMPDIR and under a directory
|
||||
# alias it builds, so the host shape that produced the flake is graded on every
|
||||
# run instead of remembered.
|
||||
#
|
||||
# Exit codes follow the repo's tools/ contract:
|
||||
# 0 = both verifiers measure what they claim
|
||||
# 0 = both verifiers measure what they claim, on both TMPDIR shapes
|
||||
# 1 = a verifier regression (a cell failed)
|
||||
# 2 = could not grade (no python3, or the cell does not import/collect)
|
||||
set -e
|
||||
set -o pipefail
|
||||
cd "$(dirname "$(readlink -f "$0")")"
|
||||
# 2 = could not grade (no python3, no fixture, or the cell will not collect)
|
||||
set -u
|
||||
|
||||
cd "$(dirname "$(readlink -f "$0")")" || {
|
||||
echo "CHECK: cannot cd to the cell's own directory -- cannot grade." >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
echo "CHECK: python3 not on PATH -- cannot grade." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
set +e
|
||||
python3 -m unittest -q test_env_verifiers >/tmp/.q109-check.out 2>&1
|
||||
rc=$?
|
||||
set -e
|
||||
tail -3 /tmp/.q109-check.out
|
||||
tmpbase=${TMPDIR:-/tmp}
|
||||
real_root=$(mktemp -d "$tmpbase/q109-alias-XXXXXX") || {
|
||||
echo "CHECK: mktemp failed -- cannot build the alias leg." >&2
|
||||
exit 2
|
||||
}
|
||||
alias_root="$real_root.alias"
|
||||
if ! ln -s "$real_root" "$alias_root"; then
|
||||
rmdir "$real_root" 2>/dev/null || true
|
||||
echo "CHECK: could not build the alias leg." >&2
|
||||
exit 2
|
||||
fi
|
||||
out=$(mktemp "$tmpbase/q109-out-XXXXXX") || {
|
||||
rm -f "$alias_root"
|
||||
rmdir "$real_root" 2>/dev/null || true
|
||||
echo "CHECK: mktemp failed -- cannot capture the cell's output." >&2
|
||||
exit 2
|
||||
}
|
||||
|
||||
case $rc in
|
||||
0) echo "CHECK: both environment verifiers measure what they claim."; exit 0 ;;
|
||||
1) echo "CHECK: verifier contract broken -- a cell failed." >&2; exit 1 ;;
|
||||
*) echo "CHECK: unittest exited $rc -- collection error, could not grade." >&2; exit 2 ;;
|
||||
esac
|
||||
fault=0
|
||||
ungradable=0
|
||||
for leg_tmp in "$tmpbase" "$alias_root"; do
|
||||
TMPDIR=$leg_tmp python3 -m unittest -q test_env_verifiers >"$out" 2>&1
|
||||
leg_rc=$?
|
||||
case $leg_rc in
|
||||
0) echo "leg TMPDIR=$leg_tmp -> rc 0" ;;
|
||||
1) fault=1; echo "leg TMPDIR=$leg_tmp -> rc 1" >&2; tail -n 12 "$out" >&2 ;;
|
||||
*) ungradable=1; echo "leg TMPDIR=$leg_tmp -> rc $leg_rc" >&2; tail -n 12 "$out" >&2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
rm -f "$alias_root" "$out"
|
||||
rmdir "$real_root" 2>/dev/null || true
|
||||
|
||||
if [ "$ungradable" -ne 0 ]; then
|
||||
echo "CHECK: unittest exited non-zero and non-one -- collection error, could not grade." >&2
|
||||
exit 2
|
||||
fi
|
||||
if [ "$fault" -ne 0 ]; then
|
||||
echo "CHECK: verifier contract broken -- a cell failed." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "CHECK: both environment verifiers measure what they claim (plain and symlinked TMPDIR)."
|
||||
exit 0
|
||||
@@ -16,6 +16,16 @@ and non-callable -- and the directory check is graded against synthetic trees
|
||||
built here, so a green reading is a statement about the arguments and not about
|
||||
this host.
|
||||
|
||||
Two cells grade the alias case, and they exist because this file was the thing
|
||||
that broke, not the code under it. The first version of the lone-copy cell
|
||||
compared the script's reported self-location (which it resolves with
|
||||
`readlink -f`) against the fixture path this cell had just built. Under a TMPDIR
|
||||
reached through a symlink those differ and the cell read a false MISSING on a
|
||||
correct pair -- the gate's only red that day. The fixture root is now
|
||||
canonicalised once in setUp, and `test_shell_lone_copy_behind_a_symlinked_dir`
|
||||
and `test_shell_pair_behind_a_symlinked_dir_is_green` pin the reading the script
|
||||
must give when it is reached by an alias.
|
||||
|
||||
Run: python3 test_env_verifiers.py (or: python3 -m unittest -q ...)
|
||||
"""
|
||||
|
||||
@@ -46,7 +56,15 @@ def stub_source(names):
|
||||
|
||||
class EnvVerifiers(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp = Path(tempfile.mkdtemp(prefix="q109-cell-", dir=tempfile.gettempdir()))
|
||||
# realpath, not the raw mkdtemp: this process may itself be running under
|
||||
# a TMPDIR whose path goes through a symlink (macOS /var -> /private/var,
|
||||
# a linked cache dir), and `verify_hermes_setup.sh` resolves its own
|
||||
# self-location with `readlink -f`. Comparing its resolved path against a
|
||||
# fixture path that still carries the alias reads a false MISSING -- the
|
||||
# flake that reds `test_shell_lone_copy_reds_on_its_sibling` on a host
|
||||
# where /tmp is not canonical. One canonical root for every fixture.
|
||||
self.tmp = Path(os.path.realpath(
|
||||
tempfile.mkdtemp(prefix="q109-cell-", dir=tempfile.gettempdir())))
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tmp, ignore_errors=True)
|
||||
@@ -201,6 +219,39 @@ class EnvVerifiers(unittest.TestCase):
|
||||
self.assertEqual(result.returncode, 1, result.stdout)
|
||||
self.assertIn("MISSING: %s" % (lone / "snippet.py"), result.stdout)
|
||||
|
||||
def test_shell_lone_copy_behind_a_symlinked_dir(self):
|
||||
"""Reached by an alias, a lone copy still names the sibling that is not there.
|
||||
|
||||
The alias is a directory symlink the cell builds, so this is not a
|
||||
statement about /tmp on this host: whatever path the script was invoked
|
||||
by, the path it reports must be the ones the kernel would resolve -- the
|
||||
real directory, where the sibling genuinely is absent.
|
||||
"""
|
||||
real = self.tmp / "real-lone"
|
||||
real.mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(SHELL, real / SHELL.name)
|
||||
alias = self.tmp / "alias-lone"
|
||||
alias.symlink_to(real, target_is_directory=True)
|
||||
root, home = self.make_tree("shell-alias-lone")
|
||||
result = self.run_shell(alias / SHELL.name, "--home", home)
|
||||
self.assertEqual(result.returncode, 1, result.stdout)
|
||||
self.assertIn("script dir: %s" % real, result.stdout)
|
||||
self.assertIn("MISSING: %s" % (real / "snippet.py"), result.stdout)
|
||||
self.assertTrue(os.path.exists(alias / SHELL.name))
|
||||
self.assertFalse(os.path.exists(real / "snippet.py"))
|
||||
|
||||
def test_shell_pair_behind_a_symlinked_dir_is_green(self):
|
||||
"""The same alias with the sibling present: the reading follows the file, not the name."""
|
||||
real = self.copy_pair("real-pair")
|
||||
alias = self.tmp / "alias-pair"
|
||||
alias.symlink_to(real, target_is_directory=True)
|
||||
root, home = self.make_tree("shell-alias-green")
|
||||
result = self.run_shell(alias / SHELL.name, "--home", home)
|
||||
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
|
||||
self.assertIn("script dir: %s" % real, result.stdout)
|
||||
self.assertIn("ok: %s" % (real / SNIPPET.name), result.stdout)
|
||||
self.assertIn("VERDICT: PASS", result.stdout)
|
||||
|
||||
def test_shell_same_verdict_from_outside_copy(self):
|
||||
"""In place and outside the repo, on the same inputs: the same reading."""
|
||||
root, home = self.make_tree("shell-same")
|
||||
|
||||
Reference in new issue
Block a user