[CmdletBinding()]
param(
    [ValidateSet('Release', 'DebugAppX')]
    [string]$BuildFlavor = 'Release',

    [ValidateSet('ReadOnly', 'DryRunPlayout', 'FullUiDb', 'ProgramPlaylistDb')]
    [string]$Profile = 'ReadOnly',

    [ValidateSet('All', 'PList', 'GraphE', 'Catalog', 'Screens')]
    [string]$FullUiDbScope = 'All',

    [string]$RecoverNamedPlaylistTitle,

    [ValidateRange(1024, 65535)]
    [int]$Port = 9339,

    [string]$Output,

    [string]$Screenshot,

    [string]$NodePath,

    [ValidateRange(10, 120)]
    [int]$LaunchTimeoutSeconds = 30,

    [ValidateRange(30, 900)]
    [int]$HarnessTimeoutSeconds = 180,

    # The local-settings/import smoke reuses the exact package identity, launch,
    # DryRun and normal-close guards from this script.  Returning after the
    # definitions keeps those guards single-sourced without launching anything.
    [switch]$DefinitionsOnly
)

Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'

Add-Type -TypeDefinition @'
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;

public static class LegacyPackageInputNative
{
    private delegate bool EnumWindowsCallback(IntPtr window, IntPtr parameter);

