Files
troupe-standup/wizard-work/spark/test_env_verifiers.py
T
volt ebba640548 volt: Q109 -- spark env verifiers measure the import and their own inputs
snippet.py: check_tools() imports hermes_tools and requires callable(getattr(...));
--require is the negative-control hook; HERMES_HOME/HERMES_PROFILE/--home/--profile
resolve every path; rc 0/1/2. verify_hermes_setup.sh: HERE from $0, sibling
snippet.py graded, --home/--root/--profile, VERDICT line, rc 0/1/2.

New test_env_verifiers.py (14 black-box cells, stub hermes_tools on PYTHONPATH,
synthetic trees) and CHECK-env-verifiers. Pre-repair blobs: 9 cells red for
snippet.py, 6 for the shell script.
2026-10-29 13:04:00 +00:00

231 lines
11 KiB
Python
Executable File

#!/usr/bin/env python3
"""Q109 cells: the lane's two environment verifiers, graded as subprocesses.
Both files used to print success without measuring anything --
`wizard-work/spark/snippet.py` filled `available[tool] = True` in a loop over a
hard-coded list (so a bare python3 with no Hermes session read "verified
successfully", rc 0), and `wizard-work/spark/verify_hermes_setup.sh` tested
three absolute paths under a pinned /root and read nothing relative to itself
(so it printed three ticks and "All critical paths verified", rc 0, on any
tree). Those are the two readings these cells kill.
Every cell runs the shipped file by path, resolved from __file__, and imports
nothing from it: no cell can agree with the code by sharing its constants. The
tool check is graded with a stub `hermes_tools` on PYTHONPATH -- full, reduced,
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.
Run: python3 test_env_verifiers.py (or: python3 -m unittest -q ...)
"""
import os
import shutil
import subprocess
import sys
import tempfile
import unittest
from pathlib import Path
LANE = Path(__file__).resolve().parent
SNIPPET = LANE / "snippet.py"
SHELL = LANE / "verify_hermes_setup.sh"
TOOLS = ["web_search", "web_extract", "read_file", "write_file"]
STUB_HEADER = '''"""Stub hermes_tools written by test_env_verifiers.py."""\n'''
def stub_source(names):
"""A stand-in hermes_tools exposing `names` as callables."""
lines = [STUB_HEADER]
for name in names:
lines.append("def %s(*args, **kwargs):\n return None\n" % name)
return "".join(lines)
class EnvVerifiers(unittest.TestCase):
def setUp(self):
self.tmp = Path(tempfile.mkdtemp(prefix="q109-cell-", dir=tempfile.gettempdir()))
def tearDown(self):
shutil.rmtree(self.tmp, ignore_errors=True)
# ---- fixtures -------------------------------------------------------
def make_tree(self, name="tree", scratch=True, home=True):
"""A synthetic Hermes installation: ROOT/profiles/<profile>/cache/scratch."""
root = self.tmp / name
root.mkdir(parents=True, exist_ok=True)
(root / "skills").mkdir(exist_ok=True)
(root / "plugins").mkdir(exist_ok=True)
profile_home = root / "profiles" / "lane"
if home:
profile_home.mkdir(parents=True, exist_ok=True)
if scratch and home:
(profile_home / "cache" / "scratch").mkdir(parents=True, exist_ok=True)
return root, profile_home
def make_stub(self, names, label="stub"):
"""A PYTHONPATH directory holding a hermes_tools stub, or none at all."""
stub_dir = self.tmp / label
stub_dir.mkdir(parents=True, exist_ok=True)
if names is not None:
(stub_dir / "hermes_tools.py").write_text(stub_source(names), encoding="utf-8")
return stub_dir
def env_for(self, stub_dir, **extra):
env = {k: v for k, v in os.environ.items()
if k not in ("HERMES_HOME", "HERMES_ROOT", "HERMES_PROFILE", "PYTHONPATH")}
env["PYTHONPATH"] = str(stub_dir)
env.update(extra)
return env
def run_snippet(self, stub_dir, *args, **extra_env):
return subprocess.run(
[sys.executable, str(SNIPPET)] + [str(a) for a in args],
capture_output=True, text=True, env=self.env_for(stub_dir, **extra_env),
)
def run_shell(self, script, *args, **extra_env):
stub_dir = self.make_stub(None, label="no-stub")
return subprocess.run(
["bash", str(script)] + [str(a) for a in args],
capture_output=True, text=True, env=self.env_for(stub_dir, **extra_env),
)
def lines(self, result, tag):
return [ln[len(tag) + 2:] for ln in result.stdout.splitlines() if ln.startswith(tag + ": ")]
def named(self, result, path):
return any(path in ln for ln in result.stdout.splitlines())
# ---- snippet.py: the tool check measures ----------------------------
def test_snippet_bare_interpreter_reds_on_tools(self):
"""The defect itself: no hermes_tools at all must not read as verified."""
root, home = self.make_tree()
result = self.run_snippet(self.make_stub(None, "empty"), "--home", home)
self.assertEqual(result.returncode, 1, result.stdout)
self.assertIn("TOOLS_IMPORT_FAILED:", result.stdout)
self.assertEqual(self.lines(result, "TOOLS_MISSING"), [str(TOOLS)])
self.assertIn("VERDICT: FAIL", result.stdout)
def test_snippet_full_stub_is_green(self):
"""Positive control: every tool callable on a complete tree reads PASS."""
root, home = self.make_tree("green")
result = self.run_snippet(self.make_stub(TOOLS), "--home", home)
self.assertEqual(result.returncode, 0, result.stdout)
self.assertEqual(self.lines(result, "TOOLS_AVAILABLE"), [str(sorted(TOOLS))])
self.assertEqual(self.lines(result, "TOOLS_MISSING"), ["[]"])
self.assertIn("VERDICT: PASS", result.stdout)
self.assertEqual(result.stderr, "")
def test_snippet_one_tool_missing_reds_and_names_it(self):
"""The negative control the item asks for: one genuinely absent tool."""
root, home = self.make_tree("partial")
stub = self.make_stub([t for t in TOOLS if t != "write_file"], "partial-stub")
result = self.run_snippet(stub, "--home", home)
self.assertEqual(result.returncode, 1, result.stdout)
self.assertEqual(self.lines(result, "TOOLS_MISSING"), ["['write_file']"])
def test_snippet_noncallable_tool_is_unavailable(self):
"""A name that resolves to None is not a tool that works."""
root, home = self.make_tree("noncallable")
stub_dir = self.make_stub(TOOLS, "noncallable-stub")
(stub_dir / "hermes_tools.py").write_text(
stub_source(TOOLS) + "web_extract = None\n", encoding="utf-8")
result = self.run_snippet(stub_dir, "--home", home)
self.assertEqual(result.returncode, 1, result.stdout)
self.assertEqual(self.lines(result, "TOOLS_MISSING"), ["['web_extract']"])
def test_snippet_missing_scratch_dir_reds_and_names_path(self):
root, home = self.make_tree("noscratch", scratch=False)
result = self.run_snippet(self.make_stub(TOOLS), "--home", home)
self.assertEqual(result.returncode, 1, result.stdout)
self.assertTrue(self.named(result, str(home / "cache" / "scratch")), result.stdout)
self.assertIn("DIR MISSING: %s" % (home / "cache" / "scratch"), result.stdout)
def test_snippet_require_absent_tool_reds(self):
root, home = self.make_tree("require")
result = self.run_snippet(self.make_stub(TOOLS), "--home", home,
"--require", "definitely_not_a_tool")
self.assertEqual(result.returncode, 1, result.stdout)
self.assertEqual(self.lines(result, "TOOLS_MISSING"), ["['definitely_not_a_tool']"])
def test_snippet_honours_hermes_home_env(self):
"""Resolution is env-first: HERMES_HOME alone must redirect the reading."""
root, home = self.make_tree("envhome")
result = self.run_snippet(self.make_stub(TOOLS), HERMES_HOME=str(home))
self.assertEqual(result.returncode, 0, result.stdout)
self.assertEqual(self.lines(result, "HERMES_HOME"), [str(home)])
self.assertEqual(self.lines(result, "HERMES_ROOT"), [str(root)])
def test_snippet_usage_error_is_2(self):
root, home = self.make_tree("usage")
result = self.run_snippet(self.make_stub(TOOLS), "--nope")
self.assertEqual(result.returncode, 2, result.stdout + result.stderr)
# ---- verify_hermes_setup.sh: reads its own inputs -------------------
def copy_pair(self, name="copy"):
"""The two files as they ship together, outside the repo."""
target = self.tmp / name
target.mkdir(parents=True, exist_ok=True)
shutil.copy2(SNIPPET, target / SNIPPET.name)
shutil.copy2(SHELL, target / SHELL.name)
return target
def test_shell_complete_tree_is_green(self):
root, home = self.make_tree("shell-green")
script = self.copy_pair() / SHELL.name
result = self.run_shell(script, "--home", home)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
self.assertTrue(self.named(result, str(home)), result.stdout)
self.assertIn("VERDICT: PASS", result.stdout)
def test_shell_missing_profile_home_reds_and_names_path(self):
root, home = self.make_tree("shell-red", home=False)
result = self.run_shell(self.copy_pair("copy-red") / SHELL.name, "--home", home)
self.assertEqual(result.returncode, 1, result.stdout)
self.assertIn("MISSING: %s" % home, result.stdout)
self.assertIn("VERDICT: FAIL (2 required path(s) missing)", result.stdout)
def test_shell_lone_copy_reds_on_its_sibling(self):
"""The self-location leg: a script with no snippet.py beside it has nothing to report."""
lone = self.tmp / "lone"
lone.mkdir(parents=True, exist_ok=True)
shutil.copy2(SHELL, lone / SHELL.name)
root, home = self.make_tree("shell-lone")
result = self.run_shell(lone / SHELL.name, "--home", home)
self.assertEqual(result.returncode, 1, result.stdout)
self.assertIn("MISSING: %s" % (lone / "snippet.py"), 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")
in_place = self.run_shell(SHELL, "--home", home)
outside = self.run_shell(self.copy_pair("copy-same") / SHELL.name, "--home", home)
self.assertEqual(in_place.returncode, outside.returncode)
self.assertEqual(in_place.returncode, 0, in_place.stdout + outside.stdout)
# Every line about the graded tree, not about where the script lives.
about_tree = lambda out: [ln for ln in out.splitlines() if str(root) in ln]
self.assertEqual(about_tree(in_place.stdout), about_tree(outside.stdout))
self.assertIn("VERDICT: PASS", outside.stdout)
def test_shell_usage_error_is_2(self):
result = self.run_shell(SHELL, "--nope")
self.assertEqual(result.returncode, 2, result.stdout + result.stderr)
# ---- the class both files were filed under -------------------------
def test_no_pinned_root_paths_in_either_file(self):
"""Q109's class: neither file may grade a path pinned to this host."""
for path in (SNIPPET, SHELL):
blob = path.read_text(encoding="utf-8")
self.assertNotIn("/root", blob, "%s still pins a /root path" % path.name)
if __name__ == "__main__":
unittest.main(verbosity=2)