From 86f0b4bd20cdec86dfb5bdb7978d1f6ff4af111a Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Fri, 14 Aug 2026 22:41:54 +0800
Subject: [PATCH] [verified] feat: export performance diagnostics

---
 C3.tools/round1-mouse-interaction-fixture-qa.sh |   73 +++++++++++++++++++++++++++---------
 1 files changed, 54 insertions(+), 19 deletions(-)

diff --git a/C3.tools/round1-mouse-interaction-fixture-qa.sh b/C3.tools/round1-mouse-interaction-fixture-qa.sh
index d0a6375..f5e0f29 100755
--- a/C3.tools/round1-mouse-interaction-fixture-qa.sh
+++ b/C3.tools/round1-mouse-interaction-fixture-qa.sh
@@ -15,10 +15,10 @@
 APP_ONLY_REPORT="$BUILD_REPORT_ROOT/round01-mouse-app-only-fixture-report.json"
 FIXTURE_APP_COUNT="${ALIGNER_ROUND1_MOUSE_FIXTURE_APP_COUNT:-8}"
 FIXTURE_WINDOWS_PER_APP="${ALIGNER_ROUND1_MOUSE_FIXTURE_WINDOWS_PER_APP:-8}"
-MOUSE_SEQUENCE="${ALIGNER_ROUND1_MOUSE_SEQUENCE:-hover-card:1:7,hover-app:5,click-app:7,hover-card:7:0,click-card:7:0}"
-APP_ONLY_MOUSE_SEQUENCE="${ALIGNER_ROUND1_MOUSE_APP_ONLY_SEQUENCE:-hover-app:5,click-app:7}"
+MOUSE_SEQUENCE="${ALIGNER_ROUND1_MOUSE_SEQUENCE:-hover-card:1:7,hover-app:5,hover-card:7:0,click-card:7:0}"
+APP_ONLY_MOUSE_SEQUENCE="${ALIGNER_ROUND1_MOUSE_APP_ONLY_SEQUENCE:-hover-app:7,click-app-near-close:7}"
 REPORT_WAIT="${ALIGNER_ROUND1_MOUSE_REPORT_WAIT:-6.0}"