    [StructLayout(LayoutKind.Sequential)]
    private struct Point
    {
        public int X;
        public int Y;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct Rect
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    private struct ClientGeometry
    {
        public int ScreenLeft;
        public int ScreenTop;
        public int Width;
        public int Height;
        public double CssScaleX;
        public double CssScaleY;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct MibTcpRowOwnerPid
    {
        public uint State;
        public uint LocalAddress;
        public uint LocalPort;
        public uint RemoteAddress;
        public uint RemotePort;
        public uint OwningProcessId;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct MibTcp6RowOwnerPid
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public byte[] LocalAddress;
        public uint LocalScopeId;
        public uint LocalPort;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public byte[] RemoteAddress;
        public uint RemoteScopeId;
        public uint RemotePort;
        public uint State;
        public uint OwningProcessId;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct MouseInput
    {
        public int Dx;
        public int Dy;
        public uint MouseData;
        public uint Flags;
        public uint Time;
        public UIntPtr ExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct KeyboardInput
    {
        public ushort VirtualKey;
        public ushort ScanCode;
        public uint Flags;
        public uint Time;
        public UIntPtr ExtraInfo;
    }

    [StructLayout(LayoutKind.Explicit)]
    private struct InputUnion
    {
        [FieldOffset(0)] public MouseInput Mouse;
        [FieldOffset(0)] public KeyboardInput Keyboard;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct Input
    {
        public uint Type;
        public InputUnion Union;
    }

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    private static extern int GetPackageFullName(
        IntPtr process,
        ref int packageFullNameLength,
        StringBuilder packageFullName);

    [DllImport("kernel32.dll")]
    private static extern uint GetCurrentThreadId();

    [DllImport("iphlpapi.dll", SetLastError = true)]
    private static extern uint GetExtendedTcpTable(
        IntPtr table,
        ref int size,
        bool order,
        int ipVersion,
        int tableClass,
        uint reserved);

    [DllImport("user32.dll")]
    private static extern bool ClientToScreen(IntPtr window, ref Point point);

    [DllImport("user32.dll")]
    private static extern bool EnumWindows(EnumWindowsCallback callback, IntPtr parameter);

    [DllImport("user32.dll")]
    private static extern IntPtr GetWindow(IntPtr window, uint command);

    [DllImport("user32.dll")]
    private static extern bool IsWindow(IntPtr window);

    [DllImport("user32.dll")]
    private static extern bool IsWindowVisible(IntPtr window);

    [DllImport("user32.dll")]
    private static extern bool IsWindowEnabled(IntPtr window);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern int GetWindowText(
        IntPtr window,
        StringBuilder value,
        int maximum);

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    private static extern int GetClassName(
        IntPtr window,
        StringBuilder value,
        int maximum);

    [DllImport("user32.dll")]
    private static extern bool GetCursorPos(out Point point);

    [DllImport("user32.dll")]
    private static extern IntPtr WindowFromPoint(Point point);

    [DllImport("user32.dll")]
    private static extern IntPtr GetAncestor(IntPtr window, uint flags);

    [DllImport("user32.dll")]
    private static extern bool GetClientRect(IntPtr window, out Rect rectangle);

    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")]
    private static extern bool SetForegroundWindow(IntPtr window);

    [DllImport("user32.dll")]
    private static extern bool BringWindowToTop(IntPtr window);

    [DllImport("user32.dll")]
    private static extern IntPtr SetActiveWindow(IntPtr window);

    [DllImport("user32.dll")]
    private static extern bool IsIconic(IntPtr window);

    [DllImport("user32.dll")]
    private static extern uint GetWindowThreadProcessId(IntPtr window, out uint processId);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool AttachThreadInput(uint from, uint to, bool attach);

    [DllImport("user32.dll")]
    private static extern int GetSystemMetrics(int index);

    [DllImport("user32.dll")]
    private static extern uint SendInput(uint count, Input[] inputs, int size);

    [DllImport("user32.dll")]
    private static extern short GetAsyncKeyState(int virtualKey);

    private const int ErrorInsufficientBuffer = 122;
    private const int AddressFamilyInterNetwork = 2;
    private const int AddressFamilyInterNetworkV6 = 23;
    private const int TcpTableOwnerPidAll = 5;
    private const uint GetAncestorRoot = 2;
    private const uint GetWindowOwner = 4;
    private const uint InputMouse = 0;
    private const uint InputKeyboard = 1;
    private const uint MouseMove = 0x0001;
    private const uint MouseLeftDown = 0x0002;
    private const uint MouseLeftUp = 0x0004;
    private const uint MouseMoveNoCoalesce = 0x2000;
    private const uint MouseVirtualDesk = 0x4000;
    private const uint MouseAbsolute = 0x8000;
    private const uint KeyUp = 0x0002;
    private const int VirtualKeyLeftButton = 0x01;
    private const ushort VirtualKeyShift = 0x10;
    private const ushort VirtualKeyHome = 0x24;
    private const ushort VirtualKeyDelete = 0x2E;
    private const ushort VirtualKeyEscape = 0x1B;
    private const ushort VirtualKeyF2 = 0x71;
    private const ushort VirtualKeyF3 = 0x72;
    private const int ClientPixelTolerance = 1;

    public static bool WindowExists(IntPtr window)
    {
        return window != IntPtr.Zero && IsWindow(window);
    }

    public static bool WindowVisible(IntPtr window)
    {
        return WindowExists(window) && IsWindowVisible(window);
    }

    public static bool WindowEnabled(IntPtr window)
    {
        return WindowExists(window) && IsWindowEnabled(window);
    }

    public static int WindowProcessId(IntPtr window)
    {
        uint processId;
        return GetWindowThreadProcessId(window, out processId) == 0
            ? 0 : checked((int)processId);
    }

    public static IntPtr RootWindow(IntPtr window)
    {
        return window == IntPtr.Zero
            ? IntPtr.Zero : GetAncestor(window, GetAncestorRoot);
    }

    public static bool OwnerChainContains(IntPtr window, IntPtr expectedOwner)
    {
        if (window == IntPtr.Zero || expectedOwner == IntPtr.Zero) return false;
        IntPtr expectedRoot = RootWindow(expectedOwner);
        IntPtr current = window;
        for (int depth = 0; depth < 12 && current != IntPtr.Zero; depth++)
        {
            if (current == expectedOwner || RootWindow(current) == expectedRoot) return true;
            current = GetWindow(current, GetWindowOwner);
        }
        return false;
    }

    public static string WindowClassName(IntPtr window)
    {
        StringBuilder value = new StringBuilder(512);
        return window != IntPtr.Zero &&
            GetClassName(window, value, value.Capacity) > 0
                ? value.ToString() : String.Empty;
    }

    public static string WindowTitle(IntPtr window)
    {
        StringBuilder value = new StringBuilder(1024);
        return window != IntPtr.Zero &&
            GetWindowText(window, value, value.Capacity) > 0
                ? value.ToString() : String.Empty;
    }

    public static IntPtr[] VisibleTopLevelWindows()
    {
        List<IntPtr> windows = new List<IntPtr>();
        EnumWindowsCallback callback = delegate(IntPtr window, IntPtr parameter)
        {
            if (window != IntPtr.Zero && IsWindowVisible(window))
            {
                windows.Add(window);
            }
            return true;
        };
        if (!EnumWindows(callback, IntPtr.Zero))
        {
            throw new InvalidOperationException(
                "The native top-level window list is unavailable.");
        }
        return windows.ToArray();
    }

    public static string ReadPackageFullName(IntPtr process)
    {
        int length = 0;
        int result = GetPackageFullName(process, ref length, null);
        if (result != ErrorInsufficientBuffer || length <= 1 || length > 4096)
        {
            throw new InvalidOperationException("The process package identity is unavailable.");
        }

        StringBuilder value = new StringBuilder(length);
        result = GetPackageFullName(process, ref length, value);
        if (result != 0 || value.Length == 0)
        {
            throw new InvalidOperationException("The process package identity could not be read.");
        }
        return value.ToString();
    }

    public static bool HasTcpConnectionForProcessAndPort(int processId, int port)
    {
        if (processId <= 0 || port < 1 || port > 65535)
        {
            throw new InvalidOperationException("The TCP ownership query is invalid.");
        }
        return HasTcp4Connection(processId, port) || HasTcp6Connection(processId, port);
    }

    public static void SendRowHeaderDragAfterThenHome(
        IntPtr window,
        int processId,
        int forbiddenPort,
        double sourceCssX,
        double sourceCssY,
        double targetCssX,
        double targetCssY,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio)
    {
        if (window == IntPtr.Zero || processId <= 0 || forbiddenPort < 1 ||
            forbiddenPort > 65535 || !IsFinitePositive(viewportCssWidth) ||
            !IsFinitePositive(viewportCssHeight) || !IsFinitePositive(devicePixelRatio) ||
            devicePixelRatio < 0.25 || devicePixelRatio > 5.0)
        {
            throw new InvalidOperationException("The Windows input coordinate contract is invalid.");
        }

        AssertKeyReleased(VirtualKeyLeftButton, "The left mouse button was held before input.");
        AssertKeyReleased(VirtualKeyHome, "The Home key was held before input.");
        AssertWindowOwnedByProcess(window, processId);
        AssertNoForbiddenTcp(processId, forbiddenPort);
        AcquireForeground(window, processId, forbiddenPort);
        ClientGeometry baseline = ReadAndAssertClientGeometry(
            window,
            viewportCssWidth,
            viewportCssHeight,
            devicePixelRatio);
        SleepWithWindowGuard(
            400,
            window,
            processId,
            forbiddenPort,
            viewportCssWidth,
            viewportCssHeight,
            devicePixelRatio,
            baseline);

        Point source = CssPointToScreen(
            baseline,
            sourceCssX,
            sourceCssY);
        Point target = CssPointToScreen(
            baseline,
            targetCssX,
            targetCssY);
        if (source.X == target.X && source.Y == target.Y)
        {
            throw new InvalidOperationException("The Windows drag source and target are identical.");
        }
        AssertPointOwnedByWindow(window, source);
        AssertPointOwnedByWindow(window, target);

        bool leftButtonDown = false;
        bool homeKeyDown = false;
        try
        {
            SendMouseMove(source.X, source.Y);
            SleepWithInputGuard(
                200, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline, source, target,
                source, false, false);

            AssertKeyReleased(
                VirtualKeyLeftButton,
                "The left mouse button became held before the mouse press.");
            AssertKeyReleased(
                VirtualKeyHome,
                "The Home key became held before the mouse press.");
            SendMouseButton(MouseLeftDown);
            leftButtonDown = true;
            SleepWithInputGuard(
                100, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline, source, target,
                source, true, false);

            Point threshold = new Point {
                X = source.X + Math.Max(8, (int)Math.Round(12.0 * baseline.CssScaleX)),
                Y = source.Y
            };
            AssertPointOwnedByWindow(window, threshold);
            SendMousePath(
                source, threshold, 6, 35, window, processId, forbiddenPort,
                viewportCssWidth, viewportCssHeight, devicePixelRatio, baseline,
                source, target);
            SendMousePath(
                threshold, target, 24, 35, window, processId, forbiddenPort,
                viewportCssWidth, viewportCssHeight, devicePixelRatio, baseline,
                source, target);

            SendMouseButton(MouseLeftUp);
            leftButtonDown = false;
            SleepWithInputGuard(
                750, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline, source, target,
                target, false, false);

            AssertKeyReleased(
                VirtualKeyHome,
                "The Home key became held before the keyboard input.");
            SendKeyboard(VirtualKeyHome, false);
            homeKeyDown = true;
            SleepWithInputGuard(
                35, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline, source, target,
                target, false, true);
            SendKeyboard(VirtualKeyHome, true);
            homeKeyDown = false;
            SleepWithInputGuard(
                300, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline, source, target,
                target, false, false);
        }
        finally
        {
            Exception cleanupFailure = null;
            if (homeKeyDown)
            {
                try
                {
                    SendKeyboard(VirtualKeyHome, true);
                    homeKeyDown = false;
                }
                catch (Exception error)
                {
                    cleanupFailure = error;
                }
            }
            if (leftButtonDown)
            {
                try
                {
                    SendMouseButton(MouseLeftUp);
                    leftButtonDown = false;
                }
                catch (Exception error)
                {
                    if (cleanupFailure == null)
                    {
                        cleanupFailure = error;
                    }
                }
            }

            try
            {
                AssertKeyReleased(
                    VirtualKeyLeftButton,
                    "The left mouse button remained held after input cleanup.");
            }
            catch (Exception error)
            {
                if (cleanupFailure == null)
                {
                    cleanupFailure = error;
                }
            }
            try
            {
                AssertKeyReleased(
                    VirtualKeyHome,
                    "The Home key remained held after input cleanup.");
            }
            catch (Exception error)
            {
                if (cleanupFailure == null)
                {
                    cleanupFailure = error;
                }
            }
            if (cleanupFailure != null)
            {
                throw new InvalidOperationException(
                    "Injected input cleanup could not prove that all keys were released.",
                    cleanupFailure);
            }
        }
    }

    public static void SendShiftClickRangeThenDeleteAndRestore(
        IntPtr window,
        int processId,
        int forbiddenPort,
        double rangeStartCssX,
        double rangeStartCssY,
        double rangeEndCssX,
        double rangeEndCssY,
        double restoreCssX,
        double restoreCssY,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio)
    {
        if (window == IntPtr.Zero || processId <= 0 || forbiddenPort < 1 ||
            forbiddenPort > 65535 || !IsFinitePositive(viewportCssWidth) ||
            !IsFinitePositive(viewportCssHeight) || !IsFinitePositive(devicePixelRatio) ||
            devicePixelRatio < 0.25 || devicePixelRatio > 5.0)
        {
            throw new InvalidOperationException("The Windows Shift-range input contract is invalid.");
        }

        AssertKeyReleased(VirtualKeyLeftButton, "The left mouse button was held before Shift selection.");
        AssertKeyReleased(VirtualKeyShift, "Shift was held before Shift selection.");
        AssertKeyReleased(VirtualKeyDelete, "Delete was held before Shift selection.");
        AssertWindowOwnedByProcess(window, processId);
        AssertNoForbiddenTcp(processId, forbiddenPort);
        AcquireForeground(window, processId, forbiddenPort);
        ClientGeometry baseline = ReadAndAssertClientGeometry(
            window, viewportCssWidth, viewportCssHeight, devicePixelRatio);
        SleepWithWindowGuard(
            500, window, processId, forbiddenPort, viewportCssWidth,
            viewportCssHeight, devicePixelRatio, baseline);

        Point rangeStart = CssPointToScreen(
            baseline, rangeStartCssX, rangeStartCssY);
        Point rangeEnd = CssPointToScreen(
            baseline, rangeEndCssX, rangeEndCssY);
        Point restore = CssPointToScreen(
            baseline, restoreCssX, restoreCssY);
        if ((rangeStart.X == rangeEnd.X && rangeStart.Y == rangeEnd.Y) ||
            (rangeEnd.X == restore.X && rangeEnd.Y == restore.Y))
        {
            throw new InvalidOperationException("The Windows Shift-range points are not distinct.");
        }
        AssertPointOwnedByWindow(window, rangeStart);
        AssertPointOwnedByWindow(window, rangeEnd);
        AssertPointOwnedByWindow(window, restore);

        bool leftButtonDown = false;
        bool shiftDown = false;
        bool deleteDown = false;
        try
        {
            SendMouseMove(rangeStart.X, rangeStart.Y);
            SleepWithWindowGuard(
                100, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);
            AssertCursorAt(rangeStart);
            SendMouseButton(MouseLeftDown);
            leftButtonDown = true;
            SleepWithWindowGuard(
                45, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);
            AssertCursorAt(rangeStart);
            AssertKeyState(
                VirtualKeyLeftButton,
                true,
                "The left mouse button changed during the range-start click.");
            SendMouseButton(MouseLeftUp);
            leftButtonDown = false;
            SleepWithWindowGuard(
                300, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);

            SendKeyboard(VirtualKeyShift, false);
            shiftDown = true;
            AssertKeyState(VirtualKeyShift, true, "Shift did not remain held for range selection.");
            SendMouseMove(rangeEnd.X, rangeEnd.Y);
            SleepWithWindowGuard(
                100, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);
            AssertCursorAt(rangeEnd);
            AssertKeyState(VirtualKeyShift, true, "Shift changed before the range click.");
            SendMouseButton(MouseLeftDown);
            leftButtonDown = true;
            SleepWithWindowGuard(
                45, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);
            AssertCursorAt(rangeEnd);
            AssertKeyState(VirtualKeyShift, true, "Shift changed during the range click.");
            AssertKeyState(
                VirtualKeyLeftButton,
                true,
                "The left mouse button changed during the range-end click.");
            SendMouseButton(MouseLeftUp);
            leftButtonDown = false;
            SendKeyboard(VirtualKeyShift, true);
            shiftDown = false;
            SleepWithWindowGuard(
                300, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);

            SendKeyboard(VirtualKeyDelete, false);
            deleteDown = true;
            SleepWithWindowGuard(
                45, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);
            AssertKeyState(VirtualKeyDelete, true, "Delete changed during the delete key press.");
            SendKeyboard(VirtualKeyDelete, true);
            deleteDown = false;
            SleepWithWindowGuard(
                650, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);

            AssertPointOwnedByWindow(window, restore);
            SendMouseMove(restore.X, restore.Y);
            SleepWithWindowGuard(
                100, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);
            AssertCursorAt(restore);
            SendMouseButton(MouseLeftDown);
            leftButtonDown = true;
            SleepWithWindowGuard(
                45, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);
            AssertCursorAt(restore);
            AssertKeyState(
                VirtualKeyLeftButton,
                true,
                "The left mouse button changed during restored selection.");
            SendMouseButton(MouseLeftUp);
            leftButtonDown = false;
            SleepWithWindowGuard(
                300, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);
        }
        finally
        {
            if (deleteDown) SendKeyboard(VirtualKeyDelete, true);
            if (shiftDown) SendKeyboard(VirtualKeyShift, true);
            if (leftButtonDown) SendMouseButton(MouseLeftUp);
            AssertKeyReleased(VirtualKeyDelete, "Delete remained held after Shift-range cleanup.");
            AssertKeyReleased(VirtualKeyShift, "Shift remained held after Shift-range cleanup.");
            AssertKeyReleased(
                VirtualKeyLeftButton,
                "The left mouse button remained held after Shift-range cleanup.");
        }
    }

    public static void SendApplicationClick(
        IntPtr window,
        int processId,
        int forbiddenPort,
        double cssX,
        double cssY,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio,
        bool allowForegroundTransitionAfterClick)
    {
        if (window == IntPtr.Zero || processId <= 0 || forbiddenPort < 1 ||
            forbiddenPort > 65535 || !IsFinitePositive(viewportCssWidth) ||
            !IsFinitePositive(viewportCssHeight) || !IsFinitePositive(devicePixelRatio) ||
            devicePixelRatio < 0.25 || devicePixelRatio > 5.0)
        {
            throw new InvalidOperationException("The Windows click coordinate contract is invalid.");
        }

        AssertKeyReleased(VirtualKeyLeftButton, "The left mouse button was held before input.");
        AssertWindowOwnedByProcess(window, processId);
        AssertNoForbiddenTcp(processId, forbiddenPort);
        AcquireForeground(window, processId, forbiddenPort);
        ClientGeometry baseline = ReadAndAssertClientGeometry(
            window, viewportCssWidth, viewportCssHeight, devicePixelRatio);
        SleepWithWindowGuard(
            150, window, processId, forbiddenPort, viewportCssWidth,
            viewportCssHeight, devicePixelRatio, baseline);

        Point point = CssPointToScreen(baseline, cssX, cssY);
        AssertPointOwnedByWindow(window, point);
        bool leftButtonDown = false;
        try
        {
            SendMouseMove(point.X, point.Y);
            SleepWithInputGuard(
                100, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline, point, point,
                point, false, false);
            SendMouseButton(MouseLeftDown);
            leftButtonDown = true;
            SleepWithInputGuard(
                45, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline, point, point,
                point, true, false);
            SendMouseButton(MouseLeftUp);
            leftButtonDown = false;
            if (allowForegroundTransitionAfterClick)
            {
                Thread.Sleep(45);
                AssertWindowOwnedByProcess(window, processId);
                AssertNoForbiddenTcp(processId, forbiddenPort);
            }
            else
            {
                SleepWithInputGuard(
                    100, window, processId, forbiddenPort, viewportCssWidth,
                    viewportCssHeight, devicePixelRatio, baseline, point, point,
                    point, false, false);
            }
        }
        finally
        {
            if (leftButtonDown)
            {
                SendMouseButton(MouseLeftUp);
            }
            AssertKeyReleased(
                VirtualKeyLeftButton,
                "The left mouse button remained held after click cleanup.");
        }
    }

    public static void SendApplicationDoubleClick(
        IntPtr window,
        int processId,
        int forbiddenPort,
        double cssX,
        double cssY,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio,
        int interClickDelayMilliseconds)
    {
        if (window == IntPtr.Zero || processId <= 0 || forbiddenPort < 1 ||
            forbiddenPort > 65535 || !IsFinitePositive(viewportCssWidth) ||
            !IsFinitePositive(viewportCssHeight) || !IsFinitePositive(devicePixelRatio) ||
            devicePixelRatio < 0.25 || devicePixelRatio > 5.0 ||
            interClickDelayMilliseconds < 50 || interClickDelayMilliseconds > 250)
        {
            throw new InvalidOperationException("The Windows double-click contract is invalid.");
        }

        AssertKeyReleased(VirtualKeyLeftButton, "The left mouse button was held before double-click input.");
        AssertWindowOwnedByProcess(window, processId);
        AssertNoForbiddenTcp(processId, forbiddenPort);
        AcquireForeground(window, processId, forbiddenPort);
        ClientGeometry baseline = ReadAndAssertClientGeometry(
            window, viewportCssWidth, viewportCssHeight, devicePixelRatio);
        SleepWithWindowGuard(
            150, window, processId, forbiddenPort, viewportCssWidth,
            viewportCssHeight, devicePixelRatio, baseline);

        Point point = CssPointToScreen(baseline, cssX, cssY);
        AssertPointOwnedByWindow(window, point);
        bool leftButtonDown = false;
        try
        {
            SendMouseMove(point.X, point.Y);
            SleepWithWindowGuard(
                100, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);
            AssertCursorAt(point);
            for (int click = 0; click < 2; click++)
            {
                SendMouseButton(MouseLeftDown);
                leftButtonDown = true;
                SleepWithWindowGuard(
                    45, window, processId, forbiddenPort, viewportCssWidth,
                    viewportCssHeight, devicePixelRatio, baseline);
                AssertCursorAt(point);
                AssertKeyState(
                    VirtualKeyLeftButton,
                    true,
                    "The left mouse button changed during double-click input.");
                SendMouseButton(MouseLeftUp);
                leftButtonDown = false;
                if (click == 0)
                {
                    SleepWithWindowGuard(
                        interClickDelayMilliseconds,
                        window,
                        processId,
                        forbiddenPort,
                        viewportCssWidth,
                        viewportCssHeight,
                        devicePixelRatio,
                        baseline);
                    AssertCursorAt(point);
                }
            }
            SleepWithWindowGuard(
                300, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline);
        }
        finally
        {
            if (leftButtonDown) SendMouseButton(MouseLeftUp);
            AssertKeyReleased(
                VirtualKeyLeftButton,
                "The left mouse button remained held after double-click cleanup.");
        }
    }

    public static IntPtr ReadForegroundWindow()
    {
        return GetForegroundWindow();
    }

    public static void AcquireOwnedForeground(
        IntPtr window,
        IntPtr expectedOwner,
        int processId,
        int forbiddenPort)
    {
        if (!WindowVisible(window) || !WindowEnabled(window) ||
            WindowProcessId(window) != processId ||
            !OwnerChainContains(window, expectedOwner))
        {
            throw new InvalidOperationException(
                "The owned background picker identity changed before foreground acquisition.");
        }
        AcquireForeground(window, processId, forbiddenPort);
        if (RootWindow(GetForegroundWindow()) != window)
        {
            throw new InvalidOperationException(
                "The exact owned background picker does not own foreground input.");
        }
    }

    public static void SendBackgroundFunctionKey(
        IntPtr window,
        int processId,
        int forbiddenPort,
        int virtualKey,
        bool allowForegroundTransitionAfterKey)
    {
        ushort key = checked((ushort)virtualKey);
        if (key != VirtualKeyF2 && key != VirtualKeyF3)
        {
            throw new InvalidOperationException(
                "Only the closed F2/F3 background shortcut set is allowed.");
        }
        AssertKeyReleased(key, "The background function key was held before input.");
        AssertWindowOwnedByProcess(window, processId);
        AssertNoForbiddenTcp(processId, forbiddenPort);
        AcquireForeground(window, processId, forbiddenPort);

        bool keyDown = false;
        try
        {
            SendKeyboard(key, false);
            keyDown = true;
            Thread.Sleep(45);
            SendKeyboard(key, true);
            keyDown = false;
            if (allowForegroundTransitionAfterKey)
            {
                Thread.Sleep(45);
                AssertWindowOwnedByProcess(window, processId);
                AssertNoForbiddenTcp(processId, forbiddenPort);
            }
            else
            {
                Thread.Sleep(150);
                AssertWindowOwnedByProcess(window, processId);
                AssertNoForbiddenTcp(processId, forbiddenPort);
                if (GetForegroundWindow() != window)
                {
                    throw new InvalidOperationException(
                        "The application lost foreground during the F3 input.");
                }
            }
        }
        finally
        {
            if (keyDown) SendKeyboard(key, true);
            AssertKeyReleased(key, "The background function key remained held after input.");
        }
    }

    public static void SendEscapeToForegroundWindow(IntPtr expectedWindow)
    {
        IntPtr foreground = GetForegroundWindow();
        if (expectedWindow == IntPtr.Zero || foreground == IntPtr.Zero ||
            GetAncestor(foreground, GetAncestorRoot) != expectedWindow)
        {
            throw new InvalidOperationException(
                "The exact folder picker does not own foreground keyboard input.");
        }

        AssertKeyReleased(VirtualKeyEscape, "Escape was held before picker cancellation.");
        bool escapeDown = false;
        try
        {
            SendKeyboard(VirtualKeyEscape, false);
            escapeDown = true;
            Thread.Sleep(45);
            // Escape cancellation may return foreground to the owner while
            // the picker is still being destroyed.  Key-up only releases the
            // injected key; the caller separately proves that this exact
            // picker closes and never sends another Escape.
            SendKeyboard(VirtualKeyEscape, true);
            escapeDown = false;
        }
        finally
        {
            if (escapeDown)
            {
                SendKeyboard(VirtualKeyEscape, true);
            }
            AssertKeyReleased(VirtualKeyEscape, "Escape remained held after picker cancellation.");
        }
    }

    private static void AcquireForeground(IntPtr window, int processId, int forbiddenPort)
    {
        AssertWindowOwnedByProcess(window, processId);
        AssertNoForbiddenTcp(processId, forbiddenPort);
        if (GetForegroundWindow() == window)
        {
            return;
        }

        IntPtr foregroundWindow = GetForegroundWindow();
        uint ignored;
        uint foregroundThread = foregroundWindow == IntPtr.Zero
            ? 0
            : GetWindowThreadProcessId(foregroundWindow, out ignored);
        uint targetThread = GetWindowThreadProcessId(window, out ignored);
        uint currentThread = GetCurrentThreadId();
        if (targetThread == 0 || currentThread == 0)
        {
            throw new InvalidOperationException("The foreground input threads are unavailable.");
        }

        bool attachedForeground = false;
        bool attachedTarget = false;
        try
        {
            if (foregroundThread != 0 && foregroundThread != currentThread &&
                foregroundThread != targetThread)
            {
                if (!AttachThreadInput(currentThread, foregroundThread, true))
                {
                    throw new InvalidOperationException("The foreground input queue could not be attached.");
                }
                attachedForeground = true;
            }
            if (targetThread != currentThread)
            {
                if (!AttachThreadInput(currentThread, targetThread, true))
                {
                    throw new InvalidOperationException("The package input queue could not be attached.");
                }
                attachedTarget = true;
            }

            if (IsIconic(window))
            {
                throw new InvalidOperationException("The package window is minimized; geometry is no longer stable.");
            }
            BringWindowToTop(window);
            SetActiveWindow(window);
            SetForegroundWindow(window);
        }
        finally
        {
            if (attachedTarget)
            {
                AttachThreadInput(currentThread, targetThread, false);
            }
            if (attachedForeground)
            {
                AttachThreadInput(currentThread, foregroundThread, false);
            }
        }

        DateTime deadline = DateTime.UtcNow.AddSeconds(3);
        while (DateTime.UtcNow < deadline && GetForegroundWindow() != window)
        {
            AssertWindowOwnedByProcess(window, processId);
            AssertNoForbiddenTcp(processId, forbiddenPort);
            Thread.Sleep(10);
            AssertNoForbiddenTcp(processId, forbiddenPort);
        }
        if (GetForegroundWindow() != window)
        {
            throw new InvalidOperationException("The exact package window could not own foreground input.");
        }
        AssertWindowOwnedByProcess(window, processId);
        AssertNoForbiddenTcp(processId, forbiddenPort);
    }

    private static void AssertWindowOwnedByProcess(IntPtr window, int processId)
    {
        uint actualProcessId;
        uint threadId = GetWindowThreadProcessId(window, out actualProcessId);
        if (threadId == 0 || actualProcessId != (uint)processId)
        {
            throw new InvalidOperationException("The input window is not owned by the exact application process.");
        }
    }

    private static void AssertNoForbiddenTcp(int processId, int forbiddenPort)
    {
        if (HasTcpConnectionForProcessAndPort(processId, forbiddenPort))
        {
            throw new InvalidOperationException("The DryRun application owns a forbidden TCP connection.");
        }
    }

    private static ClientGeometry ReadAndAssertClientGeometry(
        IntPtr window,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio)
    {
        Rect client;
        if (!GetClientRect(window, out client) || client.Left != 0 || client.Top != 0 ||
            client.Right <= 0 || client.Bottom <= 0)
        {
            throw new InvalidOperationException("The package client rectangle is invalid.");
        }

        int deviceWidth = (int)Math.Round(viewportCssWidth * devicePixelRatio);
        int deviceHeight = (int)Math.Round(viewportCssHeight * devicePixelRatio);
        int logicalWidth = (int)Math.Round(viewportCssWidth);
        int logicalHeight = (int)Math.Round(viewportCssHeight);
        bool deviceMatches = deviceWidth > 0 && deviceHeight > 0 &&
            Math.Abs(client.Right - deviceWidth) <= ClientPixelTolerance &&
            Math.Abs(client.Bottom - deviceHeight) <= ClientPixelTolerance;
        bool logicalMatches = logicalWidth > 0 && logicalHeight > 0 &&
            Math.Abs(client.Right - logicalWidth) <= ClientPixelTolerance &&
            Math.Abs(client.Bottom - logicalHeight) <= ClientPixelTolerance;
        if (!deviceMatches && !logicalMatches)
        {
            throw new InvalidOperationException(
                "The browser viewport does not match the package client rectangle.");
        }

        double cssScaleX = client.Right / viewportCssWidth;
        double cssScaleY = client.Bottom / viewportCssHeight;
        if (!IsFinitePositive(cssScaleX) || !IsFinitePositive(cssScaleY) ||
            Math.Abs(cssScaleX - cssScaleY) > 0.02)
        {
            throw new InvalidOperationException(
                "The package client CSS coordinate scale is invalid.");
        }

        Point origin = new Point { X = 0, Y = 0 };
        if (!ClientToScreen(window, ref origin))
        {
            throw new InvalidOperationException("The package client origin is unavailable.");
        }
        return new ClientGeometry {
            ScreenLeft = origin.X,
            ScreenTop = origin.Y,
            Width = client.Right,
            Height = client.Bottom,
            CssScaleX = cssScaleX,
            CssScaleY = cssScaleY
        };
    }

    private static void AssertStableClientGeometry(
        IntPtr window,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio,
        ClientGeometry baseline)
    {
        ClientGeometry current = ReadAndAssertClientGeometry(
            window,
            viewportCssWidth,
            viewportCssHeight,
            devicePixelRatio);
        if (current.ScreenLeft != baseline.ScreenLeft ||
            current.ScreenTop != baseline.ScreenTop ||
            current.Width != baseline.Width || current.Height != baseline.Height)
        {
            throw new InvalidOperationException("The package client geometry changed during input.");
        }
    }

    private static void AssertWindowGuard(
        IntPtr window,
        int processId,
        int forbiddenPort,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio,
        ClientGeometry baseline)
    {
        AssertWindowOwnedByProcess(window, processId);
        AssertNoForbiddenTcp(processId, forbiddenPort);
        if (GetForegroundWindow() != window || IsIconic(window))
        {
            throw new InvalidOperationException("The exact package window lost visible foreground input.");
        }
        AssertStableClientGeometry(
            window,
            viewportCssWidth,
            viewportCssHeight,
            devicePixelRatio,
            baseline);
    }

    private static void AssertInputGuard(
        IntPtr window,
        int processId,
        int forbiddenPort,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio,
        ClientGeometry baseline,
        Point source,
        Point target,
        Point expectedCursor,
        bool expectLeftButtonDown,
        bool expectHomeDown)
    {
        AssertWindowGuard(
            window, processId, forbiddenPort, viewportCssWidth, viewportCssHeight,
            devicePixelRatio, baseline);
        AssertPointOwnedByWindow(window, source);
        AssertPointOwnedByWindow(window, target);
        AssertPointOwnedByWindow(window, expectedCursor);
        AssertCursorAt(expectedCursor);
        AssertKeyState(
            VirtualKeyLeftButton,
            expectLeftButtonDown,
            "The left mouse button state changed during input.");
        AssertKeyState(
            VirtualKeyHome,
            expectHomeDown,
            "The Home key state changed during input.");
    }

    private static void SleepWithWindowGuard(
        int milliseconds,
        IntPtr window,
        int processId,
        int forbiddenPort,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio,
        ClientGeometry baseline)
    {
        int remaining = milliseconds;
        while (remaining > 0)
        {
            AssertWindowGuard(
                window, processId, forbiddenPort, viewportCssWidth, viewportCssHeight,
                devicePixelRatio, baseline);
            int slice = Math.Min(10, remaining);
            Thread.Sleep(slice);
            remaining -= slice;
        }
        AssertWindowGuard(
            window, processId, forbiddenPort, viewportCssWidth, viewportCssHeight,
            devicePixelRatio, baseline);
    }

    private static void SleepWithInputGuard(
        int milliseconds,
        IntPtr window,
        int processId,
        int forbiddenPort,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio,
        ClientGeometry baseline,
        Point source,
        Point target,
        Point expectedCursor,
        bool expectLeftButtonDown,
        bool expectHomeDown)
    {
        int remaining = milliseconds;
        while (remaining > 0)
        {
            AssertInputGuard(
                window, processId, forbiddenPort, viewportCssWidth, viewportCssHeight,
                devicePixelRatio, baseline, source, target, expectedCursor,
                expectLeftButtonDown, expectHomeDown);
            int slice = Math.Min(10, remaining);
            Thread.Sleep(slice);
            remaining -= slice;
        }
        AssertInputGuard(
            window, processId, forbiddenPort, viewportCssWidth, viewportCssHeight,
            devicePixelRatio, baseline, source, target, expectedCursor,
            expectLeftButtonDown, expectHomeDown);
    }

    private static void AssertPointOwnedByWindow(IntPtr window, Point point)
    {
        IntPtr hit = WindowFromPoint(point);
        IntPtr root = hit == IntPtr.Zero ? IntPtr.Zero : GetAncestor(hit, GetAncestorRoot);
        if (root != window)
        {
            throw new InvalidOperationException("A Windows input point is obscured by another top-level window.");
        }
    }

    private static void AssertCursorAt(Point expected)
    {
        Point actual;
        if (!GetCursorPos(out actual) || Math.Abs(actual.X - expected.X) > 2 ||
            Math.Abs(actual.Y - expected.Y) > 2)
        {
            throw new InvalidOperationException("The physical cursor diverged during the one-shot input sequence.");
        }
    }

    private static bool HasTcp4Connection(int processId, int port)
    {
        return ScanTcpTable<MibTcpRowOwnerPid>(
            AddressFamilyInterNetwork,
            delegate(MibTcpRowOwnerPid row)
            {
                return row.OwningProcessId == (uint)processId &&
                    (DecodePort(row.LocalPort) == port || DecodePort(row.RemotePort) == port);
            });
    }

    private static bool HasTcp6Connection(int processId, int port)
    {
        return ScanTcpTable<MibTcp6RowOwnerPid>(
            AddressFamilyInterNetworkV6,
            delegate(MibTcp6RowOwnerPid row)
            {
                return row.OwningProcessId == (uint)processId &&
                    (DecodePort(row.LocalPort) == port || DecodePort(row.RemotePort) == port);
            });
    }

    private static bool ScanTcpTable<TRow>(int addressFamily, Func<TRow, bool> predicate)
        where TRow : struct
    {
        int size = 0;
        uint result = GetExtendedTcpTable(
            IntPtr.Zero,
            ref size,
            false,
            addressFamily,
            TcpTableOwnerPidAll,
            0);
        if (result != ErrorInsufficientBuffer || size < sizeof(int) || size > 64 * 1024 * 1024)
        {
            throw new InvalidOperationException("The native TCP table size is unavailable.");
        }

        IntPtr table = Marshal.AllocHGlobal(size);
        try
        {
            result = GetExtendedTcpTable(
                table,
                ref size,
                false,
                addressFamily,
                TcpTableOwnerPidAll,
                0);
            if (result != 0)
            {
                throw new InvalidOperationException("The native TCP table could not be read.");
            }

            int count = Marshal.ReadInt32(table);
            int rowSize = Marshal.SizeOf(typeof(TRow));
            if (count < 0 || count > 100000 ||
                (long)sizeof(int) + (long)count * rowSize > size)
            {
                throw new InvalidOperationException("The native TCP table layout is invalid.");
            }
            IntPtr rowPointer = IntPtr.Add(table, sizeof(int));
            for (int index = 0; index < count; index++)
            {
                TRow row = (TRow)Marshal.PtrToStructure(rowPointer, typeof(TRow));
                if (predicate(row))
                {
                    return true;
                }
                rowPointer = IntPtr.Add(rowPointer, rowSize);
            }
            return false;
        }
        finally
        {
            Marshal.FreeHGlobal(table);
        }
    }

    private static int DecodePort(uint value)
    {
        return (int)(((value & 0x000000ffU) << 8) | ((value & 0x0000ff00U) >> 8));
    }

    private static bool IsFinitePositive(double value)
    {
        return !Double.IsNaN(value) && !Double.IsInfinity(value) && value > 0;
    }

    private static Point CssPointToScreen(
        ClientGeometry geometry,
        double cssX,
        double cssY)
    {
        if (Double.IsNaN(cssX) || Double.IsInfinity(cssX) ||
            Double.IsNaN(cssY) || Double.IsInfinity(cssY) || cssX < 0 || cssY < 0)
        {
            throw new InvalidOperationException("A CSS input point is invalid.");
        }

        int x = (int)Math.Round(cssX * geometry.CssScaleX);
        int y = (int)Math.Round(cssY * geometry.CssScaleY);
        if (x < 0 || x >= geometry.Width || y < 0 || y >= geometry.Height)
        {
            throw new InvalidOperationException("A CSS input point is outside the package client area.");
        }
        return new Point { X = geometry.ScreenLeft + x, Y = geometry.ScreenTop + y };
    }

    private static void SendMousePath(
        Point from,
        Point to,
        int steps,
        int delayMilliseconds,
        IntPtr window,
        int processId,
        int forbiddenPort,
        double viewportCssWidth,
        double viewportCssHeight,
        double devicePixelRatio,
        ClientGeometry baseline,
        Point source,
        Point target)
    {
        for (int index = 1; index <= steps; index++)
        {
            double amount = (double)index / steps;
            int x = (int)Math.Round(from.X + (to.X - from.X) * amount);
            int y = (int)Math.Round(from.Y + (to.Y - from.Y) * amount);
            SendMouseMove(x, y);
            Point current = new Point { X = x, Y = y };
            SleepWithInputGuard(
                delayMilliseconds, window, processId, forbiddenPort, viewportCssWidth,
                viewportCssHeight, devicePixelRatio, baseline, source, target,
                current, true, false);
        }
    }

    private static void SendMouseMove(int screenX, int screenY)
    {
        int left = GetSystemMetrics(76);
        int top = GetSystemMetrics(77);
        int width = GetSystemMetrics(78);
        int height = GetSystemMetrics(79);
        if (width <= 1 || height <= 1 || screenX < left || screenX >= left + width ||
            screenY < top || screenY >= top + height)
        {
            throw new InvalidOperationException("The Windows input point is outside the virtual desktop.");
        }

        int absoluteX = (int)Math.Round((screenX - left) * 65535.0 / (width - 1));
        int absoluteY = (int)Math.Round((screenY - top) * 65535.0 / (height - 1));
        Input input = new Input {
            Type = InputMouse,
            Union = new InputUnion {
                Mouse = new MouseInput {
                    Dx = absoluteX,
                    Dy = absoluteY,
                    Flags = MouseMove | MouseMoveNoCoalesce | MouseVirtualDesk | MouseAbsolute
                }
            }
        };
        SendOne(input);
    }

    private static void SendMouseButton(uint flags)
    {
        Input input = new Input {
            Type = InputMouse,
            Union = new InputUnion { Mouse = new MouseInput { Flags = flags } }
        };
        SendOne(input);
    }

    private static void SendKeyboard(ushort virtualKey, bool keyUp)
    {
        Input input = new Input {
            Type = InputKeyboard,
            Union = new InputUnion {
                Keyboard = new KeyboardInput {
                    VirtualKey = virtualKey,
                    Flags = keyUp ? KeyUp : 0
                }
            }
        };
        SendOne(input);
    }

    private static void SendOne(Input input)
    {
        Input[] inputs = new Input[] { input };
        if (SendInput(1, inputs, Marshal.SizeOf(typeof(Input))) != 1)
        {
            throw new InvalidOperationException("SendInput did not accept the one-shot input event.");
        }
    }

    private static void AssertKeyReleased(int virtualKey, string message)
    {
        AssertKeyState(virtualKey, false, message);
    }

    private static void AssertKeyState(int virtualKey, bool expectedDown, string message)
    {
        bool actualDown = (GetAsyncKeyState(virtualKey) & 0x8000) != 0;
        if (actualDown != expectedDown)
        {
            throw new InvalidOperationException(message);
        }
    }
}
'@

$PackageName = 'Wickedness.MBNStockWebView.LegacyParity'
$PackageFamilyName = 'Wickedness.MBNStockWebView.LegacyParity_qbv3jkvsn3aj0'
$PackageFullName = 'Wickedness.MBNStockWebView.LegacyParity_0.1.0.0_x64__qbv3jkvsn3aj0'
$PackagePublisher = 'CN=Comtrophy'
$PackageVersion = '0.1.0.0'
$ApplicationId = 'LegacyParityApp'
$ExecutableName = 'MBN_STOCK_WEBVIEW.LegacyParityApp.exe'
$Utf8 = [Text.UTF8Encoding]::new($false)
$StrictUtf8 = [Text.UTF8Encoding]::new($false, $true)
$ExpectedWindowTitle = $Utf8.GetString([Convert]::FromBase64String(
        'Vi1TdG9jayDspp3qtozsoJXrs7TshqHstpzsi5zsiqTthZwgZm9yIOunpOydvOqyveygnFRWICgyNi4wMy4yNik='))
$ExpectedDialogTitle = $Utf8.GetString([Convert]::FromBase64String(
        '66ek7J286rK97KCcVFY='))
$ExpectedDialogMessage = $Utf8.GetString([Convert]::FromBase64String(
        '7ZSE66Gc6re4656o7J2EIOyiheujjO2VmOqyoOyKteuLiOq5jD8='))
$ExpectedPrimaryButton = $Utf8.GetString([Convert]::FromBase64String('7JiI'))
$ExpectedCloseButton = $Utf8.GetString([Convert]::FromBase64String('7JWE64uI7JqU'))
$LiveAuthorizationVariable = 'MBN_STOCK_PLAYOUT_AUTHORIZE_LIVE_OUTPUT'
$K3dNativeHashVariable = 'MBN_STOCK_K3D_NATIVE_SHA256'
$K3dInteropHashVariable = 'MBN_STOCK_K3D_INTEROP_SHA256'
$WebViewArgumentsVariable = 'WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS'
$RepositoryRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
$HarnessPath = Join-Path $PSScriptRoot 'Test-LegacyPackageInput.mjs'
$ExpectedInstallRelativePath = switch ($BuildFlavor) {
    'Release' {
        'src\MBN_STOCK_WEBVIEW.LegacyParityApp\bin\x64\Release\net8.0-windows10.0.19041.0\win-x64'
        break
    }
    'DebugAppX' {
        'src\MBN_STOCK_WEBVIEW.LegacyParityApp\bin\x64\Debug\net8.0-windows10.0.19041.0\win-x64\AppX'
        break
    }
    default { Throw-SafeFailure 'The package build flavor is not closed.' }
}
$PackageModeLabel = "Development $BuildFlavor x64"
$ExpectedInstallLocation = Join-Path $RepositoryRoot $ExpectedInstallRelativePath
$ExpectedInstallLocation = [IO.Path]::GetFullPath($ExpectedInstallLocation)
$ConfigurationPath = Join-Path `
    ([Environment]::GetFolderPath([Environment+SpecialFolder]::LocalApplicationData)) `
    'MBN_STOCK_WEBVIEW\Config\playout.local.json'
$OperatorSettingsPath = Join-Path `
    ([Environment]::GetFolderPath([Environment+SpecialFolder]::LocalApplicationData)) `
    'MBN_STOCK_WEBVIEW\Config\runtime-folders.local.json'
$BackgroundPickerTitle = $Utf8.GetString([Convert]::FromBase64String(
        '64uk7J2MIOyepeuptCDrsLDqsr0g7ISg7YOd'))
$BackgroundDirectoryName = $Utf8.GetString([Convert]::FromBase64String('67Cw6rK9'))
$BackgroundNoneLabel = $Utf8.GetString([Convert]::FromBase64String(
        '67Cw6rK97JeG7J2M'))
$LegacyDefaultBackgroundFileName = $Utf8.GetString(
    [Convert]::FromBase64String('6riw67O4LnZydg=='))
$ExpectedSavedFixtureGraphicType = $Utf8.GetString(
    [Convert]::FromBase64String('MeyXtO2MkOq4sOuzuA=='))
$ExpectedSavedFixtureCurrentSubtype = $Utf8.GetString(
    [Convert]::FromBase64String('7ZiE7J6s6rCA'))
$ExpectedSavedFixtureAfterHoursSubtype = $Utf8.GetString(
    [Convert]::FromBase64String('7Iuc6rCE7Jm464uo7J286rCA'))

$script:ApplicationProcess = $null
$script:ApplicationWasLaunched = $false
$script:CloseMainWindowCalls = 0
$script:PrimaryInvokeCalls = 0
$script:SingleInstanceActivationCalls = 0
$script:WindowsInputRequestCalls = 0
$script:WindowsInputAcknowledgementCalls = 0
$script:BackgroundShortcutRoot = $null
$script:BackgroundShortcutRootCreated = $false
$script:Phase = 'preflight'

function Throw-SafeFailure([string]$Message) {
    throw [InvalidOperationException]::new($Message)
}

function Test-PathEqual([string]$Left, [string]$Right) {
    return [string]::Equals(
        [IO.Path]::GetFullPath($Left).TrimEnd('\'),
        [IO.Path]::GetFullPath($Right).TrimEnd('\'),
        [StringComparison]::OrdinalIgnoreCase)
}

function Assert-ExactProcessPackageIdentity([Diagnostics.Process]$Process) {
    try {
        $actualPackageFullName = [LegacyPackageInputNative]::ReadPackageFullName($Process.Handle)
    }
    catch {
        Throw-SafeFailure 'The running application package identity could not be inspected.'
    }

    if ([string]$actualPackageFullName -cne $PackageFullName) {
        Throw-SafeFailure 'The running application does not have the exact registered package identity.'
    }
}

function Resolve-EvidencePath([string]$Value, [string]$DefaultFileName) {
    if ([string]::IsNullOrWhiteSpace($Value)) {
        return [IO.Path]::GetFullPath((Join-Path `
            (Join-Path $RepositoryRoot 'artifacts\package-input-smoke') `
            $DefaultFileName))
    }

    if ([IO.Path]::IsPathRooted($Value)) {
        return [IO.Path]::GetFullPath($Value)
    }

    return [IO.Path]::GetFullPath((Join-Path $RepositoryRoot $Value))
}

function Assert-OutputPathAvailable([string]$Path, [string]$Label) {
    if ([IO.File]::Exists($Path) -or [IO.Directory]::Exists($Path)) {
        Throw-SafeFailure "$Label already exists; evidence files are never overwritten."
    }

    $parent = [IO.Path]::GetDirectoryName($Path)
    if ([string]::IsNullOrWhiteSpace($parent)) {
        Throw-SafeFailure "$Label has no parent directory."
    }

    if (-not [IO.Directory]::Exists($parent)) {
        [void][IO.Directory]::CreateDirectory($parent)
    }

    $parentItem = Get-Item -LiteralPath $parent -Force
    if (($parentItem.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) {
        Throw-SafeFailure "$Label parent must not be a reparse point."
    }
}

function Resolve-NodeExecutable([string]$RequestedPath) {
    if (-not [string]::IsNullOrWhiteSpace($RequestedPath)) {
        $resolved = [IO.Path]::GetFullPath($RequestedPath)
        if (-not [IO.File]::Exists($resolved) -or
            [IO.Path]::GetFileName($resolved) -cne 'node.exe') {
            Throw-SafeFailure 'The requested Node executable does not exist.'
        }

        return $resolved
    }

    $bundled = Join-Path $env:USERPROFILE `
        '.cache\codex-runtimes\codex-primary-runtime\dependencies\node\bin\node.exe'
    if ([IO.File]::Exists($bundled)) {
        return [IO.Path]::GetFullPath($bundled)
    }

    $command = Get-Command node.exe -CommandType Application -ErrorAction SilentlyContinue |
        Select-Object -First 1
    if ($null -eq $command) {
        Throw-SafeFailure 'Node was not found. Supply -NodePath with an absolute node.exe path.'
    }

    return [IO.Path]::GetFullPath($command.Source)
}

function Assert-LocalConfigurationIsDryRun {
    if (-not [IO.File]::Exists($ConfigurationPath)) {
        return
    }

    $item = Get-Item -LiteralPath $ConfigurationPath -Force
    if (($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0 -or
        $item.Length -gt 1MB) {
        Throw-SafeFailure 'The local playout configuration cannot be safely inspected.'
    }

    try {
        $raw = [IO.File]::ReadAllText($ConfigurationPath, [Text.Encoding]::UTF8)
        $configuration = $raw | ConvertFrom-Json -ErrorAction Stop
    }
    catch {
        # Do not include parser diagnostics: they can echo configuration content.
        Throw-SafeFailure 'The local playout configuration could not be parsed safely.'
    }

    if ($null -eq $configuration) {
        Throw-SafeFailure 'The local playout configuration is empty.'
    }

    $modeProperties = @($configuration.PSObject.Properties | Where-Object {
            [string]::Equals($_.Name, 'Mode', [StringComparison]::OrdinalIgnoreCase)
        })
    $rawModePropertyCount = [regex]::Matches(
        $raw,
        '(?i)"mode"\s*:').Count
    if ($modeProperties.Count -eq 0 -and $rawModePropertyCount -eq 0) {
        # PlayoutOptions.Mode defaults to DryRun when the property is absent.
        return
    }

    if ($modeProperties.Count -ne 1 -or $rawModePropertyCount -ne 1) {
        Throw-SafeFailure 'The local playout mode is not uniquely defined.'
    }

    $mode = $modeProperties[0].Value
    $isDryRun = ($mode -is [string] -and
        [string]::Equals($mode, 'DryRun', [StringComparison]::OrdinalIgnoreCase)) -or
        ($mode -isnot [string] -and [string]$mode -ceq '1')
    if (-not $isDryRun) {
        Throw-SafeFailure 'The local playout configuration does not resolve to DryRun.'
    }
}

function Initialize-BackgroundShortcutFixture([string]$InstallLocation) {
    if ($Profile -cne 'DryRunPlayout') {
        return
    }
    if ([IO.File]::Exists($OperatorSettingsPath) -or
        [IO.Directory]::Exists($OperatorSettingsPath)) {
        Throw-SafeFailure (
            'The F2/F3 physical test requires the default package folder layout; ' +
            'runtime folder overrides are present.')
    }

    if ([IO.File]::Exists($ConfigurationPath)) {
        try {
            $raw = [IO.File]::ReadAllText($ConfigurationPath, $StrictUtf8)
            $configuration = $raw | ConvertFrom-Json -ErrorAction Stop
        }
        catch {
            Throw-SafeFailure 'The F2/F3 physical test could not inspect its DryRun configuration.'
        }
        foreach ($propertyName in @('sceneDirectory', 'legacyBackgroundDirectory')) {
            $matches = @($configuration.PSObject.Properties | Where-Object {
                    [string]::Equals(
                        $_.Name,
                        $propertyName,
                        [StringComparison]::OrdinalIgnoreCase)
                })
            if ($matches.Count -gt 1 -or
                ($matches.Count -eq 1 -and $null -ne $matches[0].Value)) {
                Throw-SafeFailure (
                    'The F2/F3 physical test requires null scene/background folder overrides.')
            }
        }
    }

    $root = [IO.Path]::GetFullPath((Join-Path $InstallLocation $BackgroundDirectoryName))
    $expectedRoot = [IO.Path]::GetFullPath((Join-Path `
            $ExpectedInstallLocation `
            $BackgroundDirectoryName))
    if (-not (Test-PathEqual $root $expectedRoot) -or [IO.File]::Exists($root)) {
        Throw-SafeFailure 'The exact package-local background test root is unavailable.'
    }
    if (-not [IO.Directory]::Exists($root)) {
        [void][IO.Directory]::CreateDirectory($root)
        $script:BackgroundShortcutRootCreated = $true
    }
    $item = Get-Item -LiteralPath $root -Force
    if (-not $item.PSIsContainer -or
        ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0) {
        Throw-SafeFailure 'The exact package-local background test root is unsafe.'
    }
    $defaultPath = Join-Path $root $LegacyDefaultBackgroundFileName
    if ([IO.File]::Exists($defaultPath) -or [IO.Directory]::Exists($defaultPath)) {
        Throw-SafeFailure (
            'The F3 fail-closed test requires the external default background asset to be absent.')
    }
    $script:BackgroundShortcutRoot = $root
}

function Remove-BackgroundShortcutFixture {
    if (-not $script:BackgroundShortcutRootCreated -or
        [string]::IsNullOrEmpty([string]$script:BackgroundShortcutRoot)) {
        return
    }
    $root = [IO.Path]::GetFullPath([string]$script:BackgroundShortcutRoot)
    $expectedRoot = [IO.Path]::GetFullPath((Join-Path `
            $ExpectedInstallLocation `
            $BackgroundDirectoryName))
    if (-not (Test-PathEqual $root $expectedRoot) -or
        -not [IO.Directory]::Exists($root)) {
        Throw-SafeFailure 'The temporary background shortcut root identity changed.'
    }
    $item = Get-Item -LiteralPath $root -Force
    if (($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0 -or
        @(Get-ChildItem -LiteralPath $root -Force).Count -ne 0) {
        Throw-SafeFailure 'The temporary background shortcut root is no longer empty and was preserved.'
    }
    [IO.Directory]::Delete($root, $false)
    $script:BackgroundShortcutRootCreated = $false
}

function Assert-NoUnsafeEnvironment {
    $forbiddenExactNames = @(
        $LiveAuthorizationVariable,
        $K3dNativeHashVariable,
        $K3dInteropHashVariable
    )
    $targets = @(
        [EnvironmentVariableTarget]::Process,
        [EnvironmentVariableTarget]::User,
        [EnvironmentVariableTarget]::Machine
    )

    foreach ($target in $targets) {
        try {
            $environment = [Environment]::GetEnvironmentVariables($target)
        }
        catch {
            Throw-SafeFailure "The $target environment could not be inspected."
        }

        foreach ($nameObject in $environment.Keys) {
            $name = [string]$nameObject
            if ($forbiddenExactNames -contains $name -or
                $name -like 'MBN_STOCK_PLAYOUT_*' -or
                $name -like 'WEBVIEW2_*' -or
                $name -like 'COREWEBVIEW2_*') {
                # Report names/scopes only. Never report environment values.
                Throw-SafeFailure "Unsafe launch environment variable is present: $target/$name."
            }
        }
    }
}

function Get-StreamSha256Hex([IO.Stream]$Stream) {
    $algorithm = [Security.Cryptography.SHA256]::Create()
    try {
        return [BitConverter]::ToString($algorithm.ComputeHash($Stream)).Replace('-', '')
    }
    finally {
        $algorithm.Dispose()
    }
}

function Assert-DebugAppXMatchesLatestPackage([string]$InstallLocation) {
    if ($BuildFlavor -cne 'DebugAppX') {
        return
    }

    $projectRoot = Join-Path $RepositoryRoot 'src\MBN_STOCK_WEBVIEW.LegacyParityApp'
    $msix = Join-Path $projectRoot `
        'AppPackages\MBN_STOCK_WEBVIEW.LegacyParityApp_0.1.0.0_x64_Debug_Test\MBN_STOCK_WEBVIEW.LegacyParityApp_0.1.0.0_x64_Debug.msix'
    if (-not [IO.File]::Exists($msix)) {
        Throw-SafeFailure 'The latest Debug MSIX is missing; the registered AppX cannot be proven current.'
    }

    Add-Type -AssemblyName System.IO.Compression.FileSystem
    $archive = [IO.Compression.ZipFile]::OpenRead($msix)
    try {
        $expectedFiles = @(
            'AppxManifest.xml',
            'Assets/StartupHero.png',
            'MBN_STOCK_WEBVIEW.Core.dll',
            'MBN_STOCK_WEBVIEW.Infrastructure.dll',
            'MBN_STOCK_WEBVIEW.LegacyApplication.dll',
            'MBN_STOCK_WEBVIEW.LegacyBridge.dll',
            'MBN_STOCK_WEBVIEW.LegacyParityApp.dll',
            'Web/Brand/logo.png',
            'Web/app.js',
            'Web/index.html',
            'Web/playout-ui.js',
            'Web/styles.css',
            'Web/workspace-navigation.js'
        )
        foreach ($relativePath in $expectedFiles) {
            $entry = $archive.GetEntry($relativePath)
            $installed = Join-Path $InstallLocation $relativePath.Replace('/', '\')
            if ($null -eq $entry -or -not [IO.File]::Exists($installed)) {
                Throw-SafeFailure 'The registered Debug AppX is missing a required current package file.'
            }

            $entryStream = $entry.Open()
            try {
                $packageHash = Get-StreamSha256Hex $entryStream
            }
            finally {
                $entryStream.Dispose()
            }
            $installedHash = (Get-FileHash -LiteralPath $installed -Algorithm SHA256).Hash
            if ($installedHash -cne $packageHash) {
                Throw-SafeFailure 'The registered Debug AppX is stale relative to the latest Debug MSIX.'
            }
        }
    }
    finally {
        $archive.Dispose()
    }

    foreach ($relativeSource in @(
            'Web\app.js',
            'Web\index.html',
            'Web\styles.css',
            'Web\workspace-navigation.js')) {
        $sourcePath = Join-Path $projectRoot $relativeSource
        $installedPath = Join-Path $InstallLocation $relativeSource
        if (-not [IO.File]::Exists($sourcePath) -or
            -not [IO.File]::Exists($installedPath) -or
            (Get-FileHash -LiteralPath $sourcePath -Algorithm SHA256).Hash -cne
                (Get-FileHash -LiteralPath $installedPath -Algorithm SHA256).Hash) {
            Throw-SafeFailure 'The registered Debug AppX does not contain the current Web application source.'
        }
    }
}

function Get-ExactDevelopmentPackage {
    $packages = @(Get-AppxPackage -Name $PackageName -ErrorAction Stop)
    if ($packages.Count -ne 1) {
        Throw-SafeFailure 'Exactly one current-user LegacyParity development package is required.'
    }

    $package = $packages[0]
    if (-not $package.IsDevelopmentMode -or
        [string]$package.SignatureKind -cne 'None' -or
        [string]$package.Status -cne 'Ok' -or
        [string]$package.Name -cne $PackageName -or
        [string]$package.PackageFullName -cne $PackageFullName -or
        [string]$package.PackageFamilyName -cne $PackageFamilyName -or
        [string]$package.Publisher -cne $PackagePublisher -or
        [string]$package.Version -cne $PackageVersion -or
        [string]$package.Architecture -cne 'X64' -or
        -not (Test-PathEqual ([string]$package.InstallLocation) $ExpectedInstallLocation)) {
        Throw-SafeFailure "The registered package is not the exact $BuildFlavor x64 development package."
    }

    try {
        $manifest = Get-AppxPackageManifest -Package $package -ErrorAction Stop
    }
    catch {
        Throw-SafeFailure 'The registered package manifest could not be inspected.'
    }

    $applications = @($manifest.Package.Applications.Application)
    if ($applications.Count -ne 1 -or
        [string]$applications[0].Id -cne $ApplicationId -or
        [string]$applications[0].Executable -cne $ExecutableName -or
        [string]$applications[0].EntryPoint -cne 'Windows.FullTrustApplication') {
        Throw-SafeFailure 'The registered package application identity is not exact.'
    }

    $executable = Join-Path ([string]$package.InstallLocation) $ExecutableName
    if (-not [IO.File]::Exists($executable)) {
        Throw-SafeFailure "The registered $BuildFlavor application executable is missing."
    }

    Assert-DebugAppXMatchesLatestPackage ([string]$package.InstallLocation)

    return [pscustomobject]@{
        Package = $package
        Executable = [IO.Path]::GetFullPath($executable)
        InstallLocation = [IO.Path]::GetFullPath([string]$package.InstallLocation)
    }
}

function Get-LegacyApplicationProcesses {
    $live = New-Object 'Collections.Generic.List[Diagnostics.Process]'
    foreach ($candidate in @(Get-Process `
            -Name ([IO.Path]::GetFileNameWithoutExtension($ExecutableName)) `
            -ErrorAction SilentlyContinue)) {
        try {
            $candidate.Refresh()
            if (-not $candidate.HasExited) {
                [void]$live.Add($candidate)
            }
        }
        catch {
            # A process that disappears during enumeration is not a live instance.
        }
    }
    return @($live)
}

function Assert-NoExistingApplication {
    if (@(Get-LegacyApplicationProcesses).Count -ne 0) {
        Throw-SafeFailure 'A LegacyParity application process is already running.'
    }
}

function Get-TcpSnapshot {
    try {
        return @(Get-NetTCPConnection -ErrorAction Stop)
    }
    catch {
        Throw-SafeFailure 'The TCP connection table could not be inspected.'
    }
}

function Assert-PortIsFree([int]$CandidatePort) {
    if ($CandidatePort -eq 30001) {
        Throw-SafeFailure 'The WebView debugging port must not be the Tornado port.'
    }

    $listeners = @(Get-TcpSnapshot | Where-Object {
            [string]$_.State -ceq 'Listen' -and
            $_.LocalPort -eq $CandidatePort
        })
    if ($listeners.Count -ne 0) {
        Throw-SafeFailure 'The chosen loopback debugging port is already in use.'
    }
}

function Assert-NoTornadoConnection([int]$ProcessId) {
    try {
        $hasConnection = [LegacyPackageInputNative]::HasTcpConnectionForProcessAndPort(
            $ProcessId,
            30001)
    }
    catch {
        Throw-SafeFailure 'The native TCP ownership table could not be inspected.'
    }
    if ($hasConnection) {
        Throw-SafeFailure 'The DryRun application owns a Tornado port connection.'
    }
}

function ConvertTo-QuotedProcessArgument([string]$Value) {
    if ($Value.IndexOfAny([char[]]@('"', "`r", "`n")) -ge 0) {
        Throw-SafeFailure 'A process argument contains a forbidden character.'
    }

    return '"' + $Value + '"'
}

function Get-ByteArraySha256([byte[]]$Bytes) {
    $algorithm = [Security.Cryptography.SHA256]::Create()
    try {
        return ([BitConverter]::ToString($algorithm.ComputeHash($Bytes))).Replace('-', '')
    }
    finally {
        $algorithm.Dispose()
    }
}

function Assert-ExactJsonPropertyNames(
    [object]$Value,
    [string[]]$ExpectedNames,
    [string]$Label) {
    if ($null -eq $Value) {
        Throw-SafeFailure "$Label is missing."
    }

    $actualNames = @($Value.PSObject.Properties | ForEach-Object { [string]$_.Name })
    if ($actualNames.Count -ne $ExpectedNames.Count) {
        Throw-SafeFailure "$Label has an unexpected schema."
    }
    foreach ($name in $ExpectedNames) {
        if ($actualNames -cnotcontains $name) {
            Throw-SafeFailure "$Label has an unexpected schema."
        }
    }
}

function Test-ExactStringSequence([object[]]$Left, [object[]]$Right) {
    $leftValues = @($Left | ForEach-Object { [string]$_ })
    $rightValues = @($Right | ForEach-Object { [string]$_ })
    if ($leftValues.Count -ne $rightValues.Count) {
        return $false
    }
    for ($index = 0; $index -lt $leftValues.Count; $index++) {
        if ($leftValues[$index] -cne $rightValues[$index]) {
            return $false
        }
    }
    return $true
}

function Read-SmallJsonEvidenceFile([string]$Path, [string]$Label) {
    try {
        $item = Get-Item -LiteralPath $Path -Force
        if ($item.PSIsContainer -or
            ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0 -or
            $item.Length -le 0 -or $item.Length -gt 16KB) {
            Throw-SafeFailure "$Label is not a small regular file."
        }

        $bytes = [IO.File]::ReadAllBytes($Path)
        if ($bytes.Length -ne $item.Length) {
            Throw-SafeFailure "$Label changed while it was read."
        }
        $value = $StrictUtf8.GetString($bytes) | ConvertFrom-Json -ErrorAction Stop
        return [pscustomobject]@{
            Value = $value
            Bytes = $bytes
            Sha256 = Get-ByteArraySha256 $bytes
        }
    }
    catch [InvalidOperationException] {
        throw
    }
    catch {
        Throw-SafeFailure "$Label could not be validated as UTF-8 JSON."
    }
}

function Wait-ReadSmallJsonEvidenceFile(
    [string]$Path,
    [string]$Label,
    [datetime]$Deadline) {
    $previousLength = -1L
    $stableObservations = 0
    while ([datetime]::UtcNow -lt $Deadline) {
        if ([IO.File]::Exists($Path)) {
            try {
                $item = Get-Item -LiteralPath $Path -Force
                $isCandidate = -not $item.PSIsContainer -and
                    ($item.Attributes -band [IO.FileAttributes]::ReparsePoint) -eq 0 -and
                    $item.Length -gt 0 -and $item.Length -le 16KB
                if ($isCandidate -and $item.Length -eq $previousLength) {
                    $stableObservations++
                }
                else {
                    $stableObservations = 0
                }
                $previousLength = $item.Length
                if ($isCandidate -and $stableObservations -ge 1) {
                    return Read-SmallJsonEvidenceFile $Path $Label
                }
            }
            catch [InvalidOperationException] {
                throw
            }
            catch {
                $stableObservations = 0
                $previousLength = -1L
            }
        }
        Start-Sleep -Milliseconds 25
    }
    Throw-SafeFailure "$Label was not published as one stable small regular file."
}

function ConvertTo-FiniteNumber([object]$Value, [string]$Label) {
    $isJsonNumber = $Value -is [byte] -or $Value -is [sbyte] -or
        $Value -is [int16] -or $Value -is [uint16] -or
        $Value -is [int32] -or $Value -is [uint32] -or
        $Value -is [int64] -or $Value -is [uint64] -or
        $Value -is [single] -or $Value -is [double] -or $Value -is [decimal]
    if (-not $isJsonNumber) {
        Throw-SafeFailure "$Label is not a JSON number."
    }
    try {
        $number = [Convert]::ToDouble($Value, [Globalization.CultureInfo]::InvariantCulture)
    }
    catch {
        Throw-SafeFailure "$Label is not numeric."
    }
    if ([double]::IsNaN($number) -or [double]::IsInfinity($number)) {
        Throw-SafeFailure "$Label is not finite."
    }
    return $number
}

function Get-WindowsInputExchangePath(
    [string]$BasePath,
    [ValidateRange(1, 3)]
    [int]$ExchangeIndex) {
    if ($ExchangeIndex -eq 1) {
        return $BasePath
    }
    $directory = [IO.Path]::GetDirectoryName($BasePath)
    $extension = [IO.Path]::GetExtension($BasePath)
    $name = [IO.Path]::GetFileNameWithoutExtension($BasePath)
    return Join-Path $directory (
        $name + '.exchange-' + $ExchangeIndex.ToString('00') + $extension)
}

function Get-ExpectedWindowsInputExchangeCount(
    [string]$HarnessProfile,
    [string]$HarnessScope) {
    if ($HarnessProfile -ceq 'DryRunPlayout' -or
        $HarnessProfile -ceq 'dry-run-playout') {
        return 3
    }
    if (($HarnessProfile -ceq 'FullUiDb' -or $HarnessProfile -ceq 'full-ui-db') -and
        ($HarnessScope -ceq 'PList' -or $HarnessScope -ceq 'plist' -or
         $HarnessScope -ceq 'All' -or $HarnessScope -ceq 'all')) {
        return 2
    }
    return 1
}

function Write-WindowsInputAcknowledgement(
    [string]$Path,
    [int]$ExchangeIndex,
    [string]$Token,
    [string]$Operation,
    [Collections.IDictionary]$InputCounts) {
    $acknowledgement = [ordered]@{
        schemaVersion = 1
        exchangeIndex = $ExchangeIndex
        token = $Token
        result = 'PASS'
        operation = $Operation
        foregroundValidated = $true
        packageIdentityValidated = $true
        inputRetryCount = 0
    }
    foreach ($key in $InputCounts.Keys) {
        $acknowledgement[$key] = $InputCounts[$key]
    }
    $bytes = $Utf8.GetBytes(($acknowledgement | ConvertTo-Json -Compress) + "`n")
    $parent = [IO.Path]::GetDirectoryName($Path)
    $temporaryPath = Join-Path $parent (
        ([IO.Path]::GetFileName($Path)) + '.' + [Guid]::NewGuid().ToString('N') + '.tmp')
    try {
        $stream = [IO.FileStream]::new(
            $temporaryPath,
            [IO.FileMode]::CreateNew,
            [IO.FileAccess]::Write,
            [IO.FileShare]::None)
        try {
            $stream.Write($bytes, 0, $bytes.Length)
            $stream.Flush($true)
        }
        finally {
            $stream.Dispose()
        }
        [IO.File]::Move($temporaryPath, $Path)
    }
    catch {
        try {
            if ([IO.File]::Exists($temporaryPath)) {
                [IO.File]::Delete($temporaryPath)
            }
        }
        catch {
            # Cleanup failure cannot authorize another acknowledgement attempt.
        }
        Throw-SafeFailure 'The one-shot Windows input acknowledgement could not be created.'
    }

    return [pscustomobject]@{
        Bytes = $bytes
        Sha256 = Get-ByteArraySha256 $bytes
    }
}

function ConvertTo-ExactInputPoint(
    [object]$Point,
    [double]$ViewportWidth,
    [double]$ViewportHeight,
    [string]$Label) {
    Assert-ExactJsonPropertyNames $Point @('x', 'y') $Label
    $x = ConvertTo-FiniteNumber $Point.x "$Label X"
    $y = ConvertTo-FiniteNumber $Point.y "$Label Y"
    if ($x -lt 0 -or $x -ge $ViewportWidth -or
        $y -lt 0 -or $y -ge $ViewportHeight) {
        Throw-SafeFailure "$Label is outside the exact package viewport."
    }
    return [pscustomobject]@{ X = $x; Y = $y }
}

function Invoke-ExactPlaylistWindowsInputRequest(
    [object]$Request,
    [Diagnostics.Process]$Application) {
    Assert-ExactJsonPropertyNames $Request @(
        'schemaVersion', 'exchangeIndex', 'token', 'targetUrl', 'operation',
        'sourceRowId', 'targetRowId', 'rangeStartRowId', 'rangeEndRowId',
        'position', 'source', 'target', 'rangeStart', 'rangeEnd',
        'restoreSelection', 'viewport', 'devicePixelRatio', 'beforeOrder',
        'reorderedOrder', 'afterOrder', 'expectedRangeSelectedRowIds',
        'expectedSelectedRowId', 'expectedActiveRowIdAfterHome',
        'expectedFinalActiveRowId', 'expectedFocusedRowId', 'mouseDownCalls',
        'mouseUpCalls', 'homeKeyCalls', 'shiftKeyDownCalls', 'shiftKeyUpCalls',
        'deleteKeyCalls', 'inputRetryCount') 'Playlist Windows input request'
    Assert-ExactJsonPropertyNames $Request.viewport @('width', 'height') `
        'Playlist Windows input viewport'

    $sourceRowId = [string]$Request.sourceRowId
    $targetRowId = [string]$Request.targetRowId
    $rangeStartRowId = [string]$Request.rangeStartRowId
    $rangeEndRowId = [string]$Request.rangeEndRowId
    $rowIds = @($sourceRowId, $targetRowId, $rangeStartRowId, $rangeEndRowId)
    if ($Request.sourceRowId -isnot [string] -or
        $Request.targetRowId -isnot [string] -or
        $Request.rangeStartRowId -isnot [string] -or
        $Request.rangeEndRowId -isnot [string] -or
        $Request.position -isnot [string] -or
        [string]$Request.position -cne 'after' -or
        $sourceRowId -ceq $targetRowId -or
        $rangeStartRowId -ceq $rangeEndRowId -or
        (@($rowIds | Select-Object -Unique)).Count -ne 4 -or
        $rowIds.Where({ $_ -cnotmatch '\Alegacy-stock-[0-9]{8}\z' }).Count -ne 0 -or
        [string]$Request.expectedSelectedRowId -cne $sourceRowId -or
        [string]$Request.expectedFinalActiveRowId -cne $sourceRowId -or
        [string]$Request.expectedFocusedRowId -cne $sourceRowId -or
        (ConvertTo-FiniteNumber $Request.mouseDownCalls 'Playlist mouse-down count') -ne 4 -or
        (ConvertTo-FiniteNumber $Request.mouseUpCalls 'Playlist mouse-up count') -ne 4 -or
        (ConvertTo-FiniteNumber $Request.homeKeyCalls 'Playlist Home count') -ne 1 -or
        (ConvertTo-FiniteNumber $Request.shiftKeyDownCalls 'Playlist Shift-down count') -ne 1 -or
        (ConvertTo-FiniteNumber $Request.shiftKeyUpCalls 'Playlist Shift-up count') -ne 1 -or
        (ConvertTo-FiniteNumber $Request.deleteKeyCalls 'Playlist Delete count') -ne 1) {
        Throw-SafeFailure 'The playlist Windows input request is outside the exact gesture contract.'
    }

    $beforeOrder = @($Request.beforeOrder | ForEach-Object { [string]$_ })
    $reorderedOrder = @($Request.reorderedOrder | ForEach-Object { [string]$_ })
    $afterOrder = @($Request.afterOrder | ForEach-Object { [string]$_ })
    $expectedRange = @($Request.expectedRangeSelectedRowIds | ForEach-Object { [string]$_ })
    if ($beforeOrder.Count -ne 5 -or $reorderedOrder.Count -ne 5 -or
        $afterOrder.Count -ne 3 -or
        (@($beforeOrder | Select-Object -Unique)).Count -ne 5 -or
        (@($reorderedOrder | Select-Object -Unique)).Count -ne 5 -or
        (@($afterOrder | Select-Object -Unique)).Count -ne 3 -or
        -not (Test-ExactStringSequence $expectedRange @($rangeStartRowId, $rangeEndRowId))) {
        Throw-SafeFailure 'The playlist Windows input row orders are not the exact five-to-three fixture.'
    }
    foreach ($rowId in $beforeOrder + $reorderedOrder + $afterOrder) {
        if ($rowId -cnotmatch '\Alegacy-stock-[0-9]{8}\z') {
            Throw-SafeFailure 'The playlist Windows input request contains an invalid row identity.'
        }
    }

    $computedReorder = New-Object 'Collections.Generic.List[string]'
    foreach ($rowId in $beforeOrder) {
        if ($rowId -cne $sourceRowId) { [void]$computedReorder.Add($rowId) }
    }
    $targetIndex = $computedReorder.IndexOf($targetRowId)
    if ($targetIndex -lt 0) {
        Throw-SafeFailure 'The playlist drag target is absent after removing its source.'
    }
    $computedReorder.Insert($targetIndex + 1, $sourceRowId)
    if (-not (Test-ExactStringSequence @($computedReorder) $reorderedOrder) -or
        $reorderedOrder[-2] -cne $rangeStartRowId -or
        $reorderedOrder[-1] -cne $rangeEndRowId -or
        [string]$Request.expectedActiveRowIdAfterHome -cne $reorderedOrder[0]) {
        Throw-SafeFailure 'The playlist reorder/Home/range contract is not exact.'
    }
    $computedAfter = @($reorderedOrder | Where-Object {
            $_ -cne $rangeStartRowId -and $_ -cne $rangeEndRowId
        })
    if (-not (Test-ExactStringSequence $computedAfter $afterOrder)) {
        Throw-SafeFailure 'The playlist Shift-range delete result is not exact.'
    }

    $viewportWidth = ConvertTo-FiniteNumber $Request.viewport.width `
        'Playlist Windows input viewport width'
    $viewportHeight = ConvertTo-FiniteNumber $Request.viewport.height `
        'Playlist Windows input viewport height'
    $devicePixelRatio = ConvertTo-FiniteNumber $Request.devicePixelRatio `
        'Playlist Windows input device pixel ratio'
    if ($viewportWidth -lt 1 -or $viewportWidth -gt 16384 -or
        $viewportHeight -lt 1 -or $viewportHeight -gt 16384 -or
        $devicePixelRatio -lt 0.25 -or $devicePixelRatio -gt 5) {
        Throw-SafeFailure 'The playlist Windows input viewport contract is invalid.'
    }
    $source = ConvertTo-ExactInputPoint $Request.source $viewportWidth $viewportHeight 'Playlist drag source'
    $target = ConvertTo-ExactInputPoint $Request.target $viewportWidth $viewportHeight 'Playlist drag target'
    $rangeStart = ConvertTo-ExactInputPoint $Request.rangeStart $viewportWidth $viewportHeight 'Playlist range start'
    $rangeEnd = ConvertTo-ExactInputPoint $Request.rangeEnd $viewportWidth $viewportHeight 'Playlist range end'
    $restore = ConvertTo-ExactInputPoint $Request.restoreSelection $viewportWidth $viewportHeight 'Playlist restore selection'

    [LegacyPackageInputNative]::SendRowHeaderDragAfterThenHome(
        $Application.MainWindowHandle, $Application.Id, 30001,
        $source.X, $source.Y, $target.X, $target.Y,
        $viewportWidth, $viewportHeight, $devicePixelRatio)
    [LegacyPackageInputNative]::SendShiftClickRangeThenDeleteAndRestore(
        $Application.MainWindowHandle, $Application.Id, 30001,
        $rangeStart.X, $rangeStart.Y, $rangeEnd.X, $rangeEnd.Y,
        $restore.X, $restore.Y,
        $viewportWidth, $viewportHeight, $devicePixelRatio)
}

function Invoke-ExactNamedPlaylistDoubleClickRequest(
    [object]$Request,
    [Diagnostics.Process]$Application) {
    Assert-ExactJsonPropertyNames $Request @(
        'schemaVersion', 'exchangeIndex', 'token', 'targetUrl', 'operation',
        'definitionId', 'definitionTitle', 'point', 'viewport',
        'devicePixelRatio', 'expectedPlaylistContent', 'mouseDownCalls',
        'mouseUpCalls', 'doubleClickIntervalMilliseconds',
        'inputRetryCount') 'Named-playlist double-click request'
    Assert-ExactJsonPropertyNames $Request.viewport @('width', 'height') `
        'Named-playlist double-click viewport'
    if ($Request.definitionId -isnot [string] -or
        [string]::IsNullOrEmpty([string]$Request.definitionId) -or
        ([string]$Request.definitionId).Length -gt 256 -or
        [string]$Request.definitionId -cmatch '[\x00-\x1F\x7F]' -or
        $Request.definitionTitle -isnot [string] -or
        ([string]$Request.definitionTitle).Length -ne 26 -or
        [string]$Request.definitionTitle -cnotmatch
            '\ACDX_P_[0-9]{13}_[0-9a-f]{6}\z' -or
        (ConvertTo-FiniteNumber $Request.mouseDownCalls 'PList double-click mouse-down count') -ne 2 -or
        (ConvertTo-FiniteNumber $Request.mouseUpCalls 'PList double-click mouse-up count') -ne 2 -or
        (ConvertTo-FiniteNumber $Request.doubleClickIntervalMilliseconds `
            'PList double-click interval') -ne 100) {
        Throw-SafeFailure 'The named-playlist double-click identity/count contract is invalid.'
    }

    $content = @($Request.expectedPlaylistContent)
    if ($content.Count -ne 3) {
        Throw-SafeFailure 'The named-playlist double-click does not preserve exactly three rows.'
    }
    foreach ($row in $content) {
        Assert-ExactJsonPropertyNames $row @(
            'isEnabled', 'marketText', 'stockName', 'graphicType',
            'subtype', 'pageText') 'Named-playlist expected row'
        if ($row.isEnabled -ne $true -or
            $row.marketText -isnot [string] -or
            $row.stockName -isnot [string] -or
            $row.graphicType -isnot [string] -or
            $row.subtype -isnot [string] -or
            $row.pageText -isnot [string] -or
            [string]$row.graphicType -cne $ExpectedSavedFixtureGraphicType) {
            Throw-SafeFailure 'The named-playlist expected row is outside the exact saved fixture.'
        }
    }
    $subtypes = @($content | ForEach-Object { [string]$_.subtype })
    if (-not (Test-ExactStringSequence $subtypes @(
                $ExpectedSavedFixtureCurrentSubtype,
                $ExpectedSavedFixtureCurrentSubtype,
                $ExpectedSavedFixtureAfterHoursSubtype))) {
        Throw-SafeFailure 'The named-playlist expected row order is not the saved three-row fixture.'
    }

    $viewportWidth = ConvertTo-FiniteNumber $Request.viewport.width `
        'PList double-click viewport width'
    $viewportHeight = ConvertTo-FiniteNumber $Request.viewport.height `
        'PList double-click viewport height'
    $devicePixelRatio = ConvertTo-FiniteNumber $Request.devicePixelRatio `
        'PList double-click device pixel ratio'
    if ($viewportWidth -lt 1 -or $viewportWidth -gt 16384 -or
        $viewportHeight -lt 1 -or $viewportHeight -gt 16384 -or
        $devicePixelRatio -lt 0.25 -or $devicePixelRatio -gt 5) {
        Throw-SafeFailure 'The named-playlist double-click viewport contract is invalid.'
    }
    $point = ConvertTo-ExactInputPoint $Request.point $viewportWidth $viewportHeight `
        'Named-playlist double-click point'
    [LegacyPackageInputNative]::SendApplicationDoubleClick(
        $Application.MainWindowHandle, $Application.Id, 30001,
        $point.X, $point.Y, $viewportWidth, $viewportHeight,
        $devicePixelRatio, 100)
}

function Get-BackgroundPickerWindowHandles {
    $handles = New-Object 'Collections.Generic.HashSet[int64]'
    foreach ($handle in [LegacyPackageInputNative]::VisibleTopLevelWindows()) {
        if ($handle -ne [IntPtr]::Zero) { [void]$handles.Add($handle.ToInt64()) }
    }
    return $handles
}

function Get-OwnedBackgroundPickerCandidates(
    [Collections.Generic.HashSet[int64]]$BaselineHandles,
    [Diagnostics.Process]$Application) {
    $candidates = @()
    foreach ($handle in [LegacyPackageInputNative]::VisibleTopLevelWindows()) {
        try {
            if ($handle -eq [IntPtr]::Zero -or
                $BaselineHandles.Contains($handle.ToInt64()) -or
                -not [LegacyPackageInputNative]::WindowVisible($handle) -or
                -not [LegacyPackageInputNative]::WindowEnabled($handle) -or
                [LegacyPackageInputNative]::WindowProcessId($handle) -ne $Application.Id -or
                -not [LegacyPackageInputNative]::OwnerChainContains(
                    $handle,
                    $Application.MainWindowHandle) -or
                [LegacyPackageInputNative]::WindowClassName($handle) -cne '#32770' -or
                [LegacyPackageInputNative]::WindowTitle($handle) -cne
                    $BackgroundPickerTitle) {
                continue
            }
            $candidates += [pscustomobject]@{
                Handle = $handle
                ProcessId = [LegacyPackageInputNative]::WindowProcessId($handle)
                OwnerLinked = $true
                SameProcess = $true
                ClassName = [LegacyPackageInputNative]::WindowClassName($handle)
                Title = [LegacyPackageInputNative]::WindowTitle($handle)
                IsModal = -not [LegacyPackageInputNative]::WindowEnabled(
                    $Application.MainWindowHandle)
            }
        }
        catch {
            # A transient shell window is ignored unless every stable condition
            # is true in one observation.
        }
    }
    return @($candidates)
}

function Wait-UniqueOwnedBackgroundPicker(
    [Collections.Generic.HashSet[int64]]$BaselineHandles,
    [Diagnostics.Process]$Application,
    [string]$ExpectedApplicationPath,
    [datetime]$Deadline) {
    while ([datetime]::UtcNow -lt $Deadline) {
        Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
        Assert-NoTornadoConnection $Application.Id
        $candidates = @(Get-OwnedBackgroundPickerCandidates `
            $BaselineHandles `
            $Application)
        if ($candidates.Count -gt 1) {
            Throw-SafeFailure 'More than one newly opened app-owned background picker exists.'
        }
        if ($candidates.Count -eq 1) {
            $picker = $candidates[0]
            if (-not [bool]$picker.IsModal) {
                Throw-SafeFailure 'The exact app-owned background picker is not modal.'
            }
            [LegacyPackageInputNative]::AcquireOwnedForeground(
                $picker.Handle,
                $Application.MainWindowHandle,
                $Application.Id,
                30001)
            Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
            Assert-NoTornadoConnection $Application.Id
            $revalidated = @(Get-OwnedBackgroundPickerCandidates `
                $BaselineHandles `
                $Application)
            if ($revalidated.Count -ne 1 -or
                $revalidated[0].Handle -ne $picker.Handle -or
                [LegacyPackageInputNative]::RootWindow(
                    [LegacyPackageInputNative]::ReadForegroundWindow()) -ne
                    $picker.Handle) {
                Throw-SafeFailure (
                    'The exact app-owned background picker identity changed during foreground acquisition.')
            }
            return $picker
        }
        Start-Sleep -Milliseconds 50
    }
    Throw-SafeFailure 'The exact app-owned background picker did not appear in time.'
}

function Wait-BackgroundPickerClosed(
    [IntPtr]$PickerHandle,
    [Diagnostics.Process]$Application,
    [string]$ExpectedApplicationPath,
    [datetime]$Deadline) {
    while ([datetime]::UtcNow -lt $Deadline) {
        Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
        Assert-NoTornadoConnection $Application.Id
        if (-not [LegacyPackageInputNative]::WindowExists($PickerHandle) -and
            [LegacyPackageInputNative]::WindowEnabled($Application.MainWindowHandle)) {
            return
        }
        Start-Sleep -Milliseconds 50
    }
    Throw-SafeFailure (
        'The exact background picker was not destroyed after the one Escape input.')
}

function Invoke-ExactBackgroundF2CancelRequest(
    [object]$Request,
    [Diagnostics.Process]$Application,
    [string]$ExpectedApplicationPath) {
    Assert-ExactJsonPropertyNames $Request @(
        'schemaVersion', 'exchangeIndex', 'token', 'targetUrl', 'operation',
        'f2KeyCalls', 'escapeKeyCalls', 'inputRetryCount') `
        'F2 background picker request'
    if ((ConvertTo-FiniteNumber $Request.exchangeIndex 'F2 exchange index') -ne 2 -or
        (ConvertTo-FiniteNumber $Request.f2KeyCalls 'F2 key count') -ne 1 -or
        (ConvertTo-FiniteNumber $Request.escapeKeyCalls 'F2 Escape count') -ne 1 -or
        [string]::IsNullOrEmpty([string]$script:BackgroundShortcutRoot)) {
        Throw-SafeFailure 'The F2 background picker request is outside the exact contract.'
    }
    $defaultPath = Join-Path `
        ([string]$script:BackgroundShortcutRoot) `
        $LegacyDefaultBackgroundFileName
    if ([IO.File]::Exists($defaultPath) -or [IO.Directory]::Exists($defaultPath)) {
        Throw-SafeFailure 'The external default background appeared before F2 input.'
    }

    $baseline = Get-BackgroundPickerWindowHandles
    [LegacyPackageInputNative]::SendBackgroundFunctionKey(
        $Application.MainWindowHandle,
        $Application.Id,
        30001,
        0x71,
        $true)
    $picker = Wait-UniqueOwnedBackgroundPicker `
        $baseline `
        $Application `
        $ExpectedApplicationPath `
        ([datetime]::UtcNow.AddSeconds(10))
    [LegacyPackageInputNative]::SendEscapeToForegroundWindow($picker.Handle)
    Wait-BackgroundPickerClosed `
        $picker.Handle `
        $Application `
        $ExpectedApplicationPath `
        ([datetime]::UtcNow.AddSeconds(10))
    Start-Sleep -Milliseconds 300
    Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
    Assert-NoTornadoConnection $Application.Id
    return [ordered]@{
        f2KeyCalls = 1
        escapeKeyCalls = 1
        pickerUniqueNew = $true
        pickerOwnerLinked = [bool]$picker.OwnerLinked
        pickerSameProcess = [bool]$picker.SameProcess
        pickerClass = [string]$picker.ClassName
        pickerTitle = [string]$picker.Title
        pickerModal = [bool]$picker.IsModal
        pickerClosedAfterEscape = $true
    }
}

function Invoke-ExactBackgroundF3NoneRequest(
    [object]$Request,
    [Diagnostics.Process]$Application,
    [string]$ExpectedApplicationPath) {
    Assert-ExactJsonPropertyNames $Request @(
        'schemaVersion', 'exchangeIndex', 'token', 'targetUrl', 'operation',
        'f3KeyCalls', 'inputRetryCount') 'F3 background-none request'
    if ((ConvertTo-FiniteNumber $Request.exchangeIndex 'F3 exchange index') -ne 3 -or
        (ConvertTo-FiniteNumber $Request.f3KeyCalls 'F3 key count') -ne 1 -or
        [string]::IsNullOrEmpty([string]$script:BackgroundShortcutRoot)) {
        Throw-SafeFailure 'The F3 background-none request is outside the exact contract.'
    }
    $defaultPath = Join-Path `
        ([string]$script:BackgroundShortcutRoot) `
        $LegacyDefaultBackgroundFileName
    if ([IO.File]::Exists($defaultPath) -or [IO.Directory]::Exists($defaultPath)) {
        Throw-SafeFailure (
            'The external default background appeared; the one F3 fail-closed input was not sent.')
    }
    [LegacyPackageInputNative]::SendBackgroundFunctionKey(
        $Application.MainWindowHandle,
        $Application.Id,
        30001,
        0x72,
        $false)
    Start-Sleep -Milliseconds 300
    Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
    Assert-NoTornadoConnection $Application.Id
    return [ordered]@{ f3KeyCalls = 1 }
}

function Invoke-ExactWindowsInputRequest(
    [string]$RequestPath,
    [string]$AcknowledgementPath,
    [int]$ExpectedExchangeIndex,
    [Diagnostics.Process]$Application,
    [string]$ExpectedApplicationPath) {
    $script:WindowsInputRequestCalls++
    if ($script:WindowsInputRequestCalls -ne $ExpectedExchangeIndex -or
        [IO.File]::Exists($AcknowledgementPath)) {
        Throw-SafeFailure 'The Windows input one-shot budget or acknowledgement precondition changed.'
    }

    $requestEvidence = Wait-ReadSmallJsonEvidenceFile `
        $RequestPath `
        'Windows input request' `
        ([datetime]::UtcNow.AddSeconds(3))
    $request = $requestEvidence.Value
    $token = [string]$request.token
    $schemaVersion = ConvertTo-FiniteNumber $request.schemaVersion 'Windows input schema version'
    if ($request.token -isnot [string] -or
        $request.targetUrl -isnot [string] -or
        $request.operation -isnot [string] -or
        $schemaVersion -ne 1 -or
        (ConvertTo-FiniteNumber $request.exchangeIndex 'Windows input exchange index') -ne
            $ExpectedExchangeIndex -or
        $token -cnotmatch '\A[0-9A-F]{32}\z' -or
        [string]$request.targetUrl -cne 'https://legacy-parity.mbn.local/index.html' -or
        (ConvertTo-FiniteNumber $request.inputRetryCount 'Windows input retry count') -ne 0) {
        Throw-SafeFailure 'The Windows input request does not match the common closed contract.'
    }
    $inputCounts = [ordered]@{}
    $operation = [string]$request.operation
    Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
    Assert-NoTornadoConnection $Application.Id
    switch -CaseSensitive ($operation) {
        'row-header-drag-home-shift-range-delete-restore' {
            Invoke-ExactPlaylistWindowsInputRequest `
                $request `
                $Application
            $inputCounts = [ordered]@{
                mouseDownCalls = 4
                mouseUpCalls = 4
                homeKeyCalls = 1
                shiftKeyDownCalls = 1
                shiftKeyUpCalls = 1
                deleteKeyCalls = 1
            }
            break
        }
        'named-playlist-load-double-click' {
            if ($ExpectedExchangeIndex -ne 2) {
                Throw-SafeFailure 'The named-playlist double-click is not the second exchange.'
            }
            Invoke-ExactNamedPlaylistDoubleClickRequest `
                $request `
                $Application
            $inputCounts = [ordered]@{
                mouseDownCalls = 2
                mouseUpCalls = 2
                doubleClickIntervalMilliseconds = 100
            }
            break
        }
        'background-f2-picker-cancel' {
            if ($ExpectedExchangeIndex -ne 2) {
                Throw-SafeFailure 'The F2 background picker is not the second exchange.'
            }
            $inputCounts = Invoke-ExactBackgroundF2CancelRequest `
                $request `
                $Application `
                $ExpectedApplicationPath
            break
        }
        'background-f3-none' {
            if ($ExpectedExchangeIndex -ne 3) {
                Throw-SafeFailure 'The F3 background-none input is not the third exchange.'
            }
            $inputCounts = Invoke-ExactBackgroundF3NoneRequest `
                $request `
                $Application `
                $ExpectedApplicationPath
            break
        }
        default {
            Throw-SafeFailure 'The Windows input operation is outside the closed allowlist.'
        }
    }
    Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
    Assert-NoTornadoConnection $Application.Id

    $script:WindowsInputAcknowledgementCalls++
    if ($script:WindowsInputAcknowledgementCalls -ne $ExpectedExchangeIndex) {
        Throw-SafeFailure 'The Windows input acknowledgement budget changed.'
    }
    $acknowledgementEvidence = Write-WindowsInputAcknowledgement `
        $AcknowledgementPath `
        $ExpectedExchangeIndex `
        $token `
        $operation `
        $inputCounts
    return [pscustomobject]@{
        ExchangeIndex = $ExpectedExchangeIndex
        Operation = $operation
        RequestPath = $RequestPath
        AcknowledgementPath = $AcknowledgementPath
        RequestSha256 = $requestEvidence.Sha256
        AcknowledgementSha256 = $acknowledgementEvidence.Sha256
    }
}

function Invoke-NodeHarnessUnderTcpWatch(
    [string]$Executable,
    [string]$ScriptPath,
    [int]$DebugPort,
    [string]$OutputPath,
    [string]$ScreenshotPath,
    [string]$WindowsInputRequestPath,
    [string]$WindowsInputAcknowledgementPath,
    [string]$HarnessProfile,
    [string]$HarnessScope,
    [string]$RecoverNamedPlaylistTitle,
    [int]$TimeoutSeconds,
    [Diagnostics.Process]$Application,
    [string]$ExpectedApplicationPath) {
    $rawArguments = @(
        $ScriptPath,
        '--port',
        [string]$DebugPort,
        '--output',
        $OutputPath,
        '--screenshot',
        $ScreenshotPath,
        '--windows-input-request',
        $WindowsInputRequestPath,
        '--windows-input-ack',
        $WindowsInputAcknowledgementPath,
        '--profile',
        $HarnessProfile,
        '--scope',
        $HarnessScope,
        '--timeout-ms',
        [string]($TimeoutSeconds * 1000)
    )
    if (-not [string]::IsNullOrEmpty($RecoverNamedPlaylistTitle)) {
        $rawArguments += @(
            '--recover-named-playlist-title',
            $RecoverNamedPlaylistTitle)
    }
    $arguments = $rawArguments |
        ForEach-Object { ConvertTo-QuotedProcessArgument ([string]$_) }

    $startInfo = New-Object Diagnostics.ProcessStartInfo
    $startInfo.FileName = $Executable
    $startInfo.WorkingDirectory = $RepositoryRoot
    $startInfo.Arguments = $arguments -join ' '
    $startInfo.UseShellExecute = $false
    $startInfo.CreateNoWindow = $true
    $startInfo.RedirectStandardInput = $true
    try {
        $nodeProcess = [Diagnostics.Process]::Start($startInfo)
    }
    catch {
        Throw-SafeFailure 'The real input harness process could not be started.'
    }
    if ($null -eq $nodeProcess) {
        Throw-SafeFailure 'The real input harness process did not start.'
    }

    $deadline = [datetime]::UtcNow.AddSeconds($TimeoutSeconds + 30)
    $monitoringFailure = $null
    $expectedWindowsInputExchangeCount = Get-ExpectedWindowsInputExchangeCount `
        $HarnessProfile `
        $HarnessScope
    $nextWindowsInputExchangeIndex = 1
    $windowsInputEvidence = New-Object 'Collections.Generic.List[object]'
    try {
        while (-not $nodeProcess.HasExited) {
            if ([datetime]::UtcNow -ge $deadline) {
                Throw-SafeFailure 'The input harness exceeded its global deadline.'
            }
            Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
            Assert-NoTornadoConnection $Application.Id
            if ($nextWindowsInputExchangeIndex -le $expectedWindowsInputExchangeCount) {
                $nextRequestPath = Get-WindowsInputExchangePath `
                    $WindowsInputRequestPath `
                    $nextWindowsInputExchangeIndex
                $nextAcknowledgementPath = Get-WindowsInputExchangePath `
                    $WindowsInputAcknowledgementPath `
                    $nextWindowsInputExchangeIndex
            }
            if ($nextWindowsInputExchangeIndex -le $expectedWindowsInputExchangeCount -and
                [IO.File]::Exists($nextRequestPath)) {
                $exchangeEvidence = Invoke-ExactWindowsInputRequest `
                    $nextRequestPath `
                    $nextAcknowledgementPath `
                    $nextWindowsInputExchangeIndex `
                    $Application `
                    $ExpectedApplicationPath
                [void]$windowsInputEvidence.Add($exchangeEvidence)
                $nextWindowsInputExchangeIndex++
            }
            Start-Sleep -Milliseconds 100
            $nodeProcess.Refresh()
        }

        if ($nextWindowsInputExchangeIndex -ne ($expectedWindowsInputExchangeCount + 1) -or
            $windowsInputEvidence.Count -ne $expectedWindowsInputExchangeCount -or
            $script:WindowsInputRequestCalls -ne $expectedWindowsInputExchangeCount -or
            $script:WindowsInputAcknowledgementCalls -ne $expectedWindowsInputExchangeCount) {
            Throw-SafeFailure 'The required ordered one-shot Windows input exchanges were not completed.'
        }
        for ($exchangeIndex = 1;
            $exchangeIndex -le $expectedWindowsInputExchangeCount;
            $exchangeIndex++) {
            if (-not [IO.File]::Exists((Get-WindowsInputExchangePath `
                    $WindowsInputRequestPath `
                    $exchangeIndex)) -or
                -not [IO.File]::Exists((Get-WindowsInputExchangePath `
                    $WindowsInputAcknowledgementPath `
                    $exchangeIndex))) {
                Throw-SafeFailure 'A required Windows input exchange file is missing.'
            }
        }
        Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
        Assert-NoTornadoConnection $Application.Id
    }
    catch {
        $monitoringFailure = $_.Exception.Message
    }

    if ($null -ne $monitoringFailure) {
        $helperStopped = $nodeProcess.HasExited
        if (-not $helperStopped) {
            try {
                $nodeProcess.StandardInput.WriteLine('CANCEL')
                $nodeProcess.StandardInput.Flush()
                $helperStopped = $nodeProcess.WaitForExit(5000)
            }
            catch {
                $helperStopped = $false
            }
        }
        if (-not $helperStopped) {
            try {
                # Only the child Node input driver is terminated after its one-shot
                # cancellation cleanup failed. The packaged app remains open.
                $nodeProcess.Kill()
                $helperStopped = $nodeProcess.WaitForExit(10000)
            }
            catch {
                $helperStopped = $false
            }
        }
        if (-not $helperStopped) {
            Throw-SafeFailure (
                "$monitoringFailure The Node input helper could not be stopped; " +
                'the application was left open and no close was attempted.')
        }

        Throw-SafeFailure (
            "$monitoringFailure The Node input helper was stopped; " +
            'the application was left open and no close was attempted.')
    }

    return [pscustomobject]@{
        ExitCode = $nodeProcess.ExitCode
        # Windows PowerShell 5.1 throws "Argument types do not match" when an
        # array subexpression directly enumerates List[object]. Materialize the
        # completed one-shot evidence before returning it to the sealing phase.
        WindowsInput = @($windowsInputEvidence.ToArray())
    }
}

function Test-ProcessDescendsFrom([int]$ProcessId, [int]$ExpectedAncestorId) {
    $visited = New-Object 'Collections.Generic.HashSet[int]'
    $current = $ProcessId
    for ($depth = 0; $depth -lt 12; $depth++) {
        if ($current -eq $ExpectedAncestorId) {
            return $true
        }

        if ($current -le 0 -or -not $visited.Add($current)) {
            return $false
        }

        try {
            $record = Get-CimInstance Win32_Process -Filter "ProcessId = $current" `
                -ErrorAction Stop
        }
        catch {
            return $false
        }
        if ($null -eq $record) {
            return $false
        }

        $current = [int]$record.ParentProcessId
    }

    return $false
}

function Wait-ExactLoopbackListener(
    [int]$CandidatePort,
    [Diagnostics.Process]$Application,
    [datetime]$Deadline) {
    while ([datetime]::UtcNow -lt $Deadline) {
        if ($Application.HasExited) {
            Throw-SafeFailure 'The application exited before the WebView listener appeared.'
        }

        $listeners = @(Get-TcpSnapshot | Where-Object {
                [string]$_.State -ceq 'Listen' -and
                $_.LocalPort -eq $CandidatePort
            })
        if ($listeners.Count -gt 1) {
            Throw-SafeFailure 'More than one process is listening on the WebView debugging port.'
        }

        if ($listeners.Count -eq 1) {
            $listener = $listeners[0]
            if ([string]$listener.LocalAddress -cne '127.0.0.1') {
                Throw-SafeFailure 'The WebView debugging listener is not bound to exact IPv4 loopback.'
            }

            try {
                $owner = Get-Process -Id ([int]$listener.OwningProcess) -ErrorAction Stop
                $ownerPath = $owner.Path
            }
            catch {
                Throw-SafeFailure 'The WebView debugging listener owner could not be identified.'
            }

            if ([string]$owner.ProcessName -cne 'msedgewebview2' -or
                [IO.Path]::GetFileName($ownerPath) -cne 'msedgewebview2.exe' -or
                -not (Test-ProcessDescendsFrom $owner.Id $Application.Id)) {
                Throw-SafeFailure 'The WebView debugging listener is not owned by this application.'
            }

            return $listener
        }

        Start-Sleep -Milliseconds 100
    }

    Throw-SafeFailure 'The exact WebView debugging listener did not appear in time.'
}

function Get-StartedApplication(
    [string]$ExpectedPath,
    [datetime]$NotBefore,
    [datetime]$Deadline) {
    while ([datetime]::UtcNow -lt $Deadline) {
        $processes = @(Get-LegacyApplicationProcesses)
        if ($processes.Count -gt 1) {
            Throw-SafeFailure 'More than one LegacyParity process appeared after launch.'
        }

        if ($processes.Count -eq 1) {
            $process = $processes[0]
            try {
                $process.Refresh()
                $path = $process.Path
                $startUtc = $process.StartTime.ToUniversalTime()
            }
            catch {
                # A packaged full-trust process can appear in the process table a
                # few milliseconds before Path/StartTime become queryable. It has
                # not received any test input yet, so keep the launch gate closed
                # and retry only while it owns no Tornado connection.
                Assert-NoTornadoConnection $process.Id
                Start-Sleep -Milliseconds 50
                continue
            }

            if ([string]::IsNullOrWhiteSpace([string]$path)) {
                Assert-NoTornadoConnection $process.Id
                Start-Sleep -Milliseconds 50
                continue
            }

            if (-not (Test-PathEqual $path $ExpectedPath) -or
                $startUtc -lt $NotBefore.AddSeconds(-1)) {
                Throw-SafeFailure 'The launched application identity is not exact.'
            }

            try {
                $cim = Get-CimInstance Win32_Process -Filter "ProcessId = $($process.Id)" `
                    -ErrorAction Stop
            }
            catch {
                Throw-SafeFailure 'The launched application command line could not be inspected.'
            }
            if ($null -eq $cim -or
                [string]::IsNullOrWhiteSpace([string]$cim.CommandLine) -or
                [string]$cim.CommandLine -match '(?i)(?:^|\s)--development-live(?:\s|$)') {
                Throw-SafeFailure 'The Release application launch arguments are not safe.'
            }

            Assert-ExactProcessPackageIdentity $process
            return $process
        }

        Start-Sleep -Milliseconds 100
    }

    Throw-SafeFailure 'The packaged Release application did not start in time.'
}

function Start-PackagedDryRunApplication(
    [pscustomobject]$Registration,
    [int]$DebugPort) {
    $invokeCommand = Get-Command Invoke-CommandInDesktopPackage -ErrorAction SilentlyContinue
    if ($null -eq $invokeCommand -or [string]$invokeCommand.Source -cne 'Appx') {
        Throw-SafeFailure 'Invoke-CommandInDesktopPackage from the Appx module is required.'
    }

    $childPowerShell = Join-Path $env:SystemRoot `
        'System32\WindowsPowerShell\v1.0\powershell.exe'
    if (-not [IO.File]::Exists($childPowerShell)) {
        Throw-SafeFailure 'The child Windows PowerShell executable is missing.'
    }

    $executableBase64 = [Convert]::ToBase64String(
        [Text.Encoding]::UTF8.GetBytes($Registration.Executable))
    $workingDirectoryBase64 = [Convert]::ToBase64String(
        [Text.Encoding]::UTF8.GetBytes($Registration.InstallLocation))
    $browserArguments = "--remote-debugging-address=127.0.0.1 --remote-debugging-port=$DebugPort"
    $browserArgumentsBase64 = [Convert]::ToBase64String(
        [Text.Encoding]::UTF8.GetBytes($browserArguments))
    $childScript = @"
`$ErrorActionPreference = 'Stop'
`$executable = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('$executableBase64'))
`$workingDirectory = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('$workingDirectoryBase64'))
`$browserArguments = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('$browserArgumentsBase64'))
foreach (`$nameObject in @([Environment]::GetEnvironmentVariables([EnvironmentVariableTarget]::Process).Keys)) {
    `$name = [string]`$nameObject
    if (`$name -like 'MBN_STOCK_PLAYOUT_*' -or `$name -like 'WEBVIEW2_*' -or
        `$name -like 'COREWEBVIEW2_*' -or `$name -ceq '$K3dNativeHashVariable' -or
        `$name -ceq '$K3dInteropHashVariable') {
        [Environment]::SetEnvironmentVariable(`$name, `$null, [EnvironmentVariableTarget]::Process)
    }
}
[Environment]::SetEnvironmentVariable('MBN_STOCK_PLAYOUT_MODE', 'DryRun', [EnvironmentVariableTarget]::Process)
[Environment]::SetEnvironmentVariable('$WebViewArgumentsVariable', `$browserArguments, [EnvironmentVariableTarget]::Process)
`$startInfo = New-Object Diagnostics.ProcessStartInfo
`$startInfo.FileName = `$executable
`$startInfo.WorkingDirectory = `$workingDirectory
`$startInfo.UseShellExecute = `$false
`$startInfo.CreateNoWindow = `$false
`$started = [Diagnostics.Process]::Start(`$startInfo)
if (`$null -eq `$started) { exit 91 }
"@
    $encodedCommand = [Convert]::ToBase64String(
        [Text.Encoding]::Unicode.GetBytes($childScript))
    $childArguments = "-NoLogo -NoProfile -NonInteractive -WindowStyle Hidden -EncodedCommand $encodedCommand"

    $notBefore = [datetime]::UtcNow
    try {
        [void](Invoke-CommandInDesktopPackage `
            -PackageFamilyName $PackageFamilyName `
            -AppId $ApplicationId `
            -Command $childPowerShell `
            -Args $childArguments `
            -PreventBreakaway `
            -ErrorAction Stop)
    }
    catch {
        Throw-SafeFailure 'The package-context launch helper failed.'
    }

    $deadline = [datetime]::UtcNow.AddSeconds($LaunchTimeoutSeconds)
    return Get-StartedApplication $Registration.Executable $notBefore $deadline
}

function Assert-ExactApplicationStillRunning(
    [Diagnostics.Process]$Application,
    [string]$ExpectedPath) {
    try {
        $Application.Refresh()
        if ($Application.HasExited -or
            -not (Test-PathEqual $Application.Path $ExpectedPath) -or
            $Application.MainWindowHandle -eq [IntPtr]::Zero -or
            [string]$Application.MainWindowTitle -cne $ExpectedWindowTitle) {
            Throw-SafeFailure 'The application identity changed during the input smoke test.'
        }
        Assert-ExactProcessPackageIdentity $Application
    }
    catch [InvalidOperationException] {
        throw
    }
    catch {
        Throw-SafeFailure 'The application identity could not be revalidated.'
    }
}

function Wait-StartupIntroDismissed(
    [Diagnostics.Process]$Application,
    [string]$ExpectedPath) {
    Add-Type -AssemblyName UIAutomationClient
    Add-Type -AssemblyName UIAutomationTypes

    $deadline = [datetime]::UtcNow.AddSeconds(4)
    $nameCondition = [Windows.Automation.PropertyCondition]::new(
        [Windows.Automation.AutomationElement]::NameProperty,
        '매일경제TV V-STOCK 시작 화면')

    while ($true) {
        Assert-ExactApplicationStillRunning $Application $ExpectedPath
        Assert-NoTornadoConnection $Application.Id
        $Application.Refresh()
        $root = [Windows.Automation.AutomationElement]::FromHandle(
            $Application.MainWindowHandle)
        if ($null -eq $root) {
            Throw-SafeFailure 'The main window is unavailable while waiting for the startup intro.'
        }

        $intro = $root.FindFirst(
            [Windows.Automation.TreeScope]::Descendants,
            $nameCondition)
        $introIsVisible = $false
        if ($null -ne $intro) {
            try {
                $introIsVisible = -not $intro.Current.IsOffscreen
            }
            catch [System.Windows.Automation.ElementNotAvailableException] {
                $introIsVisible = $false
            }
        }

        if (-not $introIsVisible) {
            Assert-ExactApplicationStillRunning $Application $ExpectedPath
            Assert-NoTornadoConnection $Application.Id
            return
        }
        if ([datetime]::UtcNow -ge $deadline) {
            break
        }

        $remainingMilliseconds = [int][Math]::Max(
            1,
            [Math]::Min(50, ($deadline - [datetime]::UtcNow).TotalMilliseconds))
        Start-Sleep -Milliseconds $remainingMilliseconds
    }

    Assert-ExactApplicationStillRunning $Application $ExpectedPath
    Assert-NoTornadoConnection $Application.Id
    Throw-SafeFailure 'The startup intro remained visible beyond its four-second bound.'
}

function Assert-NoExistingContentDialog([IntPtr]$MainWindowHandle) {
    Add-Type -AssemblyName UIAutomationClient
    Add-Type -AssemblyName UIAutomationTypes
    $root = [Windows.Automation.AutomationElement]::FromHandle($MainWindowHandle)
    if ($null -eq $root) {
        Throw-SafeFailure 'The main window is unavailable to UI Automation.'
    }

    $all = $root.FindAll(
        [Windows.Automation.TreeScope]::Descendants,
        [Windows.Automation.Condition]::TrueCondition)
    for ($index = 0; $index -lt $all.Count; $index++) {
        $element = $all[$index]
        if ($element.Current.ControlType -eq [Windows.Automation.ControlType]::Window -and
            [string]$element.Current.ClassName -ceq 'Popup') {
            Throw-SafeFailure 'A dialog was already open before the normal close request.'
        }
    }
}

function Assert-SingleInstanceActivation(
    [Diagnostics.Process]$Application,
    [string]$ExpectedPath) {
    Assert-ExactApplicationStillRunning $Application $ExpectedPath
    $Application.Refresh()
    $expectedId = $Application.Id
    $expectedStartUtc = $Application.StartTime.ToUniversalTime()
    $expectedHandle = $Application.MainWindowHandle
    $expectedTitle = $Application.MainWindowTitle
    $preActivationProcesses = @(Get-LegacyApplicationProcesses)
    if ($preActivationProcesses.Count -ne 1 -or
        $preActivationProcesses[0].Id -ne $expectedId) {
        Throw-SafeFailure 'Single-instance activation requires exactly the pinned original process.'
    }
    Assert-NoTornadoConnection $expectedId

    $explorer = Join-Path $env:SystemRoot 'explorer.exe'
    if (-not [IO.File]::Exists($explorer)) {
        Throw-SafeFailure 'Explorer is unavailable for the single-instance activation check.'
    }

    $script:SingleInstanceActivationCalls++
    if ($script:SingleInstanceActivationCalls -ne 1) {
        Throw-SafeFailure 'The single-instance activation budget changed.'
    }
    $activationRequestedUtc = [datetime]::UtcNow
    try {
        [void](Start-Process `
            -FilePath $explorer `
            -ArgumentList "shell:AppsFolder\$PackageFamilyName!$ApplicationId" `
            -WindowStyle Hidden `
            -PassThru `
            -ErrorAction Stop)
    }
    catch {
        Throw-SafeFailure 'The single-instance package activation could not be requested.'
    }

