Run PowerToys UITest.Next suites in persistent Hyper-V VMs over PowerShell Direct. Validate full default and constrained suites on Windows 10 and Windows 11, plus applicable ARM64 guests, then automatically hand implementation tasks to ui-tests-pipeline-ci for commit/push and CI validation. Local green is not end-to-end completion. Use for agentic UI-test iteration, reusable standard-user desktops, payload staging, evidence export, VM customization, clean baselines, or hosts without nested virtualization. Keywords: Hyper-V, local VM, virtual machine, PowerShell Direct, Copy-VMFile, VMBus, checkpoint, unattend, autounattend, ISO, Windows 10 LTSC, Windows 11, ARM64, Windows on ARM, UI tests, UITest.Next, winappcli, TRX, CI handoff.
Run PowerToys .Next UI tests in a persistent, interactive Windows VM while keeping product and test
execution off the host. Use this skill as the execution complement to
ui-tests-migration. Restore the baseline checkpoint or recreate the
guest when clean-profile behavior must be validated.
The guest is a Hyper-V virtual machine. Nothing runs nested, so the same scaffold works on x64 and on Windows on ARM, where nested virtualization is unavailable to any Linux-hosted emulator.
The local correctness gate passes when the full suite is green on Windows 10 and on
Windows 11, in two separate VMs. Run Windows 10 Enterprise LTSC 2021 first for the fastest
feedback, then run the same unfiltered suite on Windows 11. Differences in the shell, compositor,
theming, and timing break tests that contain nothing Windows 11-specific, and those are exactly
the failures worth catching locally instead of in CI. On a Windows on ARM host, Windows 11 ARM64
is the only practical guest; run it with -Platform ARM64 and get the Windows 10 half from an x64 host.
Start guests with the default resource profile: 4 vCPUs and 8 GB RAM. Get the target suite fully
green before lowering resources with the Constrained profile (1 vCPU and 4 GB RAM).
For create, migrate, or stabilize tasks, complete both profiles and then automatically invoke ui-tests-pipeline-ci: pass its access preflight, commit and push the scoped changes, queue CI, and remain attached until terminal validation. Do not mark the task complete at local green or wait for another user request to publish/run CI. Respect explicit local-only/no-push/no-CI scope and the Microsoft FTE/access gates. Local execution or VM setup alone does not authorize publication. See the pipeline skill for the shared completion and blocker rules.
| Concern | Mechanism |
|---|---|
| Control channel | PowerShell Direct over VMBus. No listener, port, certificate, or firewall rule in the guest. |
| Bulk payload | Copy-VMFile over the Guest Service Interface, ~82 MB/s. The session copy is a fallback and stalls on archives near a gigabyte. |
| Exchange | Guest-local C:\PowerToysUiTestExchange\<name>, mirrored by the controller. The host never shares a folder with the guest. |
| Host privilege | Hyper-V access: an elevated shell, or an account in the local Hyper-V Administrators group. Creating a guest additionally requires real elevation. |
| Console | scripts/Get-VmConsoleImage.ps1 renders the framebuffer to PNG, so an agent can read boot and desktop state without VMConnect. |
Use it when asked to:
msvsmon.status.json, TRX, transcripts, logs, screenshots, and failure attachments.Do not treat a persistent VM as proof of clean-profile behavior. Caches, registrations, settings, and first-run state survive between runs. Restore the baseline checkpoint or recreate the VM when those are the behavior under test.
| Skill | Owns |
|---|---|
ui-tests-migration | Test design, project scaffolding, framework APIs, assertions, lifecycle, and CI stability. |
ui-tests-local-vm | Fast persistent-VM setup, deployment, interactive execution, evidence export, and iteration. |
ui-tests-pipeline-ci | Required post-local commit/push, access preflight, scoped CI, and terminal sign-off for implementation tasks. |
Do not modify stabilized tests merely to make the local VM green. First prove that the suite executes, produces assertion-bearing TRX, and has a useful success rate. Classify environment-specific failures separately unless the task explicitly asks for stabilization.
-Source Fido -Windows 10 automates Microsoft's official
mobile-user-agent ISO page and is the practical public default. The public ISO/MCT images are too
old for .NET 10 CET, so Setup Dynamic Update must bring Win10 to 1904x.5007+ before the baseline.
Use licensed Microsoft subscription media for LTSC when available, and always record the edition,
ISO hash, and installed full build (references/setup.md §3).vm.config.psd1, VHDX, checkpoints, and exchange. Never upgrade or
repurpose the Windows 10 guest into the Windows 11 guest; the two baselines must stay independent.-Platform ARM64. Hyper-V does not
emulate a foreign architecture, so that host cannot supply the Windows 10 x64 pass - run it on an
x64 host and report both.-Platform is not cosmetic: it flows to the guest as the platform environment variable, names
visual baselines, and marks the run as pipeline-like. Use only x64Win10, x64Win11, or ARM64.Read only what the task needs:
msvsmon, resource profiles, and golden-baseline guidance.NDEBUG gating, runtime detection, and reproducing CI's
classic scenario on a local signed VM.flowchart LR
A[Design or edit test] --> B[Host build]
B --> C[Package changed payload]
C --> D[Start or reuse VM]
D --> E[Probe standard-user desktop]
E --> F[Run focused test]
F --> G[Export status TRX evidence]
G --> H{Need test change?}
H -- Yes --> A
H -- No --> I[Run full suite on Win10]
I --> J[Run same full suite on Win11]
J --> K{Both fully green?}
K -- No --> A
K -- Yes --> L[Full constrained suites on both OSes]
L --> M{Local matrix green?}
M -- No --> A
M -- Yes --> N[Clean-profile confirmation when required]
N --> O[ui-tests-pipeline-ci: preflight, commit, push]
O --> P[Scoped CI and synchronous terminal validation]The CI continuation applies to implementation tasks; explicit local-only and setup-only tasks stop at their requested local outcome.
Create and maintain this task list:
- [ ] 0. Verify host setup FIRST: `Initialize-LocalVmHost.ps1 -VmRoot <root> -CheckOnly`. If it reports
IsReady=false, STOP and ask the user to run the elevated command it prints - Hyper-V group
membership, the DPAPI credential, and guest creation all need a human. Never autopilot past it
- [ ] 1. Read ui-tests-migration guidance for the target test surface
- [ ] 1a. Read the target module's dev docs — `doc/devdocs/modules/<module>.md` (search `doc/devdocs/`,
including `common/`, if the exact file is missing) — for development-cycle gotchas such as
Release/`NDEBUG` registration gating, signed sparse-MSIX context menus, and Explorer restarts,
so a module's registration/deployment requirements do not surface as opaque test failures.
For shell-extension modules also read references/shell-extensions-and-signing.md.
- [ ] 2. Scaffold or verify the local VM - references/setup.md
- [ ] 3. Build product and test projects on the host to exit code 0
- [ ] 4. Package a lean exchange and verify archive hashes
- [ ] 5. Run the controller with -PlanOnly and inspect its request/plan
- [ ] 6. Probe the non-admin interactive desktop before test execution
- [ ] 7. Run one focused test synchronously; keep the agent turn attached, read the controller
result's `.Failed` array (non-passed tests + first error line) instead of re-parsing TRX, and
use `scripts/Invoke-GuestScript.ps1` for guest-state inspection
- [ ] 8. Diagnose the first controlling failure without weakening assertions
- [ ] 9. Rebuild and rerun with -ReuseStagedPayload
- [ ] 10. Widen to the full module suite on Windows 10 and report pass rate/root-cause groups
- [ ] 11. Run the same full suite in the Windows 11 VM; both must be green before the local gate passes
- [ ] 12. Restore the baseline checkpoint for clean-profile confirmation when required
- [ ] 13. Run the full Constrained suite on both OSes; preserve default and constrained evidence
- [ ] 14. For implementation tasks, invoke ui-tests-pipeline-ci without another user prompt, pass
access preflight, commit/push task-owned changes, and record the exact branch/SHA
- [ ] 15. Queue scoped CI and wait synchronously for verified terminal results; local green alone
cannot complete the task unless the user explicitly requested local-only scopeHost setup is a one-time, human-only step: Hyper-V group membership, the DPAPI guest credential, and guest creation all need elevation or a password. Check it before anything else - this needs no elevation and changes nothing:
pwsh .github\skills\ui-tests-local-vm\scripts\Initialize-LocalVmHost.ps1 -VmRoot X:\PowerToysUiTestVm -CheckOnlyIf it reports IsReady=false, stop and ask the user to run the elevated command it prints (see
references/setup.md §0). Otherwise scaffold
the VM directory outside the repository:
pwsh .github\skills\ui-tests-local-vm\scripts\Initialize-LocalVm.ps1 `
-DestinationRoot X:\PowerToysUiTestVmThe scaffold and its shared exchange can live on any volume, including a Dev Drive. Only the VHDX
and VM configuration paths, set separately in vm.config.psd1, should point at NTFS.
Follow references/setup.md to write the untracked vm.config.psd1, save the
administrator credential with Windows DPAPI, obtain install media, and create the guest with
New-UiTestVm.ps1. Then stage the archives described in
references/agentic-loop.md and run:
pwsh .github\skills\ui-tests-local-vm\scripts\Invoke-LocalVmUiTest.ps1 `
-VmName PowerToysUiTest-Win10 `
-VmRoot X:\PowerToysUiTestVm `
-ExchangeRoot X:\PowerToysUiTestVm\shared\PowerToysUiTests\MyModule `
-TestExecutable MyModule.UITests.Next.exe `
-Filter 'Name=MyModule.FocusedTest' `
-Platform x64Win10 `
-BuildLabel (git rev-parse HEAD) `
-SuiteTimeout 15m `
-TimeoutMinutes 25 `
-ReuseStagedPayloadThe controller starts the VM if needed, requests automatic host sleep prevention, verifies the
interactive standard-user desktop, dispatches the guest runner, and waits synchronously for matching
status.json. It reports whether sleep prevention succeeded, fails early if the guest task never
starts or exits without status, summarizes TRX, and leaves the persistent VM running by default.
Initialize-LocalVmHost.ps1 performs all three; agents run it -CheckOnly, and on
IsReady=false report BLOCKED, print the elevated command it emits, and wait. Do not ask for a
password, do not substitute a weaker channel, do not proceed on a partial setup.
Invoke-LocalVmUiTest.ps1 enforces the same check.vmms at 0% CPU, even Get-VM hanging, host reboot
to recover - and moving to NTFS fixed it. This is an observation on one host, not a property of
ReFS: Hyper-V on plain ReFS is supported, so -AllowReFsVolume overrides the default refusal. The
scaffold and the exchange are unaffected and run fine on a Dev Drive.Constrained (1 vCPU / 4 GB) resources.SYSTEM.C:\PowerToysUiTestRun.total > 0 plus executed == total. A process exit code alone cannot
distinguish assertions, skipped/inconclusive tests, zero tests, timeout, or infrastructure failure.HostSleepPrevented; failure
is a warning. It cannot override manual sleep, lid-close policy, reboot, shutdown, or power loss.Reset-LocalVm.ps1 -Restore.4326404
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.