# -*- coding: utf-8 -*- """Silent divergence: commands that succeed and lie. The first oracle found the shell carries almost all of the command failure, and the operating system contributed two commands out of seventy six. Both of those two returned exit code 0 with an empty stderr, and one of them destroyed a file. That is a far more dangerous class than a failure, because nothing in the transcript marks it, and no failure rate or retry counter can ever reach it. So this probe goes looking for more of it, with the shell held constant. Every arm runs a POSIX shell, so any difference that appears belongs to the operating system and the filesystem rather than to a dialect. **Nothing is hardcoded as expected.** Several of these I did not know the answer to, and inventing an expectation would be guessing dressed as a control. Each probe records what actually happened on each arm, and the comparison is made afterwards against Linux as ground truth. The classification is then: match same result, no divergence silent exit 0 on both arms, different result. THE DANGEROUS CLASS loud the arm failed with a non-zero exit. Recoverable, because the agent can see it Usage, once per arm, both with a POSIX shell: python probe_silent.py --arm L-bash --shell "/bin/bash -c" python probe_silent.py --arm W-gitbash --shell "sh -c" """ import argparse import json import os import shutil import subprocess import tempfile import time TIMEOUT = 25 # (id, what it is looking for, command). The command must print something that # distinguishes the behaviours, and must clean up after itself inside its own dir. PROBES = [ ('case-overwrite', 'do two names differing only in case become one file', 'echo one > Beta.txt; echo two > beta.txt; cat Beta.txt; ls | wc -l | tr -d " "'), ('case-mkdir', 'does the second mkdir of a case variant succeed', 'mkdir Alpha 2>/dev/null; mkdir alpha 2>/dev/null; echo "dirs=$(ls -d */ 2>/dev/null | wc -l | tr -d \\" \\")"'), ('case-rename', 'can a file be renamed to differ only in case', 'echo v > low.txt; mv low.txt LOW.txt 2>/dev/null; ls | tr "\\n" ","'), ('case-glob', 'does a glob match a different case', 'touch data.txt; ls *.TXT 2>/dev/null | wc -l | tr -d " "'), ('case-cd', 'does cd accept the wrong case', 'mkdir -p RealDir; cd realdir 2>/dev/null && echo entered || echo refused'), ('symlink', 'does ln -s make a link or silently copy', 'echo v > target; ln -s target link 2>/dev/null; ' 'if [ -L link ]; then echo symlink; elif [ -f link ]; then echo copy; else echo none; fi'), ('hardlink', 'does ln make a hard link that shares content', 'echo a > orig; ln orig hard 2>/dev/null; echo b > orig; cat hard 2>/dev/null || echo nolink'), ('chmod-honoured', 'does chmod change what ls reports', 'touch f; chmod 600 f; ls -l f | cut -c1-10'), ('exec-bit', 'does a script need and keep an exec bit', 'printf "#!/bin/sh\\necho ran\\n" > s.sh; chmod +x s.sh; ./s.sh 2>/dev/null || echo blocked'), ('trailing-dot', 'does a trailing dot survive in a filename', 'touch "name." 2>/dev/null; ls | tr "\\n" ","'), ('trailing-space', 'does a trailing space survive in a filename', 'touch "name " 2>/dev/null; ls | sed "s/ $//" | tr "\\n" ","'), ('reserved-name', 'what happens to a Windows reserved device name', 'echo v > aux.txt 2>/dev/null && echo wrote || echo refused; ' 'echo v > con 2>/dev/null && echo wrote-con || echo refused-con; ls | tr "\\n" ","'), ('colon-in-name', 'is a colon legal in a filename', 'echo v > "a:b" 2>/dev/null && echo wrote || echo refused; ls | tr "\\n" ","'), ('delete-open-file', 'can a file be deleted while it is open', 'echo v > f; (sleep 3 & ) ; exec 3< f; rm f 2>/dev/null && echo deleted || echo locked; exec 3<&-'), ('overwrite-open-file', 'can a file be written while another handle holds it', 'echo a > f; exec 3< f; echo b > f 2>/dev/null && echo wrote || echo locked; exec 3<&-; cat f'), ('crlf-roundtrip', 'does a written LF file read back as LF', 'printf "a\\nb\\n" > f; wc -c < f | tr -d " "'), ('crlf-sed-preserve', 'does sed -i on a CRLF file preserve the CRLF', 'printf "a\\r\\nb\\r\\n" > f; sed -i "s/a/x/" f; wc -c < f | tr -d " "'), ('crlf-grep-anchor', 'does an end anchor match when the line ends CRLF', 'printf "abc\\r\\n" > f; grep -c "abc$" f | tr -d " "'), ('long-path', 'how deep can a path go before it breaks', 'p=.; for i in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20; do ' 'p="$p/dirname_that_is_long_enough_to_matter_$i"; done; ' 'mkdir -p "$p" 2>/dev/null && echo v > "$p/f" 2>/dev/null && cat "$p/f" || echo failed'), ('unicode-name', 'does a non-ascii filename survive a round trip', 'echo v > "ελληνικά.txt" 2>/dev/null; ' 'ls | tr "\\n" ","; cat "ελληνικά.txt" 2>/dev/null || echo unreadable'), ('mtime-order', 'do two writes produce distinguishable mtimes', 'echo a > f1; echo b > f2; ls -t | head -1'), ('du-apparent', 'does an empty file report zero bytes', 'touch f; wc -c < f | tr -d " "'), ('rm-rf-readonly', 'can a read only file be removed without a prompt', 'echo v > f; chmod 444 f; rm -f f 2>/dev/null; ls f 2>/dev/null && echo still-there || echo gone'), ('pipe-binary', 'does binary survive a pipe unmangled', 'printf "a\\000b" | wc -c | tr -d " "'), ] def main(): ap = argparse.ArgumentParser() ap.add_argument('--arm', required=True) ap.add_argument('--shell', required=True) a = ap.parse_args() root = tempfile.mkdtemp(prefix='silent08_') parts = a.shell.split() out = [] for pid, question, cmd in PROBES: wd = os.path.join(root, pid) os.makedirs(wd) rec = {'id': pid, 'question': question, 'command': cmd} try: p = subprocess.run(parts + [cmd], cwd=wd, timeout=TIMEOUT, stdout=subprocess.PIPE, stderr=subprocess.PIPE) rec.update({'exit': p.returncode, 'stdout': p.stdout.decode('utf-8', 'replace').strip()[:600], 'stderr': p.stderr.decode('utf-8', 'replace').strip()[:600]}) except subprocess.TimeoutExpired: rec.update({'exit': None, 'stdout': '', 'stderr': 'TIMEOUT'}) except Exception as ex: rec.update({'exit': None, 'stdout': '', 'stderr': str(ex)[:400]}) out.append(rec) shutil.rmtree(root, ignore_errors=True) print(json.dumps({'arm': a.arm, 'shell': a.shell, 'when': time.strftime('%Y-%m-%dT%H:%M:%S'), 'n': len(out), 'results': out}, indent=1)) if __name__ == '__main__': main()