Ariver
2026-06-19 6f2856fa70722dad7f7c69a3addaa05ea9fd6e94
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/bin/bash
# Round01 permission gate QA. It simulates an Accessibility-denied launch path
# and verifies Quick Switch does not open while the permissions window is shown.
 
set -euo pipefail
 
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
OUTPUT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# shellcheck source=build-output-paths.sh
source "$SCRIPT_DIR/build-output-paths.sh"
APP="$BUILD_CURRENT_APP"
OPEN_WAIT="${ALIGNER_ROUND1_PERMISSION_GATE_OPEN_WAIT:-2.5}"
QUIT_AFTER="${ALIGNER_ROUND1_PERMISSION_GATE_QUIT_AFTER:-4.0}"
QUIT_TIMEOUT="${ALIGNER_ROUND1_PERMISSION_GATE_QUIT_TIMEOUT:-5.0}"
 
fail() {
  echo "Round01 permission gate QA failed: $*" >&2
  exit 1
}
 
aligner_pids_for_current_app() {
  ps -axo pid=,args= | while read -r pid command; do
    case "$command" in
      "$APP/Contents/MacOS/Aligner"*) echo "$pid" ;;
    esac
  done
}
 
stop_current_aligner() {
  for pid in $(aligner_pids_for_current_app); do
    kill "$pid" 2>/dev/null || true
  done
 
  for _ in {1..30}; do
    [ -z "$(aligner_pids_for_current_app)" ] && return
    sleep 0.1
  done
 
  fail "current Aligner app did not exit before QA"
}
 
wait_for_app_exit() {
  local timeout="$1"
  /usr/bin/python3 - "$APP_PID" "$timeout" <<'PY'
import os
import sys
import time
 
pid = int(sys.argv[1])
timeout = float(sys.argv[2])
deadline = time.monotonic() + timeout
 
while time.monotonic() < deadline:
    stat = os.popen(f"ps -p {pid} -o stat=").read().strip()
    if not stat or "Z" in stat:
        sys.exit(0)
    time.sleep(0.1)
 
print(f"Aligner app did not quit within {timeout:.1f}s", file=sys.stderr)
sys.exit(1)
PY
}
 
stop_current_aligner
"$SCRIPT_DIR/package-app.sh" >&2
 
"$APP/Contents/MacOS/Aligner" \
  --round0-skip-permissions \
  --round01-simulate-accessibility-denied \
  --round01-open-quick-switch \
  --round01-quick-switch-quit-after="$QUIT_AFTER" &
 
APP_PID=$!
 
cleanup() {
  if kill -0 "$APP_PID" 2>/dev/null; then
    kill "$APP_PID" 2>/dev/null || true
    wait "$APP_PID" 2>/dev/null || true
  fi
}
trap cleanup EXIT
 
sleep "$OPEN_WAIT"
 
swift "$SCRIPT_DIR/window-logic-qa.swift" \
  --expect-permissions \
  --expect-no-quick-switch
 
wait_for_app_exit "$QUIT_TIMEOUT" || fail "app did not quit after permission gate check"
wait "$APP_PID"
trap - EXIT
 
swift "$SCRIPT_DIR/window-logic-qa.swift" \
  --expect-no-permissions \
  --expect-no-quick-switch
 
"$APP/Contents/MacOS/Aligner" \
  --round01-simulate-screen-recording-denied &
 
APP_PID=$!
trap cleanup EXIT
 
sleep "$OPEN_WAIT"
 
swift "$SCRIPT_DIR/window-logic-qa.swift" \
  --expect-permissions \
  --expect-no-quick-switch
 
kill "$APP_PID" 2>/dev/null || true
wait "$APP_PID" 2>/dev/null || true
trap - EXIT
 
swift "$SCRIPT_DIR/window-logic-qa.swift" \
  --expect-no-permissions \
  --expect-no-quick-switch