[CmdletBinding()]
param(
    [ValidateRange(1024, 65535)]
    [int]$Port = 9347,

    [string]$Output,

    [string]$Screenshot,

    [string]$ExchangeDirectory,

    [string]$LegacyDataDirectory,

    [string]$NodePath,

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

    [ValidateRange(60, 900)]
    [int]$HarnessTimeoutSeconds = 240,

    [switch]$StaticAudit
)

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

$requestedPort = $Port
$requestedOutput = $Output
$requestedScreenshot = $Screenshot
$requestedExchangeDirectory = $ExchangeDirectory
$requestedLegacyDataDirectory = $LegacyDataDirectory
$requestedNodePath = $NodePath
$requestedLaunchTimeout = $LaunchTimeoutSeconds
$requestedHarnessTimeout = $HarnessTimeoutSeconds
$sharedScript = Join-Path $PSScriptRoot 'Invoke-LegacyPackageInputSmoke.ps1'
if (-not [IO.File]::Exists($sharedScript)) {
    throw [InvalidOperationException]::new('The shared package input safety script is missing.')
}

# Reuse the exact registered-package, latest DebugAppX, DryRun, TCP ownership,
# process identity and normal-close guards.  -DefinitionsOnly performs no launch.
. $sharedScript `
    -BuildFlavor DebugAppX `
    -Profile ReadOnly `
    -Port $requestedPort `
    -Output $requestedOutput `
    -Screenshot $requestedScreenshot `
    -NodePath $requestedNodePath `
    -LaunchTimeoutSeconds $requestedLaunchTimeout `
    -HarnessTimeoutSeconds $requestedHarnessTimeout `
    -DefinitionsOnly

$Port = $requestedPort
$Output = $requestedOutput
$Screenshot = $requestedScreenshot
$ExchangeDirectory = $requestedExchangeDirectory
$LegacyDataDirectory = $requestedLegacyDataDirectory
$NodePath = $requestedNodePath
$LaunchTimeoutSeconds = $requestedLaunchTimeout
$HarnessTimeoutSeconds = $requestedHarnessTimeout
$HarnessPath = Join-Path $PSScriptRoot 'Test-LegacyPackageLocalStateSmoke.mjs'

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

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

    [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 IntPtr GetAncestor(IntPtr window, uint flags);

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

    [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", SetLastError = true)]
    private static extern bool AttachThreadInput(uint from, uint to, bool attach);

    [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")]
    private static extern uint GetWindowThreadProcessId(IntPtr window, out uint processId);

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

    private const uint GetWindowOwner = 4;
    private const uint GetAncestorRoot = 2;

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

    public static bool Visible(IntPtr window)
    {
        return Exists(window) && IsWindowVisible(window);
    }

    public static bool Enabled(IntPtr window)
    {
        return Exists(window) && IsWindowEnabled(window);
    }

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

    public static IntPtr Root(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 = Root(expectedOwner);
        IntPtr current = window;
        for (int depth = 0; depth < 12 && current != IntPtr.Zero; depth++)
        {
            if (current == expectedOwner || Root(current) == expectedRoot) return true;
            current = GetWindow(current, GetWindowOwner);
        }
        return false;
    }

    public static string ClassName(IntPtr window)
    {
        StringBuilder value = new StringBuilder(512);
        return window != IntPtr.Zero && GetClassName(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 void AcquireOwnedForeground(IntPtr window, IntPtr expectedOwner)
    {
        if (!Visible(window) || !Enabled(window) ||
            !OwnerChainContains(window, expectedOwner))
        {
            throw new InvalidOperationException("The owned picker identity changed before foreground acquisition.");
        }

        IntPtr foreground = GetForegroundWindow();
        if (Root(foreground) == window) return;

        uint ignored;
        uint foregroundThread = foreground == IntPtr.Zero
            ? 0 : GetWindowThreadProcessId(foreground, out ignored);
        uint targetThread = GetWindowThreadProcessId(window, out ignored);
        uint currentThread = GetCurrentThreadId();
        if (targetThread == 0 || currentThread == 0)
        {
            throw new InvalidOperationException("The picker 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 to the picker verifier.");
                }
                attachedForeground = true;
            }
            if (targetThread != currentThread)
            {
                if (!AttachThreadInput(currentThread, targetThread, true))
                {
                    throw new InvalidOperationException("The picker input queue could not be attached.");
                }
                attachedTarget = true;
            }

            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 && Root(GetForegroundWindow()) != window)
        {
            if (!Visible(window) || !Enabled(window) ||
                !OwnerChainContains(window, expectedOwner))
            {
                throw new InvalidOperationException("The owned picker identity changed during foreground acquisition.");
            }
            Thread.Sleep(10);
        }
        if (Root(GetForegroundWindow()) != window)
        {
            throw new InvalidOperationException("The exact owned picker could not acquire foreground input.");
        }
    }
}
'@

$ExpectedSourceSha256 =
    '1EE76BC464FB1C44C8B6546E99CDC21C726C0E2C24AD344F5C19AE41BFC0D2F2'
$ExpectedFreshDestinationSha256 =
    '13C07BA64587549EDA9C1A694F3DFA19875CB1F888F02C9E071F17C47739E087'
$ExpectedImportedDestinationSha256 =
    '2575C2420800670B0022EBEE819BA3D9640DB14E9552426DF46075D079F1F697'
$ExpectedInitialPairLine = $Utf8.GetString([Convert]::FromBase64String(
        'MV5LUlgxMDDsp4DsiJgs7L2U7Iqk7ZS8IOyngOyImF5eXl5eXl4='))
$ComparisonFileName = $Utf8.GetString([Convert]::FromBase64String(
        '7KKF66qp67mE6rWQLmRhdA=='))
$ExpectedInitialPairIdentity = $Utf8.GetString([Convert]::FromBase64String(
        'S1JYMTAw7KeA7IiYfOy9lOyKpO2UvCDsp4DsiJg='))
$FolderSelectLabel = $Utf8.GetString([Convert]::FromBase64String(
        '7Y+0642UIOyEoO2DnQ=='))
$CancelLabel = $Utf8.GetString([Convert]::FromBase64String('7Leo7IaM'))
if ([string]::IsNullOrWhiteSpace($LegacyDataDirectory)) {
    $LegacyDataDirectory = [IO.Path]::GetFullPath((Join-Path $RepositoryRoot `
            '..\MBN_STOCK_N\MBN_STOCK_N\bin\Debug\Data'))
} else {
    $LegacyDataDirectory = [IO.Path]::GetFullPath($LegacyDataDirectory)
}
$SourceComparisonPath = Join-Path $LegacyDataDirectory $ComparisonFileName
$DestinationComparisonPath = Join-Path `
    ([Environment]::GetFolderPath([Environment+SpecialFolder]::LocalApplicationData)) `
    (Join-Path 'MBN_STOCK_WEBVIEW\Data' $ComparisonFileName)
