From 9ba7cd3b47fb91eaaa8d0c3df8b7286a89be1756 Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sun, 28 Jun 2026 21:19:30 +0800
Subject: [PATCH] Freeze 0.1.12 local QA baseline

---
 C3.tools/round1-window-activation-fixture-qa.sh |  102 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 101 insertions(+), 1 deletions(-)

diff --git a/C3.tools/round1-window-activation-fixture-qa.sh b/C3.tools/round1-window-activation-fixture-qa.sh
index 56dba71..889b88d 100755
--- a/C3.tools/round1-window-activation-fixture-qa.sh
+++ b/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,9 +175,53 @@
 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 \
@@ -203,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

--
Gitblit v1.9.3