1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
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 {
& $Action *>&1 | Tee-Object -FilePath $path -Append
if ($LASTEXITCODE) { $exitCode = $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\agent-sandbox-mcp-1.0.0-win-x64'
$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
|