-WINDOW_WAIT="${ALIGNER_ROUND1_MOUSE_WINDOW_WAIT:-3.0}"
+WINDOW_WAIT="${ALIGNER_ROUND1_MOUSE_WINDOW_WAIT:-6.0}"
 
 fail() {
   echo "Round01 mouse interaction fixture QA failed: $*" >&2
@@ -47,7 +47,8 @@
 }
 
 wait_for_committed_hidden_report() {
-  /usr/bin/python3 - "$REPORT" "$REPORT_WAIT" <<'PY'
+  local report="${1:-$REPORT}"
+  /usr/bin/python3 - "$report" "$REPORT_WAIT" <<'PY'
 import json
 import sys
 import time
@@ -169,23 +170,36 @@
 root = report.get("rootView", {})
 items = root.get("appShelfItems", [])
 columns = root.get("waterfallColumns", [])
-click_app_commands = [command for command in mouse_sequence if command.startswith("click-app:")]
-require(click_app_commands, "app-only sequence must include click-app:<appGroupIndex>")
+click_app_prefixes = ("click-app:", "click-app-center:", "click-app-near-close:")
+click_app_commands = [command for command in mouse_sequence if command.startswith(click_app_prefixes)]
+require(click_app_commands, "app-only sequence must include an App click command")
 last_click_app = click_app_commands[-1]
 last_click_parts = last_click_app.split(":")
-require(len(last_click_parts) == 2, "click-app command must be click-app:<appGroupIndex>")
+require(len(last_click_parts) == 2, "App click command must be <command>:<appGroupIndex>")
 target_app_group_index = int(last_click_parts[1])
 
 require(report.get("snapshotLoaded") is True, "app-only snapshotLoaded must be true")
-require(report.get("quickSwitchVisible") is True, "hover/click App Shelf must not close Quick Switch")
-require(report.get("lastCommittedWindowID") is None, "hover/click App Shelf must not commit a window")
+require(report.get("quickSwitchVisible") is False, "click App Shelf must close Quick Switch after committing its first window")
 require(root.get("mouseCommandsApplied") == mouse_sequence, "app-only mouse sequence must be applied in order")
 require(0 <= target_app_group_index < fixture_app_count, "click-app target App group must be inside fixture range")
 target_column = columns[target_app_group_index]
 target_first_card = target_column.get("cards", [])[0]
+expected_window_id = target_first_card.get("windowID")
 require(root.get("selectedAppGroupIndex") == target_app_group_index, "click App Shelf must move keyboard selection to target App")
 require(root.get("selectedWindowIndex") == target_first_card.get("windowIndex"), "click App Shelf must select the first target-column window")
 require(root.get("selectedWindowID") == target_first_card.get("windowID"), "click App Shelf must focus the first target-column window")
+require(root.get("lastCommittedWindowID") == expected_window_id, "click App Shelf must commit the first target-column window")
+require(report.get("lastCommittedWindowID") == expected_window_id, "session must surface the App Shelf commit")
+require(root.get("lastCommitSource") == "mouse", "root App Shelf commit source must be mouse")
+require(report.get("lastCommitSource") == "mouse", "session App Shelf commit source must be mouse")
+require(report.get("lastActivationWindowID") == expected_window_id, "App Shelf activation window must be the first target-column window")
+require(report.get("lastActivationResult") == "activated", "debug activation must activate the App Shelf first window")
+require(report.get("lastCloseTargetKind") is None, "App Shelf body click must not enter close flow")
+require(report.get("lastCloseResult") is None, "App Shelf body click must not request close")
+require(root.get("pendingCloseTargetKind") is None, "App Shelf body click must not create pending close target")
+require(root.get("hoveredCloseTargetKind") is None, "App Shelf body click must not leave a hovered close target")
+require(root.get("closeConfirmationVisible") is False, "App Shelf body click must not show close confirmation")
+require(root.get("closeFeedbackKind") is None, "App Shelf body click must not show close feedback")
 require(root.get("lastClickedAppGroupIndex") == target_app_group_index, "click App Shelf must record target App group")
 require(root.get("lastAppShelfClickChangedSelection") is True, "click App Shelf must explicitly report selection moved to target column")
 require(root.get("waterfallScrollOffset", 0) > 0, "clicking far-right App Shelf item must position its Waterfall column")
@@ -197,6 +211,10 @@
 print(json.dumps({
     "appOnlyQuickSwitchVisible": report.get("quickSwitchVisible"),
     "selectedAppGroupIndex": root.get("selectedAppGroupIndex"),
+    "lastCommittedWindowID": root.get("lastCommittedWindowID"),
+    "lastActivationResult": report.get("lastActivationResult"),
+    "closeConfirmationVisible": root.get("closeConfirmationVisible"),
+    "pendingCloseTargetKind": root.get("pendingCloseTargetKind"),
     "lastClickedAppGroupIndex": root.get("lastClickedAppGroupIndex"),
     "waterfallScrollOffset": root.get("waterfallScrollOffset")
 }, indent=2, ensure_ascii=False))
@@ -260,10 +278,8 @@
 require(report.get("lastActivationWindowID") == expected_window_id, "session activation window must match clicked card")
 require(report.get("lastActivationResult") == "activated", "debug activation must activate a non-minimized clicked card")
 
-require(root.get("lastClickedAppGroupIndex") == expected_app_group_index, "clicking App Shelf must record target App group")
-require(root.get("lastAppShelfClickChangedSelection") is True, "clicking App Shelf must move keyboard selection before the card click")
 require(root.get("waterfallScrollable") is True, "fixture must make Waterfall horizontally scrollable")
-require(root.get("waterfallScrollOffset", 0) > 0, "clicking far-right App must scroll its Waterfall column into view")
+require(root.get("waterfallScrollOffset", 0) > 0, "clicking far-right card must scroll its Waterfall column into view")
 
 selected_cards = [card for column in columns for card in column.get("cards", []) if card.get("isSelected") is True]
 require(len(selected_cards) == 1, "Waterfall must expose exactly one selected card after click")
@@ -281,13 +297,27 @@
 require(hovered_items[0].get("index") == expected_app_group_index, "hovered window card must link to App Shelf")
 
 hovered_segments = [segment for segment in segments if "hover" in segment.get("visualStates", [])]
-require(len(hovered_segments) == 1, "hovered window card must link to exactly one Space Lane segment")
-require(hovered_segments[0].get("windowCount", 0) > 0, "hovered Space Lane segment must be a real space with windows")
-require(root.get("hoveredSpaceID") == expected_space_id, "root hoveredSpaceID must match clicked card primarySpaceID")
+space_focused_segments = [segment for segment in segments if "spaceFocus" in segment.get("visualStates", [])]
+window_associated_segments = [segment for segment in segments if segment.get("isWindowAssociated") is True]
+require(root.get("hoverTargetKind") == "window", "hovered Waterfall card must report window hover target")
+require(root.get("activeSpaceFocusID") is None, "hovered Waterfall card must not create Space Lane focus")
+require(len(hovered_segments) == 0, "hovered Waterfall card must not mark a Space Lane segment as hovered")
+require(len(space_focused_segments) == 0, "hovered Waterfall card must not mark a Space Lane segment as focused")
+require(root.get("hoveredSpaceID") == expected_space_id, "root hoveredSpaceID may still mirror clicked card primarySpaceID for window context")
+require(root.get("windowHoverAssociatedSpaceID") == expected_space_id, "hovered Waterfall card must expose its Space as windowHoverAssociatedSpaceID")
+require(len(window_associated_segments) == 1, "hovered Waterfall card must highlight exactly one associated Space segment")
+require(window_associated_segments[0].get("spaceID") == expected_space_id, "window-associated Space segment must match hovered card Space")
+require("windowAssociated" in window_associated_segments[0].get("visualStates", []), "window-associated Space segment must expose windowAssociated")
+require("focused" not in window_associated_segments[0].get("visualStates", []), "window-associated Space segment must not expose focused")
 
 frame = selected_cards[0].get("visibleFrame", {})
+selected_card_visual_overflow_tolerance = 2.5
 require(frame.get("x", -1) >= 0, "clicked Waterfall card must be horizontally visible")
-require(frame.get("x", 0) + frame.get("width", 0) <= root.get("waterfallVisibleWidth", 0) + 1, "clicked card must fit in visible Waterfall width")
+require(
+    frame.get("x", 0) + frame.get("width", 0)
+    <= root.get("waterfallVisibleWidth", 0) + selected_card_visual_overflow_tolerance,
+    "clicked card must fit in visible Waterfall width"
+)
 
 print(json.dumps({
     "quickSwitchVisible": report.get("quickSwitchVisible"),
@@ -297,7 +327,9 @@
     "lastActivationResult": report.get("lastActivationResult"),
     "waterfallScrollOffset": root.get("waterfallScrollOffset"),
     "hoveredSpaceID": root.get("hoveredSpaceID"),
-    "hoveredSpaceLabel": hovered_segments[0].get("label")
+    "windowHoverAssociatedSpaceID": root.get("windowHoverAssociatedSpaceID"),
+    "hoverTargetKind": root.get("hoverTargetKind"),
+    "activeSpaceFocusID": root.get("activeSpaceFocusID")
 }, indent=2, ensure_ascii=False))
 PY
 }
