$report=[Native41]::Top([uint32]$l.pid,'Changes since opening');Click $report 'Close';Start-Sleep -Milliseconds 300
$out="$r\roster-editor41h"
if(Test-Path $out){throw 'GUI output identity already exists'}
New-Item -ItemType Directory $out|Out-Null
Click $main 'Save a copy';Start-Sleep -Milliseconds 600
$dialog=[Native41]::Top([uint32]$l.pid,'Save a new roster copy')
$null=[Native41]::SetForegroundWindow($dialog);Start-Sleep -Milliseconds 200
Add-Type -AssemblyName System.Windows.Forms
foreach($keys in @('%n','^a',($out+'\GuiMeta.ROS'))){if([Native41]::GetForegroundWindow() -ne $dialog){throw 'Owned save dialog lost focus'};[Windows.Forms.SendKeys]::SendWait($keys);Start-Sleep -Milliseconds 120}
$paths=@([Native41]::Children($dialog)|ForEach-Object{[Native41]::ControlText($_)}|Where-Object{$_ -eq ($out+'\GuiMeta.ROS')})
if(!$paths.Count){throw 'Save filename input does not match owned output path'}
Click $dialog 'Save';Start-Sleep -Seconds 2
$popup=[Native41]::Top([uint32]$l.pid,'Roster saved')
$messages=@([Native41]::Children($popup)|ForEach-Object{[Native41]::Title($_)}|Where-Object{$_ -match 'Saved and read back'})
if($messages.Count -ne 1 -or $messages[0] -notmatch 'companion together'){throw 'Companion save confirmation absent'}
@{pid=$l.pid;utc=[DateTime]::UtcNow.ToString('o');output="$out\GuiMeta.ROS";message=$messages;rosterSha256=(Get-FileHash "$out\GuiMeta.ROS").Hash;companionSha256=(Get-FileHash "$out\GuiMeta.ROS.openhoops.json").Hash;sourceSha256=(Get-FileHash "$r\roster-editor41e\Studio.ROS").Hash;sourceCompanionSha256=(Get-FileHash "$r\roster-editor41e\Studio.ROS.openhoops.json").Hash}|ConvertTo-Json -Depth 4|Set-Content "$o\ui-save.json"
