From a2293c5609ee7b5b7bbfce3b4c0dc7ae365e31ff Mon Sep 17 00:00:00 2001
From: Ariver <shanghai3168@gmail.com>
Date: Sat, 13 Jun 2026 20:52:55 +0800
Subject: [PATCH] Fix Finder split view tab activation regression

---
 C3.tools/round1-finder-tabs-live-qa.sh                                         |   63 ++++++++++++---
 C1.source/Resources/Aligner-Info.plist                                         |    4 
 C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift |  131 ++++++++++++++------------------
 3 files changed, 112 insertions(+), 86 deletions(-)

diff --git a/C1.source/Resources/Aligner-Info.plist b/C1.source/Resources/Aligner-Info.plist
index 6118a38..03cfa10 100644
--- a/C1.source/Resources/Aligner-Info.plist
+++ b/C1.source/Resources/Aligner-Info.plist
@@ -17,9 +17,9 @@
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
-    <string>0.0.65</string>
+    <string>0.0.66</string>
 	<key>CFBundleVersion</key>
-    <string>20260613.1843</string>
+    <string>20260613.2043</string>
 	<key>LSMinimumSystemVersion</key>
 	<string>26.0</string>
 	<key>NSHighResolutionCapable</key>
diff --git a/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift b/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
index e03dddb..21abec8 100644
--- a/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
+++ b/C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
@@ -129,8 +129,7 @@
             : .activationFailed
     }
 