@@ -309,9 +341,11 @@
 "$APP/Contents/MacOS/Aligner" \
   --round0-skip-permissions \
   --round01-open-quick-switch \
+  --round01-waterfall-view-mode=vertical \
   --round01-fixture-app-count="$FIXTURE_APP_COUNT" \
   --round01-fixture-windows-per-app="$FIXTURE_WINDOWS_PER_APP" \
   --round01-disable-screenshot-refresh \
+  --round01-debug-window-activation \
   --round01-debug-mouse-sequence="$APP_ONLY_MOUSE_SEQUENCE" \
   --round01-quick-switch-report="$APP_ONLY_REPORT" &
 
@@ -324,9 +358,9 @@
 }
 trap cleanup EXIT
 
-wait_for_visible_loaded_report "$APP_ONLY_REPORT"
+wait_for_committed_hidden_report "$APP_ONLY_REPORT"
 assert_app_only_report
-wait_for_window_logic "$WINDOW_WAIT" --expect-quick-switch >&2
+wait_for_window_logic "$WINDOW_WAIT" --expect-no-quick-switch >&2
 kill "$APP_PID" 2>/dev/null || true
 wait "$APP_PID" 2>/dev/null || true
 stop_current_aligner
@@ -334,6 +368,7 @@
 "$APP/Contents/MacOS/Aligner" \
   --round0-skip-permissions \
   --round01-open-quick-switch \
+  --round01-waterfall-view-mode=vertical \
   --round01-fixture-app-count="$FIXTURE_APP_COUNT" \
   --round01-fixture-windows-per-app="$FIXTURE_WINDOWS_PER_APP" \
   --round01-disable-screenshot-refresh \

--
Gitblit v1.9.3