Ariver
2026-08-14 86f0b4bd20cdec86dfb5bdb7978d1f6ff4af111a
C3.tools/round1-window-activation-fixture-qa.sh
@@ -9,10 +9,12 @@
OUTPUT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# shellcheck source=build-output-paths.sh
source "$SCRIPT_DIR/build-output-paths.sh"
SOURCE_ROOT="$OUTPUT_ROOT/C1.source"
APP="$BUILD_CURRENT_APP"
MINIMIZED_REPORT="$BUILD_REPORT_ROOT/round01-window-activation-minimized-report.json"
NORMAL_REPORT="$BUILD_REPORT_ROOT/round01-window-activation-normal-report.json"
APP_ONLY_REPORT="$BUILD_REPORT_ROOT/round01-window-activation-app-only-report.json"
FAILURE_REPORT="$BUILD_REPORT_ROOT/round01-window-activation-failure-report.json"
REPORT_WAIT="${ALIGNER_ROUND1_ACTIVATION_REPORT_WAIT:-6.0}"
fail() {
@@ -39,6 +41,38 @@
  done
  fail "current Aligner app did not exit before QA"
}
assert_activation_budget_source() {
  /usr/bin/python3 - "$SOURCE_ROOT/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift" "$SOURCE_ROOT/Sources/Aligner/QuickSwitchSessionController.swift" <<'PY'
import re
import sys
window_service_path, session_path = sys.argv[1:3]
window_service = open(window_service_path, "r", encoding="utf-8").read()
session = open(session_path, "r", encoding="utf-8").read()
def fail(message):
    print(message, file=sys.stderr)
    sys.exit(1)
cycle_match = re.search(r"finderTabCycleMaximumAttempts\s*=\s*(\d+)", window_service)
if not cycle_match:
    fail("Finder tab cycling attempt limit is missing")
if int(cycle_match.group(1)) != 5:
    fail(f"Finder tab cycling attempt limit must be 5, got {cycle_match.group(1)}")
budget_match = re.search(r"finderTabActivationBudgetLimit:\s*TimeInterval\s*=\s*([0-9.]+)", window_service)
if not budget_match:
    fail("Finder tab activation budget limit is missing")
if float(budget_match.group(1)) > 1.5:
    fail(f"Finder tab activation budget must stay at or below 1.5s, got {budget_match.group(1)}")
if "lastActivationDurationMilliseconds" not in session:
    fail("Quick Switch activation report must expose lastActivationDurationMilliseconds")
print("Finder activation source guardrails passed")
PY
}
wait_for_activation_report() {
@@ -124,6 +158,8 @@
require(report.get("lastActivationWindowID") == expected_window_id, "activation window must match selected target")
require(report.get("lastActivationResult") == expected_result, "activation result must match expected path")
require(report.get("lastActivationError") is None, "debug activation should not record an error")
duration = report.get("lastActivationDurationMilliseconds")
require(isinstance(duration, (int, float)) and duration >= 0, "activation report must include non-negative duration")
require(len(selected_cards) == 1, "activation fixture must expose exactly one selected card")
require(selected_cards[0].get("windowID") == expected_window_id, "selected card must match activation target")
require(selected_cards[0].get("isMinimized") is expected_minimized, "selected card minimized flag must match activation target")
@@ -131,6 +167,7 @@
print(json.dumps({
    "commitSource": report.get("lastCommitSource"),
    "activationResult": report.get("lastActivationResult"),
    "activationDurationMilliseconds": report.get("lastActivationDurationMilliseconds"),
    "selectedWindowID": root.get("selectedWindowID"),
    "quickSwitchVisible": report.get("quickSwitchVisible"),
    "selectedIsMinimized": selected_cards[0].get("isMinimized")
@@ -138,17 +175,62 @@
PY
}
assert_activation_failure_suppression_report() {
  /usr/bin/python3 - "$FAILURE_REPORT" <<'PY'
import json
import sys
path = sys.argv[1]
with open(path, "r", encoding="utf-8") as file:
    report = json.load(file)
def require(condition, message):
    if not condition:
        print(message, file=sys.stderr)
        print(json.dumps(report, indent=2, ensure_ascii=False), file=sys.stderr)
        sys.exit(1)
root = report.get("rootView", {})
cards = [
    card
    for column in root.get("waterfallColumns", [])
    for card in column.get("cards", [])
]
visible_window_ids = [card.get("windowID") for card in cards]
require(report.get("snapshotLoaded") is True, "activation failure snapshotLoaded must be true")
require(report.get("quickSwitchVisible") is False, "activation failure still hides Quick Switch after commit")
require(report.get("lastActivationResult") == "activationFailed", "forced activation failure must be reported")
require(report.get("lastActivationWindowID") == 40100, "forced activation failure must target the clicked window")
require(report.get("suppressedActivationWindowCount") == 1, "activation failure must suppress exactly one target")
require(40100 in report.get("suppressedActivationWindowIDs", []), "failed windowID must be recorded as suppressed")
require(40100 not in visible_window_ids, "failed activation target must be removed from the projected Waterfall")
require(report.get("windowCount") == 2, "projected view must keep remaining windows only")
require(report.get("suppressedCloseTargetCount") == 0, "activation suppression must not use close suppression")
print(json.dumps({
    "activationResult": report.get("lastActivationResult"),
    "lastActivationWindowID": report.get("lastActivationWindowID"),
    "suppressedActivationWindowIDs": report.get("suppressedActivationWindowIDs"),
    "visibleWindowIDs": visible_window_ids
}, indent=2, ensure_ascii=False))
PY
}
assert_activation_budget_source
stop_current_aligner
"$SCRIPT_DIR/package-app.sh" >&2
rm -f "$MINIMIZED_REPORT" "$NORMAL_REPORT" "$APP_ONLY_REPORT"
rm -f "$MINIMIZED_REPORT" "$NORMAL_REPORT" "$APP_ONLY_REPORT" "$FAILURE_REPORT"
"$APP/Contents/MacOS/Aligner" \
  --round0-skip-permissions \
  --round01-open-quick-switch \
  --round01-waterfall-view-mode=vertical \
  --round01-fixture-window-activation \
  --round01-disable-screenshot-refresh \
  --round01-debug-window-activation \
  --round01-debug-key-sequence="right,enter" \
  --round01-debug-key-sequence="2,down,enter" \
  --round01-quick-switch-report="$MINIMIZED_REPORT" &
APP_PID=$!
@@ -170,6 +252,7 @@
"$APP/Contents/MacOS/Aligner" \
  --round0-skip-permissions \
  --round01-open-quick-switch \
  --round01-waterfall-view-mode=vertical \
  --round01-fixture-window-activation \
  --round01-disable-screenshot-refresh \
  --round01-debug-window-activation \
@@ -187,6 +270,7 @@
"$APP/Contents/MacOS/Aligner" \
  --round0-skip-permissions \
  --round01-open-quick-switch \
  --round01-waterfall-view-mode=vertical \
  --round01-fixture-window-activation \
  --round01-disable-screenshot-refresh \
  --round01-debug-window-activation \
@@ -200,5 +284,24 @@
kill "$APP_PID" 2>/dev/null || true
wait "$APP_PID" 2>/dev/null || true
stop_current_aligner
ALIGNER_DEBUG_WINDOW_ACTIVATION_RESULT=activationFailed "$APP/Contents/MacOS/Aligner" \
  --round0-skip-permissions \
  --round01-open-quick-switch \
  --round01-waterfall-view-mode=vertical \
  --round01-fixture-window-activation \
  --round01-disable-screenshot-refresh \
  --round01-debug-window-activation \
  --round01-debug-mouse-sequence="click-card:0:1" \
  --round01-quick-switch-report="$FAILURE_REPORT" &
APP_PID=$!
wait_for_activation_report "$FAILURE_REPORT"
swift "$SCRIPT_DIR/window-logic-qa.swift" --expect-no-quick-switch >&2
assert_activation_failure_suppression_report
kill "$APP_PID" 2>/dev/null || true
wait "$APP_PID" 2>/dev/null || true
trap - EXIT
stop_current_aligner