Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
af8b36c
test: add Windows installed gateway smoke
bkudiess Jul 24, 2026
8734197
test: add Windows Inno upgrade smoke
bkudiess Jul 24, 2026
32ff92f
feat: add Windows desktop proof automation
bkudiess Jul 24, 2026
782e1ce
fix: reject blank desktop proof captures
bkudiess Jul 24, 2026
8e522ea
feat: add compositor window proof capture
bkudiess Jul 24, 2026
075db83
fix: require desktop-capable proof runner
bkudiess Jul 24, 2026
5bad509
test: add Windows live parity lanes
bkudiess Jul 24, 2026
20175ae
test: add clean Windows runner infrastructure
bkudiess Jul 24, 2026
7f28e03
test: tighten clean Windows proof contracts
bkudiess Jul 24, 2026
7884660
test: add clean upgrade validation lanes
bkudiess Jul 24, 2026
cc53c4b
fix: close integration proof gaps
bkudiess Jul 24, 2026
9c369c9
fix: enforce network recovery shard proofs
bkudiess Jul 24, 2026
7d906ba
fix: align Windows testing skill guidance
bkudiess Jul 24, 2026
1d6f125
Add unattended Hyper-V Windows setup
bkudiess Jul 24, 2026
9421dc2
Fix elevated unattended ACL ownership
bkudiess Jul 24, 2026
12bed9f
Fix Hyper-V Windows secure boot template
bkudiess Jul 24, 2026
a6aefee
Fix Hyper-V key protector ordering
bkudiess Jul 27, 2026
9bc10d3
Validate Hyper-V key protector blobs
bkudiess Jul 27, 2026
ffbe82a
Harden Hyper-V media detach recovery
bkudiess Jul 27, 2026
563adf7
Make Hyper-V checkpoints transactional
bkudiess Jul 27, 2026
a8df432
Validate checkpoint VHD ancestry
bkudiess Jul 27, 2026
ede3e72
Stage clean guest WSL preparation
bkudiess Jul 27, 2026
91c43a9
Handle WSL package update bootstrap
bkudiess Jul 28, 2026
8dcfda8
Probe WSL package status before version
bkudiess Jul 28, 2026
3960b58
Bootstrap pinned WinGet for clean guests
bkudiess Jul 28, 2026
7993d5e
Pin WinGet installs to community source
bkudiess Jul 28, 2026
8fc8335
Hydrate pinned WinGet source before probe
bkudiess Jul 28, 2026
a60107b
Bootstrap signed WinGet source catalog
bkudiess Jul 28, 2026
506467c
Pin clean runner PowerShell to Wix
bkudiess Jul 28, 2026
00adeac
Transfer clean runner source from committed archive
bkudiess Jul 28, 2026
c2653f5
Harden clean guest Git staging
bkudiess Jul 29, 2026
bd4d869
Stage clean guest prerequisites
bkudiess Jul 29, 2026
7756b0c
Fix PS5 prerequisite worker invocation
bkudiess Jul 29, 2026
3353d40
Make clean guest package scope explicit
bkudiess Jul 29, 2026
6db4cc1
Recover verified package session transitions
bkudiess Jul 29, 2026
9aa5aa1
Harden clean guest Verify tool checks
bkudiess Jul 29, 2026
bc8ab38
Harden clean smoke artifact retrieval
bkudiess Jul 30, 2026
41bd6ff
Recover smoke artifact packaging sessions
bkudiess Jul 30, 2026
2770fef
Harden clean guest version builds
bkudiess Jul 30, 2026
d980f93
Isolate smoke artifacts per run
bkudiess Jul 30, 2026
cea6610
Stage minimal Visual Studio Build Tools
bkudiess Jul 30, 2026
aed1230
Install Visual Studio VC toolset files
bkudiess Aug 2, 2026
eea20d5
Recover Hyper-V smoke after session loss
bkudiess Aug 2, 2026
ce99d28
Harden clean Windows installed smoke
bkudiess Aug 3, 2026
e79fe98
Fix typed Inno smoke arguments
bkudiess Aug 3, 2026
7dc12e9
Harden cold gateway configuration timeout
bkudiess Aug 4, 2026
9cffe94
Recover repeated smoke session loss
bkudiess Aug 4, 2026
bb7cd06
Recover owned gateway start timeout
bkudiess Aug 4, 2026
d3eaffc
Harden cold setup CLI timeouts
bkudiess Aug 4, 2026
763001c
Accept structured approval selection
bkudiess Aug 4, 2026
2d61426
Harden gateway wizard restart recovery
bkudiess Aug 6, 2026
73aa4d2
Keep smoke validation profile loaded
bkudiess Aug 6, 2026
48c523a
Inline clean smoke argument quoting
bkudiess Aug 6, 2026
0608c5e
Normalize generated Git metadata ownership
bkudiess Aug 6, 2026
1c7de9d
Recover gateway service after wizard restart
bkudiess Aug 6, 2026
f11c047
Harden fresh WSL first launch readiness
bkudiess Aug 6, 2026
ff81c90
Remove secret-shaped readiness fixture
bkudiess Aug 6, 2026
86c9290
Retry timed-out WSL probes with partial output
bkudiess Aug 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
689 changes: 689 additions & 0 deletions .agents/skills/openclaw-hyperv-smoke/SKILL.md

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion .agents/skills/openclaw-proof-validation/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ description: "Plan and collect OpenClaw Windows validation/proof: tests, rubber-

