[CmdletBinding()] param( [string]$ExecutableName = 'VoxelForgeUnrealSurfaceNative.exe', [ValidateRange(1, 16)][int]$Workers = 8, [ValidateRange(30, 900)][int]$TimeoutSeconds = 120 ) # Rejoue les probes de strates sauvegardées et fait échouer l'audit si un passage redevient solide. # Replays the saved strate probes and fails the audit if any passage becomes solid again. Set-StrictMode -Version Latest $ErrorActionPreference = 'Stop' $PluginRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..\..\..')) $StandaloneRoot = Join-Path $PluginRoot 'Standalone' $ExecutablePath = Join-Path $StandaloneRoot ('bin\' + $ExecutableName) $ProbeRoot = Join-Path $StandaloneRoot 'Research\OwnerShapeWorld\core_strate_coverage\probes' $LogRoot = Join-Path $ProbeRoot ('round5_walkability_w' + $Workers) if ([IO.Path]::GetFileName($ExecutableName) -ne $ExecutableName -or [IO.Path]::GetExtension($ExecutableName) -ne '.exe') { throw 'ExecutableName must be an executable filename.' } if (-not (Test-Path -LiteralPath $ExecutablePath -PathType Leaf)) { throw "Viewer not found: $ExecutablePath" } if (-not (Test-Path -LiteralPath $ProbeRoot -PathType Container)) { throw "Passage probe directory not found: $ProbeRoot" } [IO.Directory]::CreateDirectory($LogRoot) | Out-Null $HostProcess = Get-Process -Id $PID $HostProcess.PriorityClass = [Diagnostics.ProcessPriorityClass]::Normal $HostProcess.ProcessorAffinity = [IntPtr]0xFFFF $Probes = @(Get-ChildItem -LiteralPath $ProbeRoot -Filter '*.json' -File | Sort-Object Name) if ($Probes.Count -ne 15) { throw "Expected all 15 saved strate probes, found $($Probes.Count)." } $Passed = 0 foreach ($Probe in $Probes) { $Stem = [IO.Path]::GetFileNameWithoutExtension($Probe.Name) $StdoutPath = Join-Path $LogRoot ($Stem + '.stdout.log') $StderrPath = Join-Path $LogRoot ($Stem + '.stderr.log') # Start-Process flattens this array into one command-line string on Windows. # Quote the JSON path because the workspace's parent directory contains a space. $Arguments = @(('"' + $Probe.FullName + '"'), '--walkability-audit', "--workers=$Workers") $Succeeded = $false for ($Attempt = 1; $Attempt -le 2 -and -not $Succeeded; ++$Attempt) { if ($Attempt -eq 2) { Write-Warning "$Stem exited with 0xC0000142; retrying once after 60 seconds." Start-Sleep -Seconds 60 } Remove-Item -LiteralPath $StdoutPath, $StderrPath -Force -ErrorAction SilentlyContinue $Process = Start-Process -FilePath $ExecutablePath -ArgumentList $Arguments ` -WorkingDirectory $StandaloneRoot -WindowStyle Hidden -PassThru ` -RedirectStandardOutput $StdoutPath -RedirectStandardError $StderrPath $StartedUtc = [datetime]::UtcNow $PeakPrivateBytes = [int64]0 try { while (-not $Process.HasExited) { Start-Sleep -Milliseconds 100 $Process.Refresh() if ($Process.HasExited) { break } $Process.PriorityClass = [Diagnostics.ProcessPriorityClass]::Normal $Process.ProcessorAffinity = [IntPtr]0xFFFF $PeakPrivateBytes = [Math]::Max($PeakPrivateBytes, [int64]$Process.PrivateMemorySize64) if (([datetime]::UtcNow - $StartedUtc).TotalSeconds -gt $TimeoutSeconds) { $Process.Kill() $Process.WaitForExit() throw "$Stem exceeded the $TimeoutSeconds-second per-probe time limit." } if ($PeakPrivateBytes -ge 8GB) { $Process.Kill() $Process.WaitForExit() throw "$Stem exceeded the 8 GiB private-memory limit." } } $Process.WaitForExit() $Process.Refresh() $ExitCode = [int]$Process.ExitCode } finally { if (-not $Process.HasExited) { $Process.Kill() $Process.WaitForExit() } } if ($ExitCode -eq -1073741502 -and $Attempt -eq 1) { continue } if ($ExitCode -eq -1073741502) { throw "$Stem repeated 0xC0000142 after its single retry." } $LogText = Get-Content -LiteralPath $StdoutPath -Raw $Walkability = [regex]::Match($LogText, '(?m)^\[Walkability\] PASS (\d+)/(\d+)') if ($LogText -match '(?m)^\[Walkability\] FAIL ' -or -not $Walkability.Success) { throw "$Stem failed the walkability regression gate; see $StdoutPath (exit $ExitCode)." } if ([int64]$Walkability.Groups[1].Value -ne [int64]$Walkability.Groups[2].Value -or [int64]$Walkability.Groups[2].Value -le 0) { throw "$Stem reported an incomplete or empty walkability sample set: $($Walkability.Value)." } if ($ExitCode -ne 0) { throw "$Stem passed route samples but the shape audit exited $ExitCode; see $StdoutPath." } $Succeeded = $true ++$Passed Write-Output "PASS probe=$Stem workers=$Workers samples=$($Walkability.Groups[1].Value)/$($Walkability.Groups[2].Value) peak_private_gb=$([math]::Round($PeakPrivateBytes / 1GB, 2))" } } Write-Output "PASS saved_strate_probes=$Passed/$($Probes.Count) workers=$Workers"