feat: in-app Windows uninstall + App-section reorder/modal + Windows stop-exit reap#321
Merged
Merged
Conversation
…indows stop-exit tray + adb reap) Adds the phased TDD plan (frontend reorder + modal, Rust windows_app_uninstall helper + ServiceApi win32 branch, tray-reap stop_flag, adb taskkill belt-and-braces) and amends the spec with item 4 after verifying gracefulShutdown only kill-servers adb on Windows (missing the taskkill the update path uses).
Part A: appSectionButtonsState now returns showUninstall = linux || win32, so the uninstall row is revealed on Windows too. install-for-all-users remains Linux-only (showInstallAllUsers unchanged). Updated doc-comment. Part B: buildAppSection reorders body.appendChild calls so the DOM top-to-bottom order is: reset (+ confirm panel) → install-for-all-users (+ note) → stop server (+ note) → uninstall (+ confirm panel). Construction code for each control is unchanged; only append sequence moved. Tests: two new Part A assertions (win32 showUninstall=true, showInstallAllUsers=false; linux both=true); one Part B DOM-order test instantiating SettingsModal in jsdom and asserting label subsequence. Updated the pre-existing win32 equality snapshot to reflect new behaviour.
Add UninstallConfirmModal (Modal subclass, static confirm() API) with keep-my-settings checkbox defaulting checked and a red-outline uninstall button (settings-btn-danger-outline). Rewire buildUninstallControl to open the modal instead of toggling an inline confirm panel; remove the inline panel, uninstallConfirmPanel field, and its collapse branch in applyAppSectionButtonsState. Add .settings-btn-danger-outline CSS rule. All changes TDD: tests written first, all 124 client tests green, tsc clean.
Pure builder `windows_app_uninstall_commands` + `parse_args` + `handle` dispatcher mirroring linux_app_uninstall.rs. Invokes Update.exe --uninstall (Velopack hook fires service/tray/ARP teardown), then removes dataRoot via std::fs per keep/wipe scope. 17 unit tests; clippy clean.
POST /api/service/uninstall-app now spawns the staged operation-server
launcher with `--windows-app-uninstall --keep|--wipe --data-root <…>
--update-exe <installRoot>\Update.exe` on win32, mirroring the linux
branch (detached spawn, 200 { ok:true, status:'uninstalling' },
scheduleExit). Elevation is delegated to Update.exe (a PerMachine
install's Update.exe self-elevates via UAC) — the same elevation-lives-
in-the-launcher model as the §30 request-uac path; the spawn itself
stays unelevated.
The staged helper is resolved from <dataRoot>/control/operation-server
(Velopack-untouchable, survives Program Files removal); installRoot is
anchored at the webpack bundle location like UpdateService so Update.exe
resolves to the Velopack root (parent of current/). The unsupported
fallback now covers only non-win32/non-linux.
… on exit D1: supervisor::run() now returns the tray-supervisor stop_flag alongside the exit code. main.rs signals it (SeqCst store true) before calling reap_tray_on_terminal_exit, preventing the 10s poll thread from respawning the tray between the signal and the taskkill. Windows-only; non-Windows gets None. D1b: gracefulShutdown() in index.ts now runs a win32-only taskkill /F /IM adb.exe /T after adb kill-server, matching the belt-and-braces pattern already present in UpdateService.preApplyHygiene. Extracted into shutdownHelpers.ts (reapStrayAdbOnWindows) for testability; 3 unit tests cover win32/non-win32 dispatch and no-match exit-code swallow.
CHANGELOG [Unreleased]: Added in-app Windows uninstall; Changed App-section order + uninstall modal; Fixed Windows stop-exit tray + stray-adb reap. smoke-full.md Module 15: Windows uninstall (keep/wipe) + stop-exit rows, with the VM-gated elevation + running-helper self-deletion decisions flagged.
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.
Implements the App-section redesign + in-app Windows uninstall (spec/plan:
docs/{specs,plans}/2026-06-08-app-section-redesign-windows-uninstall*). Built TDD via subagent-driven development, each unit independently verified.1. App-section reorder (both OS)
reset prompts -> install for all users (Linux) -> stop server & exit -> uninstall. install-for-all-users stays Linux-only; uninstall now shows on both OSes.
2. Uninstall confirm -> overlay modal (both OS)
Inline panel -> top-layer
<dialog>(UninstallConfirmModal) with a keep my settings & logs checkbox (defaults to checked — the safe option) + white cancel / red uninstall buttons.3. In-app Windows uninstall (NEW — parity with Linux)
The uninstall button now works on Windows:
ServiceApiwin32 branch -> a newlauncher/src/windows_app_uninstall.rshelper (mirror oflinux_app_uninstall.rs) ->Update.exe --uninstall(fires the existing--veloapp-uninstallhook: service + tray + ARP cleanup) + dataRoot keep/wipe (deps always gone; config + logs per the checkbox).4. Fix Windows "stop server & exit" cleanup
gracefulShutdownnow also runstaskkill /F /IM adb.exe /Tto catch stray adb, mirroring the in-app update path.Verification (unit-green)
tsc --noEmitexit 0;vitest932 passed; launchercargo test108+1,clippy -D warningsclean.VM-gated — settled on the Win11 smoke (Module 15 in
smoke-full.md)Update.exe --uninstallself-elevate when launched by the unelevated staged launcher (one UAC)? If not, route the Node spawn through the launcher's--request-uacseam (a newwindows-app-uninstallcommand).control\operation-server\(Windows can't delete a running exe)? If it orphans that dir, add a self-deleting step.Update.exe --uninstallvsmsiexec /xfor a clean Add/Remove-Programs removal.release:beta-> cuts beta.51 for the VM smoke.