$RuntimeSettingsPath = Join-Path `
    ([Environment]::GetFolderPath([Environment+SpecialFolder]::LocalApplicationData)) `
    'MBN_STOCK_WEBVIEW\Config\runtime-folders.local.json'
$Cp949 = [Text.Encoding]::GetEncoding(
    949,
    [Text.EncoderExceptionFallback]::new(),
    [Text.DecoderExceptionFallback]::new())
$ExpectedExchangePlan = @(
    [pscustomobject]@{ Operation = 'observe-local-files'; TargetId = $null; FolderKind = $null },
    [pscustomobject]@{ Operation = 'application-click'; TargetId = 'settings-navigation'; FolderKind = $null },
    [pscustomobject]@{ Operation = 'folder-picker-click-cancel'; TargetId = 'design-folder-picker'; FolderKind = 'design' },
    [pscustomobject]@{ Operation = 'folder-picker-click-cancel'; TargetId = 'resource-folder-picker'; FolderKind = 'resource' },
    [pscustomobject]@{ Operation = 'folder-picker-click-cancel'; TargetId = 'background-folder-picker'; FolderKind = 'background' },
    [pscustomobject]@{ Operation = 'observe-local-files'; TargetId = $null; FolderKind = $null },
    [pscustomobject]@{ Operation = 'application-click'; TargetId = 'comparison-navigation'; FolderKind = $null },
    [pscustomobject]@{ Operation = 'application-click'; TargetId = 'comparison-import'; FolderKind = $null },
    [pscustomobject]@{ Operation = 'application-click'; TargetId = 'native-confirmation-yes'; FolderKind = $null },
    [pscustomobject]@{ Operation = 'observe-local-files'; TargetId = $null; FolderKind = $null },
    [pscustomobject]@{ Operation = 'application-click'; TargetId = 'comparison-import'; FolderKind = $null },
    [pscustomobject]@{ Operation = 'application-click'; TargetId = 'native-confirmation-yes'; FolderKind = $null },
    [pscustomobject]@{ Operation = 'observe-local-files'; TargetId = $null; FolderKind = $null }
)

$script:LocalInputRequestCalls = 0
$script:LocalInputAcknowledgementCalls = 0
$script:BaselineSettingsState = $null
$script:DestinationBaselineMode = $null
$script:InitialDestinationState = $null
$script:FirstImportedDestinationState = $null
$script:LastObservedFileState = $null

function Assert-SafeRegularFile([string]$Path, [string]$Label, [int64]$MaximumBytes) {
    if (-not [IO.File]::Exists($Path)) {
        Throw-SafeFailure "$Label is missing."
    }
    $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 $MaximumBytes) {
        Throw-SafeFailure "$Label is not a bounded regular file."
    }
}

function Get-ComparisonFileState(
    [string]$Path,
    [string]$Label,
    [bool]$IsReadOnlySource) {
    Assert-SafeRegularFile $Path $Label (64 * 1024)
    $bytes = [IO.File]::ReadAllBytes($Path)
    try {
        $text = $Cp949.GetString($bytes)
    }
    catch {
        Throw-SafeFailure "$Label is not strict CP949."
    }
    $rows = @($text -split "`r?`n" | Where-Object { $_.Length -gt 0 })
    if ($rows.Count -lt 1 -or $rows.Count -gt 500) {
        Throw-SafeFailure "$Label row count is outside the closed contract."
    }
    for ($index = 0; $index -lt $rows.Count; $index++) {
        if ($rows[$index] -cnotmatch ('\A' + ($index + 1) + '\^[^\^,]+,[^\^,]+(?:\^[^\^]*){7}\z')) {
            Throw-SafeFailure "$Label does not retain the exact legacy row shape."
        }
    }
    $pairField = ($rows[0] -split '\^', 3)[1]
    $pair = $pairField -split ',', 2
    return [ordered]@{
        exists = $true
        length = [int64]$bytes.Length
        sha256 = Get-ByteArraySha256 $bytes
        rowCount = $rows.Count
        firstPair = $pair[0] + '|' + $pair[1]
        isReadOnlySource = $IsReadOnlySource
    }
}

