function Assert-IndependentMultiDisplayProof($Boot,$Build,$ImageManifest,[string]$ImageManifestPath,[bool]$Packaged,[string]$TaskRoot,$Snapshot) {
if($Build.Edition -cne 'Desktop' -or $Build.Configuration.DesktopMultiDisplayManagement -ne $true) { return $null }
if($Boot.MultiDisplayAcceptanceRequired -ne $true -or $Boot.MultiDisplayAcceptancePassed -ne $true -or !$Boot.MultiDisplayProof) {
throw 'Desktop multi-display delivery requires actual independent scanout and cold-boot acceptance.'
}
$path=if($Packaged){Get-IndependentFile $TaskRoot 'Validation/MultiDisplay/Result.json'}else{(Resolve-Path -LiteralPath $Boot.MultiDisplayProof.Path).Path}
Assert-IndependentHash $path $Boot.MultiDisplayProof.Sha256 'multi-display acceptance'
$proof=Read-IndependentJson $path; $root=Split-Path -Parent $path
if($proof.Kind -cne 'XfeIndependentMultiDisplayProof' -or $proof.Version -ne 1 -or $proof.Passed -ne $true -or
$proof.ImageSha256 -cne $Boot.ImageSha256 -or $proof.KernelSha256 -cne $Boot.KernelSha256 -or
$proof.ManifestSha256 -cne (Get-IndependentHash $ImageManifestPath) -or $proof.SourcesUnchanged -ne $true -or
$proof.SourceImageUnchanged -ne $true -or $proof.OnlyWorkspaceSectorsChanged -ne $true -or
$proof.HostWorkspaceInjection -ne $false -or @($proof.Boots).Count -ne 3 -or
$proof.PhysicalHardwareAcceptancePassed -ne $false -or $proof.HotplugAcceptancePassed -ne $false) {
throw 'The multi-display evidence is incomplete or belongs to another image.'
}
foreach($field in @('DuplicatePixelEqualityPassed','IndependentExtendPassed','DistinctPhysicalIdentifyPassed','SelectedOnlyPassed',
'AutomaticRevertPassed','WindowMovedAndMaximizedOnSecond','UsbColdBootLayoutRestorePassed','MissingDisplaySafeFallbackPassed')) {
$bound=$proof.PSObject.Properties[$field]
if(!$bound -or $bound.Value -ne $true) {throw ('Missing multi-display acceptance: '+$field)}
}
Assert-IndependentSourceSubset $Build.SourceSha256 $proof.SourceHashes 'display proof to build'
Assert-IndependentSourceSubset $proof.SourceHashes $Snapshot 'display proof to source snapshot'
if(!$proof.SourceHashes.PSObject.Properties['Tools/IndependentKernel/TestMultiDisplay.py']) {throw 'The multi-display test harness is not bound.'}
$files=@{}
foreach($file in $proof.EvidenceFiles) {
if($files.ContainsKey([string]$file.Path)) {throw 'Duplicate multi-display evidence path.'}
Assert-IndependentHash (Get-IndependentFile $root $file.Path) $file.Sha256 'actual independent scanout evidence'
$files[[string]$file.Path]=[string]$file.Sha256
}
for($index=0;$index -lt 3;$index++) {
$guest=$proof.Boots[$index];$number=$index+1
if($guest.Number -ne $number -or $guest.Passed -ne $true -or $null -eq $guest.QemuExitCode -or $guest.QemuExitCode -ne 0) {throw 'A display guest did not exit cleanly.'}
$serialPath='Boot'+$number+'/Serial.log'
if(!$files.ContainsKey($serialPath)) {throw 'A display boot has no raw serial evidence.'}
$serial=[IO.File]::ReadAllText((Get-IndependentFile $root $serialPath))
$count=if($index -eq 2){1}else{2}
if(!$serial.Contains('XFE_DISPLAY_OUTPUTS|Count|'+$count+'|Hotplug|0|Modeset|0') -or !$serial.Contains('XFE_INDEPENDENT_DESKTOP_FIRST_FRAME|')) {
throw 'Raw evidence does not contain the actual native display outputs.'
}
if($index -lt 2 -and @($guest.QemuArguments | Where-Object {$_ -clike 'secondary-vga,id=Display2,*'}).Count -ne 1) {throw 'The display proof does not use two independent VGA devices.'}
foreach($capture in $guest.Captures) {
if(!$files.ContainsKey([string]$capture.Path) -or $files[[string]$capture.Path] -cne $capture.Sha256 -or $capture.Output -lt 1 -or $capture.Output -gt $count) {
throw 'A per-output capture lacks a bound evidence file.'
}
}
}
foreach($name in @('Initial-Duplicate','Settings','Identify','Identify-Removed','Extend-Preview','Arranged-Left','Arrangement-Reverted',
'Window-On-Second','Second-Main','Only-Second','Timeout-Restored','Duplicate-Again','Saved-Extended')) {
$pair=@($proof.Boots[0].Captures | Where-Object {$_.Name -ceq $name} | Sort-Object Output)
if($pair.Count -ne 2 -or $pair[0].Output -ne 1 -or $pair[1].Output -ne 2) {throw ('Missing separate display captures: '+$name)}
if($name -in @('Initial-Duplicate','Settings','Identify-Removed','Duplicate-Again')) {
if($pair[0].Sha256 -cne $pair[1].Sha256) {throw 'Mirrored display pixels differ.'}
} elseif($pair[0].Sha256 -ceq $pair[1].Sha256) {throw ('Independent display pixels are identical: '+$name)}
}
if($proof.Boots[1].SavedLayoutRestored -ne $true -or $proof.Boots[2].MissingDisplaySafeFallback -ne $true) {throw 'Display cold-boot restoration and missing-monitor fallback are required.'}
return [pscustomobject]@{Path=$path;Root=$root;Proof=$proof}
}
function Assert-IndependentMultiDisplayProof($Boot,$Build,$ImageManifest,[string]$ImageManifestPath,[bool]$Packaged,[string]$TaskRoot,$Snapshot) {
if($Build.Edition -cne 'Desktop' -or $Build.Configuration.DesktopMultiDisplayManagement -ne $true) { return $null }
if($Boot.MultiDisplayAcceptanceRequired -ne $true -or $Boot.MultiDisplayAcceptancePassed -ne $true -or !$Boot.MultiDisplayProof) {
throw 'Desktop multi-display delivery requires actual independent scanout and cold-boot acceptance.'
}
$path=if($Packaged){Get-IndependentFile $TaskRoot 'Validation/MultiDisplay/Result.json'}else{(Resolve-Path -LiteralPath $Boot.MultiDisplayProof.Path).Path}
Assert-IndependentHash $path $Boot.MultiDisplayProof.Sha256 'multi-display acceptance'
$proof=Read-IndependentJson $path; $root=Split-Path -Parent $path
if($proof.Kind -cne 'XfeIndependentMultiDisplayProof' -or $proof.Version -ne 1 -or $proof.Passed -ne $true -or
$proof.ImageSha256 -cne $Boot.ImageSha256 -or $proof.KernelSha256 -cne $Boot.KernelSha256 -or
$proof.ManifestSha256 -cne (Get-IndependentHash $ImageManifestPath) -or $proof.SourcesUnchanged -ne $true -or
$proof.SourceImageUnchanged -ne $true -or $proof.OnlyWorkspaceSectorsChanged -ne $true -or
$proof.HostWorkspaceInjection -ne $false -or @($proof.Boots).Count -ne 3 -or
$proof.PhysicalHardwareAcceptancePassed -ne $false -or $proof.HotplugAcceptancePassed -ne $false) {
throw 'The multi-display evidence is incomplete or belongs to another image.'
}
foreach($field in @('DuplicatePixelEqualityPassed','IndependentExtendPassed','DistinctPhysicalIdentifyPassed','SelectedOnlyPassed',
'AutomaticRevertPassed','WindowMovedAndMaximizedOnSecond','UsbColdBootLayoutRestorePassed','MissingDisplaySafeFallbackPassed')) {
$bound=$proof.PSObject.Properties[$field]
if(!$bound -or $bound.Value -ne $true) {throw ('Missing multi-display acceptance: '+$field)}
}
Assert-IndependentSourceSubset $Build.SourceSha256 $proof.SourceHashes 'display proof to build'
Assert-IndependentSourceSubset $proof.SourceHashes $Snapshot 'display proof to source snapshot'
if(!$proof.SourceHashes.PSObject.Properties['Tools/IndependentKernel/TestMultiDisplay.py']) {throw 'The multi-display test harness is not bound.'}
$files=@{}
foreach($file in $proof.EvidenceFiles) {
if($files.ContainsKey([string]$file.Path)) {throw 'Duplicate multi-display evidence path.'}
Assert-IndependentHash (Get-IndependentFile $root $file.Path) $file.Sha256 'actual independent scanout evidence'
$files[[string]$file.Path]=[string]$file.Sha256
}
for($index=0;$index -lt 3;$index++) {
$guest=$proof.Boots[$index];$number=$index+1
if($guest.Number -ne $number -or $guest.Passed -ne $true -or $null -eq $guest.QemuExitCode -or $guest.QemuExitCode -ne 0) {throw 'A display guest did not exit cleanly.'}
$serialPath='Boot'+$number+'/Serial.log'
if(!$files.ContainsKey($serialPath)) {throw 'A display boot has no raw serial evidence.'}
$serial=[IO.File]::ReadAllText((Get-IndependentFile $root $serialPath))
$count=if($index -eq 2){1}else{2}
if(!$serial.Contains('XFE_DISPLAY_OUTPUTS|Count|'+$count+'|Hotplug|0|Modeset|0') -or !$serial.Contains('XFE_INDEPENDENT_DESKTOP_FIRST_FRAME|')) {
throw 'Raw evidence does not contain the actual native display outputs.'
}
if($index -lt 2 -and @($guest.QemuArguments | Where-Object {$_ -clike 'secondary-vga,id=Display2,*'}).Count -ne 1) {throw 'The display proof does not use two independent VGA devices.'}
foreach($capture in $guest.Captures) {
if(!$files.ContainsKey([string]$capture.Path) -or $files[[string]$capture.Path] -cne $capture.Sha256 -or $capture.Output -lt 1 -or $capture.Output -gt $count) {
throw 'A per-output capture lacks a bound evidence file.'
}
}
}
foreach($name in @('Initial-Duplicate','Settings','Identify','Identify-Removed','Extend-Preview','Arranged-Left','Arrangement-Reverted',
'Window-On-Second','Second-Main','Only-Second','Timeout-Restored','Duplicate-Again','Saved-Extended')) {
$pair=@($proof.Boots[0].Captures | Where-Object {$_.Name -ceq $name} | Sort-Object Output)
if($pair.Count -ne 2 -or $pair[0].Output -ne 1 -or $pair[1].Output -ne 2) {throw ('Missing separate display captures: '+$name)}
if($name -in @('Initial-Duplicate','Settings','Identify-Removed','Duplicate-Again')) {
if($pair[0].Sha256 -cne $pair[1].Sha256) {throw 'Mirrored display pixels differ.'}
} elseif($pair[0].Sha256 -ceq $pair[1].Sha256) {throw ('Independent display pixels are identical: '+$name)}
}
if($proof.Boots[1].SavedLayoutRestored -ne $true -or $proof.Boots[2].MissingDisplaySafeFallback -ne $true) {throw 'Display cold-boot restoration and missing-monitor fallback are required.'}
return [pscustomobject]@{Path=$path;Root=$root;Proof=$proof}
}