Repository navigation
v0.5.0: Parallel execution, health reporting, and one-command install - #3
Merged
Merged
Conversation
Three things this release delivers, against a v0.4 that had the right architecture but the wrong ergonomics. One command. The GUI shell moves from src/Shell into the module, so a PowerShell Gallery install now carries the window as well as the commands - previously the Gallery shipped the module only and the GUI needed a separate archive download. install.ps1 is a bootstrapper pinned to a release tag that prefers the signed Gallery package, falls back to a SHA256-verified release archive with no way to skip the check, and installs a `pctools` command into a directory already on PATH. Invoke-PCTools gives the same actions a scriptable front door with real exit codes. Measured performance. Nothing here had ever been measured, and the hot paths were all the same mistake in different places: independent I/O performed one item at a time. Nine connectivity probes ran in sequence, each waiting out its own timeout; a traceroute walked up to twenty TTLs one at a time; every temp directory was walked twice, once to size and once to delete. They now run concurrently behind a single Invoke-PCParallel helper, and the shipped module is compiled to one file. build/Measure-Performance.ps1 is the arbiter, and docs/PERFORMANCE.md records both the numbers and what was deliberately not done. Thirty-five new commands: storage analysis, startup and service control, health and security reporting, Windows Update and winget, scheduled maintenance, run history, HTML reports and a drop-in extension model. Safety held constant. Every mutating action still supports -WhatIf. The two sharpest new commands are allowlist-driven with no -Force: Set-PCServiceStartup refuses a fixed list of services whose loss breaks a machine, and Remove-PCAppxPackage will only remove preinstalled apps on a curated list that deliberately excludes the Store, App Installer, Photos, Calculator and every framework package. Get-PCSecurityStatus reports posture and has no counterpart that changes it. Bugs found and fixed while building it: - Get-PCResultSummary and Export-PCReport threw on an empty batch, because Measure-Object emits nothing for an empty collection and reading .Sum off nothing is a terminating error under strict mode. A network-only report reaching the HTML writer would have hit this. - Invoke-PCProcess mangled any argument containing a quote. It now applies the escaping rules CommandLineToArgvW actually uses on Windows PowerShell 5.1. - Save-PCHistory overwrote an entry when two runs finished in the same second. - Assigning the result of an `if` unrolls a one-element array to a scalar, so .Count on it threw under strict mode - in four places, each on the common single-item path. - Test-PCMtu used GetNewClosure(), which rebinds a scriptblock to a scope detached from the module's session state; the probe could not see the private helper it needed and every call failed. - Passing a live scriptblock across a runspace boundary corrupts the caller's session state. Invoke-PCParallel marshals the body as text and recompiles it in the target runspace. Tests: 713 assertions across ten suites, four of them new - Parallel, Safety, Extension, Compile and Install. Compile.Tests asserts the compiled module exports exactly what the source does, so the generated artifact cannot drift from the code the tests ran against. The Test-PCMtu search was verified exhaustively against all 1473 possible MTU values. The release pipeline now signs the compiled module before packaging rather than after, so the file users actually execute carries the signature, and publishes that same compiled module to the Gallery. ROADMAP.md is rewritten around v0.6 (trust: a real signing certificate, winget, verifiable builds), v0.7 (fit) and v1.0 (a stable command surface), plus a set of permanent non-goals: no telemetry, no unexplainable registry tweaks, no memory "optimisation", no bulk service-disabling preset, no forced restarts, and no silent changes to security settings. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkdwqfkUYsNSkp9f3AVDqg
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0068a70e15
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex review and the first CI run between them found four real defects and three stale assertions. All of them are in v0.5.0, which has not shipped. Two bugs came from the same root cause: the source tree and the compiled module nest functions at different depths, so any path built by walking up from $PSScriptRoot is correct in one and wrong in the other. - Start-PCTools resolved the GUI shell as "$PSScriptRoot\..\Shell". In the source tree the function lives in Public/ and that is right; in the compiled module $PSScriptRoot is already the module root, so it pointed at a sibling folder that does not exist. Every Gallery and archive install would have thrown "the shell is missing" - on the one command this release is named after. Verified against a simulated install: the old expression resolved a path that is not there, the new one resolves the shell. - Register-PCScheduledMaintenance built its manifest path two parents up, which landed outside the versioned module folder and fell back to Import-Module by name. A scheduled task runs as SYSTEM, whose module path does not include a CurrentUser install, so every task registered from a normal install would have failed before running its profile. Both now read $ExecutionContext.SessionState.Module.ModuleBase, which is the module root in either layout, and a test asserts neither file goes back to depending on its own nesting depth. - Invoke-PCParallel discarded results that had already completed once the batch deadline passed. The tasks run concurrently, so a slow item early in the list could burn the whole budget while every later item had finished - and those finished results were then reported as timeouts. Test-PCConnectivity is where this would have bitten: the gateway probe is both first and the likeliest to hang. Completion is now checked before the budget. The new test fails against the old logic and passes against the fix. - The release notes named pc-tools-v0.5.0.zip; the build stages the archive without the tag's leading v, so the documented verification step named a file that is not attached. CI: - docs/COMMANDS.md was written with Set-Content -Encoding UTF8, which emits a BOM on Windows PowerShell 5.1 and none on PowerShell 7. The generated file therefore differed by three bytes depending on who ran the task, which is what the freshness check reported as stale. It is now written as UTF-8 without a BOM, with LF endings, identically on every host. - Three assertions had gone stale against my own changes: two expected error text I had deliberately improved or profile lists I had added to, and the third - in Install.Tests - had the very array-unwrapping bug this release fixes in the module code, where a single regex match assigns a scalar and .Count on it throws under strict mode. Local verification: 718 assertions across ten suites, 0 failures; analyzer clean at 197 warnings against a 210 budget; the Docs task is now idempotent, the release stages, and the compiled module is still byte-reproducible. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkdwqfkUYsNSkp9f3AVDqg
CI on c5f9a8f was down to one failure, and it was a real bug rather than a stale assertion: Import-PCConfiguration's error for an action that is neither a command nor a registered extension printed literal {0} and {1} where the profile and action names belong. The format operator binds tighter than string concatenation, so "Profile '{0}' references '{1}'. " + "Run Get-Command ..." -f $a, $b formats only the second string - which has no placeholders - and leaves the first exactly as written. The concatenation needs its own parentheses. This is the same precedence trap that produced the earlier HTML-report bug, where a -f inside a method call had its arguments taken as method arguments instead. Audited every other site in the repository where a concatenation is followed by -f: three exist and all three already parenthesise the concatenation correctly, so this was the only one. The local test runner in the scratchpad was ignoring Should -Throw's -ExpectedMessage, which is precisely why this passed locally and failed in CI - something threw, so it counted as a pass regardless of what it said. It now compares the message, and with that change it reproduces the CI failure against the old code and passes against the fix. 718 assertions, 0 failures; analyzer clean at 197 warnings. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkdwqfkUYsNSkp9f3AVDqg
All 714 tests pass on Windows PowerShell 5.1 now. The job failed on the analyzer instead: 275 warnings against a budget of 210, on a tree whose sources had not changed. The cause is that Analyze scanned obj/, which holds the compiled module - the same functions, merged into one file. Compile.Tests builds it as part of the suite, so by the time the Analyze step ran, obj/ existed and every finding in module code was counted twice. The filter already excluded out/ and dist/ but not obj/. Locally I had excluded obj/ in my own analyzer invocation, which is why I measured 197 and CI measured 275 for identical code. Excluding it is right on its own merits: obj/ is generated, its findings are duplicates of ones already reported against the file a person would actually edit, and a budget that moves depending on whether a build has run is not a budget. With it excluded the count is 197, inside the existing 210 - so the budget itself did not need raising. tests/Syntax.Tests.ps1 had the same gap in its discovery filter, which is why it found 232 files in a working tree and 228 in CI, where obj/ does not exist at discovery time. Both now agree at 714 assertions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KkdwqfkUYsNSkp9f3AVDqg
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This release adds ~40 new commands, a performance-focused refactor of hot paths, and a one-command installer that works from the PowerShell Gallery.
Summary
PC Tools v0.5 is a major expansion: the module grows from ~30 commands to ~74, with new categories for health reporting, storage analysis, and system automation. The GUI gains a Dashboard page showing machine health at a glance. Performance is measured and optimized—network diagnostics that waited out timeouts serially now run concurrently.
Key Changes
New Commands (40+)
Get-PCHealthReport,Get-PCSecurityStatus,Get-PCBootPerformance,Get-PCEventSummary,Get-PCBatteryReport,Get-PCDiskHealth,Get-PCSystemInfoGet-PCDiskUsage,Get-PCDiskSpace,Optimize-PCVolume,Clear-PCWindowsOld,Clear-PCCrashDump,Clear-PCEventLog,Clear-PCDeliveryOptimization,Clear-PCThumbnailCacheGet-PCAppxPackage,Remove-PCAppxPackage,Get-PCWindowsUpdate,Install-PCWindowsUpdate,Update-PCApplication,Get-PCDriverIssueGet-PCStartupItem,Get-PCService,Disable-PCStartupItem,Enable-PCStartupItem,Set-PCServiceStartupGet-PCHistory,Save-PCHistory,Register-PCScheduledMaintenance,Unregister-PCScheduledMaintenance,Get-PCScheduledMaintenance,Register-PCExtension,Get-PCExtension,Invoke-PCToolsTest-PCDnsServer,Test-PCThroughputGet-PCResultSummary,Export-PCReport(expanded to HTML/CSV)Performance Optimization
Invoke-PCParallelfunction runs independent I/O-bound probes concurrently using runspace poolsTest-PCConnectivityandTest-PCRouterefactored to probe in parallel rather than seriallyTest-PCMtunow sends payload probes concurrently instead of binary searchInvoke-PCProcesseliminates temp file overhead by reading pipes directlyClear-PCFolderContentwalks trees once instead of twiceInstallation & Distribution
install.ps1bootstrapper: one command to install from Gallery or verified release archivepctoolscommand installed to%LOCALAPPDATA%\Microsoft\WindowsApps(no PATH edit needed)Start-PCToolscommand opens itsrc/PCTools/Shell/and integrated with module lifecycleGUI Enhancements
-Pageparameter to open directly to a specific tabBuild & Testing
Measure-Performance.ps1benchmark harness with baseline comparisonParallel.Tests.ps1,Safety.Tests.ps1,Extension.Tests.ps1,Install.Tests.ps1,Compile.Tests.ps1Compile(merge sources to .psm1),Docs(generate COMMANDS.md),Bench(run benchmarks)Safety Guards
Remove-PCAppxPackageandSet-PCServiceStartupuse allowlists, not blocklistsGet-PCCriticalServiceNameprevents disabling load-bearing servicesDocumentation
docs/COMMANDS.md: auto-generated command referencedocs/PERFORMANCE.md: benchmark methodology and resultshttps://claude.ai/code/session_01KkdwqfkUYsNSkp9f3AVDqg