Use for changes that affect tray UX, Settings, onboarding, chat/canvas, Command Center, Windows node capabilities, local MCP, gateway connection/pairing, permissions, diagnostics, or agent-facing instructions.

For choosing which validation lane (unit, UI, accessibility, local MCP, gateway, installed Inno, live, performance, clean-runner) applies to a change, see `.agents/skills/windows-node-testing/SKILL.md`.

If the validation host is macOS, read [PARALLELS.md](PARALLELS.md) for the optional local Parallels Windows VM workflow.

## Rules
Expand Down Expand Up @@ -39,7 +41,7 @@ dotnet test .\tests\OpenClaw.WinNode.Cli.Tests\OpenClaw.WinNode.Cli.Tests.csproj

| Surface | Proof to collect |
|---|---|
| UI / WinUI | Launch `.\run-app-local.ps1 -Isolated`, exercise the changed path with computer-use or developer-provided screenshots/output, and include visible evidence or blocker. If the developer captures manually, provide exact steps and confirm screenshot/artifact links resolve after updating the PR body. |
| UI / WinUI | Launch `.\run-app-local.ps1 -Isolated`, exercise the changed path with computer-use or developer-provided screenshots/output, and include visible evidence or blocker. If the developer captures manually, provide exact steps and confirm screenshot/artifact links resolve after updating the PR body. For a repeatable, scripted screenshot/manifest capture instead of manual computer-use, see `.agents/skills/windows-computer-use-proof/SKILL.md`. |
| Local MCP | Enable **Local MCP Server**, run `winnode --list-tools`, then invoke the changed command with `winnode --command <name> --params '<json-object>'`. |
| Raw MCP HTTP | For protocol/server-shape changes, paste JSON-RPC `tools/list` and `tools/call` responses from `http://127.0.0.1:8765/`. |
| Gateway path | When relevant and available, prove `openclaw nodes invoke --command <name> --params '<json-object>'`; otherwise state the gateway blocker. |
Expand Down
299 changes: 299 additions & 0 deletions .agents/skills/windows-computer-use-proof/SKILL.md

Large diffs are not rendered by default.

529 changes: 529 additions & 0 deletions .agents/skills/windows-node-testing/SKILL.md

Large diffs are not rendered by default.

