@@ -692,22 +692,83 @@ def test_g9_loop_package_imports_only_delegation_among_siblings():
|
|||||||
assert not offenders, offenders
|
assert not offenders, offenders
|
||||||
|
|
||||||
|
|
||||||
|
# The G9 guard reads CODE, not prose. Its claim is that no frozen lib.sh
|
||||||
|
# helper is *invoked* from lib_py/loop; a comment or docstring that names
|
||||||
|
# lib.sh (say, to point at the shell twin of a function so the two stay in
|
||||||
|
# sync) invokes nothing. Every way Python could actually reach a lib.sh helper
|
||||||
|
# - a path or `source` inside a subprocess argv, an identifier - lives in code
|
||||||
|
# text, which is still scanned in full, so the guard loses none of its reach.
|
||||||
|
# History: it first fired on `hashlib.sha256` (a word boundary fixed that),
|
||||||
|
# then on a docstring cross-reference in watcher.py; both were mentions.
|
||||||
|
_G9_PATTERNS = {
|
||||||
|
"ensure_subscriber_daemon": r"ensure_subscriber_daemon",
|
||||||
|
"preexec_fn": r"preexec_fn",
|
||||||
|
"lib.sh": r"\blib\.sh\b", # word boundary: `hashlib.sha256` is not lib.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _code_only(src):
|
||||||
|
"""`src` with comments and docstrings blanked, line structure kept."""
|
||||||
|
import ast
|
||||||
|
import io
|
||||||
|
import tokenize
|
||||||
|
|
||||||
|
lines = src.splitlines(True)
|
||||||
|
blank = set()
|
||||||
|
tree = ast.parse(src)
|
||||||
|
for node in ast.walk(tree):
|
||||||
|
if isinstance(node, (ast.Module, ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef)):
|
||||||
|
body = getattr(node, "body", None) or []
|
||||||
|
first = body[0] if body else None
|
||||||
|
if (isinstance(first, ast.Expr) and isinstance(first.value, ast.Constant)
|
||||||
|
and isinstance(first.value.value, str)):
|
||||||
|
blank.update(range(first.lineno, first.end_lineno + 1))
|
||||||
|
out = []
|
||||||
|
for tok in tokenize.generate_tokens(io.StringIO(src).readline):
|
||||||
|
if tok.type == tokenize.COMMENT:
|
||||||
|
(r, c), (_, c2) = tok.start, tok.end
|
||||||
|
lines[r - 1] = lines[r - 1][:c] + " " * (c2 - c) + lines[r - 1][c2:]
|
||||||
|
for i, line in enumerate(lines, 1):
|
||||||
|
out.append("\n" if i in blank else line)
|
||||||
|
return "".join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def _g9_offenders(src):
|
||||||
|
import re
|
||||||
|
code = _code_only(src)
|
||||||
|
return [name for name, pat in _G9_PATTERNS.items() if re.search(pat, code)]
|
||||||
|
|
||||||
|
|
||||||
def test_g9_phase2a_spawns_no_daemon_and_calls_no_frozen_helper():
|
def test_g9_phase2a_spawns_no_daemon_and_calls_no_frozen_helper():
|
||||||
"""The two phase 1 handoffs stay dormant: preexec_fn is unreachable because
|
"""The two phase 1 handoffs stay dormant: preexec_fn is unreachable because
|
||||||
nothing here spawns, and no frozen lib.sh helper is invoked."""
|
nothing here spawns, and no frozen lib.sh helper is invoked."""
|
||||||
import re
|
|
||||||
|
|
||||||
# `lib.sh` needs a word boundary: a bare substring search also matches
|
|
||||||
# hashlib.sha256, which is how this guard first fired on innocent code.
|
|
||||||
patterns = {
|
|
||||||
"ensure_subscriber_daemon": re.compile(r"ensure_subscriber_daemon"),
|
|
||||||
"preexec_fn": re.compile(r"preexec_fn"),
|
|
||||||
"lib.sh": re.compile(r"\blib\.sh\b"),
|
|
||||||
}
|
|
||||||
for path in sorted((SKILLS / "lib_py" / "loop").glob("*.py")):
|
for path in sorted((SKILLS / "lib_py" / "loop").glob("*.py")):
|
||||||
src = path.read_text(encoding="utf-8")
|
src = path.read_text(encoding="utf-8")
|
||||||
for name, pattern in patterns.items():
|
hits = _g9_offenders(src)
|
||||||
assert not pattern.search(src), "{} references {}".format(path.name, name)
|
assert not hits, "{} references {}".format(path.name, ", ".join(hits))
|
||||||
|
|
||||||
|
|
||||||
|
def test_g9b_the_guard_still_catches_an_invocation_and_ignores_prose():
|
||||||
|
"""The narrowing must not cost the guard its purpose: an invocation-shaped
|
||||||
|
reference in code text still trips it; the same words in a docstring or a
|
||||||
|
comment do not."""
|
||||||
|
invoked = (
|
||||||
|
'import subprocess\n'
|
||||||
|
'def go():\n'
|
||||||
|
' return subprocess.run(["bash", "-c", "source .agents/skills/lib.sh; ensure_subscriber_daemon x"])\n'
|
||||||
|
)
|
||||||
|
assert set(_g9_offenders(invoked)) == {"lib.sh", "ensure_subscriber_daemon"}
|
||||||
|
path_only = 'CMD = ["bash", "/x/.agents/skills/lib.sh"]\n'
|
||||||
|
assert _g9_offenders(path_only) == ["lib.sh"]
|
||||||
|
prose = (
|
||||||
|
'"""Module doc: same convention as lib.sh\'s _herdr_caller_server."""\n'
|
||||||
|
'import hashlib\n'
|
||||||
|
'def f():\n'
|
||||||
|
' """See lib.sh; never call ensure_subscriber_daemon from here."""\n'
|
||||||
|
' # preexec_fn is documented in lib.sh\n'
|
||||||
|
' return hashlib.sha256(b"x").hexdigest()\n'
|
||||||
|
)
|
||||||
|
assert _g9_offenders(prose) == []
|
||||||
|
|
||||||
|
|
||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|||||||
Reference in new issue
Block a user