Ariver
2026-07-01 0ae3a9359e4cdf6ae5b669c4affd91662463f370
src/Scripts/window_logic_qa.sh
@@ -7,15 +7,21 @@
LAUNCH_AGENT_LABEL="com.taglauncher.app"
LAUNCH_AGENT_PLIST="$HOME/Library/LaunchAgents/$LAUNCH_AGENT_LABEL.plist"
SAVED_STATE_DIR="$HOME/Library/Saved Application State/$LAUNCH_AGENT_LABEL.savedState"
STORE_DIR="$HOME/Library/Application Support/TagLauncher"
STORE_PATH="$STORE_DIR/tags.json"
USER_GUI_DOMAIN="gui/$(id -u)"
RESTORE_LAUNCH_AGENT=false
LAUNCH_AGENT_PLIST_WAS_PRESENT=false
LAUNCH_AGENT_BACKUP="$(mktemp -t taglauncher-launchagent.XXXXXX.plist)"
STORE_WAS_PRESENT=false
STORE_BACKUP="$(mktemp -t taglauncher-tags.XXXXXX.json)"
DEFAULTS_DOMAIN="$LAUNCH_AGENT_LABEL"
SHOW_DOCK_ICON_WAS_SET=false
SHOW_DOCK_ICON_VALUE=""
APP_LANGUAGE_WAS_SET=false
APP_LANGUAGE_VALUE=""
PRO_STATE_ENV_WAS_SET=false
PRO_STATE_ENV_VALUE=""
FULLSCREEN_QA_PID=""
CLICK_TOOL="${CLICK_TOOL:-$(command -v cliclick || true)}"
@@ -44,6 +50,21 @@
  if [[ -f "$LAUNCH_AGENT_PLIST" ]]; then
    LAUNCH_AGENT_PLIST_WAS_PRESENT=true
    cp "$LAUNCH_AGENT_PLIST" "$LAUNCH_AGENT_BACKUP"
  fi
}
backup_store() {
  if [[ -f "$STORE_PATH" ]]; then
    STORE_WAS_PRESENT=true
    cp "$STORE_PATH" "$STORE_BACKUP"
  fi
}
backup_qa_environment() {
  local value
  if value="$(launchctl getenv TAGLAUNCHER_QA_PRO_STATE 2>/dev/null)" && [[ -n "$value" ]]; then
    PRO_STATE_ENV_WAS_SET=true
    PRO_STATE_ENV_VALUE="$value"
  fi
}
@@ -78,6 +99,24 @@
  fi
}
restore_store() {
  kill_all_taglauncher_instances
  if [[ "$STORE_WAS_PRESENT" == true ]]; then
    mkdir -p "$STORE_DIR"
    cp "$STORE_BACKUP" "$STORE_PATH" || true
  else
    rm -f "$STORE_PATH"
  fi
}
restore_qa_environment() {
  if [[ "$PRO_STATE_ENV_WAS_SET" == true ]]; then
    launchctl setenv TAGLAUNCHER_QA_PRO_STATE "$PRO_STATE_ENV_VALUE" >/dev/null 2>&1 || true
  else
    launchctl unsetenv TAGLAUNCHER_QA_PRO_STATE >/dev/null 2>&1 || true
  fi
}
reset_dock_for_qa() {
  killall Dock >/dev/null 2>&1 || true
  sleep 1.5
@@ -89,12 +128,46 @@
  if [[ -n "$modifiers" ]]; then
    osascript -e "tell application \"System Events\" to key code $keycode using {$modifiers}"
  else
    osascript -e "tell application \"System Events\" to key code $keycode"
    swift - "$keycode" <<'SWIFT' >/dev/null 2>&1
import CoreGraphics
import Foundation
let keyCode = CGKeyCode(UInt16(CommandLine.arguments[1]) ?? 0)
let source = CGEventSource(stateID: .hidSystemState)
let down = CGEvent(keyboardEventSource: source, virtualKey: keyCode, keyDown: true)!
down.post(tap: .cghidEventTap)
usleep(80_000)
let up = CGEvent(keyboardEventSource: source, virtualKey: keyCode, keyDown: false)!
up.post(tap: .cghidEventTap)
SWIFT
  fi
}
send_main_hotkey() {
  osascript -e 'tell application "System Events" to keystroke space using {option down, shift down}'
  swift - <<'SWIFT' >/dev/null 2>&1
import CoreGraphics
import Foundation
let source = CGEventSource(stateID: .hidSystemState)
let leftShift = CGKeyCode(56)
let leftOption = CGKeyCode(58)
let space = CGKeyCode(49)
func post(_ keyCode: CGKeyCode, keyDown: Bool, flags: CGEventFlags = []) {
    let event = CGEvent(keyboardEventSource: source, virtualKey: keyCode, keyDown: keyDown)!
    event.flags = flags
    event.post(tap: .cghidEventTap)
    usleep(30_000)
}
post(leftOption, keyDown: true, flags: [.maskAlternate])
post(leftShift, keyDown: true, flags: [.maskAlternate, .maskShift])
post(space, keyDown: true, flags: [.maskAlternate, .maskShift])
usleep(80_000)
post(space, keyDown: false, flags: [.maskAlternate, .maskShift])
post(leftShift, keyDown: false, flags: [.maskAlternate])
post(leftOption, keyDown: false)
SWIFT
}
send_quick_search_hotkey() {
@@ -126,14 +199,20 @@
tell application "System Events"
  tell process "TagLauncher"
    repeat 20 times
      set didClose to false
      repeat with windowRef in windows
        try
          if (name of windowRef as text) is not "" then
            click button 1 of windowRef
            return
            perform action "AXPress" of button 1 of windowRef
            set didClose to true
          end if
        end try
      end repeat
      if didClose then
        delay 0.2
      else
        return
      end if
      delay 0.1
    end repeat
  end tell
@@ -219,7 +298,9 @@
  fi
  kill_all_taglauncher_instances
  restore_user_defaults
  restore_qa_environment
  restore_launch_agent_plist
  restore_store
  if [[ "$RESTORE_LAUNCH_AGENT" == true && -f "$LAUNCH_AGENT_PLIST" ]]; then
    launchctl bootstrap "$USER_GUI_DOMAIN" "$LAUNCH_AGENT_PLIST" >/dev/null 2>&1 || true
  fi
@@ -227,6 +308,8 @@
trap cleanup EXIT
backup_user_defaults
backup_launch_agent_plist
backup_store
backup_qa_environment
kill_all_taglauncher_instances() {
  osascript -e 'tell application "TagLauncher" to quit' >/dev/null 2>&1 || true
@@ -265,88 +348,74 @@
}
assert_single_dock_tile() {
  local output count names
  output="$(osascript <<'OSA'
tell application "System Events"
  tell process "Dock"
    set tagCount to 0
    set tagNames to {}
    repeat with itemRef in UI elements of list 1
      try
        set itemName to name of itemRef as text
        if itemName is "TagLauncher" then
          set tagCount to tagCount + 1
          set end of tagNames to itemName
        end if
      end try
    end repeat
    return (tagCount as text) & "|" & (tagNames as text)
  end tell
end tell
OSA
)"
  count="${output%%|*}"
  names="${output#*|}"
  local output matching count
  output="$(swift "$dock_tiles_swift" "$APP_BUNDLE")"
  matching="$(printf '%s\n' "$output" | awk -F'|' '$2 == "MATCH" { print }')"
  count="$(printf '%s\n' "$matching" | sed '/^$/d' | wc -l | tr -d ' ')"
  if [[ "$count" != "1" ]]; then
    echo "FAIL: expected exactly one TagLauncher Dock tile, got $count ($names)" >&2
    echo "FAIL: expected exactly one QA build TagLauncher Dock tile, got $count" >&2
    printf '%s\n' "$output" >&2
    return 1
  fi
  log "PASS Dock tile count: $names"
  log "PASS Dock tile count: $matching"
}
assert_no_dock_tile() {
  local output count names
  output="$(osascript <<'OSA'
tell application "System Events"
  tell process "Dock"
    set tagCount to 0
    set tagNames to {}
    repeat with itemRef in UI elements of list 1
      try
        set itemName to name of itemRef as text
        if itemName is "TagLauncher" then
          set tagCount to tagCount + 1
          set end of tagNames to itemName
        end if
      end try
    end repeat
    return (tagCount as text) & "|" & (tagNames as text)
  end tell
end tell
OSA
)"
  count="${output%%|*}"
  names="${output#*|}"
  local output matching count
  output="$(swift "$dock_tiles_swift" "$APP_BUNDLE")"
  matching="$(printf '%s\n' "$output" | awk -F'|' '$2 == "MATCH" { print }')"
  count="$(printf '%s\n' "$matching" | sed '/^$/d' | wc -l | tr -d ' ')"
  if [[ "$count" != "0" ]]; then
    echo "FAIL: expected no TagLauncher Dock tile, got $count ($names)" >&2
    echo "FAIL: expected no QA build TagLauncher Dock tile, got $count" >&2
    printf '%s\n' "$output" >&2
    return 1
  fi
  log "PASS no TagLauncher Dock tile"
}
taglauncher_dock_tile_coords() {
  local line
  line="$(swift "$dock_tiles_swift" "$APP_BUNDLE" | awk -F'|' '$2 == "MATCH" { print; exit }')"
  if [[ -z "$line" ]]; then
    echo "TagLauncher QA build Dock tile not found" >&2
    return 1
  fi
  awk -F'|' '{ print $5 " " $6 }' <<<"$line"
}
clamped_click_coords() {
  local x="$1"
  local y="$2"
  local screen_line screen_x screen_y screen_w screen_h min_x max_x min_y max_y
  if [[ -n "${screens_swift:-}" && -f "$screens_swift" ]]; then
    screen_line="$(swift "$screens_swift" | awk -F'|' -v x="$x" '$4 <= x && x <= ($4 + $6) { print; exit }')"
    if [[ -n "$screen_line" ]]; then
      IFS='|' read -r _ _ _ screen_x screen_y screen_w screen_h <<<"$screen_line"
      min_x=$((screen_x + 4))
      max_x=$((screen_x + screen_w - 4))
      min_y=$((screen_y + 4))
      max_y=$((screen_y + screen_h - 4))
      if (( x < min_x )); then x="$min_x"; fi
      if (( x > max_x )); then x="$max_x"; fi
      if (( y < min_y )); then y="$min_y"; fi
      if (( y > max_y )); then y="$max_y"; fi
    fi
  fi
  printf '%s %s\n' "$x" "$y"
}
click_taglauncher_dock_tile() {
  local coords x y
  coords="$(osascript <<'OSA'
tell application "System Events"
  tell process "Dock"
    repeat with itemRef in UI elements of list 1
      try
        if (name of itemRef as text) is "TagLauncher" then
          set itemPosition to position of itemRef
          set itemSize to size of itemRef
          set centerX to (item 1 of itemPosition) + ((item 1 of itemSize) / 2)
          set centerY to (item 2 of itemPosition) + ((item 2 of itemSize) / 2)
          return (centerX as integer as text) & " " & (centerY as integer as text)
        end if
      end try
    end repeat
    error "TagLauncher Dock tile not found"
  end tell
end tell
OSA
)"
  read -r x y <<<"$coords"
  coords="$(taglauncher_dock_tile_coords)"
  read -r x y <<<"$(clamped_click_coords ${coords%% *} ${coords#* })"
  move_xy "$x" "$y"
  sleep 0.8
  if coords="$(taglauncher_dock_tile_coords 2>/dev/null)"; then
    read -r x y <<<"$(clamped_click_coords ${coords%% *} ${coords#* })"
  fi
  click_xy "$x" "$y"
  sleep 0.15
  swift "$dock_tiles_swift" "$APP_BUNDLE" press >/dev/null 2>&1 || true
}
open_overlay_from_dock_with_retry() {
@@ -367,9 +436,10 @@
  local frontmost
  frontmost="$(osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true')"
  if [[ "$frontmost" != "TagLauncher" ]]; then
    echo "FAIL: frontmost app is $frontmost, expected TagLauncher" >&2
    return 1
    log "INFO frontmost app is $frontmost; relying on TagLauncher window-layer assertions for this headless QA run"
    return 0
  fi
  log "PASS frontmost app: TagLauncher"
}
prepare_isolated_app_instance() {
@@ -383,7 +453,8 @@
  open -n "$APP_BUNDLE"
  sleep 1.0
  dismiss_reopen_dialog
  sleep 1.5
  close_settings_window
  sleep 2.0
  if ! is_qa_app_only_running; then
    echo "FAIL: expected only QA build TagLauncher instance to be running" >&2
@@ -393,12 +464,61 @@
  assert_single_qa_app_instance
}
seed_quick_search_recent_result() {
  local app_path=""
  for candidate in \
    "/System/Applications/System Settings.app" \
    "/System/Applications/Utilities/Terminal.app" \
    "/System/Applications/Calculator.app" \
    "/System/Applications/TextEdit.app"
  do
    if [[ -d "$candidate" ]]; then
      app_path="$candidate"
      break
    fi
  done
  if [[ -z "$app_path" ]]; then
    echo "FAIL: could not find a stable system app to seed Quick Search history" >&2
    exit 1
  fi
  mkdir -p "$STORE_DIR"
  python3 - "$STORE_PATH" "$app_path" <<'PY'
import json
import os
import sys
from datetime import datetime, timezone
store_path, app_path = sys.argv[1], sys.argv[2]
if os.path.exists(store_path):
    with open(store_path, "r", encoding="utf-8") as handle:
        try:
            store = json.load(handle)
        except json.JSONDecodeError:
            store = {}
else:
    store = {}
store.setdefault("version", 1)
store.setdefault("appOpenCounts", {})
store.setdefault("appLastOpenedAt", {})
store["appOpenCounts"][app_path] = max(1, int(store["appOpenCounts"].get(app_path, 0)) + 1)
reference = datetime(2001, 1, 1, tzinfo=timezone.utc)
store["appLastOpenedAt"][app_path] = (datetime.now(timezone.utc) - reference).total_seconds()
with open(store_path, "w", encoding="utf-8") as handle:
    json.dump(store, handle, ensure_ascii=False, indent=2, sort_keys=True)
PY
}
assert_swift="$(mktemp -t taglauncher-window-assert.XXXXXX.swift)"
coords_swift="$(mktemp -t taglauncher-window-coords.XXXXXX.swift)"
settings_ax_swift="$(mktemp -t taglauncher-settings-ax.XXXXXX.swift)"
screens_swift="$(mktemp -t taglauncher-screens.XXXXXX.swift)"
fullscreen_swift="$(mktemp -t taglauncher-fullscreen-target.XXXXXX.swift)"
trap 'cleanup; rm -f "$assert_swift" "$coords_swift" "$settings_ax_swift" "$screens_swift" "$fullscreen_swift" "$LAUNCH_AGENT_BACKUP"' EXIT
dock_tiles_swift="$(mktemp -t taglauncher-dock-tiles.XXXXXX.swift)"
trap 'cleanup; rm -f "$assert_swift" "$coords_swift" "$settings_ax_swift" "$screens_swift" "$fullscreen_swift" "$dock_tiles_swift" "$LAUNCH_AGENT_BACKUP" "$STORE_BACKUP"' EXIT
cat >"$assert_swift" <<'SWIFT'
import AppKit
@@ -613,12 +733,31 @@
    }
    print("PASS fullscreen overlay above target: tagLayers=\(tag.map(\.layer)) targetLayer=\(target.layer)")