    $redirector = $null
    $redirectorId = $null
    $redirectorStartUtc = $null
    $redirectorExited = $false
    $stableOriginalSinceUtc = $null
    $deadline = [datetime]::UtcNow.AddSeconds(8)
    while ([datetime]::UtcNow -lt $deadline) {
        $processes = @(Get-LegacyApplicationProcesses)
        $originals = @($processes | Where-Object { $_.Id -eq $expectedId })
        $additional = @($processes | Where-Object { $_.Id -ne $expectedId })
        if ($originals.Count -ne 1 -or $additional.Count -gt 1) {
            Throw-SafeFailure 'Package activation did not preserve one original and at most one redirector.'
        }

        $process = $originals[0]
        try {
            $process.Refresh()
            $sameIdentity = $process.Id -eq $expectedId -and
                (Test-PathEqual $process.Path $ExpectedPath) -and
                $process.StartTime.ToUniversalTime() -eq $expectedStartUtc -and
                $process.MainWindowHandle -eq $expectedHandle -and
                [string]$process.MainWindowTitle -ceq $expectedTitle
        }
        catch {
            $sameIdentity = $false
        }
        if (-not $sameIdentity) {
            Throw-SafeFailure 'Package activation changed the running application identity.'
        }

        Assert-ExactProcessPackageIdentity $process
        Assert-NoTornadoConnection $expectedId

        if ($additional.Count -eq 1) {
            if ($redirectorExited) {
                Throw-SafeFailure 'A second redirector appeared after the verified redirector exited.'
            }

            $candidate = $additional[0]
            try {
                # The AppLifecycle redirector can exit within a few milliseconds.
                # Pin and verify its package handle before reading slower Process
                # properties so a legitimate fast redirect is not misclassified as
                # an unknown process after it has already terminated.
                $candidatePackageFullName =
                    [LegacyPackageInputNative]::ReadPackageFullName($candidate.Handle)
                $candidate.Refresh()
                $candidateId = $candidate.Id
                $candidateStartUtc = $candidate.StartTime.ToUniversalTime()
                $candidatePath = $candidate.Path
                $candidateHandle = $candidate.MainWindowHandle
                $candidateTitle = [string]$candidate.MainWindowTitle
            }
            catch {
                Throw-SafeFailure 'The transient activation redirector could not be inspected exactly.'
            }

            if ($candidateStartUtc -lt $activationRequestedUtc -or
                [string]$candidatePackageFullName -cne $PackageFullName -or
                -not (Test-PathEqual $candidatePath $ExpectedPath) -or
                $candidateHandle -ne [IntPtr]::Zero -or
                -not [string]::IsNullOrEmpty($candidateTitle)) {
                Throw-SafeFailure 'The transient activation redirector identity is not exact.'
            }
            Assert-NoTornadoConnection $candidateId

            if ($null -eq $redirectorId) {
                $redirector = $candidate
                $redirectorId = $candidateId
                $redirectorStartUtc = $candidateStartUtc
            }
            elseif ($candidateId -ne $redirectorId -or
                $candidateStartUtc -ne $redirectorStartUtc) {
                Throw-SafeFailure 'More than one transient activation redirector was observed.'
            }

            # Command-line inspection is opportunistic because a redirector may exit
            # between the native identity checks and the management query.
            try {
                $cimRows = @(Get-CimInstance Win32_Process `
                        -Filter "ProcessId = $candidateId" `
                        -ErrorAction Stop)
                if ($cimRows.Count -gt 1) {
                    Throw-SafeFailure 'The transient redirector command line is not unique.'
                }
                if ($cimRows.Count -eq 1 -and
                    -not [string]::IsNullOrWhiteSpace([string]$cimRows[0].CommandLine) -and
                    [string]$cimRows[0].CommandLine -match
                        '(?i)(?:^|\s)--development-live(?:[=\s]|$)') {
                    Throw-SafeFailure 'The transient redirector used a development-live argument.'
                }
            }
            catch [InvalidOperationException] {
                throw
            }
            catch {
                # The already-verified transient may exit before CIM can inspect it.
            }

            $stableOriginalSinceUtc = $null
        }
        elseif ($null -ne $redirectorId) {
            try {
                $redirector.Refresh()
                $isRedirectorExited = $redirector.HasExited
            }
            catch {
                $isRedirectorExited = $true
            }
            if (-not $isRedirectorExited) {
                Throw-SafeFailure 'The pinned redirector disappeared from exact process enumeration before exit.'
            }

            if (-not $redirectorExited) {
                $redirectorExited = $true
                $stableOriginalSinceUtc = [datetime]::UtcNow
            }
            elseif ($null -eq $stableOriginalSinceUtc) {
                $stableOriginalSinceUtc = [datetime]::UtcNow
            }

            if (([datetime]::UtcNow - $stableOriginalSinceUtc).TotalMilliseconds -ge 750) {
                $stableOriginalMilliseconds = [int][Math]::Floor(
                    ([datetime]::UtcNow - $stableOriginalSinceUtc).TotalMilliseconds)
                Assert-ExactApplicationStillRunning $Application $ExpectedPath
                Assert-NoTornadoConnection $expectedId
                return [pscustomobject]@{
                    ActivationCalls = $script:SingleInstanceActivationCalls
                    ProcessCount = 1
                    ProcessId = $expectedId
                    StartTimeUtc = $expectedStartUtc.ToString('o')
                    MainWindowHandle = [int64]$expectedHandle
                    RedirectorProcessId = $redirectorId
                    RedirectorStartTimeUtc = $redirectorStartUtc.ToString('o')
                    RedirectorExited = $true
                    StableOriginalMilliseconds = $stableOriginalMilliseconds
                }
            }
        }

        Start-Sleep -Milliseconds 25
    }

