# -*- coding: utf-8 -*- """The scripted oracle: does the command a model would emit actually work here? No model is involved and nothing is billed. A fixed corpus of shell commands, of the shape an LLM emits by default because that is what its training data is full of, is run through each arm's own shell and compared against a known expected result. What comes out is not a speed figure. It is a correctness figure: how much of a model's default vocabulary survives contact with this environment. This matters because it separates two claims the paper must not confuse: the environment is hostile -> the oracle fails here too the model chose badly for it -> the oracle succeeds where the model failed Every probe stores its full stdout, stderr and exit code. A classification is a claim; the captured bytes are the data. Outcome codes, and the reason the middle ones exist: ok exit code and stdout both as expected crlf correct once line endings are normalised. Not a crash. It is worse: the command worked and the text came back different, which is how an exact-string edit silently fails to match output-differs exit code right, output wrong. The silent class exit-differs exit code wrong. Includes the trap where a failing command reports success not-found the tool is not there at all timeout did not return Usage: python probe.py --arm L-bash --shell "/bin/bash -c" python probe.py --arm W-gitbash --shell "sh -c" python probe.py --arm W-ps51 --shell "powershell -NoProfile -Command" """ import argparse import json import os import shutil import subprocess import sys import tempfile import time TIMEOUT = 20 # (id, category, command, expected_stdout, expected_exit) # Expected values are what the command means on a POSIX system, because that is # the contract the model is writing against. PROBES = [ # ---- redirection and streams ------------------------------------------- ('red-devnull', 'redirection', 'echo hi > /dev/null; echo done', 'done', 0), ('red-stderr', 'redirection', 'ls nosuchfile 2>/dev/null; echo done', 'done', 0), ('red-combine', 'redirection', 'echo out; echo err 1>&2', 'out', 0), ('red-append', 'redirection', 'echo a > f1; echo b >> f1; cat f1', 'a\nb', 0), ('red-pipe', 'redirection', 'echo hello | tr a-z A-Z', 'HELLO', 0), ('red-heredoc', 'redirection', "cat < f; grep b f', 'b', 0), ('txt-grep-n', 'text', 'printf "a\\nb\\n" > f; grep -n b f', '2:b', 0), ('txt-sed', 'text', 'echo foobar | sed "s/foo/baz/"', 'bazbar', 0), ('txt-sed-i', 'text', 'echo foo > f; sed -i "s/foo/bar/" f; cat f', 'bar', 0), ('txt-awk', 'text', 'echo "a b c" | awk "{print \\$2}"', 'b', 0), ('txt-cut', 'text', 'echo "a:b:c" | cut -d: -f2', 'b', 0), ('txt-sort-uniq', 'text', 'printf "b\\na\\nb\\n" | sort | uniq', 'a\nb', 0), ('txt-wc', 'text', 'printf "a\\nb\\nc\\n" | wc -l | tr -d " "', '3', 0), ('txt-head', 'text', 'printf "1\\n2\\n3\\n" | head -2', '1\n2', 0), ('txt-tail', 'text', 'printf "1\\n2\\n3\\n" | tail -1', '3', 0), ('txt-tr-delete', 'text', 'echo "a1b2" | tr -d "0-9"', 'ab', 0), ('txt-rev-sort-n', 'text', 'printf "10\\n9\\n" | sort -n', '9\n10', 0), # ---- command substitution and variables -------------------------------- ('var-subst', 'vars', 'X=$(echo hi); echo $X', 'hi', 0), ('var-backtick', 'vars', 'X=`echo hi`; echo $X', 'hi', 0), ('var-inline-env', 'vars', "FOO=bar sh -c 'echo $FOO'", 'bar', 0), ('var-export', 'vars', 'export FOO=bar; echo $FOO', 'bar', 0), ('var-default', 'vars', 'echo ${UNSET_VAR_XYZ:-fallback}', 'fallback', 0), ('var-arith', 'vars', 'echo $((2 + 3))', '5', 0), # ---- quoting and escaping ---------------------------------------------- ('quote-single', 'quoting', "echo 'a b'", 'a b', 0), ('quote-double', 'quoting', 'echo "a b"', 'a b', 0), ('quote-nested', 'quoting', 'echo "outer \'inner\' end"', "outer 'inner' end", 0), ('quote-dollar-literal', 'quoting', "echo 'costs $5'", 'costs $5', 0), ('quote-backslash', 'quoting', 'printf "a\\tb\\n"', 'a\tb', 0), ('quote-glob-literal', 'quoting', 'echo "*"', '*', 0), # ---- paths -------------------------------------------------------------- ('path-mkdir-p', 'paths', 'mkdir -p a/b/c && echo ok', 'ok', 0), ('path-nested-write', 'paths', 'mkdir -p x/y && echo v > x/y/f && cat x/y/f', 'v', 0), ('path-spaces', 'paths', 'mkdir -p "dir with spaces" && echo v > "dir with spaces/f" ' '&& cat "dir with spaces/f"', 'v', 0), ('path-unicode', 'paths', 'mkdir -p "ελληνικά" ' '&& echo v > "ελληνικά/f" ' '&& cat "ελληνικά/f"', 'v', 0), ('path-relative-up', 'paths', 'mkdir -p p/q && cd p/q && cat ../../marker', 'MARK', 0), ('path-basename', 'paths', 'basename /a/b/c.txt', 'c.txt', 0), ('path-dirname', 'paths', 'dirname /a/b/c.txt', '/a/b', 0), ('path-trailing-slash', 'paths', 'mkdir -p t && ls -d t/ | tr -d "/"', 't', 0), # ---- case sensitivity: a data-loss trap, not a speed issue -------------- ('case-two-files', 'case', 'echo one > Alpha.txt; echo two > alpha.txt; ' 'ls | grep -ci alpha | tr -d " "', '2', 0), ('case-distinct-content', 'case', 'echo one > Beta.txt; echo two > beta.txt; cat Beta.txt', 'one', 0), ('case-grep-sensitive', 'case', 'echo Hello > f; grep -c hello f | tr -d " "', '0', 0), # ---- globbing ----------------------------------------------------------- ('glob-star', 'glob', 'touch g1.txt g2.txt; ls *.txt | sort', 'g1.txt\ng2.txt', 0), ('glob-in-for', 'glob', 'touch h1.md h2.md; for f in *.md; do echo $f; done | sort', 'h1.md\nh2.md', 0), ('glob-no-match', 'glob', 'ls *.nonexistentext 2>/dev/null; echo done', 'done', 0), # ---- find and xargs, the agent's bulk tools ---------------------------- ('find-name', 'find', 'mkdir -p d && touch d/a.py d/b.py && find d -name "*.py" | sort', 'd/a.py\nd/b.py', 0), ('find-type-f', 'find', 'mkdir -p e/sub && touch e/f1 && find e -type f', 'e/f1', 0), ('find-exec', 'find', 'mkdir -p k && touch k/z.txt && find k -name "*.txt" -exec basename {} \\;', 'z.txt', 0), ('xargs-basic', 'find', 'printf "a\\nb\\n" | xargs echo', 'a b', 0), ('xargs-null', 'find', 'mkdir -p n && touch "n/a b.txt" && find n -type f -print0 | ' 'xargs -0 basename', 'a b.txt', 0), # ---- line endings: where an exact-string edit dies quietly ------------- ('eol-printf-lf', 'eol', 'printf "a\\nb\\n" > f; wc -c < f | tr -d " "', '4', 0), ('eol-echo-roundtrip', 'eol', 'echo abc > f; cat f', 'abc', 0), ('eol-echo-bytes', 'eol', 'echo abc | wc -c | tr -d " "', '4', 0), # ---- tool availability -------------------------------------------------- ('tool-git', 'tools', 'git --version > /dev/null && echo present', 'present', 0), ('tool-python', 'tools', 'python3 -c "print(1)" 2>/dev/null || python -c "print(1)"', '1', 0), ('tool-curl', 'tools', 'curl --version > /dev/null 2>&1 && echo present', 'present', 0), ('tool-tar', 'tools', 'tar --version > /dev/null 2>&1 && echo present', 'present', 0), ('tool-diff', 'tools', 'echo a > f1; echo a > f2; diff f1 f2 && echo same', 'same', 0), ('tool-realpath', 'tools', 'realpath . > /dev/null && echo present', 'present', 0), ('tool-stat', 'tools', 'touch f; stat -c %s f 2>/dev/null || stat -f %z f', '0', 0), ('tool-du', 'tools', 'du -h . > /dev/null && echo present', 'present', 0), ('tool-which', 'tools', 'which echo > /dev/null && echo present', 'present', 0), # ---- write then immediately read: metadata coherence ------------------- ('coh-write-read', 'coherence', 'echo v > f && cat f', 'v', 0), ('coh-write-stat', 'coherence', 'echo abcd > f && wc -c < f | tr -d " "', '5', 0), ('coh-write-find', 'coherence', 'touch fresh.txt && find . -name "fresh.txt" | head -1', './fresh.txt', 0), ('coh-append-read', 'coherence', 'echo a > f; echo b >> f; tail -1 f', 'b', 0), ('coh-delete-gone', 'coherence', 'touch gone.txt && rm gone.txt && ls gone.txt 2>/dev/null; ' 'echo checked', 'checked', 0), ('coh-mv-visible', 'coherence', 'echo v > src && mv src dst && cat dst', 'v', 0), ('coh-subshell-sees', 'coherence', 'echo v > f && sh -c "cat f"', 'v', 0), ] def norm_crlf(s): return s.replace('\r\n', '\n').replace('\r', '\n') def classify(exp_out, exp_code, out, err, code): o = out.rstrip('\n').rstrip('\r') e = exp_out.rstrip('\n') low = err.lower() if code == exp_code and o == e: return 'ok' if ('not found' in low or 'not recognized' in low or 'commandnotfound' in low.replace(' ', '')): return 'not-found' if code == exp_code and norm_crlf(o) == norm_crlf(e) and o != e: return 'crlf' if code != exp_code: return 'exit-differs' return 'output-differs' 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='probe08_') parts = a.shell.split() results = [] for pid, cat, cmd, exp_out, exp_code in PROBES: wd = os.path.join(root, pid) os.makedirs(wd) # one probe needs a file two levels up to test relative traversal with open(os.path.join(wd, 'marker'), 'w') as fh: fh.write('MARK\n') rec = {'id': pid, 'category': cat, 'command': cmd, 'expected_stdout': exp_out, 'expected_exit': exp_code} try: p = subprocess.run(parts + [cmd], cwd=wd, timeout=TIMEOUT, stdout=subprocess.PIPE, stderr=subprocess.PIPE) out = p.stdout.decode('utf-8', 'replace') err = p.stderr.decode('utf-8', 'replace') rec.update({'exit': p.returncode, 'stdout': out[:4000], 'stderr': err[:2000], 'outcome': classify(exp_out, exp_code, out, err, p.returncode)}) except subprocess.TimeoutExpired: rec.update({'exit': None, 'stdout': '', 'stderr': '', 'outcome': 'timeout'}) except Exception as ex: rec.update({'exit': None, 'stdout': '', 'stderr': str(ex)[:2000], 'outcome': 'exit-differs'}) results.append(rec) shutil.rmtree(root, ignore_errors=True) counts = {} for r in results: counts[r['outcome']] = counts.get(r['outcome'], 0) + 1 print(json.dumps({ 'arm': a.arm, 'shell': a.shell, 'when': time.strftime('%Y-%m-%dT%H:%M:%S'), 'host': os.environ.get('HOSTNAME') or os.environ.get('COMPUTERNAME') or 'unknown', 'n': len(results), 'counts': counts, 'survival_pct': round(100.0 * counts.get('ok', 0) / len(results), 1), 'results': results, }, indent=1)) if __name__ == '__main__': main()