master
John Lauer Gates run beside other threads' windows (own profile, untouched); smoke expects no owner chip by default f38b7d9 29d ago
#!/usr/bin/env bash
# The ship gate for "a pup window never lands in front of the user" (John, 2026-09-18: "if you can truly
# figure out opening background pup windows, it generally solves the problem").
#
#   tools/foreground-proof.sh <box> [pinHwnd]
#
# Pins a NON-pup window in front (the given hwnd, else the topmost non-Chrome normal window), forces a cold
# lane, then does what a sign-in does: cold open, navigate, navigate, warm open, warm open, navigate; the
# whole time it samples the top-of-screen window twice a second through ab (no console, no focus change).
# PASS = zero samples with a Chrome-for-Testing window on top. Any pup window on top, even one sample, FAILS.
# Never run it on the user's own desktop: it opens windows. winvm or the conference-room box.
set -u
BOX="${1:?usage: tools/foreground-proof.sh <box> [pinHwnd]}"; PIN="${2:-}"
AB="adom-bridge --target $BOX --ai-thread pup-foreground-proof"
S="${TMPDIR:-/tmp}/fgproof-$$"; mkdir -p "$S"
lw() { timeout 25 $AB desktop_list_windows '{}' 2>/dev/null; }
top() { lw | python3 -c "
import sys,json
try:
    d=json.load(sys.stdin); o=d.get('output',d)
    if isinstance(o,str): o=json.loads(o)
    w=(o.get('data') or o).get('windows') or []
    t=[x for x in w if not x.get('minimized') and x.get('kind')=='normal']; t.sort(key=lambda x: x.get('z',999))
    print((str(t[0].get('pid') or '?')+'|'+(t[0].get('image') or '?')+'|'+(t[0].get('title') or '')[:40]) if t else 'none')
except Exception: print('?')"; }
# 2.0.665: the judge counts a sample only when the top window's PID belongs to a pup browser (command line names
# pup-profiles), sampled every 5 s. On a box where the user runs their own Chrome, counting by image name blamed
# pup for the user's windows (arav-rog, 2026-09-20).
puppids() { timeout 25 $AB run_script "{\"interpreter\":\"powershell\",\"scriptB64\":\"$(printf '%s' '(Get-CimInstance Win32_Process | Where-Object { $_.Name -eq "chrome.exe" -and $_.CommandLine -match "pup-profiles" } | ForEach-Object { $_.ProcessId }) -join ","' | base64 -w0)\",\"reason\":\"Sampling pup browser pids for the foreground gate\"}" 2>/dev/null | python3 -c "import sys,json; t=sys.stdin.read(); d=json.loads(t[t.index('{'):]); print((d.get('stdout') or '').strip())" 2>/dev/null; }
if [ -z "$PIN" ]; then PIN=$(lw | python3 -c "
import sys,json
d=json.load(sys.stdin); o=d.get('output',d)
if isinstance(o,str): o=json.loads(o)
w=(o.get('data') or o).get('windows') or []
t=[x for x in w if not x.get('minimized') and x.get('kind')=='normal' and x.get('image')!='chrome.exe']; t.sort(key=lambda x: x.get('z',999))
print(t[0].get('hwnd') if t else '')"); fi
[ -n "$PIN" ] || { echo "no non-pup window to pin on $BOX"; exit 2; }
echo "== pin window $PIN in front, force a cold lane =="
# 2.0.700: NEVER touch another thread's windows. This used to close every window on the box with takeover, then
# force-kill the browser; on 2026-10-05 it closed another thread's adom-parts-search window on arav-rog for good.
# The gate needs a cold browser, which means ending every window in it, so a box where another thread has
# windows is not a valid box for it: refuse (INVALID, exit 2) and name them. Only the gate's own leftovers close.
SESS=$(timeout 60 $AB pup_status '{}' 2>/dev/null)
OTHERS=$(printf '%s' "$SESS" | python3 -c "
import sys,json
try: print(' '.join(s.get('sessionId')+'('+str(s.get('owner'))+')' for s in json.load(sys.stdin).get('sessions') or [] if s.get('owner')!='pup-foreground-proof'))
except Exception: print('?unreadable')")
# 2.0.714: on a shared box run in the gate's OWN profile (fgproof): its own browser is the one forced cold, and other
# threads' windows are never touched. The judge is unchanged: ANY pup window on top fails.
PROF=""; KILLPAT="pup-profiles"; CLOSEALL='{"all":true,"takeover":true}'
if [ -n "$OTHERS" ]; then echo "SHARED MODE: other threads have pup windows on $BOX ($OTHERS); the gate uses its own profile and leaves them alone"; PROF=',"profile":"fgproof"'; KILLPAT='pup-profiles[\\/]fgproof'; CLOSEALL='{"all":true}'; fi
for W in $(printf '%s' "$SESS" | python3 -c "
import sys,json
try: print(' '.join(s.get('sessionId') for s in json.load(sys.stdin).get('sessions') or [] if s.get('owner')=='pup-foreground-proof'))
except Exception: pass"); do timeout 60 $AB pup_close_window "{\"window\":\"$W\",\"reason\":\"foreground proof: clear the gate's own leftover windows\"}" >/dev/null 2>&1; done
cat > "$S/cold.ps1" <<'PS'
Get-CimInstance Win32_Process -Filter "Name='chrome.exe'" | Where-Object { $_.CommandLine -match '__KILLPAT__' } | ForEach-Object { Stop-Process -Id $_.ProcessId -Force -ErrorAction SilentlyContinue }
Start-Sleep -Seconds 2; "cold"
PS
KILLPAT="$KILLPAT" python3 -c 'import os,sys; p=sys.argv[1]; t=open(p).read(); open(p,"w").write(t.replace("__KILLPAT__", os.environ["KILLPAT"]))' "$S/cold.ps1"   # byte-exact: sed and ${//} both eat the regex backslash
ENC=$(iconv -f utf-8 -t utf-16le "$S/cold.ps1" | base64 -w0)
timeout 120 $AB shell_execute "{\"command\":\"powershell -NoProfile -EncodedCommand $ENC\",\"timeoutMs\":60000,\"reason\":\"foreground proof: force a cold pup browser\"}" >/dev/null 2>&1
timeout 60 $AB desktop_bring_to_front "{\"hwnd\":$PIN,\"reason\":\"foreground proof: pin a non-pup window in front\"}" >/dev/null 2>&1; sleep 2
echo "top before: $(top)"
(for i in $(seq 1 240); do echo "$(date +%H:%M:%S) $(top)"; sleep 0.5; done > "$S/samples" 2>&1) & SP=$!
(for i in $(seq 1 60); do puppids; sleep 5; done > "$S/puppids" 2>&1) & PP=$!
mark() { echo "$(date +%H:%M:%S) ===== $*" >> "$S/marks"; }
FAILS=0
# a step must SUCCEED: a window that never opens trivially never surfaces, and that must not read as a pass
step() { local name="$1"; shift; mark "$name"; local r; r=$(timeout 250 $AB "$@" 2>&1); local ok; ok=$(echo "$r" | python3 -c "
import sys,json
try: d=json.load(sys.stdin); print('ok' if d.get('ok') is True else 'FAIL '+str(d.get('errorCode') or d.get('error') or '?')[:90])
except Exception: print('FAIL unparsable')"); case "$ok" in ok) ;; *) FAILS=$((FAILS+1)); mark "$name FAILED: $ok";; esac; }
sleep 1
step "cold open A"      pup_open_window "{\"window\":\"fgp-a\",\"url\":\"https://example.com/\"$PROF}"
step "navigate A"       pup_navigate    '{"window":"fgp-a","url":"https://example.org/"}'
step "navigate A again" pup_navigate    '{"window":"fgp-a","url":"https://example.com/"}'
step "warm open B"      pup_open_window "{\"window\":\"fgp-b\",\"url\":\"https://example.org/\"$PROF}"
step "warm open C"      pup_open_window "{\"window\":\"fgp-c\",\"url\":\"https://example.com/\"$PROF}"
step "navigate C"       pup_navigate    '{"window":"fgp-c","url":"https://example.org/"}'
mark "done"; sleep 3; kill $SP $PP 2>/dev/null; wait 2>/dev/null
BAD=$(python3 - "$S/samples" "$S/puppids" <<'PYJ'
import sys
pids=set()
for l in open(sys.argv[2]): pids.update(x.strip() for x in l.strip().split(',') if x.strip().isdigit())
bad=0
for l in open(sys.argv[1]):
    parts=l.split(' ',1)
    if len(parts)<2: continue
    top=parts[1].strip(); pid=top.split('|',1)[0]
    if pid in pids: bad+=1
print(bad)
PYJ
); TOTAL=$(grep -c . "$S/samples")   # by pup PID (see puppids); image-name counting blamed the user's own Chrome
OPEN=$(timeout 60 $AB pup_my_windows '{}' 2>/dev/null | python3 -c "
import sys,json
try: print(json.load(sys.stdin).get('count') or 0)
except Exception: print(0)")
echo; echo "== top of screen, start to finish =="; sort -m "$S/samples" "$S/marks" | uniq -f1 -c
echo
echo "steps failed: $FAILS | pup windows open at the end: $OPEN (want 3)"
if [ "$FAILS" -ne 0 ] || [ "$OPEN" -lt 3 ]; then echo "FOREGROUND PROOF: INVALID ($FAILS step(s) failed, $OPEN of 3 windows open): nothing to measure"; timeout 90 $AB pup_close "$CLOSEALL" >/dev/null 2>&1; exit 2; fi
timeout 90 $AB pup_close "$CLOSEALL" >/dev/null 2>&1
if [ "$BAD" -eq 0 ]; then echo "FOREGROUND PROOF: PASS ($TOTAL samples, 3 windows opened and navigated, a pup window was never on top)"; exit 0; else echo "FOREGROUND PROOF: FAIL ($BAD of $TOTAL samples had a pup window on top)"; exit 1; fi