Add ghost-device cleanup, fix the Activision/CoD delete scope - #1
Merged
Conversation
Two changes from FocusedWolf's follow-up to the cleanup-script credit. Ghost devices (new System Tools actions): "List ghost devices" (read-only) and "Remove ghost devices" (Advanced) surface and clean up non-present PnP device nodes via pnputil.exe. Removal is permanent with no undo, so it is allow-listed rather than blanket: checking a real machine, pnputil's "disconnected" set included live hardware (mounted disks, a GPU's HD-audio and USB-C controllers, an integrated GPU, VSS snapshots, virtual HID/MIDI stubs) alongside genuine ghosts. Only USB/HID devices identified by vendor+product ID, Bluetooth, and audio endpoints are removed, with USB root hubs excluded explicitly; everything else is reported as kept. On this machine that is 15 removed of 46 found. The read-only action runs the same script in preview mode, so it cannot drift from what removal actually does. The script is embedded and run via -EncodedCommand, never extracted to disk: WinButler runs elevated, so invoking a script from a user-writable path would let an unprivileged process overwrite it first. Script-backed actions are declared in Scripts/scripts.json and auto- register, so adding one is a drop-in (.ps1 + one entry, no code change). The manifest only names a script already embedded in the binary plus a bare-identifier mode; it cannot carry a command line, and it loads outside the definitions merge path so a future remote-definitions source could never reach it. Built-in tool actions (DISM, SFC, WMI) stay in code for the same reason. Activision/Call of Duty (data-loss fix): The activision-crashes entry treated every immediate child of %LocalAppData%\Activision as safe-to-permanently-delete, which now includes Call of Duty\players -- real user settings, not diagnostics. Why the replacement is safe: the broad entry is split into one scoped to Call of Duty (excluding "players" via a new children-mode exclude field) and one scoped to the bootstrapper's crash_reports folder. The Call of Duty entry is downgraded from safe to caution, so it goes to the Recycle Bin and is never auto-selected -- the full junk-folder set under that directory could not be verified against a real install, so an unexpected match is now recoverable rather than permanent. The narrower bootstrapper path keeps safe. Deny-list, dry-run and confirm gating are unchanged; exclude is an additional carve-out, not a replacement for any of them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FzDrUZqjXzvsQFKjM6u6TK
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.
Two changes from FocusedWolf's follow-up to the cleanup-script credit.
Ghost devices (new System Tools actions):
"List ghost devices" (read-only) and "Remove ghost devices" (Advanced)
surface and clean up non-present PnP device nodes via pnputil.exe.
Removal is permanent with no undo, so it is allow-listed rather than
blanket: checking a real machine, pnputil's "disconnected" set included
live hardware (mounted disks, a GPU's HD-audio and USB-C controllers, an
integrated GPU, VSS snapshots, virtual HID/MIDI stubs) alongside genuine
ghosts. Only USB/HID devices identified by vendor+product ID, Bluetooth,
and audio endpoints are removed, with USB root hubs excluded explicitly;
everything else is reported as kept. On this machine that is 15 removed
of 46 found. The read-only action runs the same script in preview mode,
so it cannot drift from what removal actually does.
The script is embedded and run via -EncodedCommand, never extracted to
disk: WinButler runs elevated, so invoking a script from a user-writable
path would let an unprivileged process overwrite it first.
Script-backed actions are declared in Scripts/scripts.json and auto-
register, so adding one is a drop-in (.ps1 + one entry, no code change).
The manifest only names a script already embedded in the binary plus a
bare-identifier mode; it cannot carry a command line, and it loads
outside the definitions merge path so a future remote-definitions source
could never reach it. Built-in tool actions (DISM, SFC, WMI) stay in
code for the same reason.
Activision/Call of Duty (data-loss fix):
The activision-crashes entry treated every immediate child of
%LocalAppData%\Activision as safe-to-permanently-delete, which now
includes Call of Duty\players -- real user settings, not diagnostics.
Why the replacement is safe: the broad entry is split into one scoped to
Call of Duty (excluding "players" via a new children-mode exclude field)
and one scoped to the bootstrapper's crash_reports folder. The Call of
Duty entry is downgraded from safe to caution, so it goes to the Recycle
Bin and is never auto-selected -- the full junk-folder set under that
directory could not be verified against a real install, so an unexpected
match is now recoverable rather than permanent. The narrower bootstrapper
path keeps safe. Deny-list, dry-run and confirm gating are unchanged;
exclude is an additional carve-out, not a replacement for any of them.
Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01FzDrUZqjXzvsQFKjM6u6TK