param( [string]$EvidenceRoot = 'artifacts\evidence\final-elevated', [string]$TestRoot = 'C:\tmp', [string]$VenvPython = 'C:\tmp\.venv\Scripts\python.exe', [switch]$WindowsSecurityChild ) $ErrorActionPreference = 'Continue' $OutputEncoding = [Text.UTF8Encoding]::new($false) [Console]::OutputEncoding = $OutputEncoding $repository = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path $evidence = [IO.Path]::GetFullPath((Join-Path $repository $EvidenceRoot)) if (-not $evidence.StartsWith($repository + [IO.Path]::DirectorySeparatorChar, [StringComparison]::OrdinalIgnoreCase)) { throw 'Evidence output must remain inside the repository.' } New-Item -ItemType Directory -Force -Path $evidence | Out-Null $failed = $false $metadata = Join-Path $evidence 'metadata.txt' $administrator = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator) @( "timestamp=$(Get-Date -Format o)" "commit=$(git -C $repository rev-parse HEAD)" "administrator=$administrator" "working_tree_clean=$(-not [bool](git -C $repository status --porcelain))" "os=$([Environment]::OSVersion.VersionString)" "dotnet=$(& dotnet --version)" ) | Set-Content -LiteralPath $metadata -Encoding utf8NoBOM function Invoke-VerificationStep { param([string]$Name, [scriptblock]$Action) $path = Join-Path $evidence "$Name.log" "START $Name $(Get-Date -Format o)" | Tee-Object -FilePath $path $exitCode = 0 try { $global:LASTEXITCODE = 0 & $Action *>&1 | Tee-Object -FilePath $path -Append if ($global:LASTEXITCODE) { $exitCode = $global:LASTEXITCODE } } catch { $_ | Out-String | Tee-Object -FilePath $path -Append $exitCode = 1 } "END $Name exit=$exitCode $(Get-Date -Format o)" | Tee-Object -FilePath $path -Append if ($exitCode -ne 0) { $script:failed = $true } } $bundle = Join-Path $repository 'build\Release\publish\winagent-sandbox-mcp' $windowsTests = Join-Path $repository 'build\Release\Agent.Windows.Tests\net10.0-windows10.0.26100.0\Agent.Windows.Tests.exe' $coreTests = Join-Path $repository 'build\Release\Agent.Core.Tests\net10.0-windows10.0.26100.0\Agent.Core.Tests.exe' $plannerTests = Join-Path $repository 'build\Release\Agent.Planner.Tests\net10.0\Agent.Planner.Tests.exe' if ($WindowsSecurityChild) { if (-not $administrator) { Write-Error 'Windows Security child did not receive an administrator token.'; exit 2 } $env:AGENT_MCP_MONKEY_ROOT = (Resolve-Path -LiteralPath $TestRoot).Path $env:AGENT_MCP_TEST_VENV_PYTHON = (Resolve-Path -LiteralPath $VenvPython).Path $env:AGENT_MCP_TEST_POWERSHELL = (Get-Command pwsh.exe -ErrorAction Stop).Source $env:AGENT_MCP_TEST_POWERSHELL_RUNTIME = Split-Path $env:AGENT_MCP_TEST_POWERSHELL $env:AGENT_MCP_TEST_CMD = $env:ComSpec $childLog = Join-Path $evidence 'windows-security-tests-elevated.log' # The suite intentionally shares one fixed Application Profile and global loopback state. # Serialize it so crash/recovery cases cannot race another WFP/loopback case. & $windowsTests -parallel none -failSkips *>&1 | Tee-Object -FilePath $childLog exit $LASTEXITCODE } if ($administrator) { throw 'Run the final verification orchestrator with a standard-user token. It elevates only the Windows Security test child.' } Invoke-VerificationStep 'bundle-show' { & (Join-Path $bundle 'agent-mcp.exe') show (Join-Path $bundle 'agent.yaml') } Invoke-VerificationStep 'windows-security-tests' { $pwsh = (Get-Command pwsh.exe -ErrorAction Stop).Source $child = Start-Process -FilePath $pwsh -Verb RunAs -WindowStyle Hidden -PassThru -Wait -ArgumentList @( '-NoProfile', '-File', $PSCommandPath, '-EvidenceRoot', $EvidenceRoot, '-TestRoot', $TestRoot, '-VenvPython', $VenvPython, '-WindowsSecurityChild') if ($child.ExitCode -ne 0) { throw "Elevated Windows Security test child failed with exit code $($child.ExitCode)." } } Invoke-VerificationStep 'core-unit-integration-tests' { & $coreTests } Invoke-VerificationStep 'planner-unit-tests' { & $plannerTests } Invoke-VerificationStep 'e2e-01-stdio' { & (Join-Path $PSScriptRoot 'Operational-E2E.ps1') -Transport stdio } Invoke-VerificationStep 'e2e-02-http-ipv4' { & (Join-Path $PSScriptRoot 'Operational-E2E.ps1') -Transport http -HttpHost 127.0.0.1 } Invoke-VerificationStep 'e2e-02-http-ipv6' { & (Join-Path $PSScriptRoot 'Operational-E2E.ps1') -Transport http -HttpHost ::1 } Invoke-VerificationStep 'residual-state' { $journalCount = @(Get-ChildItem -LiteralPath (Join-Path $bundle 'state\journals') -File -ErrorAction SilentlyContinue).Count $backupCount = @(Get-ChildItem -LiteralPath (Join-Path $bundle 'state\backups') -File -Recurse -ErrorAction SilentlyContinue).Count $bundleAgent = Join-Path $bundle 'agent-mcp.exe' $processCount = @(Get-Process -Name agent-mcp -ErrorAction SilentlyContinue | Where-Object { try { $_.Path -eq $bundleAgent } catch { $false } }).Count "journal_count=$journalCount backup_count=$backupCount published_process_count=$processCount" if ($journalCount -ne 0 -or $backupCount -ne 0 -or $processCount -ne 0) { throw 'Task Resource residue was detected.' } } if ($failed) { Write-Error "Final elevated verification FAILED. Evidence: $evidence" exit 1 } Write-Output "Final elevated verification PASS. Evidence: $evidence" exit 0