#!/usr/bin/env bash
# Proves the detachable container is invisible to the program inside it: the exact bytes a
# terminal sends arrive unchanged, and a window resize is delivered. Runs a probe program
# twice -- bare on a pty, then through the container -- and requires identical output.
#
# Ctrl-B is the load-bearing case: Claude Code binds it, and a multiplexer with a prefix
# key would swallow it.
#
# dtach is a workstation package, absent on the remote builders this repo's test command is
# offloaded to. There is nothing to assert about a container that cannot be built, so the
# probe is skipped there rather than reported as a passthrough regression.
set -uo pipefail

if ! command -v dtach >/dev/null 2>&1; then
  printf 'skip dtach not installed on this host\n'
  exit 0
fi

TESTROOT=$(mktemp -d -t agent-passthrough.XXXXXX)
trap 'rm -rf "$TESTROOT"' EXIT

cat >"$TESTROOT/probe.py" <<'PY'
import os, signal, sys, termios, tty
fd = sys.stdin.fileno()
tty.setraw(fd)
signal.signal(signal.SIGWINCH, lambda *_: sys.stdout.write(
    "WINCH:%s\r\n" % (os.get_terminal_size().columns,)) or sys.stdout.flush())
sys.stdout.write("READY\r\n"); sys.stdout.flush()
seen = b""
while b"\x11" not in seen:
    chunk = os.read(fd, 1)
    if not chunk:
        break
    seen += chunk
    sys.stdout.write("".join("%02x" % b for b in chunk) + "\r\n")
    sys.stdout.flush()
termios.tcsetattr(fd, termios.TCSADRAIN, termios.tcgetattr(fd))
PY

cat >"$TESTROOT/drive.py" <<'PY'
import os, pty, select, signal, sys, time, fcntl, struct
argv = sys.argv[1:]
pid, fd = pty.fork()
if pid == 0:
    os.execvp(argv[0], argv)
fcntl.ioctl(fd, termios_ws := 0x5414, struct.pack("HHHH", 24, 80, 0, 0))
out = b""
deadline = time.time() + 12
def pump(until_ready=False):
    global out
    while time.time() < deadline:
        r, _, _ = select.select([fd], [], [], 0.3)
        if not r:
            return
        try:
            data = os.read(fd, 4096)
        except OSError:
            return
        if not data:
            return
        out += data
        if until_ready and b"READY" in out:
            return
pump(until_ready=True)
# Ctrl-B, Ctrl-C, Ctrl-D, Ctrl-Z, Ctrl-R, Ctrl-Space, Up arrow, then Ctrl-Q to stop.
for payload in (b"\x02", b"\x03", b"\x04", b"\x1a", b"\x12", b"\x00", b"\x1b[A"):
    os.write(fd, payload)
    time.sleep(0.15)
    pump()
fcntl.ioctl(fd, 0x5414, struct.pack("HHHH", 30, 100, 0, 0))
time.sleep(0.3)
pump()
os.write(fd, b"\x11")
time.sleep(0.3)
pump()
try:
    os.kill(pid, signal.SIGKILL)
except ProcessLookupError:
    pass
os.waitpid(pid, 0)
sys.stdout.write(out.decode("utf8", "replace"))
PY

normalize() { grep -oE '^(READY|WINCH:[0-9]+|[0-9a-f]{2,6})$' | tr '\n' ' '; }

bare=$(python3 "$TESTROOT/drive.py" python3 "$TESTROOT/probe.py" | tr -d '\r' | normalize)
wrapped=$(python3 "$TESTROOT/drive.py" dtach -c "$TESTROOT/sock" -E -z -r winch \
  python3 "$TESTROOT/probe.py" | tr -d '\r' | normalize)

fail=0
report() { if [[ $1 == 1 ]]; then printf 'ok   %s\n' "$2"; else printf 'FAIL %s\n' "$2"; fail=1; fi; }

[[ $bare == *"02 "* ]] && report 1 "probe harness receives Ctrl-B when unwrapped" ||
  report 0 "probe harness receives Ctrl-B when unwrapped (got: $bare)"
[[ $wrapped == *"02 "* ]] && report 1 "Ctrl-B reaches the program inside the container" ||
  report 0 "Ctrl-B reaches the program inside the container (got: $wrapped)"
[[ $wrapped == *"00 "* ]] && report 1 "Ctrl-Space reaches the program inside the container" ||
  report 0 "Ctrl-Space reaches the program inside the container (got: $wrapped)"
[[ $wrapped == *"1b 5b 41 "* ]] && report 1 "arrow keys reach the program inside the container" ||
  report 0 "arrow keys reach the program inside the container (got: $wrapped)"

# The container attaches after the program has already started, so anything printed before
# the attach is not replayed -- it keeps no screen buffer. Compare the keystrokes only.
bare_keys=${bare#READY }
wrapped_keys=${wrapped#READY }
[[ $bare_keys == "$wrapped_keys" ]] && report 1 "keystroke byte stream identical wrapped and unwrapped" ||
  report 0 "keystroke byte stream identical wrapped and unwrapped
  bare:    $bare_keys
  wrapped: $wrapped_keys"
[[ $wrapped == *"WINCH:100"* ]] && report 1 "terminal resize reaches the program" ||
  report 0 "terminal resize reaches the program (got: $wrapped)"

exit $fail
