From ecec64b95bf617e23f98a5a4e7d6975c6e37cf70 Mon Sep 17 00:00:00 2001 From: volt Date: Thu, 29 Oct 2026 13:12:51 +0000 Subject: [PATCH] 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. --- wizard-work/spark/CHECK-env-verifiers | 77 ++++++++++++++++++++----- wizard-work/spark/test_env_verifiers.py | 53 ++++++++++++++++- 2 files changed, 113 insertions(+), 17 deletions(-) diff --git a/wizard-work/spark/CHECK-env-verifiers b/wizard-work/spark/CHECK-env-verifiers index 1684ff4..291f8d9 100755 --- a/wizard-work/spark/CHECK-env-verifiers +++ b/wizard-work/spark/CHECK-env-verifiers @@ -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 diff --git a/wizard-work/spark/test_env_verifiers.py b/wizard-work/spark/test_env_verifiers.py index c4ba68f..d719844 100755 --- a/wizard-work/spark/test_env_verifiers.py +++ b/wizard-work/spark/test_env_verifiers.py @@ -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")