fix(correctness): false AllAir certificates and a stale shaft cache key; 44/44 tests green
The harness's first full suite run showed 16 of 44 tests failing. Two were real defects in the owner's world: 1. ParameterRoll: the tile classifier could certify a box AllAir while the final field is solid there (3 false proofs found, e.g. density -2.092319 at (-192,16,-224)). Cause: the box diagnostic narrowed 'tail reach' to 'air reach', so the swept tunnel FLOOR -- which writes solid -- did not count as reaching the box. A false AllAir skips meshing, i.e. missing floor in game. The classifier now uses the same reach predicate as the final writer (swept chain, floor band, relief, room-mouth envelope) and propagates it through Mixed refinement nodes. Re-run: 1,288,143 lattice samples, 0 violations. 2. VerticalShaftEquivalence: LedgeSpacing and LedgeDepth were missing from the production TLS cache key, so a shaft could reuse stale ledge parameters. Both are now in the key. The other 14: broken fixtures (missing staged corpus assets, a sampler leaking the shaft TLS marker between queries, stale candidate IDs, a window entirely inside the common tail) or stale expectations after this week's owner decisions (no authored tunnel floor, slope in degrees, rooms owning their interior). No test was deleted or weakened into vacuity; retired legacy comparisons stay as telemetry and the current stack is asserted instead. PassageLandsInOpenSpace now requires a real player-capsule fit in the final density at each authored landing (14/14, worst gradient 0.115723). Suite: 42 tests green in one run, the two long op-stack sweeps green in serialized filtered runs (the 1800 s launch guard); a harness timeout-recording bug was fixed. Bounded probe exports unchanged (canonical 94B47A1C, owner 44E7C813). ⚠️ Harness perf scenario moved 50.74 s -> 53.58 s worker (+5.6%): the wider reach predicate skips fewer boxes. Measure on the game path and decide before merging. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MmSoF64BbRFmk9C3p1VsBJ
This commit is contained in:
1 parent
cc04c0bd4e
commit
7af8d0e870
18 files changed
+772
-465
No files matched your search
@@ -6,6 +6,7 @@ param(
|
||||
[ValidateSet('owner', 'default')]
|
||||
[string]$Assets = 'owner',
|
||||
[hashtable]$Cvars = @{},
|
||||
[string]$TestFilter,
|
||||
[string]$Out,
|
||||
[string]$Label
|
||||
)
|
||||
@@ -27,6 +28,9 @@ $EngineRoot = 'E:\Program Files\Epic Games\UE_5.7'
|
||||
$EditorExe = Join-Path $EngineRoot 'Engine\Binaries\Win64\UnrealEditor-Cmd.exe'
|
||||
$UbtDll = Join-Path $EngineRoot 'Engine\Binaries\DotNET\UnrealBuildTool\UnrealBuildTool.dll'
|
||||
$LaunchTimeoutSeconds = 1800
|
||||
# The VoxelForge category includes two late, several-minute op-stack sweeps. They remain in
|
||||
# the suite; when the serialized aggregate launch reaches this 30-minute guard, validate those
|
||||
# named tests with -TestFilter so every test still runs under the standing launch limit.
|
||||
# Fresh branch-tip baseline at 1c642fd1824a7e0e4f88a8fc1f42b9e23fdb1821 after a clean staged
|
||||
# sync (synthetic canonical, walk+export+probe). This is intentionally asserted so any
|
||||
# field-affecting edit makes canonical fail loudly.
|
||||
@@ -252,13 +256,13 @@ function Get-NewCrashes($Before, [datetime]$StartedUtc) {
|
||||
function Wait-OwnedProcess($Process, [int]$TimeoutSeconds) {
|
||||
$finished = $Process.WaitForExit($TimeoutSeconds * 1000)
|
||||
if ($finished) {
|
||||
$Process.WaitForExit()
|
||||
[void]$Process.WaitForExit()
|
||||
return [ordered]@{ timed_out = $false; exit_code = [int]$Process.ExitCode }
|
||||
}
|
||||
# This PID came from our Start-Process call. Never use a name-based kill or a broad process
|
||||
# query here: an owner's editor may be unrelated and must remain untouched.
|
||||
try { Stop-Process -Id ([int]$Process.Id) -Force -ErrorAction Stop } catch { }
|
||||
try { $Process.WaitForExit(5000) } catch { }
|
||||
try { [void]$Process.WaitForExit(5000) } catch { }
|
||||
return [ordered]@{ timed_out = $true; exit_code = $null }
|
||||
}
|
||||
|
||||
@@ -392,7 +396,10 @@ function Sync-StagedHost {
|
||||
|
||||
function Sync-OwnerAssets {
|
||||
$rows = [System.Collections.Generic.List[object]]::new()
|
||||
foreach ($assetName in @('DA_Strate3', 'DA_Settings')) {
|
||||
# Composer tests discover the authored strate corpus from the staged asset registry. Keep the
|
||||
# complete owner corpus here; the explore commandlet still selects DA_Strate3 explicitly for
|
||||
# the owner-world scenario below.
|
||||
foreach ($assetName in @('DA_Strate1', 'DA_Strate2', 'DA_Strate3', 'DA_Strate4', 'DA_Settings')) {
|
||||
$source = Join-Path $ProjectRoot "Content\VoxelForge\$assetName.uasset"
|
||||
$target = Join-Path $HostRoot "Content\VoxelForge\$assetName.uasset"
|
||||
if (-not (Test-Path -LiteralPath $source -PathType Leaf)) {
|
||||
@@ -412,9 +419,40 @@ function Sync-OwnerAssets {
|
||||
return @($rows)
|
||||
}
|
||||
|
||||
function Sync-TestCharacterFixture {
|
||||
$rows = [System.Collections.Generic.List[object]]::new()
|
||||
|
||||
# ScaleDiagnosis reads the owner's character CDO for movement limits. The isolated host
|
||||
# already contains the CDO, but the CDO's animation blueprint loads the complete unarmed
|
||||
# blend-space sample set. Keep that dependency closure in the harness instead of turning a
|
||||
# missing staged asset into an automation-test error. These are copies into the host only.
|
||||
$relativeDirectories = @('Characters\Mannequins\Anims\Unarmed')
|
||||
foreach ($relativeDirectory in $relativeDirectories) {
|
||||
$sourceDirectory = Join-Path $ProjectRoot "Content\$relativeDirectory"
|
||||
$targetDirectory = Join-Path $HostRoot "Content\$relativeDirectory"
|
||||
if (-not (Test-Path -LiteralPath $sourceDirectory -PathType Container)) {
|
||||
throw "Test fixture directory is missing: $sourceDirectory"
|
||||
}
|
||||
Copy-DirectoryContents $sourceDirectory $targetDirectory
|
||||
foreach ($source in @(Get-ChildItem -LiteralPath $sourceDirectory -Recurse -File)) {
|
||||
$relativeFile = $source.FullName.Substring($sourceDirectory.Length).TrimStart('\')
|
||||
$target = Join-Path $targetDirectory $relativeFile
|
||||
[void]$rows.Add([ordered]@{
|
||||
name = "TestFixture/$relativeDirectory/$relativeFile"
|
||||
used_by_scenario = $true
|
||||
source_path = $source.FullName
|
||||
source_sha256 = Get-Sha256 $source.FullName
|
||||
staged_path = $target
|
||||
staged_sha256 = Get-Sha256 $target
|
||||
})
|
||||
}
|
||||
}
|
||||
return @($rows)
|
||||
}
|
||||
|
||||
function Get-AssetEvidence {
|
||||
$rows = [System.Collections.Generic.List[object]]::new()
|
||||
foreach ($assetName in @('DA_Strate3', 'DA_Settings')) {
|
||||
foreach ($assetName in @('DA_Strate1', 'DA_Strate2', 'DA_Strate3', 'DA_Strate4', 'DA_Settings')) {
|
||||
$source = Join-Path $ProjectRoot "Content\VoxelForge\$assetName.uasset"
|
||||
$target = Join-Path $HostRoot "Content\VoxelForge\$assetName.uasset"
|
||||
[void]$rows.Add([ordered]@{
|
||||
@@ -807,6 +845,9 @@ try {
|
||||
} else {
|
||||
$AssetEvidence = @(Get-AssetEvidence)
|
||||
}
|
||||
if ($Scenario -eq 'tests') {
|
||||
$AssetEvidence += @(Sync-TestCharacterFixture)
|
||||
}
|
||||
$DllEvidence.runtime = [ordered]@{
|
||||
path = Join-Path $StagePlugin 'Binaries\Win64\UnrealEditor-VoxelForge.dll'
|
||||
sha256 = Get-Sha256 (Join-Path $StagePlugin 'Binaries\Win64\UnrealEditor-VoxelForge.dll')
|
||||
@@ -864,13 +905,14 @@ try {
|
||||
$GameMetrics = Get-StreamingMetrics (Join-Path $RunRoot 'Logs\perf.log')
|
||||
}
|
||||
'tests' {
|
||||
$baseCvars['ExecCmds'] = 'Automation RunTests VoxelForge; Quit'
|
||||
$testPath = if ([string]::IsNullOrWhiteSpace($TestFilter)) { 'VoxelForge' } else { $TestFilter }
|
||||
$baseCvars['ExecCmds'] = "Automation RunTests $testPath; Quit"
|
||||
$baseCvars['ReportExportPath'] = (Join-Path $RunRoot 'AutomationReport')
|
||||
$args = New-CommonArguments 'tests' (Join-Path $RunRoot 'Logs\tests.log') (Merge-Cvars $baseCvars)
|
||||
# ExecCmds is a command-line value, not a cvar; replace the generated -ExecCmds token
|
||||
# with the quoted form accepted by Unreal's parser.
|
||||
$args = @($args | Where-Object { $_ -notlike '-ExecCmds=*' -and $_ -notlike '-ReportExportPath=*' })
|
||||
$args += '-ExecCmds="Automation RunTests VoxelForge; Quit"'
|
||||
$args += ('-ExecCmds="Automation RunTests {0}; Quit"' -f $testPath)
|
||||
$args += ('-ReportExportPath="{0}"' -f (Join-Path $RunRoot 'AutomationReport'))
|
||||
$gameLedger = Invoke-UnrealLaunch 'automation-tests' $args `
|
||||
(Join-Path $RunRoot 'Logs\tests.log') (Join-Path $RunRoot 'Logs\tests.stdout.log') (Join-Path $RunRoot 'Logs\tests.stderr.log')
|
||||
|
||||
Reference in new issue
Block a user