-    func activate(window requestedWindow: AlignerWindow) throws -> WindowActivationResult {
-        let window = refreshedFinderWindowForPreciseAction(requestedWindow, operation: "windowActivation")
+    func activate(window: AlignerWindow) throws -> WindowActivationResult {
         DevelopmentDiagnostics.log("windowActivation.activate.start", [
             "windowID": window.id,
             "identifierSource": String(describing: window.identifierSource),
@@ -280,8 +279,7 @@
             : .appActivatedOnly
     }
 
-    func close(window requestedWindow: AlignerWindow) throws -> WindowCloseResult {
-        let window = refreshedFinderWindowForPreciseAction(requestedWindow, operation: "windowClose")
+    func close(window: AlignerWindow) throws -> WindowCloseResult {
         DevelopmentDiagnostics.log("windowClose.window.start", [
             "windowID": window.id,
             "identifierSource": String(describing: window.identifierSource),
@@ -358,59 +356,6 @@
             processIdentifier: matchedAXWindow.processIdentifier,
             attempt: "initial"
         )
-    }
-
-    private func refreshedFinderWindowForPreciseAction(
-        _ window: AlignerWindow,
-        operation: String
-    ) -> AlignerWindow {
-        guard isFinderCGOnlyPageCandidate(window) else { return window }
-
-        guard let refreshedWindow = try? allWindows().first(where: { refreshed in
-            refreshed.id == window.id
-                && refreshed.identifierSource == window.identifierSource
-                && refreshed.app.bundleIdentifier == window.app.bundleIdentifier
-        }) else {
-            DevelopmentDiagnostics.log("\(operation).finderRefresh.missing", [
-                "windowID": window.id,
-                "spaceIDCount": window.spaceIDs.count,
-                "hasFrame": window.frame != nil
-            ])
-            return window
-        }
-
-        let mergedWindow = AlignerWindow(
-            id: window.id,
-            app: window.app.processIdentifier == nil ? refreshedWindow.app : window.app,
-            title: window.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
-                ? refreshedWindow.title
-                : window.title,
-            identifierSource: window.identifierSource,
-            isMinimized: window.isMinimized || refreshedWindow.isMinimized,
-            isFullscreen: window.isFullscreen || refreshedWindow.isFullscreen,
-            isGhost: window.isGhost,
-            frame: window.frame ?? refreshedWindow.frame,
-            spaceIDs: window.spaceIDs.isEmpty ? refreshedWindow.spaceIDs : window.spaceIDs
-        )
-
-        if mergedWindow.spaceIDs != window.spaceIDs
-            || mergedWindow.isFullscreen != window.isFullscreen
-            || (window.frame == nil && refreshedWindow.frame != nil) {
-            DevelopmentDiagnostics.log("\(operation).finderRefresh.merged", [
-                "windowID": window.id,
-                "originalSpaceIDCount": window.spaceIDs.count,
-                "refreshedSpaceIDCount": refreshedWindow.spaceIDs.count,
-                "mergedSpaceIDCount": mergedWindow.spaceIDs.count,
-                "originalIsFullscreen": window.isFullscreen,
-                "refreshedIsFullscreen": refreshedWindow.isFullscreen,
-                "mergedIsFullscreen": mergedWindow.isFullscreen,
-                "originalHasFrame": window.frame != nil,
-                "refreshedHasFrame": refreshedWindow.frame != nil,
-                "mergedHasFrame": mergedWindow.frame != nil
-            ])
-        }
-
-        return mergedWindow
     }
 
     private func closeButton(for axWindow: AXWindowMetadata) -> AXUIElement? {
@@ -676,6 +621,28 @@
         }
 
         guard let host = finderTabHostAXWindow(for: window, in: axMetadata) else {
+            let normalizedTargetTitle = normalizedWindowTitle(window.title)
+            let applicationActivated = activateApplication(processIdentifier: processIdentifier)
+            let selectedViaWindowMenu = !normalizedTargetTitle.isEmpty
+                && selectFinderWindowMenuItem(
+                    processIdentifier: processIdentifier,
+                    window: window,
+                    normalizedTargetTitle: normalizedTargetTitle
+                )
+            DevelopmentDiagnostics.log("\(operation).finderTab.hostlessWindowMenuResult", [
+                "windowID": window.id,
+                "pid": processIdentifier,
+                "reason": reason,
+                "applicationActivated": applicationActivated,
+                "selectedViaWindowMenu": selectedViaWindowMenu,
+                "spaceIDs": window.spaceIDs,
+                "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
+                "targetTitleLength": window.title.count
+            ])
+            if selectedViaWindowMenu {
+                return true
+            }
+
             DevelopmentDiagnostics.log("\(operation).finderTab.hostMissing", [
                 "windowID": window.id,
                 "pid": processIdentifier,
@@ -772,21 +739,9 @@
             finderHostCanRepresentTarget(window, in: metadata)
         }
 
-        let hostCandidates: [AXWindowMetadata]
-        if targetSpaceIDs.isEmpty {
-            guard !selectableHostCandidates.isEmpty else {
-                DevelopmentDiagnostics.log("windowActivation.finderTab.noSelectableHost", [
-                    "windowID": window.id,
-                    "candidateCount": candidates.count,
-                    "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
-                    "targetTitleLength": window.title.count
-                ])
-                return nil
-            }
-            hostCandidates = selectableHostCandidates
-        } else {
-            hostCandidates = selectableHostCandidates.isEmpty ? spaceScopedCandidates : selectableHostCandidates
-        }
+        let hostCandidates = selectableHostCandidates.isEmpty
+            ? spaceScopedCandidates
+            : selectableHostCandidates
 
         let targetFrame = matchingFrame(for: window)
         let scoredHosts = hostCandidates.compactMap { metadata -> (metadata: AXWindowMetadata, score: CGFloat)? in
@@ -807,16 +762,48 @@
 
         if let best = scoredHosts.first {
             if scoredHosts.count == 1 {
+                if selectableHostCandidates.isEmpty {
+                    DevelopmentDiagnostics.log("windowActivation.finderTab.frameInferredHost", [
+                        "windowID": window.id,
+                        "hostWindowID": best.metadata.windowID,
+                        "score": Double(best.score),
+                        "spaceIDCount": targetSpaceIDs.count,
+                        "candidateCount": hostCandidates.count,
+                        "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
+                        "targetTitleLength": window.title.count
+                    ])
+                }
                 return best.metadata
             }
 
             let secondBest = scoredHosts[1]
             if best.score - secondBest.score >= 0.05 {
+                if selectableHostCandidates.isEmpty {
+                    DevelopmentDiagnostics.log("windowActivation.finderTab.frameInferredHost", [
+                        "windowID": window.id,
+                        "hostWindowID": best.metadata.windowID,
+                        "score": Double(best.score),
+                        "secondBestScore": Double(secondBest.score),
+                        "spaceIDCount": targetSpaceIDs.count,
+                        "candidateCount": hostCandidates.count,
+                        "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
+                        "targetTitleLength": window.title.count
+                    ])
+                }
                 return best.metadata
             }
         }
 
         if hostCandidates.count == 1 {
+            if selectableHostCandidates.isEmpty {
+                DevelopmentDiagnostics.log("windowActivation.finderTab.singleFrameHostFallback", [
+                    "windowID": window.id,
+                    "hostWindowID": hostCandidates[0].windowID,
+                    "spaceIDCount": targetSpaceIDs.count,
+                    "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
+                    "targetTitleLength": window.title.count
+                ])
+            }
             return hostCandidates[0]
         }
 
diff --git a/C3.tools/round1-finder-tabs-live-qa.sh b/C3.tools/round1-finder-tabs-live-qa.sh
index 1773b03..343a215 100755
--- a/C3.tools/round1-finder-tabs-live-qa.sh
+++ b/C3.tools/round1-finder-tabs-live-qa.sh
@@ -259,10 +259,6 @@
         continue
     ids = [int(value) for value in re.findall(r"\d+", match.group(1))]
 
-if not ids:
-    print("No attributed Finder tab/page windowIDs found in this QA run", file=sys.stderr)
-    sys.exit(3)
-
 print(",".join(str(value) for value in sorted(set(ids))))
 PY
 }
@@ -291,15 +287,13 @@
         sys.exit(4)
 
 snapshot_windows = {window.get("id"): window for window in snapshot.get("windows", [])}
-finder_attributed = [
+finder_candidates = [
     window for window_id, window in snapshot_windows.items()
-    if window_id in attributed_ids
-    and window.get("app", {}).get("bundleIdentifier") == "com.apple.finder"
+    if window.get("app", {}).get("bundleIdentifier") == "com.apple.finder"
     and window.get("identifierSource") == "cgWindow"
-    and window.get("spaceIDs")
     and window.get("title")
 ]
-require(finder_attributed, "snapshot must contain at least one attributed Finder CG-only tab/page")
+require(finder_candidates, "snapshot must contain at least one Finder CG-only tab/page")
 
 root = report.get("rootView", {})
 cards = []
@@ -307,7 +301,10 @@
     if column.get("bundleIdentifier") != "com.apple.finder":
         continue
     for card in column.get("cards", []):
-        if card.get("windowID") not in attributed_ids:
+        window = snapshot_windows.get(card.get("windowID"), {})
+        if window.get("app", {}).get("bundleIdentifier") != "com.apple.finder":
+            continue
+        if window.get("identifierSource") != "cgWindow":
             continue
         visible = card.get("visibleFrame") or {}
         if visible.get("width", 0) <= 1 or visible.get("height", 0) <= 1:
@@ -317,13 +314,14 @@
             continue
         cards.append((column, card, title))
 
-require(cards, "Quick Switch report must expose at least one visible attributed Finder tab/page card")
+require(cards, "Quick Switch report must expose at least one visible Finder CG tab/page card")
 
 title_counts = {}
 for _, _, title in cards:
     title_counts[title] = title_counts.get(title, 0) + 1
 
 cards.sort(key=lambda item: (
+    0 if not (snapshot_windows.get(item[1].get("windowID"), {}).get("spaceIDs") or []) else 1,
     0 if title_counts[item[2]] == 1 else 1,
     item[1].get("globalIndex", 10**9),
     item[1].get("windowID", 10**9),
@@ -340,6 +338,8 @@
         "appGroupIndex": column["appGroupIndex"],
         "windowIndex": card["windowIndex"],
         "primarySpaceID": card.get("primarySpaceID"),
+        "hasAttributedSpace": window_id in attributed_ids,
+        "snapshotSpaceIDs": snapshot_windows.get(window_id, {}).get("spaceIDs") or [],
         "title": title,
         "titleLength": len(title),
         "titleHash": card.get("titleHash") or snapshot_windows.get(window_id, {}).get("titleHash"),
@@ -451,6 +451,43 @@
 PY
 }
 
+assert_no_finder_activation_failure_log() {
+  local log_file="$1"
+  local target="$2"
+  /usr/bin/python3 - "$log_file" "$target" <<'PY'
+import json
+import sys
+
+log_path, target_path = sys.argv[1:3]
+with open(target_path, "r", encoding="utf-8") as file:
+    target = json.load(file)
+
+window_id = str(target.get("windowID"))
+bad_lines = []
+for line in open(log_path, "r", encoding="utf-8", errors="replace"):
+    if f"windowID={window_id}" not in line:
+        continue
+    if "event=windowActivation.finderTab.noSelectableHost" in line:
+        bad_lines.append(line.strip())
+    elif "event=windowActivation.finderTab.hostMissing" in line:
+        bad_lines.append(line.strip())
+    elif "event=windowActivation.activate.finderTabResult" in line and "activated=false" in line:
+        bad_lines.append(line.strip())
+    elif "event=quickSwitch.activation.commit.result" in line and "result=activationFailed" in line:
+        bad_lines.append(line.strip())
+
+if bad_lines:
+    print("Finder activation log contains failure markers for clicked target", file=sys.stderr)
+    print(json.dumps({
+        "targetWindowID": target.get("windowID"),
+        "hasAttributedSpace": target.get("hasAttributedSpace"),
+        "snapshotSpaceIDs": target.get("snapshotSpaceIDs"),
+        "lines": bad_lines[-8:],
+    }, indent=2, ensure_ascii=False), file=sys.stderr)
+    sys.exit(7)
+PY
+}
+
 mkdir -p "$REPORT_DIR"
 stop_current_aligner
 "$SCRIPT_DIR/package-app.sh" >&2
@@ -487,6 +524,7 @@
 
   assert_click_report "$CLICK_REPORT" "$TARGET_JSON"
   assert_focused_finder_title "$TARGET_JSON" "$FOCUSED_JSON"
+  assert_no_finder_activation_failure_log "$CLICK_DEV_LOG" "$TARGET_JSON"
 done
 
 stop_current_aligner
@@ -495,8 +533,9 @@
 Round01 Finder tabs live QA passed
 Log directory: $REPORT_DIR
 Covered:
-- Finder CG-only tab/page records inherit a high-confidence fullscreen Space.
+- Finder CG-only tab/page records are clicked even when Space attribution is unavailable.
 - Quick Switch clicks target exact Finder tab/page windowIDs.
 - Finder focused window title matches each clicked card after activation.
+- Finder activation logs contain no hostMissing/noSelectableHost/activationFailed for clicked targets.
 - Multiple Finder tab/page targets are exercised in one run to catch intermittent host mismatch.
 EOF

--
Gitblit v1.9.3