Files
winutil/SPEC.md
Chris Titus 2cb20893fc Expand Pester coverage across install, tweaks, and UI workflows (#4792)
* Harden Pester CI and discard runspace return values

* Add prioritized test backlog

* Add WinUtil action logging

* Add config integrity tests

* Add XAML control wiring tests

* Add registry and service helper tests

* Add package manager tests

* Add runspace behavior tests

* Add tweak orchestration tests

* Add install workflow tests

* Add update profile tests

* Add AppX removal tests

* Log package installer output

* Add UI state helper tests

* Pin Pester test runner version

* Expand Win11 Creator tests

* Add preferences and theme tests

* Add search filter tests

* Add compile contract tests

* Use single WinUtil session log

* Remove installer output logging helper

* Handle locked WinUtil transcript log

* Avoid appending to active transcript log

* Log install uninstall package identities
2026-07-01 21:49:15 -05:00

6.1 KiB

SPEC.md

Project Contract

WinUtil is a Windows PowerShell utility with a WPF interface. The repository is maintained as modular source files, but the released artifact is a single generated winutil.ps1 script.

The compiled winutil.ps1 is not source code for editing or review. It is generated by Compile.ps1 and produced during release automation. All durable changes must be made to the source files that feed the compiler.

Goals

  • Provide a single-script Windows utility that can be launched from PowerShell.
  • Keep development modular enough for contributors to work on functions, config, UI, docs, and tooling independently.
  • Make install, tweak, feature, repair, update, and ISO workflows discoverable from the WPF UI.
  • Keep common lists and options declarative in JSON config where possible.
  • Preserve a repeatable compile process so local builds and GitHub Actions builds produce the distributable script from the same inputs.

Non-Goals

  • winutil.ps1 is not hand-maintained.
  • The project is not structured as a PowerShell module at runtime.
  • The GUI is not a separate packaged desktop application in this repository's normal release path.
  • Generated files should not be reviewed as source changes.

Repository Layout

  • Compile.ps1: build script that creates winutil.ps1.
  • scripts/start.ps1: startup/bootstrap segment used at the beginning of the compiled script.
  • scripts/main.ps1: main entrypoint appended at the end of the compiled script.
  • functions/public/: public/UI-facing PowerShell functions.
  • functions/private/: internal helper PowerShell functions.
  • config/: JSON configuration consumed at compile time and embedded into $sync.configs.
  • xaml/inputXML.xaml: WPF UI markup embedded into the compiled script.
  • tools/autounattend.xml: unattended setup XML embedded for Windows ISO workflows.
  • pester/: Pester tests for config and function checks.
  • lint/PSScriptAnalyser.ps1: PowerShell Script Analyzer settings.
  • docs/: Hugo documentation site.
  • winutil.ps1: ignored generated build artifact.

Compile Specification

Compile.ps1 must produce a standalone root winutil.ps1 by combining all required project files.

The compile flow is:

  1. Initialize shared state with $sync = [Hashtable]::Synchronized(@{}) and $sync.configs = @{}.
  2. Read scripts/start.ps1.
  3. Replace #{replaceme} in startup code with the current yy.MM.dd build date.
  4. Append raw content from all files under functions/ recursively.
  5. For every file in config/, parse JSON and embed it into $sync.configs.<basename>.
  6. Special-case config/applications.json so application keys are emitted with the WPFInstall prefix.
  7. Embed xaml/inputXML.xaml as $inputXML.
  8. Embed tools/autounattend.xml as $WinUtilAutounattendXml.
  9. Append scripts/main.ps1.
  10. Write the combined script to winutil.ps1.
  11. If -Run is supplied, execute the generated script.

The generated script must have everything it needs from repository sources embedded or appended by this process.

Runtime Model

  • WinUtil runs in PowerShell on Windows and uses WPF for the UI.
  • Shared mutable state is stored in $sync, including configs, UI element references, runspace state, selections, and progress.
  • Long-running operations should use runspaces or existing async patterns so the UI remains responsive.
  • UI updates from background work must be dispatched back to the WPF UI thread.
  • Declarative features such as apps, tweaks, presets, DNS providers, and navigation should stay in config/*.json unless code is required.

UI And Event Contract

  • UI layout lives in xaml/inputXML.xaml.
  • Named WPF controls are discovered and stored in $sync.
  • Button/action wiring follows existing naming conventions, where an element named like WPFThingButton maps to a function named like Invoke-WPFThingButton.
  • When adding controls, ensure the XAML name, config key, and PowerShell function names line up with the existing event system.

Configuration Contract

Config files must remain valid JSON and compile cleanly through ConvertFrom-Json.

config/applications.json defines installable applications. Each application entry should include the fields expected by tests and UI code, such as package manager IDs, category, display content, description, and link.

config/tweaks.json defines Windows tweaks. Registry and service changes should include original values or original states when applicable so undo workflows can restore user systems.

Preset and navigation files should reference valid config keys. Avoid renaming config keys unless all presets, UI references, docs, and code paths are updated together.

Safety Requirements

  • Registry, service, package manager, Windows Update, AppX removal, and ISO operations can affect the host system. Changes must be explicit, reversible where practical, and consistent with existing logging and confirmation patterns.
  • Tweak changes should include undo metadata when the schema supports it.
  • Package installation should prefer existing WinGet and Chocolatey helper functions.
  • ISO workflows must not modify the user's original ISO file; they should work on copied/mounted content following existing patterns.

Testing And CI

Expected validation for source changes:

  • .\Compile.ps1 verifies the compiler can generate winutil.ps1.
  • .\Compile.ps1 -Run compiles and launches the generated utility for manual GUI verification.
  • Install-Module -Name Pester -RequiredVersion 5.8.0 -Scope CurrentUser -Force -SkipPublisherCheck installs the supported Pester version.
  • Import-Module Pester -RequiredVersion 5.8.0 -Force; Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed -CI runs the Pester suite.
  • GitHub Actions also runs a compile check and PowerShell Script Analyzer with lint/PSScriptAnalyser.ps1.

The generated winutil.ps1 may appear locally after compile. It remains ignored build output and must not be committed.

Release Artifact

GitHub Actions is responsible for producing the release winutil.ps1 from repository sources. A release should be considered valid only if the generated script came from the compile process, not from direct manual edits to winutil.ps1.