From 979ababb8f8f72a272de6a465a4db4c3d080dfb8 Mon Sep 17 00:00:00 2001 From: kisfenyo Date: Tue, 6 Oct 2026 01:40:43 +0200 Subject: [PATCH] R-426: volume-persistence decoys - the injected-prober suite run from here, and a dead runtime end to end test_gate_decoys.py runs test_check_volume_persistence.py (the blind and crying-wolf probers refused rc=3, `wrote nothing` never CLEAN, the papra signature convicted) and requires it green, so COVERS is a fact; and runs the working-tree gate in a scratch catalog with PATH = ONLY a stub docker that fails every call: a runtime that answers nothing, no docker, nothing to judge are each HARNESS REFUSED rc=3, never 0. An always-succeeding stub is deliberately not used - it would walk the prober into the host filesystem. COVERS gains "volume-persistence". Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS --- scripts/test_gate_decoys.py | 71 +++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/scripts/test_gate_decoys.py b/scripts/test_gate_decoys.py index 38fe42f..ff97c79 100644 --- a/scripts/test_gate_decoys.py +++ b/scripts/test_gate_decoys.py @@ -47,6 +47,7 @@ ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # Read by felhom.eu/scripts/decoy_coverage_gate.py, which AST-parses this literal. A gate named here # MUST have a decoy below that has been seen to fail. COVERS = { + "volume-persistence": "the classifier and the self-test via the injected-prober suite scripts/test_check_volume_persistence.py, RUN FROM HERE and required green (a blind prober and a crying-wolf prober are refused rc=3; `wrote nothing`, a container not running, a path token alone, an unresolved suspect are UNDETERMINED or clean, never a false CLEAN/BROKEN; the papra signature convicts); and END TO END with a PATH-STUB docker that fails every call, no docker at all, nothing to judge - each HARNESS REFUSED rc=3, never 0 (R-426)", "image-resolvable": "END TO END through the gate's own `docker manifest inspect` call, with a PATH-STUB docker (PATH holds ONLY the stub, so the real runtime is unreachable): the label of success without the fact - rc=0 carrying a throttle or any error text, a docker that resolves EVERYTHING incl. the .invalid canary, no docker at all, nothing to judge - each INCONCLUSIVE or HARNESS REFUSED, never 0; the cry-wolf direction - a throttle or an unrecognised error on rc=1 is never an accusation; vs a registry that positively says `manifest unknown` (convicted, naming the app) and a clean run (R-426)", "image-pins": "the pin's LABEL without the pin: a registry PORT (`:5000`) read as a tag, `@sha256:` with no digest behind it, a QUOTED `\"image\":` key, an interpolated `${APP_IMAGE:-nginx}`, `:LATEST`/`:latest` in quotes - vs the inert shapes that must pass (a commented `# image: nginx`, an `x-image:` extension field, a README line) and the genuine pins (a tag, a real 64-hex digest, `:latest@sha256:` pinned by its digest, a port with a tag) (R-426)", "engine-major": "the major moved in a comment/env var/README/app image, not on an engine's image: line", @@ -836,6 +837,75 @@ def image_resolvable_cases(): shutil.rmtree(ws, ignore_errors=True) +FAIL_DOCKER = """#!%s +# PATH-stub docker for the volume-persistence decoys: a host whose runtime answers nothing. Every call fails. +import sys +sys.stderr.write("Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?\\n") +sys.exit(1) +""" + + +def volume_persistence_cases(): + """check-volume-persistence.py (R-426). Two halves. + + 1. Its classifier and self-test are pure and already fixture-tested with an INJECTED prober — the blind prober, + the crying-wolf prober, `wrote nothing`, the papra signature. Those ARE decoys; this suite runs that file and + requires it green, so the COVERS line above is a fact and not a label (felhom.eu's guide-quote precedent). + 2. End to end, the working-tree script copied into a scratch catalog and run with PATH = ONLY a stub docker. The + stub FAILS every call, so the gate stops at its canary build and nothing — no compose, no container, no + volume — is ever created; an always-succeeding stub is deliberately NOT used, because it would walk the + prober into the host filesystem. The real docker acts on DooPlex and cannot be reached from here. + """ + global ran + ran += 1 + r = subprocess.run([sys.executable, os.path.join(ROOT, "scripts", "test_check_volume_persistence.py")], + cwd=ROOT, capture_output=True, text=True, input="") + tail = (r.stdout + r.stderr).strip().splitlines() + if r.returncode != 0: + fails.append("volume-persistence: its injected-prober decoy suite FAILED rc=%d\n%s" + % (r.returncode, "\n".join(tail[-25:]))) + else: + print(" ok %-52s %s" % ("volume-persistence: injected-prober suite", tail[-1] if tail else "?")) + + ws = tempfile.mkdtemp(prefix="catalog-volpersist-") + try: + stub = os.path.join(ws, "stubbin") + os.makedirs(stub) + io.open(os.path.join(stub, "docker"), "w", encoding="utf-8").write(FAIL_DOCKER % sys.executable) + os.chmod(os.path.join(stub, "docker"), 0o755) + empty = os.path.join(ws, "nobin") + os.makedirs(empty) + + def run(name, expect_rc, must=(), path=stub, templates=True): + global ran + cat = os.path.join(ws, "cat") + shutil.rmtree(cat, ignore_errors=True) + os.makedirs(os.path.join(cat, "scripts")) + shutil.copy(os.path.join(ROOT, "scripts", "check-volume-persistence.py"), os.path.join(cat, "scripts")) + if templates: + d = os.path.join(cat, "templates", "demo") + os.makedirs(d) + io.open(os.path.join(d, "docker-compose.yml"), "w", encoding="utf-8").write( + "services:\n demo:\n image: example.org/demo:1.0\n volumes:\n - demo_data:/data\n" + "volumes:\n demo_data:\n") + r = subprocess.run([sys.executable, os.path.join(cat, "scripts", "check-volume-persistence.py")], + cwd=cat, env={"PATH": path}, capture_output=True, text=True, input="", timeout=300) + out = r.stdout + r.stderr + ran += 1 + miss = [m for m in must if m not in out] + if r.returncode == expect_rc and not miss: + print(" ok %-52s rc=%d (expected %d)" % ("volume-persistence: " + name, r.returncode, expect_rc)) + else: + fails.append("volume-persistence: %s: rc=%d expected %d%s; missing %s\n%s" % ( + name, r.returncode, expect_rc, " - LIVE HOLE" if r.returncode == 0 else "", miss, out[-600:])) + + run("LABEL: a runtime that answers nothing", 3, ("HARNESS REFUSED", "failed its canary")) + run("LABEL: no docker at all", 3, ("HARNESS REFUSED",), path=empty) + run("LABEL: nothing to judge", 3, ("HARNESS REFUSED",), templates=False) + finally: + shutil.rmtree(ws, ignore_errors=True) + + def mem_sum_cases(): """check-mem-limit-sum.py reads FILES: templates/*/docker-compose.yml + .felhom.yml, via --root (R-758).""" global ran @@ -1461,6 +1531,7 @@ i18n: image_pins_cases() image_resolvable_cases() + volume_persistence_cases() onboarding_cases() family_gate_cases() mem_sum_cases()