Ariver
2026-06-13 bedb145ee1413482763707fe73787b622cb52cbf
Fix Finder tab space activation
4 files modified
2 files added
1091 ■■■■■ changed files
C1.source/Resources/Aligner-Info.plist 4 ●●●● patch | view | raw | blame | history
C1.source/Sources/Aligner/Diagnostics/Round1SnapshotDump.swift 12 ●●●●● patch | view | raw | blame | history
C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift 324 ●●●●● patch | view | raw | blame | history
C1.source/Sources/AlignerCore/Windows/FinderTabSpaceAttributionPolicy.swift 143 ●●●●● patch | view | raw | blame | history
C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift 156 ●●●●● patch | view | raw | blame | history
C3.tools/round1-finder-tabs-live-qa.sh 452 ●●●●● patch | view | raw | blame | history
C1.source/Resources/Aligner-Info.plist
@@ -17,9 +17,9 @@
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>0.0.63</string>
    <string>0.0.64</string>
    <key>CFBundleVersion</key>
    <string>20260613.1401</string>
    <string>20260613.1606</string>
    <key>LSMinimumSystemVersion</key>
    <string>26.0</string>
    <key>NSHighResolutionCapable</key>
C1.source/Sources/Aligner/Diagnostics/Round1SnapshotDump.swift
@@ -89,6 +89,7 @@
            "isMinimized": window.isMinimized,
            "isFullscreen": window.isFullscreen,
            "isGhost": window.isGhost,
            "frame": frameDictionary(window.frame) as Any,
            "spaceIDs": window.spaceIDs,
            "app": appDictionary(window.app)
        ] as [String: Any]
@@ -98,6 +99,17 @@
        return result
    }
    private static func frameDictionary(_ frame: CGRect?) -> Any {
        guard let frame else { return NSNull() }
        return [
            "x": frame.origin.x,
            "y": frame.origin.y,
            "width": frame.size.width,
            "height": frame.size.height
        ]
    }
    private static func appDictionary(_ app: AlignerApp) -> [String: Any] {
        let pathSummary = DevelopmentDiagnostics.pathSummary(app.executablePath)
        var result = [
C1.source/Sources/Aligner/Infrastructure/Windows/CGWindowAXWindowService.swift
@@ -162,9 +162,10 @@
        let privateActivationOutcome = activateViaPrivateWindowServerAPI(window)
        let didPrivatelyActivate = privateActivationOutcome?.succeeded == true
        let currentAXMetadata = AXWindowMetadataReader.metadata(appCategorizer: appCategorizer)
        let axWindow = axWindow(
            for: window,
            in: AXWindowMetadataReader.metadata(appCategorizer: appCategorizer),
            in: currentAXMetadata,
            operation: "windowActivation",
            matchAttempt: "initial"
        )
@@ -188,6 +189,20 @@
            "spaceFocusError": spaceFocusOutcome?.error
        ])
        guard let axWindow else {
            if let finderTabActivated = activateFinderTabPageIfNeeded(
                window: window,
                axMetadata: currentAXMetadata,
                operation: "windowActivation",
                reason: "axMissing"
            ) {
                DevelopmentDiagnostics.log("windowActivation.activate.finderTabResult", [
                    "windowID": window.id,
                    "pid": window.app.processIdentifier,
                    "activated": finderTabActivated
                ])
                return finderTabActivated ? .activated : .activationFailed
            }
            let activated = activateApplication(for: window)
            DevelopmentDiagnostics.log("windowActivation.activate.axMissing", [
                "windowID": window.id,
@@ -393,6 +408,21 @@
            return nil
        }
        if let finderTabActivated = activateFinderTabPageIfNeeded(
            window: window,
            axMetadata: AXWindowMetadataReader.metadata(appCategorizer: appCategorizer),
            operation: "windowClose",
            reason: reason
        ) {
            guard finderTabActivated else {
                DevelopmentDiagnostics.log("windowClose.commandW.finderTabActivationFailed", [
                    "windowID": window.id,
                    "pid": processIdentifier,
                    "reason": reason
                ])
                return .failed("finderTabActivationFailed")
            }
        } else {
        guard let activationOutcome = activateViaPrivateWindowServerAPI(window),
              activationOutcome.succeeded
        else {
@@ -402,6 +432,7 @@
                "reason": reason
            ])
            return nil
            }
        }
        Thread.sleep(forTimeInterval: 0.08)
