<# .SYNOPSIS Campaign V repeat-run connected gate: N full connect-render-screenshot cycles against the local ACE server, with a pass/fail verdict per run. .DESCRIPTION The V4c blank-world regression was INTERMITTENT: roughly 1 launch in 3 at the worst location, 0 in 7 at the parent commit. A single connected capture is therefore worthless as a gate for this defect class - the broken binary passes it most of the time. This script exists so no future slice can call itself connected-clean on one lucky run. Each run: launch connected -> teleloc to the pinned worst-case cell -> wait for world-visible -> settle -> screenshot -> graceful close -> cooldown. The verdict is by screenshot content size: a rendered 1280x720 world compresses to ~1.5 MB; the blank-world failure produces a few-KB flat PNG. The teleloc is pinned because the failure rate is location-sensitive, and stray input into a minimized window silently moves the character between runs. Graceful close matters: a hard kill leaves ACE holding the session ~3 minutes and every subsequent run fails with 'CharacterList not received'. .PARAMETER Runs Cycles to run. Default 10. The defect's observed rate was ~1/3, so ten clean runs bound it below ~4% at 90% confidence - adequate for a re-land gate. .PARAMETER ExePath Client executable. Defaults to this repo's Release output. .PARAMETER Teleloc The pinned location, as the full /teleloc argument string. Default is the cell with the worst observed failure rate (5/5 blank at the V4c HEAD). .PARAMETER MinRenderedBytes Screenshot size below which a run is called blank. Default 500000. #> [CmdletBinding()] param( [int]$Runs = 10, [string]$ExePath, [string]$Teleloc = "0x2E430012 57.895 42.116 16.802 1 0 0 0", [int]$MinRenderedBytes = 500000 ) $ErrorActionPreference = 'Stop' $repo = Split-Path -Parent $PSScriptRoot if (-not $ExePath) { $ExePath = Join-Path $repo 'src\AcDream.App\bin\Release\net10.0\AcDream.App.exe' } if (-not (Test-Path $ExePath)) { throw "Client not found at $ExePath." } # Never race a session someone is already playing: same account, same server. if (Get-Process -Name AcDream.App -ErrorAction SilentlyContinue) { throw 'AcDream.App is already running. This gate uses the shared test account and must not steal its session.' } $root = Join-Path $env:TEMP "claude\repeat-connected-$([DateTime]::Now.ToString('HHmmss'))" New-Item -ItemType Directory -Force -Path $root | Out-Null $results = @() for ($i = 1; $i -le $Runs; $i++) { $dir = Join-Path $root "run-$i" New-Item -ItemType Directory -Force -Path $dir | Out-Null Set-Content -Encoding utf8 (Join-Path $dir 'probe.txt') -Value @" wait world-ready 90000 command /teleloc $Teleloc wait materialized 1 90000 wait world-visible 30000 sleep 15000 screenshot repeat-run 30000 sleep 1000 "@ $env:ACDREAM_DAT_DIR = Join-Path $env:USERPROFILE "Documents\Asheron's Call" $env:ACDREAM_LIVE = '1' $env:ACDREAM_TEST_HOST = '127.0.0.1' $env:ACDREAM_TEST_PORT = '9000' $env:ACDREAM_TEST_USER = 'testaccount' $env:ACDREAM_TEST_PASS = 'testpassword' $env:ACDREAM_RETAIL_UI = '1' $env:ACDREAM_UI_PROBE_SCRIPT = Join-Path $dir 'probe.txt' $env:ACDREAM_AUTOMATION_ARTIFACT_DIR = $dir $log = Join-Path $dir 'client.log' $proc = Start-Process -FilePath $ExePath -RedirectStandardOutput $log ` -RedirectStandardError "$log.err" -PassThru -WindowStyle Minimized $shot = Join-Path $dir 'screenshots\repeat-run.png' $deadline = (Get-Date).AddSeconds(180) while ((Get-Date) -lt $deadline) { if (Test-Path $shot) { Start-Sleep -Seconds 2; break } if ($proc.HasExited) { break } Start-Sleep -Seconds 2 } $app = Get-Process -Name AcDream.App -ErrorAction SilentlyContinue if ($app) { $app.CloseMainWindow() | Out-Null if (-not $app.WaitForExit(12000)) { $app | Stop-Process -Force } } $size = if (Test-Path $shot) { (Get-Item $shot).Length } else { 0 } $verdict = if ($size -ge $MinRenderedBytes) { 'RENDERED' } elseif ($size -gt 0) { 'BLANK' } else { 'NO-CAPTURE' } $results += [pscustomobject]@{ Run = $i; Verdict = $verdict; Bytes = $size } Write-Host ("[repeat-gate] run {0}/{1}: {2} ({3} bytes)" -f $i, $Runs, $verdict, $size) Start-Sleep -Seconds 10 # let ACE clear the graceful logout before the next login } Write-Host '' $blank = @($results | Where-Object Verdict -ne 'RENDERED') $results | Format-Table -AutoSize | Out-String | Write-Host if ($blank.Count -gt 0) { Write-Host ("[repeat-gate] FAILED: {0}/{1} runs did not render. Artifacts: {2}" -f $blank.Count, $Runs, $root) -ForegroundColor Red exit 1 } Write-Host ("[repeat-gate] PASS: {0}/{0} runs rendered. Artifacts: {1}" -f $Runs, $root) exit 0