function Get-SettingsFileState {
    if (-not [IO.File]::Exists($RuntimeSettingsPath)) {
        return [ordered]@{
            exists = $false
            length = 0
            sha256 = $null
        }
    }
    Assert-SafeRegularFile $RuntimeSettingsPath 'Runtime folder settings JSON' (16 * 1024)
    $bytes = [IO.File]::ReadAllBytes($RuntimeSettingsPath)
    try {
        [void]$StrictUtf8.GetString($bytes)
    }
    catch {
        Throw-SafeFailure 'Runtime folder settings JSON is not strict UTF-8.'
    }
    return [ordered]@{
        exists = $true
        length = [int64]$bytes.Length
        sha256 = Get-ByteArraySha256 $bytes
    }
}

function Get-LocalFileState {
    return [ordered]@{
        source = Get-ComparisonFileState `
            $SourceComparisonPath `
            'Original comparison source' `
            $true
        destination = Get-ComparisonFileState `
            $DestinationComparisonPath `
            'Current local comparison file' `
            $false
        settings = Get-SettingsFileState
    }
}

function Test-JsonEquivalent($Left, $Right) {
    return (($Left | ConvertTo-Json -Depth 12 -Compress) -ceq
        ($Right | ConvertTo-Json -Depth 12 -Compress))
}

function Assert-LocalFilePreflight {
    $state = Get-LocalFileState
    if ([string]$state.source.sha256 -cne $ExpectedSourceSha256 -or
        [int]$state.source.rowCount -ne 8 -or
        [string]$state.destination.firstPair -cne $ExpectedInitialPairIdentity) {
        Throw-SafeFailure `
            ('The original 8-row source or known comparison baseline changed; ' +
             'no import was started.')
    }
    $isFresh =
        [string]$state.destination.sha256 -ceq $ExpectedFreshDestinationSha256 -and
        [int]$state.destination.rowCount -eq 1
    $isAlreadyImported =
        [string]$state.destination.sha256 -ceq $ExpectedImportedDestinationSha256 -and
        [int]$state.destination.rowCount -eq 9
    if (-not $isFresh -and -not $isAlreadyImported) {
        Throw-SafeFailure `
            'The comparison destination is neither the known fresh nor imported baseline.'
    }
    if ($isFresh) {
        $initialBytes = [IO.File]::ReadAllBytes($DestinationComparisonPath)
        if ($Cp949.GetString($initialBytes).TrimEnd("`r", "`n") -cne
            $ExpectedInitialPairLine) {
            Throw-SafeFailure 'The current one-row comparison baseline is not the expected known pair.'
        }
    }
    $script:BaselineSettingsState = $state.settings
    $script:DestinationBaselineMode = if ($isFresh) { 'fresh' } else { 'alreadyImported' }
    $script:InitialDestinationState = $state.destination
    $script:LastObservedFileState = $state
    return $state
}

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

function Get-OwnedFolderPickerCandidates(
    [Collections.Generic.HashSet[int64]]$BaselineHandles,
    [IntPtr]$MainWindowHandle,
    [int]$ApplicationProcessId) {
    $candidates = @()
    foreach ($handle in [LegacyLocalStateNative]::VisibleTopLevelWindows()) {
        try {
            if ($handle -eq [IntPtr]::Zero -or
                $BaselineHandles.Contains($handle.ToInt64()) -or
                -not [LegacyLocalStateNative]::Visible($handle)) {
                continue
            }
            $sameProcess = [LegacyLocalStateNative]::ProcessId($handle) -eq $ApplicationProcessId
            $ownerLinked = $sameProcess -or
                [LegacyLocalStateNative]::OwnerChainContains($handle, $MainWindowHandle)
            if (-not $ownerLinked) { continue }

            $window = [System.Windows.Automation.AutomationElement]::FromHandle($handle)
            if ($null -eq $window) { continue }
            $windowName = [string]$window.Current.Name
            $windowClass = [LegacyLocalStateNative]::ClassName($handle)
            if ($windowClass -cne '#32770' -or
                (-not $windowName.StartsWith(
                    $FolderSelectLabel,
                    [StringComparison]::Ordinal) -and
                 $windowName -cnotmatch '\ASelect Folder(?:\(&.\))?\z')) {
                continue
            }

            # The Win32 folder picker may expose its bottom Button windows as
            # ControlType.Pane through UI Automation (observed on the Korean
            # Windows shell).  Keep the label/count gate, but also recognize
            # the exact legacy Button class/IDs instead of requiring only the
            # synthesized ControlType.Button view.
            $controls = $window.FindAll(
                [System.Windows.Automation.TreeScope]::Descendants,
                [System.Windows.Automation.Condition]::TrueCondition)
            $confirmCount = 0
            $cancelCount = 0
            foreach ($control in $controls) {
                $automationId = [string]$control.Current.AutomationId
                $isAutomationButton =
                    $control.Current.ControlType -eq [System.Windows.Automation.ControlType]::Button
                $isLegacyDialogButton =
                    [string]$control.Current.ClassName -ceq 'Button' -and
                    ($automationId -ceq '1' -or $automationId -ceq '2')
                if (-not $isAutomationButton -and -not $isLegacyDialogButton) { continue }

                $name = [string]$control.Current.Name
                if ($name.StartsWith($FolderSelectLabel, [StringComparison]::Ordinal) -or
                    $name -cmatch '\A(?:Select Folder|Select)(?:\(&.\))?\z') {
                    $confirmCount++
                }
                if ($name.StartsWith($CancelLabel, [StringComparison]::Ordinal) -or
                    $name -cmatch '\ACancel(?:\(&.\))?\z') {
                    $cancelCount++
                }
            }
            if ($confirmCount -ne 1 -or $cancelCount -ne 1) { continue }

            $windowPatternObject = $null
            if (-not $window.TryGetCurrentPattern(
                    [System.Windows.Automation.WindowPattern]::Pattern,
                    [ref]$windowPatternObject) -or
                $null -eq $windowPatternObject) {
                continue
            }
            $windowPattern = $windowPatternObject -as
                [System.Windows.Automation.WindowPattern]
            $isModal = [bool]$windowPattern.Current.IsModal
            if (-not $isModal) { continue }

            $candidates += [pscustomobject]@{
                Element = $window
                Handle = $handle
                ProcessId = [LegacyLocalStateNative]::ProcessId($handle)
                SameProcess = $sameProcess
                OwnerLinked = $ownerLinked
                Name = $windowName
                ClassName = $windowClass
                ConfirmButtonCount = $confirmCount
                CancelButtonCount = $cancelCount
                IsModal = $isModal
            }
        }
        catch {
            # A transient shell window is ignored unless it satisfies every
            # stable ownership and folder-button condition in one observation.
        }
    }
    return @($candidates)
}