    if ($null -eq $redirectorId) {
        Throw-SafeFailure 'The single activation did not expose one verifiable transient redirector.'
    }
    if (-not $redirectorExited) {
        Throw-SafeFailure 'The verified transient activation redirector did not exit in time.'
    }
    Throw-SafeFailure 'The original instance was not stable alone for 750 milliseconds.'
}

function Wait-ExactNeutralCloseDialog(
    [IntPtr]$MainWindowHandle,
    [Diagnostics.Process]$Application,
    [datetime]$Deadline) {
    while ([datetime]::UtcNow -lt $Deadline) {
        if ($Application.HasExited) {
            Throw-SafeFailure 'The application exited before close confirmation.'
        }
        Assert-NoTornadoConnection $Application.Id

        $root = [Windows.Automation.AutomationElement]::FromHandle($MainWindowHandle)
        if ($null -eq $root) {
            Throw-SafeFailure 'The main window disappeared before close confirmation.'
        }

        $all = $root.FindAll(
            [Windows.Automation.TreeScope]::Descendants,
            [Windows.Automation.Condition]::TrueCondition)
        $matches = New-Object Collections.Generic.List[object]
        for ($index = 0; $index -lt $all.Count; $index++) {
            $element = $all[$index]
            if ($element.Current.ControlType -eq [Windows.Automation.ControlType]::Window -and
                [string]$element.Current.ClassName -ceq 'Popup' -and
                [string]$element.Current.Name -ceq $ExpectedDialogTitle) {
                [void]$matches.Add($element)
            }
        }

        if ($matches.Count -gt 1) {
            Throw-SafeFailure 'The neutral close dialog is not unique.'
        }
        if ($matches.Count -eq 1) {
            Assert-NoTornadoConnection $Application.Id
            return $matches[0]
        }

        Start-Sleep -Milliseconds 100
    }

    Throw-SafeFailure 'The neutral close dialog did not appear in time.'
}

function Invoke-ExactNormalClose(
    [Diagnostics.Process]$Application,
    [string]$ExpectedPath) {
    Assert-ExactApplicationStillRunning $Application $ExpectedPath
    $mainWindowHandle = $Application.MainWindowHandle
    Assert-NoExistingContentDialog $mainWindowHandle

    $script:CloseMainWindowCalls++
    if ($script:CloseMainWindowCalls -ne 1 -or -not $Application.CloseMainWindow()) {
        Throw-SafeFailure 'The single normal close request was not accepted.'
    }

    $dialog = Wait-ExactNeutralCloseDialog `
        $mainWindowHandle `
        $Application `
        ([datetime]::UtcNow.AddSeconds(15))
    $descendants = $dialog.FindAll(
        [Windows.Automation.TreeScope]::Descendants,
        [Windows.Automation.Condition]::TrueCondition)
    $buttons = New-Object Collections.Generic.List[object]
    $texts = New-Object Collections.Generic.List[object]
    for ($index = 0; $index -lt $descendants.Count; $index++) {
        $element = $descendants[$index]
        if ($element.Current.ControlType -eq [Windows.Automation.ControlType]::Button) {
            [void]$buttons.Add($element)
        }
        elseif ($element.Current.ControlType -eq [Windows.Automation.ControlType]::Text) {
            [void]$texts.Add($element)
        }
    }

    $primary = @($buttons | Where-Object {
            [string]$_.Current.AutomationId -ceq 'PrimaryButton' -and
            [string]$_.Current.Name -ceq $ExpectedPrimaryButton -and
            $_.Current.IsEnabled -and -not $_.Current.IsOffscreen
        })
    $close = @($buttons | Where-Object {
            [string]$_.Current.AutomationId -ceq 'CloseButton' -and
            [string]$_.Current.Name -ceq $ExpectedCloseButton -and
            $_.Current.IsEnabled -and -not $_.Current.IsOffscreen
        })
    $message = @($texts | Where-Object {
            [string]$_.Current.Name -ceq $ExpectedDialogMessage
        })
    if ($buttons.Count -ne 2 -or $primary.Count -ne 1 -or
        $close.Count -ne 1 -or $message.Count -ne 1) {
        Throw-SafeFailure 'The close dialog is not the exact neutral Yes/No confirmation.'
    }

    $patternObject = $null
    if (-not $primary[0].TryGetCurrentPattern(
            [Windows.Automation.InvokePattern]::Pattern,
            [ref]$patternObject) -or
        $null -eq $patternObject) {
        Throw-SafeFailure 'The exact Yes button has no InvokePattern.'
    }

    $script:PrimaryInvokeCalls++
    if ($script:PrimaryInvokeCalls -ne 1) {
        Throw-SafeFailure 'The close confirmation invocation budget changed.'
    }
    ($patternObject -as [Windows.Automation.InvokePattern]).Invoke()

    $exitDeadline = [datetime]::UtcNow.AddSeconds(30)
    while ([datetime]::UtcNow -lt $exitDeadline) {
        $Application.Refresh()
        if ($Application.HasExited) {
            return
        }
        Assert-NoTornadoConnection $Application.Id
        Start-Sleep -Milliseconds 100
    }
    Throw-SafeFailure 'Normal application exit was not observed after the single confirmation.'
}

function Wait-PortReleased([int]$CandidatePort, [datetime]$Deadline) {
    while ([datetime]::UtcNow -lt $Deadline) {
        $listeners = @(Get-TcpSnapshot | Where-Object {
                [string]$_.State -ceq 'Listen' -and
                $_.LocalPort -eq $CandidatePort
            })
        if ($listeners.Count -eq 0) {
            return
        }

        Start-Sleep -Milliseconds 100
    }

    Throw-SafeFailure 'The WebView debugging listener remained after normal application exit.'
}

function Read-AndAssertHarnessEvidence(
    [string]$OutputPath,
    [string]$ScreenshotPath,
    [string]$WindowsInputRequestPath,
    [string]$WindowsInputAcknowledgementPath,
    [string]$HarnessProfile,
    [string]$HarnessScope,
    [string]$ExpectedRecoveryTitle,
    [int]$ExpectedPort,
    [int]$ExpectedTimeoutSeconds) {
    try {
        $evidence = [IO.File]::ReadAllText($OutputPath, [Text.Encoding]::UTF8) |
            ConvertFrom-Json -ErrorAction Stop
        $result = [string]$evidence.result
        $safeResult = $result -ceq 'PASS' -or $result -ceq 'PASS_WITH_WARNING'
        $warnings = @($evidence.warnings)
        $expectedProfile = switch -CaseSensitive ($HarnessProfile) {
            'FullUiDb' { 'full-ui-db'; break }
            'DryRunPlayout' { 'dry-run-playout'; break }
            'ProgramPlaylistDb' { 'program-playlist-db'; break }
            default { 'read-only' }
        }
        $expectedScope = if ($HarnessProfile -ceq 'FullUiDb') {
            $HarnessScope.ToLowerInvariant()
        }
        else {
            'all'
        }
        $expectedRecoveryRequested = -not [string]::IsNullOrEmpty(
            $ExpectedRecoveryTitle)
        $recoveryEvidence = if ($null -ne $evidence.fullUiDb) {
            $evidence.fullUiDb.namedPlaylistRecovery
        }
        else {
            $null
        }
        $namedPlaylistDeleteWriteCount = @(
            $evidence.safety.approvedDatabaseWriteMessages |
                Where-Object {
                    [string]$_.type -ceq 'delete-selected-named-playlist'
                }).Count
        $sealedRecoveryMatchCount = if ($expectedRecoveryRequested) {
            @($evidence.finalSnapshot.state.namedPlaylist.definitions |
                Where-Object {
                    [string]$_.title -ceq $ExpectedRecoveryTitle
                }).Count
        }
        else {
            0
        }
        $namedPlaylistRecoveryContractOk = if (-not $expectedRecoveryRequested) {
            $null -eq $recoveryEvidence
        }
        elseif ($null -eq $recoveryEvidence -or
            [string]$recoveryEvidence.targetTitle -cne $ExpectedRecoveryTitle -or
            ([string]$recoveryEvidence.targetTitle).Length -ne 26 -or
            [string]$recoveryEvidence.targetTitle -cnotmatch
                '^CDX_P_[0-9]{13}_[0-9a-f]{6}$' -or
            $recoveryEvidence.freshListVerified -ne $true -or
            $recoveryEvidence.exactAbsenceVerified -ne $true -or
            $sealedRecoveryMatchCount -ne 0) {
            $false
        }
        elseif ([string]$recoveryEvidence.result -ceq 'alreadyAbsent') {
            [int]$recoveryEvidence.exactMatchCount -eq 0 -and
                [int]$recoveryEvidence.writeCount -eq 0 -and
                [string]::IsNullOrEmpty(
                    [string]$recoveryEvidence.mutationOutcome) -and
                $namedPlaylistDeleteWriteCount -eq 1
        }
        elseif ([string]$recoveryEvidence.result -ceq 'deleted') {
            [int]$recoveryEvidence.exactMatchCount -eq 1 -and
                [int]$recoveryEvidence.writeCount -eq 1 -and
                @('committedFresh', 'committedOptimistic') -ccontains
                    [string]$recoveryEvidence.mutationOutcome -and
                $namedPlaylistDeleteWriteCount -eq 2
        }
        else {
            $false
        }
        $databaseWriteContractOk = if ($HarnessProfile -ceq 'FullUiDb') {
            $evidence.safety.databaseWriteIntentIssued -eq $true -and
                @($evidence.safety.approvedDatabaseWriteMessages).Count -ge 3 -and
                [string]$evidence.fullUiDb.result -ceq 'PASS' -and
                $evidence.fullUiDb.cleanupVerified -eq $true
        }
        elseif ($HarnessProfile -ceq 'ProgramPlaylistDb') {
            $evidence.safety.databaseWriteIntentIssued -eq $true -and
                @($evidence.safety.approvedDatabaseWriteMessages).Count -eq 3 -and
                @($evidence.safety.approvedDatabaseWriteMessages | Where-Object {
                        [string]$_.type -ceq 'create-named-playlist'
                    }).Count -eq 1 -and
                @($evidence.safety.approvedDatabaseWriteMessages | Where-Object {
                        [string]$_.type -ceq 'save-current-named-playlist-to'
                    }).Count -eq 1 -and
                @($evidence.safety.approvedDatabaseWriteMessages | Where-Object {
                        [string]$_.type -ceq 'delete-selected-named-playlist'
                    }).Count -eq 1 -and
                $null -eq $evidence.fullUiDb -and
                [string]$evidence.programPlaylistDb.result -ceq 'PASS' -and
                [string]$evidence.programPlaylistDb.title -ceq
                    [string]$evidence.fixture.namedPlaylistTitle -and
                ([string]$evidence.programPlaylistDb.title).Length -eq 26 -and
                [string]$evidence.programPlaylistDb.title -cmatch
                    '^CDX_P_[0-9]{13}_[0-9a-f]{6}$' -and
                -not [string]::IsNullOrWhiteSpace(
                    [string]$evidence.programPlaylistDb.definitionId) -and
                -not [string]::IsNullOrWhiteSpace(
                    [string]$evidence.programPlaylistDb.saveDefinitionId) -and
                @($evidence.safety.approvedDatabaseWriteMessages | Where-Object {
                        [string]$_.type -ceq 'create-named-playlist' -and
                        [string]$_.title -ceq
                            [string]$evidence.programPlaylistDb.title -and
                        -not [string]::IsNullOrWhiteSpace([string]$_.requestId)
                    }).Count -eq 1 -and
                @($evidence.safety.approvedDatabaseWriteMessages | Where-Object {
                        [string]$_.type -ceq 'save-current-named-playlist-to' -and
                        [string]$_.definitionId -ceq
                            [string]$evidence.programPlaylistDb.saveDefinitionId
                    }).Count -eq 1 -and
                @($evidence.safety.approvedDatabaseWriteMessages | Where-Object {
                        [string]$_.type -ceq 'delete-selected-named-playlist' -and
                        -not [string]::IsNullOrWhiteSpace([string]$_.requestId)
                    }).Count -eq 1 -and
                [int]$evidence.programPlaylistDb.rowCount -eq 3 -and
                [int]$evidence.programPlaylistDb.createWriteCount -eq 1 -and
                [int]$evidence.programPlaylistDb.saveWriteCount -eq 1 -and
                [int]$evidence.programPlaylistDb.deleteWriteCount -eq 1 -and
                $evidence.programPlaylistDb.freshDefinitionReadbackVerified -eq $true -and
                $evidence.programPlaylistDb.exactAbsenceVerified -eq $true -and
                [string]$evidence.programPlaylistDb.finalPhase -ceq 'idle' -and
                @($evidence.finalSnapshot.state.namedPlaylist.definitions |
                    Where-Object {
                        [string]$_.title -ceq
                            [string]$evidence.programPlaylistDb.title
                    }).Count -eq 0
        }
        else {
            $evidence.safety.databaseWriteIntentIssued -eq $false -and
                @($evidence.safety.approvedDatabaseWriteMessages).Count -eq 0 -and
                $null -eq $evidence.fullUiDb -and
                $null -eq $evidence.programPlaylistDb
        }
        $playoutIntentContractOk = if ($HarnessProfile -ceq 'DryRunPlayout') {
            $dryRunProgramContractOk =
                $evidence.safety.playoutIntentIssued -eq $true -and
                [string]$evidence.dryRunPlayout.result -ceq 'PASS' -and
                -not [string]::IsNullOrWhiteSpace(
                    [string]$evidence.dryRunPlayout.selectedEntryId) -and
                -not [string]::IsNullOrWhiteSpace(
                    [string]$evidence.dryRunPlayout.nextEntryId) -and
                -not [string]::IsNullOrWhiteSpace(
                    [string]$evidence.dryRunPlayout.stagedEntryId) -and
                -not [string]::IsNullOrWhiteSpace(
                    [string]$evidence.dryRunPlayout.skippedEntryId) -and
                [string]$evidence.dryRunPlayout.stagedEntryId -ceq
                    [string]$evidence.dryRunPlayout.skippedEntryId -and
                [string]$evidence.dryRunPlayout.selectedEntryId -cne
                    [string]$evidence.dryRunPlayout.nextEntryId -and
                [string]$evidence.dryRunPlayout.stagedEntryId -cne
                    [string]$evidence.dryRunPlayout.selectedEntryId -and
                [string]$evidence.dryRunPlayout.skippedEntryId -cne
                    [string]$evidence.dryRunPlayout.nextEntryId -and
                -not [string]::IsNullOrWhiteSpace(
                    [string]$evidence.dryRunPlayout.tailAppendedEntryId) -and
                [string]$evidence.dryRunPlayout.tailAppendedEntryId -cne
                    [string]$evidence.dryRunPlayout.selectedEntryId -and
                [string]$evidence.dryRunPlayout.tailAppendedEntryId -cne
                    [string]$evidence.dryRunPlayout.nextEntryId -and
                [int]$evidence.dryRunPlayout.playlistCountAfterDoubleClick -eq
                    ([int]$evidence.dryRunPlayout.playlistCountBeforeSelection + 1) -and
                [int]$evidence.dryRunPlayout.programCutSelection -ge 0 -and
                [int]$evidence.dryRunPlayout.programDragParity.cutPhysicalIndex -ge 0 -and
                -not [string]::IsNullOrWhiteSpace(
                    [string]$evidence.dryRunPlayout.programDragParity.appendedEntryId) -and
                [string]$evidence.dryRunPlayout.programDragParity.appendedEntryId -cne
                    [string]$evidence.dryRunPlayout.tailAppendedEntryId -and
                [string]$evidence.dryRunPlayout.programDragParity.appendedEntryId -cne
                    [string]$evidence.dryRunPlayout.selectedEntryId -and
                [string]$evidence.dryRunPlayout.programDragParity.appendedEntryId -cne
                    [string]$evidence.dryRunPlayout.nextEntryId -and
                [string]$evidence.dryRunPlayout.programDragParity.appendedEntryId -cne
                    [string]$evidence.dryRunPlayout.skippedEntryId -and
                [int]$evidence.dryRunPlayout.programDragParity.appendIntentCount -eq 1 -and
                [int]$evidence.dryRunPlayout.programDragParity.cleanupDeleteIntentCount -eq 1 -and
                $evidence.dryRunPlayout.programDragParity.onAirEntryPreserved -eq $true -and
                [string]$evidence.dryRunPlayout.programEnableParity.currentEntryId -ceq
                    [string]$evidence.dryRunPlayout.selectedEntryId -and
                [string]$evidence.dryRunPlayout.programEnableParity.skippedEntryId -ceq
                    [string]$evidence.dryRunPlayout.skippedEntryId -and
                [string]$evidence.dryRunPlayout.programEnableParity.nextEntryId -ceq
                    [string]$evidence.dryRunPlayout.nextEntryId -and
                [int]$evidence.dryRunPlayout.programEnableParity.futureRowCount -ge 3 -and
                $evidence.dryRunPlayout.programEnableParity.mouseCheckboxDisabled -eq $true -and
                [int]$evidence.dryRunPlayout.programEnableParity.setAllIntentCount -eq 2 -and
                $evidence.dryRunPlayout.programEnableParity.setAllAppliesEveryRow -eq $true -and
                [int]$evidence.dryRunPlayout.programEnableParity.toggleActiveIntentCount -eq 1 -and
                $evidence.dryRunPlayout.programEnableParity.endOfPlaylistObserved -eq $true -and
                $evidence.dryRunPlayout.programEnableParity.playlistNextRestored -eq $true
            $dryRunBackgroundContractOk =
                [int]$evidence.dryRunPlayout.backgroundShortcutParity.f2IntentCount -eq 1 -and
                [int]$evidence.dryRunPlayout.backgroundShortcutParity.f2KeyCalls -eq 1 -and
                [int]$evidence.dryRunPlayout.backgroundShortcutParity.escapeKeyCalls -eq 1 -and
                $evidence.dryRunPlayout.backgroundShortcutParity.pickerOwnedAndCancelled -eq $true -and
                [int]$evidence.dryRunPlayout.backgroundShortcutParity.f3IntentCount -eq 1 -and
                [int]$evidence.dryRunPlayout.backgroundShortcutParity.f3KeyCalls -eq 1 -and
                $evidence.dryRunPlayout.backgroundShortcutParity.defaultAssetAbsentFailClosed -eq $true -and
                $evidence.dryRunPlayout.backgroundShortcutParity.finalBackgroundEnabled -eq $false -and
                $evidence.dryRunPlayout.backgroundShortcutParity.finalBackgroundNoneChecked -eq $true -and
                [string]$evidence.dryRunPlayout.backgroundShortcutParity.finalPhase -ceq 'idle' -and
                $evidence.finalSnapshot.state.playout.backgroundEnabled -eq $false -and
                [string]$evidence.finalSnapshot.state.playout.backgroundFileName -ceq '' -and
                $evidence.finalSnapshot.dom.backgroundNoneChecked -eq $true -and
                [string]$evidence.finalSnapshot.dom.backgroundNameValue -ceq
                    $BackgroundNoneLabel
            $dryRunKeyContractOk =
                [int]$evidence.dryRunPlayout.shortcutParity.f8IntentCount -eq 1 -and
                [int]$evidence.dryRunPlayout.shortcutParity.escapeIntentCount -eq 1 -and
                [string]$evidence.dryRunPlayout.shortcutParity.finalPhase -ceq 'idle'
            $dryRunMessageContractOk =
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'take-in'
                    }).Count -eq 1 -and
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'next-playout'
                    }).Count -eq 1 -and
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'take-out'
                    }).Count -eq 1 -and
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'set-all-playlist-enabled'
                    }).Count -eq 2 -and
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'toggle-active-playlist-enabled'
                    }).Count -eq 1 -and
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'choose-background'
                    }).Count -eq 1 -and
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'toggle-background'
                    }).Count -eq 1
            $dryRunShortcutContractOk =
                $dryRunBackgroundContractOk -and
                $dryRunKeyContractOk -and
                $dryRunMessageContractOk
            $dryRunProgramContractOk -and $dryRunShortcutContractOk
        }
        elseif ($HarnessProfile -ceq 'ProgramPlaylistDb') {
            $evidence.safety.playoutIntentIssued -eq $true -and
                $null -eq $evidence.dryRunPlayout -and
                [string]$evidence.programPlaylistDb.result -ceq 'PASS' -and
                -not [string]::IsNullOrWhiteSpace(
                    [string]$evidence.programPlaylistDb.currentEntryId) -and
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'take-in'
                    }).Count -eq 1 -and
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'take-out'
                    }).Count -eq 1 -and
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'next-playout'
                    }).Count -eq 0 -and
                @($evidence.safety.observedOutboundMessageTypes | Where-Object {
                        [string]$_ -ceq 'prepare-playout'
                    }).Count -eq 0
        }
        else {
            $evidence.safety.playoutIntentIssued -eq $false -and
                $null -eq $evidence.dryRunPlayout -and
                $null -eq $evidence.programPlaylistDb
        }
        $screenshotPathOk =
            -not [string]::IsNullOrWhiteSpace([string]$evidence.screenshot.path) -and
            (Test-PathEqual ([string]$evidence.screenshot.path) $ScreenshotPath)
        $safetyChecks = [ordered]@{
            schema = [int]$evidence.schemaVersion -eq 1
            profile = [string]$evidence.profile -ceq $expectedProfile
            scope = [string]$evidence.scope -ceq $expectedScope
            result = $safeResult
            warnings = -not ($result -ceq 'PASS_WITH_WARNING' -and $warnings.Count -eq 0)
            error = $null -eq $evidence.error
            expectedUrl = [string]$evidence.target.expectedUrl -ceq
                'https://legacy-parity.mbn.local/index.html'
            port = [int]$evidence.target.port -eq $ExpectedPort
            timeout = [int]$evidence.target.timeoutMilliseconds -eq
                ($ExpectedTimeoutSeconds * 1000)
            actualUrl = [string]$evidence.target.url -ceq
                'https://legacy-parity.mbn.local/index.html'
            mode = [string]$evidence.safety.requiredMode -ceq 'dryRun'
            phase = [string]$evidence.safety.requiredPhase -ceq 'idle'
            appClose = $evidence.safety.appCloseRequested -eq $false
            playout = [bool]$playoutIntentContractOk
            databaseWrite = [bool]$databaseWriteContractOk
            namedPlaylistRecovery = [bool]$namedPlaylistRecoveryContractOk
            externalCancellation = $evidence.safety.externalCancellationRequested -eq $false
            blockedOutbound = @($evidence.safety.blockedOutboundMessages).Count -eq 0
            stateViolations = @($evidence.safety.stateViolations).Count -eq 0
            screenshotPath = $screenshotPathOk
        }
        $failedSafetyChecks = @($safetyChecks.GetEnumerator() | Where-Object {
                $_.Value -ne $true
            } | ForEach-Object { $_.Key })
        if ($failedSafetyChecks.Count -ne 0) {
            $playoutDiagnostic = if ($failedSafetyChecks -ccontains 'playout') {
                $playoutValueType = if ($null -eq $playoutIntentContractOk) {
                    'null'
                }
                else {
                    $playoutIntentContractOk.GetType().FullName
                }
                " Playout value type: $playoutValueType; value: " +
                    "'$([string]$playoutIntentContractOk)'." +
                    $(if ($HarnessProfile -ceq 'DryRunPlayout') {
                            " Program contract: '$([string]$dryRunProgramContractOk)';" +
                                " background contract: '$([string]$dryRunBackgroundContractOk)';" +
                                " key contract: '$([string]$dryRunKeyContractOk)';" +
                                " message contract: '$([string]$dryRunMessageContractOk)'."
                        }
                        else {
                            ''
                        })
            }
            else {
                ''
            }
            Throw-SafeFailure (
                'The real input evidence does not satisfy the DryRun safety contract. ' +
                'Failed checks: ' + ($failedSafetyChecks -join ', ') + '.' +
                $playoutDiagnostic)
        }

        if ($HarnessProfile -ceq 'ReadOnly' -or
            $HarnessProfile -ceq 'DryRunPlayout' -or
            $HarnessProfile -ceq 'ProgramPlaylistDb') {
            $allowedOutbound = @(
                'ready', 'search-stocks', 'select-stock', 'cut-pointer-down',
                'cut-key-down', 'drop-selected-cuts', 'select-tab',
                'hover-swap-tabs',
                'activate-playlist-row',
                'select-playlist-row', 'move-selected-playlist-rows',
                'reorder-playlist-rows',
                'select-playlist-boundary', 'delete-selected-playlist-rows',
                'set-playlist-enabled',
                'refresh-named-playlists')
            if ($HarnessProfile -ceq 'DryRunPlayout') {
                $allowedOutbound += @(
                    'choose-background', 'toggle-background',
                    'take-in', 'next-playout', 'take-out',
                    'set-all-playlist-enabled',
                    'toggle-active-playlist-enabled')
            }
            elseif ($HarnessProfile -ceq 'ProgramPlaylistDb') {
                $allowedOutbound += @(
                    'select-named-playlist',
                    'create-named-playlist',
                    'save-current-named-playlist-to',
                    'delete-selected-named-playlist',
                    'dismiss-dialog',
                    'take-in', 'take-out')
            }
            foreach ($messageType in @($evidence.safety.observedOutboundMessageTypes)) {
                if ($allowedOutbound -cnotcontains [string]$messageType) {
                    Throw-SafeFailure 'The evidence contains an outbound message outside the selected non-write allowlist.'
                }
            }
        }
        else {
            $playoutMessages = @(
                'prepare-playout', 'take-in', 'next-playout', 'take-out',
                'choose-background', 'toggle-background')
            foreach ($messageType in @($evidence.safety.observedOutboundMessageTypes)) {
                if ($playoutMessages -ccontains [string]$messageType) {
                    Throw-SafeFailure 'The full UI/DB evidence contains a playout message.'
                }
            }
        }

        $screenshotItem = Get-Item -LiteralPath $ScreenshotPath -Force
        $screenshotHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $ScreenshotPath).Hash
        if ($screenshotItem.PSIsContainer -or
            ($screenshotItem.Attributes -band [IO.FileAttributes]::ReparsePoint) -ne 0 -or
            $screenshotItem.Length -le 0 -or
            [int64]$evidence.screenshot.bytes -ne $screenshotItem.Length -or
            [string]$evidence.screenshot.sha256 -cne $screenshotHash) {
            Throw-SafeFailure 'The screenshot evidence does not match its sealed file.'
        }

        $expectedExchangeCount = Get-ExpectedWindowsInputExchangeCount `
            $HarnessProfile `
            $HarnessScope
        $sealedExchanges = @($evidence.windowsInput.exchanges)
        if ([bool]$evidence.windowsInput.required -ne $true -or
            [string]$evidence.windowsInput.result -cne 'PASS' -or
            [int]$evidence.windowsInput.expectedExchangeCount -ne $expectedExchangeCount -or
            [int]$evidence.windowsInput.completedExchangeCount -ne $expectedExchangeCount -or
            $sealedExchanges.Count -ne $expectedExchangeCount -or
            -not (Test-PathEqual ([string]$evidence.windowsInput.requestPath) `
                $WindowsInputRequestPath) -or
            -not (Test-PathEqual ([string]$evidence.windowsInput.acknowledgementPath) `
                $WindowsInputAcknowledgementPath)) {
            Throw-SafeFailure 'The sealed Windows input exchange count/path contract is not exact.'
        }
        $request = $null
        for ($exchangeIndex = 1;
            $exchangeIndex -le $expectedExchangeCount;
            $exchangeIndex++) {
            $requestPath = Get-WindowsInputExchangePath `
                $WindowsInputRequestPath `
                $exchangeIndex
            $acknowledgementPath = Get-WindowsInputExchangePath `
                $WindowsInputAcknowledgementPath `
                $exchangeIndex
            $requestEvidence = Read-SmallJsonEvidenceFile `
                $requestPath `
                "Final Windows input request $exchangeIndex"
            $acknowledgementEvidence = Read-SmallJsonEvidenceFile `
                $acknowledgementPath `
                "Final Windows input acknowledgement $exchangeIndex"
            $sealedExchange = $sealedExchanges[$exchangeIndex - 1]
            if ([int]$sealedExchange.exchangeIndex -ne $exchangeIndex -or
                [string]$sealedExchange.operation -cne
                    [string]$requestEvidence.Value.operation -or
                [string]$sealedExchange.result -cne 'PASS' -or
                -not (Test-PathEqual ([string]$sealedExchange.requestPath) $requestPath) -or
                -not (Test-PathEqual `
                    ([string]$sealedExchange.acknowledgementPath) `
                    $acknowledgementPath) -or
                [string]$sealedExchange.requestSha256 -cne $requestEvidence.Sha256 -or
                [string]$sealedExchange.acknowledgementSha256 -cne
                    $acknowledgementEvidence.Sha256) {
                Throw-SafeFailure 'A sealed Windows input exchange does not match its files.'
            }
            if ($exchangeIndex -eq 1) {
                $request = $requestEvidence.Value
                if ([string]$request.operation -cne
                        'row-header-drag-home-shift-range-delete-restore' -or
                    [string]$evidence.windowsInput.requestSha256 -cne
                        $requestEvidence.Sha256 -or
                    [string]$evidence.windowsInput.acknowledgementSha256 -cne
                        $acknowledgementEvidence.Sha256 -or
                    -not (Test-ExactStringSequence `
                        @($evidence.windowsInput.beforeOrder) `
                        @($request.beforeOrder)) -or
                    -not (Test-ExactStringSequence `
                        @($evidence.windowsInput.afterOrder) `
                        @($request.afterOrder)) -or
                    -not (Test-ExactStringSequence `
                        @($evidence.windowsInput.shiftRangeDeletedRowIds) `
                        @($request.expectedRangeSelectedRowIds)) -or
                    [string]$evidence.windowsInput.activeRowIdAfterHome -cne
                        [string]$request.expectedActiveRowIdAfterHome -or
                    [string]$evidence.windowsInput.finalActiveRowId -cne
                        [string]$request.expectedFinalActiveRowId) {
                    Throw-SafeFailure 'The sealed playlist Windows input evidence is not exact.'
                }
            }
            elseif ($HarnessProfile -ceq 'DryRunPlayout' -and
                $exchangeIndex -eq 2) {
                if ([string]$requestEvidence.Value.operation -cne
                        'background-f2-picker-cancel' -or
                    [int]$requestEvidence.Value.f2KeyCalls -ne 1 -or
                    [int]$requestEvidence.Value.escapeKeyCalls -ne 1 -or
                    [int]$acknowledgementEvidence.Value.f2KeyCalls -ne 1 -or
                    [int]$acknowledgementEvidence.Value.escapeKeyCalls -ne 1 -or
                    $acknowledgementEvidence.Value.pickerUniqueNew -ne $true -or
                    $acknowledgementEvidence.Value.pickerOwnerLinked -ne $true -or
                    $acknowledgementEvidence.Value.pickerSameProcess -ne $true -or
                    [string]$acknowledgementEvidence.Value.pickerClass -cne '#32770' -or
                    [string]$acknowledgementEvidence.Value.pickerTitle -cne
                        $BackgroundPickerTitle -or
                    $acknowledgementEvidence.Value.pickerModal -ne $true -or
                    $acknowledgementEvidence.Value.pickerClosedAfterEscape -ne $true -or
                    $evidence.dryRunPlayout.backgroundShortcutParity.pickerOwnedAndCancelled -ne
                        $true) {
                    Throw-SafeFailure 'The sealed physical F2 picker cancellation evidence is not exact.'
                }
            }
            elseif ($HarnessProfile -ceq 'DryRunPlayout' -and
                $exchangeIndex -eq 3) {
                if ([string]$requestEvidence.Value.operation -cne
                        'background-f3-none' -or
                    [int]$requestEvidence.Value.f3KeyCalls -ne 1 -or
                    [int]$acknowledgementEvidence.Value.f3KeyCalls -ne 1 -or
                    $evidence.dryRunPlayout.backgroundShortcutParity.defaultAssetAbsentFailClosed -ne
                        $true -or
                    $evidence.dryRunPlayout.backgroundShortcutParity.finalBackgroundEnabled -ne
                        $false -or
                    $evidence.dryRunPlayout.backgroundShortcutParity.finalBackgroundNoneChecked -ne
                        $true) {
                    Throw-SafeFailure 'The sealed physical F3 background-none evidence is not exact.'
                }
            }
            elseif ([string]$requestEvidence.Value.operation -cne
                    'named-playlist-load-double-click' -or
                [string]$requestEvidence.Value.definitionTitle -cne
                    [string]$evidence.fixture.namedPlaylistTitle -or
                @($requestEvidence.Value.expectedPlaylistContent).Count -ne 3 -or
                @($evidence.fullUiDb.databaseChecks | Where-Object {
                        [string]$_.name -ceq
                            'PList physical double-click fresh readback' -and
                        $_.details.contentRestored -eq $true -and
                        $_.details.startedUnselected -eq $true -and
                        [int]$_.details.selectionIntentCount -eq 1 -and
                        [int]$_.details.loadIntentCount -eq 1 -and
                        [string]$_.details.input -ceq 'Windows SendInput double-click'
                    }).Count -ne 1) {
                Throw-SafeFailure 'The sealed PList physical double-click evidence is not exact.'
            }
        }

        $snapshot = $evidence.finalSnapshot
        $state = $snapshot.state
        $playout = $state.playout
        $dom = $snapshot.dom
        if ($null -eq $snapshot -or $null -eq $state -or $null -eq $playout -or
            $null -eq $dom -or
            $state.isBusy -ne $false -or
            [string]$playout.mode -cne 'dryRun' -or
            [string]$playout.connectionState -cne 'dryRunReady' -or
            [string]$playout.phase -cne 'idle' -or
            $playout.isConnected -ne $false -or
            $playout.liveTakeInAllowed -ne $false -or
            $playout.isPlayCompletionPending -ne $false -or
            $playout.isTakeOutCompletionPending -ne $false -or
            $playout.outcomeUnknown -ne $false -or
            $playout.isBusy -ne $false -or
            $playout.refreshActive -ne $false -or
            $null -ne $playout.preparedCode -or
            $null -ne $playout.onAirCode -or
            $null -ne $playout.currentEntryId -or
            $snapshot.safety.postMessageWrapped -ne $true -or
            @($snapshot.safety.blockedOutboundMessages).Count -ne 0 -or
            @($snapshot.safety.stateViolations).Count -ne 0 -or
            [string]$dom.readyState -cne 'complete' -or
            [string]$dom.url -cne 'https://legacy-parity.mbn.local/index.html' -or
            [string]$dom.bodyBusy -cne 'false' -or
            [string]$dom.connectionText -cne 'DRY RUN' -or
            $dom.legacyDialogHidden -ne $true -or
            $dom.namedModalHidden -ne $true -or
            $dom.namedConfirmationHidden -ne $true) {
            Throw-SafeFailure 'The sealed final application state is not exact DryRun IDLE.'
        }

        $expectedAfterOrder = @($request.afterOrder | ForEach-Object { [string]$_ })
        $expectedFinalOrder = @($expectedAfterOrder)
        if ($HarnessProfile -ceq 'DryRunPlayout') {
            # DryRun deliberately proves that a PROGRAM cut double-click appends one
            # safe tail row. Preserve the sealed Windows drag order as the prefix and
            # require that exact new opaque row id at the tail after TAKE OUT.
            $expectedFinalOrder += @(
                [string]$evidence.dryRunPlayout.tailAppendedEntryId)
        }
        $statePlaylist = @($state.playlist)
        $domPlaylist = @($dom.playlist)
        $statePlaylistIds = @($statePlaylist | ForEach-Object { [string]$_.rowId })
        $domPlaylistIds = @($domPlaylist | ForEach-Object { [string]$_.rowId })
        $selectedStateIds = @($statePlaylist | Where-Object { $_.isSelected -eq $true } |
            ForEach-Object { [string]$_.rowId })
        $activeStateIds = @($statePlaylist | Where-Object { $_.isActive -eq $true } |
            ForEach-Object { [string]$_.rowId })
        $selectedDomIds = @($domPlaylist | Where-Object { $_.selected -eq $true } |
            ForEach-Object { [string]$_.rowId })
        $activeDomIds = @($domPlaylist | Where-Object { $_.active -eq $true } |
            ForEach-Object { [string]$_.rowId })
        $dragVisualCount = @($domPlaylist | Where-Object {
                $_.dragging -eq $true -or $_.dragBefore -eq $true -or $_.dragAfter -eq $true
            }).Count
        if (($HarnessProfile -ceq 'ReadOnly' -or
             $HarnessProfile -ceq 'DryRunPlayout' -or
             $HarnessProfile -ceq 'ProgramPlaylistDb') -and (
            -not (Test-ExactStringSequence $statePlaylistIds $expectedFinalOrder) -or
            -not (Test-ExactStringSequence $domPlaylistIds $expectedFinalOrder) -or
            -not (Test-ExactStringSequence $selectedStateIds @([string]$request.sourceRowId)) -or
            -not (Test-ExactStringSequence $selectedDomIds @([string]$request.sourceRowId)) -or
            -not (Test-ExactStringSequence `
                $activeStateIds `
                @([string]$request.expectedFinalActiveRowId)) -or
            -not (Test-ExactStringSequence `
                $activeDomIds `
                @([string]$request.expectedFinalActiveRowId)) -or
            $dragVisualCount -ne 0 -or
            @($dom.playlistPointerCapture.rowIds).Count -ne 0)) {
            Throw-SafeFailure 'The sealed final playlist state does not match the Windows input result.'
        }
        $expectedFullUiDbPlaylistCount = if ($HarnessScope -ceq 'GraphE' -or
            $HarnessScope -ceq 'Screens' -or $HarnessScope -ceq 'All') { 0 } else { 3 }
        if ($HarnessProfile -ceq 'FullUiDb' -and (
            $statePlaylist.Count -ne $expectedFullUiDbPlaylistCount -or
            $domPlaylist.Count -ne $expectedFullUiDbPlaylistCount -or
            $dragVisualCount -ne 0 -or
            @($dom.playlistPointerCapture.rowIds).Count -ne 0)) {
            Throw-SafeFailure 'The sealed full UI/DB playlist readback is not exact.'
        }

        return $evidence
    }
    catch [InvalidOperationException] {
        throw
    }
    catch {
        # Never echo evidence JSON or parser diagnostics.
        Throw-SafeFailure 'The real input evidence could not be validated safely.'
    }
}

if ($DefinitionsOnly) {
    return
}

$recoveryRequested = -not [string]::IsNullOrEmpty($RecoverNamedPlaylistTitle)
if ($recoveryRequested -and
    ($RecoverNamedPlaylistTitle.Length -ne 26 -or
     $RecoverNamedPlaylistTitle -cnotmatch '^CDX_P_[0-9]{13}_[0-9a-f]{6}$')) {
    Throw-SafeFailure 'RecoverNamedPlaylistTitle must be one exact generated CDX_P fixture title.'
}
if ($recoveryRequested -and
    ($Profile -cne 'FullUiDb' -or
     ($FullUiDbScope -cne 'PList' -and $FullUiDbScope -cne 'All'))) {
    Throw-SafeFailure 'Named-playlist recovery is allowed only for FullUiDb PList or All.'
}

$timestamp = [datetime]::UtcNow.ToString('yyyyMMddTHHmmssfffZ')
$Output = Resolve-EvidencePath $Output "legacy-package-input-$timestamp.json"
$Screenshot = Resolve-EvidencePath $Screenshot "legacy-package-input-$timestamp.png"
$WindowsInputRequest = [IO.Path]::ChangeExtension(
    $Output,
    '.windows-input-request.json')
$WindowsInputAcknowledgement = [IO.Path]::ChangeExtension(
    $Output,
    '.windows-input-ack.json')
$ExpectedWindowsInputExchangeCount = Get-ExpectedWindowsInputExchangeCount `
    $Profile `
    $FullUiDbScope
$WindowsInputRequestPaths = @(1..$ExpectedWindowsInputExchangeCount | ForEach-Object {
        Get-WindowsInputExchangePath $WindowsInputRequest $_
    })
$WindowsInputAcknowledgementPaths = @(1..$ExpectedWindowsInputExchangeCount |
    ForEach-Object {
        Get-WindowsInputExchangePath $WindowsInputAcknowledgement $_
    })
$NodePath = Resolve-NodeExecutable $NodePath

try {
    if (-not [IO.File]::Exists($HarnessPath)) {
        Throw-SafeFailure 'The tracked package input harness is missing.'
    }
    if (-not [string]::Equals(
            [IO.Path]::GetExtension($Output), '.json', [StringComparison]::OrdinalIgnoreCase) -or
        -not [string]::Equals(
            [IO.Path]::GetExtension($Screenshot), '.png', [StringComparison]::OrdinalIgnoreCase)) {
        Throw-SafeFailure 'Output must be .json and screenshot must be .png.'
    }
    $evidencePaths = @($Output, $Screenshot) +
        $WindowsInputRequestPaths + $WindowsInputAcknowledgementPaths
    for ($leftIndex = 0; $leftIndex -lt $evidencePaths.Count; $leftIndex++) {
        for ($rightIndex = $leftIndex + 1; $rightIndex -lt $evidencePaths.Count; $rightIndex++) {
            if (Test-PathEqual $evidencePaths[$leftIndex] $evidencePaths[$rightIndex]) {
                Throw-SafeFailure 'All evidence paths must be different.'
            }
        }
    }

    Assert-OutputPathAvailable $Output 'Output'
    Assert-OutputPathAvailable $Screenshot 'Screenshot'
    for ($exchangeIndex = 1;
        $exchangeIndex -le $ExpectedWindowsInputExchangeCount;
        $exchangeIndex++) {
        Assert-OutputPathAvailable $WindowsInputRequestPaths[$exchangeIndex - 1] `
            "Windows input request $exchangeIndex"
        Assert-OutputPathAvailable $WindowsInputAcknowledgementPaths[$exchangeIndex - 1] `
            "Windows input acknowledgement $exchangeIndex"
    }
    Assert-LocalConfigurationIsDryRun
    Assert-NoUnsafeEnvironment
    $registration = Get-ExactDevelopmentPackage
    Assert-NoExistingApplication
    Assert-PortIsFree $Port
    Initialize-BackgroundShortcutFixture $registration.InstallLocation

    $script:Phase = 'package launch'
    $script:ApplicationProcess = Start-PackagedDryRunApplication $registration $Port
    $script:ApplicationWasLaunched = $true
    [void](Wait-ExactLoopbackListener `
        $Port `
        $script:ApplicationProcess `
        ([datetime]::UtcNow.AddSeconds($LaunchTimeoutSeconds)))
    Assert-NoTornadoConnection $script:ApplicationProcess.Id
    Wait-StartupIntroDismissed `
        $script:ApplicationProcess `
        $registration.Executable

