Skip to content

fix(cua-driver): stop Windows update --apply from killing itself - #2805

Merged
f-trycua merged 5 commits into
trycua:mainfrom
rsyuzyov:fix/windows-installer-false-legacy-detection
Aug 4, 2026
Merged

fix(cua-driver): stop Windows update --apply from killing itself#2805
f-trycua merged 5 commits into
trycua:mainfrom
rsyuzyov:fix/windows-installer-false-legacy-detection

Conversation

@rsyuzyov

@rsyuzyov rsyuzyov commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • require a real pre-v0.2.14 artifact (packages/ or bin/ under the old home, or the old visible bin directory) before running Windows legacy migration; current cache and telemetry files alone no longer trigger it
  • protect the installer's complete current-process ancestry in both daemon cleanup passes, so cua-driver update --apply cannot terminate its own launcher while unrelated legacy daemons are still stopped
  • add deterministic PowerShell regression coverage and a hosted Windows install/reinstall cell that verifies the binary, current-package junction, legacy migration, and cua-driver-serve scheduled-task state
  • keep the release-gate workflow contract synchronized with the expanded installer/update lane

Fixes #2803.

Root cause

Current Cua Driver releases write update-check and telemetry state to ~/.cua-driver-rs, but the installer treated the directory itself as proof of a legacy install. update --apply creates that state before launching the installer, so it always entered migration. Migration then killed every cua-driver.exe, including the updater process that launched the PowerShell installer; the Stop-Process fallback originally repeated the same mistake.

Validation

Candidate: f1a1e8ac98d0beec09c4751e2f8be7ed39bad710.

  • git diff --check origin/main...HEAD
  • workflow YAML and shell syntax checks passed
  • release-wiring contract: 35 passed
  • deterministic Windows contract covers cache/telemetry-only home, all supported true legacy markers, complete synthetic launcher ancestry, and unrelated-daemon cleanup
  • exact-SHA hosted Windows installer run: exact source resolution, installer/update smoke, and matrix summary passed

Credit

Diagnosis and the original fix are by @rsyuzyov. Roman Syuzyov remains the author of the contribution, and the original Claude co-author trailer is preserved.

Copilot AI review requested due to automatic review settings August 3, 2026 07:58
@rsyuzyov
rsyuzyov requested a review from f-trycua as a code owner August 3, 2026 07:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a Windows-specific failure mode in cua-driver update --apply where the installer incorrectly enters the legacy-migration path (due to ~/.cua-driver-rs being created by modern versions) and then terminates the updater process during cleanup.

Changes:

  • Tightens legacy-layout detection to require actual legacy artifacts (packages/ or bin/) instead of treating a bare ~/.cua-driver-rs directory as legacy.
  • Adds ancestor PID discovery and uses taskkill filters to avoid terminating the process tree that invoked the installer (notably when launched by cua-driver update --apply).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +1202 to +1206