42 changes: 40 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -348,13 +348,20 @@ jobs:
include:
- name: setup-connect
timeout_minutes: 45
filter: "FullyQualifiedName~OpenClaw.E2ETests.Setup.SetupAndConnectTests|FullyQualifiedName~OpenClaw.E2ETests.Setup.MxcSetupAndConnectTests"
filter: "FullyQualifiedName~OpenClaw.E2ETests.Setup.SetupAndConnectTests|FullyQualifiedName~OpenClaw.E2ETests.Setup.MxcSetupAndConnectTests|FullyQualifiedName~OpenClaw.E2ETests.Setup.PublishedGatewayNativeChatTests"
- name: revocation-recovery
timeout_minutes: 25
filter: FullyQualifiedName~OpenClaw.E2ETests.Setup.RevocationAndRecoveryTests
- name: network-recovery
timeout_minutes: 25
filter: FullyQualifiedName~OpenClaw.E2ETests.Setup.NetworkRecoveryTests
# Live parity contract/unit tests are secretless and fixtureless
# (no WSL gateway, no live model/Discord fixture) so they are
# safe to piggyback on this shard. Only the *ContractTests
# classes are listed here by exact class name: the live proof
# classes (LiveModelE2ETests, RealChannelE2ETests) are
# deliberately NOT included in any normal CI filter, since they
# require real secrets/profiles that normal CI never provides.
filter: "FullyQualifiedName~OpenClaw.E2ETests.Setup.NetworkRecoveryTests|FullyQualifiedName~OpenClaw.E2ETests.LiveParity.LiveParityGateContractTests|FullyQualifiedName~OpenClaw.E2ETests.LiveParity.LiveParityProfileContractTests|FullyQualifiedName~OpenClaw.E2ETests.LiveParity.LiveParitySupportContractTests"
steps:
- name: Fail if repo hygiene failed
if: ${{ needs.repo-hygiene.result != 'success' }}
Expand Down Expand Up @@ -417,7 +424,38 @@ jobs:
Write-Error "E2E shard '${{ matrix.name }}' executed zero tests. Check OPENCLAW_RUN_E2E gating/filter before merging."
exit 1
}
if ("${{ matrix.name }}" -eq "network-recovery") {
$networkRecoveryProofNames = @(
"GatewayStopAndStart_TrayLeavesReadyThenRecovers",
"RepeatedGatewayRestart_TrayAndNodeRecoverEachTime"
)

foreach ($networkRecoveryProofName in $networkRecoveryProofNames) {
$networkRecoveryProof = @($trx.TestRun.Results.UnitTestResult | Where-Object { $_.testName -like "*$networkRecoveryProofName*" }) | Select-Object -First 1
if ($null -eq $networkRecoveryProof) {
Write-Error "E2E shard '${{ matrix.name }}' did not report the network recovery proof '$networkRecoveryProofName'. Check the network-recovery filter before merging."
exit 1
}
if ([string]$networkRecoveryProof.outcome -ne "Passed") {
Write-Error "Network recovery proof '$networkRecoveryProofName' must pass and cannot be skipped. Outcome: '$($networkRecoveryProof.outcome)'."
exit 1
}
Write-Host "Network recovery E2E proof passed: $networkRecoveryProofName"
}
}
if ("${{ matrix.name }}" -eq "setup-connect") {
$publishedGatewayProofName = "RealPublishedGateway_DeviceInfo_AndNativeChat_Roundtrip"
$publishedGatewayProof = @($trx.TestRun.Results.UnitTestResult | Where-Object { $_.testName -like "*$publishedGatewayProofName*" }) | Select-Object -First 1
if ($null -eq $publishedGatewayProof) {
Write-Error "E2E shard '${{ matrix.name }}' did not report the published gateway proof '$publishedGatewayProofName'. Check the setup-connect filter before merging."
exit 1
}
if ([string]$publishedGatewayProof.outcome -ne "Passed") {
Write-Error "Published gateway proof '$publishedGatewayProofName' must pass and cannot be skipped. Outcome: '$($publishedGatewayProof.outcome)'."
exit 1
}
Write-Host "Published gateway E2E proof passed: $publishedGatewayProofName"

$mxcProofNames = @(
"RealGateway_SystemRun_ExecutesThroughWindowsNodeMxcSandbox",
"RealGateway_SystemRun_BlocksWritesToTrayDataDirectoryInMxcSandbox"
Expand Down
91 changes: 91 additions & 0 deletions .github/workflows/windows-desktop-proof.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: Windows Desktop Proof (manual)

# Manual-only proof lane. This workflow never runs on push or pull_request,
# so it cannot affect required PR/merge CI. It targets a fixed self-hosted
# label reserved for an unlocked, interactive Windows desktop. Generic hosted
# runners do not guarantee compositor-backed app-window capture.
on:
workflow_dispatch:
inputs:
configuration:
description: 'Build configuration'
required: false
default: 'Debug'
type: choice
options:
- Debug
- Release

permissions:
contents: read

jobs:
desktop-proof:
runs-on: [self-hosted, windows, openclaw-desktop-proof]
steps:
- name: Verify active interactive desktop
shell: pwsh
run: |
$sessionId = [Diagnostics.Process]::GetCurrentProcess().SessionId
if ($sessionId -eq 0 -or -not [Environment]::UserInteractive) {
throw "Desktop proof requires an interactive non-Session-0 runner process."
}

$session = & "$env:SystemRoot\System32\qwinsta.exe" $sessionId 2>&1 | Out-String
if ($LASTEXITCODE -ne 0 -or $session -notmatch '(?im)\bActive\b') {
throw "Desktop proof requires an active, connected desktop session. qwinsta output: $session"
}

- uses: actions/checkout@v7

- name: Setup .NET 10
uses: actions/setup-dotnet@v6
with:
dotnet-version: 10.0.x

- name: Install WindowsAppRuntime
shell: pwsh
run: |
[xml]$props = Get-Content (Join-Path $env:GITHUB_WORKSPACE "Directory.Build.props")
$versionNode = $props.SelectSingleNode("/Project/PropertyGroup/MicrosoftWindowsAppSDKVersion")
if ($null -eq $versionNode -or [string]::IsNullOrWhiteSpace($versionNode.InnerText)) {
throw "MicrosoftWindowsAppSDKVersion was not found in Directory.Build.props"
}

$version = $versionNode.InnerText.Trim()
$channel = [regex]::Match($version, '^\d+\.\d+').Value
if ([string]::IsNullOrWhiteSpace($channel)) {
throw "Cannot derive WindowsAppRuntime channel from MicrosoftWindowsAppSDKVersion '$version'"
}

$url = "https://aka.ms/windowsappsdk/$channel/$version/windowsappruntimeinstall-x64.exe"
Write-Host "Installing WindowsAppRuntime $version from $url"
$exe = "$env:RUNNER_TEMP\WindowsAppRuntimeInstall.exe"
Invoke-WebRequest -Uri $url -OutFile $exe
& $exe --quiet
if ($LASTEXITCODE -ne 0) { throw "WindowsAppRuntimeInstall failed with exit code $LASTEXITCODE" }

- name: Restore dependencies
run: dotnet restore

- name: Capture Windows desktop proof
id: proof
shell: pwsh
run: |
$env:OPENCLAW_REPO_ROOT = (Get-Location).Path
.\scripts\capture-windows-desktop-proof.ps1 `
-Configuration "${{ inputs.configuration }}" `
-ArtifactRoot "TestResults\DesktopProof"

# Uploaded unconditionally so a failing/fail-closed run still publishes
# its manifest and diagnostics; a missing artifact upload must never be
# the only trace of a capture attempt.
- name: Upload desktop proof artifacts
if: always()
uses: actions/upload-artifact@v7
with:
name: windows-desktop-proof
path: |
TestResults/DesktopProof/**
!TestResults/DesktopProof/**/*.trx
if-no-files-found: error
63 changes: 63 additions & 0 deletions .github/workflows/windows-inno-upgrade-smoke.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: Windows Inno Upgrade Smoke

on:
workflow_dispatch:
inputs:
previous_release:
description: Exact official previous release tag, for example v0.6.12
required: true
type: string
previous_installer_sha256:
description: SHA-256 for the official x64 installer asset
required: true
type: string
clean_machine_confirmation:
description: Enter CLEAN-OPENCLAW-VM to acknowledge the release-identity lane
required: true
type: string

permissions:
contents: read

jobs:
upgrade-smoke:
runs-on: windows-latest
timeout-minutes: 90
steps:
- name: Require explicit clean-runner confirmation
shell: pwsh
env:
CLEAN_MACHINE_CONFIRMATION: ${{ inputs.clean_machine_confirmation }}
run: |
if ($env:CLEAN_MACHINE_CONFIRMATION -cne "CLEAN-OPENCLAW-VM") {
throw "clean_machine_confirmation must be exactly CLEAN-OPENCLAW-VM."
}

- uses: actions/checkout@v7
with:
fetch-depth: 0

- name: Setup .NET 10
uses: actions/setup-dotnet@v6
with:
dotnet-version: 10.0.x

- name: Validate clean Windows upgrade
shell: pwsh
env:
PREVIOUS_RELEASE: ${{ inputs.previous_release }}
PREVIOUS_INSTALLER_SHA256: ${{ inputs.previous_installer_sha256 }}
run: |
.\scripts\validate-inno-upgrade-smoke.ps1 `
-PreviousRelease $env:PREVIOUS_RELEASE `
-PreviousInstallerSha256 $env:PREVIOUS_INSTALLER_SHA256 `
-ConfirmCleanMachineReleaseIdentity

- name: Upload upgrade smoke artifacts
if: always()
uses: actions/upload-artifact@v6
with:
name: windows-inno-upgrade-smoke
path: TestResults/UpgradeSmoke
if-no-files-found: error
retention-days: 14
16 changes: 16 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,22 @@ When changing MXC sandboxing, `system.run`, exec approvals, Windows node command

The script sets `OPENCLAW_RUN_E2E` and `OPENCLAW_RUN_MXC_E2E` itself, then runs the real WSL Gateway -> Windows node -> `system.run` MXC E2E proofs. It fails if the MXC proof skips. Use `-AllowSkip` only to document that the current host is not MXC-capable; do not report an `-AllowSkip` run as merge validation for MXC-related work.

### Live model / real Discord channel parity

When changing the `tests\OpenClaw.E2ETests\LiveParity` helpers, the live model or real Discord channel lanes, `scripts\validate-live-parity-e2e.ps1`, or the CI shard that runs their contract tests, first run the ordinary secretless contract tests (no live fixture, no secrets, safe in any environment):

```powershell
dotnet test .\tests\OpenClaw.E2ETests\OpenClaw.E2ETests.csproj --no-restore --filter "FullyQualifiedName~OpenClaw.E2ETests.LiveParity.LiveParityGateContractTests|FullyQualifiedName~OpenClaw.E2ETests.LiveParity.LiveParityProfileContractTests|FullyQualifiedName~OpenClaw.E2ETests.LiveParity.LiveParitySupportContractTests"
```

Only run the live proof lanes themselves when you have real credentials to spend and intend to prove the actual round trip:

```powershell
.\scripts\validate-live-parity-e2e.ps1 -Lane LiveModel # or RealChannel, or All
```

Both lanes require an explicit absolute profile path and real credentials; they are opt-in and never run unattended in hosted CI. See `docs/LIVE_PARITY_TESTING.md` for the exact profile schema, environment variables, cost/rate-limit caveats, and cleanup/security behavior.

## UI, MCP, and PR Proof

Use `.agents/skills/openclaw-proof-validation/SKILL.md` when a change touches tray UX, Settings, onboarding, chat/canvas, Command Center, Windows node capabilities, MCP, gateway connection/pairing, permissions, diagnostics, or agent-facing instructions.
Expand Down
Loading