@@ -564,6 +595,271 @@
                && metadata.subrole == .standard
        }
        return finderCandidates.count == 1 ? finderCandidates[0] : nil
    }
    private func activateFinderTabPageIfNeeded(
        window: AlignerWindow,
        axMetadata: [AXWindowMetadata],
        operation: String,
        reason: String
    ) -> Bool? {
        guard isFinderCGOnlyPageCandidate(window),
              let processIdentifier = window.app.processIdentifier
        else {
            return nil
        }
        guard let host = finderTabHostAXWindow(for: window, in: axMetadata) else {
            DevelopmentDiagnostics.log("\(operation).finderTab.hostMissing", [
                "windowID": window.id,
                "pid": processIdentifier,
                "reason": reason,
                "spaceIDs": window.spaceIDs
            ])
            return false
        }
        let hostPrivateActivationSucceeded: Bool
        if let hostWindowID = host.windowID,
           let privateActivationBridge {
            hostPrivateActivationSucceeded = privateActivationBridge.activate(
                processIdentifier: processIdentifier,
                windowID: hostWindowID
            ).succeeded
        } else {
            hostPrivateActivationSucceeded = false
        }
        let applicationActivated = activateApplication(processIdentifier: processIdentifier)
        let focusBeforeResult = focusWindowResult(host.element, processIdentifier: processIdentifier)
        let raiseBeforeResult = raiseWindowResult(host.element)
        let selectedTab = selectFinderTab(window, in: host)
        Thread.sleep(forTimeInterval: 0.05)
        let focusAfterResult = focusWindowResult(host.element, processIdentifier: processIdentifier)
        let raiseAfterResult = raiseWindowResult(host.element)
        let didFocusOrRaise = focusBeforeResult.success
            || raiseBeforeResult.success
            || focusAfterResult.success
            || raiseAfterResult.success
        let activated = selectedTab
            && (hostPrivateActivationSucceeded || applicationActivated || didFocusOrRaise)
        DevelopmentDiagnostics.log("\(operation).finderTab.result", [
            "windowID": window.id,
            "pid": processIdentifier,
            "reason": reason,
            "hostWindowID": host.windowID,
            "hostTitleHash": DevelopmentDiagnostics.stableFingerprint(host.title),
            "hostTitleLength": host.title?.count,
            "hostPrivateActivated": hostPrivateActivationSucceeded,
            "applicationActivated": applicationActivated,
            "selectedTab": selectedTab,
            "focusBeforeAXError": String(describing: focusBeforeResult.error),
            "raiseBeforeAXError": String(describing: raiseBeforeResult.error),
            "focusAfterAXError": String(describing: focusAfterResult.error),
            "raiseAfterAXError": String(describing: raiseAfterResult.error),
            "activated": activated
        ])
        return activated
    }
    private func isFinderCGOnlyPageCandidate(_ window: AlignerWindow) -> Bool {
        window.identifierSource == .cgWindow
            && window.app.bundleIdentifier == "com.apple.finder"
            && !window.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
    }
    private func finderTabHostAXWindow(
        for window: AlignerWindow,
        in axMetadata: [AXWindowMetadata]
    ) -> AXWindowMetadata? {
        guard let processIdentifier = window.app.processIdentifier else { return nil }
        let candidates = axMetadata.filter { metadata in
            metadata.processIdentifier == processIdentifier
                && metadata.subrole == .standard
                && metadata.frame?.isEmpty == false
        }
        guard !candidates.isEmpty else { return nil }
        let targetSpaceIDs = Set(window.spaceIDs)
        let candidateIDs = candidates.compactMap(\.windowID)
        let candidateSpacesByID = targetSpaceIDs.isEmpty ? [:] : spaceIDsByWindowIDProvider(candidateIDs)
        let spaceCompatibleCandidates = targetSpaceIDs.isEmpty
            ? candidates
            : candidates.filter { metadata in
                guard let windowID = metadata.windowID else { return false }
                return !Set(candidateSpacesByID[windowID] ?? []).isDisjoint(with: targetSpaceIDs)
            }
        let hostCandidates = spaceCompatibleCandidates.isEmpty ? candidates : spaceCompatibleCandidates
        let targetFrame = cgWindowFrame(for: window) ?? window.frame
        let scoredHosts = hostCandidates.compactMap { metadata -> (metadata: AXWindowMetadata, score: CGFloat)? in
            guard let score = frameOverlapScore(targetFrame, metadata.frame),
                  score >= 0.85
            else {
                return nil
            }
            return (metadata, score)
        }
        .sorted { lhs, rhs in
            if lhs.score != rhs.score {
                return lhs.score > rhs.score
            }
            return (lhs.metadata.windowID ?? UInt32.max) < (rhs.metadata.windowID ?? UInt32.max)
        }
        if let best = scoredHosts.first {
            if scoredHosts.count == 1 {
                return best.metadata
            }
            let secondBest = scoredHosts[1]
            if best.score - secondBest.score >= 0.05 {
                return best.metadata
            }
        }
        return hostCandidates.count == 1 ? hostCandidates[0] : nil
    }
    private func selectFinderTab(
        _ window: AlignerWindow,
        in host: AXWindowMetadata
    ) -> Bool {
        let normalizedTargetTitle = normalizedWindowTitle(window.title)
        guard !normalizedTargetTitle.isEmpty else { return false }
        if normalizedWindowTitle(host.title ?? "") == normalizedTargetTitle {
            return true
        }
        guard let tabButton = finderTabButton(
            matchingNormalizedTitle: normalizedTargetTitle,
            in: host.element
        ) else {
            DevelopmentDiagnostics.log("windowActivation.finderTab.tabButtonMissing", [
                "windowID": window.id,
                "hostWindowID": host.windowID,
                "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
                "targetTitleLength": window.title.count
            ])
            return false
        }
        let tabButtonRole = axStringAttribute(kAXRoleAttribute as String, for: tabButton)
        let tabButtonSubrole = axStringAttribute(kAXSubroleAttribute as String, for: tabButton)
        let pressResult = AXUIElementPerformAction(tabButton, kAXPressAction as CFString)
        DevelopmentDiagnostics.log("windowActivation.finderTab.pressTab", [
            "windowID": window.id,
            "hostWindowID": host.windowID,
            "tabButtonRole": tabButtonRole,
            "tabButtonSubrole": tabButtonSubrole,
            "axError": String(describing: pressResult)
        ])
        guard pressResult == .success else { return false }
        for _ in 0..<10 {
            Thread.sleep(forTimeInterval: 0.04)
            let selectedTitle = normalizedWindowTitle(
                axStringAttribute(kAXTitleAttribute as String, for: host.element) ?? ""
            )
            if selectedTitle == normalizedTargetTitle {
                return true
            }
        }
        let currentHostTitle = axStringAttribute(kAXTitleAttribute as String, for: host.element) ?? ""
        DevelopmentDiagnostics.log("windowActivation.finderTab.selectionVerificationFailed", [
            "windowID": window.id,
            "hostWindowID": host.windowID,
            "targetTitleHash": DevelopmentDiagnostics.stableFingerprint(window.title),
            "targetTitleLength": window.title.count,
            "currentHostTitleHash": DevelopmentDiagnostics.stableFingerprint(currentHostTitle),
            "currentHostTitleLength": currentHostTitle.count
        ])
        return false
    }
    private func finderTabButton(
        matchingNormalizedTitle targetTitle: String,
        in root: AXUIElement
    ) -> AXUIElement? {
        var visitedCount = 0
        func search(_ element: AXUIElement, depth: Int, insideTabGroup: Bool) -> AXUIElement? {
            visitedCount += 1
            guard visitedCount <= 240, depth <= 9 else { return nil }
            let role = axStringAttribute(kAXRoleAttribute as String, for: element)
            let subrole = axStringAttribute(kAXSubroleAttribute as String, for: element)
            let title = axStringAttribute(kAXTitleAttribute as String, for: element)
                ?? axStringAttribute(kAXDescriptionAttribute as String, for: element)
                ?? axStringAttribute(kAXValueAttribute as String, for: element)
            let isTabGroup = role == "AXTabGroup"
            let isTabControl = subrole == "AXTabButton"
                || (insideTabGroup && (role == kAXRadioButtonRole as String || role == kAXButtonRole as String))
            if normalizedWindowTitle(title ?? "") == targetTitle,
               isTabControl {
                return element
            }
            guard isTabGroup || insideTabGroup || depth < 7 else { return nil }
            for child in axChildren(of: element) {
                if let match = search(child, depth: depth + 1, insideTabGroup: insideTabGroup || isTabGroup) {
                    return match
                }
            }
            return nil
        }
        return search(root, depth: 0, insideTabGroup: false)
    }
    private func axChildren(of element: AXUIElement) -> [AXUIElement] {
        var value: CFTypeRef?
        guard AXUIElementCopyAttributeValue(element, kAXChildrenAttribute as CFString, &value) == .success,
              let children = value as? [AXUIElement]
        else {
            return []
        }
        return children
    }
    private func axStringAttribute(_ attribute: String, for element: AXUIElement) -> String? {
        var value: CFTypeRef?
        guard AXUIElementCopyAttributeValue(element, attribute as CFString, &value) == .success,
              let value
        else {
            return nil
        }
        return value as? String
    }
    private func frameOverlapScore(_ lhs: CGRect?, _ rhs: CGRect?) -> CGFloat? {
        guard let lhs,
              let rhs,
              !lhs.isEmpty,
              !rhs.isEmpty
        else {
            return nil
        }
        let intersection = lhs.intersection(rhs)
        guard !intersection.isNull,
              !intersection.isEmpty
        else {
            return nil
        }
        let denominator = min(lhs.width * lhs.height, rhs.width * rhs.height)
        guard denominator > 0 else { return nil }
        return (intersection.width * intersection.height) / denominator
    }
    private func cgWindowFingerprint(for window: AlignerWindow) -> AXWindowFingerprint? {
@@ -895,7 +1191,31 @@
        }
        restorableAXWindowsByID = nextRestorableAXWindowsByID
        return cgRecords + axOnlyRecords
        let records = cgRecords + axOnlyRecords
        let attributedRecords = FinderTabSpaceAttributionPolicy.attributedRecords(records)
        DevelopmentDiagnostics.log("windowEnumeration.finderTabSpaceAttribution", [
            "finderNoSpaceCandidateCount": records.filter { record in
                record.app.bundleIdentifier == "com.apple.finder"
                    && record.identifierSource == .cgWindow
                    && record.spaceIDs.isEmpty
                    && !record.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
                    && record.frame?.isEmpty == false
            }.count,
            "finderFullscreenHostCount": records.filter { record in
                record.app.bundleIdentifier == "com.apple.finder"
                    && record.isFullscreen
                    && !record.spaceIDs.isEmpty
                    && record.subrole == .standard
                    && record.frame?.isEmpty == false
            }.count,
            "attributedCount": zip(records, attributedRecords).filter { before, after in
                before.spaceIDs.isEmpty && !after.spaceIDs.isEmpty
            }.count,
            "attributedWindowIDs": zip(records, attributedRecords).compactMap { before, after in
                before.spaceIDs.isEmpty && !after.spaceIDs.isEmpty ? after.id : nil
            }
        ])
        return attributedRecords
    }
    private func app(
C1.source/Sources/AlignerCore/Windows/FinderTabSpaceAttributionPolicy.swift
New file
@@ -0,0 +1,143 @@
import CoreGraphics
import Foundation
public enum FinderTabSpaceAttributionPolicy {
    private static let finderBundleIdentifier = "com.apple.finder"
    private static let minimumOverlapRatio: CGFloat = 0.85
    private static let minimumBestScoreGap: CGFloat = 0.05
    public static func attributedRecords(_ records: [WindowEnumerationRecord]) -> [WindowEnumerationRecord] {
        let hosts = records.filter(isFinderFullscreenHost)
        guard !hosts.isEmpty else { return records }
        return records.map { record in
            guard isFinderTabCandidate(record),
                  let host = bestHost(for: record, in: hosts)
            else {
                return record
            }
            return copy(
                record,
                isFullscreen: true,
                spaceIDs: host.spaceIDs
            )
        }
    }
    private static func isFinderTabCandidate(_ record: WindowEnumerationRecord) -> Bool {
        WindowEnumerationPolicy.shouldInclude(record)
            && record.identifierSource == .cgWindow
            && record.app.bundleIdentifier == finderBundleIdentifier
            && record.spaceIDs.isEmpty
            && !record.isMinimized
            && !record.title.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
            && record.frame?.isEmpty == false
    }
    private static func isFinderFullscreenHost(_ record: WindowEnumerationRecord) -> Bool {
        WindowEnumerationPolicy.shouldInclude(record)
            && record.app.bundleIdentifier == finderBundleIdentifier
            && record.isFullscreen
            && !record.spaceIDs.isEmpty
            && record.subrole == .standard
            && record.frame?.isEmpty == false
    }
    private static func bestHost(
        for candidate: WindowEnumerationRecord,
        in hosts: [WindowEnumerationRecord]
    ) -> WindowEnumerationRecord? {
        let compatibleHosts = hosts.filter { host in
            sameProcess(candidate, host)
        }
        let scoredHosts = compatibleHosts.compactMap { host -> (record: WindowEnumerationRecord, score: CGFloat)? in
            guard let score = overlapScore(candidate.frame, host.frame),
                  score >= minimumOverlapRatio
            else {
                return nil
            }
            return (host, score)
        }
        .sorted { lhs, rhs in
            if lhs.score != rhs.score {
                return lhs.score > rhs.score
            }
            return lhs.record.id < rhs.record.id
        }
        guard let best = scoredHosts.first else { return nil }
        if scoredHosts.count == 1 {
            return best.record
        }
        let sameSpaceCompetitors = scoredHosts.filter { $0.record.spaceIDs == best.record.spaceIDs }
        if sameSpaceCompetitors.count == scoredHosts.count {
            return best.record
        }
        let secondBest = scoredHosts[1]
        return best.score - secondBest.score >= minimumBestScoreGap ? best.record : nil
    }
    private static func sameProcess(
        _ lhs: WindowEnumerationRecord,
        _ rhs: WindowEnumerationRecord
    ) -> Bool {
        guard let lhsPID = lhs.app.processIdentifier,
              let rhsPID = rhs.app.processIdentifier
        else {
            return false
        }
        return lhsPID == rhsPID
    }
    private static func overlapScore(_ lhs: CGRect?, _ rhs: CGRect?) -> CGFloat? {
        guard let lhs,
              let rhs,
              !lhs.isEmpty,
              !rhs.isEmpty
        else {
            return nil
        }
        let intersection = lhs.intersection(rhs)
        guard !intersection.isNull,
              !intersection.isEmpty
        else {
            return nil
        }
        let denominator = min(lhs.width * lhs.height, rhs.width * rhs.height)
        guard denominator > 0 else { return nil }
        return (intersection.width * intersection.height) / denominator
    }
    private static func copy(
        _ record: WindowEnumerationRecord,
        isFullscreen: Bool,
        spaceIDs: [UInt64]
    ) -> WindowEnumerationRecord {
        WindowEnumerationRecord(
            id: record.id,
            app: record.app,
            activationPolicy: record.activationPolicy,
            title: record.title,
            identifierSource: record.identifierSource,
            size: record.size,
            frame: record.frame,
            subrole: record.subrole,
            isMinimized: record.isMinimized,
            isFullscreen: isFullscreen,
            isGhost: record.isGhost,
            isDesktopElement: record.isDesktopElement,
            isSystemCritical: record.isSystemCritical,
            isInteractable: record.isInteractable,
            hasAXBacking: record.hasAXBacking,
            isOnscreen: record.isOnscreen,
            spaceIDs: spaceIDs
        )
    }
}
C1.source/Tests/AlignerCoreTests/AlignerCoreTests.swift
@@ -377,6 +377,162 @@
        XCTAssertNil(WindowEnumerationPolicy.window(from: tinyRecord))
    }
    func testFinderTabSpaceAttributionInheritsFullscreenHostSpaceForMatchingFrame() {
        let finderApp = AlignerApp(
            bundleIdentifier: "com.apple.finder",
            name: "访达",
            category: .finder,
            processIdentifier: 74678
        )
        let frame = CGRect(x: 0, y: 0, width: 960, height: 1080)
        let host = WindowEnumerationRecord(
            id: 33112,
            app: finderApp,
            title: "下载",
            size: frame.size,
            frame: frame,
            subrole: .standard,
            isFullscreen: true,
            hasAXBacking: true,
            spaceIDs: [843]
        )
        let inactiveTab = WindowEnumerationRecord(
            id: 42286,
            app: finderApp,
            title: "Appcache",
            size: frame.size,
            frame: frame,
            subrole: .standard,
            hasAXBacking: false,
            isOnscreen: false
        )
        let attributed = FinderTabSpaceAttributionPolicy.attributedRecords([inactiveTab, host])
        XCTAssertEqual(attributed[0].spaceIDs, [843])
        XCTAssertTrue(attributed[0].isFullscreen)
    }
    func testFinderTabSpaceAttributionDoesNotGuessNoSpaceWindowsWithoutHostOverlap() {
        let finderApp = AlignerApp(
            bundleIdentifier: "com.apple.finder",
            name: "访达",
            category: .finder,
            processIdentifier: 74678
        )
        let otherApp = AlignerApp(
            bundleIdentifier: "com.example.Other",
            name: "Other",
            category: .generic,
            processIdentifier: 74678
        )
        let hostFrame = CGRect(x: 0, y: 0, width: 960, height: 1080)
        let farFrame = CGRect(x: 1200, y: 0, width: 500, height: 600)
        let host = WindowEnumerationRecord(
            id: 33112,
            app: finderApp,
            title: "下载",
            size: hostFrame.size,
            frame: hostFrame,
            subrole: .standard,
            isFullscreen: true,
            hasAXBacking: true,
            spaceIDs: [843]
        )
        let farFinderTab = WindowEnumerationRecord(
            id: 42286,
            app: finderApp,
            title: "Appcache",
            size: farFrame.size,
            frame: farFrame,
            subrole: .standard,
            hasAXBacking: false,
            isOnscreen: false
        )
        let nonFinderWindow = WindowEnumerationRecord(
            id: 50222,
            app: otherApp,
            title: "Appcache",
            size: hostFrame.size,
            frame: hostFrame,
            subrole: .standard,
            hasAXBacking: false,
            isOnscreen: false
        )
        let attributed = FinderTabSpaceAttributionPolicy.attributedRecords([farFinderTab, nonFinderWindow, host])
        XCTAssertEqual(attributed[0].spaceIDs, [])
        XCTAssertFalse(attributed[0].isFullscreen)
        XCTAssertEqual(attributed[1].spaceIDs, [])
        XCTAssertFalse(attributed[1].isFullscreen)
    }
    func testFinderTabSpaceAttributionHandlesFinderSplitViewHostsByFrame() {
        let finderApp = AlignerApp(
            bundleIdentifier: "com.apple.finder",
            name: "访达",
            category: .finder,
            processIdentifier: 74678
        )
        let leftFrame = CGRect(x: 0, y: 0, width: 960, height: 1080)
        let rightFrame = CGRect(x: 960, y: 0, width: 960, height: 1080)
        let leftHost = WindowEnumerationRecord(
            id: 33112,
            app: finderApp,
            title: "下载",
            size: leftFrame.size,
            frame: leftFrame,
            subrole: .standard,
            isFullscreen: true,
            hasAXBacking: true,
            spaceIDs: [843]
        )
        let rightHost = WindowEnumerationRecord(
            id: 41557,
            app: finderApp,
            title: "应用程序",
            size: rightFrame.size,
            frame: rightFrame,
            subrole: .standard,
            isFullscreen: true,
            hasAXBacking: true,
            spaceIDs: [843]
        )
        let leftInactiveTab = WindowEnumerationRecord(
            id: 42286,
            app: finderApp,
            title: "Appcache",
            size: leftFrame.size,
            frame: leftFrame,
            subrole: .standard,
            hasAXBacking: false,
            isOnscreen: false
        )
        let rightInactiveTab = WindowEnumerationRecord(
            id: 61385,
            app: finderApp,
            title: "build",
            size: rightFrame.size,
            frame: rightFrame,
            subrole: .standard,
            hasAXBacking: false,
            isOnscreen: false
        )
        let attributed = FinderTabSpaceAttributionPolicy.attributedRecords([
            leftInactiveTab,
            rightInactiveTab,
            leftHost,
            rightHost
        ])
        XCTAssertEqual(attributed[0].spaceIDs, [843])
        XCTAssertEqual(attributed[1].spaceIDs, [843])
        XCTAssertTrue(attributed[0].isFullscreen)
        XCTAssertTrue(attributed[1].isFullscreen)
    }
    func testWindowEnumerationPolicyKeepsMinimizedAndFullscreenCGOnlyOffscreenWindows() {
        let minimized = makeWindowRecord(
            title: "Minimized Document.md",
C3.tools/round1-finder-tabs-live-qa.sh
New file
@@ -0,0 +1,452 @@
#!/bin/bash
# Round01 real-desktop QA for Finder tabs/pages. It verifies that CG-only
# Finder pages inherit the high-confidence fullscreen Space from their visible
# host, and that clicking such a card actually selects the matching Finder tab
# instead of only reporting a WindowServer activation success.
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"
RUN_ID="$(date +%Y%m%d_%H%M%S)"
REPORT_DIR="$BUILD_REPORT_ROOT/round01-finder-tabs-live-$RUN_ID"
DEV_LOG="$HOME/Library/Logs/Aligner/aligner-dev.log"
REPORT_WAIT="${ALIGNER_ROUND1_FINDER_TABS_REPORT_WAIT:-7.0}"
fail() {
  echo "Round01 Finder tabs live 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"
}
dev_log_size() {
  if [ -f "$DEV_LOG" ]; then
    stat -f%z "$DEV_LOG"
  else
    echo 0
  fi
}
extract_dev_log_since() {
  local offset="$1"
  local output="$2"
  if [ ! -f "$DEV_LOG" ]; then
    : >"$output"
    return
  fi
  dd if="$DEV_LOG" bs=1 skip="$offset" 2>/dev/null >"$output" || : >"$output"
}
wait_for_report() {
  local report="$1"
  local mode="$2"
  /usr/bin/python3 - "$report" "$REPORT_WAIT" "$mode" <<'PY'
import json
import sys
import time
path = sys.argv[1]
timeout = float(sys.argv[2])
mode = sys.argv[3]
deadline = time.monotonic() + timeout
last_report = None
def ready(report):
    if report.get("snapshotLoaded") is not True:
        return False
    if mode == "loaded":
        return True
    if mode == "activated":
        return (
            report.get("quickSwitchVisible") is False
            and report.get("lastActivationResult") is not None
        )
    return False
while time.monotonic() < deadline:
    try:
        with open(path, "r", encoding="utf-8") as file:
            report = json.load(file)
        last_report = report
        if ready(report):
            sys.exit(0)
    except FileNotFoundError:
        pass
    except json.JSONDecodeError:
        pass
    time.sleep(0.2)
if last_report is not None:
    print(json.dumps(last_report, indent=2, ensure_ascii=False), file=sys.stderr)
print(f"Finder tabs report {path} did not reach mode={mode} within {timeout:.1f}s", file=sys.stderr)
sys.exit(1)
PY
}
run_snapshot_dump() {
  local snapshot="$1"
  local stderr_log="$2"
  stop_current_aligner
  ALIGNER_DIAGNOSTICS_INCLUDE_SENSITIVE=1 \
    "$APP/Contents/MacOS/Aligner" \
    --round0-skip-permissions \
    --round01-dump-window-snapshot \
    --round01-dump-window-snapshot-pretty >"$snapshot" 2>"$stderr_log"
}
run_report() {
  local report="$1"
  local app_log="$2"
  stop_current_aligner
  rm -f "$report"
  ALIGNER_DIAGNOSTICS_INCLUDE_SENSITIVE=1 \
    "$APP/Contents/MacOS/Aligner" \
    --round0-skip-permissions \
    --round01-open-quick-switch \
    --round01-disable-screenshot-refresh \
    --round01-quick-switch-auto-hide-after=0.8 \
    --round01-quick-switch-quit-after=1.3 \
    --round01-quick-switch-report="$report" >"$app_log" 2>&1
  wait_for_report "$report" "loaded"
}
run_click() {
  local app_group_index="$1"
  local window_index="$2"
  local report="$3"
  local app_log="$4"
  stop_current_aligner
  rm -f "$report"
  ALIGNER_DIAGNOSTICS_INCLUDE_SENSITIVE=1 \
    "$APP/Contents/MacOS/Aligner" \
    --round0-skip-permissions \
    --round01-open-quick-switch \
    --round01-disable-screenshot-refresh \
    --round01-debug-mouse-sequence="click-card:$app_group_index:$window_index" \
    --round01-quick-switch-quit-after=1.8 \
    --round01-quick-switch-report="$report" >"$app_log" 2>&1
  wait_for_report "$report" "activated"
}
focused_finder_window_report() {
  local output="$1"
  swift - "$output" <<'SWIFT'
import AppKit
import ApplicationServices
import Foundation
func fail(_ message: String, code: Int32 = 2) -> Never {
    fputs(message + "\n", stderr)
    exit(code)
}
func jsonString(_ value: String) -> String {
    let data = try! JSONSerialization.data(withJSONObject: ["value": value], options: [])
    let text = String(data: data, encoding: .utf8)!
    let prefix = "{\"value\":\""
    let suffix = "\"}"
    return String(text.dropFirst(prefix.count).dropLast(suffix.count))
}
func stableFingerprint(_ text: String) -> String {
    var hash: UInt64 = 0xcbf29ce484222325
    for byte in text.utf8 {
        hash ^= UInt64(byte)
        hash = hash &* 0x100000001b3
    }
    return String(format: "%016llx", hash)
}
func title(of element: AXUIElement) -> String? {
    var value: CFTypeRef?
    guard AXUIElementCopyAttributeValue(element, kAXTitleAttribute as CFString, &value) == .success else {
        return nil
    }
    return value as? String
}
func focusedWindowID(_ element: AXUIElement) -> UInt32? {
    var value: CFTypeRef?
    if AXUIElementCopyAttributeValue(element, "AXWindowNumber" as CFString, &value) == .success,
       let number = value as? NSNumber {
        return number.uint32Value
    }
    return nil
}
let outputPath = CommandLine.arguments[1]
guard let finder = NSWorkspace.shared.runningApplications.first(where: { $0.bundleIdentifier == "com.apple.finder" }) else {
    fail("Finder is not running")
}
let appElement = AXUIElementCreateApplication(finder.processIdentifier)
var windowValue: CFTypeRef?
var axError = AXUIElementCopyAttributeValue(appElement, kAXFocusedWindowAttribute as CFString, &windowValue)
if axError != .success || windowValue == nil || CFGetTypeID(windowValue!) != AXUIElementGetTypeID() {
    axError = AXUIElementCopyAttributeValue(appElement, kAXMainWindowAttribute as CFString, &windowValue)
}
guard axError == .success,
      let rawWindow = windowValue,
      CFGetTypeID(rawWindow) == AXUIElementGetTypeID()
else {
    fail("Finder focused/main window is unavailable: \(axError)")
}
let window = rawWindow as! AXUIElement
let windowTitle = title(of: window) ?? ""
let output = """
{
  "bundleIdentifier": "com.apple.finder",
  "pid": \(finder.processIdentifier),
  "focusedWindowID": \(focusedWindowID(window).map(String.init) ?? "null"),
  "title": "\(jsonString(windowTitle))",
  "titleLength": \(windowTitle.count),
  "titleHash": "\(stableFingerprint(windowTitle))"
}
"""
try output.write(toFile: outputPath, atomically: true, encoding: .utf8)
SWIFT
}
extract_attributed_ids() {
  local log_file="$1"
  /usr/bin/python3 - "$log_file" <<'PY'
import re
import sys
ids = []
for line in open(sys.argv[1], "r", encoding="utf-8", errors="replace"):
    if "event=windowEnumeration.finderTabSpaceAttribution" not in line:
        continue
    match = re.search(r'attributedWindowIDs="?(\[[^\]"]*\])"?', line)
    if not match:
        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
}
select_target() {
  local snapshot="$1"
  local report="$2"
  local attributed_ids_csv="$3"
  local output="$4"
  /usr/bin/python3 - "$snapshot" "$report" "$attributed_ids_csv" "$output" <<'PY'
import json
import sys
snapshot_path, report_path, ids_csv, output_path = sys.argv[1:5]
attributed_ids = {int(value) for value in ids_csv.split(",") if value}
with open(snapshot_path, "r", encoding="utf-8") as file:
    snapshot = json.load(file)
with open(report_path, "r", encoding="utf-8") as file:
    report = json.load(file)
def require(condition, message):
    if not condition:
        print(message, file=sys.stderr)
        sys.exit(4)
snapshot_windows = {window.get("id"): window for window in snapshot.get("windows", [])}
finder_attributed = [
    window for window_id, window in snapshot_windows.items()
    if window_id in attributed_ids
    and 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")
root = report.get("rootView", {})
cards = []
for column in root.get("waterfallColumns", []):
    if column.get("bundleIdentifier") != "com.apple.finder":
        continue
    for card in column.get("cards", []):
        if card.get("windowID") not in attributed_ids:
            continue
        visible = card.get("visibleFrame") or {}
        if visible.get("width", 0) <= 1 or visible.get("height", 0) <= 1:
            continue
        title = card.get("title") or snapshot_windows.get(card.get("windowID"), {}).get("title") or ""
        if not title.strip():
            continue
        cards.append((column, card, title))
require(cards, "Quick Switch report must expose at least one visible attributed Finder 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 title_counts[item[2]] == 1 else 1,
    item[1].get("globalIndex", 10**9),
    item[1].get("windowID", 10**9),
))
column, card, title = cards[0]
target = {
    "windowID": card["windowID"],
    "appGroupIndex": column["appGroupIndex"],
    "windowIndex": card["windowIndex"],
    "primarySpaceID": card.get("primarySpaceID"),
    "title": title,
    "titleLength": len(title),
    "titleHash": card.get("titleHash") or snapshot_windows.get(card.get("windowID"), {}).get("titleHash"),
    "visibleFrame": card.get("visibleFrame"),
}
with open(output_path, "w", encoding="utf-8") as file:
    json.dump(target, file, indent=2, ensure_ascii=False)
print(f"TARGET_WINDOW_ID={target['windowID']}")
print(f"APP_GROUP_INDEX={target['appGroupIndex']}")
print(f"WINDOW_INDEX={target['windowIndex']}")
print(f"TARGET_SPACE_ID={target['primarySpaceID']}")
PY
}
assert_click_report() {
  local report="$1"
  local target="$2"
  /usr/bin/python3 - "$report" "$target" <<'PY'
import json
import sys
with open(sys.argv[1], "r", encoding="utf-8") as file:
    report = json.load(file)
with open(sys.argv[2], "r", encoding="utf-8") as file:
    target = json.load(file)
def require(condition, message):
    if not condition:
        print(message, file=sys.stderr)
        print(json.dumps({
            "targetWindowID": target.get("windowID"),
            "lastCommittedWindowID": report.get("lastCommittedWindowID"),
            "lastActivationWindowID": report.get("lastActivationWindowID"),
            "lastActivationResult": report.get("lastActivationResult"),
            "lastActivationError": report.get("lastActivationError"),
            "quickSwitchVisible": report.get("quickSwitchVisible"),
        }, indent=2, ensure_ascii=False), file=sys.stderr)
        sys.exit(5)
require(report.get("lastCommittedWindowID") == target["windowID"], "commit must target the clicked Finder card")
require(report.get("lastActivationWindowID") == target["windowID"], "activation must receive exact Finder tab/page windowID")
require(report.get("lastActivationResult") == "activated", "activation result must be activated")
require(report.get("quickSwitchVisible") is False, "Quick Switch must close after click activation")
PY
}
assert_focused_finder_title() {
  local target="$1"
  local focused="$2"
  /usr/bin/python3 - "$target" "$focused" <<'PY'
import json
import sys
with open(sys.argv[1], "r", encoding="utf-8") as file:
    target = json.load(file)
with open(sys.argv[2], "r", encoding="utf-8") as file:
    focused = json.load(file)
target_title = target.get("title", "").strip()
focused_title = focused.get("title", "").strip()
if target_title != focused_title:
    print("Focused Finder window title must match clicked tab/page title", file=sys.stderr)
    print(json.dumps({
        "targetWindowID": target.get("windowID"),
        "targetTitleHash": target.get("titleHash"),
        "targetTitleLength": target.get("titleLength"),
        "focusedWindowID": focused.get("focusedWindowID"),
        "focusedTitleHash": focused.get("titleHash"),
        "focusedTitleLength": focused.get("titleLength"),
    }, indent=2, ensure_ascii=False), file=sys.stderr)
    sys.exit(6)
print(json.dumps({
    "case": "finderTabRealActivation",
    "targetWindowID": target.get("windowID"),
    "targetSpaceID": target.get("primarySpaceID"),
    "targetTitleHash": target.get("titleHash"),
    "targetTitleLength": target.get("titleLength"),
    "focusedWindowID": focused.get("focusedWindowID"),
    "focusedTitleHash": focused.get("titleHash"),
    "focusedTitleLength": focused.get("titleLength"),
}, indent=2, ensure_ascii=False))
PY
}
mkdir -p "$REPORT_DIR"
stop_current_aligner
"$SCRIPT_DIR/package-app.sh" >&2
SNAPSHOT_JSON="$REPORT_DIR/snapshot.json"
SNAPSHOT_STDERR="$REPORT_DIR/snapshot.stderr.log"
SNAPSHOT_DEV_LOG="$REPORT_DIR/snapshot-dev.log"
INITIAL_REPORT="$REPORT_DIR/initial-report.json"
INITIAL_APP_LOG="$REPORT_DIR/initial-app.log"
CLICK_REPORT="$REPORT_DIR/click-report.json"
CLICK_APP_LOG="$REPORT_DIR/click-app.log"
CLICK_DEV_LOG="$REPORT_DIR/click-dev.log"
TARGET_JSON="$REPORT_DIR/target.json"
FOCUSED_JSON="$REPORT_DIR/focused-finder.json"
SNAPSHOT_LOG_OFFSET="$(dev_log_size)"
run_snapshot_dump "$SNAPSHOT_JSON" "$SNAPSHOT_STDERR"
sleep 0.4
extract_dev_log_since "$SNAPSHOT_LOG_OFFSET" "$SNAPSHOT_DEV_LOG"
ATTRIBUTED_IDS="$(extract_attributed_ids "$SNAPSHOT_DEV_LOG")"
run_report "$INITIAL_REPORT" "$INITIAL_APP_LOG"
eval "$(select_target "$SNAPSHOT_JSON" "$INITIAL_REPORT" "$ATTRIBUTED_IDS" "$TARGET_JSON")"
CLICK_LOG_OFFSET="$(dev_log_size)"
run_click "$APP_GROUP_INDEX" "$WINDOW_INDEX" "$CLICK_REPORT" "$CLICK_APP_LOG"
sleep 0.8
extract_dev_log_since "$CLICK_LOG_OFFSET" "$CLICK_DEV_LOG"
focused_finder_window_report "$FOCUSED_JSON"
assert_click_report "$CLICK_REPORT" "$TARGET_JSON"
assert_focused_finder_title "$TARGET_JSON" "$FOCUSED_JSON"
stop_current_aligner
cat <<EOF
Round01 Finder tabs live QA passed
Log directory: $REPORT_DIR
Covered:
- Finder CG-only tab/page records inherit a high-confidence fullscreen Space.
- Quick Switch click targets the exact Finder tab/page windowID.
- Finder focused window title matches the clicked card after activation.
EOF