R-426: decoys for the shared reuse-refs, instructions and observations gates
COVERS "reuse-refs", "instructions", "observations": the three shared felhom.eu scripts run against a scratch clone of THIS repo (in a scratch workspace symlinking the sibling clones they reach across to), so the plant is in the agent's own REUSE.md / CLAUDE.md / REPORT.md. Convicted: a missing cited .go and .md path, a version literal in CLAUDE.md's effective text, R-419's prose-only Observations note. Passed: the real files, the version inside an HTML comment, both genuine markers. DECOY_SHARED_DIR lets a red-proof judge a mutated copy of the shared scripts without editing the felhom.eu clone. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -42,6 +42,9 @@ import threading
|
||||
|
||||
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
PARENT = os.path.dirname(ROOT)
|
||||
# DECOY_SHARED_DIR exists for ONE purpose: the red-proof. It lets a mutated COPY of the shared scripts
|
||||
# be judged without editing the felhom.eu clone. Unset, the suite judges the real shared scripts.
|
||||
SHARED = os.environ.get("DECOY_SHARED_DIR") or os.path.join(PARENT, "felhom.eu", "scripts")
|
||||
|
||||
# ── WHAT THIS FILE COVERS ────────────────────────────────────────────────────────────────────────
|
||||
# Read by felhom.eu/scripts/decoy_coverage_gate.py, which AST-parses this literal. A gate named here
|
||||
@@ -57,6 +60,12 @@ COVERS = {
|
||||
"heading above it, a newer version named only in prose or under `###`, a tag that only "
|
||||
"origin has (the shallow-CI shape); a LOCAL-only tag passes BY DESIGN (CI's fresh clone "
|
||||
"and the published gate's converse probe are what see it) (R-426)",
|
||||
"reuse-refs": "a cited .go and a cited .md path that do not exist, planted in THIS repo's REUSE.md - vs the "
|
||||
"real file (R-426)",
|
||||
"instructions": "a component version literal in THIS repo's CLAUDE.md effective text - vs the same sentence "
|
||||
"inside an HTML comment (R-426)",
|
||||
"observations": "R-419 in THIS repo's REPORT.md: an Observations note SAYING it carries no marker - vs the "
|
||||
"two genuine markers (R-426)",
|
||||
}
|
||||
|
||||
fails = []
|
||||
@@ -278,6 +287,59 @@ def release_cases(base, ws):
|
||||
pkg_status=500)
|
||||
|
||||
|
||||
# ── the shared felhom.eu scripts, against THIS repo's inputs ─────────────────────────────────────
|
||||
def shared_cases(ws):
|
||||
"""A scratch WORKSPACE: a clone of this repo beside symlinks to the siblings, because the shared
|
||||
scripts reach across (REUSE.md cites hub paths; instructions_gate reads the workspace CLAUDE.md)."""
|
||||
for g in ("reuse_refs_check.py", "instructions_gate.py", "observations_gate.py"):
|
||||
if not os.path.isfile(os.path.join(SHARED, g)):
|
||||
fails.append("shared gate %s is MISSING beside this clone (tried %s) - a failure, never a skip"
|
||||
% (g, SHARED))
|
||||
return
|
||||
space = os.path.join(ws, "workspace")
|
||||
os.makedirs(space)
|
||||
for entry in sorted(os.listdir(PARENT)):
|
||||
if entry in ("felhom.eu", "felhom-controller", "app-catalog-felhom.eu", "homelab-manifests",
|
||||
"CLAUDE.md", ".claude-memory"):
|
||||
os.symlink(os.path.join(PARENT, entry), os.path.join(space, entry))
|
||||
repo = os.path.join(space, "felhom-agent")
|
||||
sh(["git", "clone", "-q", "--no-tags", "file://" + ROOT, repo], ws)
|
||||
# the WORKING-TREE inputs the plants go into, so a case judges today's file
|
||||
for f in ("REUSE.md", "CLAUDE.md", "REPORT.md"):
|
||||
shutil.copy(os.path.join(ROOT, f), os.path.join(repo, f))
|
||||
|
||||
def case(name, gate, relpath, extra, expect_rc, must=()):
|
||||
p = os.path.join(repo, relpath)
|
||||
backup = io.open(p, encoding="utf-8").read()
|
||||
try:
|
||||
if extra:
|
||||
io.open(p, "w", encoding="utf-8").write(backup + extra)
|
||||
rc, out = run([sys.executable, os.path.join(SHARED, gate), repo], repo)
|
||||
report(name, rc, out, expect_rc, must)
|
||||
finally:
|
||||
io.open(p, "w", encoding="utf-8").write(backup)
|
||||
|
||||
case("reuse-refs: GENUINE: this repo's REUSE.md", "reuse_refs_check.py", "REUSE.md", "", 0, ("FAILED 0",))
|
||||
case("reuse-refs: FACT: a cited .go path that does not exist", "reuse_refs_check.py", "REUSE.md",
|
||||
u"\n- see `internal/localapi/does_not_exist.go`\n", 1, ("does_not_exist.go",))
|
||||
case("reuse-refs: FACT: a cited .md path that does not exist", "reuse_refs_check.py", "REUSE.md",
|
||||
u"\n- see `docs/99-does-not-exist.md`\n", 1, ("99-does-not-exist.md",))
|
||||
case("instructions: GENUINE: this repo's CLAUDE.md", "instructions_gate.py", "CLAUDE.md", "", 0,
|
||||
("instructions_gate: OK",))
|
||||
case("instructions: FACT: a version literal in effective text", "instructions_gate.py", "CLAUDE.md",
|
||||
u"\nThe agent runs v0.148.0 today.\n", 1, ("v0.148.0",))
|
||||
case("instructions: GENUINE: the same sentence in an HTML comment", "instructions_gate.py", "CLAUDE.md",
|
||||
u"\n<!--\nThe agent ran v0.148.0 on 2026-10-06.\n-->\n", 0, ("instructions_gate: OK",))
|
||||
case("observations: FACT: R-419, prose SAYING it has no marker", "observations_gate.py", "REPORT.md",
|
||||
u"\n## Observations\n\n1. **A real finding.** It carries no `FILED:` marker and no "
|
||||
u"`NOT-A-FINDING:` marker, deliberately.\n", 1)
|
||||
case("observations: GENUINE: a FILED marker", "observations_gate.py", "REPORT.md",
|
||||
u"\n## Observations\n\n1. **A real finding.** Something broke. **FILED: R-419**\n", 0)
|
||||
case("observations: GENUINE: a NOT-A-FINDING marker", "observations_gate.py", "REPORT.md",
|
||||
u"\n## Observations\n\n1. **A real finding.** Odd. **NOT-A-FINDING: my own typo, corrected in "
|
||||
u"the same minute.**\n", 0)
|
||||
|
||||
|
||||
def main():
|
||||
srv = Server(("127.0.0.1", 0), Handler)
|
||||
threading.Thread(target=srv.serve_forever, daemon=True).start()
|
||||
@@ -287,6 +349,7 @@ def main():
|
||||
try:
|
||||
published_cases(base)
|
||||
release_cases(base, ws)
|
||||
shared_cases(ws)
|
||||
finally:
|
||||
srv.shutdown()
|
||||
srv.server_close()
|
||||
|
||||
Reference in New Issue
Block a user