    $script:Phase = 'real input harness'
    $harnessRun = Invoke-NodeHarnessUnderTcpWatch `
        $NodePath `
        $HarnessPath `
        $Port `
        $Output `
        $Screenshot `
        $WindowsInputRequest `
        $WindowsInputAcknowledgement `
        $(if ($Profile -ceq 'FullUiDb') {
                'full-ui-db'
            }
            elseif ($Profile -ceq 'DryRunPlayout') {
                'dry-run-playout'
            }
            elseif ($Profile -ceq 'ProgramPlaylistDb') {
                'program-playlist-db'
            }
            else {
                'read-only'
            }) `
        $(if ($Profile -ceq 'FullUiDb') { $FullUiDbScope.ToLowerInvariant() } else { 'all' }) `
        $RecoverNamedPlaylistTitle `
        $HarnessTimeoutSeconds `
        $script:ApplicationProcess `
        $registration.Executable
    if ($harnessRun.ExitCode -ne 0) {
        Throw-SafeFailure "The real input harness failed with exit code $($harnessRun.ExitCode)."
    }
    if (-not [IO.File]::Exists($Output) -or
        -not [IO.File]::Exists($Screenshot) -or
        (Get-Item -LiteralPath $Output).Length -le 0 -or
        (Get-Item -LiteralPath $Screenshot).Length -le 0 -or
        @($WindowsInputRequestPaths + $WindowsInputAcknowledgementPaths |
            Where-Object {
                -not [IO.File]::Exists($_) -or
                (Get-Item -LiteralPath $_).Length -le 0
            }).Count -ne 0) {
        Throw-SafeFailure 'The real input evidence files are missing or empty.'
    }
    $harnessEvidence = Read-AndAssertHarnessEvidence `
        $Output `
        $Screenshot `
        $WindowsInputRequest `
        $WindowsInputAcknowledgement `
        $Profile `
        $FullUiDbScope `
        $RecoverNamedPlaylistTitle `
        $Port `
        $HarnessTimeoutSeconds
    $wrapperWindowsInput = @($harnessRun.WindowsInput)
    $sealedWindowsInput = @($harnessEvidence.windowsInput.exchanges)
    if ($wrapperWindowsInput.Count -ne $ExpectedWindowsInputExchangeCount -or
        $sealedWindowsInput.Count -ne $ExpectedWindowsInputExchangeCount) {
        Throw-SafeFailure 'The wrapper and harness Windows input exchange counts differ.'
    }
    for ($exchangeIndex = 1;
        $exchangeIndex -le $ExpectedWindowsInputExchangeCount;
        $exchangeIndex++) {
        $wrapperExchange = $wrapperWindowsInput[$exchangeIndex - 1]
        $sealedExchange = $sealedWindowsInput[$exchangeIndex - 1]
        if ([int]$wrapperExchange.ExchangeIndex -ne $exchangeIndex -or
            [int]$sealedExchange.exchangeIndex -ne $exchangeIndex -or
            [string]$wrapperExchange.Operation -cne [string]$sealedExchange.operation -or
            [string]$wrapperExchange.RequestSha256 -cne
                [string]$sealedExchange.requestSha256 -or
            [string]$wrapperExchange.AcknowledgementSha256 -cne
                [string]$sealedExchange.acknowledgementSha256) {
            Throw-SafeFailure 'The wrapper and harness Windows input exchange hashes differ.'
        }
    }

