Files
VoxelForge/Standalone/Core/verification/RunPassageWalkabilityAudit.ps1
T
Fr0zkaandClaude Opus 5.5 874c796c65 wip(assembler): M1 round 1 -- manifest format, block contract, bound audit, native Heightfield2D
Luna, M1 round 1 of 4 (plan in Standalone/ASSEMBLER_M1_REPORT.md):
- Versioned fixed-scale world manifest (the shipped plan format) and the Core block
  contract: point evaluation, interval-or-unknown, influence bound, detail envelope, channels.
- Interval audit: 256 boxes / 6,912 samples, 0 missed, 0 unknown; a deliberately false bound
  is detected (negative control).
- Native Heightfield2D with biome input: 4,096-point hash fae2721c052aec5c identical at
  W1/W8/W16; point queries 2.059 ms vs 62.115 ms legacy -- but NOT a match yet (mean density
  error 274 voxels, 2,261 sign mismatches vs the legacy surface). 45 mesh-free Core queries
  match direct evaluation exactly. Existing cave world unchanged (walkability, 64/64 tiles).
- Open: collision readiness, a valid full-view timing (viewer captures were occluded/empty;
  top-down height maps are the only usable pair).
Also carries the design doc's owner decisions (fixed water; player edits unrestricted, route
law for automatic changes only) and three plugin files + BuildHost scripts that earlier round
commits had missed (also fixed on unreal/core-integration as 2574b56).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
2026-10-09 00:04:30 +02:00

113 lines
5.2 KiB
PowerShell

[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"