#Requires -Version 7.0 param([Parameter(Mandatory=$true)][ValidateSet('check','list','focused','all','clippy','build')][string]$Stage) Set-StrictMode -Version Latest $ErrorActionPreference='Stop' $taskWorkspace='C:\Users\User\Documents\Git\ARCADIA-Studio\.local\scenario-layout-ytr83r-20260913' $taskTarget='C:\Users\User\Documents\Git\ARCADIA-Studio\target' $taskPin='aed07176ab453b981d5f9c76e504c531f6dd7f42' function Hash-Input([string]$Path){return (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash.ToLowerInvariant()} $taskLog=Join-Path $PSScriptRoot ($Stage+'.log') $taskReceipt=Join-Path $PSScriptRoot ($Stage+'-receipt.json') if((Test-Path -LiteralPath $taskLog)-or(Test-Path -LiteralPath $taskReceipt)){throw 'Do not replace gate evidence; prepare a new directory for retries.'} $clearancePath=Join-Path $PSScriptRoot 'package-clearance.json' $clearance=Get-Content -Raw -LiteralPath $clearancePath | ConvertFrom-Json if($clearance.base -cne $taskPin -or $clearance.cargoExitCode -ne 0 -or [IO.Path]::GetFullPath($clearance.target) -ine $taskTarget -or -not $clearance.dependenciesRetained){throw 'Parent-owned successful package clearance with retained dependencies is required.'} $expectedPath=Join-Path $PSScriptRoot 'expected-tests.json' $selection=Get-Content -Raw -LiteralPath $expectedPath | ConvertFrom-Json $expected=@($selection.tests | Sort-Object -Unique) if($selection.source_commit -cne $taskPin -or $selection.expected_count -ne 11 -or $expected.Count -ne 11){throw 'Wrong exact regression membership.'} $previous=@{list='check';focused='list';all='focused';clippy='all';build='clippy'} if($previous.ContainsKey($Stage)){ $prior=Get-Content -Raw -LiteralPath (Join-Path $PSScriptRoot ($previous[$Stage]+'-receipt.json')) | ConvertFrom-Json if($prior.base -cne $taskPin -or $prior.cargoExitCode -ne 0 -or -not $prior.selectionValid -or -not $prior.inputsUnchanged){throw 'Previous sequential stage did not pass.'} } $boundScripts=@{} foreach($file in @('run.ps1','capture.ps1','expected-tests.json','inputs-complete-before.json','package-clearance.json')){$boundScripts[$file]=Hash-Input (Join-Path $PSScriptRoot $file)} Push-Location -LiteralPath $taskWorkspace try { & (Join-Path $PSScriptRoot 'capture.ps1') -Stage ($Stage+'-before') . 'C:\Users\User\Documents\Git\ARCADIA-Studio\.local\toolchain\env.ps1' $env:CARGO_TARGET_DIR=$taskTarget $env:CARGO_TERM_COLOR='never' $taskArgs=switch($Stage){ 'check' { @('check','-p','oa-desktop','--all-targets','--locked','--offline','--verbose') } 'list' { @('test','-p','oa-desktop','--all-targets','--locked','--offline','--','--list') } 'focused' { @('test','-p','oa-desktop','--bin','arcadia-studio','--locked','--offline','--','--exact')+$expected+@('--test-threads=1') } 'all' { @('test','-p','oa-desktop','--all-targets','--locked','--offline','--','--test-threads=1') } 'clippy' { @('clippy','-p','oa-desktop','--all-targets','--locked','--offline','--','-D','warnings') } 'build' { @('build','-p','oa-desktop','--bin','arcadia-studio','--locked','--offline') } } $taskStart=[DateTime]::UtcNow.ToString('o') & cargo @taskArgs 2>&1 | Tee-Object -FilePath $taskLog $taskExit=$LASTEXITCODE $taskEnd=[DateTime]::UtcNow.ToString('o') $taskText=Get-Content -Raw -LiteralPath $taskLog $taskValid=$true $taskFailure=$null $listed=@();$executed=@();$matched=@();$ignored=@() if($Stage -eq 'list'){ $listed=@([regex]::Matches($taskText,'(?m)^([^\r\n]+): test\r?$') | ForEach-Object { $_.Groups[1].Value }) $matched=@($listed | Where-Object { $_ -cin $expected } | Sort-Object) $taskValid=$listed.Count -gt 11 -and @($listed | Sort-Object -Unique).Count -eq $listed.Count -and $matched.Count -eq 11 -and @((Compare-Object $expected $matched)).Count -eq 0 } if($Stage -in @('focused','all')){ $executed=@([regex]::Matches($taskText,'(?m)^test ([^\r\n]+?) \.\.\. (ok|FAILED|ignored)[^\r\n]*\r?$') | ForEach-Object { [ordered]@{name=$_.Groups[1].Value;result=$_.Groups[2].Value} }) $matched=@($executed | Where-Object { $_.name -cin $expected -and $_.result -eq 'ok' } | ForEach-Object { $_.name } | Sort-Object) $ignored=@($executed | Where-Object { $_.result -eq 'ignored' } | ForEach-Object { $_.name }) $taskValid=$matched.Count -eq 11 -and @((Compare-Object $expected $matched)).Count -eq 0 -and @($executed | Where-Object { $_.result -eq 'FAILED' }).Count -eq 0 if($Stage -eq 'focused'){$taskValid=$taskValid -and $executed.Count -eq 11 -and $ignored.Count -eq 0 -and $taskText -match 'test result: ok\. 11 passed; 0 failed; 0 ignored;'} if($Stage -eq 'all'){ $listReceipt=Get-Content -Raw -LiteralPath (Join-Path $PSScriptRoot 'list-receipt.json') | ConvertFrom-Json $actualNames=@($executed | ForEach-Object { $_.name } | Sort-Object) $listedNames=@($listReceipt.listedTests | Sort-Object) $taskValid=$taskValid -and $actualNames.Count -eq $listedNames.Count -and @((Compare-Object $listedNames $actualNames)).Count -eq 0 } } $inputsUnchanged=$false try{ & (Join-Path $PSScriptRoot 'capture.ps1') -Stage ($Stage+'-after') foreach($file in $boundScripts.Keys){if((Hash-Input (Join-Path $PSScriptRoot $file)) -cne $boundScripts[$file]){throw ('Gate script/input changed: '+$file)}} $inputsUnchanged=$true }catch{$taskFailure=$_.Exception.Message} $binary=$null if($Stage -eq 'build' -and $taskExit -eq 0){$path=Join-Path $taskTarget 'debug/arcadia-studio.exe';$item=Get-Item -LiteralPath $path;$binary=[ordered]@{path=$item.FullName;bytes=$item.Length;sha256=(Hash-Input $path);mtimeUtc=$item.LastWriteTimeUtc.ToString('o')}} [ordered]@{command=('cargo '+($taskArgs -join ' '));arguments=$taskArgs;base=$taskPin;workspace=$taskWorkspace;target=$taskTarget;startUtc=$taskStart;endUtc=$taskEnd;cargoExitCode=$taskExit;selectionValid=$taskValid;inputsUnchanged=$inputsUnchanged;postflightFailure=$taskFailure;boundScriptAndInputHashes=$boundScripts;listedTests=$listed;executedTests=$executed;matchedRegressionTests=$matched;ignoredTests=$ignored;binary=$binary}|ConvertTo-Json -Depth 12|Set-Content -LiteralPath $taskReceipt -Encoding utf8 if($taskExit -ne 0){exit $taskExit} if(-not $taskValid -or -not $inputsUnchanged){throw 'Gate membership or input binding failed; inspect receipt and raw output.'} }finally{Pop-Location}