    Assert-ExactApplicationStillRunning $script:ApplicationProcess $registration.Executable
    Assert-NoTornadoConnection $script:ApplicationProcess.Id

    if ($Profile -cne 'FullUiDb' -and $Profile -cne 'ProgramPlaylistDb') {
        $script:Phase = 'single-instance activation'
        $singleInstance = Assert-SingleInstanceActivation `
            $script:ApplicationProcess `
            $registration.Executable
    }
    else {
        # The read-only package smoke already owns the single-instance contract.
        # Avoid launching an unrelated redirector after an authorized DB-write run.
        $singleInstance = [pscustomobject]@{
            ActivationCalls = 0
            ProcessCount = 1
            RedirectorProcessId = $null
            RedirectorStartTimeUtc = $null
            RedirectorExited = $null
            StableOriginalMilliseconds = $null
        }
    }

    $script:Phase = 'normal close'
    Invoke-ExactNormalClose $script:ApplicationProcess $registration.Executable
    Wait-PortReleased $Port ([datetime]::UtcNow.AddSeconds(15))
    if (@(Get-LegacyApplicationProcesses).Count -ne 0) {
        Throw-SafeFailure 'A LegacyParity process remained after normal exit.'
    }
    Remove-BackgroundShortcutFixture

    $script:Phase = 'complete'
    [pscustomobject]@{
        result = [string]$harnessEvidence.result
        packageFullName = $PackageFullName
        packageMode = $PackageModeLabel
        playoutMode = 'DryRun'
        processId = $script:ApplicationProcess.Id
        cdpAddress = '127.0.0.1'
        cdpPort = $Port
        tornadoPortConnections = 0
        tornadoMonitoringScope = 'application PID from exact launch identity through normal exit'
        windowsInputRequestCalls = $script:WindowsInputRequestCalls
        windowsInputAcknowledgementCalls = $script:WindowsInputAcknowledgementCalls
        windowsInputRequest = $WindowsInputRequest
        windowsInputRequestSha256 = [string]$wrapperWindowsInput[0].RequestSha256
        windowsInputAcknowledgement = $WindowsInputAcknowledgement
        windowsInputAcknowledgementSha256 = `
            [string]$wrapperWindowsInput[0].AcknowledgementSha256
        windowsInputExchanges = @($wrapperWindowsInput)
        singleInstanceActivationCalls = $singleInstance.ActivationCalls
        singleInstanceProcessCount = $singleInstance.ProcessCount
        singleInstanceRedirectorProcessId = $singleInstance.RedirectorProcessId
        singleInstanceRedirectorStartTimeUtc = $singleInstance.RedirectorStartTimeUtc
        singleInstanceRedirectorExited = $singleInstance.RedirectorExited
        singleInstanceStableOriginalMilliseconds = $singleInstance.StableOriginalMilliseconds
        closeMainWindowCalls = $script:CloseMainWindowCalls
        primaryInvokeCalls = $script:PrimaryInvokeCalls
        output = $Output
        outputSha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $Output).Hash
        screenshot = $Screenshot
        screenshotSha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $Screenshot).Hash
    }
}
catch {
    $message = $_.Exception.Message
    if ($script:CloseMainWindowCalls -gt 0 -or $script:PrimaryInvokeCalls -gt 0) {
        Throw-SafeFailure (
            "Package input smoke became ambiguous during '$($script:Phase)': $message " +
            'No close retry or forced termination was attempted.')
    }

    $running = $false
    if ($script:ApplicationWasLaunched -and $null -ne $script:ApplicationProcess) {
        try {
            $script:ApplicationProcess.Refresh()
            $running = -not $script:ApplicationProcess.HasExited
        }
        catch {
            $running = $false
        }
    }
    if (-not $running) {
        try {
            $running = @(Get-LegacyApplicationProcesses).Count -gt 0
        }
        catch {
            # An inability to re-enumerate cannot authorize another close attempt.
            $running = $false
        }
    }

    if ($running) {
        Throw-SafeFailure (
            "Package input smoke stopped during '$($script:Phase)': $message " +
            'The application was intentionally left open; no close retry or forced termination was attempted.')
    }

    if ($script:BackgroundShortcutRootCreated) {
        Remove-BackgroundShortcutFixture
    }

    throw
}