function Wait-UniqueOwnedFolderPicker(
    [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-OwnedFolderPickerCandidates `
            $BaselineHandles `
            $Application.MainWindowHandle `
            $Application.Id)
        if ($candidates.Count -gt 1) {
            Throw-SafeFailure 'More than one newly opened app-owned folder picker exists.'
        }
        if ($candidates.Count -eq 1) {
            $picker = $candidates[0]
            Assert-NoTornadoConnection $Application.Id
            [LegacyLocalStateNative]::AcquireOwnedForeground(
                $picker.Handle,
                $Application.MainWindowHandle)
            Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
            Assert-NoTornadoConnection $Application.Id
            $revalidated = @(Get-OwnedFolderPickerCandidates `
                $BaselineHandles `
                $Application.MainWindowHandle `
                $Application.Id)
            if ($revalidated.Count -ne 1 -or
                $revalidated[0].Handle -ne $picker.Handle) {
                Throw-SafeFailure 'The unique app-owned folder picker identity changed during foreground acquisition.'
            }
            $foregroundRoot = [LegacyLocalStateNative]::Root(
                [LegacyPackageInputNative]::ReadForegroundWindow())
            if ($foregroundRoot -eq $picker.Handle) { return $picker }
        }
        Start-Sleep -Milliseconds 50
    }
    Throw-SafeFailure 'The exact app-owned folder picker did not appear in time.'
}

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

