5 Commits

Author SHA1 Message Date
程序员阿江(Relakkes)
730e21f717 fix(test): stop attributing stray processes to the no-CLR installer stages
`Verify Windows installer execution` failed twice in a row on the v0.5.0
tag, both times at the same assertion:

    Elevated default-mode reinstall without CLR expected process exit
    code 20, received 22.

20 and 22 are different answers to "why did setup stop". 20 is legacy
recovery refusing to continue; 22 is "a matching process is running". The
stage breaks the CLR on purpose so the installer cannot run PowerShell,
which is exactly when CcHahaFindInstallProcess degrades from resolving
paths to matching bare image names -- `Claude Code Haha.exe`, the three
`claude-sidecar*` names, `OpenConsole.exe`, `winpty-agent.exe`, `rg.exe`.
Any process on the runner carrying one of those names answers for the
stage, whoever started it.

The stage before it expects 22, so a stray match there is indistinguishable
from a pass; the stage after it expects 20, so the same stray match is a
failure. That asymmetry is why this reads as "one flaky assertion" rather
than "the whole no-CLR group is unguarded".

This does not fix the installer, because the installer is not wrong:
refusing to delete user data when it cannot confirm what is running is the
intended fail-closed behaviour, and neither installer.nsh nor this script
changed between v0.4.11 (green) and v0.5.0 (red). What changed is what was
running on the runner. So the script now controls that instead of assuming
it:

- Both stages that expect 20 first clear any process matching the same
  name list. `WaitForExit` only covers the PIDs this script started; the
  fallback matches names, so it also sees leftovers from earlier steps of
  this job -- the compiled-sidecar smoke starts 20 sidecars -- and any
  child a probe spawned.
- Clearing warns instead of throwing when something survives. A survivor
  is runner-owned and out of reach, and failing there would replace the
  stage's own failure with a less informative one.
- A mismatched exit code now prints every matching process with PID and
  path, and a baseline is printed before the first install. Between those
  two, a future failure says whether the runner was dirty or the installer
  regressed, which this run had no way to answer.

The name list is duplicated from installer.nsh by necessity -- NSIS
compile-time state is not readable from PowerShell -- and is commented on
both sides to be kept in sync.

Not verified locally: this needs Windows and an ephemeral runner (the
script refuses to run unless CI=true, since it mutates installer registry
state). Reviewed for Windows PowerShell 5.1, which is what the workflow
invokes: no pwsh-only syntax, and the file is kept pure ASCII as it was,
so 5.1 cannot mis-decode it.
2026-07-27 08:42:48 +08:00
程序员阿江(Relakkes)
c48171e2f0 fix(desktop): harden Windows upgrades (#1028, #1029, #1036) 2026-07-17 23:38:59 +08:00
程序员阿江(Relakkes)
d7de7d47c9 test(release): expose Windows recovery diagnostics 2026-07-14 04:50:18 +08:00
程序员阿江(Relakkes)
d5be1f824a fix(release): bound Windows installer smoke waits 2026-07-14 04:18:58 +08:00
程序员阿江(Relakkes)
ecb66bfdd5 fix(desktop): unblock Windows installer upgrades #1000 2026-07-14 03:16:12 +08:00