#!/bin/bash # Round01 minimized-window QA. It launches a temporary AppKit helper, lets that # helper miniaturize its own window, then verifies the real snapshot sees it. 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" SOURCE_ROOT="$OUTPUT_ROOT/C1.source" APP="$BUILD_CURRENT_APP" REPORT="$BUILD_REPORT_ROOT/round01-minimized-window-qa-snapshot.json" SAMPLE_TITLE="Aligner Round01 Minimized QA Sample" HELPER_HOLD_SECONDS="${ALIGNER_ROUND1_MINIMIZED_HELPER_HOLD_SECONDS:-20.0}" READY_ATTEMPTS="${ALIGNER_ROUND1_MINIMIZED_READY_ATTEMPTS:-16}" READY_INTERVAL="${ALIGNER_ROUND1_MINIMIZED_READY_INTERVAL:-0.5}" HELPER_PID="" cleanup() { if [[ -n "$HELPER_PID" ]] && kill -0 "$HELPER_PID" 2>/dev/null; then kill "$HELPER_PID" 2>/dev/null || true wait "$HELPER_PID" 2>/dev/null || true fi } trap cleanup EXIT cd "$SOURCE_ROOT" swift build >&2 "$SCRIPT_DIR/package-app.sh" >&2 swift "$SCRIPT_DIR/round1-minimized-window-helper.swift" "$HELPER_HOLD_SECONDS" & HELPER_PID=$! snapshot() { "$APP/Contents/MacOS/Aligner" \ --round0-skip-permissions \ --round01-dump-window-snapshot \ --round01-dump-window-snapshot-pretty > "$REPORT" } snapshot_has_minimized_sample() { /usr/bin/python3 - "$REPORT" "$SAMPLE_TITLE" <<'PY' import json import sys report_path, sample_title = sys.argv[1:3] def stable_fingerprint(value): hash_value = 0xCBF29CE484222325 for byte in (value or "").encode("utf-8"): hash_value ^= byte hash_value = (hash_value * 0x100000001B3) & 0xFFFFFFFFFFFFFFFF return f"{hash_value:016x}" sample_title_hash = stable_fingerprint(sample_title) try: with open(report_path, "r", encoding="utf-8") as handle: data = json.load(handle) except Exception: sys.exit(1) windows = data.get("windows", []) sample = [ window for window in windows if window.get("titleHash") == sample_title_hash and window.get("isMinimized") is True ] sys.exit(0 if sample else 1) PY } for _ in $(seq 1 "$READY_ATTEMPTS"); do snapshot if snapshot_has_minimized_sample; then break fi sleep "$READY_INTERVAL" done /usr/bin/python3 - "$REPORT" "$SAMPLE_TITLE" <<'PY' import json import sys report_path, sample_title = sys.argv[1:3] def stable_fingerprint(value): hash_value = 0xCBF29CE484222325 for byte in (value or "").encode("utf-8"): hash_value ^= byte hash_value = (hash_value * 0x100000001B3) & 0xFFFFFFFFFFFFFFFF return f"{hash_value:016x}" sample_title_hash = stable_fingerprint(sample_title) with open(report_path, "r", encoding="utf-8") as handle: data = json.load(handle) windows = data.get("windows", []) minimized = [window for window in windows if window.get("isMinimized") is True] sample_minimized = [ window for window in minimized if window.get("titleHash") == sample_title_hash ] sample_synthetic = [ window for window in sample_minimized if window.get("identifierSource") == "syntheticAX" and window.get("isSyntheticWindowID") is True ] sample_cg = [ window for window in sample_minimized if window.get("identifierSource") == "cgWindow" and window.get("isSyntheticWindowID") is False ] synthetic = [ window for window in minimized if window.get("identifierSource") == "syntheticAX" or window.get("isSyntheticWindowID") is True ] missing_identifier_source = [window.get("id") for window in windows if "identifierSource" not in window] if missing_identifier_source: print(f"Missing identifierSource on windows: {missing_identifier_source}", file=sys.stderr) sys.exit(1) if not sample_minimized: print( f"Expected minimized helper window '{sample_title}' in snapshot; " f"minimizedWindowCount={len(minimized)}", file=sys.stderr, ) sys.exit(1) if not sample_synthetic and not sample_cg: print( f"Expected minimized helper window '{sample_title}' to use cgWindow or syntheticAX; " f"sampleMinimized={sample_minimized}", file=sys.stderr, ) sys.exit(1) summary = { "windowCount": len(windows), "minimizedWindowCount": len(minimized), "sampleMinimizedCount": len(sample_minimized), "syntheticAXCount": len(synthetic), "sampleWindows": [ { "id": window.get("id"), "titleHash": window.get("titleHash"), "titleLength": window.get("titleLength"), "identifierSource": window.get("identifierSource"), "isSyntheticWindowID": window.get("isSyntheticWindowID"), } for window in sample_minimized ], } print(json.dumps(summary, ensure_ascii=False, indent=2, sort_keys=True)) PY