function ConvertTo-LocalFiniteNumber($Value, [string]$Label) {
    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 Write-LocalAcknowledgement(
    [string]$Path,
    $Request,
    $Files,
    $Picker) {
    $acknowledgement = [ordered]@{
        schemaVersion = 1
        token = [string]$Request.token
        sequence = [int]$Request.sequence
        result = 'PASS'
        operation = [string]$Request.operation
        targetId = if ($null -eq $Request.targetId) { $null } else { [string]$Request.targetId }
        folderKind = if ($null -eq $Request.folderKind) { $null } else { [string]$Request.folderKind }
        packageIdentityValidated = $true
        dryRunValidated = $true
        tornadoConnectionCount = 0
        mouseDownCalls = [int]$Request.mouseDownCalls
        mouseUpCalls = [int]$Request.mouseUpCalls
        escapeKeyCalls = [int]$Request.escapeKeyCalls
        inputRetryCount = 0
        picker = $Picker
        files = $Files
    }
    $bytes = $Utf8.GetBytes(($acknowledgement | ConvertTo-Json -Depth 12 -Compress) + "`n")
    $temporary = $Path + '.' + [Guid]::NewGuid().ToString('N') + '.tmp'
    try {
        $stream = [IO.FileStream]::new(
            $temporary,
            [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($temporary, $Path)
    }
    catch {
        try { if ([IO.File]::Exists($temporary)) { [IO.File]::Delete($temporary) } } catch { }
        Throw-SafeFailure 'The immutable local-state acknowledgement could not be created.'
    }
    return [pscustomobject]@{
        Sha256 = Get-ByteArraySha256 $bytes
    }
}

function Invoke-LocalStateExchange(
    [int]$Sequence,
    [string]$RequestPath,
    [string]$AcknowledgementPath,
    [Diagnostics.Process]$Application,
    [string]$ExpectedApplicationPath) {
    $script:LocalInputRequestCalls++
    if ($script:LocalInputRequestCalls -ne $Sequence -or
        [IO.File]::Exists($AcknowledgementPath)) {
        Throw-SafeFailure 'The local-state one-shot input sequence changed.'
    }
    $requestEvidence = Wait-ReadSmallJsonEvidenceFile `
        $RequestPath `
        "Local-state request $Sequence" `
        ([datetime]::UtcNow.AddSeconds(3))
    $request = $requestEvidence.Value
    Assert-ExactJsonPropertyNames $request @(
        'schemaVersion', 'token', 'sequence', 'targetUrl', 'operation',
        'targetId', 'folderKind', 'point', 'viewport', 'devicePixelRatio',
        'mouseDownCalls', 'mouseUpCalls', 'escapeKeyCalls', 'inputRetryCount') `
        "Local-state request $Sequence"
    $expected = $ExpectedExchangePlan[$Sequence - 1]
    $targetId = if ($null -eq $request.targetId) { $null } else { [string]$request.targetId }
    $folderKind = if ($null -eq $request.folderKind) { $null } else { [string]$request.folderKind }
    if ([int](ConvertTo-LocalFiniteNumber $request.schemaVersion 'schemaVersion') -ne 1 -or
        [int](ConvertTo-LocalFiniteNumber $request.sequence 'sequence') -ne $Sequence -or
        $request.token -isnot [string] -or [string]$request.token -cnotmatch '\A[0-9A-F]{32}\z' -or
        [string]$request.targetUrl -cne 'https://legacy-parity.mbn.local/index.html' -or
        [string]$request.operation -cne [string]$expected.Operation -or
        $targetId -cne $expected.TargetId -or $folderKind -cne $expected.FolderKind -or
        [int](ConvertTo-LocalFiniteNumber $request.inputRetryCount 'inputRetryCount') -ne 0) {
        Throw-SafeFailure "Local-state request $Sequence is outside the closed plan."
    }

    Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
    Assert-NoTornadoConnection $Application.Id
    $pickerEvidence = $null
    if ([string]$expected.Operation -ceq 'observe-local-files') {
        if ($null -ne $request.point -or $null -ne $request.viewport -or
            $null -ne $request.devicePixelRatio -or
            [int]$request.mouseDownCalls -ne 0 -or [int]$request.mouseUpCalls -ne 0 -or
            [int]$request.escapeKeyCalls -ne 0) {
            Throw-SafeFailure 'A file observation request attempted to carry input geometry.'
        }
    }
    else {
        Assert-ExactJsonPropertyNames $request.point @('x', 'y') "Request $Sequence point"
        Assert-ExactJsonPropertyNames $request.viewport @('width', 'height') "Request $Sequence viewport"
        $x = ConvertTo-LocalFiniteNumber $request.point.x 'point.x'
        $y = ConvertTo-LocalFiniteNumber $request.point.y 'point.y'
        $width = ConvertTo-LocalFiniteNumber $request.viewport.width 'viewport.width'
        $height = ConvertTo-LocalFiniteNumber $request.viewport.height 'viewport.height'
        $scale = ConvertTo-LocalFiniteNumber $request.devicePixelRatio 'devicePixelRatio'
        $expectedEscapeCount = if ([string]$expected.Operation -ceq
            'folder-picker-click-cancel') { 1 } else { 0 }
        if ($width -lt 1 -or $width -gt 16384 -or $height -lt 1 -or $height -gt 16384 -or
            $x -lt 0 -or $x -ge $width -or $y -lt 0 -or $y -ge $height -or
            $scale -lt 0.25 -or $scale -gt 5 -or
            [int]$request.mouseDownCalls -ne 1 -or [int]$request.mouseUpCalls -ne 1 -or
            [int]$request.escapeKeyCalls -ne $expectedEscapeCount) {
            Throw-SafeFailure "Request $Sequence input geometry or exact count is invalid."
        }
        $baselineWindows = if ([string]$expected.Operation -ceq
            'folder-picker-click-cancel') { Get-TopLevelWindowHandles } else { $null }
        [LegacyPackageInputNative]::SendApplicationClick(
            $Application.MainWindowHandle,
            $Application.Id,
            30001,
            $x,
            $y,
            $width,
            $height,
            $scale,
            [string]$expected.Operation -ceq 'folder-picker-click-cancel')
        if ([string]$expected.Operation -ceq 'folder-picker-click-cancel') {
            $picker = Wait-UniqueOwnedFolderPicker `
                $baselineWindows `
                $Application `
                $ExpectedApplicationPath `
                ([datetime]::UtcNow.AddSeconds(10))
            [LegacyPackageInputNative]::SendEscapeToForegroundWindow($picker.Handle)
            Wait-FolderPickerClosed `
                $picker.Handle `
                $Application `
                $ExpectedApplicationPath `
                ([datetime]::UtcNow.AddSeconds(10))
            $pickerEvidence = [ordered]@{
                uniqueNewPicker = $true
                ownerLinkedToApplication = [bool]$picker.OwnerLinked
                sameProcessAsApplication = [bool]$picker.SameProcess
                processId = [int]$picker.ProcessId
                windowClass = [string]$picker.ClassName
                windowTitle = [string]$picker.Name
                isModal = [bool]$picker.IsModal
                folderSelectButtonCount = [int]$picker.ConfirmButtonCount
                cancelButtonCount = [int]$picker.CancelButtonCount
                escapeCancelled = $true
                closedAfterEscape = $true
            }
        }
    }
    Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
    Assert-NoTornadoConnection $Application.Id
    # A physical Yes click starts an asynchronous atomic store operation.  Do
    # not race that write by opening the destination in the click handler.  Node
    # waits for the native completion receipt and then publishes the dedicated
    # observation request (10 or 13), which is the first permitted fresh read.
    $files = if ($Sequence -eq 9 -or $Sequence -eq 12) {
        $script:LastObservedFileState
    }
    else {
        $fresh = Get-LocalFileState
        $script:LastObservedFileState = $fresh
        $fresh
    }
    if (-not (Test-JsonEquivalent $files.settings $script:BaselineSettingsState)) {
        Throw-SafeFailure 'The runtime folder settings file changed during a cancel-only smoke.'
    }
    if ([string]$files.source.sha256 -cne $ExpectedSourceSha256 -or
        [int]$files.source.rowCount -ne 8) {
        Throw-SafeFailure 'The original read-only comparison source changed during the smoke.'
    }
    if ($Sequence -lt 9 -and
        (-not (Test-JsonEquivalent $files.destination $script:InitialDestinationState))) {
        Throw-SafeFailure 'The comparison destination changed before the authorized Yes input.'
    }
    if ($Sequence -eq 10) {
        if ([int]$files.destination.rowCount -ne 9 -or
            [string]$files.destination.firstPair -cne $ExpectedInitialPairIdentity -or
            [string]$files.destination.sha256 -cne $ExpectedImportedDestinationSha256) {
            Throw-SafeFailure 'The first authorized import did not retain the known nine-row result.'
        }
        $script:FirstImportedDestinationState = $files.destination
    }
    if ($Sequence -eq 13 -and
        (-not (Test-JsonEquivalent $files.destination $script:FirstImportedDestinationState))) {
        Throw-SafeFailure 'The second import changed the comparison file instead of added0 idempotence.'
    }

    $script:LocalInputAcknowledgementCalls++
    if ($script:LocalInputAcknowledgementCalls -ne $Sequence) {
        Throw-SafeFailure 'The local-state acknowledgement budget changed.'
    }
    $acknowledgement = Write-LocalAcknowledgement `
        $AcknowledgementPath `
        $request `
        $files `
        $pickerEvidence
    return [pscustomobject]@{
        Sequence = $Sequence
        RequestSha256 = $requestEvidence.Sha256
        AcknowledgementSha256 = $acknowledgement.Sha256
    }
}

function Invoke-LocalHarnessUnderWatch(
    [string]$Executable,
    [string]$ScriptPath,
    [int]$DebugPort,
    [string]$OutputPath,
    [string]$ScreenshotPath,
    [string]$ExchangePath,
    [int]$TimeoutSeconds,
    [Diagnostics.Process]$Application,
    [string]$ExpectedApplicationPath) {
    $rawArguments = @(
        $ScriptPath,
        '--port', [string]$DebugPort,
        '--output', $OutputPath,
        '--screenshot', $ScreenshotPath,
        '--exchange-directory', $ExchangePath,
        '--timeout-ms', [string]($TimeoutSeconds * 1000))
    $startInfo = [Diagnostics.ProcessStartInfo]::new()
    $startInfo.FileName = $Executable
    $startInfo.WorkingDirectory = $RepositoryRoot
    $startInfo.Arguments = ($rawArguments | ForEach-Object {
        ConvertTo-QuotedProcessArgument ([string]$_)
    }) -join ' '
    $startInfo.UseShellExecute = $false
    $startInfo.CreateNoWindow = $true
    $startInfo.RedirectStandardInput = $true
    try { $node = [Diagnostics.Process]::Start($startInfo) }
    catch { Throw-SafeFailure 'The local-state Node harness could not be started.' }
    if ($null -eq $node) { Throw-SafeFailure 'The local-state Node harness did not start.' }

    $deadline = [datetime]::UtcNow.AddSeconds($TimeoutSeconds + 30)
    $sequence = 1
    $exchanges = @()
    $monitoringFailure = $null
    try {
        while (-not $node.HasExited) {
            if ([datetime]::UtcNow -ge $deadline) {
                Throw-SafeFailure 'The local-state harness exceeded its global deadline.'
            }
            Assert-ExactApplicationStillRunning $Application $ExpectedApplicationPath
            Assert-NoTornadoConnection $Application.Id
            if ($sequence -le $ExpectedExchangePlan.Count) {
                $requestPath = Join-Path $ExchangePath (
                    $sequence.ToString('00') + '.request.json')
                $ackPath = Join-Path $ExchangePath (
                    $sequence.ToString('00') + '.ack.json')
                if ([IO.File]::Exists($requestPath)) {
                    $exchanges += Invoke-LocalStateExchange `
                        $sequence `
                        $requestPath `
                        $ackPath `
                        $Application `
                        $ExpectedApplicationPath
                    $sequence++
                }
            }
            Start-Sleep -Milliseconds 50
            $node.Refresh()
        }
        if ($sequence -ne ($ExpectedExchangePlan.Count + 1) -or
            $script:LocalInputRequestCalls -ne $ExpectedExchangePlan.Count -or
            $script:LocalInputAcknowledgementCalls -ne $ExpectedExchangePlan.Count) {
            Throw-SafeFailure 'The closed thirteen-step local-state sequence did not complete.'
        }
    }
    catch { $monitoringFailure = $_.Exception.Message }

    if ($null -ne $monitoringFailure) {
        $stopped = $node.HasExited
        if (-not $stopped) {
            try {
                $node.StandardInput.WriteLine('CANCEL')
                $node.StandardInput.Flush()
                $stopped = $node.WaitForExit(5000)
            }
            catch { $stopped = $false }
        }
        if (-not $stopped) {
            try {
                $node.Kill()
                $stopped = $node.WaitForExit(10000)
            }
            catch { $stopped = $false }
        }
        Throw-SafeFailure (
            "$monitoringFailure The input helper was stopped if possible; " +
            'the packaged app was left open and no input was retried.')
    }
    return [pscustomobject]@{
        ExitCode = $node.ExitCode
        Exchanges = @($exchanges)
    }
}

function Read-LocalHarnessEvidenceFile([string]$Path) {
    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 128KB) {
            Throw-SafeFailure 'Local-state harness evidence is not a bounded regular file.'
        }

        $bytes = [IO.File]::ReadAllBytes($Path)
        if ($bytes.Length -ne $item.Length) {
            Throw-SafeFailure 'Local-state harness evidence 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 'Local-state harness evidence is not strict bounded JSON.'
    }
}

function Assert-LocalHarnessEvidence(
    [string]$EvidencePath,
    [string]$ScreenshotPath,
    [string]$ExchangePath) {
    $sealed = Read-LocalHarnessEvidenceFile $EvidencePath
    $value = $sealed.Value
    $baselineMode = [string]$value.files.initialDestinationMode
    $expectedFirstAdded = if ($baselineMode -ceq 'fresh') { 8 } else { 0 }
    $expectedFirstSkipped = if ($baselineMode -ceq 'fresh') { 0 } else { 8 }
    $expectedInitialPairCount = if ($baselineMode -ceq 'fresh') { 1 } else { 9 }
    if (($baselineMode -cne 'fresh' -and $baselineMode -cne 'alreadyImported') -or
        $baselineMode -cne $script:DestinationBaselineMode -or
        [int]$value.schemaVersion -ne 1 -or
        [string]$value.profile -cne 'local-settings-comparison-import' -or
        [string]$value.result -cne 'PASS' -or $null -ne $value.error -or
        [string]$value.target.expectedUrl -cne
            'https://legacy-parity.mbn.local/index.html' -or
        [int]$value.target.port -ne $Port -or
        [string]$value.target.url -cne
            'https://legacy-parity.mbn.local/index.html' -or
        [string]$value.safety.requiredMode -cne 'dryRun' -or
        [string]$value.safety.requiredPhase -cne 'idle' -or
        $value.safety.appCloseRequested -ne $false -or
        $value.safety.playoutIntentIssued -ne $false -or
        [int]$value.safety.inputRetryCount -ne 0 -or
        @($value.safety.blockedOutboundMessages).Count -ne 0 -or
        @($value.safety.stateViolations).Count -ne 0 -or
        $value.settings.allCancelled -ne $true -or
        $value.settings.settingsFileUnchanged -ne $true -or
        -not (Test-ExactStringSequence @($value.settings.pickerKinds) @(
            'design', 'resource', 'background')) -or
        $value.comparison.initialPairPreserved -ne $true -or
        [int]$value.comparison.initialPairCount -ne $expectedInitialPairCount -or
        $value.comparison.secondImportIdempotent -ne $true -or
        [int]$value.comparison.afterFirstImport.receipt.addedPairCount -ne
            $expectedFirstAdded -or
        [int]$value.comparison.afterFirstImport.receipt.skippedDuplicateCount -ne
            $expectedFirstSkipped -or
        [int]$value.comparison.afterFirstImport.pairCount -ne 9 -or
        [int]$value.comparison.afterSecondImport.receipt.addedPairCount -ne 0 -or
        [int]$value.comparison.afterSecondImport.receipt.skippedDuplicateCount -ne 8 -or
        [int]$value.comparison.afterSecondImport.pairCount -ne 9 -or
        [string]$value.files.destinationAfterFirstImport.sha256 -cne
            $ExpectedImportedDestinationSha256 -or
        [string]$value.files.destinationAfterFirstImport.sha256 -cne
            [string]$value.files.destinationAfterSecondImport.sha256 -or
        @($value.exchanges).Count -ne 13) {
        Throw-SafeFailure 'The local-state evidence does not satisfy the exact cancel/import contract.'
    }
    $screenshot = Get-Item -LiteralPath $ScreenshotPath -Force
    if ($screenshot.Length -le 0 -or
        [int64]$value.screenshot.bytes -ne $screenshot.Length -or
        [string]$value.screenshot.sha256 -cne
            (Get-FileHash -Algorithm SHA256 -LiteralPath $ScreenshotPath).Hash) {
        Throw-SafeFailure 'The local-state screenshot does not match its sealed evidence.'
    }
    for ($index = 0; $index -lt 13; $index++) {
        $sequence = $index + 1
        $entry = $value.exchanges[$index]
        $requestPath = Join-Path $ExchangePath ($sequence.ToString('00') + '.request.json')
        $ackPath = Join-Path $ExchangePath ($sequence.ToString('00') + '.ack.json')
        if ([int]$entry.sequence -ne $sequence -or
            -not (Test-PathEqual ([string]$entry.requestPath) $requestPath) -or
            -not (Test-PathEqual ([string]$entry.acknowledgementPath) $ackPath) -or
            [string]$entry.requestSha256 -cne
                (Get-FileHash -Algorithm SHA256 -LiteralPath $requestPath).Hash -or
            [string]$entry.acknowledgementSha256 -cne
                (Get-FileHash -Algorithm SHA256 -LiteralPath $ackPath).Hash) {
            Throw-SafeFailure "Local-state exchange $sequence is not sealed exactly."
        }
        $expectedOperation = [string]$ExpectedExchangePlan[$index].Operation
        if ($expectedOperation -ceq 'observe-local-files') {
            if ($null -ne $entry.physicalPointer) {
                Throw-SafeFailure "File observation $sequence unexpectedly contains pointer input."
            }
        }
        elseif ($null -eq $entry.physicalPointer -or
            $entry.physicalPointer.down.isTrusted -ne $true -or
            $entry.physicalPointer.up.isTrusted -ne $true -or
            [string]$entry.physicalPointer.down.pointerType -cne 'mouse' -or
            [string]$entry.physicalPointer.up.pointerType -cne 'mouse' -or
            [string]$entry.physicalPointer.down.targetId -cne
                [string]$ExpectedExchangePlan[$index].TargetId -or
            [string]$entry.physicalPointer.up.targetId -cne
                [string]$ExpectedExchangePlan[$index].TargetId) {
            Throw-SafeFailure "Input exchange $sequence lacks exact trusted pointer evidence."
        }
    }
    return $value
}

if ($StaticAudit) {
    [pscustomobject]@{
        result = 'PASS'
        profile = 'local-settings-comparison-import'
        packageFlavor = 'DebugAppX'
        exchangeCount = $ExpectedExchangePlan.Count
        physicalClickCount = @($ExpectedExchangePlan | Where-Object {
            $_.Operation -ceq 'application-click' -or
            $_.Operation -ceq 'folder-picker-click-cancel'
        }).Count
        folderPickerCancelCount = @($ExpectedExchangePlan | Where-Object {
            $_.Operation -ceq 'folder-picker-click-cancel'
        }).Count
        fileObservationCount = @($ExpectedExchangePlan | Where-Object {
            $_.Operation -ceq 'observe-local-files'
        }).Count
        inputRetryCount = 0
        expectedSourceSha256 = $ExpectedSourceSha256
        expectedSourceRows = 8
        expectedFreshDestinationSha256 = $ExpectedFreshDestinationSha256
        expectedFreshDestinationRows = 1
        expectedImportedDestinationSha256 = $ExpectedImportedDestinationSha256
        expectedImportedDestinationRows = 9
        sendInputClickAvailable = $null -ne
            [LegacyPackageInputNative].GetMethod('SendApplicationClick')
        sendInputEscapeAvailable = $null -ne
            [LegacyPackageInputNative].GetMethod('SendEscapeToForegroundWindow')
        harnessPath = $HarnessPath
        harnessSha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $HarnessPath).Hash
    } | ConvertTo-Json -Compress
    return
}

$timestamp = [datetime]::UtcNow.ToString('yyyyMMddTHHmmssfffZ')
$Output = Resolve-EvidencePath $Output "legacy-package-local-state-$timestamp.json"
$Screenshot = Resolve-EvidencePath $Screenshot "legacy-package-local-state-$timestamp.png"
if ([string]::IsNullOrWhiteSpace($ExchangeDirectory)) {
    $ExchangeDirectory = [IO.Path]::ChangeExtension($Output, $null) + '.exchanges'
}
elseif (-not [IO.Path]::IsPathRooted($ExchangeDirectory)) {
    $ExchangeDirectory = [IO.Path]::GetFullPath((Join-Path $RepositoryRoot $ExchangeDirectory))
}
else { $ExchangeDirectory = [IO.Path]::GetFullPath($ExchangeDirectory) }
$NodePath = Resolve-NodeExecutable $NodePath

try {
    if (-not [IO.File]::Exists($HarnessPath)) {
        Throw-SafeFailure 'The tracked local-state harness is missing.'
    }
    Assert-OutputPathAvailable $Output 'Output'
    Assert-OutputPathAvailable $Screenshot 'Screenshot'
    Assert-OutputPathAvailable $ExchangeDirectory 'Exchange directory'
    [void][IO.Directory]::CreateDirectory($ExchangeDirectory)
    if (@(Get-ChildItem -LiteralPath $ExchangeDirectory -Force).Count -ne 0) {
        Throw-SafeFailure 'The new exchange directory is not empty.'
    }
    Assert-LocalFilePreflight | Out-Null
    Assert-LocalConfigurationIsDryRun
    Assert-NoUnsafeEnvironment
    $registration = Get-ExactDevelopmentPackage
    Assert-NoExistingApplication
    Assert-PortIsFree $Port

    $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

    $script:Phase = 'local settings and comparison input harness'
    $harness = Invoke-LocalHarnessUnderWatch `
        $NodePath `
        $HarnessPath `
        $Port `
        $Output `
        $Screenshot `
        $ExchangeDirectory `
        $HarnessTimeoutSeconds `
        $script:ApplicationProcess `
        $registration.Executable
    if ($harness.ExitCode -ne 0) {
        Throw-SafeFailure "The local-state harness failed with exit code $($harness.ExitCode)."
    }
    $evidence = Assert-LocalHarnessEvidence $Output $Screenshot $ExchangeDirectory
    if ($harness.Exchanges.Count -ne 13) {
        Throw-SafeFailure 'The wrapper did not observe all thirteen sealed exchanges.'
    }
    Assert-ExactApplicationStillRunning $script:ApplicationProcess $registration.Executable
    Assert-NoTornadoConnection $script:ApplicationProcess.Id
    $finalFiles = Get-LocalFileState
    if (-not (Test-JsonEquivalent $finalFiles.settings $script:BaselineSettingsState) -or
        -not (Test-JsonEquivalent $finalFiles.destination $script:FirstImportedDestinationState) -or
        [string]$finalFiles.source.sha256 -cne $ExpectedSourceSha256) {
        Throw-SafeFailure 'Final local files do not match the sealed cancel/idempotence result.'
    }

    # The authorized import may have appended the fresh baseline or confirmed
    # the existing imported baseline. Normal close is the only remaining action.
    $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.'
    }

    $script:Phase = 'complete'
    [pscustomobject]@{
        result = [string]$evidence.result
        packageFullName = $PackageFullName
        packageMode = $PackageModeLabel
        playoutMode = 'DryRun'
        processId = $script:ApplicationProcess.Id
        tornadoPortConnections = 0
        inputRetryCount = 0
        localInputRequestCalls = $script:LocalInputRequestCalls
        localInputAcknowledgementCalls = $script:LocalInputAcknowledgementCalls
        settingsPickerCancelCount = 3
        comparisonBaselineMode = $script:DestinationBaselineMode
        comparisonImportAddedCount = if ($script:DestinationBaselineMode -ceq 'fresh') { 8 } else { 0 }
        comparisonSecondImportAddedCount = 0
        output = $Output
        outputSha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $Output).Hash
        screenshot = $Screenshot
        screenshotSha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $Screenshot).Hash
        exchangeDirectory = $ExchangeDirectory
    }
}
catch {
    $message = $_.Exception.Message
    if ($script:CloseMainWindowCalls -gt 0 -or $script:PrimaryInvokeCalls -gt 0) {
        Throw-SafeFailure (
            "Local-state 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 ($running) {
        Throw-SafeFailure (
            "Local-state smoke stopped during '$($script:Phase)': $message " +
            'The app was intentionally left open; no input retry, guessed cleanup, ' +
            'close retry or forced termination was attempted.')
    }
    throw
}