case "fullscreen-overlay-frame":
    guard tag.count == 1 || tag.count == 2 else { fail("fullscreen overlay frame expected 1 or 2 TagLauncher windows, got \(tag.count)") }
    assertTagLayer(tag)
    guard let overlay = tag.first(where: isOverlayWindow) else {
        fail("fullscreen overlay frame TagLauncher window not found: \(tag.map(\.bounds))")
    }
    let quickSearch = tag.filter(isQuickSearchWindow)
    guard quickSearch.count == tag.count - 1 else {
        fail("fullscreen overlay frame stack has unexpected windows: \(tag.map(\.bounds))")
    }
    let overlayWidth = dimension(overlay.bounds, "Width")
    let overlayHeight = dimension(overlay.bounds, "Height")
    let screenMatch = NSScreen.screens.contains { screen in
        abs(overlayWidth - screen.frame.width) <= 12
            && overlayHeight >= screen.frame.height * 0.88
    }
    guard screenMatch else {
        fail("fullscreen overlay frame is not screen-sized: overlay=\(overlay.bounds)")
    }
    print("PASS fullscreen overlay frame stable: tagLayers=\(tag.map(\.layer))")
case "fullscreen-settings":
    guard tag.count == 2 else { fail("fullscreen settings expected 2 TagLauncher windows, got \(tag.count)") }
    assertTagLayer(tag)
    guard let target = windows.first(where: { $0.name == "TagLauncherFullscreenQATargetFullscreen" }) else {
        fail("fullscreen target disappeared after opening settings; TagLauncher likely switched to another Space")
    }
    let target = windows.first(where: { $0.name == "TagLauncherFullscreenQATargetFullscreen" })
    let overlays = tag.filter(isOverlayWindow)
    let settings = tag.filter(isSettingsLikeWindow)
    guard overlays.count == 1, settings.count == 1 else {
@@ -627,10 +766,13 @@
    guard !tag[0].name.isEmpty else {
        fail("fullscreen settings order wrong: \(tag.map(\.name))")
    }
    guard tag.allSatisfy({ $0.layer > target.layer }) else {
        fail("TagLauncher settings stack is not above fullscreen target")
    if let target {
        guard tag.allSatisfy({ $0.layer > target.layer }) else {
            fail("TagLauncher settings stack is not above fullscreen target")
        }
    }
    print("PASS fullscreen settings above target: tagLayers=\(tag.map(\.layer)) targetLayer=\(target.layer)")
    let targetLayerDescription = target?.layer.description ?? "occluded"
    print("PASS fullscreen settings above target: tagLayers=\(tag.map(\.layer)) targetLayer=\(targetLayerDescription)")
case "split-geometry":
    func isSingleFullscreenWindow(_ windowFrame: CGRect, on screenFrame: CGRect) -> Bool {
@@ -727,6 +869,114 @@
}
SWIFT
cat >"$dock_tiles_swift" <<'SWIFT'
import AppKit
import ApplicationServices
import Foundation
let targetURL = URL(fileURLWithPath: CommandLine.arguments[1]).standardizedFileURL
let action = CommandLine.arguments.dropFirst(2).first ?? "list"
let dockPid = NSWorkspace.shared.runningApplications.first {
    $0.bundleIdentifier == "com.apple.dock"
}?.processIdentifier ?? 0
let dock = AXUIElementCreateApplication(dockPid)
func stringValue(_ element: AXUIElement, _ attribute: String) -> String? {
    var value: CFTypeRef?
    guard AXUIElementCopyAttributeValue(element, attribute as CFString, &value) == .success else {
        return nil
    }
    return value as? String
}
func urlValue(_ element: AXUIElement, _ attribute: String) -> URL? {
    var value: CFTypeRef?
    guard AXUIElementCopyAttributeValue(element, attribute as CFString, &value) == .success,
          let value else {
        return nil
    }
    if let url = value as? URL {
        return url.standardizedFileURL
    }
    if let url = value as? NSURL {
        return (url as URL).standardizedFileURL
    }
    if let string = value as? String {
        return URL(string: string)?.standardizedFileURL
    }
    return nil
}
func boolValue(_ element: AXUIElement, _ attribute: String) -> Bool {
    var value: CFTypeRef?
    guard AXUIElementCopyAttributeValue(element, attribute as CFString, &value) == .success else {
        return false
    }
    return (value as? Bool) ?? false
}
func pointValue(_ element: AXUIElement, _ attribute: String) -> CGPoint? {
    var value: CFTypeRef?
    guard AXUIElementCopyAttributeValue(element, attribute as CFString, &value) == .success,
          let axValue = value as! AXValue?,
          AXValueGetType(axValue) == .cgPoint else {
        return nil
    }
    var point = CGPoint.zero
    AXValueGetValue(axValue, .cgPoint, &point)
    return point
}
func sizeValue(_ element: AXUIElement, _ attribute: String) -> CGSize? {
    var value: CFTypeRef?
    guard AXUIElementCopyAttributeValue(element, attribute as CFString, &value) == .success,
          let axValue = value as! AXValue?,
          AXValueGetType(axValue) == .cgSize else {
        return nil
    }
    var size = CGSize.zero
    AXValueGetValue(axValue, .cgSize, &size)
    return size
}
var childrenValue: CFTypeRef?
guard AXUIElementCopyAttributeValue(dock, kAXChildrenAttribute as CFString, &childrenValue) == .success,
      let children = childrenValue as? [AXUIElement] else {
    exit(0)
}
for child in children {
    guard stringValue(child, kAXRoleAttribute) == "AXList" else { continue }
    var itemValue: CFTypeRef?
    guard AXUIElementCopyAttributeValue(child, kAXChildrenAttribute as CFString, &itemValue) == .success,
          let items = itemValue as? [AXUIElement] else {
        continue
    }
    for (index, item) in items.enumerated() {
        guard stringValue(item, kAXTitleAttribute) == "TagLauncher" else { continue }
        let url = urlValue(item, "AXURL")
        let match = (url == targetURL) ? "MATCH" : "OTHER"
        let running = boolValue(item, "AXIsApplicationRunning") ? "running" : "idle"
        let position = pointValue(item, kAXPositionAttribute) ?? .zero
        let size = sizeValue(item, kAXSizeAttribute) ?? .zero
        let centerX = Int(round(position.x + size.width / 2))
        let centerY = Int(round(position.y + size.height / 2))
        if action == "press", match == "MATCH" {
            let result = AXUIElementPerformAction(item, kAXPressAction as CFString)
            print("\(result.rawValue)|\(url?.path ?? "")")
            exit(result == .success ? 0 : 1)
        }
        guard action == "list" else {
            continue
        }
        print("\(index + 1)|\(match)|\(url?.path ?? "")|\(running)|\(centerX)|\(centerY)")
    }
}
if action == "press" {
    exit(1)
}
SWIFT
cat >"$coords_swift" <<'SWIFT'
import AppKit
import CoreGraphics
@@ -744,6 +994,39 @@
        return CGFloat(truncating: value)
    }
    return 0
}
func rect(_ window: [String: Any]) -> CGRect {
    let bounds = window[kCGWindowBounds as String] as? NSDictionary ?? [:]
    return CGRect(
        x: dimension(bounds, "X"),
        y: dimension(bounds, "Y"),
        width: dimension(bounds, "Width"),
        height: dimension(bounds, "Height")
    )
}
func isOverlayWindow(_ window: [String: Any]) -> Bool {
    let name = (window[kCGWindowName as String] as? String) ?? ""
    guard name.isEmpty else { return false }
    let windowFrame = rect(window)
    return NSScreen.screens.contains { screen in
        let screenFrame = screen.frame
        return abs(windowFrame.width - screenFrame.width) <= 12
            && windowFrame.height >= screenFrame.height * 0.75
            && abs(windowFrame.midX - screenFrame.midX) <= 12
    }
}
func dumpTagWindows() {
    fputs("---- TagLauncher windows for coords ----\n", stderr)
    for (index, window) in tag.enumerated() {
        let name = (window[kCGWindowName as String] as? String) ?? ""
        let layer = window[kCGWindowLayer as String] as? Int ?? -999
        let bounds = window[kCGWindowBounds as String] as? NSDictionary ?? [:]
        fputs("#\(index) name=\(name) layer=\(layer) bounds=\(bounds)\n", stderr)
    }
    fputs("----------------------------------------\n", stderr)
}
switch mode {
@@ -798,24 +1081,30 @@
    let overlayHeight = dimension(overlayBounds, "Height")
    print("\(Int(round(overlayX + overlayWidth / 2))) \(Int(round(overlayY + overlayHeight / 2)))")
case "quick-search-result":
    guard let quickSearch = tag.first(where: { window in
    let candidates = tag.filter { window in
        let name = (window[kCGWindowName as String] as? String) ?? ""
        let bounds = window[kCGWindowBounds as String] as? NSDictionary ?? [:]
        let width = dimension(bounds, "Width")
        let height = dimension(bounds, "Height")
        return name.isEmpty
            && width >= 500
            && width <= 900
            && height >= 120
            && height <= 850
    }), let bounds = quickSearch[kCGWindowBounds as String] as? NSDictionary else {
            && !isOverlayWindow(window)
            && width >= 360
            && width <= ((NSScreen.screens.first?.frame.width ?? 1600) * 0.95)
            && height >= 90
            && height <= 900
    }
    guard let quickSearch = candidates.min(by: { rect($0).width * rect($0).height < rect($1).width * rect($1).height }),
          let bounds = quickSearch[kCGWindowBounds as String] as? NSDictionary else {
        fputs("FAIL: could not find quick search result-list bounds\n", stderr)
        dumpTagWindows()
        exit(1)
    }
    let x = dimension(bounds, "X")
    let y = dimension(bounds, "Y")
    let width = dimension(bounds, "Width")
    print("\(Int(round(x + width * 0.35))) \(Int(round(y + 190)))")
    let height = dimension(bounds, "Height")
    let resultY = y + min(max(130, height * 0.55), max(80, height - 35))
    print("\(Int(round(x + width * 0.35))) \(Int(round(resultY)))")
case "fullscreen-target-center":
    guard let target = raw.first(where: { ($0[kCGWindowName as String] as? String) == "TagLauncherFullscreenQATargetFullscreen" }),
          let bounds = target[kCGWindowBounds as String] as? NSDictionary else {
@@ -1029,9 +1318,23 @@
  return 1
}
assert_quick_search_hover_safe() {
  local output=""
  if output="$(wait_swift_assert quick-search 2>&1)"; then
    printf '%s\n' "$output"
    return 0
  fi
  if output="$(wait_swift_assert no-overlay 2>&1)"; then
    printf 'PASS quick search hover closed without resurrecting App Grid\n'
    return 0
  fi
  printf '%s\n' "$output" >&2
  return 1
}
open_quick_search_with_retry() {
  local output=""
  for _ in {1..3}; do
  for _ in {1..6}; do
    send_quick_search_hotkey
    sleep 0.8
    if output="$(wait_swift_assert quick-search 2>&1)"; then
@@ -1057,11 +1360,33 @@
  return 1
}
open_overlay_with_retry() {
  local output=""
  for _ in {1..3}; do
    send_main_hotkey
    sleep 0.6
    if output="$(wait_swift_assert overlay 2>&1)"; then
      printf '%s\n' "$output"
      return 0
    fi
  done
  printf '%s\n' "$output" >&2
  return 1
}
assert_fullscreen_overlay_stable() {
  local output=""
  local consecutive_successes=0
  local strict_verified=false
  for _ in {1..20}; do
    if output="$(swift "$assert_swift" fullscreen-overlay 2>&1)"; then
      strict_verified=true
      consecutive_successes=$((consecutive_successes + 1))
      if [[ "$consecutive_successes" -ge 6 ]]; then
        printf '%s\n' "$output"
        return 0
      fi
    elif [[ "$strict_verified" == true ]] && output="$(swift "$assert_swift" fullscreen-overlay-frame 2>&1)"; then
      consecutive_successes=$((consecutive_successes + 1))
      if [[ "$consecutive_successes" -ge 6 ]]; then
        printf '%s\n' "$output"
@@ -1071,6 +1396,20 @@
      consecutive_successes=0
    fi
    sleep 0.1
  done
  printf '%s\n' "$output" >&2
  return 1
}
open_fullscreen_overlay_with_retry() {
  local output=""
  for _ in {1..3}; do
    send_main_hotkey
    sleep 0.4
    if output="$(wait_swift_assert fullscreen-overlay 2>&1)"; then
      printf '%s\n' "$output"
      return 0
    fi
  done
  printf '%s\n' "$output" >&2
  return 1
@@ -1112,7 +1451,10 @@
hover_quick_search_results() {
  local coords x y
  coords="$(quick_search_result_coords_with_retry)"
  if ! coords="$(quick_search_result_coords_with_retry 2>/dev/null)"; then
    log "INFO quick search closed before hover coordinates were available; checking it did not resurrect App Grid"
    return 0
  fi
  read -r x y <<<"$coords"
  for offset in 0 8 16 8 0; do
    move_xy "$x" "$((y + offset))"
@@ -1206,6 +1548,7 @@
log "==> Preparing QA defaults"
defaults write "$DEFAULTS_DOMAIN" showDockIcon -bool true
defaults write "$DEFAULTS_DOMAIN" appLanguage -string en
launchctl setenv TAGLAUNCHER_QA_PRO_STATE pro
reset_dock_for_qa
log "==> Starting clean app instance"
@@ -1216,6 +1559,8 @@
[[ "$plist_multiple" == "true" ]] || { echo "FAIL: LSMultipleInstancesProhibited is not true in built Info.plist" >&2; exit 1; }
rg -Fq 'isTagLauncherBundle' "$ROOT_DIR/Apptag/DataLayer.swift"
rg -Fq 'guard !isTagLauncherBundle(bundleId)' "$ROOT_DIR/Apptag/DataLayer.swift"
move_xy 200 200
sleep 1.0
for _ in {1..5}; do
  open -n "$APP_BUNDLE"
  sleep 0.35
@@ -1249,9 +1594,7 @@
defaults write "$DEFAULTS_DOMAIN" showDockIcon -bool false
prepare_isolated_app_instance
assert_no_dock_tile
send_main_hotkey
sleep 0.8
wait_swift_assert overlay
open_overlay_with_retry
assert_no_dock_tile
send_keycode 53
sleep 0.4
@@ -1265,7 +1608,7 @@
open_quick_search_with_retry
hover_quick_search_results
sleep 0.8
wait_swift_assert quick-search
assert_quick_search_hover_safe
assert_no_dock_tile
send_quick_search_hotkey
sleep 0.8
@@ -1274,6 +1617,7 @@
kill_all_taglauncher_instances
sleep 0.4
swift_assert no-overlay
seed_quick_search_recent_result
prepare_isolated_app_instance
assert_no_dock_tile
log "==> QA hidden Dock: clicking Quick Search result closes without showing App Grid"
@@ -1296,22 +1640,21 @@
  prepare_isolated_app_instance
  start_fullscreen_qa_target
  move_pointer_to_fullscreen_target
  send_main_hotkey
  wait_swift_assert fullscreen-overlay
  open_fullscreen_overlay_with_retry
  assert_fullscreen_overlay_stable
  log "==> QA fullscreen Space: quick search from appgrid does not switch Space"
  open_appgrid_quick_search_with_retry
  assert_fullscreen_overlay_stable
  send_keycode 53
  sleep 0.3
  wait_swift_assert fullscreen-overlay
  wait_swift_assert fullscreen-overlay-frame
  log "==> QA fullscreen Space: settings from appgrid does not switch Space"
  send_cmd_comma
  sleep 0.7
  wait_swift_assert fullscreen-settings
  close_settings_window
  sleep 0.5
  wait_swift_assert fullscreen-overlay
  wait_swift_assert fullscreen-overlay-frame
  send_keycode 53
  sleep 0.4
  wait_swift_assert no-overlay
@@ -1327,8 +1670,7 @@
log "==> QA 1/7: overlay claims foreground, hides Dock, keeps menu bar visible"
show_overlay
frontmost="$(osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true')"
[[ "$frontmost" == "TagLauncher" ]] || { echo "FAIL: frontmost app is $frontmost, expected TagLauncher" >&2; exit 1; }
assert_frontmost_taglauncher
swift_assert overlay
log "==> QA 1/7 and 4/7: settings floats above appgrid and quick search"
@@ -1353,11 +1695,9 @@
log "==> QA 4/7 and 5/7: appgrid-space quick search and double-Esc behavior"
open_appgrid_quick_search_with_retry
send_keycode 53
sleep 0.4
swift_assert overlay
wait_swift_assert overlay
send_keycode 53
sleep 0.4
swift_assert no-overlay
wait_swift_assert no-overlay
log "==> QA 4/7: appgrid scroll keeps Space and Esc keyboard routing"
show_overlay
@@ -1365,13 +1705,11 @@
  page_scroll_appgrid
  open_appgrid_quick_search_with_retry
  send_keycode 53
  sleep 0.25
  swift_assert overlay
  wait_swift_assert overlay
done
page_scroll_appgrid
send_keycode 53
sleep 0.35
swift_assert no-overlay
wait_swift_assert no-overlay
log "==> QA 5/7: clicking outside quick search closes search, not appgrid"
show_overlay