$selfFilters = @()
foreach ($ancestorPid in (Get-AncestorProcessIds)) {
$selfFilters += '/FI'
$selfFilters += "PID ne $ancestorPid"
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — fixed in 2935965. The ancestor PID list is now computed once before the try block and applied to both passes: taskkill via /FI "PID ne <pid>" filters, and the Stop-Process backstop via an explicit -contains skip.

@rsyuzyov rsyuzyov changed the title fix(cua-driver)(windows): stop treating the update cache as a legacy install (fixes update --apply) fix(cua-driver): stop Windows update --apply from killing itself Aug 3, 2026
@f-trycua
f-trycua marked this pull request as draft August 4, 2026 10:15
@f-trycua
f-trycua force-pushed the fix/windows-installer-false-legacy-detection branch from 2935965 to 0e8894a Compare August 4, 2026 10:18
@f-trycua
f-trycua marked this pull request as ready for review August 4, 2026 12:26
rsyuzyov and others added 4 commits August 4, 2026 07:36
…install

`cua-driver update --apply` never completes on Windows: it stops at the
legacy-migration step and exits 1, leaving the version unchanged.

Two defects combine:

1. `Remove-LegacyInstall` treated the mere existence of `~/.cua-driver-rs`
   as a v0.2.13-or-earlier layout, but the current version writes its
   update-check cache and telemetry ids into that same directory
   (`crates/cua-driver/src/version_check.rs`, `HOME_SUBDIRECTORY`).
   Since `update --apply` performs a version check first, the directory is
   guaranteed to exist by the time the installer inspects it, so the
   migration branch runs on every invocation. Detection now requires an
   actual legacy artifact (`packages/` or `bin/` under the old home).

2. The migration killed `cua-driver.exe` by image name. When the installer
   is launched by `cua-driver update --apply`, its own parent process IS a
   `cua-driver.exe`, so the unfiltered kill terminated the update in flight.
   The kill now excludes this process and its ancestors.

Reproduced on a clean host (no prior install): install 0.16.0, run
`cua-driver check-update` once, then `cua-driver update --apply` -> exit 1.
The documented `irm install.ps1 | iex` path was unaffected, which is likely
why this went unnoticed: there the installer runs inside powershell.exe.

Verified on Windows 11 (0.17.0, per-user install, non-elevated shell):
the patched installer no longer reports the legacy layout and completes
with exit 0; a `taskkill /IM cua-driver.exe /T /FI "PID ne <ancestor>"`
terminates other daemons while leaving the caller alive.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The taskkill pass already filtered out our own process tree, but the
Stop-Process backstop right after it did not — so when the installer runs
as a child of `cua-driver update --apply` the updater was still killed
mid-flight by the second pass.

Hoist the ancestor PID list out of the try block and apply it to both
cleanup passes.
Exercise cache-only and true legacy layouts, protect the full launcher ancestry, prove unrelated daemon cleanup remains active, and certify install/reinstall scheduled-task state in the hosted Windows installer lane.

Co-authored-by: trycua-release[bot] <trycua-release[bot]@users.noreply.github.com>
PowerShell 7 routes Write-Host through the information stream. Capture every stream so the hosted migration smoke can assert the installer banner.

Co-authored-by: trycua-release[bot] <trycua-release[bot]@users.noreply.github.com>
@f-trycua
f-trycua force-pushed the fix/windows-installer-false-legacy-detection branch from a7fb828 to e587dc9 Compare August 4, 2026 12:36
f-trycua pushed a commit to rsyuzyov/cua that referenced this pull request Aug 4, 2026
Keep the release-gate test bound to the expanded installer and update smoke lane.

Salvaged from trycua#2805

Co-authored-by: Roman Syuzyov <rsyuzyov@gmail.com>
@f-trycua
f-trycua force-pushed the fix/windows-installer-false-legacy-detection branch from 2c3d489 to 123e731 Compare August 4, 2026 12:44
Keep the release-gate test bound to the expanded installer and update smoke lane.
@f-trycua
f-trycua force-pushed the fix/windows-installer-false-legacy-detection branch from 123e731 to f1a1e8a Compare August 4, 2026 12:46
@f-trycua
f-trycua merged commit aebd996 into trycua:main Aug 4, 2026
20 checks passed
f-trycua added a commit that referenced this pull request Aug 13, 2026
…3032)

* fix(cua-driver): write the update-check cache to the canonical home

`version_check` still resolved its cache under the pre-rename
`~/.cua-driver-rs/`, while `telemetry.rs` and `skills.rs` had moved to
`~/.cua-driver/` and actively migrate away from the old home. Even
`read_config_flag` in this same file already reads the config from
`bundle::user_home_subdirectory()` — only the cache path lagged behind.

The effect is that every current install re-creates the legacy home the
installer just swept, so the telemetry migration can never finish and
`~/.cua-driver-rs` looks like a legacy-layout marker on machines that have
only ever run current versions (the root cause discussed in #2803, whose
installer half shipped in #2805).

Resolve the cache through `bundle::user_home_subdirectory()` (which also
covers the `.cua-driver-local` source-build case the old inline branch
handled), and migrate a cache left in the pre-rename home on first read:
move the file, then drop the directory only if it is empty, matching
`migrate_legacy_telemetry_home`. Keeping the file is worth the few lines
because it carries the dismissed-version list.

(cherry picked from commit 1c0a2ba)

* fix(cua-driver): preserve cache when migration fails

Keep the legacy version-check cache unless the canonical cache already exists or the move succeeds, and cover a deterministic destination failure.

Co-authored-by: Roman Syuzyov <7994115+rsyuzyov@users.noreply.github.com>

---------

Co-authored-by: Roman Syuzyov <rsyuzyov@gmail.com>
Co-authored-by: Roman Syuzyov <7994115+rsyuzyov@users.noreply.github.com>
Co-authored-by: Francesco Bonacci <f@trycua.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

4 participants